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 "telescope/oskar_telescope.h"
7 #include "utility/oskar_dir.h"
8 #include "math/oskar_cmath.h"
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 static void oskar_telescope_save_private(const oskar_Telescope* telescope,
15         const char* dir_path, const oskar_Station* station, int depth,
16         int* status);
17 
oskar_telescope_save(const oskar_Telescope * telescope,const char * dir_path,int * status)18 void oskar_telescope_save(const oskar_Telescope* telescope,
19         const char* dir_path, int* status)
20 {
21     oskar_telescope_save_private(telescope, dir_path, NULL, 0, status);
22 }
23 
oskar_telescope_save_private(const oskar_Telescope * telescope,const char * dir_path,const oskar_Station * station,int depth,int * status)24 static void oskar_telescope_save_private(const oskar_Telescope* telescope,
25         const char* dir_path, const oskar_Station* station, int depth,
26         int* status)
27 {
28     char* path = 0;
29     int i = 0, num_stations = 0;
30 
31     if (depth == 0)
32     {
33         /* Check if directory already exists, and remove it if so. */
34         if (oskar_dir_exists(dir_path))
35         {
36             if (!oskar_dir_remove(dir_path))
37             {
38                 *status = OSKAR_ERR_FILE_IO;
39                 return;
40             }
41         }
42     }
43 
44     /* Create the directory if it doesn't exist. */
45     if (!oskar_dir_exists(dir_path))
46     {
47         oskar_dir_mkpath(dir_path);
48     }
49 
50     if (depth == 0)
51     {
52         /* Write the reference position. */
53         FILE* file = 0;
54         path = oskar_dir_get_path(dir_path, "position.txt");
55         file = fopen(path, "w");
56         free(path);
57         if (!file)
58         {
59             *status = OSKAR_ERR_FILE_IO;
60             return;
61         }
62         fprintf(file, "%.12f, %.12f, %.12f\n",
63                 oskar_telescope_lon_rad(telescope) * 180.0 / M_PI,
64                 oskar_telescope_lat_rad(telescope) * 180.0 / M_PI,
65                 oskar_telescope_alt_metres(telescope));
66         fclose(file);
67 
68         /* Write the station coordinates. */
69         path = oskar_dir_get_path(dir_path, "layout.txt");
70         oskar_telescope_save_layout(telescope, path, status);
71         free(path);
72 
73         /* Write the station type mapping. */
74         path = oskar_dir_get_path(dir_path, "station_type_map.txt");
75         file = fopen(path, "w");
76         free(path);
77         oskar_mem_save_ascii(file, 1, 0,
78                 oskar_telescope_num_stations(telescope), status,
79                 oskar_telescope_station_type_map_const(telescope));
80         fclose(file);
81 
82         /* Get the number of stations. */
83         num_stations = oskar_telescope_num_station_models(telescope);
84     }
85     else
86     {
87         int num_feeds = 2, name_offset = 1;
88 
89         /* Write the station configuration data. */
90         path = oskar_dir_get_path(dir_path, "mount_types.txt");
91         oskar_station_save_mount_types(station, path, status);
92         free(path);
93         if (!oskar_station_has_child(station))
94         {
95             path = oskar_dir_get_path(dir_path, "feed_angle_x.txt");
96             oskar_station_save_feed_angle(station, 0, path, status);
97             free(path);
98             path = oskar_dir_get_path(dir_path, "feed_angle_y.txt");
99             oskar_station_save_feed_angle(station, 1, path, status);
100             free(path);
101         }
102         if (oskar_station_num_element_types(station) > 1)
103         {
104             path = oskar_dir_get_path(dir_path, "element_types.txt");
105             oskar_station_save_element_types(station, path, status);
106             free(path);
107         }
108         if (oskar_station_num_permitted_beams(station) > 0)
109         {
110             path = oskar_dir_get_path(dir_path, "permitted_beams.txt");
111             oskar_station_save_permitted_beams(station, path, status);
112             free(path);
113         }
114         if (oskar_station_common_pol_beams(station))
115         {
116             num_feeds = 1;
117             name_offset = 0;
118         }
119         const char* layout_name[] = {
120                 "layout.txt",
121                 "layout_x.txt",
122                 "layout_y.txt"};
123         const char* cable_name[] = {
124                 "cable_length_error.txt",
125                 "cable_length_error_x.txt",
126                 "cable_length_error_y.txt"};
127         const char* gain_phase_name[] = {
128                 "gain_phase.txt",
129                 "gain_phase_x.txt",
130                 "gain_phase_y.txt"};
131         const char* apodisation_name[] = {
132                 "apodisation.txt",
133                 "apodisation_x.txt",
134                 "apodisation_y.txt"};
135         for (i = 0; i < num_feeds; ++i)
136         {
137             const int i_name = i + name_offset;
138             path = oskar_dir_get_path(dir_path, layout_name[i_name]);
139             oskar_station_save_layout(station, i, path, status);
140             free(path);
141             path = oskar_dir_get_path(dir_path, cable_name[i_name]);
142             oskar_station_save_cable_length_error(station, i, path, status);
143             free(path);
144             if (oskar_station_apply_element_errors(station))
145             {
146                 path = oskar_dir_get_path(dir_path, gain_phase_name[i_name]);
147                 oskar_station_save_gain_phase(station, i, path, status);
148                 free(path);
149             }
150             if (oskar_station_apply_element_weight(station))
151             {
152                 path = oskar_dir_get_path(dir_path, apodisation_name[i_name]);
153                 oskar_station_save_apodisation(station, i, path, status);
154                 free(path);
155             }
156         }
157 
158         /* Get the number of stations. */
159         if (oskar_station_has_child(station))
160         {
161             num_stations = oskar_station_num_elements(station);
162         }
163     }
164 
165     /* Recursive call to write stations. */
166     for (i = 0; i < num_stations; ++i)
167     {
168         /* Get station name, and a pointer to the station to save. */
169         const oskar_Station* s = 0;
170         char station_name[128], *path = 0;
171         sprintf(station_name, "level%1d_%03d", depth, i);
172         s = (depth == 0) ? oskar_telescope_station_const(telescope, i) :
173                 oskar_station_child_const(station, i);
174 
175         /* Save this station. */
176         if (!s) continue;
177         path = oskar_dir_get_path(dir_path, station_name);
178         oskar_telescope_save_private(telescope, path, s, depth + 1, status);
179         free(path);
180     }
181 }
182 
183 #ifdef __cplusplus
184 }
185 #endif
186