Jpp  16.0.0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JAcousticsMonitorTest.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 
17 #include "JGizmo/JRootObjectID.hh"
18 #include "JGizmo/JGizmoToolkit.hh"
19 #include "JTools/JRange.hh"
20 #include "JLang/JLangToolkit.hh"
21 #include "JLang/JColorFacet.hh"
22 #include "JLang/JVectorize.hh"
23 
24 #include "Jeep/JParser.hh"
25 #include "Jeep/JMessage.hh"
26 #include "Jeep/JPrint.hh"
27 #include "Jeep/JColor.hh"
28 
29 #include "TH2D.h"
30 
31 
32 namespace {
33 
34  using JTOOLS::JRange;
35 
36  /**
37  * Auxilliary data structure with test criteria.
38  */
39  struct JParameters_t {
40 
41  static const char SKIPLINE = '#'; //!< skip line character
42 
43  /**
44  * Default constructor.
45  */
46  JParameters_t() :
47  working(1),
48  expected_rate(0),
49  range(JRange<double>::DEFAULT_RANGE),
50  number_of_outliers(0)
51  {}
52 
53 
54  /**
55  * Read parameters from input stream.
56  *
57  * \param input input stream
58  * \param object parameters
59  * \return input stream
60  */
61  friend inline std::istream& operator>>(std::istream& in, JParameters_t& object)
62  {
63  using namespace std;
64  return in >> object.working >> object.expected_rate >> object.range >> object.number_of_outliers;
65  }
66 
67 
68  /**
69  * Write parameters to output stream.
70  *
71  * \param output output stream
72  * \param object parameters
73  * \return output stream
74  */
75  friend inline std::ostream& operator<<(std::ostream& out, const JParameters_t& object)
76  {
77  using namespace std;
78  using namespace JPP;
79 
80  return out << setw(6) << object.working << ' '
81  << FIXED(2,6) << object.expected_rate << ' '
82  << FIXED(2,6) << object.range.getLowerLimit() << ' '
83  << FIXED(2,6) << object.range.getUpperLimit() << ' '
84  << setw(4) << object.number_of_outliers;
85  }
86 
87  int working;
88  double expected_rate;
89  JRange<double> range;
90  int number_of_outliers;
91  };
92 
93  /*
94  * Gets list of keys in a ROOT TDirectory and stores it on a vector.
95  *
96  * \param dir The ROOT directory
97  * \param buffer Vector to store keys
98  */
99  void readDir(TDirectory* dir,
101 
102  TIter iter(dir->GetListOfKeys());
103 
104  for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
105 
106  if (key->IsFolder()){
107 
108  dir->cd(key->GetName());
109 
110  TDirectory *subdir = gDirectory;
111  readDir(subdir, buffer);
112 
113  dir->cd();
114 
115  } else {
116 
117  JGIZMO::JRootObjectID objectID(MAKE_STRING(dir->GetPath() << key->GetName()));
118 
119  buffer.push_back(objectID);
120  }
121  }
122  }
123 
124 }
125 
126 
127 /**
128  *
129  * Program to test:
130  * - If there is acoustic data.
131  * - If the rate recorded by each receiver is within the expected range.
132  * - If emitters and receivers are working and compares it to what is expected.
133  *
134  * Reports failure if: no acoustic data, too large number of outliers, emitter expected to work is not working,
135  * hydrophone expected to work is not working.
136  *
137  */
138 
139 int main(int argc, char **argv)
140 {
141  using namespace std;
142  using namespace JPP;
143 
144  string inputFile;
145  string parametersFile;
146  string facet;
147  string outputFile;
148  int debug;
149  int number_of_failures = 0;
150  int run;
151 
152  try {
153 
154  JParser<> zap("Auxiliary program to apply test criteria to 2D histograms monitoring acoustic rate per emitter.");
155 
156  zap['f'] = make_field(inputFile, "output root file from JAcousticsMonitor_short");
157  zap['P'] = make_field(parametersFile, "ASCII formatted input file with test criteria (acoustic_monitor_00000XXX.txt)");
158  zap['F'] = make_field(facet, "Color facet") = get_keys(color_facets);
159  zap['d'] = make_field(debug) = 1;
160  zap['w'] = make_field(outputFile, "output summary file");
161  zap['r'] = make_field(run, "run number");
162  zap(argc, argv);
163  }
164  catch(const exception &error) {
165  FATAL(error.what() << endl);
166  }
167 
168  ofstream out(outputFile.c_str());
169  out.imbue(locale(out.getloc(), color_facets[facet]->clone()));
170  out << "ACOUSTIC MONITORING \nRun: " << run << endl;
171  out << "\n(Note: red highlights are the reason for the warning)" << endl;
172  // read parameters file
173 
174  typedef map<string, JParameters_t> map_type;
175 
176  map_type zmap;
177 
178  ifstream in(parametersFile.c_str());
179 
180  if (in) {
181 
182  string key;
183  JParameters_t parameters;
184 
185  for (string buffer; getline(in, buffer); ) {
186 
187  if (!buffer.empty() && buffer[0] != JParameters_t::SKIPLINE) {
188 
189  istringstream is(buffer);
190 
191  if (is >> key >> parameters) { zmap[key] = parameters; }
192  }
193  }
194 
195  in.close();
196 
197  } else {
198  FATAL("Error opening file: " << parametersFile << endl);
199  }
200 
201  // read input file
202 
203  TFile* f = TFile::Open(inputFile.c_str());
204 
205  vector<JRootObjectID> objectIDs;
206 
207  readDir(f,objectIDs);
208 
209  // check if the monitor.root file is empty
210  if(objectIDs.empty()) {
211  ++number_of_failures;
212  out << RED << "No acoustic data." << endl;
213  out << RESET;
214  }
215 
216  // loop over expected emitters
217 
218  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
219 
220  if (i->first[0] == '0') { continue; } // skip receivers
221 
222  out << "\nEmitter: " << i->first << endl;
223 
224  const TRegexp regexp(i->first);
225 
226 
227  // check if data from emitter is in input file
228 
229  for (vector<JRootObjectID>::const_iterator objectID = objectIDs.cbegin() ; objectID != objectIDs.cend() ; ++objectID) {
230 
231  const TString& objectName = objectID->getFullObjectName();
232 
233  // data from emitter is in input file
234  if (objectName.Index(regexp) != -1) {
235 
236  // check if expected status emitter changed
237  if (!i->second.working) {
238  out << (i->second.working != 0 ? RED : GREEN);
239  out << "Emitter started working." << endl;
240  out << RESET;
241  out << "(Acoustic rates not tested)" << endl;
242  }
243 
244  if (i->second.working) {
245  // test acoustic rate
246  TObject* p = (TObject*)f->Get(objectName);
247  TH2* h2 = NULL;
248 
249  int number_of_bins = 0;
250  int number_of_outliers = 0;
251 
252  double min_rate = i->second.expected_rate * i->second.range.getLowerLimit();
253  double max_rate = i->second.expected_rate * i->second.range.getUpperLimit();
254  int outliers = i->second.number_of_outliers;
255 
256  if (h2 == NULL && dynamic_cast<TH2*>(p) != NULL) { h2 = dynamic_cast<TH2*>(p); };
257 
258  if (h2 != NULL) {
259 
260  for (Int_t ix = 1; ix <= h2->GetXaxis()->GetNbins(); ++ix) {
261  for (Int_t iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) {
262 
263  const Double_t z = h2->GetBinContent(ix, iy);
264  string du = to_string(h2->GetXaxis()->GetBinLabel(ix));
265  string floor = to_string(h2->GetYaxis()->GetBinLabel(iy));
266 
267  du.insert(du.begin(), 4 - du.length(), '0');
268  floor.insert(floor.begin(), 3 - floor.length(), '0');
269  const string id = du + '.' + floor;
270 
271  int working = 1;
272  if (zmap.find(id)!=zmap.end()) { working = zmap.find(id)->second.working; }
273 
274  ++number_of_bins;
275 
276  // acoustic rate out of range
277  if (z < min_rate || z > max_rate) {
278 
279  ++number_of_outliers;
280  if (working) { // receiver expected to work
281 
282  if (floor == "000" && z == 0) { // if hydrophone doesn't work
283  out << "DU " << du << ", floor " << floor << " : Acoustic rate out of range -> " << z << " Hz." << RED << " Hydrophone stopped working." << endl;
284  out << RESET;
285  ++number_of_failures;
286  } else {
287  out << "DU " << du << ", floor " << floor << " : Acoustic rate out of range -> " << z << " Hz." << endl;
288  }
289  }
290  } else if (!working) { // receiver expected to not work
291  out << "DU " << du << ", floor " << floor << " : Working again -> " << z << " Hz." << endl;
292  }
293  }
294  }
295  } else { FATAL("Object at " << objectName << " is not TH2." << endl); }
296 
297  out << (number_of_outliers > outliers ? RED : GREEN) << "Number of outliers = " << number_of_outliers << "/" << number_of_bins << endl;
298  out << RESET;
299 
300  if (number_of_outliers > outliers) {
301 
302  ++number_of_failures;
303  out << (number_of_outliers > outliers ? RED : GREEN) << "Test failed." << endl;
304  out << RESET;
305  } else {
306 
307  out << (outliers > number_of_outliers ? GREEN : RED) << "Test passed." << endl;
308  out << RESET;
309  }
310  }
311  break;
312 
313 
314  // data from emitter is not in input file
315  } else if (objectID + 1 == objectIDs.cend()) {
316 
317  // check if expected status emitter changed
318  if (i->second.working) {
319  ++number_of_failures;
320  out << (i->second.working != 0 ? RED : GREEN) << "Emitter stopped working." << endl;
321  out << RESET;
322  } else {
323  out << "Emitter is expected to not work." << endl;
324  }
325  }
326  }
327  }
328  // if number_of_failures > 0 program output needs to be reported
329  cout << number_of_failures << endl;
330  return 0;
331 }
Utility class to parse command line options.
Definition: JParser.hh:1500
int main(int argc, char *argv[])
Definition: Main.cc:15
o $QUALITY_ROOT d $DEBUG!JPlot1D f
Definition: JDataQuality.sh:66
Definition: JRoot.hh:19
*fatal Wrong number of arguments esac JCookie sh typeset Z DETECTOR typeset Z SOURCE_RUN typeset Z TARGET_RUN set_variable PARAMETERS_FILE $WORKDIR parameters
Definition: diff-Tuna.sh:38
Auxiliary class to handle file name, ROOT directory and object name.
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:446
string outputFile
is
Definition: JDAQCHSM.chsm:167
#define MAKE_STRING(A)
Make string.
Definition: JPrint.hh:142
static const JColorFacetMap_t color_facets
Color facets.
Definition: JColorFacet.hh:332
I/O formatting auxiliaries.
I/O coloring auxiliaries.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1961
std::istream & getline(std::istream &in, JString &object)
Read string from input stream until end of line.
Definition: JString.hh:478
int debug
debug level
Definition: JSirene.cc:63
Auxiliary methods to convert data members or return values of member methods of a set of objects to a...
Range of values.
Definition: JRange.hh:38
General purpose messaging.
#define FATAL(A)
Definition: JMessage.hh:67
z range($ZMAX-$ZMIN)< $MINIMAL_DZ." fi fi typeset -Z 4 STRING typeset -Z 2 FLOOR JPlot1D -f $
std::istream & operator>>(std::istream &in, JAANET::JHead &header)
Read header from input.
Definition: JHead.hh:1693
Auxiliary class to define a range between two values.
Utility class to parse command line options.
std::string to_string(const T &value)
Convert value to string.
std::ostream & operator<<(std::ostream &stream, const CLBCommonHeader &header)
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY source JAcoustics sh $DETECTOR_ID CHECK_EXIT_CODE typeset A TRIPODS get_tripods $WORKDIR tripod txt TRIPODS for EMITTER in
Definition: JCanberra.sh:42
const array_type< JKey_t > & get_keys(const std::map< JKey_t, JValue_t, JComparator_t, JAllocator_t > &data)
Method to create array of keys of map.
Definition: JVectorize.hh:139
void readDir(TDirectory *dir, std::vector< TString > &v)