48 static const char* rates_t =
"rates";
49 static const char* count_t =
"counts";
50 static const char* tails_t =
"tails";
51 static const char* rndms_t =
"randoms";
56 static const double ToTmax_ns = std::numeric_limits<KM3NETDAQ::JDAQHit::JTOT_t>::max();
79 JHistogram(TH2D* __h2s,
104 int main(
int argc,
char **argv)
115 JMultipleFileScanner<JDAQTimesliceTypes_t> inputFile;
120 JRange<double> rateRange_Hz;
121 JRange<double> totRange_ns;
122 JRange<double> Tail_ns;
123 JRange<int> multiplicity;
125 JROOTClassSelector selector;
127 JPreprocessor option;
132 JParser<> zap(
"Auxiliary program to determine PMT parameters from K40 data.");
134 zap[
'f'] =
make_field(inputFile,
"input file.");
136 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
137 zap[
'a'] =
make_field(detectorFile,
"detector file.");
138 zap[
'T'] =
make_field(TMax_ns,
"time window [ns].") = 20.0;
139 zap[
'V'] =
make_field(rateRange_Hz,
"PMT rate range [Hz].") = JRange<double>(0.0, 20.0e3);
140 zap[
't'] =
make_field(totRange_ns,
"PMT time-over-threshold range [ns].") = JRange<double>(0.0, ToTmax_ns);
141 zap[
'b'] =
make_field(background,
"background estimation method.") = rates_t, count_t, tails_t, rndms_t;
142 zap[
'B'] =
make_field(Tail_ns,
"time window used for background estimation.") = JRange<double>(15.0, 20.0);
143 zap[
'M'] =
make_field(multiplicity,
"multiplicity range of hits on DOM.") = JRange<int>(2, 31);
144 zap[
'D'] =
make_field(deadTime_us,
"L1 dead time (us)") = 0.0;
145 zap[
'C'] =
make_field(selector,
"timeslice selector, e.g. JDAQTimesliceL1.") = getROOTClassSelection<JDAQTimesliceTypes_t>();
146 zap[
'O'] =
make_field(option,
"hit pre-processing option.") = JPreprocessor::getOptions();
151 catch(
const exception &error) {
152 FATAL(error.what() << endl);
161 if (selector == JDAQTimesliceL2::Class_Name() ||
162 selector == JDAQTimesliceSN::Class_Name()) {
163 FATAL(
"Option -C <selector> " << selector <<
" not compatible with calibration method." << endl);
166 if (selector == JDAQTimeslice ::Class_Name() ||
167 selector == JDAQTimesliceL1::Class_Name()) {
174 catch(
const JException& error) {
175 FATAL(
"No trigger parameters from input:" << error.what() << endl);
178 if ((selector == JDAQTimeslice ::Class_Name() && parameters.
writeL1.
prescale > 0) ||
179 (selector == JDAQTimesliceL1::Class_Name())) {
182 FATAL(
"Option -T <TMax_ns> = " << TMax_ns <<
" is larger than in the trigger " << parameters.
TMaxLocal_ns << endl);
185 if (background == rndms_t ||
186 background == count_t) {
187 FATAL(
"Option -C <selector> " << selector <<
" incompatible with option -b <background> " << background << endl);
192 if (!multiplicity.is_valid() || multiplicity.getLowerLimit() < 2) {
193 FATAL(
"Invalid option -M <multiplicity> " << multiplicity << endl);
196 if (!totRange_ns.is_valid()) {
197 FATAL(
"Invalid option -t <totRange_ns> " << totRange_ns << endl);
200 if (background == tails_t) {
202 if (!Tail_ns.is_valid()) {
203 FATAL(
"Invalid option -B <Tail_ns> " << Tail_ns << endl);
206 if (Tail_ns.getUpperLimit() > TMax_ns) {
207 FATAL(
"Invalid option -B <Tail_ns> " << Tail_ns <<
"; upper limit larger than option -T <TMax_ns> " << TMax_ns << endl);
218 load(detectorFile, detector);
220 catch(
const JException& error) {
224 if (detector.empty()) {
225 FATAL(
"Empty detector." << endl);
228 const JModuleRouter router(detector);
229 JSummaryRouter summaryRouter;
238 t0.push_back(i * 2 * TMax_ns);
245 const JPMTAnalogueSignalProcessor cpu;
248 const double RTU = (cpu.getIntegralOfProbability(cpu.getNPE(totRange_ns.getLowerLimit()), cpu.getNPE(totRange_ns.getUpperLimit()), NPE)
250 cpu.getIntegralOfProbability(cpu.getNPE(0.0), cpu.getNPE(ToTmax_ns), NPE));
265 weights_hist.GetXaxis()->SetBinLabel(2,
WS_t);
266 weights_hist.GetXaxis()->SetBinLabel(3,
WB_t);
268 const int nx = combinatorics.getNumberOfPairs();
269 const double xmin = -0.5;
270 const double xmax = nx - 0.5;
272 const double ymin = -floor(TMax_ns) + 0.5;
273 const double ymax = +floor(TMax_ns) - 0.5;
274 const int ny = (int) ((ymax - ymin) / 1.0);
277 for (JDetector::iterator module = detector.begin(); module != detector.end(); ++module) {
279 const JModuleAddress& address = router.getAddress(module->getID());
281 NOTICE(
"Booking histograms for module " << module->getID() << endl);
283 zmap[address.first] = JHistogram(
new TH2D(
MAKE_CSTRING(module->getID() <<
_2S), NULL, nx, xmin, xmax, ny, ymin, ymax),
289 JTreeScanner<JDAQSummaryslice, JDAQEvaluator> summaryFile(inputFile);
291 typedef JHitR0 hit_type;
292 typedef JSuperFrame2D<hit_type> JSuperFrame2D_t;
293 typedef JSuperFrame1D<hit_type> JSuperFrame1D_t;
295 const JMatchL0<hit_type> match(TMax_ns);
297 const double deadTime_ns = deadTime_us * 1e3;
299 JObjectMultiplexer<JDAQTimesliceTypes_t, JDAQTimeslice> in(inputFile, selector);
303 for ( ; in.hasNext() && counter != inputFile.getLimit(); ++counter) {
305 STATUS(
"event: " << setw(10) << counter <<
'\r');
DEBUG(endl);
309 if (background == rates_t) {
311 const Long64_t index = summaryFile.find(*timeslice);
317 summaryRouter.update(summaryFile.getEntry(index));
319 if (timeslice->
getFrameIndex() != summaryRouter.getFrameIndex()) {
321 ERROR(
"Frame indices do not match "
322 <<
"[counter=" << counter <<
"]"
324 <<
"[summaryslice=" << summaryRouter.getFrameIndex() <<
"]" << endl);
329 FATAL(
"ROOT TTrees not aligned; Run number " << timeslice->
getRunNumber() << endl);
334 for (JDAQTimeslice::const_iterator frame = timeslice->begin(); frame != timeslice->end(); ++frame) {
336 if (router.hasModule(frame->getModuleID())) {
347 if (background == count_t) {
355 }
else if (background == rates_t) {
357 if (!summaryRouter.hasSummaryFrame(frame->getModuleID())) {
358 FATAL(
"Summary frame not found " << timeslice->
getFrameIndex() <<
":" << frame->getModuleID() << endl);
361 const JDAQSummaryFrame& summary_frame = summaryRouter.getSummaryFrame(frame->getModuleID());
366 rate_Hz[i] = RTU * summary_frame.
getRate(i);
393 const JModuleAddress& address = router.getAddress(frame->getModuleID());
394 const JModule& module = detector.getModule(address);
396 combinatorics.configure(module.size());
398 combinatorics.sort(JPairwiseComparator(module));
400 TH2D* h2s = zmap[address.first].h2s;
401 TH1D* h1b = zmap[address.first].h1b;
402 TH1D* h1L = zmap[address.first].h1L;
408 for (
size_t i = 0; i < combinatorics.getNumberOfPairs(); ++i) {
410 const int pmt1 = combinatorics.getPair(i).first;
411 const int pmt2 = combinatorics.getPair(i).second;
413 if (!veto[pmt1] && rateRange_Hz(rate_Hz[pmt1]) &&
414 !veto[pmt2] && rateRange_Hz(rate_Hz[pmt2]) ) {
424 JSuperFrame2D_t& buffer = JSuperFrame2D_t::demultiplex(*frame, module);
426 buffer.preprocess(option, match);
428 for (JSuperFrame2D_t::iterator i = buffer.begin(); i != buffer.end(); ++i) {
430 const int pmt = i->getPMTAddress();
432 if ( veto[pmt] || !rateRange_Hz(rate_Hz[pmt]) ) {
437 JSuperFrame1D_t& data = JSuperFrame1D_t::multiplex(buffer);
441 DEBUG(
"Number of hits " << timeslice->
getFrameIndex() <<
":" << frame->getModuleID() <<
' ' << frame->size() <<
' ' << data.size() << endl);
450 double t1 = -numeric_limits<double>::max();
456 while (++q != data.end() && q->getT() - p->getT() <= TMax_ns) {}
460 if (multiplicity(N)) {
462 if (p->getT() > t1 + deadTime_ns) {
467 if (totRange_ns( __p->getToT()) && totRange_ns(__q->getToT())) {
468 h2s->Fill((
double) combinatorics.getIndex(__p->getPMT(),__q->getPMT()),
469 JCombinatorics::getSign(__p->getPMT(),__q->getPMT()) * (__q->getT() - __p->getT()));
484 if (background == rndms_t) {
487 *i = hit_type(i->getPMT(), JHit(i->getT() + t0[i->getPMT()], i->getToT()));
490 sort(data.begin(), data.end());
496 while (++q != data.end() && q->getT() - p->getT() <= TMax_ns) {}
500 if (multiplicity(N)) {
505 if (totRange_ns(__p->getToT()) && totRange_ns(__q->getToT())) {
506 h1b->Fill((
double) combinatorics.getIndex(p->getPMT(),q->getPMT()), 1.0);
515 }
else if (background == rates_t ||
516 background == count_t) {
522 const Double_t
R1 = rate_Hz[i];
524 if (!veto[i] && rateRange_Hz(
R1)) {
532 const Double_t
R1 = rate_Hz[i];
533 const Double_t R2 = rate_Hz[
j];
535 if (!veto[i] && rateRange_Hz(
R1) &&
536 !veto[
j] && rateRange_Hz(R2)) {
539 const double ED = (Rs - rate_Hz[i] - rate_Hz[
j]) * 2 * TMax_ns * 1e-9;
540 const double E1 = rate_Hz[i] * 2 * TMax_ns * 1e-9;
541 const double E2 = rate_Hz[
j] * 2 * TMax_ns * 1e-9;
545 multiplicity.getLowerLimit(),
546 multiplicity.getUpperLimit()) *
getFrameTime() / (2*TMax_ns);
548 h1b->Fill((
double) combinatorics.getIndex(i,
j), N);
558 if (background == tails_t ) {
562 TH2D* h2s = hist->h2s;
563 TH1D* h1b = hist->h1b;
571 int k = combinatorics.getIndex(i,
j);
573 for (
int l = 1; l <= h2s->GetYaxis()->GetNbins(); ++l) {
575 const Double_t dt = h2s->GetYaxis()->GetBinCenter(l) ;
577 if (Tail_ns(fabs(dt))) {
578 Y += h2s->GetBinContent(k+1,l);
579 W += h2s->GetBinError(k+1,l) * h2s->GetBinError(k+1,l);
584 h1b->SetBinContent(k+1, Y / N * (2.0*TMax_ns) / ((ymax - ymin)/ny) );
585 h1b->SetBinError (k+1, sqrt(W/N) * (2.0*TMax_ns) / ((ymax - ymin)/ny) );
596 weights_hist.Fill(
WS_t, (ymax - ymin)/ny);
597 weights_hist.Fill(
WB_t, 2.0*TMax_ns);
604 weights_hist.Write() ;