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