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);