Jpp master_rocky-44-g75b7c4f75
the software that should make you happy
Loading...
Searching...
No Matches
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
21
23
24#include "JSupport/JMeta.hh"
25#include "JSupport/JSupport.hh"
29
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"
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
62namespace JRECONSTRUCTION {
63
66 using JFIT::JLine1Z;
67 using JFIT::JLine3Z;
69 using JTRIGGER::JHit;
70
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 */
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
133 typedef JFIT::JRegressor <JFIT::JLine3Z, JFIT::JGandalf> JRegressor_t;
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 */
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
172 buffer_type data;
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 {
263
264 return JPerth::Q.getMean();
265 }
266
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 */
281int 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
379 JRegressor_t::debug = debug;
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.
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
General exception.
Definition JException.hh:24
int getID() const
Get identifier.
Definition JObjectID.hh:50
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.
Range of values.
Definition JRange.hh:42
Template L0 hit builder.
Definition JBuildL0.hh:38
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
JDirection3D getDirection(const Vec &dir)
Get direction.
void copy(const Head &from, JHead &to)
Copy header from from to to.
Definition JHead.cc:162
JPosition3D getPosition(const Vec &pos)
Get position.
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.
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.
JTOOLS::JRange< double > JZRange
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.
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
JLANG::JSTDObjectReader< const event_type > input_type
Definition JPerth.cc:83
std::vector< event_type > data_type
Definition JPerth.cc:82
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
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
Auxiliary class to match data points with given model.
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
virtual const pointer_type & next() override
Get next element.
virtual bool hasNext() override
Check availability of next element.
Implementation of object iteration from STD container.
Auxiliary class for recursive type list generation.
Definition JTypeList.hh:351
Auxiliary data structure for average.
void put(const double x)
Put value.
void reset()
Reset.
double getMean() const
Get mean value.
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
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
static counter_type max()
Get maximum counter value.
Definition JLimit.hh:128
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