66int main(
int argc,
char **argv)
82 bool overwriteDetector;
91 string transmittanceFile;
115 JParser<> zap(
"Auxiliary program to fit PMT parameters from JMergeCalibrateK40 output.");
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;
142 catch(
const exception &error) {
143 FATAL(error.what() << endl);
147 if ((fitModel ? 1 : 0) +
150 (QE != 0.0 ? 1 : 0) > 1) {
151 FATAL(
"Use either option -M, -D, -B or -Q" << endl);
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);
171 catch(
const exception &error) {
172 FATAL(error.what() << endl);
189 parameters.
load(pmtFile.c_str());
191 catch(
const exception& error) {}
198 if (transmittanceFile !=
"") {
200 transmittances.
load(transmittanceFile.c_str());
202 catch(
const exception& error) {}
205 TFile* in = TFile::Open(inputFile.c_str(),
"exist");
207 if (in == NULL || !in->IsOpen()) {
208 FATAL(
"File: " << inputFile <<
" not opened." << endl);
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);
233 TH2D H2(
"detector", NULL,
234 string.size() + 0, -0.5,
string.size() - 0.5,
237 for (Int_t i = 1; i <= H2.GetXaxis()->GetNbins(); ++i) {
238 H2.GetXaxis()->SetBinLabel(i,
MAKE_CSTRING(
string.at(i-1)));
240 for (Int_t i = 1; i <= H2.GetYaxis()->GetNbins(); ++i) {
244 TH2D* HN = (TH2D*) H2.Clone(
"iterations");
248 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ++module) {
250 if (module->getFloor() == 0) {
256 NOTICE(
"Module " << setw(10) << module->getID() <<
' ' <<
getLabel(module->getLocation()) <<
" !" <<
distance(range.first, range.second) << endl);
260 if (h2d == NULL || h2d->GetEntries() == 0) {
262 NOTICE(
"No data for module " << module->getID() <<
" -> set QEs to 0." << endl);
273 for (
const char c : transmittance) {
277 if (transmittances.count(module->getID())) {
279 model.transmittance[i].fix(transmittances[module->getID()][i]);
285 model.parameters[pmt].QE.fix(QE);
296 for (
int ix = 1; ix <= h2d->GetXaxis()->GetNbins(); ++ix) {
300 auto& buffer = data[
pair];
305 for (
int iy = 1; iy <= h2d->GetYaxis()->GetNbins(); ++iy) {
307 const double x = h2d->GetXaxis()->GetBinCenter(ix);
308 const double y = h2d->GetYaxis()->GetBinCenter(iy);
312 double value = h2d->GetBinContent(ix,iy);
313 double error = h2d->GetBinError (ix,iy);
315 buffer.push_back(
rate_type(y, value, error));
317 double width = h2d->GetYaxis()->GetBinWidth(iy);
329 if (V <= 0.0 - STDEV*W) {
330 count[0][
pair.first] += 1;
331 count[0][
pair.second] += 1;
334 if (V <= MINIMAL_RATE_HZ + STDEV*W) {
335 count[1][
pair.first] += 1;
336 count[1][
pair.second] += 1;
342 if (count[0][pmt] >= MAXIMAL_COUNTS) {
344 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
" some rates negative -> fit background" << endl);
346 if (fit.value.parameters[pmt].status) {
347 model.parameters[pmt].bg.set();
351 if (count[1][pmt] == NUMBER_OF_PMTS) {
353 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
" all rates to low -> disable" << endl);
355 model.parameters[pmt].disable();
359 DEBUG(
"Start value:" << endl <<
model << endl);
371 ERROR(
"Fit result " << setw(10) << module->getID() <<
" NDF " << setw(5) <<
result.ndf <<
" -> skip" << endl);
380 if (fit.value.parameters[pmt].status) {
382 if (fit.value.parameters[pmt].QE() <= QE_MIN ) {
384 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
' '
386 <<
FIXED(5,3) << fit.value.parameters[pmt].QE() <<
" +/- "
387 <<
FIXED(5,3) << fit.error.parameters[pmt].QE() <<
" "
388 <<
" -> disable" << (!refit ?
" and refit" :
"") << endl);
390 fit.value.parameters[pmt].disable();
399 if (fit.value.parameters[pmt].status) {
401 if (fit.value.parameters[pmt].t0.atLimit(T0_NS)) {
403 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
' '
405 <<
FIXED(7,3) << fit.value.parameters[pmt].t0() <<
" +/- "
406 <<
FIXED(7,3) << fit.error.parameters[pmt].t0());
408 if (refit ==
false) {
410 WARNING(
" -> disable and refit" << endl);
412 fit.value.parameters[pmt].disable();
420 fit.value.parameters[pmt].t0.set(0.0);
431 if (fit.value.parameters[pmt].status) {
440 NOTICE(
"Fit result " << setw(10) << module->getID() <<
" chi2 / NDF " <<
FIXED(10,2) <<
result.chi2 <<
" / " << setw(5) <<
result.ndf <<
' ' << setw(5) << fit.numberOfIterations << endl);
443 fit.value.model.print(cout);
450 transmittances[module->getID()] = fit.value.transmittance;
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);
465 T[i]->Fill(fit.value.transmittance[i]());
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);
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());
481 out << h1t << h1s << h1q;
483 for (
int ix = 1; ix <= h2d->GetXaxis()->GetNbins(); ++ix) {
487 for (
int iy = 1; iy <= h2d->GetYaxis()->GetNbins(); ++iy) {
489 const double dt_ns = h2d->GetYaxis()->GetBinCenter(iy);
491 h2d->SetBinContent(ix, iy, fit.value.getValue(
pair, dt_ns));
492 h2d->SetBinError (ix, iy, 0.0);
499 const double x =
string.getIndex(module->getString());
500 const double y =
module->getFloor();
503 HN->Fill(x, y, fit.numberOfIterations);
506 const double t0 = (fit.value.hasFixedTimeOffset() ? fit.value.getFixedTimeOffset() : 0.0);
517 data.QE = fit.value.parameters[pmt].QE() * fit.value.transmittance[ring]() / R;
522 data.TTS_ns = fit.value.parameters[pmt].TTS();
525 module->getPMT(pmt).addT0(fit.value.parameters[pmt].t0() - t0);
528 catch(
const exception& error) {
530 ERROR(
"Module " << setw(10) << module->getID() <<
' ' << error.what() <<
" -> set QEs to 0." << endl);
543 JSTDObjectWriter <JMeta> writer(meta);
548 for (vector<JMeta>::const_reverse_iterator i = meta.rbegin(); i != meta.rend(); ++i) {
553 if (overwriteDetector) {
555 NOTICE(
"Store calibration data on file " << detectorFile << endl);
561 parameters.
store(pmtFile.c_str());
564 if (transmittanceFile !=
"") {
565 transmittances.
store(transmittanceFile.c_str());
568 for (vector<JMeta>::const_iterator i = meta.begin(); i != meta.end(); ++i) {
578 out << h0 << hn << hr << h1 << h2 << h3 << h4 << hc << hb << H2 << *HN;