50{
53
56 string detectorFile;
57 bool overwriteDetector;
58 string function;
60 string option;
62 double WMin;
65
66 try {
67
68 JParser<> zap(
"Program to fit time-residuals histogram in output of JCalibrateMuon.cc.");
69
70 zap[
'f'] =
make_field(inputFile,
"input files (output from JCalibrateMuon).");
72 zap[
'a'] =
make_field(detectorFile,
"detector file.");
73 zap[
'A'] =
make_field(overwriteDetector,
"overwrite detector file provided through '-a' with correct time offsets.");
74 zap[
'F'] =
make_field(function,
"fit function") = gauss_t, landau_t, emg_t, breitwigner_t;
76 zap[
'O'] =
make_field(option,
"ROOT fit option, see TH1::Fit.") =
"";
78 zap[
'W'] =
make_field(WMin,
"minimal histogram contents.") = 100.0;
81
82 zap(argc, argv);
83 }
84 catch(const exception &error) {
85 FATAL(error.what() << endl);
86 }
87
88
90 FATAL(
"Invalid fit range [ns] " << T_ns << endl);
91 }
92
94
95 try {
97 }
100 }
101
102
103 if (option.find('S') == string::npos) { option += 'S'; }
105
106 TH2D* h2 = NULL;
107
108 for (vector<string>::const_iterator i = inputFile.begin(); i != inputFile.end(); ++i) {
109
110 NOTICE(
"Processing " << *i << endl);
111
112 TFile in(i->c_str(), "exist");
113
114 if (!in.IsOpen()) {
115 FATAL(
"File " << *i <<
" not opened." << endl);
116 }
117
118 TH2D* p = dynamic_cast<TH2D*>(in.Get(h2_t));
119
120 if (p == NULL) {
121 FATAL(
"File " << *i <<
" has no histogram <" << h2_t <<
">." << endl);
122 }
123
124 if (h2 == NULL)
125 h2 = (TH2D*) p->Clone();
126 else
127 h2->Add(p);
128
129 h2->SetDirectory(0);
130
131 in.Close();
132 }
133
134 if (h2 == NULL) {
135 FATAL(
"No histogram <" << h2_t <<
">." << endl);
136 }
137
138
139
140 struct result_type {
141
142 result_type() :
143 value(0.0),
144 error(0.0)
145 {}
146
147 result_type(double value,
148 double error) :
149 value(value),
150 error(error)
151 {}
152
153 double value;
154 double error;
155 };
156
158
159 map_type zmap;
160
161
162
163
164 const TAxis* x_axis = h2->GetXaxis();
165 const TAxis* y_axis = h2->GetYaxis();
166
167 TH1D h0("h0", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
168 TH1D hc("hc", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
169 TH1D hq("hq", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
170
171
173
174 size_t counts = 0;
175 size_t errors = 0;
176
177 for (Int_t ix = 1; ix <= x_axis->GetNbins(); ++ix) {
178
180
182
184 continue;
185 }
186
188 continue;
189 }
190
191 TH1D h1(
MAKE_CSTRING(module.
getID() <<
".1D"), NULL, y_axis->GetNbins(), y_axis->GetXmin(), y_axis->GetXmax());
192
193
194
195 Double_t ymax = 0.0;
196 Double_t x0 = 0.0;
197 Double_t
sigma = 4.0;
198 Double_t W = 0.0;
199
200 for (Int_t iy = 1; iy <= y_axis->GetNbins(); ++iy) {
201
202 h1.SetBinContent(iy, h2->GetBinContent(ix,iy));
203 h1.SetBinError (iy, sqrt(h2->GetBinContent(ix,iy)));
204
205 const Double_t
x = h1.GetBinCenter (iy);
206 const Double_t
y = h1.GetBinContent(iy);
207
209
210 if (y > ymax) {
213 }
214 }
215
216 if (W <= WMin) {
217
218 WARNING(
"Not enough entries for slice " << ix <<
' ' << W <<
"; skip fit." << endl);
219
220 continue;
221 }
222
223 ymax *= 0.9;
224
227
228
230
231 if (function == gauss_t) {
232
233 f1 =
new TF1(function.c_str(),
"[0]*TMath::Gaus(x,[1],[2])");
234
235 f1->SetParameter(0, 0.8*ymax);
236 f1->SetParameter(1, x0);
237 f1->SetParameter(2, sigma);
238
239 f1->SetParError(0, sqrt(ymax) * 0.1);
240 f1->SetParError(1, 0.01);
241 f1->SetParError(2, 0.01);
242
243 } else if (function == landau_t) {
244
245 f1 =
new TF1(function.c_str(),
"[0]*TMath::Landau(x,[1],[2])");
246
247 f1->SetParameter(0, 0.8*ymax);
248 f1->SetParameter(1, x0);
249 f1->SetParameter(2, sigma);
250
251 f1->SetParError(0, sqrt(ymax) * 0.1);
252 f1->SetParError(1, 0.01);
253 f1->SetParError(2, 0.01);
254
255 } else if (function == emg_t) {
256
257 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]))");
258
259 f1->SetParameter(0, 0.5*ymax);
260 f1->SetParameter(1, x0 - sigma);
261 f1->SetParameter(2, sigma);
262 f1->SetParameter(3, 0.06);
263
264 f1->SetParError(0, sqrt(ymax) * 0.1);
265 f1->SetParError(1, 0.01);
266 f1->SetParError(2, 0.01);
267 f1->SetParError(3, 1.0e-4);
268
269 } else if (function == breitwigner_t) {
270
271 f1 =
new TF1(function.c_str(),
"(x <= [1])*[0]*[2]*TMath::BreitWigner(x,[1],[2])+(x > [1])*[0]*[3]*TMath::BreitWigner(x,[1],[3])");
272
273 f1->SetParameter(0, 0.8*ymax);
274 f1->SetParameter(1, x0);
275 f1->SetParameter(2, 15.0);
276 f1->SetParameter(3, 25.0);
277
278 f1->SetParError(0, sqrt(ymax) * 0.1);
279 f1->SetParError(1, 0.01);
280 f1->SetParError(2, 0.1);
281 f1->SetParError(3, 0.1);
282
283 } else {
284
285 FATAL(
"Unknown fit function " << function << endl);
286 }
287
288
289 DEBUG(
"Start values:" << endl);
290
291 for (
int i = 0; i !=
f1->GetNpar(); ++i) {
292 DEBUG(left << setw(12) <<
f1->GetParName (i) <<
' ' <<
294 }
295
296
297
298 TFitResultPtr
result = h1.Fit(f1, option.c_str(),
"same", xmin, xmax);
299
301 cout << "Slice: "
302 << setw(4) << ix << ' '
303 << setw(16) << h1.GetName() << ' '
304 <<
FIXED(7,3) <<
f1->GetParameter(1) <<
" +/- "
305 <<
FIXED(7,3) <<
f1->GetParError(1) <<
' '
308 << (
result->IsValid() ?
"" :
"failed") << endl;
309 }
310
311 counts += 1;
312
314 errors += 1;
315 }
316
318 zmap[ix] = result_type(
f1->GetParameter(1),
f1->GetParError (1));
319 }
320
323 }
324
325 hq.SetBinContent(ix,
result->IsValid() ? 1.0 : 0.0);
326
327 h1.Write();
328
330 }
331
332
333 if (!zmap.empty()) {
334
335
336
337 double t0 = 0.0;
338
339 for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
340 t0 += i->second.value;
341 }
342
343 t0 /= zmap.size();
344
345 NOTICE(
"Average time offset [ns] " <<
FIXED(7,2) << t0 << endl);
346 NOTICE(
"Number of fits passed/failed " << counts <<
"/" << errors << endl);
347
348 for (map_type::iterator i = zmap.begin(); i != zmap.end(); ++i) {
349 i->second.value -= t0;
350 }
351
352 for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
353 h0.SetBinContent(i->first, i->second.value);
354 h0.SetBinError (i->first, i->second.error);
355 }
356
357
360
361 TH2D hi("hi", NULL,
362 string.size(), -0.5, string.size() - 0.5,
364
365 for (Int_t i = 1; i <= hi.GetXaxis()->GetNbins(); ++i) {
366 hi.GetXaxis()->SetBinLabel(i,
MAKE_CSTRING(
string.at(i-1)));
367 }
368 for (Int_t i = 1; i <= hi.GetYaxis()->GetNbins(); ++i) {
370 }
371
372 for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
373 hi.SetBinContent(
detector[i->first - 1].getString(),
375 i->second.value);
376 }
377
378 hi.Write();
379
380
381 if (overwriteDetector) {
382
383 NOTICE(
"Store calibration data on file " << detectorFile << endl);
384
386
387 for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
388
389 if (E_ns(i->second.error))
390 detector[i->first - 1].sub(i->second.value);
391 else
392 ERROR(
"Slice " << setw(4) << i->first <<
" fit uncertainty " <<
FIXED(5,2) << i->second.error <<
" outside specified range (option -E <E_ns>)" << endl);
393 }
394
396 }
397
398 } else {
399
400 NOTICE(
"No calibration results." << endl);
401 }
402
403 h0 .Write();
404 hc .Write();
405 hq .Write();
406 h2->Write();
407
408 out.Close();
409}
#define DEBUG(A)
Message macros.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
#define MAKE_CSTRING(A)
Make C-string.
const JLocation & getLocation() const
Get location.
int getFloor() const
Get floor number.
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.
std::string getLabel(const JLocation &location)
Get module label for monitoring and other applications.
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.
Router for mapping of string identifier to index.
Auxiliary data structure for floating point format specification.