52int main(
int argc, 
char **argv)
 
   60  bool            overwriteDetector;
 
   72    JParser<> zap(
"Program to fit time-residuals histogram in output of JCalibrateMuon.cc.");
 
   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;
 
   84    zap[
'R'] = 
make_field(
target,            
"option for time calibration.")                                   =  module_t, string_t;
 
   89  catch(
const exception &error) {
 
   90    FATAL(error.what() << endl);
 
   95    FATAL(
"Invalid fit range [ns] " << T_ns << endl);
 
  113  else if (
target == string_t)
 
  116    FATAL(
"No valid target; check option -R" << endl);
 
  118  if (option.find(
'S') == string::npos) { option += 
'S'; }
 
  123  for (vector<string>::const_iterator i = inputFile.begin(); i != inputFile.end(); ++i) {
 
  125    NOTICE(
"Processing " << *i << endl);
 
  127    TFile in(i->c_str(), 
"exist");
 
  130      FATAL(
"File " << *i << 
" not opened." << endl);
 
  133    TH2D* p = 
dynamic_cast<TH2D*
>(in.Get(h2_t));
 
  136      FATAL(
"File " << *i << 
" has no histogram <" << h2_t << 
">." << endl);
 
  140      h2 = (TH2D*) p->Clone();
 
  150    FATAL(
"No histogram <" << h2_t << 
">." << endl);
 
  162    result_type(
double value,
 
  179  const TAxis* x_axis = h2->GetXaxis();
 
  180  const TAxis* y_axis = h2->GetYaxis();
 
  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);
 
  189  TH2D H2(
"detector", NULL,
 
  190          strings.size(), -0.5, strings.size() - 0.5,
 
  193  for (Int_t ix = 1; ix <= H2.GetXaxis()->GetNbins(); ++ix) {
 
  194    H2.GetXaxis()->SetBinLabel(ix, 
MAKE_CSTRING(strings.at(ix-1)));
 
  196  for (Int_t iy = 1; iy <= H2.GetYaxis()->GetNbins(); ++iy) {
 
  205  for (Int_t ix = 1; ix <= x_axis->GetNbins(); ++ix) {
 
  207    const int index = ix - 1; 
 
  208    const int id    = rpm->
getID(index);
 
  210    DEBUG(
"Bin " << setw(4) << ix << 
" -> " << setw(8) << 
id << endl);
 
  212    if (
ID != -1 && 
ID != 
id) {
 
  216    TH1D h1(
MAKE_CSTRING(
id << 
".1D"), NULL, y_axis->GetNbins(), y_axis->GetXmin(), y_axis->GetXmax());
 
  222    Double_t sigma  =  4.0;       
 
  225    for (Int_t iy = 1; iy <= y_axis->GetNbins(); ++iy) {
 
  227      h1.SetBinContent(iy,      h2->GetBinContent(ix,iy));
 
  228      h1.SetBinError  (iy, sqrt(h2->GetBinContent(ix,iy)));
 
  230      const Double_t x = h1.GetBinCenter (iy);
 
  231      const Double_t y = h1.GetBinContent(iy);
 
  243      WARNING(
"Not enough entries for slice " << ix << 
' ' << W << 
"; skip fit." << endl);
 
  256    if        (function == gauss_t) {
 
  258      f1 = 
new TF1(function.c_str(), 
"[0]*TMath::Gaus(x,[1],[2])");
 
  260      f1->SetParameter(0, 0.8*ymax);
 
  261      f1->SetParameter(1, x0);
 
  262      f1->SetParameter(2, sigma);
 
  264      f1->SetParError(0, sqrt(ymax) * 0.1);
 
  265      f1->SetParError(1, 0.01);
 
  266      f1->SetParError(2, 0.01);
 
  268    } 
else if (function == landau_t) {
 
  270      f1 = 
new TF1(function.c_str(), 
"[0]*TMath::Landau(x,[1],[2])");
 
  272      f1->SetParameter(0, 0.8*ymax);
 
  273      f1->SetParameter(1, x0);
 
  274      f1->SetParameter(2, sigma);
 
  276      f1->SetParError(0, sqrt(ymax) * 0.1);
 
  277      f1->SetParError(1, 0.01);
 
  278      f1->SetParError(2, 0.01);
 
  280    } 
else if (function == emg_t) {
 
  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]))");
 
  284      f1->SetParameter(0, 0.5*ymax);
 
  285      f1->SetParameter(1, x0 - sigma);
 
  286      f1->SetParameter(2, sigma);
 
  287      f1->SetParameter(3, 0.06);
 
  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);
 
  294    } 
else if (function == breitwigner_t) {
 
  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])");
 
  298      f1->SetParameter(0, 0.8*ymax);
 
  299      f1->SetParameter(1, x0);
 
  300      f1->SetParameter(2, 15.0);
 
  301      f1->SetParameter(3, 25.0);
 
  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);
 
  310      FATAL(
"Unknown fit function " << function << endl);
 
  314    DEBUG(
"Start values:" << endl);
 
  316    for (
int i = 0; i != f1->GetNpar(); ++i) {
 
  317      DEBUG(left << setw(12) << f1->GetParName  (i) << 
' ' << 
 
  318            SCIENTIFIC(12,5) << f1->GetParameter(i) << endl);
 
  323    TFitResultPtr result = h1.Fit(f1, option.c_str(), 
"same", xmin, xmax);
 
  325    const bool status = result->IsValid() && E_ns(f1->GetParError(1));
 
  327    if (
debug >= notice_t || !result->IsValid()) {
 
  329           << setw(4)    << ix                    << 
' ' 
  330           << setw(16)   << h1.GetName()          << 
' ' 
  331           << 
FIXED(7,3) << f1->GetParameter(1)   << 
" +/- "  
  332           << 
FIXED(7,3) << f1->GetParError(1)    << 
' '  
  333           << 
FIXED(9,2) << result->Chi2()        << 
'/' 
  334           << result->Ndf()                       << 
' ' 
  336           << E_ns(f1->GetParError(1))            << 
' ' 
  337           << (status ? 
"" : 
"failed")            << endl;
 
  347      zmap[index] = result_type(f1->GetParameter(1), f1->GetParError(1)); 
 
  350    if (result->Ndf() > 0) {
 
  351      hc.SetBinContent(ix, result->Chi2() / result->Ndf());
 
  354    hq.SetBinContent(ix, status ? 1.0 : 0.0);
 
  368    for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
 
  369      t0 += i->second.value;
 
  374    NOTICE(
"Average time offset [ns] " << 
FIXED(7,2) << t0 << endl);
 
  375    NOTICE(
"Number of fits passed/failed " << counts << 
"/" << errors << endl);
 
  377    for (map_type::iterator i = zmap.begin(); i != zmap.end(); ++i) {
 
  378      i->second.value -= t0;
 
  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);
 
  386    for (Int_t ix = 1; ix <= H2.GetXaxis()->GetNbins(); ++ix) {
 
  387      for (Int_t iy = 1; iy <= H2.GetYaxis()->GetNbins(); ++iy) {
 
  389        const JLocation location(strings.at(ix-1), iy);
 
  396          if (zmap.count(index) != 0) {
 
  397            H2.SetBinContent(ix, iy, zmap[index].value);
 
  403    if (overwriteDetector) {
 
  405      NOTICE(
"Store calibration data on file " << detectorFile << endl);
 
  409      for (
size_t string = 0; 
string != strings.size(); ++string) {
 
  410        for (
int floor = 1; floor <= floors.
getUpperLimit(); ++floor) {
 
  412          const JLocation location(strings.at(
string), floor);
 
  419            if (zmap.count(index) != 0) {
 
  420              module.sub(zmap[index].value);
 
  431    NOTICE(
"No calibration results." << endl);