Jpp  17.2.1-pre0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JAcousticsEventBuilder.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <iomanip>
3 #include <vector>
4 #include <map>
5 #include <algorithm>
6 
7 #include "TROOT.h"
8 #include "TFile.h"
9 
11 
12 #include "JLang/JComparator.hh"
13 
14 #include "JDB/JToAshort.hh"
15 #include "JDB/JSupport.hh"
16 
17 #include "JDetector/JDetector.hh"
20 #include "JDetector/JTripod.hh"
22 #include "JDetector/JHydrophone.hh"
23 
24 #include "JLang/JPredicate.hh"
25 #include "JLang/JComparator.hh"
26 #include "JTools/JRange.hh"
27 #include "JTools/JQuantile.hh"
28 #include "JTools/JHashMap.hh"
31 #include "JSupport/JMeta.hh"
32 
33 #include "JAcoustics/JEmitterID.hh"
39 #include "JAcoustics/JEvent.hh"
42 #include "JAcoustics/JSupport.hh"
43 
44 #include "Jeep/JContainer.hh"
45 #include "Jeep/JPrint.hh"
46 #include "Jeep/JParser.hh"
47 #include "Jeep/JMessage.hh"
48 
49 
50 /**
51  * \file
52  *
53  * Main program to trigger events in acoustic data.
54  *
55  * An acoustic event is based on a coincidence of estimated times of emission from the same emitter.\n
56  * If the number of coincident times of emission exceeds a preset minimum,
57  * the event is triggered and subsequently stored in the output file.\n
58  * Note that an event counter is added which can be used to disambiguate
59  * the different cycles from the same emitter within one so-called "super" event that is used for the global fit.\n
60  * In this, a super event refers to the coincidence of events from a variety of emitters.
61  * \author mdejong
62  */
63 int main(int argc, char **argv)
64 {
65  using namespace std;
66  using namespace JPP;
67 
69 
70  typedef JContainer< vector<JTripod> > tripods_container;
71  typedef JContainer< vector<JTransmitter> > transmitters_container;
72  typedef JContainer< vector<JHydrophone> > hydrophones_container;
73 
75  JLimit_t& numberOfEvents = inputFile.getLimit();
78  JSoundVelocity V = getSoundVelocity; // default sound velocity
79  string detectorFile;
80  tripods_container tripods; // tripods
81  transmitters_container transmitters; // transmitters
82  hydrophones_container hydrophones; // hydrophones
83  double precision;
84  int debug;
85 
86  try {
87 
88  JParser<> zap("Main program to trigger events in acoustic data.");
89 
90  zap['f'] = make_field(inputFile, "output of JConvertDB -q toashort");
91  zap['n'] = make_field(numberOfEvents) = JLimit::max();
92  zap['@'] = make_field(parameters, "trigger parameters");
93  zap['o'] = make_field(outputFile, "output file") = "event.root";
94  zap['V'] = make_field(V, "sound velocity") = JPARSER::initialised();
95  zap['a'] = make_field(detectorFile, "detector file");
96  zap['T'] = make_field(tripods, "tripod data");
97  zap['Y'] = make_field(transmitters, "transmitter data") = JPARSER::initialised();
98  zap['H'] = make_field(hydrophones, "hydrophone data") = JPARSER::initialised();
99  zap['W'] = make_field(getEmitterID, "waveform identification data") = JPARSER::initialised();
100  zap['p'] = make_field(precision, "precision time-of-arrival") = 1.0e-6;
101  zap['d'] = make_field(debug) = 1;
102 
103  zap(argc, argv);
104  }
105  catch(const exception &error) {
106  FATAL(error.what() << endl);
107  }
108 
109 
111 
112  try {
113  load(detectorFile, detector);
114  }
115  catch(const JException& error) {
116  FATAL(error);
117  }
118 
119  V.set(detector.getUTMZ());
120 
121  JHashMap<int, JReceiver> receivers;
122  JHashMap<int, JEmitter> emitters;
123 
124  for (JDetector::const_iterator i = detector.begin(); i != detector.end(); ++i) {
125 
126  if ((i->getFloor() == 0 && !i->has(HYDROPHONE_DISABLE)) ||
127  (i->getFloor() != 0 && !i->has(PIEZO_DISABLE))) {
128 
129  JPosition3D pos(0.0, 0.0, 0.0);
130 
131  if (i->getFloor() == 0) { // get relative position of hydrophone
132 
133  try {
134  pos = getPosition(hydrophones.begin(),
135  hydrophones.end(),
136  make_predicate(&JHydrophone::getString, i->getString()));
137  }
138  catch(const exception&) {
139  continue; // if no position available, discard hydrophone
140  }
141  }
142 
143  receivers[i->getID()] = JReceiver(i->getID(),
144  i->getPosition() + pos,
145  i->getT0() * 1.0e-9);
146  }
147  }
148 
149  for (tripods_container::const_iterator i = tripods.begin(); i != tripods.end(); ++i) {
150  emitters[i->getID()] = JEmitter(i->getID(),
151  i->getUTMPosition() - detector.getUTMPosition());
152  }
153 
154  for (transmitters_container::const_iterator i = transmitters.begin(); i != transmitters.end(); ++i) {
155  try {
156  emitters[i->getID()] = JEmitter(i->getID(),
157  i->getPosition() + detector.getModule(i->getLocation()).getPosition());
158  }
159  catch(const exception&) {
160  continue; // if no string available, discard transmitter
161  }
162  }
163 
164 
165  outputFile.open();
166 
167  if (!outputFile.is_open()) {
168  FATAL("Error opening file " << outputFile << endl);
169  }
170 
171  outputFile.put(JMeta(argc, argv));
172  outputFile.put(parameters);
173 
174  // statistics
175 
176  struct map_type :
177  public map<int, JQuantile>
178  {
179  long long int sum() const
180  {
181  long long int count = 0;
182 
183  for (const_iterator i = this->begin(); i != this->end(); ++i) {
184  count += i->second.getCount();
185  }
186 
187  return count;
188  }
189  };
190 
191  map_type number_of_entries;
192  map_type number_of_aliens;
193  map_type number_of_triggers;
194  map_type number_of_events;
195  map_type number_of_outliers;
196 
197  // input data
198 
199  string oid; // detector identifier
200 
201  typedef vector<JTransmission> buffer_type; // data type
202 
203  map<int, map< int, buffer_type > > f1; // emitter -> receiver -> data
204 
205  while (inputFile.hasNext()) {
206 
207  if (inputFile.getCounter()%1000 == 0) {
208  STATUS("counter: " << setw(8) << inputFile.getCounter() << '\r' << flush); DEBUG(endl);
209  }
210 
211  JToAshort* parameters = inputFile.next();
212 
213  if (oid == "") {
214  oid = parameters->DETID;
215  }
216 
217  if (oid != parameters->DETID) { // consistency check
218  FATAL("Invalid detector identifier " << parameters->DETID << " != " << oid << endl);
219  }
220 
221  try {
222 
223  const int id = getEmitterID(parameters->EMITTERID);
224 
225  number_of_entries[parameters->EMITTERID].put(1);
226 
227  if (emitters.has(id) && receivers.has(parameters->DOMID)) {
228 
229  const JTransceiver transceiver(emitters[id], receivers[parameters->DOMID]);
230 
231  f1[transceiver.emitter.getID()][transceiver.receiver.getID()].push_back(transceiver.getTransmission(*parameters, V));
232  }
233  }
234  catch(const exception&) {
235  number_of_aliens[parameters->EMITTERID].put(1);
236  }
237  }
238  STATUS(endl);
239 
240  for (map_type::const_iterator i = number_of_entries.begin(); i != number_of_entries.end(); ++i) {
241  STATUS("number of entries: " << setw(3) << i->first << ' ' << setw(8) << i->second.getCount() << endl);
242  }
243 
244  for (map_type::const_iterator i = number_of_aliens.begin(); i != number_of_aliens.end(); ++i) {
245  STATUS("number of aliens: " << setw(3) << i->first << ' ' << setw(8) << i->second.getCount() << endl);
246  }
247 
248 
249  // filter similar hits
250 
251  for (map<int, map< int, buffer_type> >::iterator i = f1.begin(); i != f1.end(); ++i) {
252 
253  for (map< int, buffer_type>::iterator receiver = i->second.begin(); receiver != i->second.end(); ++receiver) {
254 
255  buffer_type& buffer = receiver->second;
256 
257  sort(buffer.begin(), buffer.end(), JTransmission::compare(precision));
258 
259  buffer.erase(unique(buffer.begin(), buffer.end(), JTransmission::equals(precision)), buffer.end());
260  }
261  }
262 
263 
264  // output events
265 
266  for (map<int, map< int, buffer_type> >::iterator i = f1.begin(); i != f1.end(); ++i) {
267 
268  buffer_type buffer;
269 
270  for (map< int, buffer_type>::iterator receiver = i->second.begin(); receiver != i->second.end(); ++receiver) {
271 
272  // selection based on quality
273 
274  buffer_type& f2 = receiver->second;
275  double Qmin = parameters.Q;
276 
277  if (parameters.Q > 0.0 && // use quantile to evaluate corresponding quality
278  parameters.Q < 1.0) { //
279 
280  const JQuantile Q1("quality", make_array(f2.begin(), f2.end(), &JTransmission::getQ), true);
281 
282  Qmin = Q1.getQuantile(parameters.Q);
283  }
284 
285  buffer_type::iterator __end = partition(f2.begin(), f2.end(), make_predicate(&JTransmission::getQ, Qmin, JComparison::gt()));
286 
287  copy(f2.begin(), __end, back_inserter(buffer));
288  }
289 
290 
291  sort(buffer.begin(), buffer.end()); // sort according time-of-emisson
292 
293  JQuantile Q;
294 
295  JTriggerOutput data;
296 
297  for (buffer_type::const_iterator p = buffer.begin(); p != buffer.end(); ++p) {
298 
299  buffer_type::const_iterator q = p;
300 
301  // basic correlator
302 
303  while (++q != buffer.end() && q->getToE() - p->getToE() <= parameters.TMax_s) {}
304 
305  Q.put(distance(p,q));
306 
307  if (distance(p,q) >= parameters.numberOfHits) {
308 
309  STATUS("trigger: " << setw(8) << number_of_triggers.sum() << '\r' << flush); DEBUG(endl);
310 
311  JEvent event(oid, number_of_triggers.sum(), i->first, p, q);
312 
313  number_of_triggers[i->first].put(event.size());
314 
315  DEBUG("trigger: " << endl << event);
316 
317  data.push_back(event);
318  }
319  }
320 
321  STATUS("number of toes: " << setw(3) << i->first << ' ' << setw(8) << buffer.size());
322  if (Q.getCount() > 0) {
323  STATUS(' ' << FIXED(6,1) << Q.getMean() <<
324  ' ' << FIXED(6,1) << Q.getXmin() <<
325  ' ' << FIXED(6,1) << Q.getXmax());
326  }
327  STATUS(endl);
328 
329  data.merge(JEventOverlap(parameters.TMax_s));
330 
331  for (JTriggerOutput::const_iterator event = data.begin(); event != data.end(); ++event) {
332 
333  number_of_events[event->getID()].put(event->size());
334 
335  if (parameters.quantile < 1.0) {
336 
337  const int M = (int) (event->size() * 0.5 * (1.0 - parameters.quantile));
338 
339  JEvent::const_iterator p = event-> begin(); advance(p, M);
340  JEvent::const_reverse_iterator q = event->rbegin(); advance(q, M);
341 
342  const double Tmin = p->getToE();
343  const double Tmax = q->getToE();
344 
345  const double W = (1.0 - parameters.quantile) / parameters.quantile;
346 
347  while (p != event-> begin() && (p - 1)->getToE() >= Tmin - 0.5 * (Tmax - Tmin) * W) { --p; }
348  while (q != event->rbegin() && (q - 1)->getToE() <= Tmax + 0.5 * (Tmax - Tmin) * W) { --q; }
349 
350  number_of_outliers[event->getID()].put(event->size() - distance(p, q.base()));
351 
352  outputFile.put(JEvent(event->getOID(),
353  event->getCounter(),
354  event->getID(),
355  p, q.base()));
356 
357  } else {
358 
359  number_of_outliers[event->getID()].put(0);
360 
361  outputFile.put(*event);
362  }
363  }
364  }
365  STATUS(endl);
366 
367  for (map_type::const_iterator i = number_of_triggers.begin(); i != number_of_triggers.end(); ++i) {
368  STATUS("number of triggers: " << setw(3) << i->first << ' ' << setw(8) << i->second.getCount() << endl);
369  }
370 
371  for (map_type::const_iterator i = number_of_events.begin(); i != number_of_events.end(); ++i) {
372  STATUS("number of events: " << setw(3) << i->first << ' ' << setw(8) << i->second.getCount() << ' ' << FIXED(7,3) << i->second.getMean() << ' ' << FIXED(7,3) << number_of_outliers[i->first].getMean() << endl);
373  }
374 
375  JMultipleFileScanner<JMeta> io(inputFile);
376 
377  io >> outputFile;
378 
379  outputFile.close();
380 }
Auxiliary class for ROOT I/O of application specific meta data.
Definition: JMeta.hh:70
Object writing to file.
Utility class to parse command line options.
Definition: JParser.hh:1517
General exception.
Definition: JException.hh:23
Acoustic receiver.
Definition: JReceiver.hh:27
Q(UTCMax_s-UTCMin_s)-livetime_s
JPredicate< JResult_t T::*, JComparison::eq > make_predicate(JResult_t T::*member, const JResult_t value)
Helper method to create predicate for data member.
Definition: JPredicate.hh:128
int main(int argc, char *argv[])
Definition: Main.cc:15
Greater than.
Definition: JComparison.hh:73
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
General purpose class for hash map of unique keys.
Definition: JHashMap.hh:72
Auxiliary data structure for running average, standard deviation and quantiles.
Definition: JQuantile.hh:43
General purpose class for hash map of unique elements.
#define STATUS(A)
Definition: JMessage.hh:63
ROOT TTree parameter settings.
Detector data structure.
Definition: JDetector.hh:89
Recording of objects on file according a format that follows from the file name extension.
std::string DETID
constraint
Definition: JToAshort.hh:22
*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
Acoustic event.
then fatal Number of tripods
Definition: JFootprint.sh:45
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition: JParser.hh:83
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:446
V(JDAQEvent-JTriggerReprocessor)*1.0/(JDAQEvent+1.0e-10)
string outputFile
Data structure for detector geometry and calibration.
Data structure for hydrophone.
then fatal Not enough arguments fi set_variable INDEX_STRING_START while[[${${argv[${START_INDEX_STRING}]}##*.}!="root"]]
Type list.
Definition: JTypeList.hh:22
JFIT::JEvent JEvent
Definition: JHistory.hh:353
const JPolynome f1(1.0, 2.0, 3.0)
Function.
Auxiliary class for defining the range of iterations of objects.
Definition: JLimit.hh:41
static const JSoundVelocity getSoundVelocity(1541.0,-17.0e-3,-2000.0)
Function object for velocity of sound.
I/O formatting auxiliaries.
Detector file.
Definition: JHead.hh:226
Acoustics support kit.
Detector support kit.
Data structure for transmitter.
Acoustic emitter.
Definition: JEmitter.hh:27
void merge(const JMatch_t &match)
Merge events.
Acoustics toolkit.
Auxiliary wrapper for I/O of container with optional comment (see JComment).
Definition: JContainer.hh:39
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1993
const array_type< JValue_t > & make_array(const JValue_t(&array)[N])
Method to create array of values.
Definition: JVectorize.hh:54
int getID() const
Get identifier.
Definition: JObjectID.hh:50
ROOT I/O of application specific meta data.
JPosition3D getPosition(const Vec &pos)
Get position.
double getQuantile(const double Q, const Quantile_t option=forward_t) const
Get quantile.
Definition: JQuantile.hh:319
static struct JACOUSTICS::@4 compare
Auxiliary data structure to sort transmissions.
JTransmission getTransmission(const JToAshort &data, const JAbstractSoundVelocity &V) const
Get transmission.
Definition: JTransceiver.hh:62
Acoustic transceiver.
Definition: JTransceiver.hh:29
Emitter identification.
ROOT TTree parameter settings.
double getQ(const double D_m, const double f_kHz, const double d_m)
Get relative quality for given frequency at given distance.
General purpose messaging.
counter_type advance(counter_type &counter, const counter_type value, const counter_type limit=std::numeric_limits< counter_type >::max())
Advance counter.
Implementation for depth dependend velocity of sound.
#define FATAL(A)
Definition: JMessage.hh:67
Scanning of objects from multiple files according a format that follows from the extension of each fi...
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
Acoustic trigger parameters.
std::vector< int > count
Definition: JAlgorithm.hh:180
Auxiliary class to define a range between two values.
General purpose class for object reading from a list of file names.
Utility class to parse command line options.
Acoustic transceiver.
static const int PIEZO_DISABLE
Enable (disable) use of piezo if this status bit is 0 (1);.
Acoustic transmission.
void copy(const Head &from, JHead &to)
Copy header from from to to.
Definition: JHead.cc:161
Acoustic event.
static const int HYDROPHONE_DISABLE
Enable (disable) use of hydrophone if this status bit is 0 (1);.
Data structure for position in three dimensions.
Definition: JPosition3D.hh:36
const JLimit & getLimit() const
Get limit.
Definition: JLimit.hh:73
bool equals(const JFirst_t &first, const JSecond_t &second, const double precision=std::numeric_limits< double >::min())
Check equality.
Definition: JMathToolkit.hh:86
static JEmitterID getEmitterID
Function object for emitter identification.
Definition: JEmitterID.hh:119
do set_variable DETECTOR_TXT $WORKDIR detector
Data structure for tripod.
Match of two events considering overlap in time.
int EMITTERID
waveform identifier
Definition: JToAshort.hh:27
Container I/O.
int debug
debug level
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62