46 {
50
51 string inputLigier;
52 string ligierFireDrill;
53 string inputFileName;
54 string outputLigier;
55 JTag outputTag, tagFireDrill;
56 string outputFileName;
57 int nEntries;
59
60 string detectorFile;
61 string domDetectorFile;
62
64 int numberOfTimeouts = 1e3;
65 int queueLength = 100;
66 int windowLength = 5;
67
68 int TMax_ns = 10;
69 int preTriggerThreshold = 4;
71 double TVeto_ns = 1000;
74
75 string summaryFile = "";
76 int statPrintInterval_s = 30;
77
78 try {
79
81 string properties_description = "\n";
82
84
86 properties_description.append("\ttimeout_us: timeout for input [us]\n");
88 properties_description.append("\tnumberOfTimeouts: number of timeouts before stop\n");
90 properties_description.append("\tqueueLength: number of timeslices of trigger queue\n");
92 properties_description.append("\twindowLength: number of timeslices of trigger sliding window\n");
93
95 properties_description.append("\tTMax_ns: coincidence time window [ns]\n");
97 properties_description.append("\tpreTriggerThreshold: muon veto multiplicity threshold\n");
99 properties_description.append("\ttotSelector_ns: hit selector\n");
101 properties_description.append("\tTVeto_ns: muon veto time interval [ns]\n");
103 properties_description.append("\tM: multiplicity range for SN coincidence level\n");
105 properties_description.append("\tM_BDT: multiplicity range for SN coincidence level (with BDT)\n");
106
108 properties_description.append("\tsummaryFile: summary output file\n");
110 properties_description.append("\tstatPrintInterval_s: statistics & file print interval [s]");
111
112 JParser<> zap(
"Supernova realtime processor");
113
114 zap[
'H'] =
make_field(inputLigier,
"Input Ligier server") =
"";
115 zap[
'l'] =
make_field(ligierFireDrill,
"Ligier server for the fire drill") =
"";
116 zap[
'g'] =
make_field(tagFireDrill,
"Ligier tag for the fire drill") =
JTag(
"FDRILL");
118 zap[
'L'] =
make_field(outputLigier,
"Output Ligier server") =
"";
119 zap[
'T'] =
make_field(outputTag,
"Output tag for the json messages") =
JTag();
120 zap[
'o'] =
make_field(outputFileName,
"Output json file name (no output to Ligier)") =
"";
121 zap[
'n'] =
make_field(nEntries,
"Number of entries to write") = -1;
126
127 zap(argc, argv);
128
129 }
130
131 catch(const exception &error) {
132 FATAL(error.what() << endl);
133 }
134
135 if (queueLength <= windowLength) {
136 FATAL(
"Length of the trigger window must be smaller than the queue.");
137 }
138
139
141
143
144
145
146
147
150
151 try {
153 }
156 }
157
158 try {
159 load(domDetectorFile, domDetector);
160 }
163 }
164
166
168
170
171 const int detectorSize =
detector.size();
172
174
175
176
177
178
180
181 typedef priority_queue<trigger_type, vector<trigger_type>, greater<trigger_type> > queue_type;
182
183 typedef deque<trigger_type> window_type;
184
185
186
190
191 queue_type trgQueue;
192 window_type trgWindow;
193 rates_type rates;
194 npmt_type pmts;
195 veto_type veto;
197
199
200 long int counter_live_ts = 0;
201 long int counter_lost_ts = 0;
202
204
205
207 int nWrittenEntries = 0;
208 if (outputFileName != ""){
210 }
211
212
213
214
215
216 try {
217
218
219
223
227
228 if (inputFileName != "") {
232
233 }
234 else if (inputLigier != "") {
236
237
238
239 const double asyncTimeout_us = 1000.0;
240
243 }
244 else {
FATAL(
"Need either a root file or a ligier as input!" << endl); }
245
247 if (outputLigier != "") {
249 }
250
252
253 if (ligierFireDrill != "") {
256
257 fireDrill.MyId("JGetMessage");
258 fireDrill.Subscribe(buffer);
259 fireDrill.SendMeAlways();
260 }
261
263 if (outputFileName != "") {
265 }
266
267
268
269 int RUN = 0;
270 int timesliceSize = 0;
271
272
273 int startedFireDrill = false;
276 ifstream fireDrillData;
277 int fireDrillTimeslice = 0;
278 double fireDrillOffsetTime, timeFireDrill, MultFireDrill, RFireDrill, CThetaFireDrill, TotalToTFireDrill, DeltaTFireDrill;
279 int timeSinceLastFireDrill = 10000;
280
281 for (int i = 0; i != numberOfTimeouts; ) {
282
284
286
287 DEBUG(timeslice->getDAQHeader() << endl);
288
289 timesliceSize = timeslice->size();
290
291
292
293
294
295 const int r = timeslice->getRunNumber();
296
297 if (r != RUN) {
298
299 if (RUN != 0) {
300
301 NOTICE(
"RUN CHANGE" << endl);
302
303 while (trgQueue.size() > 0) { trgQueue.pop(); }
304
305 trgWindow.clear();
306
307 rates.clear();
308
309 pmts.clear();
310
311 veto.clear();
312
313 }
314
315 RUN = r;
316
317 }
318
319
320
321
322
324
326
328
330
331 for (JDAQSummaryslice::const_iterator summary_frame = summary->begin();
332 summary_frame != summary->end();
333 ++summary_frame) {
334
335 int DOMID = summary_frame->getModuleID();
336
338 rates[frame_index][DOMID] += summary_frame->getRate(ipmt, 1.0/1000);
339 }
340
341 doms[frame_index].push_back(DOMID);
342
343 pmts[frame_index] += summary_frame->countActiveChannels();
344 }
345
346 }
347
349
351
352 DEBUG(
"EVT " << event->getDAQHeader() << endl);
353
354 int frame_index = event->getFrameIndex();
355
356 veto[frame_index].push_back(
JVeto(*event, hitRouter));
357
358 }
359
360
361
362
363
364 JDataSN preTrigger(TMax_ns, preTriggerThreshold);
365
366 preTrigger(timeslice, moduleRouter, totSelector_ns, domDetector);
367
369
371
373 trigger_final.frameIndex =
trigger.frameIndex;
374 trigger_final.timeUTC =
trigger.timeUTC;
375
376
377
378
379
380 if (!startedFireDrill){
381
382 timeSinceLastFireDrill += 0.1;
383
384
385 int drill = fireDrill.CheckHead(prefix);
386 if (drill){
387 fireDrillFile.resize(prefix.
getSize());
388 fireDrill.GetFullData(fireDrillFile.data(), fireDrillFile.size());
389 }
390
391
392
393 if (fireDrillFile.size()>0 && timeSinceLastFireDrill > 100) {
394 startedFireDrill = true;
395 fireDrillOffsetTime = 0.05;
396 fireDrillTimeslice = 0;
397 string fireDrillFileName(fireDrillFile.begin()+1, fireDrillFile.end()-1);
398 fireDrillData.open(fireDrillFileName.c_str());
399 timeFireDrill = -100;
400 } else {
402 }
403 }
404
405
406 if (startedFireDrill) {
407
408 double tmin = 0.1*fireDrillTimeslice;
409 double tmax = tmin + 0.1;
410
411 if (fireDrillTimeslice == 0) {
412 fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill;
413 timeFireDrill += fireDrillOffsetTime;
414 }
415
416
418 double event_time = (sn_it==
trigger.end()) ? 100 : sn_it->getPeak().time/1.0e9;
419
420
421 while (fireDrillData && timeFireDrill < tmax) {
422
423
424 while(event_time < timeFireDrill-tmin && sn_it !=
trigger.end()) {
425 trigger_final.push_back(*sn_it);
426 sn_it++;
427 if (sn_it !=
trigger.end()) event_time = sn_it->getPeak().time/1.0e9;
428 }
429
430 if (sn_it >
trigger.begin() && event_time > timeFireDrill-tmin) sn_it -= 1;
431
432
433 if (timeFireDrill >= tmin && timeFireDrill < tmax) {
434
435
436 int frame_number = timeslice->getFrameIndex();
437 int dom_id = doms[frame_number][(int)
getRandom(0,(
int)doms[frame_number].size())];
438
439 JCoincidenceSN sn((timeFireDrill-tmin)*1e9, (
int) MultFireDrill,
dom_id, 0, CThetaFireDrill, RFireDrill, DeltaTFireDrill, TotalToTFireDrill, -1,
true);
441 sncluster.push_back(sn);
442 trigger_final.push_back(sncluster);
443
444 }
445
446
447 fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill;
448 timeFireDrill += fireDrillOffsetTime;
449
450 }
451
452
453 while(sn_it !=
trigger.end()) {
454 trigger_final.push_back(*sn_it);
455 sn_it++;
456 }
457
458 fireDrillTimeslice++;
459
460
461 if (!fireDrillData){
462 startedFireDrill = false;
463 fireDrillFile.clear();
464 timeSinceLastFireDrill = 0;
465 fireDrillData.close();
466 }
467
468 }
469
470 trgQueue.push(trigger_final);
471
472
473
474
475
476 if ( trgQueue.size() >= (unsigned) queueLength ) {
477
478 while ( trgWindow.size() <= (unsigned) windowLength ) {
479
480 trigger_type pending = trgQueue.top();
481
482 if ( trgWindow.size() == 0 || pending > trgWindow.back() ) {
483
484 trgWindow.push_back( pending );
485
486 counter_live_ts++;
487
488 }
489 else {
490
491 counter_lost_ts++;
492 }
493
494 trgQueue.pop();
495
496 }
497 }
498 else {
499 NOTICE(
"Filling trigger queue: " << trgQueue.size() <<
"/" << queueLength <<
'\r');
500 }
501 }
502
503 else if ( inputFileName != "" ) {
504
505
506 if ( trgQueue.size() > 0 ) {
507 while ( trgQueue.size() > 0 ) {
508 trgWindow.push_back(trgQueue.top());
509 trgQueue.pop();
510 }
511 }
512 else if ( trgWindow.size() < (unsigned) windowLength ) {
513 i = numberOfTimeouts;
514 }
515 }
516 else {
517 NOTICE(
"timeout " << setw(3) << i << endl);
518
519 ++i;
520 }
521
522 if (trgWindow.size() >= (unsigned) windowLength) {
523
524
525
528
529 int trg_cc_counts = 0;
530 int trg_cc_modules = 0;
532
533 int trg_ev_counts = 0;
534 int trg_ev_modules = 0;
536
537
538
541
542 int trg_cc_counts_nofakes = 0;
543 int trg_cc_modules_nofakes = 0;
545
546 int trg_ev_counts_nofakes = 0;
547 int trg_ev_modules_nofakes = 0;
549
550
551 for (int its = 0; its < windowLength; its++) {
552
553 const int frame_index = trgWindow[its].frameIndex;
554
556 if (veto.count(frame_index)) {
557 vetoSet = veto.at(frame_index);
558 }
559
562
563 set<int> cc_vec = trgWindow[its].getModules(F_M1);
564 set<int> ev_vec = trgWindow[its].getModules(F_MV);
565
566
569
570 for (auto &trg: trgWindow[its]){
571 if (F_M1(trg)){
572 if (!trg.getPeak().fake) trg_cc_counts_nofakes++;
573 for (auto &snc: trg){
574 if (!snc.fake){
575 cc_vec_nofakes.insert(snc.moduleID);
576 }
577 }
578 }
579 if (F_MV(trg)){
580 if (!trg.getPeak().fake) trg_ev_counts_nofakes++;
581 for (auto &snc: trg){
582 if (!snc.fake){
583 ev_vec_nofakes.insert(snc.moduleID);
584 }
585 }
586 }
587 }
588
589 cc_modules.insert(cc_vec.begin(), cc_vec.end());
590 ev_modules.insert(ev_vec.begin(), ev_vec.end());
591
592 cc_modules_nofakes.insert(cc_vec_nofakes.begin(), cc_vec_nofakes.end());
593 ev_modules_nofakes.insert(ev_vec_nofakes.begin(), ev_vec_nofakes.end());
594
595 trg_cc_counts += count_if(trgWindow[its].begin(), trgWindow[its].end(), F_M1);
596 trg_ev_counts += count_if(trgWindow[its].begin(), trgWindow[its].end(), F_MV);
597
598
599 for (auto &trg: trgWindow[its]){
600 auto sn_candidate = trg.getPeak();
601 if (F_MV_BDT(sn_candidate)){
602 multiplicities.push_back(sn_candidate.multiplicity);
603 observables.push_back(sn_candidate.total_ToT);
604 observables.push_back(sn_candidate.deltaT);
605 observables.push_back(sn_candidate.mean_dir_norm);
606 observables.push_back(sn_candidate.mean_dir_ctheta);
607
608 if (!sn_candidate.fake){
609 multiplicities_nofakes.push_back(sn_candidate.multiplicity);
610 observables_nofakes.push_back(sn_candidate.total_ToT);
611 observables_nofakes.push_back(sn_candidate.deltaT);
612 observables_nofakes.push_back(sn_candidate.mean_dir_norm);
613 observables_nofakes.push_back(sn_candidate.mean_dir_ctheta);
614 }
615 }
616 }
617 }
618
619 trg_cc_modules = cc_modules.size();
620 trg_ev_modules = ev_modules.size();
621
622 trg_cc_modules_nofakes = cc_modules_nofakes.size();
623 trg_ev_modules_nofakes = ev_modules_nofakes.size();
624
625
626
627 int currentFrame = trgWindow[0].frameIndex;
629
630 trgWindow.pop_front();
631
632
633
634 ++stats[trg_cc_counts];
635
636
637
638 int activeModules = -1;
639 double detectorRate = 0.0;
640
641 if (!rates.empty() &&
642 rates.count(currentFrame)) {
643
644 activeModules = 0;
645
647 p != rates.at(currentFrame).end(); p++ ) {
648
649 detectorRate += p->second;
650
651 activeModules += (p->second > 0);
652
653 }
654 } else {
655
656 activeModules = timesliceSize;
657
658 }
659
660
661
663 string daq_time =
to_string(currentTime);
664
665
679
680 string msg = jd.dump();
681
683
684
685
686 string msg2 = "";
687 if (multiplicities.size() != multiplicities_nofakes.size()){
701
702 msg2 = jd.dump();
703
705 }
706
707 if (outputFileName != ""){
708 if (nWrittenEntries < nEntries || nEntries == -1) {
709
711 nWrittenEntries++;
712 }
713 else {
714
716 break;
717 }
718 }
719 else {
720
721
722 if (out != NULL) {
725 }
726 }
727
728
729
730 if ( (counter_live_ts % ((int)(statPrintInterval_s / frameTime_s)) == 0 ) ) {
731
732 double livetime = counter_live_ts * frameTime_s;
733
735
738 NOTICE(
"=> discarded out-of-order timeslices = " << counter_lost_ts << endl);
739
740 if (summaryFile != "") {
741 ofstream of(summaryFile.c_str());
742 of << stats.toSummaryFile();
743 of.close();
744 }
745
746 }
747 }
748 }
749 }
750
753 }
754
755 if (outputFileName !=
"") {
outputFile.close(); }
756
757}
#define DEBUG(A)
Message macros.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
#define gmake_property(A)
macros to convert (template) parameter to JPropertiesElement object
static const std::string active_pmts_name
static const std::string cc_name
static const std::string daq_time_name
static const std::string detid_name
static const std::string c_name
static const std::string m_name
static const std::string run_number_name
static const std::string observables_name
static const std::string detector_rate_name
static const std::string ev_name
static const std::string trigger_name
static const std::string active_doms_name
static const std::string frame_index_name
static const std::string multiplicities_name
Simple wrapper around JModuleRouter class for direct addressing of PMT data in detector data structur...
Router for direct addressing of module data in detector data structure.
Utility class to parse parameter values.
void setEndOfLine(const std::string &eol)
Set end of line characters.
virtual const char * what() const override
Get error message.
Interface of object iteration for a single data type.
virtual bool hasNext()=0
Check availability of next element.
virtual const pointer_type & next()=0
Get next element.
Auxiliary class for time values.
Object iteration through ControlHost.
int PutFullString(const JTag &tag, const std::string &buffer)
Send string.
int getSize() const
Get size.
JSubscriptionList & add(const JSubscription &subscription)
Add subscription.
Utility class to parse command line options.
Auxiliary class to manage a cluster of coincidences.
Auxiliary class to store reduced information of a coincidence on an optical module This class allows ...
Auxiliary class to build the supernova trigger dataset.
SN filter based on veto window.
SN filter based on multiplicity selection optional suppression of multi-module coincidences WARNING: ...
SN trigger statistics, the information is stored in the form of a count as a function of the trigger ...
Auxiliary class to apply the supernova trigger to SN data.
Auxiliary class to manage a set of vetoes.
Auxiliary class to define a veto time window on a set of optical modules.
Template definition for direct access of elements in ROOT TChain.
int getFrameIndex() const
Get frame index.
Data structure for UTC time.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
std::string to_string(const T &value)
Convert value to string.
T getRandom()
Get random value.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
std::vector< event_type > data_type
KM3NeT DAQ data structures and auxiliaries.
double getFrameTime()
Get frame time duration.
void setDAQLongprint(const bool option)
Set DAQ print option.
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
Normalisation of MUPAGE events.
Data structure for measured coincidence rates of all pairs of PMTs in optical module.
Auxiliary class for all subscription.
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Auxiliary class to select DAQ hits based on time-over-treshold value.
Timeslice data structure for SN data.