Jpp  master_rocky-43-ge265d140c
the software that should make you happy
JPerth.cc
Go to the documentation of this file.
1 #include <string>
2 #include <iostream>
3 #include <iomanip>
4 #include <type_traits>
5 #include <functional>
6 #include <future>
7 #include <mutex>
8 #include <thread>
9 #include <vector>
10 #include <set>
11 #include <memory>
12 #include <algorithm>
13 
16 #include "JDAQ/JDAQEventIO.hh"
17 
18 #include "JDetector/JDetector.hh"
21 
22 #include "JDynamics/JDynamics.hh"
23 
24 #include "JSupport/JMeta.hh"
25 #include "JSupport/JSupport.hh"
29 
31 #include "JReconstruction/JEvt.hh"
34 
35 #include "JTrigger/JHitL0.hh"
36 #include "JTrigger/JBuildL0.hh"
37 
38 #include "JFit/JFitToolkit.hh"
39 #include "JFit/JLine1Z.hh"
40 #include "JFit/JLine3Z.hh"
41 #include "JFit/JModel.hh"
42 #include "JFit/JGandalf.hh"
43 #include "JFit/JRegressorHelper.hh"
44 #include "JFit/JLine3ZRegressor.hh"
45 #include "JFit/JGradient.hh"
46 
48 #include "JLang/JVectorize.hh"
49 
51 
52 #include "JMath/JMath.hh"
53 #include "JMath/JQuantile_t.hh"
54 
55 #include "JTools/JRange.hh"
56 
57 #include "Jeep/JProperties.hh"
58 #include "Jeep/JParser.hh"
59 #include "Jeep/JMessage.hh"
60 
61 
62 namespace JRECONSTRUCTION {
63 
65  using JFIT::JParameter_t;
66  using JFIT::JLine1Z;
67  using JFIT::JLine3Z;
69  using JTRIGGER::JHit;
70 
71  typedef std::vector<JHitW0> buffer_type; //!< hits
72  typedef std::map<int, buffer_type> map_type; //!< identifier -> hits
73 
74  /**
75  * Auxiliary data structure to store data and fit in memory.
76  */
77  struct event_type {
80  };
81 
84 
85 
86  /**
87  * Auxiliary class for editing time offset.
88  */
89  struct JEditor :
90  public JParameter_t
91  {
92  /**
93  * Constructor.
94  *
95  * \param data data
96  * \param id identifier
97  */
98  JEditor(data_type& data, const int id) :
99  data(data),
100  id(id),
101  t0(0.0)
102  {}
103 
104 
105  /**
106  * Apply step.
107  *
108  * \param step step
109  */
110  virtual void apply(const double step) override
111  {
112  for (data_type::iterator evt = data.begin(); evt != data.end(); ++evt) {
113 
114  map_type::iterator p = evt->data.find(id);
115 
116  if (p != evt->data.end()) {
117  for (buffer_type::iterator hit = p->second.begin(); hit != p->second.end(); ++hit) {
118  static_cast<JHit&>(*hit) = JHit(hit->getT1() + step, hit->getToT());
119  }
120  }
121  }
122 
123  this->t0 += step;
124  }
125 
126  data_type& data; //!< data
127  int id; //!< identifier
128  double t0; //!< time offset [ns]
129  };
130 
131 
134 
135 
136  /**
137  * Thread pool for fits to data.
138  */
139  struct JPerth {
140  /**
141  * Constructor.
142  *
143  * \param storage storage for PDFs
144  * \param data data
145  * \param ns number of threads
146  */
147  JPerth(const JRegressorStorage_t& storage,
148  const data_type& data,
149  const size_t ns) :
150  input(data),
151  stop(false)
152  {
153  using namespace std;
154  using namespace JPP;
155 
156  Q.reset();
157 
158  for (size_t i = 0; i < ns; ++i) {
159 
160  thread worker([this, storage]() {
161 
162  JRegressor_t regressor(storage);
163 
164  regressor.parameters.resize(5);
165 
166  regressor.parameters[0] = JLine3Z::pX();
167  regressor.parameters[1] = JLine3Z::pY();
168  regressor.parameters[2] = JLine3Z::pT();
169  regressor.parameters[3] = JLine3Z::pDX();
170  regressor.parameters[4] = JLine3Z::pDY();
171 
173  JLine3Z value;
174 
175  for ( ; ; ) {
176 
177  {
178  unique_lock<mutex> lock(in);
179 
180  cv.wait(lock, [this]() { return stop || this->input.hasNext(); });
181 
182  if (stop && !this->input.hasNext()) {
183  return;
184  }
185 
186  const event_type* evt = this->input.next();
187 
188  // re-organise data
189 
190  data.clear();
191 
192  for (map_type::const_iterator p = evt->data.begin(); p != evt->data.end(); ++p) {
193  copy(p->second.begin(), p->second.end(), back_inserter(data));
194  }
195 
196  value = evt->value;
197  }
198 
199  const double chi2 = regressor(value, data.begin(), data.end());
200 
201  {
202  unique_lock<mutex> lock(out);
203 
204  Q.put(chi2);
205  }
206  }
207  });
208 
209  workers.emplace_back(std::move(worker));
210  }
211  }
212 
213 
214  /**
215  * Destructor.
216  */
218  {
219  using namespace std;
220 
221  {
222  unique_lock<mutex> lock(in);
223 
224  stop = true;
225  }
226 
227  cv.notify_all();
228 
229  for (auto& worker : workers) {
230  worker.join();
231  }
232  }
233 
235 
236  private:
239  std::mutex in;
240  std::mutex out;
241  std::condition_variable cv;
242  bool stop;
243  };
244 
245  /**
246  */
248 
249 
250  /**
251  * Auxiliary data structure for chi2 function object.
252  */
253  struct JPerth_t {
254  /**
255  * Get chi2.
256  *
257  * \param option option
258  * \return chi2/NDF
259  */
260  double operator()(const int option) const
261  {
262  JPerth(storage, data, ns);
263 
264  return JPerth::Q.getMean();
265  }
266 
268  const data_type& data;
269  const size_t ns;
270  };
271 }
272 
273 
274 /**
275  * \file
276  *
277  * Program to determine inter-string time calibration.
278  *
279  * \author mdejong
280  */
281 int main(int argc, char **argv)
282 {
283  using namespace std;
284  using namespace JPP;
285  using namespace KM3NETDAQ;
286 
287  typedef JParallelFileScanner< JTypeList<JDAQEvent, JFIT::JEvt> > JParallelFileScanner_t;
288  typedef JParallelFileScanner_t::multi_pointer_type multi_pointer_type;
290  JACOUSTICS::JEvt>::typelist calibration_types;
291  typedef JMultipleFileScanner<calibration_types> JCalibration_t;
292 
293  JMultipleFileScanner<> inputFile;
294  JLimit_t& numberOfEvents = inputFile.getLimit();
295  string detectorFile;
296  JCalibration_t calibrationFile;
297  double Tmax_s;
298  string pdfFile;
299  JMuonGandalfParameters_t parameters;
300  bool overwriteDetector;
301  set<int> strings; // string identifiers
302  set<int> modules; // module identifiers
303  int number_of_iterations = 1000;
304  int number_of_extra_steps = 0;
305  double epsilon = 1.0e-4;
306  double T_ns = 2.5; // step size
307  size_t threads; // number of threads
308  int debug;
309 
310  const int DEFAULT_ID = -1;
311 
312  try {
313 
314  JProperties properties;
315 
316  properties.insert(gmake_property(number_of_iterations));
317  properties.insert(gmake_property(number_of_extra_steps));
318  properties.insert(gmake_property(epsilon));
319  properties.insert(gmake_property(T_ns));
320 
321  JParser<> zap("Program to determine inter-string time calibration.");
322 
323  zap['f'] = make_field(inputFile);
324  zap['a'] = make_field(detectorFile);
325  zap['+'] = make_field(calibrationFile) = JPARSER::initialised();
326  zap['T'] = make_field(Tmax_s) = 100.0;
327  zap['n'] = make_field(numberOfEvents) = JLimit::max();
328  zap['P'] = make_field(pdfFile);
329  zap['@'] = make_field(parameters) = JPARSER::initialised();
330  zap['A'] = make_field(overwriteDetector, "overwrite detector file provided through '-a' with fitted time offsets.");
331  zap['S'] = make_field(strings, "string identifiers (" << DEFAULT_ID << " => all)") = JPARSER::initialised();
332  zap['M'] = make_field(modules, "module identifiers (" << DEFAULT_ID << " => all)") = JPARSER::initialised();
333  zap['%'] = make_field(properties, "fit parameters") = JPARSER::initialised();
334  zap['N'] = make_field(threads, "number of threads") = 1;
335  zap['d'] = make_field(debug) = 1;
336 
337  zap(argc, argv);
338  }
339  catch(const exception& error) {
340  FATAL(error.what() << endl);
341  }
342 
343 
344  if (strings.empty() == modules.empty()) {
345  FATAL("Set either strings (option -S) or modules (option -M)." << endl);
346  }
347 
349 
350  try {
351  load(detectorFile, detector);
352  }
353  catch(const JException& error) {
354  FATAL(error);
355  }
356 
357  unique_ptr<JDynamics> dynamics;
358 
359  try {
360 
361  dynamics.reset(new JDynamics(detector, Tmax_s));
362 
363  dynamics->load(calibrationFile);
364  }
365  catch(const exception& error) {
366  if (!calibrationFile.empty()) {
367  FATAL(error.what());
368  }
369  }
370 
371  const JModuleRouter router(dynamics ? dynamics->getDetector() : detector);
372 
373  NOTICE("Reading PDFs... " << flush);
374 
375  const JRegressorStorage_t storage(pdfFile, parameters.TTS_ns);
376 
377  NOTICE("OK" << endl);
378 
380  JRegressor_t::T_ns.setRange(parameters.TMin_ns, parameters.TMax_ns);
381  JRegressor_t::Vmax_npe = parameters.VMax_npe;
382  JRegressor_t::MAXIMUM_ITERATIONS = parameters.NMax;
383 
384 
385  // preprocess input data
386 
387  const JBuildL0<JHitL0> buildL0;
388 
389  data_type data;
390 
391  counter_type skip = inputFile.getLowerLimit();
392  counter_type counter = inputFile.getLowerLimit();
393 
394  for (JMultipleFileScanner<>::const_iterator i = inputFile.begin(); i != inputFile.end(); ++i) {
395 
396  JSummaryFileRouter summary(*i, parameters.R_Hz);
397 
398  for (JParallelFileScanner_t in(*i); (skip -= in.skip(skip)) == 0 && in.hasNext() && counter != numberOfEvents; ++counter) {
399 
400  STATUS("event: " << setw(10) << counter << '\r'); DEBUG(endl);
401 
402  multi_pointer_type ps = in.next();
403 
404  const JDAQEvent* tev = ps;
405  const JFIT::JEvt* evt = ps;
406 
407  summary.update(*tev);
408 
409  if (dynamics) {
410  dynamics->update(*tev);
411  }
412 
413  if (!evt->empty()) {
414 
415  vector<JHitL0> dataL0;
416 
417  buildL0(*tev, router, true, back_inserter(dataL0));
418 
419  const JFIT::JFit& fit = (*evt)[0];
420 
421  const JRotation3D R (getDirection(fit));
422  const JLine1Z tz(getPosition (fit).rotate(R), fit.getT());
423  JRange<double> Z_m;
424 
425  if (fit.hasW(JSTART_LENGTH_METRES) &&
426  fit.getW(JSTART_LENGTH_METRES) > 0.0) {
427  Z_m = JZRange(parameters.ZMin_m, parameters.ZMax_m + fit.getW(JSTART_LENGTH_METRES));
428  }
429 
430  const JFIT::JModel<JLine1Z> match(tz, parameters.roadWidth_m, JRegressor_t::T_ns, Z_m);
431 
432  // hit selection based on start value
433 
434  buffer_type buffer;
435 
436  for (vector<JHitL0>::const_iterator i = dataL0.begin(); i != dataL0.end(); ++i) {
437 
438  JHitW0 hit(*i, summary.getRate(i->getPMTIdentifier()));
439 
440  hit.rotate(R);
441 
442  if (match(hit)) {
443  buffer.push_back(hit);
444  }
445  }
446 
447  // select first hit
448 
449  sort(buffer.begin(), buffer.end(), JHitL0::compare);
450 
451  buffer_type::const_iterator __end = unique(buffer.begin(), buffer.end(), equal_to<JDAQPMTIdentifier>());
452 
453  // re-organise data
454 
455  map_type map;
456 
457  for (buffer_type::const_iterator hit = buffer.begin(); hit != __end; ++hit) {
458 
459  const JModule& module = router.getModule(hit->getModuleID());
460 
461  if (!strings.empty()) { map[module.getString()].push_back(*hit); }
462  if (!modules.empty()) { map[module.getID()] .push_back(*hit); }
463  }
464 
465  data.push_back({map, tz});
466  }
467  }
468  }
469  STATUS(endl);
470 
471 
472  // fit
473 
474  JGradient fit(number_of_iterations, number_of_extra_steps, epsilon, 3);
475 
476  if (strings.count(DEFAULT_ID) != 0) { strings = getStringIDs(detector); }
477  if (modules.count(DEFAULT_ID) != 0) { modules = getModuleIDs(detector); }
478 
479  for (int id : strings) { fit.push_back(JModifier_t(MAKE_STRING("string: " << FILL(4,'0') << id << FILL()), new JEditor(data, id), T_ns)); }
480  for (int id : modules) { fit.push_back(JModifier_t(MAKE_STRING("module: " << setw(8) << id), new JEditor(data, id), T_ns)); }
481 
482  const JPerth_t perth = {storage, data, threads};
483 
484  const double chi2 = fit(perth);
485 
486  STATUS("result: " << FIXED(12,6) << chi2 << ' ' << setw(6) << fit.numberOfIterations << endl);
487 
488  for (size_t i = 0; i != fit.size(); ++i) {
489  {
490  const JEditor* p = dynamic_cast<const JEditor*>(fit[i].get());
491 
492  if (p != NULL) { STATUS(fit[i].name << ' ' << FIXED(9,3) << p->t0 << " [ns]" << endl); }
493  }
494  }
495 
496 
497  if (overwriteDetector) {
498 
499  detector.comment.add(JMeta(argc, argv));
500 
502 
503  for (size_t i = 0; i != fit.size(); ++i) {
504 
505  const JEditor* p = dynamic_cast<const JEditor*>(fit[i].get());
506 
507  if (p != NULL) {
508  calibration[p->id] = p->t0;
509  }
510  }
511 
512  const double t0 = getAverage(get_values(calibration), 0.0);
513 
514  for (JDetector::iterator module = detector.begin(); module != detector.end(); ++module) {
515 
516  if (!module->empty()) {
517 
518  map<int, double>::const_iterator p = (!strings.empty() ? calibration.find(module->getString()) :
519  !modules.empty() ? calibration.find(module->getID()) :
520  calibration.end());
521  if (p != calibration.end()) {
522  for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
523  module->getPMT(pmt).addT0(p->second - t0);
524  }
525  }
526  }
527  }
528 
529  NOTICE("Store calibration data on file " << detectorFile << endl);
530 
531  store(detectorFile, detector);
532  }
533 }
Data structure for detector geometry and calibration.
Dynamic detector calibration.
Auxiliary methods to evaluate Poisson probabilities and chi2.
Basic data structure for L0 hit.
Data regression method for JFIT::JLine3Z.
Base class for data structures with artithmetic capabilities.
General purpose messaging.
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
#define STATUS(A)
Definition: JMessage.hh:63
#define NOTICE(A)
Definition: JMessage.hh:64
#define FATAL(A)
Definition: JMessage.hh:67
int debug
debug level
Definition: JSirene.cc:69
ROOT I/O of application specific meta data.
Direct access to module in detector data structure.
Scanning of objects from multiple files according a format that follows from the extension of each fi...
Parallel scanning of objects from a single file or multiple files according a format that follows fro...
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:2142
int main(int argc, char **argv)
Definition: JPerth.cc:281
#define MAKE_STRING(A)
Make string.
Definition: JPrint.hh:63
Utility class to parse parameter values.
#define gmake_property(A)
macros to convert (template) parameter to JPropertiesElement object
Auxiliary class to define a range between two values.
ROOT TTree parameter settings of various packages.
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
int getString() const
Get string number.
Definition: JLocation.hh:135
Router for direct addressing of module data in detector data structure.
const JModule & getModule(const JObjectID &id) const
Get module parameters.
Data structure for a composite optical module.
Definition: JModule.hh:75
Utility class to parse parameter values.
Definition: JProperties.hh:501
Data structure for set of track fit results.
Data structure for track fit results with history and optional associated values.
const std::vector< double > & getW() const
Get associated values.
double getT() const
Get time.
bool hasW(const int i) const
Check availability of value.
Data structure for fit of straight line paralel to z-axis.
Definition: JLine1Z.hh:29
static parameter_type pY()
Definition: JLine1Z.hh:181
static parameter_type pX()
Definition: JLine1Z.hh:180
static parameter_type pT()
Definition: JLine1Z.hh:182
Data structure for fit of straight line in positive z-direction.
Definition: JLine3Z.hh:40
static parameter_type pDY()
Definition: JLine3Z.hh:320
static parameter_type pDX()
Definition: JLine3Z.hh:319
JAxis3D & rotate(const JRotation3D &R)
Rotate axis.
Definition: JAxis3D.hh:225
Rotation matrix.
Definition: JRotation3D.hh:114
General exception.
Definition: JException.hh:24
int getID() const
Get identifier.
Definition: JObjectID.hh:50
virtual const pointer_type & next()=0
Get next element.
virtual bool hasNext()=0
Check availability of next element.
Utility class to parse command line options.
Definition: JParser.hh:1698
Auxiliary class for a hit with background rate value.
Definition: JHitW0.hh:23
General purpose class for object reading from a list of file names.
General purpose class for parallel reading of objects from a single file or multiple files.
File router for fast addressing of summary data.
void update(const JDAQHeader &header)
Update router.
double getRate() const
Get default rate.
Template specialisation of L0 builder for JHitL0 data type.
Definition: JBuildL0.hh:105
Hit data structure.
const char * map
Definition: elog.cc:87
static const int JSTART_LENGTH_METRES
distance between first and last hits in metres from JStart.cc
const double epsilon
Definition: JQuadrature.cc:21
void copy(const Head &from, JHead &to)
Copy header from from to to.
Definition: JHead.cc:162
std::set< int > getStringIDs(const JDetector &detector)
Get list of strings identifiers.
std::set< int > getModuleIDs(const JDetector &detector, const bool option=false)
Get list of modules identifiers.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
JTOOLS::JRange< double > JZRange
Definition: JFit/JModel.hh:21
const array_type< JValue_t > & get_values(const std::map< JKey_t, JValue_t, JComparator_t, JAllocator_t > &data)
Method to create array of values of map.
Definition: JVectorize.hh:152
std::iterator_traits< T >::value_type getAverage(T __begin, T __end)
Get average.
Definition: JMath.hh:494
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Model fits to data.
std::vector< JHitW0 > buffer_type
hits
Definition: JPerth.cc:71
JPosition3D getPosition(const JFit &fit)
Get position.
JLANG::JSTDObjectReader< const event_type > input_type
Definition: JPerth.cc:83
std::vector< event_type > data_type
Definition: JPerth.cc:82
JDirection3D getDirection(const JFit &fit)
Get direction.
JFIT::JRegressor< JFIT::JLine3Z, JFIT::JGandalf > JRegressor_t
Definition: JPerth.cc:133
JFIT::JRegressorStorage< JFIT::JLine3Z, JFIT::JGandalf > JRegressorStorage_t
Definition: JPerth.cc:132
std::map< int, buffer_type > map_type
identifier -> hits
Definition: JPerth.cc:72
Long64_t counter_type
Type definition for counter.
std::vector< size_t > ns
KM3NeT DAQ data structures and auxiliaries.
Definition: DataQueue.cc:39
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
Definition: JDAQ.hh:26
Definition: JSTDTypes.hh:14
Auxiliary data structure for sequence of same character.
Definition: JManip.hh:330
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:448
Calibration.
Definition: JHead.hh:330
Detector file.
Definition: JHead.hh:227
Acoustic event fit.
Data structure for measured coincidence rates of all pairs of PMTs in optical module.
Definition: JFitK40.hh:103
Orientation of module.
Dynamic detector calibration.
Definition: JDynamics.hh:84
Conjugate gradient fit.
Definition: JGradient.hh:75
size_t numberOfIterations
Definition: JGradient.hh:273
Template specialisation of class JModel to match hit with muon trajectory along z-axis.
Definition: JFit/JModel.hh:36
Auxiliary data structure for editable parameter.
Definition: JGradient.hh:49
Auxiliary data structure for fit parameter.
Definition: JGradient.hh:28
Template data structure for storage for PDF tables.
Template definition of a data regressor of given model.
Definition: JRegressor.hh:70
Auxiliary class for recursive type list generation.
Definition: JTypeList.hh:351
Auxiliary data structure for average.
Definition: JQuantile_t.hh:25
void put(const double x)
Put value.
Definition: JQuantile_t.hh:49
void reset()
Reset.
Definition: JQuantile_t.hh:38
double getMean() const
Get mean value.
Definition: JQuantile_t.hh:60
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition: JParser.hh:68
Auxiliary class for editing time offset.
Definition: JPerth.cc:91
data_type & data
data
Definition: JPerth.cc:126
double t0
time offset [ns]
Definition: JPerth.cc:128
JEditor(data_type &data, const int id)
Constructor.
Definition: JPerth.cc:98
int id
identifier
Definition: JPerth.cc:127
virtual void apply(const double step) override
Apply step.
Definition: JPerth.cc:110
double TMin_ns
minimal time w.r.t. Cherenkov hypothesis [ns]
double TMax_ns
maximal time w.r.t. Cherenkov hypothesis [ns]
double VMax_npe
maximum number of of photo-electrons
Auxiliary data structure for chi2 function object.
Definition: JPerth.cc:253
const JRegressorStorage_t & storage
Definition: JPerth.cc:267
double operator()(const int option) const
Get chi2.
Definition: JPerth.cc:260
const data_type & data
Definition: JPerth.cc:268
Thread pool for fits to data.
Definition: JPerth.cc:139
JPerth(const JRegressorStorage_t &storage, const data_type &data, const size_t ns)
Constructor.
Definition: JPerth.cc:147
std::vector< std::thread > workers
Definition: JPerth.cc:237
std::condition_variable cv
Definition: JPerth.cc:241
static JMATH::JQuantile_t Q
Definition: JPerth.cc:234
~JPerth()
Destructor.
Definition: JPerth.cc:217
Auxiliary data structure to store data and fit in memory.
Definition: JPerth.cc:77
Auxiliary class for defining the range of iterations of objects.
Definition: JLimit.hh:45
Auxiliary class for ROOT I/O of application specific meta data.
Definition: JMeta.hh:72
Auxiliary data structure for sorting of hits.
Definition: JHitL0.hh:85