76 using namespace KM3NETDAQ;
80 const double epsilon = 1.0e-10;
89 bool overwriteDetector;
112 JParser<> zap(
"Auxiliary program to fit PMT parameters from JMergeCalibrateK40 output.");
115 zap[
'f'] =
make_field(inputFile,
"input file (output from JMergeCalibrateK40).");
117 zap[
'a'] =
make_field(detectorFile,
"detector file.");
118 zap[
'P'] =
make_field(pmtFile,
"specify PMT file name that can be given to JTriggerEfficiency.") =
"";
120 "Fix time offset(s) of PMT(s) of certain module(s), e.g."
121 "\n-! \"808969848 0 808982077 23\" will fix offset of PMT 0 of module 808969848 and of PMT 23 of module 808982077."
122 "\nSame PMT offset can be fixed for all optical modules, e.g."
123 "\n-! \"-1 0 -1 23\" will fix offsets of PMTs 0 and 23 for all optical modules.")
125 zap[
'r'] =
make_field(reverse,
"reverse TDC constraints due to option -! <TDC>.");
126 zap[
'A'] =
make_field(overwriteDetector,
"overwrite detector file provided through '-a' with correct time offsets.");
127 zap[
'w'] =
make_field(writeFits,
"write fit results.");
128 zap[
'D'] =
make_field(fitAngDist,
"fit angular distribution; fix normalisation.");
129 zap[
'M'] =
make_field(fitModel,
"fit angular distribution; fix PMT QEs = 1.0.");
130 zap[
'x'] =
make_field(X,
"ROOT fit range (PMT pairs).") = JRange_t();
131 zap[
'y'] =
make_field(
Y,
"ROOT fit range (time residual).") = JRange_t();
132 zap[
'O'] =
make_field(option,
"ROOT fit option, see TH1::Fit.") =
"";
137 catch(
const exception &error) {
138 FATAL(error.what() << endl);
142 ROOT::Math::MinimizerOptions::SetDefaultMaxFunctionCalls(1000000);
149 for (JTDC_t::const_iterator i = TDC.begin(); i != TDC.end(); ++i) {
150 DEBUG(
"PMT " << setw(10) << i->first <<
' ' << setw(2) << i->second <<
" constrain t0." << endl);
184 if (option.find(
'O') == string::npos) { option +=
'0'; }
185 if (option.find(
'S') == string::npos) { option +=
'S'; }
189 TFile*
in = TFile::Open(inputFile.c_str(),
"exist");
191 if (
in == NULL || !
in->IsOpen()) {
192 FATAL(
"File: " << inputFile <<
" not opened." << endl);
196 TDirectory::AddDirectory(NULL);
202 TH1D hc(
"chi2", NULL, 500, 0.0, 5.0);
204 TH1D
p1(
"p1", NULL, 501, -5.0, +5.0);
205 TH1D
p2(
"p2", NULL, 501, -5.0, +5.0);
206 TH1D
p3(
"p3", NULL, 501, -5.0, +5.0);
207 TH1D p4(
"p4", NULL, 501, -5.0, +5.0);
208 TH1D bg(
"bg", NULL, 501, -0.1, +0.1);
209 TH1D cc(
"cc", NULL, 501, -0.1, +0.1);
216 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ++module) {
218 NOTICE(
"Module " << setw(10) << module->getID() <<
' ' << module->getLocation() << endl);
220 if (module->empty()) {
230 if (h2s == NULL || h2s->GetEntries() == 0) {
232 NOTICE(
"No data for module " << module->getID() <<
"; set corresponding QEs to 0." << endl);
252 h2s->GetXaxis()->GetXmin(),
253 h2s->GetXaxis()->GetXmax(),
254 h2s->GetYaxis()->GetXmin(),
255 h2s->GetYaxis()->GetXmax(),
256 range.first == range.second);
258 fit.setModelParameters(fitk40.getModelParameters());
260 for (JTDC_t::const_iterator i = range.first; i != range.second; ++i) {
261 fixParameter(fit, fit.getModelParameter(i->second, &JPMTParameters_t::t0));
266 fixParameter(fit, fit.getModelParameter(pmt, &JPMTParameters_t::QE));
271 fixParameter(fit, fit.getModelParameter(&JFitK40::Rate_Hz));
287 for (
int ix = 1; ix <= h2s->GetXaxis()->GetNbins(); ++ix) {
289 Double_t value = 0.0;
290 Double_t error = 0.0;
292 for (
int iy = 1; iy <= h2s->GetYaxis()->GetNbins(); ++iy) {
293 value += h2s->GetBinContent(ix,iy);
294 error += h2s->GetBinError(ix,iy) * h2s->GetBinError(ix,iy);
299 if (value < MINIMAL_RATE_HZ + STDEV*error) {
303 buffer[pair.first] += 1;
304 buffer[pair.second] += 1;
314 WARNING(
"PMT " << setw(10) << module->getID() <<
' ' << setw(2) << pmt <<
" too low a rate; switch off." << endl);
322 NOTICE(
"Skip fit for module " << module->getID() <<
"; set corresponding QEs to 0." << endl);
333 if (X != JRange_t()) {
334 h2s->GetXaxis()->SetRangeUser(max(X.getLowerLimit(), h2s->GetXaxis()->GetXmin()),
335 min(X.getUpperLimit(), h2s->GetXaxis()->GetXmax()));
337 if (
Y != JRange_t()) {
338 h2s->GetYaxis()->SetRangeUser(max(
Y.getLowerLimit(), h2s->GetYaxis()->GetXmin()),
339 min(
Y.getUpperLimit(), h2s->GetYaxis()->GetXmax()));
344 TH1D
h1(
MAKE_CSTRING(module->getID() <<
_1D), NULL, h2s->GetXaxis()->GetNbins(), h2s->GetXaxis()->GetXmin(), h2s->GetXaxis()->GetXmax());
346 const Double_t sigma[] = {
348 (min(
Y.getUpperLimit(), h2s->GetYaxis()->GetXmax()) -
349 max(
Y.getLowerLimit(), h2s->GetYaxis()->GetXmin())) / sqrt(12.0),
355 for (Int_t ix = 1; ix <= h2s->GetXaxis()->GetNbins(); ++ix) {
359 Double_t value = 0.0;
360 Double_t error = 0.0;
362 for (Int_t iy = 1; iy <= h2s->GetYaxis()->GetNbins(); ++iy) {
364 const Double_t y = h2s->GetYaxis()->GetBinCenter(iy);
365 const Double_t z = h2s->GetBinContent(ix, iy);
366 const Double_t
w = h2s->GetBinError (ix, iy);
382 h1.SetBinContent(ix, y0);
383 h1.SetBinError (ix, value > MINIMAL_RATE_HZ + STDEV * error ? sigma[1] * error / value : sigma[0]);
389 TFitResultPtr
result = f1(
h1, option.c_str());
393 TH1D h2(
MAKE_CSTRING(module->getID() <<
_1F), NULL,
h1.GetXaxis()->GetNbins(),
h1.GetXaxis()->GetXmin(),
h1.GetXaxis()->GetXmax());
395 for (
int ix = 1; ix <= h2.GetXaxis()->GetNbins(); ++ix) {
397 const Double_t x = h2.GetXaxis()->GetBinCenter(ix);
399 h2.SetBinContent(ix, f1.Eval(x));
400 h2.SetBinError (ix, 0.0);
408 cout <<
"Fit result chi2 / NDF " << result->Chi2() <<
' ' << result->Ndf() <<
' ' << (result->IsValid() ?
"" :
"failed") << endl;
413 << setw(2) << pmt <<
' '
414 <<
FIXED(7,2) << f1.getT0 (pmt) <<
' ';
415 cout << (result->IsParameterFixed(f1.getModelParameter(pmt, &JPMTParameters_t::t0)) ?
" *** fixed t0 *** " :
"");
416 cout << (f1.is_disabled (pmt) ?
" (disabled)" :
"");
417 cout << (f1.is_average_t0(pmt) ?
" (averaged)" :
"");
422 fit.setModelParameters(f1.getModelParameters());
426 TFitResultPtr result = fit(*h2s, option);
438 if (!result->IsParameterFixed(fit.getModelParameter(pmt, &JPMTParameters_t::QE)) && !
is_valid(
values.getQE(pmt), errors.getQE(pmt))) {
440 WARNING(
"PMT " << setw(10) << module->getID() <<
' ' << setw(2) << pmt <<
' '
443 <<
FIXED(5,2) << errors.getQE(pmt)
444 <<
" compatible with zero -> set QE = 0 and t0 = 0; -> refit." << endl);
455 NOTICE(
"Skip fit for module " << module->getID() <<
"; set corresponding QEs to 0." << endl);
471 fit.setModelParameters(f1.getModelParameters());
473 result = fit(*h2s, option);
480 hc.Fill(TMath::Log10(result->Chi2() / result->Ndf()));
484 h2s->GetXaxis()->GetNbins(), h2s->GetXaxis()->GetXmin (), h2s->GetXaxis()->GetXmax (),
485 h2s->GetYaxis()->GetNbins(), h2s->GetYaxis()->GetXmin (), h2s->GetYaxis()->GetXmax ());
487 for (
int ix = 1; ix <= h2f.GetXaxis()->GetNbins(); ++ix) {
488 for (
int iy = 1; iy <= h2f.GetYaxis()->GetNbins(); ++iy) {
490 const Double_t x = h2f.GetXaxis()->GetBinCenter(ix);
491 const Double_t y = h2f.GetYaxis()->GetBinCenter(iy);
493 h2f.SetBinContent(ix, iy, fit.Eval(x,y));
494 h2f.SetBinError (ix, iy, 0.0);
501 cout <<
"Fit result chi2 / NDF " << result->Chi2() <<
' ' << result->Ndf() <<
' ' << (result->IsValid() ?
"" :
"failed") << endl;
503 cout <<
"Rate_Hz= " <<
FIXED(8,4) <<
values.Rate_Hz << (result->IsParameterFixed(fit.getModelParameter(&JFitK40::Rate_Hz)) ?
" *** fixed *** " :
"") << endl;
505 cout <<
"p1= " <<
FIXED(8,4) <<
values.p1 << (result->IsParameterFixed(fit.getModelParameter(&
JFitK40::p1)) ?
" *** fixed *** " :
"") << endl;
506 cout <<
"p2= " <<
FIXED(8,4) <<
values.p2 << (result->IsParameterFixed(fit.getModelParameter(&
JFitK40::p2)) ?
" *** fixed *** " :
"") << endl;
507 cout <<
"p3= " <<
FIXED(8,4) <<
values.p3 << (result->IsParameterFixed(fit.getModelParameter(&
JFitK40::p2)) ?
" *** fixed *** " :
"") << endl;
508 cout <<
"p4= " <<
FIXED(8,4) <<
values.p4 << (result->IsParameterFixed(fit.getModelParameter(&
JFitK40::p3)) ?
" *** fixed *** " :
"") << endl;
510 cout <<
"Background (correlated): " <<
FIXED(8,5) <<
values.bg << (result->IsParameterFixed(fit.getModelParameter(&JFitK40::bg)) ?
" *** fixed *** " :
"") << endl;
511 cout <<
"Background (uncorrelated): " <<
FIXED(8,5) <<
values.cc << (result->IsParameterFixed(fit.getModelParameter(&JFitK40::cc)) ?
" *** fixed *** " :
"") << endl;
513 cout <<
" PMT t0 [ns] TTS [ns] R" << endl;
520 << setw(2) << pmt <<
' '
521 <<
FIXED(7,2) << fit.getT0 (pmt) <<
' '
522 <<
FIXED(7,2) << fit.getTTS(pmt) <<
' '
523 <<
FIXED(7,3) << fit.getQE (pmt);
525 cout << (result->IsParameterFixed(fit.getModelParameter(pmt, &JPMTParameters_t::QE)) ?
" *** fixed QE *** " :
"");
526 cout << (result->IsParameterFixed(fit.getModelParameter(pmt, &JPMTParameters_t::TTS)) ?
" *** fixed TTS *** " :
"");
527 cout << (result->IsParameterFixed(fit.getModelParameter(pmt, &JPMTParameters_t::t0)) ?
" *** fixed t0 *** " :
"");
528 cout << (fit.is_disabled (pmt) ?
" (disabled)" :
"");
529 cout << (fit.is_average_t0(pmt) ?
" (averaged)" :
"");
532 Q[0].
put(fit.getT0 (pmt));
533 Q[1].
put(fit.getTTS(pmt));
534 Q[2].
put(fit.getQE (pmt));
571 h1t.SetBinContent(pmt + 1,
values.getT0 (pmt));
572 h1s.SetBinContent(pmt + 1,
values.getTTS(pmt));
573 h1q.SetBinContent(pmt + 1,
values.getQE (pmt));
575 h1t.SetBinError (pmt + 1, max(errors.getT0 (pmt), epsilon));
576 h1s.SetBinError (pmt + 1, max(errors.getTTS(pmt), epsilon));
577 h1q.SetBinError (pmt + 1, max(errors.getQE (pmt), epsilon));
580 out << h1t << h1s << h1q;
590 if (overwriteDetector) {
591 module->getPMT(pmt).addT0(fit.getT0(pmt));
598 out << hc <<
p1 <<
p2 <<
p3 << p4 << bg << cc;
604 if (overwriteDetector) {
606 NOTICE(
"Store calibration data on file " << detectorFile << endl);
Utility class to parse command line options.
JCombinatorics::pair_type pair_type
#define gmake_property(A)
macro to convert (template) parameter to JPropertiesElement object
Auxiliary class for TDC constraints.
Template specialisation of two-fold coincidence rate due to K40 and other radioactive decays...
Utility class to parse parameter values.
*fatal Wrong number of arguments esac JCookie sh typeset Z DETECTOR typeset Z SOURCE_RUN typeset Z TARGET_RUN set_variable PARAMETERS_FILE $WORKDIR parameters
#define MAKE_CSTRING(A)
Make C-string.
then for HISTOGRAM in h0 h1
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Template specialisation of two-fold coincidence rate due to K40 and other radioactive decays...
then fatal Wrong number of arguments fi set_variable STRING $argv[1] set_variable DETECTORXY_TXT $WORKDIR $DETECTORXY_TXT tail read X Y CHI2 RMS printf optimum n $X $Y $CHI2 $RMS awk v Y
Auxiliary data structure for floating point format specification.
static const char *const _1F
Name extension for 1D time offset fit.
static const char *const _2F
Name extension for 2F rate fitted.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
bool is_valid(const json &js)
Check validity of JSon data.
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
static const char *const _2R
Name extension for 2D rate measured.
Auxiliary class for map of PMT parameters.
Fit parameters for single PMT.
z range($ZMAX-$ZMIN)< $MINIMAL_DZ." fi fi mv $WORKDIR/fit.root $MODULE_ROOT typeset -Z 4 STRING typeset -Z 2 FLOOR JPlot1D -f $
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
bool fixParameter(TF1 &f1, const JFitParameter_t ¶meter)
Fix fit parameter.
do set_variable DETECTOR_TXT $WORKDIR detector
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY source JAcoustics sh $DETECTOR_ID typeset A TRIPODS get_tripods $WORKDIR tripod txt TRIPODS for EMITTER in
Fit parameters for two-fold coincidence rate due to K40.
static const char *const _1D
Name extension for 1D time offset.
#define DEBUG(A)
Message macros.