46 {
50
51 string inputLigier;
52 string ligierFireDrill;
53 string inputFileName;
54 string outputLigier;
55 JTag outputTag, tagFireDrill;
56 string outputFileName;
57 int nEntries;
58 size_t nBufferedTimeslices;
60
61 string detectorFile;
62 string domDetectorFile;
63
65 int numberOfTimeouts = 1e3;
66 int queueLength = 100;
67 int windowLength = 5;
68
69 int TMax_ns = 10;
70 int preTriggerThreshold = 4;
72 double TVeto_ns = 1000;
75 int M_RATE = 8;
76
77 string summaryFile = "";
78 int statPrintInterval_s = 30;
79
80 try {
81
83 string properties_description = "\n";
84
86
88 properties_description.append("\ttimeout_us: timeout for input [us]\n");
90 properties_description.append("\tnumberOfTimeouts: number of timeouts before stop\n");
92 properties_description.append("\tqueueLength: number of timeslices of trigger queue\n");
94 properties_description.append("\twindowLength: number of timeslices of trigger sliding window\n");
95
97 properties_description.append("\tTMax_ns: coincidence time window [ns]\n");
99 properties_description.append("\tpreTriggerThreshold: muon veto multiplicity threshold\n");
101 properties_description.append("\ttotSelector_ns: hit selector\n");
103 properties_description.append("\tTVeto_ns: muon veto time interval [ns]\n");
105 properties_description.append("\tM: multiplicity range for SN coincidence level\n");
107 properties_description.append("\tM_BDT: multiplicity range for SN coincidence level (with BDT)\n");
108
110 properties_description.append("\tM_RATE: multiplicity threshold to compare the SN hit rates to the triggered event rates\n");
111
113 properties_description.append("\tsummaryFile: summary output file\n");
115 properties_description.append("\tstatPrintInterval_s: statistics & file print interval [s]");
116
117 JParser<> zap(
"Supernova realtime processor");
118
119 zap[
'H'] =
make_field(inputLigier,
"Input Ligier server") =
"";
120 zap[
'l'] =
make_field(ligierFireDrill,
"Ligier server for the fire drill") =
"";
121 zap[
'g'] =
make_field(tagFireDrill,
"Ligier tag for the fire drill") =
JTag(
"FDRILL");
123 zap[
'L'] =
make_field(outputLigier,
"Output Ligier server") =
"";
124 zap[
'T'] =
make_field(outputTag,
"Output tag for the json messages") =
JTag();
125 zap[
'o'] =
make_field(outputFileName,
"Output json file name (no output to Ligier)") =
"";
126 zap[
'n'] =
make_field(nEntries,
"Number of entries to write") = -1;
127 zap[
'N'] =
make_field(nBufferedTimeslices,
"Maximum number of timeslices to save in DOM ID map") = 200;
132
133 zap(argc, argv);
134
135 }
136
137 catch(const exception &error) {
138 FATAL(error.what() << endl);
139 }
140
141 if (queueLength <= windowLength) {
142 FATAL(
"Length of the trigger window must be smaller than the queue.");
143 }
144
145
147
149
150
151
152
153
156
157 try {
159 }
162 }
163
164 try {
165 load(domDetectorFile, domDetector);
166 }
169 }
170
172
174
176
177 const int detectorSize =
detector.size();
178
180
181
182
183
184
186
187 typedef priority_queue<trigger_type, vector<trigger_type>, greater<trigger_type> > queue_type;
188
189 typedef deque<trigger_type> window_type;
190
191
192
196
197 queue_type trgQueue;
198 window_type trgWindow;
199 rates_type rates;
200 npmt_type pmts;
201 veto_type veto;
204
206
207 long int counter_live_ts = 0;
208 long int counter_lost_ts = 0;
209
211
212
214 int nWrittenEntries = 0;
215 if (outputFileName != ""){
217 }
218
219
220
221
222
223 try {
224
225
226
230
234
235 if (inputFileName != "") {
239
240 }
241 else if (inputLigier != "") {
243
244
245
246 const double asyncTimeout_us = 1000.0;
247
250 }
251 else {
FATAL(
"Need either a root file or a ligier as input!" << endl); }
252
254 if (outputLigier != "") {
256 }
257
259
260 if (ligierFireDrill != "") {
263
264 fireDrill.MyId("JGetMessage");
265 fireDrill.Subscribe(buffer);
266 fireDrill.SendMeAlways();
267 }
268
270 if (outputFileName != "") {
272 }
273
274
275
276 int RUN = 0;
277 int timesliceSize = 0;
279
280
281 int startedFireDrill = false;
284 ifstream fireDrillData;
285 int fireDrillTimeslice = 0;
286 double fireDrillOffsetTime, timeFireDrill, MultFireDrill, RFireDrill, CThetaFireDrill, TotalToTFireDrill, DeltaTFireDrill;
287 int timeSinceLastFireDrill = 10000;
288
289 for (int i = 0; i != numberOfTimeouts; ) {
290
292
294
295 DEBUG(timeslice->getDAQHeader() << endl);
296 timesliceSize = timeslice->size();
297
298 timesliceSize_all[timeslice->getFrameIndex()] = timesliceSize;
299
300
301
302
303
304 const int r = timeslice->getRunNumber();
305
306 if (r != RUN) {
307
308 if (RUN != 0) {
309
310 NOTICE(
"RUN CHANGE" << endl);
311
312 while (trgQueue.size() > 0) { trgQueue.pop(); }
313
314 trgWindow.clear();
315
316 timesliceSize_all.clear();
317
318 rates.clear();
319
320 pmts.clear();
321
322 veto.clear();
323
324 doms.clear();
325
326 coincNumber.clear();
327
328 }
329
330 RUN = r;
331
332 }
333
334
335
336
337
339
341
343
345
346 for (JDAQSummaryslice::const_iterator summary_frame = summary->begin();
347 summary_frame != summary->end();
348 ++summary_frame) {
349
350 int DOMID = summary_frame->getModuleID();
351
353 rates[frame_index][DOMID] += summary_frame->getRate(ipmt, 1.0/1000);
354 }
355
356 doms[frame_index].push_back(DOMID);
357
358
359 if (doms.size() > nBufferedTimeslices){
360 doms.erase(doms.begin()->first);
361 }
362
363 pmts[frame_index] += summary_frame->countActiveChannels();
364 }
365
366 }
367
369
371
372 DEBUG(
"EVT " << event->getDAQHeader() << endl);
373
374 int frame_index = event->getFrameIndex();
375
376 veto[frame_index].push_back(
JVeto(*event, hitRouter));
377
378 }
379
380
381
382
383
384 JDataSN preTrigger(TMax_ns, preTriggerThreshold);
385
386 preTrigger(timeslice, moduleRouter, totSelector_ns, domDetector);
387
389
391
393 trigger_final.frameIndex =
trigger.frameIndex;
394 trigger_final.timeUTC =
trigger.timeUTC;
395
396
397
398
399
400 if (!startedFireDrill){
401
402 timeSinceLastFireDrill += 0.1;
403
404
405 int drill = fireDrill.CheckHead(prefix);
406 if (drill){
407 fireDrillFile.resize(prefix.
getSize());
408 fireDrill.GetFullData(fireDrillFile.data(), fireDrillFile.size());
409 }
410
411
412
413 if (fireDrillFile.size()>0 && timeSinceLastFireDrill > 100) {
414 startedFireDrill = true;
415 fireDrillOffsetTime = 0.05;
416 fireDrillTimeslice = 0;
417 string fireDrillFileName(fireDrillFile.begin()+1, fireDrillFile.end()-1);
418 fireDrillData.open(fireDrillFileName.c_str());
419 timeFireDrill = -100;
420 } else {
422 }
423 }
424
425
426 if (startedFireDrill) {
427
428 double tmin = 0.1*fireDrillTimeslice;
429 double tmax = tmin + 0.1;
430
431 if (fireDrillTimeslice == 0) {
432 fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill;
433 timeFireDrill += fireDrillOffsetTime;
434 }
435
436
438 double event_time = (sn_it==
trigger.end()) ? 100 : sn_it->getPeak().time/1.0e9;
439
440
441 while (fireDrillData && timeFireDrill < tmax) {
442
443
444 while(event_time < timeFireDrill-tmin && sn_it !=
trigger.end()) {
445 trigger_final.push_back(*sn_it);
446 sn_it++;
447 if (sn_it !=
trigger.end()) event_time = sn_it->getPeak().time/1.0e9;
448 }
449
450 if (sn_it >
trigger.begin() && event_time > timeFireDrill-tmin) sn_it -= 1;
451
452
453 if (timeFireDrill >= tmin && timeFireDrill < tmax) {
454
455
456 int frame_number = timeslice->getFrameIndex();
457 int dom_id = doms[frame_number][(int)
getRandom(0,(
int)doms[frame_number].size())];
458
459 JCoincidenceSN sn((timeFireDrill-tmin)*1e9, (
int) MultFireDrill,
dom_id, 0, CThetaFireDrill, RFireDrill, DeltaTFireDrill, TotalToTFireDrill, -1,
true);
461 sncluster.push_back(sn);
462 trigger_final.push_back(sncluster);
463
464 }
465
466
467 fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill;
468 timeFireDrill += fireDrillOffsetTime;
469
470 }
471
472
473 while(sn_it !=
trigger.end()) {
474 trigger_final.push_back(*sn_it);
475 sn_it++;
476 }
477
478 fireDrillTimeslice++;
479
480
481 if (!fireDrillData){
482 startedFireDrill = false;
483 fireDrillFile.clear();
484 timeSinceLastFireDrill = 0;
485 fireDrillData.close();
486 }
487
488 }
489
490 trgQueue.push(trigger_final);
491
492
493
494
495
496 if ( trgQueue.size() >= (unsigned) queueLength ) {
497
498 while ( trgWindow.size() <= (unsigned) windowLength ) {
499
500 trigger_type pending = trgQueue.top();
501
502 if ( trgWindow.size() == 0 || pending > trgWindow.back() ) {
503
504 trgWindow.push_back( pending );
505
506 counter_live_ts++;
507
508 }
509 else {
510
511 counter_lost_ts++;
512 }
513
514 trgQueue.pop();
515
516 }
517 }
518 else {
519 NOTICE(
"Filling trigger queue: " << trgQueue.size() <<
"/" << queueLength <<
'\r');
520 }
521 }
522
523 else if ( inputFileName != "" ) {
524
525
526 if ( trgQueue.size() > 0 ) {
527 while ( trgQueue.size() > 0 ) {
528 trgWindow.push_back(trgQueue.top());
529
530 trgQueue.pop();
531 }
532 }
533 else if ( trgWindow.size() < (unsigned) windowLength ) {
534 i = numberOfTimeouts;
535 }
536 }
537 else {
538 NOTICE(
"timeout " << setw(3) << i << endl);
539
540 ++i;
541 }
542
543 if (trgWindow.size() >= (unsigned) windowLength) {
544
545
546
549
550 int trg_cc_counts = 0;
551 int trg_cc_modules = 0;
553
554 int trg_ev_counts = 0;
555 int trg_ev_modules = 0;
557
558
559
562
563 int trg_cc_counts_nofakes = 0;
564 int trg_cc_modules_nofakes = 0;
566
567 int trg_ev_counts_nofakes = 0;
568 int trg_ev_modules_nofakes = 0;
570
571
572 for (int its = 0; its < windowLength; its++) {
573
574 const int frame_index = trgWindow[its].frameIndex;
575
577 if (veto.count(frame_index)) {
578 vetoSet = veto.at(frame_index);
579 }
580
583
584 set<int> cc_vec = trgWindow[its].getModules(F_M1);
585 set<int> ev_vec = trgWindow[its].getModules(F_MV);
586
587
590
591 int ncoinc = 0;
592 for (auto &trg: trgWindow[its]){
593 if (trg.getPeak().multiplicity >= M_RATE) {
594 ncoinc++;
595 }
596 if (F_M1(trg)){
597 if (!trg.getPeak().fake) trg_cc_counts_nofakes++;
598 for (auto &snc: trg){
599 if (!snc.fake){
600 cc_vec_nofakes.insert(snc.moduleID);
601 }
602 }
603 }
604 if (F_MV(trg)){
605 if (!trg.getPeak().fake) trg_ev_counts_nofakes++;
606 for (auto &snc: trg){
607 if (!snc.fake){
608 ev_vec_nofakes.insert(snc.moduleID);
609 }
610 }
611 }
612 }
613
614
615
616 coincNumber[frame_index] = ncoinc;
617
618 cc_modules.insert(cc_vec.begin(), cc_vec.end());
619 ev_modules.insert(ev_vec.begin(), ev_vec.end());
620
621 cc_modules_nofakes.insert(cc_vec_nofakes.begin(), cc_vec_nofakes.end());
622 ev_modules_nofakes.insert(ev_vec_nofakes.begin(), ev_vec_nofakes.end());
623
624 trg_cc_counts += count_if(trgWindow[its].begin(), trgWindow[its].end(), F_M1);
625 trg_ev_counts += count_if(trgWindow[its].begin(), trgWindow[its].end(), F_MV);
626
627
628 for (auto &trg: trgWindow[its]){
629 auto sn_candidate = trg.getPeak();
630 if (F_MV_BDT(sn_candidate)){
631 multiplicities.push_back(sn_candidate.multiplicity);
632 observables.push_back(sn_candidate.total_ToT);
633 observables.push_back(sn_candidate.deltaT);
634 observables.push_back(sn_candidate.mean_dir_norm);
635 observables.push_back(sn_candidate.mean_dir_ctheta);
636
637 if (!sn_candidate.fake){
638 multiplicities_nofakes.push_back(sn_candidate.multiplicity);
639 observables_nofakes.push_back(sn_candidate.total_ToT);
640 observables_nofakes.push_back(sn_candidate.deltaT);
641 observables_nofakes.push_back(sn_candidate.mean_dir_norm);
642 observables_nofakes.push_back(sn_candidate.mean_dir_ctheta);
643 }
644 }
645 }
646 }
647
648 trg_cc_modules = cc_modules.size();
649 trg_ev_modules = ev_modules.size();
650
651 trg_cc_modules_nofakes = cc_modules_nofakes.size();
652 trg_ev_modules_nofakes = ev_modules_nofakes.size();
653
654
655
656 int currentFrame = trgWindow[0].frameIndex;
658
659 trgWindow.pop_front();
660
661
662
663 ++stats[trg_cc_counts];
664
665
666
667 int activeModules = -1;
668 int activePMTs = 0;
669 double detectorRate = 0.0;
670 double triggerNum = 0.0;
671 int coincNum = 0;
672
673 for (int frame=0; frame < windowLength; frame++) {
674
675 activePMTs += pmts[currentFrame+frame];
676 triggerNum += veto[currentFrame+frame].size();
677 coincNum += coincNumber[currentFrame+frame];
678
679 int activeModules_frame = 0;
680
681 if (!rates.empty() &&
682 rates.count(currentFrame+frame)) {
683
684 activeModules_frame = 0;
685
687 p != rates.at(currentFrame+frame).end(); p++ ) {
688
689 detectorRate += p->second;
690
691 activeModules_frame += (p->second > 0);
692
693 }
694
695 } else {
696
697 activeModules_frame = timesliceSize_all[currentFrame+frame];
698
699 }
700
701 activeModules += activeModules_frame;
702
703 }
704
705 activeModules /= windowLength;
706 activePMTs /= windowLength;
707
708
709
711 string daq_time =
to_string(currentTime);
712
713
729
730 string msg = jd.dump();
731
733
734
735
736 string msg2 = "";
737 if (multiplicities.size() != multiplicities_nofakes.size()){
753
754 msg2 = jd.dump();
755
757 }
758
759 if (outputFileName != ""){
760 if (nWrittenEntries < nEntries || nEntries == -1) {
761
763 nWrittenEntries++;
764 }
765 else {
766
768 break;
769 }
770 }
771 else {
772
773
774 if (out != NULL) {
777 }
778 }
779
780
781
782 if ( (counter_live_ts % ((int)(statPrintInterval_s / frameTime_s)) == 0 ) ) {
783
784 double livetime = counter_live_ts * frameTime_s;
785
787
790 NOTICE(
"=> discarded out-of-order timeslices = " << counter_lost_ts << endl);
791
792 if (summaryFile != "") {
793 ofstream of(summaryFile.c_str());
794 of << stats.toSummaryFile();
795 of.close();
796 }
797
798 }
799 }
800 }
801 }
802
805 }
806
807 if (outputFileName !=
"") {
outputFile.close(); }
808
809}
#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 trignum_name
static const std::string c_name
static const std::string m_name
static const std::string coincnum_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.