Jpp test-rotations-old
the software that should make you happy
Loading...
Searching...
No Matches
JAcousticsMonitorRateTest.cc
Go to the documentation of this file.
1#include <string>
2#include <iostream>
3#include <fstream>
4#include <iomanip>
5#include <map>
6#include <locale>
7
8#include "TROOT.h"
9#include "TFile.h"
10#include "TObject.h"
11#include "TKey.h"
12#include "TString.h"
13#include "TRegexp.h"
14#include "TGraph.h"
15#include "TF1.h"
16#include "TH2D.h"
17
20#include "JTools/JRange.hh"
22#include "JTools/JHashMap.hh"
23#include "JLang/JLangToolkit.hh"
24#include "JLang/JColorFacet.hh"
25#include "JLang/JVectorize.hh"
26
27#include "Jeep/JParser.hh"
28#include "Jeep/JMessage.hh"
29#include "Jeep/JPrint.hh"
30#include "Jeep/JColor.hh"
31
32#include "JROOT/JManager.hh"
33
36
37namespace {
38
39 using JTOOLS::JRange;
40
41 /**
42 * Auxilliary data structure with test criteria.
43 */
44 struct JParameters_t {
45
46 static const char SKIPLINE = '#'; //!< skip line character
47
48 /**
49 * Default constructor.
50 */
51 JParameters_t() :
52 working(1),
53 expected_rate(0),
54 range(JRange<double>::DEFAULT_RANGE()),
55 number_of_outliers(0)
56 {}
57
58
59 /**
60 * Read parameters from input stream.
61 *
62 * \param input input stream
63 * \param object parameters
64 * \return input stream
65 */
66 friend inline std::istream& operator>>(std::istream& in, JParameters_t& object)
67 {
68 using namespace std;
69 return in >> object.working >> object.expected_rate >> object.range >> object.number_of_outliers;
70 }
71
72
73 /**
74 * Write parameters to output stream.
75 *
76 * \param output output stream
77 * \param object parameters
78 * \return output stream
79 */
80 friend inline std::ostream& operator<<(std::ostream& out, const JParameters_t& object)
81 {
82 using namespace std;
83 using namespace JPP;
84
85 return out << setw(6) << object.working << ' '
86 << FIXED(2,6) << object.expected_rate << ' '
87 << FIXED(2,6) << object.range.getLowerLimit() << ' '
88 << FIXED(2,6) << object.range.getUpperLimit() << ' '
89 << setw(4) << object.number_of_outliers;
90 }
91
92 int working;
93 double expected_rate;
94 JRange<double> range;
95 int number_of_outliers;
96 };
97
98 /*
99 * Gets list of keys in a ROOT TDirectory and stores it on a vector.
100 *
101 * \param dir The ROOT directory
102 * \param buffer Vector to store keys
103 */
104 void readDir(TDirectory* dir,
106
107 TIter iter(dir->GetListOfKeys());
108
109 for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
110
111 if (key->IsFolder()){
112
113 dir->cd(key->GetName());
114
115 TDirectory *subdir = gDirectory;
116 readDir(subdir, buffer);
117
118 dir->cd();
119
120 } else {
121
122 JGIZMO::JRootObjectID objectID(MAKE_STRING(dir->GetPath() << key->GetName()));
123
124 buffer.push_back(objectID);
125 }
126 }
127 }
128
129}
130
131
132/**
133 *
134 * Program to test:
135 * - If there is acoustic data.
136 * - If the rate recorded by each receiver is within the expected range.
137 * - If emitters and receivers are working and compares it to what is expected.
138 *
139 * Reports failure if: no acoustic data, too large number of outliers, emitter expected to work is not working,
140 * hydrophone expected to work is not working.
141 *
142 */
143
144int main(int argc, char **argv)
145{
146 using namespace std;
147 using namespace JPP;
148
149 string inputFile;
150 string parametersFile;
151 string facet;
152 string output_summary;
153 string output_status;
154 string detectorFile;
155 int debug;
156 int number_of_failures = 0;
157 int run;
158
159 try {
160
161 JParser<> zap("Auxiliary program to apply test criteria to 2D histograms monitoring acoustic rate per emitter.");
162
163 zap['i'] = make_field(inputFile, "output root file from JAcousticsMonitorRateSummary");
164 zap['@'] = make_field(parametersFile, "ASCII formatted input file with test criteria (acoustics_monitor)");
165 zap['F'] = make_field(facet, "Color facet") = get_keys(color_facets);
166 zap['d'] = make_field(debug) = 1;
167 zap['s'] = make_field(output_summary, "output summary file");
168 zap['o'] = make_field(output_status, "output information file working/not working");
169 zap['a'] = make_field(detectorFile);
170 zap['r'] = make_field(run, "run number");
171 zap(argc, argv);
172 }
173 catch(const exception &error) {
174 FATAL(error.what() << endl);
175 }
176
177 ofstream out_summary(output_summary.c_str());
178 out_summary.imbue(locale(out_summary.getloc(), color_facets[facet]->clone()));
179 out_summary << "ACOUSTIC MONITORING \nRun: " << run << endl;
180 out_summary << "\n(Note: red highlights are the reason for the warning)" << endl;
181
182 ofstream out_status;
183 out_status.open(output_status.c_str());
184 out_status << "INFORMATION ABOUT RECEIVER STATUS \nRun: " << run << endl;
185
186 // read parameters file
187
188 typedef map<string, JParameters_t> map_type;
189
190 map_type zmap;
191
192 ifstream in(parametersFile.c_str());
193
194 if (in) {
195
196 string key;
197 JParameters_t parameters;
198
199 for (string buffer; getline(in, buffer); ) {
200
201 if (!buffer.empty() && buffer[0] != JParameters_t::SKIPLINE) {
202
203 istringstream is(buffer);
204
205 if (is >> key >> parameters) { zmap[key] = parameters; }
206 }
207 }
208
209 in.close();
210
211 } else {
212 FATAL("Error opening file: " << parametersFile << endl);
213 }
214
215 // create hist for test output
216
218
219 try {
220 load(detectorFile, detector);
221 }
222 catch(const JException& error) {
223 FATAL(error);
224 }
225
226 JHashMap<int, JLocation> receivers;
227
228 for (JDetector::const_iterator i = detector.begin(); i != detector.end(); ++i) {
229
230 receivers[i->getID()] = i->getLocation();
231 }
232
233 const JHashCollection<int> string1(make_array(detector.begin(), detector.end(), &JModule::getString));
234 const JRange <int> floor1 (make_array(detector.begin(), detector.end(), &JModule::getFloor));
235
236 JManager<int, TH2D> H3(new TH2D("H[%].rate-test", NULL,
237 string1.size(), - 0.5, string1.size() - 0.5,
238 floor1.getUpperLimit() + 1, - 0.5, floor1.getUpperLimit() + 0.5));
239
240 for (Int_t i = 1; i <= H3->GetXaxis()->GetNbins(); ++i) {
241 H3->GetXaxis()->SetBinLabel(i, MAKE_CSTRING(string1.at(i-1)));
242 }
243
244 for (Int_t i = 1; i <= H3->GetYaxis()->GetNbins(); ++i) {
245 H3->GetYaxis()->SetBinLabel(i, MAKE_CSTRING(i-1));
246 }
247
248 // read input file
249
250 TFile* f = TFile::Open(inputFile.c_str());
251
252 vector<JRootObjectID> objectIDs;
253
254 readDir(f,objectIDs);
255
256 // check if the monitor.root file is empty
257 int no_data = 0;
258 if(objectIDs.empty()) {
259 ++number_of_failures;
260 no_data += 1;
261 out_summary << RED << "No acoustic data." << endl;
262 out_summary << RESET;
263 }
264
265 // loop over expected emitters
266
267 for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
268
269 if (i->first[0] == '0') { continue; } // skip receivers parameters file
270
271 out_summary << "\nEmitter: " << i->first << endl;
272 out_status << "\nEmitter: " << i->first << endl;
273 const TRegexp regexp("H\\[" + i->first + "\\]");
274
275 TH2D* h3 = H3[stoi(i->first)];
276
277 // if no data at all, all receivers out of range
278 if (no_data > 0) {
279 out_summary << "No data at all." << endl;
280 out_status << "expected rate: " << i->second.expected_rate << endl;
281 out_status << "min rate fraction: " << i->second.range.getLowerLimit() << endl;
282 out_status << "max rate fraction: " << i->second.range.getUpperLimit() << endl;
283 out_status << "max allowed outliers: " << i->second.number_of_outliers << endl;
284 out_status << "\nDU\tFloor\tOutOfRange\tSupposedToWork\tRate" << endl;
285 for (Int_t ix = 1; ix <= h3->GetXaxis()->GetNbins(); ++ix) {
286 for (Int_t iy = 1; iy <= h3->GetYaxis()->GetNbins(); ++iy) {
287 string du = to_string(h3->GetXaxis()->GetBinLabel(ix));
288 string floor = to_string(h3->GetYaxis()->GetBinLabel(iy));
289 h3->Fill(ix-1, iy-1, 1.0);
290 out_status << du << "\t" << floor << "\t" << 1 << "\t" << i->second.working << "\t" << 0 << endl; // for all receivers OutOfRange=1, Rate=0
291 }
292 }
293 }
294
295 // check if data from emitter is in input file
296 for (vector<JRootObjectID>::const_iterator objectID = objectIDs.cbegin() ; objectID != objectIDs.cend() ; ++objectID) {
297
298 const TString& objectName = objectID->getFullObjectName();
299 // data from emitter is in input file
300 if (objectName.Index(regexp) != -1) {
301
302 // check if expected status emitter changed
303 if (!i->second.working) {
304 out_summary << (i->second.working != 0 ? RED : GREEN);
305 out_summary << "Emitter started working." << endl;
306 out_summary << RESET;
307 out_summary << "(Acoustic rates not tested)" << endl;
308 }
309
310 // if emitter expected to work, test acoustic rate
311 if (i->second.working) {
312 TObject* p = (TObject*)f->Get(objectName);
313 TH2* h2 = NULL;
314
315 int number_of_bins = 0;
316 int number_of_outliers = 0;
317
318 double min_rate = i->second.expected_rate * i->second.range.getLowerLimit();
319 double max_rate = i->second.expected_rate * i->second.range.getUpperLimit();
320 int outliers = i->second.number_of_outliers;
321
322 if (h2 == NULL && dynamic_cast<TH2*>(p) != NULL) { h2 = dynamic_cast<TH2*>(p); };
323
324 if (h2 != NULL) {
325 out_summary << "Testing acoustic rate." << endl;
326 out_status << "expected rate: " << i->second.expected_rate << endl;
327 out_status << "min rate fraction: " << i->second.range.getLowerLimit() << endl;
328 out_status << "max rate fraction: " << i->second.range.getUpperLimit() << endl;
329 out_status << "max allowed outliers: " << i->second.number_of_outliers << endl;
330 out_status << "\nDU\tFloor\tOutOfRange\tSupposedToWork\tRate" << endl;
331
332 for (Int_t ix = 1; ix <= h2->GetXaxis()->GetNbins(); ++ix) {
333 for (Int_t iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) {
334
335 const Double_t z = h2->GetBinContent(ix, iy);
336 string du = to_string(h2->GetXaxis()->GetBinLabel(ix));
337 string floor = to_string(h2->GetYaxis()->GetBinLabel(iy));
338
339 du.insert(du.begin(), 4 - du.length(), '0');
340 floor.insert(floor.begin(), 3 - floor.length(), '0');
341 const string id = du + '.' + floor;
342
343 int working = 1;
344 int status = 0; // assume receiver is working
345 if (zmap.find(id)!=zmap.end()) { working = zmap.find(id)->second.working; }
346
347 ++number_of_bins;
348
349 // acoustic rate out of range
350 if (z < min_rate || z > max_rate) {
351
352 h3->Fill(ix-1, iy-1, 1.0);
353 status = 1; // set receiver to not working
354
355 ++number_of_outliers;
356
357 if (working) { // receiver expected to work
358
359 if (floor == "000" && z == 0) { // if hydrophone doesn't work
360 out_summary << "DU " << du << ", floor " << floor << " : Acoustic rate out of range -> " << z << " Hz." << RED << " Hydrophone stopped working." << endl;
361 out_summary << RESET;
362 ++number_of_failures;
363 } else {
364 out_summary << "DU " << du << ", floor " << floor << " : Acoustic rate out of range -> " << z << " Hz." << endl;
365 }
366 }
367 } else if (!working) { // receiver expected to not work
368 out_summary << "DU " << du << ", floor " << floor << " : Working again -> " << z << " Hz." << endl;
369 }
370 out_status << du << "\t" << floor << "\t" << status << "\t" << working << "\t" << z << endl;
371 }
372 }
373 } else { FATAL("Object at " << objectName << " is not TH2." << endl); }
374
375 out_summary << (number_of_outliers > outliers ? RED : GREEN) << "Number of outliers = " << number_of_outliers << "/" << number_of_bins << endl;
376 out_summary << RESET;
377
378 if (number_of_outliers > outliers) {
379
380 ++number_of_failures;
381 out_summary << (number_of_outliers > outliers ? RED : GREEN) << "Test failed." << endl;
382 out_summary << RESET;
383 } else {
384
385 out_summary << (outliers >= number_of_outliers ? GREEN : RED) << "Test passed." << endl;
386 out_summary << RESET;
387 }
388 }
389 break;
390
391 // data from emitter is not in input file
392 } else if (objectID + 1 == objectIDs.cend()) {
393 out_summary << "Data from emitter not in input file." << endl;
394 out_status << "expected rate: " << i->second.expected_rate << endl;
395 out_status << "min rate fraction: " << i->second.range.getLowerLimit() << endl;
396 out_status << "max rate fraction: " << i->second.range.getUpperLimit() << endl;
397 out_status << "max allowed outliers: " << i->second.number_of_outliers << endl;
398 out_status << "\nDU\tFloor\tOutOfRange\tSupposedToWork\tRate" << endl;
399 // for all receivers rate out of range
400 for (Int_t ix = 1; ix <= h3->GetXaxis()->GetNbins(); ++ix) {
401 for (Int_t iy = 1; iy <= h3->GetYaxis()->GetNbins(); ++iy) {
402 string du = to_string(h3->GetXaxis()->GetBinLabel(ix));
403 string floor = to_string(h3->GetYaxis()->GetBinLabel(iy));
404 h3->Fill(ix-1, iy-1, 1.0);
405 out_status << du << "\t" << floor << "\t" << 1 << "\t" << i->second.working << "\t" << 0 << endl; // for all receivers OutOfRange=1, Rate=0
406 }
407 }
408
409 // check if expected status emitter changed
410 if (i->second.working) {
411 ++number_of_failures;
412 out_summary << (i->second.working != 0 ? RED : GREEN) << "Emitter stopped working." << endl;
413 out_summary << RESET;
414 } else {
415 out_summary << "Emitter is expected to not work." << endl;
416 }
417 }
418 }
419 }
420 out_summary.close();
421 out_status.close();
422
423 return 0;
424}
int main(int argc, char **argv)
Program to test:
I/O coloring auxiliaries.
Data structure for detector geometry and calibration.
General purpose class for a hash collection of unique elements.
General purpose class for hash map of unique elements.
std::istream & operator>>(std::istream &in, JAANET::JHead &header)
Read header from input.
Definition JHead.hh:1832
Dynamic ROOT object management.
General purpose messaging.
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:72
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2142
void readDir(TDirectory *dir, std::vector< TString > &v)
I/O formatting auxiliaries.
#define MAKE_CSTRING(A)
Make C-string.
Definition JPrint.hh:72
#define MAKE_STRING(A)
Make string.
Definition JPrint.hh:63
Auxiliary class to define a range between two values.
Auxiliary methods to convert data members or return values of member methods of a set of objects to a...
Detector data structure.
Definition JDetector.hh:96
Auxiliary class to handle file name, ROOT directory and object name.
General exception.
Definition JException.hh:24
Utility class to parse command line options.
Definition JParser.hh:1698
General purpose class for hash collection of unique elements.
Range of values.
Definition JRange.hh:42
T getUpperLimit() const
Get upper limit.
Definition JRange.hh:213
std::ostream & operator<<(std::ostream &stream, const CLBCommonHeader &header)
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Detector file.
Definition JHead.hh:227
General purpose class for hash map of unique keys.
Definition JHashMap.hh:75