Jpp  master_rocky
the software that should make you happy
Functions
JTurbot.cc File Reference

Example program to search for correlations between triggered events and time slice data. More...

#include <string>
#include <iostream>
#include <iomanip>
#include <limits>
#include <map>
#include <vector>
#include "TROOT.h"
#include "TFile.h"
#include "TH1D.h"
#include "TF1.h"
#include "TMath.h"
#include "JROOT/JMinimizer.hh"
#include "km3net-dataformat/online/JDAQ.hh"
#include "km3net-dataformat/definitions/pmt_status.hh"
#include "km3net-dataformat/definitions/module_status.hh"
#include "JDAQ/JDAQEventIO.hh"
#include "JDAQ/JDAQTimesliceIO.hh"
#include "JDAQ/JDAQEvaluator.hh"
#include "JDetector/JDetector.hh"
#include "JDetector/JDetectorToolkit.hh"
#include "JDetector/JDAQHitRouter.hh"
#include "JTrigger/JBuildL0.hh"
#include "JTrigger/JBuildL1.hh"
#include "JLang/JSinglePointer.hh"
#include "JROOT/JManager.hh"
#include "JTools/JWeight.hh"
#include "JROOT/JROOTClassSelector.hh"
#include "JSupport/JSingleFileScanner.hh"
#include "JSupport/JTreeScannerInterface.hh"
#include "JSupport/JTreeScanner.hh"
#include "JSupport/JAutoTreeScanner.hh"
#include "JSupport/JSupport.hh"
#include "JSupport/JMeta.hh"
#include "Jeep/JPrint.hh"
#include "Jeep/JParser.hh"
#include "Jeep/JMessage.hh"

Go to the source code of this file.

Functions

int main (int argc, char **argv)
 

Detailed Description

Example program to search for correlations between triggered events and time slice data.


This application can be used to identify optical modules that are out-of-sync with respect to the central White Rabbit clock.
To this end, time correlations are searched for between triggered events and local coincidences, referred to as L1 hits. The local coincidences are independently obtained from time slice data and can thereby cross the time slice border of a triggered event.
The MODULE_OUT_OF_SYNC of status the modules that are found to be out-of-sync are set.

The number of time slices to look for L1 hits away from the triggered event can be set via command line option -N <number of time slices>.
The larger this value, the bigger time offsets can be covered. To identify the modules that are out-of-sync as fast as possible (without determining the time offset), this value can be set to 0 with the caveat that a out-of-sync occurring during the data taking run may then be missed.

Author
mdejong

Definition in file JTurbot.cc.

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 88 of file JTurbot.cc.

