1 /*
2 * Copyright (c) 2013-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 "apps/oskar_settings_to_telescope.h"
9 #include "binary/oskar_binary.h"
10 #include "log/oskar_log.h"
11 #include "settings/oskar_option_parser.h"
12 #include "telescope/oskar_telescope.h"
13 #include "utility/oskar_file_exists.h"
14 #include "utility/oskar_get_error_string.h"
15 #include "utility/oskar_version_string.h"
16 #include "vis/oskar_vis_block.h"
17 #include "vis/oskar_vis_header.h"
18
19 #include <cstdlib>
20 #include <iostream>
21 #include <string>
22 #include <vector>
23
24 using namespace oskar;
25 using namespace std;
26
27 static const char app[] = "oskar_vis_add_noise";
28 static const char app_s[] = "oskar_sim_interferometer";
29
30
main(int argc,char ** argv)31 int main(int argc, char** argv)
32 {
33 int status = 0;
34
35 // Obtain command line options & arguments.
36 OptionParser opt(app, oskar_version_string(), oskar_app_settings(app_s));
37 opt.set_description("Application to add noise to OSKAR binary visibility "
38 "files.");
39 opt.add_required("OSKAR visibility file(s)...");
40 opt.add_flag("-s", "OSKAR settings file (noise settings).", 1, "", true);
41 opt.add_flag("-v", "Verbose logging.");
42 opt.add_flag("-q", "Suppress all logging output.");
43 if (!opt.check_options(argc, argv)) return EXIT_FAILURE;
44
45 int num_files = 0;
46 string settings(opt.get_string("-s"));
47 const char* const* vis_filename_in = opt.get_input_files(1, &num_files);
48 bool verbose = opt.is_set("-v") ? true : false;
49 bool quiet = opt.is_set("-q") ? true : false;
50
51 // Set log parameters.
52 oskar_Log* log = 0;
53 int file_priority = OSKAR_LOG_MESSAGE;
54 int term_priority = OSKAR_LOG_STATUS;
55 if (quiet) term_priority = OSKAR_LOG_WARNING;
56 if (verbose) term_priority = OSKAR_LOG_DEBUG;
57 oskar_log_set_file_priority(log, file_priority);
58 oskar_log_set_term_priority(log, term_priority);
59 oskar_log_set_keep_file(log, false);
60
61 // Load the settings file.
62 SettingsTree* s = oskar_app_settings_tree(app_s, settings.c_str());
63 if (!s)
64 {
65 oskar_log_error(0, "Failed to read settings file.");
66 return EXIT_FAILURE;
67 }
68
69 // Write settings to log.
70 oskar_settings_log(s, log);
71 if (!s->to_int("interferometer/noise/enable", &status))
72 {
73 oskar_log_error(log, "Noise addition disabled in the settings.");
74 oskar_log_free(log);
75 SettingsTree::free(s);
76 return EXIT_FAILURE;
77 }
78
79 // Set up the telescope model.
80 oskar_Telescope* tel = oskar_settings_to_telescope(s, 0, &status);
81 oskar_telescope_analyse(tel, &status);
82
83 // Create list of output vis file names.
84 vector<string> vis_filename_out(num_files);
85 for (int i = 0; i < (int)vis_filename_out.size(); ++i)
86 {
87 if (status) break;
88 string str = vis_filename_in[i];
89 if (!oskar_file_exists(str.c_str()))
90 {
91 oskar_log_error(log, "Visibility file %s not found.", str.c_str());
92 status = OSKAR_ERR_FILE_IO;
93 break;
94 }
95 // TODO check if the file exists
96 str.erase(str.end()-4, str.end());
97 vis_filename_out[i] = str + "_noise.vis";
98 }
99
100 // Print a summary of what is about to happen.
101 if (!status)
102 {
103 oskar_log_line(log, 'D', ' ');
104 oskar_log_line(log, 'D', '-');
105 oskar_log_value(log, 'D', -1, "Number of input files", "%i", num_files);
106 for (int i = 0; i < num_files; ++i)
107 {
108 oskar_log_message(log, 'D', 1, "%s", vis_filename_in[i]);
109 }
110 oskar_log_value(log, 'D', -1, "Settings file", "%s", settings.c_str());
111 oskar_log_value(log, 'D', -1,
112 "Verbose", "%s", verbose ? "true" : "false");
113 oskar_log_line(log, 'D', '-');
114 }
115
116 // Add uncorrelated noise to each of the visibility files.
117 for (int i = 0; i < num_files; ++i)
118 {
119 if (status) break;
120 const char* in_file = vis_filename_in[i];
121 const char* out_file = vis_filename_out[i].c_str();
122 oskar_log_line(log, 'D', ' ');
123 oskar_log_value(log, 'D', -1, "Loading visibility file", "%s", in_file);
124
125 // Load the input file and create the output file.
126 oskar_Binary* h_in = oskar_binary_create(in_file, 'r', &status);
127 oskar_VisHeader* hdr = oskar_vis_header_read(h_in, &status);
128 oskar_Binary* h_out = oskar_vis_header_write(hdr, out_file, &status);
129
130 // TODO Check that the visibility file was written with normalise
131 // beam mode enabled. If not print a warning.
132 // TODO Also verify any settings in the vis file against those loaded.
133
134 // Get header data.
135 int type = oskar_vis_header_coord_precision(hdr);
136 oskar_Mem* station_work = oskar_mem_create(type, OSKAR_CPU, 0, &status);
137
138 // Create a visibility block to read into.
139 oskar_VisBlock* blk = oskar_vis_block_create_from_header(OSKAR_CPU,
140 hdr, &status);
141
142 // Loop over blocks and add noise to each one.
143 const int num_blocks = oskar_vis_header_num_blocks(hdr);
144 for (int b = 0; b < num_blocks; ++b)
145 {
146 if (status) break;
147 oskar_vis_block_read(blk, hdr, h_in, b, &status);
148 oskar_vis_block_add_system_noise(blk, hdr, tel, station_work,
149 &status);
150 oskar_vis_block_write(blk, h_out, b, &status);
151 }
152
153 // Free memory for vis header and vis block, and close files.
154 oskar_mem_free(station_work, &status);
155 oskar_vis_block_free(blk, &status);
156 oskar_vis_header_free(hdr, &status);
157 oskar_binary_free(h_in);
158 oskar_binary_free(h_out);
159 }
160
161 // Free telescope model.
162 oskar_telescope_free(tel, &status);
163 if (status)
164 {
165 oskar_log_error(log, "Error: %s", oskar_get_error_string(status));
166 }
167 oskar_log_free(log);
168 SettingsTree::free(s);
169 return status ? EXIT_FAILURE : EXIT_SUCCESS;
170 }
171