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