67{
71
73
75
76 string inputFile;
78 string detectorFile;
79 string pmtFile;
81 bool reverse;
82 bool overwriteDetector;
84 bool fitAngle;
85 bool fitNoise;
86 bool fitModel;
87 double QE;
91 string transmittanceFile;
94
95 try {
96
98
114
115 JParser<> zap(
"Auxiliary program to fit PMT parameters from JMergeCalibrateK40 output.");
116
118 zap[
'f'] =
make_field(inputFile,
"input file (output from JMergeCalibrateK40).");
120 zap[
'a'] =
make_field(detectorFile,
"detector file.");
121 zap[
'P'] =
make_field(pmtFile,
"specify PMT file name that can be given to JTriggerEfficiency.") =
"";
123 "Fix time offset(s) of PMT(s) of certain module(s), e.g."
124 "\n-! \"808969848 0 808982077 23\" will fix time offsets of PMT 0 of module 808969848 and of PMT 23 of module 808982077."
125 "\nSame PMT offset can be fixed for all optical modules, e.g."
126 "\n-! \"-1 0 -1 23\" will fix time offsets of PMTs 0 and 23 of all optical modules.") =
JPARSER::initialised();
127 zap[
'r'] =
make_field(reverse,
"reverse TDC constraints due to option -! <TDC>.");
128 zap[
'A'] =
make_field(overwriteDetector,
"overwrite detector file provided through '-a' with fitted time offsets.");
129 zap[
'w'] =
make_field(writeFits,
"write fit results to ROOT file; -ww also write fitted TTS to PMT file.");
130 zap[
'D'] =
make_field(fitAngle,
"fit angular distribution; fix normalisation.");
131 zap[
'B'] =
make_field(fitNoise,
"fit background.");
132 zap[
'M'] =
make_field(fitModel,
"fit angular distribution as well as normalisation; fix PMT QEs = 1.0.");
133 zap[
'Q'] =
make_field(QE,
"fix PMT QEs") = 0.0;
139
140 zap(argc, argv);
141 }
142 catch(const exception &error) {
143 FATAL(error.what() << endl);
144 }
145
146
147 if ((fitModel ? 1 : 0) +
148 (fitAngle ? 1 : 0) +
149 (fitNoise ? 1 : 0) +
150 (QE != 0.0 ? 1 : 0) > 1) {
151 FATAL(
"Use either option -M, -D, -B or -Q" << endl);
152 }
153
159
160 if (reverse) {
162 }
163
164 for (JTDC_t::const_iterator i = TDC.begin(); i != TDC.end(); ++i) {
165 DEBUG(
"PMT " << setw(10) << i->first <<
' ' << setw(2) << i->second <<
" constrain t0." << endl);
166 }
167
168 try {
170 }
171 catch(const exception &error) {
172 FATAL(error.what() << endl);
173 }
174
176
177 try {
179 }
182 }
183
184
186
187 if (pmtFile != "") {
188 try {
189 parameters.
load(pmtFile.c_str());
190 }
191 catch(const exception& error) {}
192 }
193
195
197
198 if (transmittanceFile != "") {
199 try {
200 transmittances.
load(transmittanceFile.c_str());
201 }
202 catch(const exception& error) {}
203 }
204
205 TFile* in = TFile::Open(inputFile.c_str(), "exist");
206
207 if (in == NULL || !in->IsOpen()) {
208 FATAL(
"File: " << inputFile <<
" not opened." << endl);
209 }
210
211
213
214 TH1D h0("chi2", NULL, 500, 0.0, 5.0);
215 TH1D hn("hn", NULL, 501, -0.5, 500.0);
216 TH1D hr("rate", NULL, 500, 0.0, 25.0);
217 TH1D h1("p1", NULL, 500, -5.0, +5.0);
218 TH1D h2("p2", NULL, 500, -5.0, +5.0);
219 TH1D h3("p3", NULL, 500, -5.0, +5.0);
220 TH1D h4("p4", NULL, 500, -5.0, +5.0);
221 TH1D hc("cc", NULL, 500, -0.1, +0.1);
222 TH1D hb("bc", NULL, 500, -0.1, +0.1);
223
225
228 }
229
232
233 TH2D H2("detector", NULL,
234 string.size() + 0, -0.5, string.size() - 0.5,
236
237 for (Int_t i = 1; i <= H2.GetXaxis()->GetNbins(); ++i) {
238 H2.GetXaxis()->SetBinLabel(i,
MAKE_CSTRING(
string.at(i-1)));
239 }
240 for (Int_t i = 1; i <= H2.GetYaxis()->GetNbins(); ++i) {
242 }
243
244 TH2D* HN = (TH2D*) H2.Clone("iterations");
245
247
248 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ++module) {
249
250 if (module->getFloor() == 0) {
251 continue;
252 }
253
255
256 NOTICE(
"Module " << setw(10) << module->getID() <<
' ' <<
getLabel(module->getLocation()) <<
" !" <<
distance(range.first, range.second) << endl);
257
259
260 if (h2d == NULL || h2d->GetEntries() == 0) {
261
262 NOTICE(
"No data for module " << module->getID() <<
" -> set QEs to 0." << endl);
263
266 }
267
268 continue;
269 }
270
272
273 for (const char c : transmittance) {
275 }
276
277 if (transmittances.count(module->getID())) {
279 model.transmittance[i].fix(transmittances[module->getID()][i]);
280 }
281 }
282
283 if (QE != 0.0) {
285 model.parameters[pmt].QE.fix(QE);
286 }
287 }
288
290
294 };
295
296 for (int ix = 1; ix <= h2d->GetXaxis()->GetNbins(); ++ix) {
297
299
301
302 double V = 0.0;
303 double W = 0.0;
304
305 for (int iy = 1; iy <= h2d->GetYaxis()->GetNbins(); ++iy) {
306
307 const double x = h2d->GetXaxis()->GetBinCenter(ix);
308 const double y = h2d->GetYaxis()->GetBinCenter(iy);
309
311
312 double value = h2d->GetBinContent(ix,iy);
313 double error = h2d->GetBinError (ix,iy);
314
315 buffer.push_back(
rate_type(y, value, error));
316
317 double width = h2d->GetYaxis()->GetBinWidth(iy);
318
319 value *= width;
320 error *= width;
321
322 V += value;
323 W += error * error;
324 }
325 }
326
327 W = sqrt(W);
328
329 if (V <= 0.0 - STDEV*W) {
330 count[0][
pair.first] += 1;
331 count[0][
pair.second] += 1;
332 }
333
334 if (V <= MINIMAL_RATE_HZ + STDEV*W) {
335 count[1][
pair.first] += 1;
336 count[1][
pair.second] += 1;
337 }
338 }
339
341
342 if (count[0][pmt] >= MAXIMAL_COUNTS) {
343
344 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
" some rates negative -> fit background" << endl);
345
346 if (fit.value.parameters[pmt].status) {
347 model.parameters[pmt].bg.set();
348 }
349 }
350
351 if (count[1][pmt] == NUMBER_OF_PMTS) {
352
353 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
" all rates to low -> disable" << endl);
354
355 model.parameters[pmt].disable();
356 }
357 }
358
359 DEBUG(
"Start value:" << endl <<
model << endl);
360
361 try {
362
364
366
368
370
371 ERROR(
"Fit result " << setw(10) << module->getID() <<
" NDF " << setw(5) <<
result.ndf <<
" -> skip" << endl);
372
373 continue;
374 }
375
376 bool refit = false;
377
379
380 if (fit.value.parameters[pmt].status) {
381
382 if (fit.value.parameters[pmt].QE() <= QE_MIN ) {
383
384 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
' '
385 << "QE = "
386 <<
FIXED(5,3) << fit.value.parameters[pmt].QE() <<
" +/- "
387 <<
FIXED(5,3) << fit.error.parameters[pmt].QE() <<
" "
388 << " -> disable" << (!refit ? " and refit" : "") << endl);
389
390 fit.value.parameters[pmt].disable();
391
392 refit = true;
393 }
394 }
395 }
396
398
399 if (fit.value.parameters[pmt].status) {
400
401 if (fit.value.parameters[pmt].t0.atLimit(T0_NS)) {
402
403 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
' '
404 << "t0 at limit "
405 <<
FIXED(7,3) << fit.value.parameters[pmt].t0() <<
" +/- "
406 <<
FIXED(7,3) << fit.error.parameters[pmt].t0());
407
408 if (refit == false) {
409
410 WARNING(
" -> disable and refit" << endl);
411
412 fit.value.parameters[pmt].disable();
413
414 refit = true;
415
416 } else {
417
419
420 fit.value.parameters[pmt].t0.set(0.0);
421 }
422 }
423 }
424 }
425
426 if (refit) {
427
429
431 if (fit.value.parameters[pmt].status) {
433 }
434 }
435
436 refit = false;
438 }
439
440 NOTICE(
"Fit result " << setw(10) << module->getID() <<
" chi2 / NDF " <<
FIXED(10,2) <<
result.chi2 <<
" / " << setw(5) <<
result.ndf <<
' ' << setw(5) << fit.numberOfIterations << endl);
441
443 fit.value.model.print(cout);
444 }
445
447
448
449
450 transmittances[module->getID()] = fit.value.transmittance;
451
452 if (writeFits) {
453
455 hn.Fill(fit.numberOfIterations);
456 hr.Fill(fit.value.model.R );
457 h1.Fill(fit.value.model.p1);
458 h2.Fill(fit.value.model.p2);
459 h3.Fill(fit.value.model.p3);
460 h4.Fill(fit.value.model.p4);
461 hc.Fill(fit.value.model.cc);
462 hb.Fill(fit.value.model.bc);
463
465 T[i]->Fill(fit.value.transmittance[i]());
466 }
467
468 TH1D h1t(
MAKE_CSTRING(module->getID() <<
".1t0"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS - 0.5);
469 TH1D h1s(
MAKE_CSTRING(module->getID() <<
".1TTS"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS - 0.5);
470 TH1D h1q(
MAKE_CSTRING(module->getID() <<
".1QE"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS - 0.5);
471
473 h1t.SetBinContent(pmt + 1, fit.value.parameters[pmt].t0 ());
474 h1t.SetBinError (pmt + 1, fit.error.parameters[pmt].t0 () + numeric_limits<double>::epsilon());
475 h1s.SetBinContent(pmt + 1, fit.value.parameters[pmt].TTS());
476 h1s.SetBinError (pmt + 1, fit.error.parameters[pmt].TTS() + numeric_limits<double>::epsilon());
477 h1q.SetBinContent(pmt + 1, fit.value.parameters[pmt].QE ());
478 h1q.SetBinError (pmt + 1, fit.error.parameters[pmt].QE () + numeric_limits<double>::epsilon());
479 }
480
481 out << h1t << h1s << h1q;
482
483 for (int ix = 1; ix <= h2d->GetXaxis()->GetNbins(); ++ix) {
484
486
487 for (int iy = 1; iy <= h2d->GetYaxis()->GetNbins(); ++iy) {
488
489 const double dt_ns = h2d->GetYaxis()->GetBinCenter(iy);
490
491 h2d->SetBinContent(ix, iy, fit.value.getValue(
pair, dt_ns));
492 h2d->SetBinError (ix, iy, 0.0);
493 }
494 }
495
497 h2d->Write();
498
499 const double x =
string.getIndex(module->getString());
500 const double y =
module->getFloor();
501
503 HN->Fill(x, y, fit.numberOfIterations);
504 }
505
506 const double t0 = (fit.value.hasFixedTimeOffset() ? fit.value.getFixedTimeOffset() : 0.0);
507
509
511
513
515
516 if (R > 0.0)
517 data.QE = fit.value.parameters[pmt].QE() * fit.value.transmittance[ring]() / R;
518 else
520
521 if (writeFits > 1) {
522 data.TTS_ns = fit.value.parameters[pmt].TTS();
523 }
524
525 module->getPMT(pmt).addT0(fit.value.parameters[pmt].t0() - t0);
526 }
527 }
528 catch(const exception& error) {
529
530 ERROR(
"Module " << setw(10) << module->getID() <<
' ' << error.what() <<
" -> set QEs to 0." << endl);
531
534 }
535 }
536 }
537
538
540
541 {
543 JSTDObjectWriter <JMeta> writer(meta);
544
545 writer << reader;
546 }
547
548 for (vector<JMeta>::const_reverse_iterator i = meta.rbegin(); i != meta.rend(); ++i) {
551 }
552
553 if (overwriteDetector) {
554
555 NOTICE(
"Store calibration data on file " << detectorFile << endl);
556
558 }
559
560 if (pmtFile != "") {
561 parameters.
store(pmtFile.c_str());
562 }
563
564 if (transmittanceFile != "") {
565 transmittances.
store(transmittanceFile.c_str());
566 }
567
568 for (vector<JMeta>::const_iterator i = meta.begin(); i != meta.end(); ++i) {
570 }
571
574 }
575
576 if (writeFits) {
577
578 out << h0 << hn << hr << h1 << h2 << h3 << h4 << hc << hb << H2 << *HN;
579
581 out << *T[i];
582 }
583 }
584
585 out.Close();
586
587 return 0;
588}
#define DEBUG(A)
Message macros.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
#define MAKE_CSTRING(A)
Make C-string.
#define gmake_property(A)
macros to convert (template) parameter to JPropertiesElement object
#define TEST(T)
Test data member.
Auxiliary class for map of PMT parameters.
Data structure for PMT parameters.
Utility class to parse parameter values.
Utility class to parse command line options.
Object reading from a list of files.
static double TEROSTAT_R1
scaling factor
static const char *const _2F
Name extension for 2F rate fitted.
@ FIT_PMTS_QE_FIXED_t
fit parameters of PMTs with QE fixed
@ FIT_PMTS_AND_ANGULAR_DEPENDENCE_t
fit parameters of PMTs and angular dependence of K40 rate
@ FIT_MODEL_t
fit parameters of K40 rate and TTSs of PMTs
@ FIT_PMTS_AND_BACKGROUND_t
fit parameters of PMTs and background
@ FIT_PMTS_t
fit parameters of PMTs
static const char *const _2R
Name extension for 2D rate measured.
static const int NUMBER_OF_RINGS
number of rings in optical module.
static double TEROSTAT_DZ
maximal PMT inclination
ring_type getRing(const double dz)
Get ring.
static double BELL_SHAPE
Bell shape.
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.
double getSurvivalProbability(const JPMTParameters ¶meters)
Get model dependent probability that a one photo-electron hit survives the simulation of the PMT assu...
void model(JModel_t &value)
Auxiliary function to constrain model during fit.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
bool putObject(TDirectory &dir, const TObject &object)
Write object to ROOT directory.
KM3NeT DAQ data structures and auxiliaries.
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
Auxiliary data structure for sequence of same character.
Auxiliary data structure for floating point format specification.
Type definition of range.
Model for fit to acoustics data.
Fit parameters for two-fold coincidence rate due to K40.
static const JK40Parameters & getInstance()
Get default values.
static const JPMTParameters_t & getInstance()
Get default values.
Auxiliary class for TDC constraints.
range_type equal_range(const int id)
Get range of constraints for given module.
void reverse()
Reverse constraints.
bool is_valid(const bool option=false) const
Check validity of TDC constrants.
static const JTransmittance & getInstance()
Get default values.
Data structure for measured coincidence rates of all pairs of PMTs in optical module.
Data structure for measured coincidence rate of pair of PMTs.
Auxiliary data structure to define ring.
int getIndex() const
Get index.
static ring_type getRing(const int index)
Get ring.
Auxiliary data structure for I/O of transmittances of optical modules in detector.
Router for mapping of string identifier to index.
void store(const char *file_name) const
Store to output file.
void load(const char *file_name)
Load from input file.
Empty structure for specification of parser element that is initialised (i.e. does not require input)...