58{
   62 
   65 
   66  string                          inputFile;
   68  string                          detectorFile;
   69  string                          pmtFile;
   70  bool                            writeFits;
   71  
   72  double                          Wmin              =   5e3;                
   73  double                          LeftMargin        =  10.0;                
   74  double                          RightMargin       =  10.0;                
   75  double                          gradientThreshold =  -0.005;              
   76                                                                            
   81  
   83  string                          option;
   84  
   85  string                          regexp;
   87 
   88  try { 
   89 
   91    
   98    
   99    JParser<> zap(
"Auxiliary program to fit time-over-threshold distributions.");
 
  100    
  101    zap[
'f'] = 
make_field(inputFile,         
"input file (output from JCalibrateToT).");
 
  103    zap[
'a'] = 
make_field(detectorFile,      
"detector file.");
 
  104    zap[
'P'] = 
make_field(pmtFile,           
"specify PMT file name that can be given to JTriggerEfficiency.") = 
"";
 
  105    zap[
'w'] = 
make_field(writeFits,         
"write fit results.");
 
  106    zap[
'O'] = 
make_field(option,            
"ROOT fit options, see TH1::Fit")                                 = 
"";
 
  108    zap[
'x'] = 
make_field(ToTfitRange,       
"ROOT fit range (time-over-threshold).")                          = 
JRange_t(0.0, 35.0);    
 
  111 
  112    zap(argc, argv);
  113  }
  114  catch(const exception &error) {
  115    FATAL(error.what() << endl);
 
  116  }
  117 
  118 
  119  
  120  
  121  
  122 
  124 
  125  try { 
  127  }
  130  }
  131 
  132 
  134 
  135  if (!pmtFile.empty()) {
  136 
  137    try {
  138      parametersMap.
load(pmtFile.c_str()); 
 
  139    }
  141  }
  142 
  143  
  144  if (option.find('R') == string::npos) { option += 'R'; }
  145  if (option.find('S') == string::npos) { option += 'S'; }
  147 
  148 
  149  TFile* in = TFile::Open(inputFile.c_str(), "exist");
  150 
  151  if (in == NULL || !in->IsOpen()) {
  152    FATAL(
"File: " << inputFile << 
" not opened." << endl);
 
  153  }
  154 
  155 
  156  TH2D gain("gain", NULL,
  157            100,  0.0, 2.0,
  158            100,  0.0, 1.0);
  159  TH1D chi2("chi2", NULL, 100,  0.0, 5.0);
  160 
  162 
  165  }
  166  
  168 
  169  
  170  
  171  
  172 
  173  for (JDetector::iterator module = 
detector.begin(); module != 
detector.end(); ++module) {
 
  174 
  175    NOTICE(
"Module " << setw(10) << module->getID() << 
' ' << module->getLocation() << endl);
 
  176 
  177    if (module->empty()) {
  178      continue;
  179    }
  180 
  181    
  182    
  183    
  184 
  186 
  187    if (h2s == NULL) {
  188 
  189      WARNING(
"No histogram " << module->getID() << 
"; skip fit." << endl);
 
  190 
  191      continue;
  192    }
  193 
  194    const double ny   = h2s->GetYaxis()->GetNbins();
  195    const double ymin = h2s->GetYaxis()->GetXmin();
  196    const double ymax = h2s->GetYaxis()->GetXmax();
  197 
  198    TH1D chi2_1d      (
MAKE_CSTRING(module->getID() << 
".1chi2"),       NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS-0.5);
 
  199    TH1D gain_1d      (
MAKE_CSTRING(module->getID() << 
".1gain"),       NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS-0.5);
 
  200    TH1D gainspread_1d(
MAKE_CSTRING(module->getID() << 
".1gainspread"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS-0.5);
 
  201    
  202    for (int ix = 1; ix <= h2s->GetXaxis()->GetNbins(); ++ix) {
  203 
  205 
  206      const string name = 
MAKE_STRING(module->getID()    << 
'.' << 
FILL(2,
'0') <<
 
  208 
  209      DEBUG(
"Processing histogram " << name << endl);
 
  210 
  211      TH1D h1(name.c_str(), NULL, ny, ymin, ymax); 
  212 
  213      h1.Sumw2();
  214      
  215      for (int iy = h2s->GetNbinsY(); iy >= 1; --iy) {
  216 
  217        const double w = h1.GetBinWidth (iy);
  218        const double y = h2s->GetBinContent(ix, iy);
 
  219  
  220        h1.SetBinContent(iy, y/w);
  221        h1.SetBinError  (iy, sqrt(y)/w);
  222      }
  223 
  225      
  226      const double weight = h1.Integral(h1.FindBin(range.getLowerLimit()),
  227                                        h1.FindBin(range.getUpperLimit()));
  228      
  229      if (weight <= Wmin) {
  230 
  231        WARNING(
"Insufficient histogram entries for PMT "  << 
id <<
 
  232                "(" << weight << " < " << Wmin << "); skip fit." << endl);
  233        
  234        if (writeFits) {
  236        }
  237        
  238        continue;
  239      }
  240 
  241      
  242      
  243      
  244 
  245      double max     = 0.0;
  247 
  249 
  251            RIGHT(10) << 
"threshold" << 
RIGHT(10) << 
"Mode"   << 
RIGHT(10) << 
"Max" << endl);
 
  252      
  253      for (int i = h1.GetBinCenter(ny-1);
  254               i > h1.GetBinCenter(h1.FindBin(parameters.
mean_ns + parameters.
sigma_ns));
 
  255             --i) {
  256 
  257         const double x = h1.GetBinCenter (i);
 
  258         const double y = h1.GetBinContent(i);
 
  259 
  260         const double gradient = ( (h1.GetBinContent(i-1) - h1.GetBinContent(i+1)) /
  261                                   (h1.GetBinCenter (i+1) - h1.GetBinCenter (i-1)) );
  262 
  264               FIXED(10,1) << -fabs(gradientThreshold) * h1.Integral() << 
FIXED(10,1) << ToTmode << 
FIXED(10,1) << max << endl);
 
  265 
  266 
  267         if (y > max) {
  268 
  271           
  272         } else if (gradient < -fabs(gradientThreshold) * h1.Integral()) {
  273 
  274           break;
  275         }
  276      }
  277      
  278      
  279      
  280      
  281 
  282      if (!range.is_valid()) {
  283        range.setRange(ToTmode - LeftMargin,
  284                       ToTmode + RightMargin);
  285      }
  286      
  287      range.setRange(std::max(h1.GetXaxis()->GetXmin(), range.getLowerLimit()),
  288                     std::min(h1.GetXaxis()->GetXmax(), range.getUpperLimit()));
  289 
  291 
  292      
  293      
  294      
  295 
  296      JFitToT fit(parameters, range);
 
  297      
  298      setParLimits(fit, fit.getModelParameter(&JFitToT::JFitToTParameters::gain),
 
  299                   gainLimits.getLowerLimit(), gainLimits.getUpperLimit());
  300      setParLimits(fit, fit.getModelParameter(&JFitToT::JFitToTParameters::gainSpread),
 
  301                   gainSpreadLimits.getLowerLimit(), gainSpreadLimits.getUpperLimit());
  302      
  303      const double initGain       = fit.getCPU().getNPE(ToTmode);
  304      const double initGainSpread = initGain / 3.0;
  305      
  306      if (!gainLimits(initGain)) { 
  307        
  308        WARNING(
"Invalid initial gain for PMT " << 
id << 
"; set default values." << endl);
 
  309        
  310        parameters.
gain       = gainLimits      .constrain(initGain);
 
  311        parameters.
gainSpread = gainSpreadLimits.constrain(initGainSpread);
 
  312 
  313        if (writeFits) {
  315        }
  316 
  317        continue;
  318      }
  319      
  320      fit.gain       = initGain;
  321      fit.gainSpread = initGainSpread;
  322      
  323      const TFitResultPtr 
result = fit(h1, option);
 
  324 
  325      if (
result.Get() == NULL) {
 
  326        FATAL(
"Invalid TFitResultPtr " << h1.GetName() << endl);
 
  327      }
  328 
  330 
  331        WARNING(
"Fit failure for PMT " << 
id << 
"; set initialization values." << endl);
 
  332          
  333        h1.GetListOfFunctions()->Clear();
  334 
  335        parameters.
gain       = initGain;
 
  337 
  338        if (writeFits) {
  340        }
  341 
  342        continue;
  343      }
  344 
  345      if ((ymin < range.getLowerLimit()  || ymax > range.getUpperLimit()) &&
  346          (option.find("0") == string::npos && option.find("N") == string::npos)) {
  347        
  348        
  349        
  351                          &fit,
  353                          ymin,
  355                          JFitToT::getNumberOfModelParameters());
  356        f1->SetParameters(fit.GetParameters());
 
  357        f1->SetLineStyle(kDotted);
 
  359 
  360        h1.GetListOfFunctions()->Add(f1);
  361      }
  362 
  363      
  364 
  365      const double reducedChi2 = 
