63int main(
int argc,
char **argv)
79 bool overwriteDetector;
107 JParser<> zap(
"Auxiliary program to fit PMT parameters from JMergeCalibrateK40 output.");
110 zap[
'f'] =
make_field(inputFile,
"input file (output from JMergeCalibrateK40).");
112 zap[
'a'] =
make_field(detectorFile,
"detector file.");
113 zap[
'P'] =
make_field(pmtFile,
"specify PMT file name that can be given to JTriggerEfficiency.") =
"";
115 "Fix time offset(s) of PMT(s) of certain module(s), e.g."
116 "\n-! \"808969848 0 808982077 23\" will fix time offsets of PMT 0 of module 808969848 and of PMT 23 of module 808982077."
117 "\nSame PMT offset can be fixed for all optical modules, e.g."
118 "\n-! \"-1 0 -1 23\" will fix time offsets of PMTs 0 and 23 of all optical modules.") =
JPARSER::initialised();
119 zap[
'r'] =
make_field(reverse,
"reverse TDC constraints due to option -! <TDC>.");
120 zap[
'A'] =
make_field(overwriteDetector,
"overwrite detector file provided through '-a' with fitted time offsets.");
121 zap[
'w'] =
make_field(writeFits,
"write fit results to ROOT file; -ww also write fitted TTS to PMT file.");
122 zap[
'D'] =
make_field(fitAngle,
"fit angular distribution; fix normalisation.");
123 zap[
'B'] =
make_field(fitNoise,
"fit background.");
124 zap[
'M'] =
make_field(fitModel,
"fit angular distribution as well as normalisation; fix PMT QEs = 1.0.");
125 zap[
'Q'] =
make_field(fixQE,
"fix PMT QEs = 1.0.");
132 catch(
const exception &error) {
133 FATAL(error.what() << endl);
137 if ((fitModel ? 1 : 0) +
140 (fixQE ? 1 : 0) > 1) {
141 FATAL(
"Use either option -M, -D, -B or -Q" << endl);
154 for (JTDC_t::const_iterator i = TDC.begin(); i != TDC.end(); ++i) {
155 DEBUG(
"PMT " << setw(10) << i->first <<
' ' << setw(2) << i->second <<
" constrain t0." << endl);
161 catch(
const exception &error) {
162 FATAL(error.what() << endl);
179 parameters.
load(pmtFile.c_str());
181 catch(
const exception& error) {}
187 TFile* in = TFile::Open(inputFile.c_str(),
"exist");
189 if (in == NULL || !in->IsOpen()) {
190 FATAL(
"File: " << inputFile <<
" not opened." << endl);
196 TH1D h0(
"chi2", NULL, 500, 0.0, 5.0);
197 TH1D hn(
"hn", NULL, 501, -0.5, 500.0);
198 TH1D hr(
"rate", NULL, 500, 0.0, 25.0);
199 TH1D h1(
"p1", NULL, 500, -5.0, +5.0);
200 TH1D h2(
"p2", NULL, 500, -5.0, +5.0);
201 TH1D h3(
"p3", NULL, 500, -5.0, +5.0);
202 TH1D h4(
"p4", NULL, 500, -5.0, +5.0);
203 TH1D hc(
"cc", NULL, 500, -0.1, +0.1);
204 TH1D hb(
"bc", NULL, 500, -0.1, +0.1);
209 TH2D H2(
"detector", NULL,
210 string.size() + 0, -0.5,
string.size() - 0.5,
213 for (Int_t i = 1; i <= H2.GetXaxis()->GetNbins(); ++i) {
214 H2.GetXaxis()->SetBinLabel(i,
MAKE_CSTRING(
string.at(i-1)));
216 for (Int_t i = 1; i <= H2.GetYaxis()->GetNbins(); ++i) {
220 TH2D* HN = (TH2D*) H2.Clone(
"iterations");
224 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ++module) {
226 if (module->getFloor() == 0) {
232 NOTICE(
"Module " << setw(10) << module->getID() <<
' ' <<
getLabel(module->getLocation()) <<
" !" <<
distance(range.first, range.second) << endl);
236 if (h2d == NULL || h2d->GetEntries() == 0) {
238 NOTICE(
"No data for module " << module->getID() <<
" -> set QEs to 0." << endl);
254 for (
int ix = 1; ix <= h2d->GetXaxis()->GetNbins(); ++ix) {
258 auto& buffer = data[
pair];
263 for (
int iy = 1; iy <= h2d->GetYaxis()->GetNbins(); ++iy) {
265 const double x = h2d->GetXaxis()->GetBinCenter(ix);
266 const double y = h2d->GetYaxis()->GetBinCenter(iy);
270 double value = h2d->GetBinContent(ix,iy);
271 double error = h2d->GetBinError (ix,iy);
273 buffer.push_back(
rate_type(y, value, error));
275 double width = h2d->GetYaxis()->GetBinWidth(iy);
287 if (V <= 0.0 - STDEV*W) {
288 count[0][
pair.first] += 1;
289 count[0][
pair.second] += 1;
292 if (V <= MINIMAL_RATE_HZ + STDEV*W) {
293 count[1][
pair.first] += 1;
294 count[1][
pair.second] += 1;
300 if (count[0][pmt] >= MAXIMAL_COUNTS) {
302 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
" some rates negative -> fit background" << endl);
304 if (fit.value.parameters[pmt].status) {
305 model.parameters[pmt].bg.set();
309 if (count[1][pmt] == NUMBER_OF_PMTS) {
311 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
" all rates to low -> disable" << endl);
313 model.parameters[pmt].disable();
317 DEBUG(
"Start value:" << endl <<
model << endl);
327 ERROR(
"Fit result " << setw(10) << module->getID() <<
" NDF " << setw(5) <<
result.ndf <<
" -> skip" << endl);
336 if (fit.value.parameters[pmt].status) {
338 if (fit.value.parameters[pmt].QE() <= QE_MIN ||
339 fit.value.parameters[pmt].QE() <= 0.0 + STDEV * fit.error.parameters[pmt].QE()) {
341 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
' '
343 <<
FIXED(5,3) << fit.value.parameters[pmt].QE() <<
" +/- "
344 <<
FIXED(5,3) << fit.error.parameters[pmt].QE() <<
" "
345 <<
" -> disable" << (!refit ?
" and refit" :
"") << endl);
347 fit.value.parameters[pmt].disable();
352 if (fit.value.parameters[pmt].t0.atLimit(T0_NS)) {
354 WARNING(
"PMT " << setw(10) << module->getID() <<
'.' <<
FILL(2,
'0') << pmt <<
FILL() <<
' '
356 <<
FIXED(5,3) << fit.value.parameters[pmt].t0() <<
" +/- "
357 <<
FIXED(5,3) << fit.error.parameters[pmt].t0() <<
" "
358 <<
" -> disable" << (!refit ?
" and refit" :
"") << endl);
360 fit.value.parameters[pmt].disable();
370 if (fit.value.parameters[pmt].status) {
379 NOTICE(
"Fit result " << setw(10) << module->getID() <<
" chi2 / NDF " <<
FIXED(10,2) <<
result.chi2 <<
" / " << setw(5) <<
result.ndf <<
' ' << setw(5) << fit.numberOfIterations << endl);
390 hn.Fill(fit.numberOfIterations);
391 hr.Fill(fit.value.R );
392 h1.Fill(fit.value.p1);
393 h2.Fill(fit.value.p2);
394 h3.Fill(fit.value.p3);
395 h4.Fill(fit.value.p4);
396 hc.Fill(fit.value.cc);
397 hb.Fill(fit.value.bc);
399 TH1D h1t(
MAKE_CSTRING(module->getID() <<
".1t0"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS - 0.5);
400 TH1D h1s(
MAKE_CSTRING(module->getID() <<
".1TTS"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS - 0.5);
401 TH1D h1q(
MAKE_CSTRING(module->getID() <<
".1QE"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS - 0.5);
404 h1t.SetBinContent(pmt + 1, fit.value.parameters[pmt].t0 ());
405 h1t.SetBinError (pmt + 1, fit.error.parameters[pmt].t0 () + numeric_limits<double>::epsilon());
406 h1s.SetBinContent(pmt + 1, fit.value.parameters[pmt].TTS());
407 h1s.SetBinError (pmt + 1, fit.error.parameters[pmt].TTS() + numeric_limits<double>::epsilon());
408 h1q.SetBinContent(pmt + 1, fit.value.parameters[pmt].QE ());
409 h1q.SetBinError (pmt + 1, fit.error.parameters[pmt].QE () + numeric_limits<double>::epsilon());
412 out << h1t << h1s << h1q;
414 for (
int ix = 1; ix <= h2d->GetXaxis()->GetNbins(); ++ix) {
418 for (
int iy = 1; iy <= h2d->GetYaxis()->GetNbins(); ++iy) {
420 const double dt_ns = h2d->GetYaxis()->GetBinCenter(iy);
422 h2d->SetBinContent(ix, iy, fit.value.getValue(
pair, dt_ns));
423 h2d->SetBinError (ix, iy, 0.0);
430 const double x =
string.getIndex(module->getString());
431 const double y =
module->getFloor();
434 HN->Fill(x, y, fit.numberOfIterations);
437 const double t0 = (fit.value.hasFixedTimeOffset() ? fit.value.getFixedTimeOffset() : 0.0);
446 data.QE = fit.value.parameters[pmt].QE / P;
451 data.TTS_ns = fit.value.parameters[pmt].TTS();
454 module->getPMT(pmt).addT0(fit.value.parameters[pmt].t0.get() - t0);
457 catch(
const exception& error) {
459 ERROR(
"Module " << setw(10) << module->getID() <<
' ' << error.what() <<
" -> set QEs to 0." << endl);
472 JSTDObjectWriter <JMeta> writer(meta);
477 for (vector<JMeta>::const_reverse_iterator i = meta.rbegin(); i != meta.rend(); ++i) {
482 if (overwriteDetector) {
484 NOTICE(
"Store calibration data on file " << detectorFile << endl);
490 parameters.
store(pmtFile.c_str());
494 for (vector<JMeta>::const_iterator i = meta.begin(); i != meta.end(); ++i) {
503 out << h0 << hn << hr << h1 << h2 << h3 << h4 << hc << hb << H2 << *HN;