53{
   56 
   59  string          detectorFile;
   60  bool            overwriteDetector;
   61  string          function;
   63  string          option;
   65  double          WMin;
   69 
   70  try {
   71 
   72    JParser<> zap(
"Program to fit time-residuals histogram in output of JCalibrateMuon.cc.");
 
   73 
   74    zap[
'f'] = 
make_field(inputFile,         
"input files (output from JCalibrateMuon).");
 
   76    zap[
'a'] = 
make_field(detectorFile,      
"detector file.");
 
   77    zap[
'A'] = 
make_field(overwriteDetector, 
"overwrite detector file provided through '-a' with correct time offsets.");
 
   78    zap[
'F'] = 
make_field(function,          
"fit function")                                                   = gauss_t, landau_t, emg_t, breitwigner_t;
 
   80    zap[
'O'] = 
make_field(option,            
"ROOT fit option, see TH1::Fit.")                                 = 
"";
 
   82    zap[
'W'] = 
make_field(WMin,              
"minimal histogram contents.")                                    = 100.0;
 
   86 
   87    zap(argc, argv);
   88  }
   89  catch(const exception &error) {
   90    FATAL(error.what() << endl);
 
   91  }
   92 
   93 
   95    FATAL(
"Invalid fit range [ns] " << T_ns << endl);
 
   96  }
   97 
   99 
  100  try {
  102  }
  105  }
  106 
  108  
  110 
  113  else if (
target == string_t)
 
  115  else
  116    FATAL(
"No valid target; check option -R" << endl);
 
  117 
  118  if (option.find('S') == string::npos) { option += 'S'; }
  120 
  121  TH2D* h2 = NULL;
  122 
  123  for (vector<string>::const_iterator i = inputFile.begin(); i != inputFile.end(); ++i) {
  124 
  125    NOTICE(
"Processing " << *i << endl);
 
  126 
  127    TFile in(i->c_str(), "exist");
  128 
  129    if (!in.IsOpen()) {
  130      FATAL(
"File " << *i << 
" not opened." << endl);
 
  131    }
  132 
  133    TH2D* p = dynamic_cast<TH2D*>(in.Get(h2_t));
  134      
  135    if (p == NULL) {
  136      FATAL(
"File " << *i << 
" has no histogram <" << h2_t << 
">." << endl);
 
  137    }
  138 
  139    if (h2 == NULL)
  140      h2 = (TH2D*) p->Clone();
  141    else
  142      h2->Add(p);
  143 
  144    h2->SetDirectory(0);
  145 
  146    in.Close();
  147  }
  148 
  149  if (h2 == NULL) {
  150    FATAL(
"No histogram <" << h2_t << 
">." << endl);
 
  151  }
  152 
  153  
  154 
  155  struct result_type {
  156 
  157    result_type() :
  158      value(0.0),
  159      error(0.0)
  160    {}
  161 
  162    result_type(double value,
  163                double error) :
  164      value(value),
  165      error(error)
  166    {}
  167 
  168    double value;
  169    double error;
  170  };
  171 
  173 
  174  map_type zmap;
  175 
  176 
  177  
  178 
  179  const TAxis* x_axis = h2->GetXaxis();
  180  const TAxis* y_axis = h2->GetYaxis();
  181 
  182  TH1D h0("h0", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
  183  TH1D hc("hc", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
  184  TH1D hq("hq", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
  185 
  188 
  189  TH2D H2("detector", NULL,
  190          strings.size(), -0.5, strings.size() - 0.5,
  192 
  193  for (Int_t ix = 1; ix <= H2.GetXaxis()->GetNbins(); ++ix) {
  194    H2.GetXaxis()->SetBinLabel(ix, 
MAKE_CSTRING(strings.at(ix-1)));
 
  195  }
  196  for (Int_t iy = 1; iy <= H2.GetYaxis()->GetNbins(); ++iy) {
  198  }
  199 
  201 
  202  size_t counts = 0;
  203  size_t errors = 0;
  204  
  205  for (Int_t ix = 1; ix <= x_axis->GetNbins(); ++ix) {
  206 
  207    const int index = ix - 1; 
  208    const int id    = rpm->
getID(index);
 
  209 
  210    DEBUG(
"Bin " << setw(4) << ix << 
" -> " << setw(8) << 
id << endl);
 
  211 
  212    if (
ID != -1 && 
ID != 
id) {
 
  213      continue;
  214    }
  215 
  216    TH1D h1(
MAKE_CSTRING(
id << 
".1D"), NULL, y_axis->GetNbins(), y_axis->GetXmin(), y_axis->GetXmax());
 
  217 
  218    
  219    
  220    Double_t ymax   =  0.0;
  221    Double_t x0     =  0.0;       
  222    Double_t 
sigma  =  4.0;       
 
  223    Double_t W      =  0.0;
  224 
  225    for (Int_t iy = 1; iy <= y_axis->GetNbins(); ++iy) {
  226 
  227      h1.SetBinContent(iy,      h2->GetBinContent(ix,iy));
  228      h1.SetBinError  (iy, sqrt(h2->GetBinContent(ix,iy)));
  229 
  230      const Double_t 
x = h1.GetBinCenter (iy);
 
  231      const Double_t 
y = h1.GetBinContent(iy);
 
  232      
  234 
  235      if (y > ymax) {
  238      }
  239    }
  240 
  241    if (W <= WMin) {
  242 
  243      WARNING(
"Not enough entries for slice " << ix << 
' ' << W << 
"; skip fit." << endl);
 
  244      
  245      continue;
  246    } 
  247 
  248    ymax *= 0.9;
  249 
  252 
  253 
  255 
  256    if        (function == gauss_t) {
  257 
  258      f1 = 
new TF1(function.c_str(), 
"[0]*TMath::Gaus(x,[1],[2])");
 
  259 
  260      f1->SetParameter(0, 0.8*ymax);
 
  261      f1->SetParameter(1, x0);
 
  262      f1->SetParameter(2, sigma);
 
  263 
  264      f1->SetParError(0, sqrt(ymax) * 0.1);
 
  265      f1->SetParError(1, 0.01);
 
  266      f1->SetParError(2, 0.01);
 
  267 
  268    } else if (function == landau_t) {
  269 
  270      f1 = 
new TF1(function.c_str(), 
"[0]*TMath::Landau(x,[1],[2])");
 
  271 
  272      f1->SetParameter(0, 0.8*ymax);
 
  273      f1->SetParameter(1, x0);
 
  274      f1->SetParameter(2, sigma);
 
  275 
  276      f1->SetParError(0, sqrt(ymax) * 0.1);
 
  277      f1->SetParError(1, 0.01);
 
  278      f1->SetParError(2, 0.01);
 
  279    
  280    } else if (function == emg_t) {
  281      
  282      f1 = 
new TF1(function.c_str(), 
"[0]*TMath::Exp(0.5*[3]*(2.0*[1]+[3]*[2]*[2]-2.0*x))*TMath::Erfc(([1]+[3]*[2]*[2]-x)/(TMath::Sqrt(2.0)*[2]))");
 
  283 
  284      f1->SetParameter(0, 0.5*ymax);
 
  285      f1->SetParameter(1, x0 - sigma);
 
  286      f1->SetParameter(2, sigma);
 
  287      f1->SetParameter(3, 0.06);
 
  288 
  289      f1->SetParError(0, sqrt(ymax) * 0.1);
 
  290      f1->SetParError(1, 0.01);
 
  291      f1->SetParError(2, 0.01);
 
  292      f1->SetParError(3, 1.0e-4);
 
  293 
  294    } else if (function == breitwigner_t) {
  295      
  296      f1 = 
new TF1(function.c_str(), 
"(x <= [1])*[0]*[2]*TMath::BreitWigner(x,[1],[2])+(x > [1])*[0]*[3]*TMath::BreitWigner(x,[1],[3])");
 
  297 
  298      f1->SetParameter(0, 0.8*ymax);
 
  299      f1->SetParameter(1, x0);
 
  300      f1->SetParameter(2, 15.0);
 
  301      f1->SetParameter(3, 25.0);
 
  302 
  303      f1->SetParError(0, sqrt(ymax) * 0.1);
 
  304      f1->SetParError(1, 0.01);
 
  305      f1->SetParError(2, 0.1);
 
  306      f1->SetParError(3, 0.1);
 
  307 
  308    } else {
  309 
  310      FATAL(
"Unknown fit function " << function << endl);
 
  311    }
  312 
  313 
  314    DEBUG(
"Start values:" << endl);
 
  315      
  316    for (
int i = 0; i != 
f1->GetNpar(); ++i) {
 
  317      DEBUG(left << setw(12) << 
f1->GetParName  (i) << 
' ' << 
 
  319    }
  320 
  321    
  322      
  323    TFitResultPtr 
result = h1.Fit(f1, option.c_str(), 
"same", xmin, xmax);
 
  324 
  325    const bool status = 
result->IsValid() && E_ns(
f1->GetParError(1));
 
  326 
  328      cout << "Slice: " 
  329           << setw(4)    << ix                    << ' '
  330           << setw(16)   << h1.GetName()          << ' '
  331           << 
FIXED(7,3) << 
f1->GetParameter(1)   << 
" +/- "  
  332           << 
FIXED(7,3) << 
f1->GetParError(1)    << 
' '  
  336           << E_ns(
f1->GetParError(1))            << 
' ' 
  337           << (status ? "" : "failed")            << endl;
  338    }
  339 
  340    counts += 1;
  341 
  342    if (!status) {
  343      errors += 1;
  344    }
  345 
  346    if (status) {
  347      zmap[index] = result_type(
f1->GetParameter(1), 
f1->GetParError(1)); 
 
  348    }
  349 
  352    }
  353 
  354    hq.SetBinContent(ix, status ? 1.0 : 0.0);
  355 
  356    h1.Write();
  357 
  359  }
  360 
  361 
  362  if (!zmap.empty()) {
  363 
  364    
  365 
  366    double t0 = 0.0;
  367 
  368    for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
  369      t0 += i->second.value;
  370    }
  371 
  372    t0 /= zmap.size();
  373 
  374    NOTICE(
"Average time offset [ns] " << 
FIXED(7,2) << t0 << endl);
 
  375    NOTICE(
"Number of fits passed/failed " << counts << 
"/" << errors << endl);
 
  376 
  377    for (map_type::iterator i = zmap.begin(); i != zmap.end(); ++i) {
  378      i->second.value -= t0;
  379    }
  380    
  381    for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
  382      h0.SetBinContent(i->first, i->second.value);
  383      h0.SetBinError  (i->first, i->second.error);
  384    }
  385 
  386    for (Int_t ix = 1; ix <= H2.GetXaxis()->GetNbins(); ++ix) {
  387      for (Int_t iy = 1; iy <= H2.GetYaxis()->GetNbins(); ++iy) {
  388 
  389        const JLocation location(strings.at(ix-1), iy);
 
  390 
  391        if (router.hasLocation(location)) {
  392 
  393          const JModule& module = router.getModule(location);
 
  395 
  396          if (zmap.count(index) != 0) {
  397            H2.SetBinContent(ix, iy, zmap[index].value);
  398          }
  399        }
  400      }
  401    }
  402 
  403    if (overwriteDetector) {
  404 
  405      NOTICE(
"Store calibration data on file " << detectorFile << endl);
 
  406 
  408 
  409      for (size_t string = 0; string != strings.size(); ++string) {
  410        for (
int floor = 1; floor <= floors.
getUpperLimit(); ++floor) {
 
  411 
  412          const JLocation location(strings.at(
string), floor);
 
  413 
  414          if (router.hasLocation(location)) {
  415 
  418 
  419            if (zmap.count(index) != 0) {
  420              module.sub(zmap[index].value);
  421            }
  422          }
  423        }
  424      }
  425      
  427    }
  428 
  429  } else {
  430 
  431    NOTICE(
"No calibration results." << endl);
 
  432  }
  433 
  434  h0 .Write();
  435  hc .Write();
  436  hq .Write();
  437  h2->Write();
  438  H2 .Write();  
  439 
  440  out.Close();
  441 
  442  delete rpm;
  443}
#define DEBUG(A)
Message macros.
 
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
 
#define MAKE_CSTRING(A)
Make C-string.
 
Router for direct addressing of location data in detector data structure.
 
Logical location of module.
 
Data structure for a composite optical module.
 
int getID() const
Get identifier.
 
Utility class to parse command line options.
 
const JPolynome f1(1.0, 2.0, 3.0)
Function.
 
const char *const module_t
routing by module
 
const char *const string_t
routing by string
 
floor_range getRangeOfFloors(const JDetector &detector)
Get range of floors.
 
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
 
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
 
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
 
Auxiliary data structure for floating point format specification.
 
Interface for routing module identifier to index and vice versa.
 
virtual int getIndex(const int id) const =0
Get index.
 
virtual int getID(const int index) const =0
Get identifier.
 
Router for mapping of string identifier to index.
 
Auxiliary data structure for floating point format specification.