result->Chi2() / 
result->Ndf();
 
  366 
  369      
  370      chi2_1d.      SetBinContent(ix, reducedChi2);
  371      gain_1d.      SetBinContent(ix, values.gain);
  372      gain_1d.      SetBinError  (ix, errors.gain);
  373      gainspread_1d.SetBinContent(ix, values.gainSpread);
  374      gainspread_1d.SetBinError  (ix, errors.gainSpread);
  375      
  376      gain.Fill(fit.gain, fit.gainSpread);
  377      chi2.Fill(TMath::Log10(reducedChi2));
  378      
  379      NOTICE(
"PMT " << 
id << 
" chi2 / NDF " << 
result->Chi2() << 
' ' << 
result->Ndf() << endl);
 
  380      
  381      parameters.
gain       = fit.gain;
 
  383        
  384      if (writeFits) {
  386      }
  387    }
  388 
  389    if (writeFits) {
  393    }
  394  }
  395 
  396  {
  398 
  400 
  401      const JMeta* meta = in.next();
 
  402 
  403      buffer.push_back(*meta);
  404 
  406    }
  407 
  408    for (vector<JMeta>::const_reverse_iterator i = buffer.rbegin(); i != buffer.rend(); ++i) {
  410    }
  411  }
  412 
  415  }
  416 
  417  
  418  if (pmtFile != "") {
  419    parametersMap.
store(pmtFile.c_str());
 
  420  }
  421 
  424 
  426}
