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; 
 
   76  string summaryFile = 
""; 
 
   77  int statPrintInterval_s = 30; 
 
   82    string properties_description = 
"\n";
 
   87    properties_description.append(
"\ttimeout_us: timeout for input [us]\n");
 
   89    properties_description.append(
"\tnumberOfTimeouts: number of timeouts before stop\n");
 
   91    properties_description.append(
"\tqueueLength: number of timeslices of trigger queue\n");
 
   93    properties_description.append(
"\twindowLength: number of timeslices of trigger sliding window\n");
 
   96    properties_description.append(
"\tTMax_ns: coincidence time window [ns]\n");
 
   98    properties_description.append(
"\tpreTriggerThreshold: muon veto multiplicity threshold\n");
 
  100    properties_description.append(
"\ttotSelector_ns: hit selector\n");
 
  102    properties_description.append(
"\tTVeto_ns: muon veto time interval [ns]\n");
 
  104    properties_description.append(
"\tM: multiplicity range for SN coincidence level\n");
 
  106    properties_description.append(
"\tM_BDT: multiplicity range for SN coincidence level (with BDT)\n");
 
  109    properties_description.append(
"\tsummaryFile: summary output file\n");
 
  111    properties_description.append(
"\tstatPrintInterval_s: statistics & file print interval [s]");
 
  113    JParser<> zap(
"Supernova realtime processor");
 
  115    zap[
'H'] = 
make_field(inputLigier, 
"Input Ligier server") = 
"";
 
  116    zap[
'l'] = 
make_field(ligierFireDrill, 
"Ligier server for the fire drill") = 
"";
 
  117    zap[
'g'] = 
make_field(tagFireDrill, 
"Ligier tag for the fire drill") = 
JTag(
"FDRILL");
 
  119    zap[
'L'] = 
make_field(outputLigier, 
"Output Ligier server") = 
"";
 
  120    zap[
'T'] = 
make_field(outputTag, 
"Output tag for the json messages") = 
JTag();
 
  121    zap[
'o'] = 
make_field(outputFileName, 
"Output json file name (no output to Ligier)") = 
"";
 
  122    zap[
'n'] = 
make_field(nEntries, 
"Number of entries to write") = -1;
 
  123    zap[
'N'] = 
make_field(nBufferedTimeslices, 
"Maximum number of timeslices to save in DOM ID map") = 200;
 
  133  catch(
const exception &error) {
 
  134    FATAL(error.what() << endl);
 
  137  if (queueLength <= windowLength) {
 
  138    FATAL(
"Length of the trigger window must be smaller than the queue.");
 
  161    load(domDetectorFile, domDetector);
 
  173  const int detectorSize = 
detector.size();
 
  183  typedef priority_queue<trigger_type, vector<trigger_type>, greater<trigger_type> > queue_type;
 
  185  typedef deque<trigger_type> window_type;
 
  194  window_type trgWindow;
 
  202  long int counter_live_ts = 0;
 
  203  long int counter_lost_ts = 0;
 
  209  int nWrittenEntries = 0;
 
  210  if (outputFileName != 
""){
 
  230    if (inputFileName != 
"") {
 
  236    else if (inputLigier != 
"") {
 
  241      const double asyncTimeout_us = 1000.0;
 
  246    else { 
FATAL(
"Need either a root file or a ligier as input!" << endl); }
 
  249    if (outputLigier != 
"") {
 
  255    if (ligierFireDrill != 
"") {
 
  259      fireDrill.
MyId(
"JGetMessage");
 
  265    if (outputFileName != 
"") {
 
  272    int timesliceSize = 0;
 
  275    int startedFireDrill = 
false;
 
  278    ifstream fireDrillData;
 
  279    int fireDrillTimeslice = 0;
 
  280    double fireDrillOffsetTime, timeFireDrill, MultFireDrill, RFireDrill, CThetaFireDrill, TotalToTFireDrill, DeltaTFireDrill;
 
  281    int timeSinceLastFireDrill = 10000;
 
  283    for (
int i = 0; i != numberOfTimeouts; ) {
 
  289        DEBUG(timeslice->getDAQHeader() << endl);
 
  290        timesliceSize = timeslice->size();
 
  296        const int r = timeslice->getRunNumber();
 
  302            NOTICE(
"RUN CHANGE" << endl);
 
  304            while (trgQueue.size() > 0) { trgQueue.pop(); }
 
  334          for (JDAQSummaryslice::const_iterator summary_frame = summary->begin();
 
  335               summary_frame != summary->end();
 
  338            int DOMID = summary_frame->getModuleID();
 
  341              rates[frame_index][DOMID] += summary_frame->getRate(ipmt, 1.0/1000);
 
  344            doms[frame_index].push_back(DOMID);
 
  347            if (doms.size() > nBufferedTimeslices){
 
  348              doms.erase(doms.begin()->first);
 
  351            pmts[frame_index] += summary_frame->countActiveChannels();
 
  360          DEBUG(
"EVT " << event->getDAQHeader() << endl);
 
  362          int frame_index = 
event->getFrameIndex();
 
  364          veto[frame_index].push_back(
JVeto(*event, hitRouter));
 
  372        JDataSN preTrigger(TMax_ns, preTriggerThreshold);
 
  374        preTrigger(timeslice, moduleRouter, totSelector_ns, domDetector);
 
  388        if (!startedFireDrill){
 
  390          timeSinceLastFireDrill += 0.1;
 
  395            fireDrillFile.resize(prefix.
getSize());
 
  396            fireDrill.
GetFullData(fireDrillFile.data(), fireDrillFile.size());
 
  401          if (fireDrillFile.size()>0 && timeSinceLastFireDrill > 100) { 
 
  402            startedFireDrill = 
true;
 
  403            fireDrillOffsetTime = 0.05; 
 
  404            fireDrillTimeslice = 0;
 
  405            string fireDrillFileName(fireDrillFile.begin()+1, fireDrillFile.end()-1); 
 
  406            fireDrillData.open(fireDrillFileName.c_str());
 
  407            timeFireDrill = -100;
 
  414        if (startedFireDrill) {
 
  416          double tmin = 0.1*fireDrillTimeslice;
 
  417          double tmax = tmin + 0.1;
 
  419          if (fireDrillTimeslice == 0) { 
 
  420            fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill; 
 
  421            timeFireDrill += fireDrillOffsetTime;
 
  426          double event_time = (sn_it==
trigger.end()) ? 100 : sn_it->getPeak().time/1.0e9; 
 
  429          while (fireDrillData && timeFireDrill < tmax) {
 
  432            while(event_time < timeFireDrill-tmin && sn_it != 
trigger.end()) {
 
  433              trigger_final.push_back(*sn_it);
 
  435              if (sn_it != 
trigger.end()) event_time = sn_it->getPeak().time/1.0e9;
 
  438            if (sn_it > 
trigger.begin() && event_time > timeFireDrill-tmin) sn_it -= 1; 
 
  441            if (timeFireDrill >= tmin && timeFireDrill < tmax) {
 
  444              int frame_number = timeslice->getFrameIndex();
 
  445              int dom_id = doms[frame_number][(int) 
getRandom(0,(
int)doms[frame_number].size())];
 
  447              JCoincidenceSN sn((timeFireDrill-tmin)*1e9, (
int) MultFireDrill, 
dom_id, 0, CThetaFireDrill, RFireDrill, DeltaTFireDrill, TotalToTFireDrill, -1, 
true);
 
  449              sncluster.push_back(sn); 
 
  450              trigger_final.push_back(sncluster); 
 
  455            fireDrillData >> timeFireDrill >> MultFireDrill >> CThetaFireDrill >> RFireDrill >> TotalToTFireDrill >> DeltaTFireDrill; 
 
  456            timeFireDrill += fireDrillOffsetTime;
 
  461          while(sn_it != 
trigger.end()) {
 
  462            trigger_final.push_back(*sn_it);
 
  466          fireDrillTimeslice++; 
 
  470            startedFireDrill = 
false;
 
  471            fireDrillFile.clear();
 
  472            timeSinceLastFireDrill = 0;
 
  473            fireDrillData.close();
 
  478        trgQueue.push(trigger_final);
 
  484        if ( trgQueue.size() >= (
unsigned) queueLength ) {
 
  486          while ( trgWindow.size() <= (
unsigned) windowLength ) {
 
  488            trigger_type pending = trgQueue.top();
 
  490            if ( trgWindow.size() == 0 || pending > trgWindow.back() ) {
 
  492              trgWindow.push_back( pending );
 
  507          NOTICE(
"Filling trigger queue: " << trgQueue.size() << 
"/" << queueLength << 
'\r');
 
  511      else if ( inputFileName != 
"" ) {
 
  514        if ( trgQueue.size() > 0 ) {
 
  515          while ( trgQueue.size() > 0 ) {
 
  516            trgWindow.push_back(trgQueue.top());
 
  520        else if ( trgWindow.size() < (
unsigned) windowLength ) {
 
  521          i = numberOfTimeouts;
 
  525        NOTICE(
"timeout " << setw(3) << i << endl);
 
  530      if (trgWindow.size() >= (
unsigned) windowLength) {
 
  537        int trg_cc_counts   = 0;
 
  538        int trg_cc_modules  = 0;
 
  541        int trg_ev_counts   = 0;
 
  542        int trg_ev_modules  = 0;
 
  550        int trg_cc_counts_nofakes   = 0;
 
  551        int trg_cc_modules_nofakes  = 0;
 
  554        int trg_ev_counts_nofakes   = 0;
 
  555        int trg_ev_modules_nofakes  = 0;
 
  559        for (
int its = 0; its < windowLength; its++) {
 
  561          const int frame_index = trgWindow[its].frameIndex;
 
  564          if (veto.count(frame_index)) {
 
  565            vetoSet = veto.at(frame_index);
 
  571          set<int> cc_vec = trgWindow[its].getModules(F_M1);
 
  572          set<int> ev_vec = trgWindow[its].getModules(F_MV);
 
  578          for (
auto &trg: trgWindow[its]){
 
  580              if (!trg.getPeak().fake) trg_cc_counts_nofakes++;
 
  581              for (
auto &snc: trg){
 
  583                  cc_vec_nofakes.insert(snc.moduleID);
 
  588              if (!trg.getPeak().fake) trg_ev_counts_nofakes++;
 
  589              for (
auto &snc: trg){
 
  591                  ev_vec_nofakes.insert(snc.moduleID);
 
  597          cc_modules.insert(cc_vec.begin(), cc_vec.end());
 
  598          ev_modules.insert(ev_vec.begin(), ev_vec.end());
 
  600          cc_modules_nofakes.insert(cc_vec_nofakes.begin(), cc_vec_nofakes.end());
 
  601          ev_modules_nofakes.insert(ev_vec_nofakes.begin(), ev_vec_nofakes.end());
 
  603          trg_cc_counts += count_if(trgWindow[its].begin(), trgWindow[its].end(), F_M1);
 
  604          trg_ev_counts += count_if(trgWindow[its].begin(), trgWindow[its].end(), F_MV);
 
  607          for (
auto &trg: trgWindow[its]){
 
  608            auto sn_candidate = trg.getPeak();
 
  609            if (F_MV_BDT(sn_candidate)){
 
  610              multiplicities.push_back(sn_candidate.multiplicity);
 
  611              observables.push_back(sn_candidate.total_ToT);
 
  612              observables.push_back(sn_candidate.deltaT);
 
  613              observables.push_back(sn_candidate.mean_dir_norm);
 
  614              observables.push_back(sn_candidate.mean_dir_ctheta);
 
  616              if (!sn_candidate.fake){
 
  617                multiplicities_nofakes.push_back(sn_candidate.multiplicity);
 
  618                observables_nofakes.push_back(sn_candidate.total_ToT);
 
  619                observables_nofakes.push_back(sn_candidate.deltaT);
 
  620                observables_nofakes.push_back(sn_candidate.mean_dir_norm);
 
  621                observables_nofakes.push_back(sn_candidate.mean_dir_ctheta);
 
  627        trg_cc_modules = cc_modules.size();
 
  628        trg_ev_modules = ev_modules.size();
 
  630        trg_cc_modules_nofakes = cc_modules_nofakes.size();
 
  631        trg_ev_modules_nofakes = ev_modules_nofakes.size();
 
  635        int currentFrame             = trgWindow[0].frameIndex;
 
  638        trgWindow.pop_front();
 
  642        ++stats[trg_cc_counts];
 
  646        int    activeModules =  -1;
 
  647        double detectorRate  = 0.0;
 
  649        if (!rates.empty()          &&
 
  650            rates.count(currentFrame)) {
 
  655               p != rates.at(currentFrame).end(); p++ ) {
 
  657            detectorRate  += p->second;
 
  659            activeModules += (p->second > 0);
 
  664          activeModules = timesliceSize;
 
  671        string daq_time = 
to_string(currentTime);
 
  688        string msg = jd.dump();
 
  695        if (multiplicities.size() != multiplicities_nofakes.size()){
 
  715        if (outputFileName != 
""){
 
  716          if (nWrittenEntries < nEntries || nEntries == -1) {
 
  738        if ( (counter_live_ts % ((
int)(statPrintInterval_s / frameTime_s)) == 0 ) ) {
 
  740          double livetime = counter_live_ts * frameTime_s;
 
  746          NOTICE(
"=> discarded out-of-order timeslices = " << counter_lost_ts << endl);
 
  748          if (summaryFile != 
"") {
 
  749            ofstream of(summaryFile.c_str());
 
  760    ERROR(error.what() << endl);
 
  763  if (outputFileName != 
"") { 
outputFile.close(); }