89 {
90  using namespace std;
91  using namespace JPP;
92  using namespace KM3NETDAQ;
93 
94  JSingleFileScanner<> inputFile;
95  JLimit_t& numberOfEvents = inputFile.getLimit();
96  string outputFile;
97  string detectorFile;
98  bool overwriteDetector;
99  double TMaxLocal_ns;
100  int numberOfTimeslices;
101  double binWidth_ns;
102  double deadTime_us;
103  double Pmin;
104  JROOTClassSelector selector;
105  int qaqc;
106  int debug;
107 
108  try {
109 
110  JParser<> zap("Example program to search for correlations between triggered events and timeslice data.");
111 
112  zap['f'] = make_field(inputFile, "input file.");
113  zap['o'] = make_field(outputFile, "optional output file containing ROOT histograms.") = "";
114  zap['a'] = make_field(detectorFile, "detector file.");
115  zap['A'] = make_field(overwriteDetector, "overwrite detector file provided through '-a' with module (PMT) status.");
116  zap['n'] = make_field(numberOfEvents) = JLimit::max();
117  zap['T'] = make_field(TMaxLocal_ns, "time window for local coincidences (L1),") = 20.0;
118  zap['N'] = make_field(numberOfTimeslices, "time slice difference between triggered event and L1.") = 100;
119  zap['W'] = make_field(binWidth_ns, "bin width for output histograms." ) = 10e3;
120  zap['D'] = make_field(deadTime_us, "L1 dead time (us)") = 200.0;
121  zap['p'] = make_field(Pmin, "minimal probability for background to be signal.") = 1.0e-7;
122  zap['C'] = make_field(selector, "data type selection (default is all).") = "", getROOTClassSelection<JDAQTimesliceTypes_t>();
123  zap['Q'] = make_field(qaqc) = 0;
124  zap['d'] = make_field(debug) = 2;
125 
126  zap(argc, argv);
127  }
128  catch(const exception& error) {
129  FATAL(error.what() << endl);
130  }
131 
132 
134 
135  try {
136  load(detectorFile, detector);
137  }
138  catch(const JException& error) {
139  FATAL(error);
140  }
141 
142  if (detector.empty()) {
143  FATAL("Empty detector " << detectorFile << endl);
144  }
145 
146  const JDAQHitRouter router(detector);
147 
148  const double TMax_ns = max(binWidth_ns, getMaximalTime(detector)); // signal time window
149  const double BOOST = 20.0; // scaling of time window for background
150  const double deadTime_ns = deadTime_us * 1e3;
151 
152  NOTICE("Time window " << FIXED(7,1) << TMax_ns << " [ns]" << endl);
153 
154  typedef double hit_type;
155 
156  JBuildL0<hit_type> buildL0;
157  JBuildL1<hit_type> buildL1(JBuildL1Parameters(TMaxLocal_ns, true));
159 
160  typedef JManager<int, TH1D> JManager_t;
161 
162  const Double_t xmin = -(numberOfTimeslices + 1) * getFrameTime() - 0.5*binWidth_ns;
163  const Double_t xmax = +(numberOfTimeslices + 1) * getFrameTime() + 0.5*binWidth_ns;
164  const Int_t nx = (Int_t) ((xmax - xmin) / binWidth_ns);
165 
166  JManager_t manager(new TH1D("M_%", NULL, nx, xmin, xmax));
167 
169 
171 
173 
174  if (selector == "") {
175 
176  if ((ps = new JTreeScanner< JAssertConversion<JDAQTimesliceSN, JDAQTimeslice> >(inputFile))->getEntries() != 0 ||
177  (ps = new JTreeScanner< JAssertConversion<JDAQTimesliceL2, JDAQTimeslice> >(inputFile))->getEntries() != 0 ||
178  (ps = new JTreeScanner< JAssertConversion<JDAQTimesliceL1, JDAQTimeslice> >(inputFile))->getEntries() != 0 ||
179  (ps = new JTreeScanner< JAssertConversion<JDAQTimesliceL0, JDAQTimeslice> >(inputFile))->getEntries() != 0 ||
180  (ps = new JTreeScanner< JAssertConversion<JDAQTimeslice, JDAQTimeslice> >(inputFile))->getEntries() != 0) {
181  } else {
182  FATAL("No timeslice data." << endl);
183  }
184 
185  NOTICE("Selected class " << ps->getClassName() << endl);
186 
187  } else {
188 
189  ps = zmap[selector];
190 
191  ps->configure(inputFile);
192  }
193 
194  ps->setLimit(inputFile.getLimit());
195 
196  typedef map<int, vector<double> > map_type; // frame index -> event times
197 
198  map_type buffer;
199 
200  for (JTreeScanner<JDAQEvent> in(inputFile.getFilename()); in.hasNext(); ) {
201 
202  if (in.getCounter()%1000 == 0) {
203  STATUS("event: " << setw(10) << in.getCounter() << '\r'); DEBUG(endl);
204  }
205 
206  JDAQEvent* event = in.next();
207 
208  // Average time of triggered hits
209 
210  double t0 = 0.0;
211 
212  for (JDAQEvent::const_iterator<JDAQTriggeredHit> hit = event->begin<JDAQTriggeredHit>(); hit != event->end<JDAQTriggeredHit>(); ++hit) {
213  t0 += getTime(*hit, router.getPMT(*hit));
214  }
215 
216  t0 /= event->size<JDAQTriggeredHit>();
217  t0 += event->getFrameIndex() * getFrameTime();
218 
219  buffer[event->getFrameIndex()].push_back(t0);
220  }
221  STATUS(endl);
222 
223 
224  while (ps->hasNext()) {
225 
226  if (ps->getCounter()%1000 == 0) {
227  STATUS("event: " << setw(10) << ps->getCounter() << '\r'); DEBUG(endl);
228  }
229 
230  JDAQTimeslice* timeslice = ps->next();
231 
232  map_type::const_iterator p = buffer.lower_bound(timeslice->getFrameIndex() - numberOfTimeslices);
233  map_type::const_iterator q = buffer.upper_bound(timeslice->getFrameIndex() + numberOfTimeslices);
234 
235  int number_of_events = 0;
236 
237  for (map_type::const_iterator i = p; i != q; ++i) {
238  number_of_events += i->second.size();
239  }
240 
241  if (number_of_events == 0) {
242  continue;
243  }
244 
245  for (JDAQTimeslice::const_iterator frame = timeslice->begin(); frame != timeslice->end(); ++frame) {
246 
247  data.clear();
248 
249  buildL1(*frame, router.getModule(frame->getModuleID()), back_inserter(data));
250 
251  TH1D* h1 = manager[frame->getModuleID()];
252 
253  double t1 = numeric_limits<double>::lowest();
254 
255  for (vector<hit_type>::const_iterator hit = data.begin(); hit != data.end(); ++hit) {
256 
257  const double t2 = *hit + frame->getFrameIndex() * getFrameTime();
258 
259  if (t2 > t1 + deadTime_ns) {
260 
261  for (map_type::const_iterator i = p; i != q; ++i) {
262  for (map_type::mapped_type::const_iterator t0 = i->second.begin(); t0 != i->second.end(); ++t0) {
263  h1->Fill(t2 - *t0);
264  }
265  }
266 
267  t1 = t2;
268  }
269  }
270  }
271  }
272  STATUS(endl);
273 
274 
275  // fit function
276 
277  TF1 f1("f1", "[0]*exp(-0.5*(x-[1])*(x-[1])/([2]*[2])) + [3]");
278 
279  string option = "L";
280 
281  if (debug < debug_t) {
282  option += "Q";
283  }
284 
285 
286  map<int, JStatus_t> status;
287 
288  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
289 
290  if (module->getFloor() != 0) {
291 
292  status[module->getID()] = DEFAULT;
293 
294  JManager_t::iterator p = manager.find(module->getID());
295 
296  if (p == manager.end() || p->second->GetEntries() == 0) {
297 
298  status[module->getID()] = NODATA;
299 
300  continue;
301  }
302 
303  TH1D* h1 = p->second;
304 
305  // start values
306 
307  Double_t ymax = 0.0;
308  Double_t x0 = 0.0; // [ns]
309  Double_t sigma = 250.0; // [ns]
310  Double_t ymin = 0.0;
311 
312  for (int i = 1; i != h1->GetNbinsX(); ++i) {
313 
314  const Double_t x = h1->GetBinCenter (i);
315  const Double_t y = h1->GetBinContent(i);
316 
317  if (y > ymax) {
318  ymax = y;
319  x0 = x;
320  }
321 
322  ymin += y;
323  }
324 
325  ymin /= h1->GetNbinsX();
326 
327  f1.SetParameter(0, ymax);
328  f1.SetParameter(1, x0);
329  if (binWidth_ns < sigma)
330  f1.SetParameter(2, sigma);
331  else
332  f1.FixParameter(2, binWidth_ns/sqrt(12.0));
333  f1.SetParameter(3, ymin);
334 
335  for (Int_t i = 0; i != f1.GetNpar(); ++i) {
336  f1.SetParError(i, 0.0);
337  }
338 
339  // fit
340 
341  h1->Fit(&f1, option.c_str(), "same", x0 - 5 * sigma, x0 + 5 * sigma);
342 
343  if (fabs(f1.GetParameter(1)) <= 0.5*getFrameTime() && // position
344  f1.GetParameter(0) >= f1.GetParameter(3)) { // S/N
345 
346  status[module->getID()] = IN_SYNC;
347  }
348 
349  double fm = fmod(f1.GetParameter(1), getFrameTime());
350 
351  if (fm < -0.5 * getFrameTime()) { fm += getFrameTime(); }
352  if (fm > +0.5 * getFrameTime()) { fm -= getFrameTime(); }
353 
354  STATUS("Module/fit "
355  << setw(10) << module->getID() << ' '
356  << FIXED(15,3) << f1.GetParameter(1) << ' '
357  << FIXED(12,3) << f1.GetParameter(0) << ' '
358  << FIXED(12,3) << f1.GetParameter(3) << ' '
359  << FIXED(12,3) << fm << ' '
360  << status[module->getID()] << endl);
361 
362  // look for peaks at time offsets equal to a multiple of frame time
363 
364  map<int, JWeight> bg; // background
365  map<int, JWeight> sn; // signal(s)
366 
367  for (Int_t i = 1, ns = -(numberOfTimeslices + 1); i <= h1->GetNbinsX(); ++i) {
368 
369  const Double_t x = h1->GetBinCenter (i);
370  const Double_t y = h1->GetBinContent(i);
371 
372  while (x > (ns + 1) * getFrameTime() - BOOST * TMax_ns) {
373  ++ns;
374  }
375 
376  if (fabs(x - ns * getFrameTime()) < TMax_ns)
377  sn[ns].put(y);
378  else if (fabs(x - ns * getFrameTime()) < BOOST * TMax_ns)
379  bg[ns].put(y);
380  }
381 
382  for (map<int, JWeight>::iterator i = sn.begin(); i != sn.end(); ) {
383 
384  const Double_t y = getBackground(i->second, bg[i->first]);
385  const Double_t P = TMath::PoissonI(i->second.getTotal(), y);
386 
387  if (debug >= debug_t || status[module->getID()] != IN_SYNC) {
388  cout << "Module/peak " << setw(10) << module->getID() << ' '
389  << setw(4) << i->first << ' '
390  << "["
391  << FIXED(15,1) << i->first * getFrameTime() - TMax_ns
392  << ","
393  << FIXED(15,1) << i->first * getFrameTime() + TMax_ns
394  << "]"
395  << " S/N = "
396  << FIXED(7,1) << i->second.getTotal() << " / "
397  << FIXED(7,1) << y << ' '
398  << SCIENTIFIC(12,3) << P << ' '
399  << (i->second.getTotal() > y && P < Pmin && i->first != 0 ? "***" : "") << endl;
400  }
401 
402  if (i->second.getTotal() > y && P < Pmin)
403  ++i; // keep
404  else
405  sn.erase(i++); // remove
406  }
407 
408  if (!(sn.size() == 1 &&
409  sn.begin()->first == 0)) {
410 
411  status[module->getID()] = (sn.size() == 1 ? OUT_SYNC : ERROR);
412 
413  ERROR("Module/error "
414  << setw(10) << module->getID() << ' '
415  << "number of peaks " << sn.size() << ' '
416  << "peak " << (sn.size() == 1 ? MAKE_CSTRING(sn.begin()->first) : "?") << ' '
417  << status[module->getID()] << endl);
418  }
419  }
420  }
421 
422  if (overwriteDetector) {
423 
424  detector.comment.add(JMeta(argc, argv));
425 
426  for (map<int, JStatus_t>::const_iterator i = status.begin(); i != status.end(); ++i) {
427 
428  if (i->second != IN_SYNC &&
429  i->second != NODATA) {
430 
431  NOTICE("Module " << setw(8) << i->first << " set out-of-sync." << endl);
432 
433  JModule& module = detector.getModule(router.getAddress(i->first));
434 
435  module.getStatus().set(MODULE_OUT_OF_SYNC);
436 
437  for (JModule::iterator pmt = module.begin(); pmt != module.end(); ++pmt) {
438  pmt->getStatus().set(OUT_OF_SYNC);
439  }
440  }
441  }
442 
443  store(detectorFile.c_str(), detector);
444  }
445 
446  if (outputFile != "") {
447  manager.Write(outputFile.c_str());
448  }
449 
450  int nin = 0;
451  int nout = 0;
452 
453  for (map<int, JStatus_t>::const_iterator i = status.begin(); i != status.end(); ++i) {
454  if (i->second == IN_SYNC) {
455  ++nin;
456  }
457  if (i->second != IN_SYNC &&
458  i->second != NODATA) {
459  ++nout;
460  }
461  }
462 
463  NOTICE("Number of modules out/in sync " << nout << '/' << nin << endl);
464 
465  QAQC(nin << ' ' << nout << endl);
466 
467  return 0;
468 }
string outputFile
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
#define STATUS(A)
Definition: JMessage.hh:63
#define QAQC(A)
QA/QC output macro.
Definition: JMessage.hh:100
#define ERROR(A)
Definition: JMessage.hh:66
int qaqc
QA/QC file descriptor.
#define NOTICE(A)
Definition: JMessage.hh:64
#define FATAL(A)
Definition: JMessage.hh:67
int debug
debug level
Definition: JSirene.cc:69
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:2142
#define MAKE_CSTRING(A)
Make C-string.
Definition: JPrint.hh:72
Simple wrapper around JModuleRouter class for direct addressing of PMT data in detector data structur...
Detector data structure.
Definition: JDetector.hh:96
Data structure for a composite optical module.
Definition: JModule.hh:75
Auxialiary class to assert type conversion.
Definition: JConversion.hh:43
General exception.
Definition: JException.hh:24
The template JSinglePointer class can be used to hold a pointer to an object.
Utility class to parse command line options.
Definition: JParser.hh:1698
Auxiliary class to manage set of compatible ROOT objects (e.g. histograms) using unique keys.
Definition: JManager.hh:47
Template definition for direct access of elements in ROOT TChain.
Template L0 hit builder.
Definition: JBuildL0.hh:38
Template L1 hit builder.
Definition: JBuildL1.hh:90
int getFrameIndex() const
Get frame index.
Template const_iterator.
Definition: JDAQEvent.hh:68
JTriggerCounter_t next()
Increment trigger counter.
static const int MODULE_OUT_OF_SYNC
Enable (disable) synchronous signal from this module if this status bit is 0 (1);.
const double sigma[]
Definition: JQuadrature.cc:74
const JPolynome f1(1.0, 2.0, 3.0)
Function.
const double xmax
Definition: JQuadrature.cc:24
const double xmin
Definition: JQuadrature.cc:23
double getTime(const Hit &hit)
Get true time of hit.
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.
@ debug_t
debug
Definition: JMessage.hh:29
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
std::vector< size_t > ns
KM3NeT DAQ data structures and auxiliaries.
Definition: DataQueue.cc:39
double getFrameTime()
Get frame time duration.
Definition: JDAQClock.hh:162
double getMaximalTime(const double R_Hz)
Get maximal time for given rate.
std::map< int, range_type > map_type
Definition: JSTDTypes.hh:14
static const int OUT_OF_SYNC
Enable (disable) synchronous signal from this PMT if this status bit is 0 (1);.
Definition: pmt_status.hh:17
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:448
Detector file.
Definition: JHead.hh:227
int getStatus() const
Get status.
Definition: JStatus.hh:63
Auxiliary class for a type holder.
Definition: JType.hh:19
Auxiliary class to select ROOT class based on class name.
Auxiliary class to select JTreeScanner based on ROOT class name.
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 L1 build parameters.
Definition: JBuildL1.hh:38
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:488