58{
62
65
66 string inputFile;
68 string detectorFile;
69 string pmtFile;
70 bool writeFits;
71
72 double Wmin = 5e3;
73 double LeftMargin = 10.0;
74 double RightMargin = 10.0;
75 double gradientThreshold = -0.005;
76
81
83 string option;
84
85 string regexp;
87
88 try {
89
91
98
99 JParser<> zap(
"Auxiliary program to fit time-over-threshold distributions.");
100
101 zap[
'f'] =
make_field(inputFile,
"input file (output from JCalibrateToT).");
103 zap[
'a'] =
make_field(detectorFile,
"detector file.");
104 zap[
'P'] =
make_field(pmtFile,
"specify PMT file name that can be given to JTriggerEfficiency.") =
"";
105 zap[
'w'] =
make_field(writeFits,
"write fit results.");
106 zap[
'O'] =
make_field(option,
"ROOT fit options, see TH1::Fit") =
"";
108 zap[
'x'] =
make_field(ToTfitRange,
"ROOT fit range (time-over-threshold).") =
JRange_t(0.0, 35.0);
111
112 zap(argc, argv);
113 }
114 catch(const exception &error) {
115 FATAL(error.what() << endl);
116 }
117
118
119
120
121
122
124
125 try {
127 }
130 }
131
132
134
135 if (!pmtFile.empty()) {
136
137 try {
138 parametersMap.
load(pmtFile.c_str());
139 }
141 }
142
143
144 if (option.find('R') == string::npos) { option += 'R'; }
145 if (option.find('S') == string::npos) { option += 'S'; }
147
148
149 TFile* in = TFile::Open(inputFile.c_str(), "exist");
150
151 if (in == NULL || !in->IsOpen()) {
152 FATAL(
"File: " << inputFile <<
" not opened." << endl);
153 }
154
155
156 TH2D gain("gain", NULL,
157 100, 0.0, 2.0,
158 100, 0.0, 1.0);
159 TH1D chi2("chi2", NULL, 100, 0.0, 5.0);
160
162
165 }
166
168
169
170
171
172
173 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ++module) {
174
175 NOTICE(
"Module " << setw(10) << module->getID() <<
' ' << module->getLocation() << endl);
176
177 if (module->empty()) {
178 continue;
179 }
180
181
182
183
184
186
187 if (h2s == NULL) {
188
189 WARNING(
"No histogram " << module->getID() <<
"; skip fit." << endl);
190
191 continue;
192 }
193
194 const double ny = h2s->GetYaxis()->GetNbins();
195 const double ymin = h2s->GetYaxis()->GetXmin();
196 const double ymax = h2s->GetYaxis()->GetXmax();
197
198 TH1D chi2_1d (
MAKE_CSTRING(module->getID() <<
".1chi2"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS-0.5);
199 TH1D gain_1d (
MAKE_CSTRING(module->getID() <<
".1gain"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS-0.5);
200 TH1D gainspread_1d(
MAKE_CSTRING(module->getID() <<
".1gainspread"), NULL, NUMBER_OF_PMTS, -0.5, NUMBER_OF_PMTS-0.5);
201
202 for (int ix = 1; ix <= h2s->GetXaxis()->GetNbins(); ++ix) {
203
205
206 const string name =
MAKE_STRING(module->getID() <<
'.' <<
FILL(2,
'0') <<
208
209 DEBUG(
"Processing histogram " << name << endl);
210
211 TH1D h1(name.c_str(), NULL, ny, ymin, ymax);
212
213 h1.Sumw2();
214
215 for (int iy = h2s->GetNbinsY(); iy >= 1; --iy) {
216
217 const double w = h1.GetBinWidth (iy);
218 const double y = h2s->GetBinContent(ix, iy);
219
220 h1.SetBinContent(iy, y/w);
221 h1.SetBinError (iy, sqrt(y)/w);
222 }
223
225
226 const double weight = h1.Integral(h1.FindBin(range.getLowerLimit()),
227 h1.FindBin(range.getUpperLimit()));
228
229 if (weight <= Wmin) {
230
231 WARNING(
"Insufficient histogram entries for PMT " <<
id <<
232 "(" << weight << " < " << Wmin << "); skip fit." << endl);
233
234 if (writeFits) {
236 }
237
238 continue;
239 }
240
241
242
243
244
245 double max = 0.0;
247
249
251 RIGHT(10) <<
"threshold" <<
RIGHT(10) <<
"Mode" <<
RIGHT(10) <<
"Max" << endl);
252
253 for (int i = h1.GetBinCenter(ny-1);
254 i > h1.GetBinCenter(h1.FindBin(parameters.
mean_ns + parameters.
sigma_ns));
255 --i) {
256
257 const double x = h1.GetBinCenter (i);
258 const double y = h1.GetBinContent(i);
259
260 const double gradient = ( (h1.GetBinContent(i-1) - h1.GetBinContent(i+1)) /
261 (h1.GetBinCenter (i+1) - h1.GetBinCenter (i-1)) );
262
264 FIXED(10,1) << -fabs(gradientThreshold) * h1.Integral() <<
FIXED(10,1) << ToTmode <<
FIXED(10,1) << max << endl);
265
266
267 if (y > max) {
268
271
272 } else if (gradient < -fabs(gradientThreshold) * h1.Integral()) {
273
274 break;
275 }
276 }
277
278
279
280
281
282 if (!range.is_valid()) {
283 range.setRange(ToTmode - LeftMargin,
284 ToTmode + RightMargin);
285 }
286
287 range.setRange(std::max(h1.GetXaxis()->GetXmin(), range.getLowerLimit()),
288 std::min(h1.GetXaxis()->GetXmax(), range.getUpperLimit()));
289
291
292
293
294
295
296 JFitToT fit(parameters, range);
297
298 setParLimits(fit, fit.getModelParameter(&JFitToT::JFitToTParameters::gain),
299 gainLimits.getLowerLimit(), gainLimits.getUpperLimit());
300 setParLimits(fit, fit.getModelParameter(&JFitToT::JFitToTParameters::gainSpread),
301 gainSpreadLimits.getLowerLimit(), gainSpreadLimits.getUpperLimit());
302
303 const double initGain = fit.getCPU().getNPE(ToTmode);
304 const double initGainSpread = initGain / 3.0;
305
306 if (!gainLimits(initGain)) {
307
308 WARNING(
"Invalid initial gain for PMT " <<
id <<
"; set default values." << endl);
309
310 parameters.
gain = gainLimits .constrain(initGain);
311 parameters.
gainSpread = gainSpreadLimits.constrain(initGainSpread);
312
313 if (writeFits) {
315 }
316
317 continue;
318 }
319
320 fit.gain = initGain;
321 fit.gainSpread = initGainSpread;
322
323 const TFitResultPtr
result = fit(h1, option);
324
325 if (
result.Get() == NULL) {
326 FATAL(
"Invalid TFitResultPtr " << h1.GetName() << endl);
327 }
328
330
331 WARNING(
"Fit failure for PMT " <<
id <<
"; set initialization values." << endl);
332
333 h1.GetListOfFunctions()->Clear();
334
335 parameters.
gain = initGain;
337
338 if (writeFits) {
340 }
341
342 continue;
343 }
344
345 if ((ymin < range.getLowerLimit() || ymax > range.getUpperLimit()) &&
346 (option.find("0") == string::npos && option.find("N") == string::npos)) {
347
348
349
351 &fit,
353 ymin,
355 JFitToT::getNumberOfModelParameters());
356 f1->SetParameters(fit.GetParameters());
357 f1->SetLineStyle(kDotted);
359
360 h1.GetListOfFunctions()->Add(f1);
361 }
362
363
364
365 const double reducedChi2 =
result->Chi2() /
result->Ndf();
366
369
370 chi2_1d. SetBinContent(ix, reducedChi2);
371 gain_1d. SetBinContent(ix, values.gain);
372 gain_1d. SetBinError (ix, errors.gain);
373 gainspread_1d.SetBinContent(ix, values.gainSpread);
374 gainspread_1d.SetBinError (ix, errors.gainSpread);
375
376 gain.Fill(fit.gain, fit.gainSpread);
377 chi2.Fill(TMath::Log10(reducedChi2));
378
379 NOTICE(
"PMT " <<
id <<
" chi2 / NDF " <<
result->Chi2() <<
' ' <<
result->Ndf() << endl);
380
381 parameters.
gain = fit.gain;
383
384 if (writeFits) {
386 }
387 }
388
389 if (writeFits) {
393 }
394 }
395
396 {
398
400
401 const JMeta* meta = in.next();
402
403 buffer.push_back(*meta);
404
406 }
407
408 for (vector<JMeta>::const_reverse_iterator i = buffer.rbegin(); i != buffer.rend(); ++i) {
410 }
411 }
412
415 }
416
417
418 if (pmtFile != "") {
419 parametersMap.
store(pmtFile.c_str());
420 }
421
424
426}
#define DEBUG(A)
Message macros.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
#define MAKE_CSTRING(A)
Make C-string.
#define MAKE_STRING(A)
Make string.
#define gmake_property(A)
macros to convert (template) parameter to JPropertiesElement object
Auxiliary class for map of PMT parameters.
Data structure for PMT parameters.
double sigma_ns
time-over-threshold standard deviation of threshold-band hits [ns]
double gainSpread
gain spread [unit]
double mean_ns
mean time-over-threshold of threshold-band hits [ns]
double saturation
saturation [ns]
Utility class to parse parameter values.
Utility class to parse command line options.
Object reading from a list of files.
virtual bool hasNext() override
Check availability of next element.
const JPolynome f1(1.0, 2.0, 3.0)
Function.
static const char *const _2SToT
Histogram naming.
static const double FITTOT_GAINSPREAD_MAX
Default maximal gain spread.
static const std::string FITTOT_FNAME
static const std::string FITTOT_SUFFIX
static const double FITTOT_GAIN_MAX
Default maximal gain.
static const double FITTOT_GAIN_MIN
Default minimal gain.
static const double FITTOT_GAINSPREAD_MIN
Default minimal gain spread.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
const double TIME_OVER_THRESHOLD_NS
Specification for time-over-threshold corresponding to a one photo-electron pulse.
std::string replace(const std::string &input, const std::string &target, const std::string &replacement)
Replace tokens in string.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
bool setParLimits(TF1 &f1, const Int_t index, Double_t xmin, Double_t xmax)
Set fit parameter limits.
KM3NeT DAQ data structures and auxiliaries.
static const char WILDCARD
Auxiliary data structure for sequence of same character.
Auxiliary data structure for floating point format specification.
Type definition of range.
Fit parameters for two-fold coincidence rate due to K40.
Parametrisation of time-over-threshold distribution.
Double_t getValue(const Double_t *x, const Double_t *par)
Get rate as a function of the fit parameters.
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)...