52int main(
int argc, 
char **argv)
 
   63  JLimit_t& numberOfEvents =          inputFile.getLimit();
 
   74  bool               monitorOccupancy;
 
   79    JParser<> zap(
"Auxiliary program to estimate PMT and hit multiplicities.");
 
   91    zap[
'F'] = 
make_field(filterLevel, 
"0 = raw data; 1 = filtered data; 2+ = only clean frames") = 1;
 
   92    zap[
'D'] = 
make_field(twoDim, 
"2D mode for background subtraction");
 
   93    zap[
'O'] = 
make_field(monitorOccupancy, 
"produces 2D PMT vs multiplicity plots");
 
   94    zap[
'j'] = 
make_field(notJoin, 
"do not join consecutive hits on same PMT (diagnostic purpose)");
 
   98  catch(
const exception &error) {
 
   99    FATAL(error.what() << endl);
 
  108  bool hasTriggerParameters = 
true;
 
  112    NOTICE(
"Get trigger parameters from input." << endl);
 
  115    ERROR(
"No trigger parameters from input." << endl);
 
  116    hasTriggerParameters = 
false;
 
  123  if (hasTriggerParameters) {
 
  127    if (parameters.writeL1.prescale > 0  && (selector == 
"JDAQTimeslice" || selector == 
"JDAQTimesliceL1") &&
 
  128        parameters.TMaxLocal_ns < TMax_ns) {
 
  129      FATAL(
"TMax_ns (-T) " << TMax_ns << 
" ns is larger than in the trigger " << parameters.TMaxLocal_ns << 
" ns." << endl);
 
  132    if (selector == 
"JDAQTimeslice") {
 
  134      prescale = (parameters.writeL1.prescale != 0) ? parameters.writeL1.prescale : parameters.writeL0.prescale;
 
  137    if (selector == 
"JDAQTimesliceL0") {
 
  138      prescale = parameters.writeL0.prescale;
 
  141    if (selector == 
"JDAQTimesliceL1") {
 
  142      prescale = parameters.writeL1.prescale;
 
  145    if (selector == 
"JDAQTimesliceSN") {
 
  146      prescale = parameters.writeSN.prescale;
 
  152    FATAL(
"[R] According to trigger parameters, the " << selector << 
" stream should be empty.");
 
  154    NOTICE(
"[R] Prescale factor is " << prescale << endl);
 
  158    FATAL(
"Invalid time over threshold " << totVeto_ns   << endl); 
 
  175    FATAL(
"Empty detector." << endl);
 
  192  NOTICE(
"[R] Tmax       [ns] "       << TMax_ns               << endl);
 
  193  NOTICE(
"[R] Rate range [Hz] "       << rateVeto_Hz           << endl);
 
  194  NOTICE(
"[R] ToT range  [ns] "       << totVeto_ns            << endl);
 
  195  NOTICE(
"[R] Timeslice stream      " << selector              << endl);
 
  196  NOTICE(
"[R] Detector file has " << detSize << 
" DOMs." << endl);
 
  203  TH1D* h_livetime = 
new TH1D(
"LiveTime", 
"Livetime", 1 + detSize, 0.0, 1.0 + detSize); 
 
  206  h_livetime->GetXaxis()->SetBinLabel(ibin++, 
"Nominal");
 
  207  for (JDetector::iterator module = 
detector.begin(); module != 
detector.end(); ++module) {
 
  208    h_livetime->GetXaxis()->SetBinLabel(ibin++, TString(
getLabel(*module)));
 
  211  h_livetime->GetYaxis()->SetTitle(
"Livetime (s)");
 
  216  const double xmin = -0.5;
 
  217  const double xmax = nx - 0.5;
 
  221  JManager_t 
H(
new TH1D(
"%_H", NULL, nx, xmin, xmax)); 
H->Sumw2();
 
  222  JManager_t P(
new TH1D(
"%_P", NULL, nx, xmin, xmax)); P->Sumw2();
 
  224  JManager2D_t HT(
new TH2D(
"%_HT", NULL, nx, xmin, xmax, 100, -TMax_ns, +TMax_ns));
 
  226  TH2D* CO_proto = 
new TH2D(
"%_CO", NULL, NUMBER_OF_PMTS, 0.5, 0.5 + NUMBER_OF_PMTS, NUMBER_OF_PMTS, -0.5, -0.5 + NUMBER_OF_PMTS);
 
  228  if (monitorOccupancy) {
 
  233  JManager2D_t CO(CO_proto);
 
  236  const int sn_mul_min = 6;
 
  237  TH1D* time_distr = 
new TH1D(
"T_distr", 
"Coincidence (M > 6) distribution in timeslice", 100, 0, 1e8); 
 
  252  int treeMismatchCount = 0;
 
  271  bool   hasMCHeader   = true ;
 
  272  bool   isMupage      = 
false;
 
  273  double liveTimeMC    = 0    ;
 
  274  double liveTimeMCErr = 0    ;
 
  285  NOTICE(
"[R] File source is " << (hasMCHeader ? 
"MC" : 
"DAQ") << 
"." << endl);
 
  289    if (liveTimeMC > 0) {
 
  291      NOTICE(
"[R] mupage live time is (" << liveTimeMC << 
" +/- " << liveTimeMCErr << 
") s." << endl);
 
  293      NOTICE(
"[R] aanet header found but mupage live time is zero. Likely not a mupage file.");
 
  301  if (summaryFile.hasNext()) { 
 
  302    runNumber = summaryFile.getEntry(0)->getRunNumber();
 
  303    NOTICE(
"[R] Processing run #" << runNumber << endl);
 
  304    summaryFile.rewind();
 
  311  for ( ; in.
hasNext() && counter != inputFile.getLimit(); ++counter) {
 
  313    STATUS(
"Entry: " << setw(10) << counter  << 
'\r');
 
  316    const Long64_t          index     = summaryFile.find(*timeslice);
 
  317    JDAQSummaryslice*       summary   = (index != -1 ? summaryFile.getEntry(index) : NULL);
 
  319    summaryRouter.
update(summary);
 
  322    if (summary != NULL) {
 
  325        ERROR(
"[R>T] Frame indices do not match [counter=" << counter << 
", timeslice=" << timeslice->
getFrameIndex() << 
", summaryslice=" << summary->
getFrameIndex() << 
"]" << endl);
 
  326        if (treeMismatchCount > 1) {
 
  327          FATAL(
"ROOT TTrees not aligned. Run #" << runNumber << endl);
 
  336    for (JDAQTimeslice::const_iterator super_frame = timeslice->begin(); super_frame != timeslice->end(); ++super_frame) {
 
  342      int moduleID = super_frame->getModuleID();
 
  358      if (summary == NULL) { 
 
  359        WARNING(
"[R>T>F] Missing summary for timeslice." << endl);
 
  374        if (!summaryRouter.
hasSummaryFrame(super_frame->getModuleIdentifier())) {
 
  375          summaryRouter.print(cout); 
 
  376          FATAL(
"[R>D>F] Summary frame not found, module = " << super_frame->getModuleID() << endl);
 
  378          summary_frame = summaryRouter.
getSummaryFrame(super_frame->getModuleID());
 
  383          rate_Hz[i] = summary_frame.
getRate(i);
 
  397          WARNING(
"[R>D>F] DAQ status not okay in timeslice #" << timeslice->
getFrameIndex() << 
", DOM=" << super_frame->getModuleID() << endl);
 
  402      bool moduleLiveTime = 0;
 
  405      for (vector<double>::const_iterator r = rate_Hz.begin(); !moduleLiveTime && r != rate_Hz.end(); ++r) {
 
  413      int frame_URV_count = 0; 
 
  416        if ((veto[i] = (veto[i] || !rateVeto_Hz(rate_Hz[i])))) {
 
  421      count_HRV += frame_HRV_count;
 
  422      count_FAF += frame_FAF_count;
 
  423      count_URV += frame_URV_count;
 
  425      int frame_VETO_count = frame_HRV_count + frame_FAF_count + frame_URV_count;
 
  428      if (filterLevel >= 2 && frame_VETO_count > 0) {
 
  430        fill(veto.begin(), veto.end(), 
true);
 
  431      } 
else if (filterLevel >= 1 && frame_HRV_count + frame_FAF_count > 0) {
 
  439      if (muteChannel != -1) {
 
  442        int mute_VETO_count = 
 
  445          !rateVeto_Hz(rate_Hz[muteChannel]  );
 
  447        if (mute_VETO_count == frame_VETO_count) {
 
  449          fill(veto.begin(), veto.end(), 
false);
 
  452        veto[muteChannel] = 
true;
 
  459      const TString         moduleLabel   = 
getLabel(module);
 
  462      if (moduleLiveTime) {
 
  463        h_livetime->Fill(moduleLabel, 
getFrameTime() * 1e-9 * moduleLiveTime);
 
  470      JSuperFrame2D_t& buffer = JSuperFrame2D_t::demultiplex(*super_frame, router.
getModule(super_frame->getModuleID())); 
 
  473        for (JSuperFrame2D_t::iterator i = buffer.begin(); i != buffer.end(); ++i) {
 
  478      JSuperFrame1D_t& data = JSuperFrame1D_t::multiplex(buffer);
 
  480      filteredData.clear();
 
  482      for (vector<JHitR0>::const_iterator h = data.begin(); h != data.end(); ++h) {
 
  484        const int pmt = h->getPMT();
 
  488            rateVeto_Hz(rate_Hz[pmt]) &&
 
  489            totVeto_ns(h->getToT()) )     {
 
  490          filteredData.push_back(*h);
 
  496      if (filteredData.size() > 1) {
 
  498        TH1D* h_hit =  
H[moduleLabel];
 
  499        TH1D* h_pmt =  P[moduleLabel];
 
  501        TH2D* h2_hit = HT[moduleLabel];
 
  502        TH2D* h2_co  = CO[moduleLabel];
 
  504        sort(filteredData.begin(), filteredData.end());
 
  509        for (vector<JHitR0>::const_iterator p = filteredData.begin(); p != filteredData.end(); ) {
 
  511          vector<JHitR0>::const_iterator q = p;
 
  514          while (++q != filteredData.end() && q->getT() - p->getT() <= TMax_ns ) {}
 
  517          int hit_multiplicity = 
distance(p,q);
 
  519          for (vector<JHitR0>::const_iterator __p = p ; __p != q; ++__p ) { pmthit.insert(__p->getPMT()) ; }
 
  520          int pmt_multiplicity = pmthit.size() ;
 
  523          h_pmt->Fill(pmt_multiplicity);
 
  524          h_hit->Fill(hit_multiplicity);
 
  526          if (twoDim && hit_multiplicity > 1) { 
 
  527            const double W = 
factorial(hit_multiplicity, 2);
 
  528            for (vector<JHitR0>::const_iterator __p = p; __p != q; ++__p) {
 
  529              for (vector<JHitR0>::const_iterator __q = __p; ++__q != q; ) {
 
  531                h2_hit->Fill(hit_multiplicity, dt, 1.0/W);
 
  536          if (monitorOccupancy) {
 
  539              TString pmtLabel(pmtAddress.
toString());
 
  540              h2_co->Fill(pmt_multiplicity, pmtLabel, 1.0/pmt_multiplicity);
 
  545          if (hit_multiplicity >= sn_mul_min) {
 
  546            time_distr->Fill(p->getT());
 
  559  NOTICE(
"[R] " << counter << 
" timeslices processed." << endl);
 
  562    h_livetime->Scale(liveTimeMC / (
getFrameTime() * 1e-9 * counter * prescale));
 
  566  double nominalLiveTime = (isMupage ? liveTimeMC : counter * 
getFrameTime() * 1e-9) / prescale;
 
  567  h_livetime->Fill(
"Nominal", nominalLiveTime);
 
  571  int nLiveDOMs = 
H.size();
 
  584  if (monitorOccupancy) {
 
  590  double rate_HRV = count_HRV / (1.0 * counter);
 
  591  double rate_FAF = count_FAF / (1.0 * counter);
 
  592  double rate_URV = count_URV / (1.0 * counter);
 
  593  double biolumIndex = (rate_HRV + rate_FAF) / (nLiveDOMs * NUMBER_OF_PMTS);
 
  594  NOTICE(
"[R] Average HRV count per timeslice: " << rate_HRV << endl);
 
  595  NOTICE(
"[R] Average FIFO-almost-full count per timeslice: " << rate_FAF << endl);
 
  596  NOTICE(
"[R] Average user rate veto count per timeslice: " << rate_URV << endl);
 
  597  NOTICE(
"[R] " << 
H.size() << 
" DOMs were active in the run." << endl);
 
  598  NOTICE(
"[R] Bioluminescence proxy index: " << biolumIndex << endl);
 
  606  return (counter ? 0 : 1);