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.