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