#define DEBUG(A)
Message macros.
 
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
 
#define MAKE_CSTRING(A)
Make C-string.
 
#define MAKE_STRING(A)
Make string.
 
#define gmake_property(A)
macros to convert (template) parameter to JPropertiesElement object
 
Auxiliary class for map of PMT parameters.
 
Data structure for PMT parameters.
 
double sigma_ns
time-over-threshold standard deviation of threshold-band hits [ns]
 
double gainSpread
gain spread [unit]
 
double mean_ns
mean time-over-threshold of threshold-band hits [ns]
 
double saturation
saturation [ns]
 
Utility class to parse parameter values.
 
Utility class to parse command line options.
 
Object reading from a list of files.
 
virtual bool hasNext() override
Check availability of next element.
 
const JPolynome f1(1.0, 2.0, 3.0)
Function.
 
static const char *const _2SToT
Histogram naming.
 
static const double FITTOT_GAINSPREAD_MAX
Default maximal gain spread.
 
static const std::string FITTOT_FNAME
 
static const std::string FITTOT_SUFFIX
 
static const double FITTOT_GAIN_MAX
Default maximal gain.
 
static const double FITTOT_GAIN_MIN
Default minimal gain.
 
static const double FITTOT_GAINSPREAD_MIN
Default minimal gain spread.
 
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
 
const double TIME_OVER_THRESHOLD_NS
Specification for time-over-threshold corresponding to a one photo-electron pulse.
 
std::string replace(const std::string &input, const std::string &target, const std::string &replacement)
Replace tokens in string.
 
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
 
bool setParLimits(TF1 &f1, const Int_t index, Double_t xmin, Double_t xmax)
Set fit parameter limits.
 
KM3NeT DAQ data structures and auxiliaries.
 
static const char WILDCARD
 
Auxiliary data structure for sequence of same character.
 
Auxiliary data structure for floating point format specification.
 
Type definition of range.
 
Fit parameters for two-fold coincidence rate due to K40.
 
Parametrisation of time-over-threshold distribution.
 
Double_t getValue(const Double_t *x, const Double_t *par)
Get rate as a function of the fit parameters.
 
void store(const char *file_name) const
Store to output file.
 
void load(const char *file_name)
Load from input file.
 
Empty structure for specification of parser element that is initialised (i.e. does not require input)...