46int main(
int argc,
char* argv[]) {
52 string ligierFireDrill;
55 JTag outputTag, tagFireDrill;
56 string outputFileName;
58 size_t nBufferedTimeslices;
62 string domDetectorFile;
65 int numberOfTimeouts = 1e3;
66 int queueLength = 100;
70 int preTriggerThreshold = 4;
72 double TVeto_ns = 1000;
77 string summaryFile =
"";
78 int statPrintInterval_s = 30;
83 string properties_description =
"\n";
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");
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");
110 properties_description.append(
"\tM_RATE: multiplicity threshold to compare the SN hit rates to the triggered event rates\n");
113 properties_description.append(
"\tsummaryFile: summary output file\n");
115 properties_description.append(
"\tstatPrintInterval_s: statistics & file print interval [s]");
117 JParser<> zap(
"Supernova realtime processor");
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;
137 catch(
const exception &error) {
138 FATAL(error.what() << endl);
141 if (queueLength <= windowLength) {
142 FATAL(
"Length of the trigger window must be smaller than the queue.");
165 load(domDetectorFile, domDetector);
177 const int detectorSize =
detector.size();
187 typedef priority_queue<trigger_type, vector<trigger_type>, greater<trigger_type> > queue_type;
189 typedef deque<trigger_type> window_type;
198 window_type trgWindow;
207 long int counter_live_ts = 0;
208 long int counter_lost_ts = 0;
214 int nWrittenEntries = 0;
215 if (outputFileName !=
""){
235 if (inputFileName !=
"") {
241 else if (inputLigier !=
"") {
246 const double asyncTimeout_us = 1000.0;
251 else {
FATAL(
"Need either a root file or a ligier as input!" << endl); }
254 if (outputLigier !=
"") {
260 if (ligierFireDrill !=
"") {
264 fireDrill.
MyId(
"JGetMessage");
270 if (outputFileName !=
"") {
277 int timesliceSize = 0;
281 int startedFireDrill =
false;
284 ifstream fireDrillData;
285 int fireDrillTimeslice = 0;
286 double fireDrillOffsetTime, timeFireDrill, MultFireDrill, RFireDrill, CThetaFireDrill, TotalToTFireDrill, DeltaTFireDrill;
287 int timeSinceLastFireDrill = 10000;
289 for (
int i = 0; i != numberOfTimeouts; ) {
295 DEBUG(timeslice->getDAQHeader() << endl);
296 timesliceSize = timeslice->size();
298 timesliceSize_all[timeslice->getFrameIndex()] = timesliceSize;
304 const int r = timeslice->getRunNumber();
310 NOTICE(
"RUN CHANGE" << endl);
312 while (trgQueue.size() > 0) { trgQueue.pop(); }
316 timesliceSize_all.clear();
346 for (JDAQSummaryslice::const_iterator summary_frame = summary->begin();
347 summary_frame != summary->end();
350 int DOMID = summary_frame->getModuleID();
353 rates[frame_index][DOMID] += summary_frame->getRate(ipmt, 1.0/1000);
356 doms[frame_index].push_back(DOMID);
359 if (doms.size() > nBufferedTimeslices){
360 doms.erase(doms.begin()->first);
363 pmts[frame_index] += summary_frame->countActiveChannels();
372 DEBUG(
"EVT " << event->getDAQHeader() << endl);
374 int frame_index =
event->getFrameIndex();
376 veto[frame_index].push_back(
JVeto(*event, hitRouter));
384 JDataSN preTrigger(TMax_ns, preTriggerThreshold);
386 preTrigger(timeslice, moduleRouter, totSelector_ns, domDetector);
400 if (!startedFireDrill){
402 timeSinceLastFireDrill += 0.1;
407 fireDrillFile.resize(prefix.
getSize());
408 fireDrill.
GetFullData(fireDrillFile.data(), fireDrillFile.size());
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;
426 if (startedFireDrill) {
428 double tmin = 0.1*fireDrillTimeslice;
429 double tmax = tmin + 0.1;
431 if (fireDrillTimeslice == 0) {
432 fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill;
433 timeFireDrill += fireDrillOffsetTime;
438 double event_time = (sn_it==
trigger.end()) ? 100 : sn_it->getPeak().time/1.0e9;
441 while (fireDrillData && timeFireDrill < tmax) {
444 while(event_time < timeFireDrill-tmin && sn_it !=
trigger.end()) {
445 trigger_final.push_back(*sn_it);
447 if (sn_it !=
trigger.end()) event_time = sn_it->getPeak().time/1.0e9;
450 if (sn_it >
trigger.begin() && event_time > timeFireDrill-tmin) sn_it -= 1;
453 if (timeFireDrill >= tmin && timeFireDrill < tmax) {
456 int frame_number = timeslice->getFrameIndex();
457 int dom_id = doms[frame_number][(int)
getRandom(0,(
int)doms[frame_number].size())];
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);
467 fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill;
468 timeFireDrill += fireDrillOffsetTime;
473 while(sn_it !=
trigger.end()) {
474 trigger_final.push_back(*sn_it);
478 fireDrillTimeslice++;
482 startedFireDrill =
false;
483 fireDrillFile.clear();
484 timeSinceLastFireDrill = 0;
485 fireDrillData.close();
490 trgQueue.push(trigger_final);
496 if ( trgQueue.size() >= (
unsigned) queueLength ) {
498 while ( trgWindow.size() <= (
unsigned) windowLength ) {
500 trigger_type pending = trgQueue.top();
502 if ( trgWindow.size() == 0 || pending > trgWindow.back() ) {
504 trgWindow.push_back( pending );
519 NOTICE(
"Filling trigger queue: " << trgQueue.size() <<
"/" << queueLength <<
'\r');
523 else if ( inputFileName !=
"" ) {
526 if ( trgQueue.size() > 0 ) {
527 while ( trgQueue.size() > 0 ) {
528 trgWindow.push_back(trgQueue.top());
533 else if ( trgWindow.size() < (
unsigned) windowLength ) {
534 i = numberOfTimeouts;
538 NOTICE(
"timeout " << setw(3) << i << endl);
543 if (trgWindow.size() >= (
unsigned) windowLength) {
550 int trg_cc_counts = 0;
551 int trg_cc_modules = 0;
554 int trg_ev_counts = 0;
555 int trg_ev_modules = 0;
563 int trg_cc_counts_nofakes = 0;
564 int trg_cc_modules_nofakes = 0;
567 int trg_ev_counts_nofakes = 0;
568 int trg_ev_modules_nofakes = 0;
572 for (
int its = 0; its < windowLength; its++) {
574 const int frame_index = trgWindow[its].frameIndex;
577 if (veto.count(frame_index)) {
578 vetoSet = veto.at(frame_index);
584 set<int> cc_vec = trgWindow[its].getModules(F_M1);
585 set<int> ev_vec = trgWindow[its].getModules(F_MV);
592 for (
auto &trg: trgWindow[its]){
593 if (trg.getPeak().multiplicity >= M_RATE) {
597 if (!trg.getPeak().fake) trg_cc_counts_nofakes++;
598 for (
auto &snc: trg){
600 cc_vec_nofakes.insert(snc.moduleID);
605 if (!trg.getPeak().fake) trg_ev_counts_nofakes++;
606 for (
auto &snc: trg){
608 ev_vec_nofakes.insert(snc.moduleID);
616 coincNumber[frame_index] = ncoinc;
618 cc_modules.insert(cc_vec.begin(), cc_vec.end());
619 ev_modules.insert(ev_vec.begin(), ev_vec.end());
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());
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);
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);
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);
648 trg_cc_modules = cc_modules.size();
649 trg_ev_modules = ev_modules.size();
651 trg_cc_modules_nofakes = cc_modules_nofakes.size();
652 trg_ev_modules_nofakes = ev_modules_nofakes.size();
656 int currentFrame = trgWindow[0].frameIndex;
659 trgWindow.pop_front();
663 ++stats[trg_cc_counts];
667 int activeModules = -1;
669 double detectorRate = 0.0;
670 double triggerNum = 0.0;
673 for (
int frame=0; frame < windowLength; frame++) {
675 activePMTs += pmts[currentFrame+frame];
676 triggerNum += veto[currentFrame+frame].size();
677 coincNum += coincNumber[currentFrame+frame];
679 int activeModules_frame = 0;
681 if (!rates.empty() &&
682 rates.count(currentFrame+frame)) {
684 activeModules_frame = 0;
687 p != rates.at(currentFrame+frame).end(); p++ ) {
689 detectorRate += p->second;
691 activeModules_frame += (p->second > 0);
697 activeModules_frame = timesliceSize_all[currentFrame+frame];
701 activeModules += activeModules_frame;
705 activeModules /= windowLength;
706 activePMTs /= windowLength;
711 string daq_time =
to_string(currentTime);
730 string msg = jd.dump();
737 if (multiplicities.size() != multiplicities_nofakes.size()){
759 if (outputFileName !=
""){
760 if (nWrittenEntries < nEntries || nEntries == -1) {
782 if ( (counter_live_ts % ((
int)(statPrintInterval_s / frameTime_s)) == 0 ) ) {
784 double livetime = counter_live_ts * frameTime_s;
790 NOTICE(
"=> discarded out-of-order timeslices = " << counter_lost_ts << endl);
792 if (summaryFile !=
"") {
793 ofstream of(summaryFile.c_str());
804 ERROR(error.what() << endl);
807 if (outputFileName !=
"") {
outputFile.close(); }