1 /*
2  * Copyright (c) 2012-2021, The OSKAR Developers.
3  * See the LICENSE file at the top-level directory of this distribution.
4  */
5 
6 #include "sky/oskar_sky.h"
7 #include "math/oskar_cmath.h"
8 #include <stdio.h>
9 
10 #define RAD2DEG 180.0/M_PI
11 #define RAD2ARCSEC RAD2DEG * 3600.0
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
oskar_sky_save(const oskar_Sky * sky,const char * filename,int * status)17 void oskar_sky_save(const oskar_Sky* sky, const char* filename, int* status)
18 {
19     int i = 0;
20     FILE* file = 0;
21     if (*status) return;
22 
23     /* Check sky model is in CPU memory. */
24     if (oskar_sky_mem_location(sky) != OSKAR_CPU)
25     {
26         *status = OSKAR_ERR_BAD_LOCATION;
27         return;
28     }
29 
30     /* Open the output file. */
31     file = fopen(filename, "w");
32     if (!file)
33     {
34         *status = OSKAR_ERR_FILE_IO;
35         return;
36     }
37 
38     /* Get the data type and number of sources. */
39     const int type = oskar_sky_precision(sky);
40     const int num_sources = oskar_sky_num_sources(sky);
41 
42     /* Print a helpful header. */
43     fprintf(file, "# Number of sources: %i\n", num_sources);
44     fprintf(file, "# RA (deg), Dec (deg), I (Jy), Q (Jy), U (Jy), V (Jy), "
45             "Ref. freq. (Hz), Spectral index, Rotation measure (rad/m^2), "
46             "FWHM major (arcsec), FWHM minor (arcsec), Position angle (deg)\n");
47 
48     /* Print out sky model in ASCII format. */
49     if (type == OSKAR_DOUBLE)
50     {
51         const double *ra_ = 0, *dec_ = 0, *I_ = 0, *Q_ = 0, *U_ = 0, *V_ = 0;
52         const double *ref_ = 0, *sp_ = 0, *rm_ = 0;
53         const double *maj_ = 0, *min_ = 0, *pa_ = 0;
54         ra_  = oskar_mem_double_const(oskar_sky_ra_rad_const(sky), status);
55         dec_ = oskar_mem_double_const(oskar_sky_dec_rad_const(sky), status);
56         I_   = oskar_mem_double_const(oskar_sky_I_const(sky), status);
57         Q_   = oskar_mem_double_const(oskar_sky_Q_const(sky), status);
58         U_   = oskar_mem_double_const(oskar_sky_U_const(sky), status);
59         V_   = oskar_mem_double_const(oskar_sky_V_const(sky), status);
60         ref_ = oskar_mem_double_const(oskar_sky_reference_freq_hz_const(sky), status);
61         sp_  = oskar_mem_double_const(oskar_sky_spectral_index_const(sky), status);
62         rm_  = oskar_mem_double_const(oskar_sky_rotation_measure_rad_const(sky), status);
63         maj_ = oskar_mem_double_const(oskar_sky_fwhm_major_rad_const(sky), status);
64         min_ = oskar_mem_double_const(oskar_sky_fwhm_minor_rad_const(sky), status);
65         pa_  = oskar_mem_double_const(oskar_sky_position_angle_rad_const(sky), status);
66 
67         for (i = 0; i < num_sources; ++i)
68         {
69             fprintf(file, "% 11.6f,% 11.6f,% 12.6e,% 12.6e,% 12.6e,% 12.6e,"
70                     "% 12.6e,% 12.6e,% 12.6e,% 12.6e,% 12.6e,% 11.6f\n",
71                     ra_[i] * RAD2DEG, dec_[i] * RAD2DEG,
72                     I_[i], Q_[i], U_[i], V_[i], ref_[i], sp_[i], rm_[i],
73                     maj_[i] * RAD2ARCSEC, min_[i] * RAD2ARCSEC,
74                     pa_[i] * RAD2DEG);
75         }
76     }
77     else if (type == OSKAR_SINGLE)
78     {
79         const float *ra_ = 0, *dec_ = 0, *I_ = 0, *Q_ = 0, *U_ = 0, *V_ = 0;
80         const float *ref_ = 0, *sp_ = 0, *rm_ = 0;
81         const float *maj_ = 0, *min_ = 0, *pa_ = 0;
82         ra_  = oskar_mem_float_const(oskar_sky_ra_rad_const(sky), status);
83         dec_ = oskar_mem_float_const(oskar_sky_dec_rad_const(sky), status);
84         I_   = oskar_mem_float_const(oskar_sky_I_const(sky), status);
85         Q_   = oskar_mem_float_const(oskar_sky_Q_const(sky), status);
86         U_   = oskar_mem_float_const(oskar_sky_U_const(sky), status);
87         V_   = oskar_mem_float_const(oskar_sky_V_const(sky), status);
88         ref_ = oskar_mem_float_const(oskar_sky_reference_freq_hz_const(sky), status);
89         sp_  = oskar_mem_float_const(oskar_sky_spectral_index_const(sky), status);
90         rm_  = oskar_mem_float_const(oskar_sky_rotation_measure_rad_const(sky), status);
91         maj_ = oskar_mem_float_const(oskar_sky_fwhm_major_rad_const(sky), status);
92         min_ = oskar_mem_float_const(oskar_sky_fwhm_minor_rad_const(sky), status);
93         pa_  = oskar_mem_float_const(oskar_sky_position_angle_rad_const(sky), status);
94 
95         for (i = 0; i < num_sources; ++i)
96         {
97             fprintf(file, "% 11.6f,% 11.6f,% 12.6e,% 12.6e,% 12.6e,% 12.6e,"
98                     "% 12.6e,% 12.6e,% 12.6e,% 12.6e,% 12.6e,% 11.6f\n",
99                     ra_[i] * RAD2DEG, dec_[i] * RAD2DEG,
100                     I_[i], Q_[i], U_[i], V_[i], ref_[i], sp_[i], rm_[i],
101                     maj_[i] * RAD2ARCSEC, min_[i] * RAD2ARCSEC,
102                     pa_[i] * RAD2DEG);
103         }
104     }
105     else
106     {
107         *status = OSKAR_ERR_BAD_DATA_TYPE;
108     }
109 
110     fclose(file);
111 }
112 
113 #ifdef __cplusplus
114 }
115 #endif
116