1 /*
2 * Copyright (c) 2014-2021, The OSKAR Developers.
3 * See the LICENSE file at the top-level directory of this distribution.
4 */
5
6 #include "apps/oskar_app_settings.h"
7 #include "apps/oskar_settings_log.h"
8 #include "log/oskar_log.h"
9 #include "settings/oskar_option_parser.h"
10 #include "telescope/station/element/oskar_element.h"
11 #include "utility/oskar_dir.h"
12 #include "utility/oskar_get_error_string.h"
13 #include "utility/oskar_version_string.h"
14
15 #include <cmath>
16 #include <cstdio>
17 #include <cstdlib>
18 #include <iomanip>
19 #include <sstream>
20
21 using namespace oskar;
22 using std::string;
23
24 static const char app[] = "oskar_fit_element_data";
25
26 static string construct_element_pathname(string output_dir,
27 int port, int element_type_index, double frequency_hz);
28
main(int argc,char ** argv)29 int main(int argc, char** argv)
30 {
31 OptionParser opt(app, oskar_version_string(), oskar_app_settings(app));
32 opt.add_settings_options();
33 opt.add_flag("-q", "Suppress printing.", false, "--quiet");
34 if (!opt.check_options(argc, argv)) return EXIT_FAILURE;
35 const char* settings = opt.get_arg(0);
36 int e = 0;
37
38 // Load the settings file.
39 SettingsTree* s = oskar_app_settings_tree(app, settings);
40 if (!s)
41 {
42 oskar_log_error(0, "Failed to read settings file '%s'", settings);
43 return EXIT_FAILURE;
44 }
45
46 // Get/set setting if necessary.
47 if (opt.is_set("--get"))
48 {
49 printf("%s\n", s->to_string(opt.get_arg(1), &e));
50 SettingsTree::free(s);
51 return !e ? 0 : EXIT_FAILURE;
52 }
53 else if (opt.is_set("--set"))
54 {
55 const char* key = opt.get_arg(1);
56 const char* val = opt.get_arg(2);
57 bool ok = val ? s->set_value(key, val) : s->set_default(key);
58 if (!ok) oskar_log_error(0, "Failed to set '%s'='%s'", key, val);
59 SettingsTree::free(s);
60 return ok ? 0 : EXIT_FAILURE;
61 }
62
63 // Set log parameters.
64 int priority = opt.is_set("-q") ? OSKAR_LOG_WARNING : OSKAR_LOG_STATUS;
65 oskar_Log* log = oskar_log_create(OSKAR_LOG_MESSAGE, priority);
66
67 // Write settings to log.
68 oskar_log_set_keep_file(log, 0);
69 oskar_settings_log(s, log);
70
71 // Get the main settings.
72 s->begin_group("element_fit");
73 string input_cst_file = s->to_string("input_cst_file", &e);
74 string input_scalar_file = s->to_string("input_scalar_file", &e);
75 string output_dir = s->to_string("output_directory", &e);
76 string pol_type = s->to_string("pol_type", &e);
77 // string coordinate_system = s->to_string("coordinate_system", &e);
78 int element_type_index = s->to_int("element_type_index", &e);
79 double frequency_hz = s->to_double("frequency_hz", &e);
80 double average_fractional_error =
81 s->to_double("average_fractional_error", &e);
82 double average_fractional_error_factor_increase =
83 s->to_double("average_fractional_error_factor_increase", &e);
84 int ignore_below_horizon = s->to_int("ignore_data_below_horizon", &e);
85 int ignore_at_pole = s->to_int("ignore_data_at_pole", &e);
86 int port = pol_type == "X" ? 1 : pol_type == "Y" ? 2 : 0;
87
88 // Check that the input and output files have been set.
89 if ((input_cst_file.empty() && input_scalar_file.empty()) ||
90 output_dir.empty())
91 {
92 oskar_log_error(log, "Specify input and output file names.");
93 oskar_log_free(log);
94 SettingsTree::free(s);
95 return EXIT_FAILURE;
96 }
97
98 // Create an element model.
99 oskar_Element* element = oskar_element_create(OSKAR_DOUBLE, OSKAR_CPU, &e);
100
101 // Load the CST text file for the correct port, if specified (X=1, Y=2).
102 if (!input_cst_file.empty())
103 {
104 oskar_log_line(log, 'M', ' ');
105 oskar_log_message(log, 'M', 0, "Loading CST element pattern: %s",
106 input_cst_file.c_str());
107 oskar_element_load_cst(element, port, frequency_hz,
108 input_cst_file.c_str(), average_fractional_error,
109 average_fractional_error_factor_increase,
110 ignore_at_pole, ignore_below_horizon, log, &e);
111
112 // Construct the output file name based on the settings.
113 if (port == 0)
114 {
115 string output = construct_element_pathname(output_dir, 1,
116 element_type_index, frequency_hz);
117 oskar_element_write(element, output.c_str(), 1,
118 frequency_hz, log, &e);
119 output = construct_element_pathname(output_dir, 2,
120 element_type_index, frequency_hz);
121 oskar_element_write(element, output.c_str(), 2,
122 frequency_hz, log, &e);
123 }
124 else
125 {
126 string output = construct_element_pathname(output_dir, port,
127 element_type_index, frequency_hz);
128 oskar_element_write(element, output.c_str(), port,
129 frequency_hz, log, &e);
130 }
131 }
132
133 // Load the scalar text file, if specified.
134 if (!input_scalar_file.empty())
135 {
136 oskar_log_message(log, 'M', 0, "Loading scalar element pattern: %s",
137 input_scalar_file.c_str());
138 oskar_element_load_scalar(element, frequency_hz,
139 input_scalar_file.c_str(), average_fractional_error,
140 average_fractional_error_factor_increase,
141 ignore_at_pole, ignore_below_horizon, log, &e);
142
143 // Construct the output file name based on the settings.
144 string output = construct_element_pathname(output_dir, 0,
145 element_type_index, frequency_hz);
146 oskar_element_write(element, output.c_str(), 0, frequency_hz, log, &e);
147 }
148
149 // Check for errors.
150 if (e)
151 {
152 oskar_log_error(log, "Run failed with code %i: %s.", e,
153 oskar_get_error_string(e));
154 }
155
156 // Free memory.
157 oskar_element_free(element, &e);
158 oskar_log_free(log);
159 SettingsTree::free(s);
160 return e ? EXIT_FAILURE : EXIT_SUCCESS;
161 }
162
163
construct_element_pathname(string output_dir,int port,int element_type_index,double frequency_hz)164 static string construct_element_pathname(string output_dir,
165 int port, int element_type_index, double frequency_hz)
166 {
167 std::ostringstream stream;
168 stream << "element_pattern_fit_";
169 if (port == 0)
170 {
171 stream << "scalar_";
172 }
173 else if (port == 1)
174 {
175 stream << "x_";
176 }
177 else if (port == 2)
178 {
179 stream << "y_";
180 }
181
182 // Append the element type index.
183 stream << element_type_index << "_";
184
185 // Append the frequency in MHz.
186 stream << std::fixed << std::setprecision(0)
187 << std::setfill('0') << std::setw(3) << frequency_hz / 1.0e6;
188
189 // Append the file extension.
190 stream << ".bin";
191
192 // Construct the full path.
193 char* path = oskar_dir_get_path(output_dir.c_str(), stream.str().c_str());
194 string p = string(path);
195 free(path);
196 return p;
197 }
198