ATLAS Offline Software
ZDCPulseAnalyzer.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include "TFitResult.h"
8 #include "TFitResultPtr.h"
9 #include "TVirtualFitter.h"
10 #include "TList.h"
11 #include "TMinuit.h"
12 
13 #include <algorithm>
14 #include <sstream>
15 #include <cmath>
16 #include <numeric>
17 #include <iomanip>
18 #include <stdexcept>
19 
21 //
22 // List of allowed JSON configuration parameters
23 //
24 // For each parameter we have name, JSON value type, whether it can be set per channel, and whether it is required
25 //
26 // if the type is -1, then there's no value, the presence of the parameter itself is a boolean -- i.e. enabling
27 //
29  {"tag", {JSON::value_t::string, 1, true, true}},
30  {"enabled", {JSON::value_t::boolean, 1, true, true}},
31  {"LGMode", {JSON::value_t::number_unsigned, 1, false, true}},
32  {"Nsample", {JSON::value_t::number_integer, 1, false, true}},
33  {"FADCFreqMHz", {JSON::value_t::number_integer, 1, false, true}},
34  {"preSampleIdx", {JSON::value_t::number_integer, 1, true, true}},
35  {"nominalPedestal", {JSON::value_t::number_integer, 1, false, true}},
36  {"fitFunction", {JSON::value_t::string, 1, true, true}},
37  {"peakSample", {JSON::value_t::number_integer, 1, true, true}},
38  {"peakTolerance", {JSON::value_t::number_integer, 1, true, false}},
39  {"2ndDerivThreshHG", {JSON::value_t::number_integer, 1, true, true}},
40  {"2ndDerivThreshLG", {JSON::value_t::number_integer, 1, true, true}},
41  {"2ndDerivStep", {JSON::value_t::number_integer, 1, false, false}},
42  {"HGOverflowADC", {JSON::value_t::number_integer, 1, true, true}},
43  {"HGUnderflowADC", {JSON::value_t::number_integer, 1, true, true}},
44  {"LGOverflowADC", {JSON::value_t::number_integer, 1, true, true}},
45  {"nominalT0HG", {JSON::value_t::number_float, 1, true, true}},
46  {"nominalT0LG", {JSON::value_t::number_float, 1, true, true}},
47  {"nominalTau1", {JSON::value_t::number_float, 1, true, false}},
48  {"nominalTau2", {JSON::value_t::number_float, 1, true, false}},
49  {"fixTau1", {JSON::value_t::boolean, 1, true, false}},
50  {"fixTau2", {JSON::value_t::boolean, 1, true, false}},
51  {"T0CutsHG", {JSON::value_t::array, 2, true, true}},
52  {"T0CutsLG", {JSON::value_t::array, 2, true, true}},
53  {"chisqDivAmpCutHG", {JSON::value_t::number_float, 1, true, true}},
54  {"chisqDivAmpCutLG", {JSON::value_t::number_float, 1, true, true}},
55  {"gainFactorHG", {JSON::value_t::number_float, 1, true, true}},
56  {"gainFactorLG", {JSON::value_t::number_float, 1, true, true}},
57  {"noiseSigmaHG", {JSON::value_t::number_float, 1, true, true}},
58  {"noiseSigmaLG", {JSON::value_t::number_float, 1, true, true}},
59  {"enableRepass", {JSON::value_t::boolean, 1, false, false}},
60  {"Repass2ndDerivThreshHG", {JSON::value_t::number_integer, 1, true, true}},
61  {"Repass2ndDerivThreshLG", {JSON::value_t::number_integer, 1, true, true}},
62  {"fitAmpMinMaxHG", {JSON::value_t::array, 2, true, false}},
63  {"fitAmpMinMaxLG", {JSON::value_t::array, 2, true, false}},
64  {"ampMinSignifHGLG", {JSON::value_t::array, 2, true, false}},
65  {"enablePreExclusion", {JSON::value_t::array, 3, false, false}},
66  {"enablePostExclusion", {JSON::value_t::array, 3, false, false}},
67  {"enableTimingCorrection", {JSON::value_t::array, 2, false, false}},
68  {"timeCorrCoeffHG", {JSON::value_t::array, 0, true, false}},
69  {"timeCorrCoeffLG", {JSON::value_t::array, 0, true, false}},
70  {"enableADCNLCorrection", {JSON::value_t::array, 3, false, false}},
71  {"ADCNLCorrCoeffs", {JSON::value_t::array, 0, true, false}},
72  {"useDelayed", {JSON::value_t::boolean, 1, false, false}},
73  {"delayDeltaT", {JSON::value_t::number_float, 1, true, false}}
74 };
75 
76 
81 float ZDCPulseAnalyzer::s_combinedFitTMin = -0.5; // add to allow switch to high gain by skipping early samples
82 std::vector<float> ZDCPulseAnalyzer::s_pullValues;
83 
84 void ZDCPulseAnalyzer::CombinedPulsesFCN(int& /*numParam*/, double*, double& f, double* par, int flag)
85 {
86  // The first parameter is a correction factor to account for decrease in beam intensity between x
87  // and y scan. It is applied here and not passed to the actual fit function
88  //
89  int nSamples = s_undelayedFitHist->GetNbinsX();
90 
91  if (flag == 3) {
92  s_pullValues.assign(nSamples * 2, 0);
93  }
94 
95  double chiSquare = 0;
96 
97  float delayBaselineAdjust = par[0];
98 
99  // undelayed
100  //
101  for (int isample = 0; isample < nSamples; isample++) {
102  double histValue = s_undelayedFitHist->GetBinContent(isample + 1);
103  double histError = std::max(s_undelayedFitHist->GetBinError(isample + 1), 1.0);
104  double t = s_undelayedFitHist->GetBinCenter(isample + 1);
105 
106  if (t > s_combinedFitTMax) break;
107  if (t < s_combinedFitTMin) continue;
108 
109  double funcVal = s_combinedFitFunc->EvalPar(&t, &par[1]);
110 
111  double pull = (histValue - funcVal) / histError;
112 
113  if (flag == 3) s_pullValues[2 * isample] = pull;
114  chiSquare += pull * pull;
115  }
116 
117  // delayed
118  //
119  for (int isample = 0; isample < nSamples; isample++) {
120  double histValue = s_delayedFitHist->GetBinContent(isample + 1);
121  double histError = std::max(s_delayedFitHist->GetBinError(isample + 1), 1.0);
122  double t = s_delayedFitHist->GetBinCenter(isample + 1);
123 
124  if (t > s_combinedFitTMax) break;
125  if (t < s_combinedFitTMin) continue;
126 
127  double funcVal = s_combinedFitFunc->EvalPar(&t, &par[1]) + delayBaselineAdjust;
128  double pull = (histValue - funcVal) / histError;
129 
130  if (flag == 3) s_pullValues[2 * isample + 1] = pull;
131  chiSquare += pull * pull;
132  }
133 
134  f = chiSquare;
135 }
136 
137 
138 ZDCPulseAnalyzer::ZDCPulseAnalyzer(ZDCMsg::MessageFunctionPtr msgFunc_p, const std::string& tag, int Nsample, float deltaTSample, size_t preSampleIdx, int pedestal,
139  float gainHG, const std::string& fitFunction, int peak2ndDerivMinSample,
140  float peak2ndDerivMinThreshHG, float peak2ndDerivMinThreshLG) :
141  m_msgFunc_p(std::move(msgFunc_p)),
142  m_tag(tag), m_Nsample(Nsample),
143  m_preSampleIdx(preSampleIdx),
144  m_deltaTSample(deltaTSample),
145  m_pedestal(pedestal), m_gainHG(gainHG), m_fitFunction(fitFunction),
146  m_peak2ndDerivMinSample(peak2ndDerivMinSample),
147  m_peak2ndDerivMinThreshLG(peak2ndDerivMinThreshLG),
148  m_peak2ndDerivMinThreshHG(peak2ndDerivMinThreshHG),
149  m_ADCSamplesHGSub(Nsample, 0), m_ADCSamplesLGSub(Nsample, 0),
150  m_ADCSSampSigHG(Nsample, 0), m_ADCSSampSigLG(Nsample, 0),
151  m_samplesSub(Nsample, 0)
152 {
153  // Create the histogram used for fitting
154  //
155  m_tmin = -deltaTSample / 2;
156  m_tmax = m_tmin + ((float) Nsample) * deltaTSample;
158 
159  std::string histName = "ZDCFitHist" + tag;
160  std::string histNameLGRefit = "ZDCFitHist" + tag + "_LGRefit";
161 
162  m_fitHist = std::make_unique<TH1F>(histName.c_str(), "", m_Nsample, m_tmin, m_tmax);
163  m_fitHistLGRefit = std::make_unique<TH1F>(histNameLGRefit.c_str(), "", m_Nsample, m_tmin, m_tmax);
164 
165  m_fitHist->SetDirectory(0);
166  m_fitHistLGRefit->SetDirectory(0);
167 
168  SetDefaults();
169  Reset();
170 }
171 
173  m_msgFunc_p(msgFunc_p)
174 {
175  SetDefaults();
176 
177  // auto [result, resultString] = ValidateJSONConfig(configJSON);
178  // (*m_msgFunc_p)(ZDCMsg::Debug, "ValidateJSON produced result: " + resultString);
179 
180  auto [result2, resultString2] = ConfigFromJSON(configJSON);
181  (*m_msgFunc_p)(ZDCMsg::Debug, "ConfigFromJSON produced result: "+ resultString2);
182 
184 
185  // Create the histogram used for fitting
186  //
187  m_deltaTSample = 1000./m_freqMHz;
188  m_tmin = -m_deltaTSample / 2;
191 
192  std::string histName = "ZDCFitHist" + m_tag;
193  std::string histNameLGRefit = "ZDCFitHist" + m_tag + "_LGRefit";
194 
195  m_fitHist = std::make_unique<TH1F>(histName.c_str(), "", m_Nsample, m_tmin, m_tmax);
196  m_fitHistLGRefit = std::make_unique<TH1F>(histNameLGRefit.c_str(), "", m_Nsample, m_tmin, m_tmax);
197 
198  m_fitHist->SetDirectory(0);
199  m_fitHistLGRefit->SetDirectory(0);
200 
201  Reset();
202 }
203 
204 void ZDCPulseAnalyzer::enableDelayed(float deltaT, float pedestalShift, bool fixedBaseline)
205 {
206  m_useDelayed = true;
207  m_useFixedBaseline = fixedBaseline;
208 
209  m_delayedDeltaT = deltaT;
210  m_delayedPedestalDiff = pedestalShift;
211 
212  m_deltaTSample /= 2.;
213 
214  std::string delayedHGName = std::string(m_fitHist->GetName()) + "delayed";
215  std::string delayedLGName = std::string(m_fitHistLGRefit->GetName()) + "delayed";
216 
217  m_delayedHist = std::make_unique<TH1F>(delayedHGName.c_str(), "", m_Nsample, m_tmin + m_delayedDeltaT, m_tmax + m_delayedDeltaT);
218  m_delayedHist->SetDirectory(0);
219 
220  m_delayedHistLGRefit = std::make_unique<TH1F>(delayedLGName.c_str(), "", m_Nsample, m_tmin + m_delayedDeltaT, m_tmax + m_delayedDeltaT);
221  m_delayedHistLGRefit->SetDirectory(0);
222 
223  m_ADCSamplesHGSub.assign(2 * m_Nsample, 0);
224  m_ADCSamplesLGSub.assign(2 * m_Nsample, 0);
225 }
226 
227 void ZDCPulseAnalyzer::enableRepass(float peak2ndDerivMinRepassHG, float peak2ndDerivMinRepassLG)
228 {
229  m_enableRepass = true;
230  m_peak2ndDerivMinRepassHG = peak2ndDerivMinRepassHG;
231  m_peak2ndDerivMinRepassLG = peak2ndDerivMinRepassLG;
232 }
233 
235 {
237 
238  m_nominalTau1 = 1.5;
239  m_nominalTau2 = 5;
240 
241  m_fixTau1 = false;
242  m_fixTau2 = false;
243 
244  m_HGOverflowADC = 3500;
245  m_HGUnderflowADC = 1;
246  m_LGOverflowADC = 3900;
247 
248  // Default values for the gain factors uswed to match low and high gain
249  //
250  m_gainFactorLG = 10;
251  m_gainFactorHG = 1;
252 
253  m_2ndDerivStep = 1;
254 
255  m_noiseSigHG = 1;
256  m_noiseSigLG = 1;
257 
258  m_timeCutMode = 0;
259  m_chisqDivAmpCutLG = 100;
260  m_chisqDivAmpCutHG = 100;
261 
262  m_LGT0CorrParams.assign(4, 0);
263  m_HGT0CorrParams.assign(4, 0);
264 
265  // m_defaultFitTMax = m_tmax;
266  // m_defaultFitTMin = m_tmin;
267 
268  m_fitAmpMinHG = 1;
269  m_fitAmpMinLG = 1;
270 
271  m_fitAmpMaxHG = 1500;
272  m_fitAmpMaxLG = 1500;
273 
274  m_haveSignifCuts = false;
275 
276  m_postPulse = false;
277  m_prePulse = false;
278 
279  m_initialPrePulseT0 = -10;
281 
282  m_initialPostPulseT0 = 100;
283 
284  m_initialExpAmp = 0;
285  m_fitPostT0lo = 0;
286 
287  m_useDelayed = false;
288  m_enablePreExcl = false;
289  m_enablePostExcl = false;
290 
292  m_haveNonlinCorr = false;
293  m_quietFits = true;
294  m_fitOptions = "s";
295 }
296 
297 void ZDCPulseAnalyzer::Reset(bool repass)
298 {
299  if (!repass) {
300  m_haveData = false;
301 
302  m_useLowGain = false;
303  m_fail = false;
304  m_HGOverflow = false;
305 
306  m_HGUnderflow = false;
307  m_PSHGOverUnderflow = false;
308  m_LGOverflow = false;
309  m_LGUnderflow = false;
310 
311  m_ExcludeEarly = false;
312  m_ExcludeLate = false;
313 
314  m_adjTimeRangeEvent = false;
315  m_backToHG_pre = false;
316  m_fixPrePulse = false;
317 
318  m_minADCLG = -1;
319  m_maxADCLG = -1;
320  m_minADCHG = -1;
321  m_maxADCHG = -1;
322 
323  m_minADCSampleHG = -1;
324  m_maxADCSampleHG = -1;
325  m_minADCSampleLG = -1;
326  m_maxADCSampleLG = -1;
327 
328  m_ADCPeakHG = -1;
329  m_ADCPeakLG = -1;
330 
331  int sampleVecSize = m_Nsample;
332  if (m_useDelayed) sampleVecSize *= 2;
333 
334  m_ADCSamplesHG.clear();
335  m_ADCSamplesLG.clear();
336 
337  m_ADCSamplesHGSub.clear();
338  m_ADCSamplesLGSub.clear();
339 
340  m_ADCSSampSigHG.assign(sampleVecSize, m_noiseSigHG);
341  m_ADCSSampSigLG.assign(sampleVecSize, m_noiseSigLG);
342 
343  m_minSampleEvt = 0;
344  m_maxSampleEvt = (m_useDelayed ? 2 * m_Nsample - 1 : m_Nsample - 1);
345 
346  m_usedPresampIdx = 0;
347 
350 
351  m_lastHGOverFlowSample = -999;
353  }
354 
355 
358 
359  if (m_initializedFits) {
363  }
364 
365  // -----------------------
366  // Statuses
367  //
368  m_havePulse = false;
369 
370  m_prePulse = false;
371  m_postPulse = false;
372  m_fitFailed = false;
373  m_badChisq = false;
374 
375  m_badT0 = false;
376  m_preExpTail = false;
377  m_repassPulse = false;
378 
379  m_fitMinAmp = false;
380  m_evtLGRefit = false;
381  m_failSigCut = false;
382 
383  // -----------------------
384 
386 
387  m_fitAmplitude = 0;
388  m_ampNoNonLin = 0;
389  m_fitTime = -100;
390  m_fitTimeSub = -100;
391  m_fitTimeCorr = -100;
392  m_fitTCorr2nd = -100;
393 
394  m_fitPreT0 = -100;
395  m_fitPreAmp = -100;
396  m_fitPostT0 = -100;
397  m_fitPostAmp = -100;
398  m_fitExpAmp = -100;
399 
400  m_minDeriv2ndSig = -10;
401  m_preExpSig = -10;
402  m_prePulseSig = -10;
403 
404  m_fitChisq = 0;
405 
406  m_amplitude = 0;
407  m_ampError = 0;
408  m_preSampleAmp = 0;
409  m_preAmplitude = 0;
410  m_postAmplitude = 0;
411  m_expAmplitude = 0;
412  m_bkgdMaxFraction = 0;
413 
414  m_refitLGAmpl = 0;
415  m_refitLGAmpError = 0;
416  m_refitLGChisq = 0;
417  m_refitLGTime = -100;
418  m_refitLGTimeSub = -100;
419 
420  m_initialPrePulseT0 = -10;
422 
423  m_initialPostPulseT0 = 100;
424 
425  m_initialExpAmp = 0;
426  m_fitPostT0lo = 0;
427 
428  m_fitPulls.clear();
429 
430  m_sigMinLG = 0;
431  m_sigMinHG = 0;
432 
433  m_samplesSub.clear();
434  m_samplesDeriv2nd.clear();
435 }
436 
437 
438 void ZDCPulseAnalyzer::setMinimumSignificance(float sigMinHG, float sigMinLG)
439 {
440  m_haveSignifCuts = true;
441  m_sigMinHG = sigMinHG;
442  m_sigMinLG = sigMinLG;
443 }
444 
445 void ZDCPulseAnalyzer::SetGainFactorsHGLG(float gainFactorHG, float gainFactorLG)
446 {
447  m_gainFactorHG = gainFactorHG;
448  m_gainFactorLG = gainFactorLG;
449 }
450 
451 void ZDCPulseAnalyzer::SetFitMinMaxAmp(float minAmpHG, float minAmpLG, float maxAmpHG, float maxAmpLG)
452 {
453  m_fitAmpMinHG = minAmpHG;
454  m_fitAmpMinLG = minAmpLG;
455 
456  m_fitAmpMaxHG = maxAmpHG;
457  m_fitAmpMaxLG = maxAmpLG;
458 }
459 
460 void ZDCPulseAnalyzer::SetTauT0Values(bool fixTau1, bool fixTau2, float tau1, float tau2, float t0HG, float t0LG)
461 {
462  m_fixTau1 = fixTau1;
463  m_fixTau2 = fixTau2;
464  m_nominalTau1 = tau1;
465  m_nominalTau2 = tau2;
466 
467  m_nominalT0HG = t0HG;
468  m_nominalT0LG = t0LG;
469 
470  std::ostringstream ostrm;
471  ostrm << "ZDCPulseAnalyzer::SetTauT0Values:: m_fixTau1=" << m_fixTau1 << " m_fixTau2=" << m_fixTau2 << " m_nominalTau1=" << m_nominalTau1 << " m_nominalTau2=" << m_nominalTau2 << " m_nominalT0HG=" << m_nominalT0HG << " m_nominalT0LG=" << m_nominalT0LG;
472 
473  (*m_msgFunc_p)(ZDCMsg::Info, ostrm.str());
474 
475  m_initializedFits = false;
476 }
477 
479 {
480  if (tmax < m_tmin) {
481  (*m_msgFunc_p)(ZDCMsg::Error, ("ZDCPulseAnalyzer::SetFitTimeMax:: invalid FitTimeMax: " + std::to_string(tmax)));
482  return;
483  }
484 
486 
488 }
489 
490 void ZDCPulseAnalyzer::SetADCOverUnderflowValues(int HGOverflowADC, int HGUnderflowADC, int LGOverflowADC)
491 {
492  m_HGOverflowADC = HGOverflowADC;
493  m_LGOverflowADC = LGOverflowADC;
494  m_HGUnderflowADC = HGUnderflowADC;
495 }
496 
497 void ZDCPulseAnalyzer::SetCutValues(float chisqDivAmpCutHG, float chisqDivAmpCutLG,
498  float deltaT0MinHG, float deltaT0MaxHG,
499  float deltaT0MinLG, float deltaT0MaxLG)
500 {
501  m_chisqDivAmpCutHG = chisqDivAmpCutHG;
502  m_chisqDivAmpCutLG = chisqDivAmpCutLG;
503 
504  m_T0CutLowHG = deltaT0MinHG;
505  m_T0CutLowLG = deltaT0MinLG;
506 
507  m_T0CutHighHG = deltaT0MaxHG;
508  m_T0CutHighLG = deltaT0MaxLG;
509 }
510 
511 void ZDCPulseAnalyzer::enableTimeSigCut(bool AND, float sigCut, const std::string& TF1String,
512  const std::vector<double>& parsHG,
513  const std::vector<double>& parsLG)
514 {
515  m_timeCutMode = AND ? 2 : 1;
516  m_t0CutSig = sigCut;
517 
518  // Make the TF1's that provide the resolution
519  //
520  std::string timeResHGName = "TimeResFuncHG_" + m_tag;
521  std::string timeResLGName = "TimeResFuncLG_" + m_tag;
522 
523  TF1* funcHG_p = new TF1(timeResHGName.c_str(), TF1String.c_str(), 0, m_HGOverflowADC);
524  TF1* funcLG_p = new TF1(timeResLGName.c_str(), TF1String.c_str(), 0, m_LGOverflowADC);
525 
526  if (parsHG.size() != static_cast<unsigned int>(funcHG_p->GetNpar()) ||
527  parsLG.size() != static_cast<unsigned int>(funcLG_p->GetNpar())) {
528  //
529  // generate an error message
530  }
531 
532  funcHG_p->SetParameters(&parsHG[0]);
533  funcLG_p->SetParameters(&parsLG[0]);
534 
535  m_timeResFuncHG_p.reset(funcHG_p);
536  m_timeResFuncLG_p.reset(funcLG_p);
537 
538 }
539 
540 void ZDCPulseAnalyzer::enableFADCCorrections(bool correctPerSample, std::unique_ptr<const TH1>& correHistHG, std::unique_ptr<const TH1>& correHistLG)
541 {
542  m_haveFADCCorrections = true;
543  m_FADCCorrPerSample = correctPerSample;
544 
545  // check for appropriate limits
546  //
547  auto getXmin=[](const TH1 * pH){
548  return pH->GetXaxis()->GetXmin();
549  };
550  auto getXmax=[](const TH1 * pH){
551  return pH->GetXaxis()->GetXmax();
552  };
553  auto xmin= getXmin(correHistHG.get());
554  auto xmax= getXmax(correHistHG.get());
555  if (std::abs(xmin+0.5) > 1e-3 || std::abs(xmax - 4095.5) > 1e-3) {
556  (*m_msgFunc_p)(ZDCMsg::Error, "ZDCPulseAnalyzer::enableFADCCorrections:: invalid high gain correction histogram range: xmin, xmax = " +
557  std::to_string(xmin ) + ", " + std::to_string(xmax) );
558  }
559  else {
560  m_FADCCorrHG = std::move(correHistHG);
561  }
562  xmin= getXmin(correHistLG.get());
563  xmax= getXmax(correHistLG.get());
564  if (std::abs(xmin+0.5) > 1e-3 ||
565  std::abs(xmax - 4095.5) > 1e-3) {
566  (*m_msgFunc_p)(ZDCMsg::Error, "ZDCPulseAnalyzer::enableFADCCorrections:: invalid low gain correction histogram range: xmin, xmax = " +
567  std::to_string(xmin) + ", " + std::to_string(xmax) );
568  }
569  else {
570  m_FADCCorrLG = std::move(correHistLG);
571  }
572 }
573 
574 std::vector<float> ZDCPulseAnalyzer::GetFitPulls(bool refitLG) const
575 {
576  //
577  // If there was no pulse for this event, return an empty vector (see reset() method)
578  //
579  if (!m_havePulse) {
580  return m_fitPulls;
581  }
582 
583  //
584  // The combined (delayed+undelayed) pulse fitting fills out m_fitPulls directly
585  //
586  if (m_useDelayed) {
587  return m_fitPulls;
588  }
589  else {
590  //
591  // When not using combined fitting, We don't have the pre-calculated pulls. Calculate them on the fly.
592  //
593  std::vector<float> pulls(m_Nsample, -100);
594 
595  const TH1* dataHist_p = refitLG ? m_fitHistLGRefit.get() : m_fitHist.get();
596  const TF1* fit_p = static_cast<const TF1*>(dataHist_p->GetListOfFunctions()->Last());
597 
598  for (size_t ibin = 0; ibin < m_Nsample ; ibin++) {
599  float t = dataHist_p->GetBinCenter(ibin + 1);
600  float fitVal = fit_p->Eval(t);
601  float histVal = dataHist_p->GetBinContent(ibin + 1);
602  float histErr = dataHist_p->GetBinError(ibin + 1);
603  float pull = (histVal - fitVal)/histErr;
604  pulls[ibin] = pull;
605  }
606 
607  return pulls;
608  }
609 }
610 
612 {
613  double amplCorrFactor = 1;
614 
615  // If we have FADC correction and we aren't applying it per-sample, do so here
616  //
618  double fadcCorr = highGain ? m_FADCCorrHG->Interpolate(m_fitAmplitude) : m_FADCCorrLG->Interpolate(m_fitAmplitude);
619  amplCorrFactor *= fadcCorr;
620  }
621 
622  double amplCorr = m_fitAmplitude * amplCorrFactor;
623 
624  // If we have a non-linear correction, apply it here
625  // We apply it as an inverse correction - i.e. we divide by a correction
626  // term tha is a sum of coefficients times the ADC minus a reference
627  // to a power. The lowest power is 1, the highest is deteremined by
628  // the number of provided coefficients
629 
630  if (m_haveNonlinCorr) {
631  float invNLCorr = 1.0;
632  float nlPolyArg = (amplCorr - m_nonLinCorrRefADC) / m_nonLinCorrRefScale;
633 
634  if (highGain) {
635  for (size_t power = 1; power <= m_nonLinCorrParamsHG.size(); power++) {
636  invNLCorr += m_nonLinCorrParamsHG[power - 1]*pow(nlPolyArg, power);
637  }
638  }
639  else {
640  for (size_t power = 1; power <= m_nonLinCorrParamsLG.size(); power++) {
641  invNLCorr += m_nonLinCorrParamsLG[power - 1]*pow(nlPolyArg, power);
642  }
643  }
644 
645  amplCorrFactor /= invNLCorr;
646  }
647 
648  return amplCorrFactor;
649 }
650 
652 {
653  float prePulseTMin = 0;
654  float prePulseTMax = prePulseTMin + m_deltaTSample * (m_peak2ndDerivMinSample - m_peak2ndDerivMinTolerance);
655 
656  if (m_fitFunction == "FermiExp") {
657  if (!m_fixTau1 || !m_fixTau2) {
658  //
659  // Use the variable tau version of the expFermiFit
660  //
662  }
663  else {
664  m_defaultFitWrapper = std::unique_ptr<ZDCFitWrapper>(new ZDCFitExpFermiFixedTaus(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
665  }
666 
667  m_preExpFitWrapper = std::unique_ptr<ZDCFitExpFermiPreExp>(new ZDCFitExpFermiPreExp(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2, m_nominalTau2, false));
668  m_prePulseFitWrapper = std::unique_ptr<ZDCPrePulseFitWrapper>(new ZDCFitExpFermiPrePulse(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
669  }
670  else if (m_fitFunction == "FermiExpRun3") {
671  if (!m_fixTau1 || !m_fixTau2) {
672  //
673  // Use the variable tau version of the expFermiFit
674  //
676  }
677  else {
678  m_defaultFitWrapper = std::unique_ptr<ZDCFitWrapper>(new ZDCFitExpFermiFixedTaus(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
679  }
680 
681  m_preExpFitWrapper = std::unique_ptr<ZDCFitExpFermiPreExp>(new ZDCFitExpFermiPreExp(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2, 6, false));
682  m_prePulseFitWrapper = std::unique_ptr<ZDCPrePulseFitWrapper>(new ZDCFitExpFermiPrePulse(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
683  }
684  else if (m_fitFunction == "FermiExpLHCf") {
685  //
686  // Use the variable tau version of the expFermiFit
687  //
690 
691  m_preExpFitWrapper = std::unique_ptr<ZDCFitExpFermiLHCfPreExp>(new ZDCFitExpFermiLHCfPreExp(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2, 6, false));
692 
693  m_prePulseFitWrapper = std::unique_ptr<ZDCPrePulseFitWrapper>(new ZDCFitExpFermiLHCfPrePulse(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
694  }
695  else if (m_fitFunction == "FermiExpLinear") {
696  if (!m_fixTau1 || !m_fixTau2) {
697  //
698  // Use the variable tau version of the expFermiFit
699  //
701  }
702  else {
704  }
705 
706  m_preExpFitWrapper = std::unique_ptr<ZDCFitExpFermiPreExp>(new ZDCFitExpFermiPreExp(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2, 6, false));
707  m_prePulseFitWrapper = std::unique_ptr<ZDCPrePulseFitWrapper>(new ZDCFitExpFermiLinearPrePulse(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
708  }
709  else if (m_fitFunction == "ComplexPrePulse") {
710  if (!m_fixTau1 || !m_fixTau2) {
711  //
712  // Use the variable tau version of the expFermiFit
713  //
715  }
716  else {
718  }
719 
720  m_prePulseFitWrapper = std::unique_ptr<ZDCPrePulseFitWrapper>(new ZDCFitComplexPrePulse(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
721  }
722  else if (m_fitFunction == "GeneralPulse") {
723  if (!m_fixTau1 || !m_fixTau2) {
724  //
725  // Use the variable tau version of the expFermiFit
726  //
728  }
729  else {
731  }
732 
733  m_prePulseFitWrapper = std::unique_ptr<ZDCPrePulseFitWrapper>(new ZDCFitGeneralPulse(m_tag, m_tmin, m_tmax, m_nominalTau1, m_nominalTau2));
734  }
735  else {
736  (*m_msgFunc_p)(ZDCMsg::Fatal, "Wrong fit function type: " + m_fitFunction);
737  }
738 
739  m_prePulseFitWrapper->SetPrePulseT0Range(prePulseTMin, prePulseTMax);
740 
741  m_initializedFits = true;
742 }
743 
744 bool ZDCPulseAnalyzer::LoadAndAnalyzeData(const std::vector<float>& ADCSamplesHG, const std::vector<float>& ADCSamplesLG)
745 {
746  if (m_useDelayed) {
747  (*m_msgFunc_p)(ZDCMsg::Fatal, "ZDCPulseAnalyzer::LoadAndAnalyzeData:: Wrong LoadAndAnalyzeData called -- expecting both delayed and undelayed samples");
748  }
749 
751 
752  // Clear any transient data
753  //
754  Reset(false);
755 
756  // Make sure we have the right number of samples. Should never fail. necessry?
757  //
758  if (ADCSamplesHG.size() != m_Nsample || ADCSamplesLG.size() != m_Nsample) {
759  m_fail = true;
760  return false;
761  }
762 
763  m_ADCSamplesHG = ADCSamplesHG;
764  m_ADCSamplesLG = ADCSamplesLG;
765 
766  return DoAnalysis(false);
767 }
768 
769 bool ZDCPulseAnalyzer::LoadAndAnalyzeData(const std::vector<float>& ADCSamplesHG, const std::vector<float>& ADCSamplesLG,
770  const std::vector<float>& ADCSamplesHGDelayed, const std::vector<float>& ADCSamplesLGDelayed)
771 {
772  if (!m_useDelayed) {
773  (*m_msgFunc_p)(ZDCMsg::Fatal, "ZDCPulseAnalyzer::LoadAndAnalyzeData:: Wrong LoadAndAnalyzeData called -- expecting only undelayed samples");
774  }
775 
777 
778  // Clear any transient data
779  //
780  Reset();
781 
782  // Make sure we have the right number of samples. Should never fail. necessry?
783  //
784  if (ADCSamplesHG.size() != m_Nsample || ADCSamplesLG.size() != m_Nsample ||
785  ADCSamplesHGDelayed.size() != m_Nsample || ADCSamplesLGDelayed.size() != m_Nsample) {
786  m_fail = true;
787  return false;
788  }
789 
790  m_ADCSamplesHG.reserve(m_Nsample*2);
791  m_ADCSamplesLG.reserve(m_Nsample*2);
792 
793  // Now do pedestal subtraction and check for overflows
794  //
795  for (size_t isample = 0; isample < m_Nsample; isample++) {
796  float ADCHG = ADCSamplesHG[isample];
797  float ADCLG = ADCSamplesLG[isample];
798 
799  float ADCHGDelay = ADCSamplesHGDelayed[isample] - m_delayedPedestalDiff;
800  float ADCLGDelay = ADCSamplesLGDelayed[isample] - m_delayedPedestalDiff;
801 
802  if (m_delayedDeltaT > 0) {
803  m_ADCSamplesHG.push_back(ADCHG);
804  m_ADCSamplesHG.push_back(ADCHGDelay);
805 
806  m_ADCSamplesLG.push_back(ADCLG);
807  m_ADCSamplesLG.push_back(ADCLGDelay);
808  }
809  else {
810  m_ADCSamplesHG.push_back(ADCHGDelay);
811  m_ADCSamplesHG.push_back(ADCHG);
812 
813  m_ADCSamplesLG.push_back(ADCLGDelay);
814  m_ADCSamplesLG.push_back(ADCLG);
815  }
816  }
817 
818  return DoAnalysis(false);
819 }
820 
822 {
823  Reset(true);
824 
825  bool result = DoAnalysis(true);
826  if (result && havePulse()) {
827  m_repassPulse = true;
828  }
829 
830  return result;
831 }
832 
834 {
835  //
836  // Dump samples to verbose output
837  //
838  bool doDump = (*m_msgFunc_p)(ZDCMsg::Verbose, "Dumping all samples before subtraction: ");
839 
840  m_NSamplesAna = m_ADCSamplesHG.size();
841 
842  m_ADCSamplesHGSub.assign(m_NSamplesAna, 0);
843  m_ADCSamplesLGSub.assign(m_NSamplesAna, 0);
844 
845  m_useSampleHG.assign(m_NSamplesAna, true);
846  m_useSampleLG.assign(m_NSamplesAna, true);
847 
848  // Now do pedestal subtraction and check for overflows
849  //
852 
853  m_maxADCHG = 0;
854  m_maxADCLG = 0;
855 
856  for (size_t isample = 0; isample < m_NSamplesAna; isample++) {
857  float ADCHG = m_ADCSamplesHG[isample];
858  float ADCLG = m_ADCSamplesLG[isample];
859 
860  //
861  // We always pedestal subtract even if the sample isn't going to be used in analysis
862  // basically for diagnostics
863  //
864  m_ADCSamplesHGSub[isample] = ADCHG - m_pedestal;
865  m_ADCSamplesLGSub[isample] = ADCLG - m_pedestal;
866 
867 
868  // If we have the per-sample FADC correction, we apply it after pedestal correction
869  // since we analyze the FADC response after baseline (~ same as pedestal) subtraction
870  //
872  double fadcCorrHG = m_FADCCorrHG->Interpolate(m_ADCSamplesHGSub[isample]);
873  double fadcCorrLG = m_FADCCorrLG->Interpolate(m_ADCSamplesLGSub[isample]);
874 
875  m_ADCSamplesHGSub[isample] *= fadcCorrHG;
876  m_ADCSamplesLGSub[isample] *= fadcCorrLG;
877 
878  if (doDump) {
879  std::ostringstream dumpString;
880  dumpString << "After FADC correction, sample " << isample << ", HG ADC = " << m_ADCSamplesHGSub[isample]
881  << ", LG ADC = " << m_ADCSamplesLGSub[isample] << std::endl;
882  (*m_msgFunc_p)(ZDCMsg::Verbose, dumpString.str().c_str());
883  }
884  }
885 
886  if (ADCHG > m_maxADCHG) {
887  m_maxADCHG = ADCHG;
888  m_maxADCSampleHG = isample;
889  }
890  else if (ADCHG < m_minADCHG) {
891  m_minADCHG = ADCHG;
892  m_minADCSampleHG = isample;
893  }
894 
895  if (ADCLG > m_maxADCLG) {
896  m_maxADCLG = ADCLG;
897  m_maxADCSampleLG = isample;
898  }
899  else if (ADCLG < m_minADCLG) {
900  m_minADCLG = ADCLG;
901  m_minADCSampleLG = isample;
902  }
903 
904  if (m_useSampleHG[isample]) {
905  if (m_enablePreExcl) {
906  if (ADCHG > m_preExclHGADCThresh && isample < m_maxSamplesPreExcl) {
907  m_useSampleHG[isample] = false;
908  continue;
909  }
910  }
911 
912  if (m_enablePostExcl) {
913  if (ADCHG > m_postExclHGADCThresh && isample >= m_NSamplesAna - m_maxSamplesPostExcl) {
914  m_useSampleHG[isample] = false;
915  continue;
916  }
917  }
918 
919  // If we get here, we've passed the above filters on the sample
920  //
921  if (ADCHG > m_HGOverflowADC) {
922  m_HGOverflow = true;
923 
924  if (isample == m_preSampleIdx) m_PSHGOverUnderflow = true;
925 
926  // Note: the implementation of the explicit pre- and post- sample exclusion should make this
927  // code obselete but before removing it we first need to validate the pre- and post-exclusion
928  //
929  if ((int) isample > m_lastHGOverFlowSample) m_lastHGOverFlowSample = isample;
930  if ((int) isample < m_firstHGOverFlowSample) m_firstHGOverFlowSample = isample;
931  }
932  else if (ADCHG < m_HGUnderflowADC) {
933  m_HGUnderflow = true;
934 
935  if (isample == m_preSampleIdx) m_PSHGOverUnderflow = true;
936  }
937  }
938 
939  // Now the low gain sample
940  //
941  if (m_useSampleLG[isample]) {
942  if (m_enablePreExcl) {
943  if (ADCLG > m_preExclLGADCThresh && isample <= m_maxSamplesPreExcl) {
944  m_useSampleLG[isample] = false;
945  continue;
946  }
947  }
948 
949  if (m_enablePostExcl) {
950  if (ADCLG > m_postExclLGADCThresh && isample >= m_NSamplesAna - m_maxSamplesPostExcl) {
951  m_useSampleLG[isample] = false;
952  m_ExcludeLate = true;
953  continue;
954  }
955  }
956 
957  if (ADCLG > m_LGOverflowADC) {
958  m_LGOverflow = true;
959  m_fail = true;
960  m_amplitude = m_LGOverflowADC * m_gainFactorLG; // Give a vale here even though we know it's wrong because
961  // the user may not check the return value and we know that
962  // amplitude is bigger than this
963  }
964 
965  if (ADCLG == 0) {
966  m_LGUnderflow = true;
967  m_fail = true;
968  }
969  }
970  }
971 
972  // if (doDump) {
973  // (*m_msgFunc_p)(ZDCMsg::Verbose, "Dump of useSamples: ");
974 
975  // std::ostringstream dumpStringUseHG;
976  // dumpStringUseHG << "HG: ";
977  // for (auto val : m_useSampleHG) {
978  // dumpStringUseHG << val << " ";
979  // }
980  // (*m_msgFunc_p)(ZDCMsg::Verbose, dumpStringUseHG.str().c_str());
981 
982  // std::ostringstream dumpStringUseLG;
983  // dumpStringUseLG << "LG: ";
984  // for (auto val : m_useSampleLG) {
985  // dumpStringUseLG << val << " ";
986  // }
987  // (*m_msgFunc_p)(ZDCMsg::Verbose, dumpStringUseLG.str().c_str());
988  // }
989 
990  // This ugly code should be obseleted by the introduction of the better, pre- and post-sample exclusion but
991  // that code still has to be fully validated.
992  //
993  // See if we can still use high gain even in the case of HG overflow if the overflow results from
994  // the first few samples or the last few samples
995  //
996  if (m_HGOverflow && !m_HGUnderflow) {
997  if (m_lastHGOverFlowSample < 2 && m_lastHGOverFlowSample > -1) {
998  m_HGOverflow = false;
1000  m_adjTimeRangeEvent = true;
1001  m_backToHG_pre = true;
1002  m_ExcludeEarly = true;
1003  }
1004  else if (m_firstHGOverFlowSample < static_cast<int>(m_NSamplesAna) && m_firstHGOverFlowSample >= static_cast<int>(m_NSamplesAna - 2) ) {
1006  m_HGOverflow = false;
1007  m_adjTimeRangeEvent = true;
1008  m_ExcludeLate = true;
1009  }
1010  }
1011 
1012  // (*m_msgFunc_p)(ZDCMsg::Verbose, "ZDCPulseAnalyzer:: " + m_tag + ": ScanAndSubtractSamples done");
1013 
1014  return true;
1015 }
1016 
1018 {
1019  float deriv2ndThreshHG = 0;
1020  float deriv2ndThreshLG = 0;
1021 
1022  if (!repass) {
1024 
1025  deriv2ndThreshHG = m_peak2ndDerivMinThreshHG;
1026  deriv2ndThreshLG = m_peak2ndDerivMinThreshLG;
1027  }
1028  else {
1029  deriv2ndThreshHG = m_peak2ndDerivMinRepassHG;
1030  deriv2ndThreshLG = m_peak2ndDerivMinRepassLG;
1031  }
1032 
1034  if (m_useLowGain) {
1035  // (*m_msgFunc_p)(ZDCMsg::Verbose, "ZDCPulseAnalyzer:: " + m_tag + " using low gain data ");
1036 
1038  deriv2ndThreshLG, m_noiseSigLG, m_LGT0CorrParams,
1040  if (result) {
1041  //
1042  // +++BAC
1043  //
1044  // I have removed some code that attempted a refit in case of failure of the chi-square cut
1045  // Instead, we should implement an analysis of the failure with possible re-fit afterwards
1046  // with possible change of the pre- or post-pulse condition
1047  //
1048  // --BAC
1049  //
1050 
1051  double amplCorrFactor = getAmplitudeCorrection(false);
1052 
1053  //
1054  // Multiply amplitude by gain factor
1055  //
1057  m_amplitude = m_fitAmplitude * amplCorrFactor * m_gainFactorLG;
1058  m_ampError = m_fitAmpError * amplCorrFactor * m_gainFactorLG;
1063 
1064  // BAC: also scale up the 2nd derivative by the gain factor so low and high gain can be treated on the same footing
1065  //
1067  }
1068 
1069  return result;
1070  }
1071  else {
1072  // (*m_msgFunc_p)(ZDCMsg::Verbose, "ZDCPulseAnalyzer:: " + m_tag + " using high gain data ");
1073 
1075  deriv2ndThreshHG, m_noiseSigHG, m_HGT0CorrParams,
1077  if (result) {
1078  // +++BAC
1079  //
1080  // I have removed some code that attempted a refit in case of failure of the chi-square cut
1081  // Instead, we should implement an analysis of the failure with possible re-fit afterwards
1082  // with possible change of the pre- or post-pulse condition
1083  //
1084  // --BAC
1085 
1093 
1095 
1096  // If we have a non-linear correction, apply it here
1097  //
1098  // We apply it as an inverse correction - i.e. we divide by a correction
1099  // term tha is a sum of coefficients times the ADC minus a reference
1100  // to a power. The lowest power is 1, the highest is deteremined by
1101  // the number of provided coefficients
1102  //
1103  double amplCorrFactor = getAmplitudeCorrection(true);
1104 
1105  m_amplitude *= amplCorrFactor;
1106  m_ampError *= amplCorrFactor;
1107  }
1108 
1109  // If LG refit has been requested, do it now
1110  //
1111  if (m_LGMode == LGModeRefitLG && m_havePulse) {
1113  DoFit(true);
1114 
1115  double amplCorrFactor = getAmplitudeCorrection(false);
1116  m_refitLGAmplCorr = m_refitLGAmpl*amplCorrFactor;
1117  }
1118 
1119  return result;
1120  }
1121 }
1122 
1123 bool ZDCPulseAnalyzer::AnalyzeData(size_t nSamples, size_t preSampleIdx,
1124  const std::vector<float>& samples, // The samples used for this event
1125  const std::vector<bool>& useSample, // The samples used for this event
1126  float peak2ndDerivMinThresh,
1127  float noiseSig,
1128  const std::vector<float>& t0CorrParams, // The parameters used to correct the t0
1129  float maxChisqDivAmp, // The maximum chisq / amplitude ratio
1130  float minT0Corr, float maxT0Corr // The minimum and maximum corrected T0 values
1131  )
1132 {
1133 
1134  // We keep track of which sample we used to do the subtraction sepaate from m_minSampleEvt
1135  // because the corresponding time is the reference time we provide to the fit function when
1136  // we have pre-pulses and in case we change the m_minSampleEvt after doing the subtraction
1137  //
1138  // e.g. our refit when the chisquare cuts fails
1139  //
1140 
1141  // Find the first used sample in the event
1142  //
1143  bool haveFirst = false;
1144  unsigned int lastUsed = 0;
1145 
1146  for (unsigned int sample = preSampleIdx; sample < nSamples; sample++) {
1147  if (useSample[sample]) {
1148  //
1149  // We're going to use this sample in the analysis, update bookeeping
1150  //
1151  if (!haveFirst) {
1153  haveFirst = true;
1154  }
1155  else {
1156  lastUsed = sample;
1157  }
1158  }
1159  }
1160 
1161  if (lastUsed < m_maxSampleEvt) m_maxSampleEvt = lastUsed;
1162 
1163  // Check to see whether we've changed the range of samples used in the analysis
1164  //
1165  // Should be obseleted with reworking of the fitting using Root::Fit package
1166  //
1167  if (m_minSampleEvt > preSampleIdx) {
1168  m_ExcludeEarly = true;
1169  m_adjTimeRangeEvent = true;
1170  }
1171 
1172  if (m_maxSampleEvt < nSamples - 1) {
1173  m_adjTimeRangeEvent = true;
1174  m_ExcludeLate = true;
1175  }
1176 
1177  // Prepare for subtraction
1178  //
1180  m_preSample = samples[m_usedPresampIdx];
1181 
1182  // std::ostringstream pedMessage;
1183  // pedMessage << "Pedestal index = " << m_usedPresampIdx << ", value = " << m_preSample;
1184  // (*m_msgFunc_p)(ZDCMsg::Verbose, pedMessage.str().c_str());
1185 
1186  m_samplesSub = samples;
1187  m_samplesSig.assign(m_NSamplesAna, noiseSig);
1188 
1189 
1190  //
1191  // When we are combinig delayed and undelayed samples we have to deal with the fact that
1192  // the two readouts can have different noise and thus different baselines. Which is a huge
1193  // headache.
1194  //
1195  if (m_useDelayed) {
1196  if (m_useFixedBaseline) {
1198  }
1199  else {
1200  //
1201  // Use much-improved method to match delayed and undelayed baselines
1202  //
1204  std::ostringstream baselineMsg;
1205  baselineMsg << "Delayed samples baseline correction = " << m_baselineCorr << std::endl;
1206  (*m_msgFunc_p)(ZDCMsg::Debug, baselineMsg.str().c_str());
1207  }
1208 
1209  // Now apply the baseline correction to align ADC values for delayed and undelayed samples
1210  //
1211  for (size_t isample = 0; isample < nSamples; isample++) {
1212  if (isample % 2) m_samplesSub[isample] -= m_baselineCorr;
1213  }
1214 
1215  // If we use one of the delayed samples for presample, we have to adjust the presample value as well
1216  //
1218  }
1219 
1220  // Do the presample subtraction
1221  //
1222  std::for_each(m_samplesSub.begin(), m_samplesSub.end(), [ = ] (float & adcUnsub) {return adcUnsub -= m_preSample;} );
1223 
1224  // Calculate the second derivatives using step size m_2ndDerivStep
1225  //
1227 
1228  // Find the sample which has the lowest 2nd derivative. We loop over the range defined by the
1229  // tolerance on the position of the minimum second derivative. Note: the +1 in the upper iterator is because
1230  // that's where the loop terminates, not the last element.
1231  //
1232  SampleCIter minDeriv2ndIter;
1233 
1235 
1236  minDeriv2ndIter = std::min_element(m_samplesDeriv2nd.begin() + m_peak2ndDerivMinSample - m_peak2ndDerivMinTolerance, m_samplesDeriv2nd.begin() + upperDelta);
1237 
1238  m_minDeriv2nd = *minDeriv2ndIter;
1239  m_minDeriv2ndSig = -m_minDeriv2nd/(std::sqrt(6.0)*noiseSig);
1240 
1241  m_minDeriv2ndIndex = std::distance(m_samplesDeriv2nd.cbegin(), minDeriv2ndIter);
1242 
1243  // BAC 02-04-23 This check turned out to be problematic. Todo: figure out how to replace
1244  //
1245  // // Also check the ADC value for the "peak" sample to make sure it is significant (at least 3 sigma)
1246  // // The factor of sqrt(2) on the noise is because we have done a pre-sample subtraction
1247  // //
1248  if (std::abs(m_minDeriv2nd) >= peak2ndDerivMinThresh) {
1249  m_havePulse = true;
1250  }
1251  else {
1252  m_havePulse = false;
1253  }
1254 
1255  // save the low and high gain ADC values at the peak -- if we have a pulse, at m_minDeriv2ndIndex
1256  // otherwise at m_peak2ndDerivMinSample
1257  //
1258  if (m_havePulse) {
1261  }
1262  else {
1265  }
1266 
1267  // Now decide whether we have a preceeding pulse or not. There are two possible kinds of preceeding pulses:
1268  // 1) exponential tail from a preceeding pulse
1269  // 2) peaked pulse before the main pulse
1270  //
1271  // we can, of course, have both
1272  //
1273 
1274  // To check for exponential tail, test the slope determined by the minimum ADC value (and pre-sample)
1275  // **beware** this can cause trouble in 2015 data where the pulses had overshoot due to the transformers
1276  //
1277 
1278  // Implement a much simpler test for presence of an exponential tail from an OOT pulse
1279  // namely if the slope evaluated at the presample is significantly negative, then
1280  // we have a preceeding pulse.
1281  //
1282  // Note that we don't have to subtract the FADC value corresponding to the presample because
1283  // that subtraction has already been done.
1284  //
1285  if (m_havePulse) {
1286  // If we've alreday excluded early samples, we have almost by construction have negative exponential tail
1287  //
1288  if (m_ExcludeEarly) m_preExpTail = true;
1289 
1290  //
1291  // The subtracted ADC value at m_usedPresampIdx is, by construction, zero
1292  // The next sample has had the pre-sample subtracted, so it represents the initial derivative
1293  //
1294  float derivPresampleSig = m_samplesSub[m_usedPresampIdx+1]/(std::sqrt(2.0)*noiseSig);
1295  if (derivPresampleSig < -5) {
1296  m_preExpTail = true;
1297  m_preExpSig = derivPresampleSig;
1298  }
1299 
1300  for (unsigned int isample = m_usedPresampIdx; isample < m_samplesSub.size(); isample++) {
1301  if (!useSample[isample]) continue;
1302 
1303  float sampleSig = -m_samplesSub[isample]/(std::sqrt(2.0)*noiseSig);
1304 
1305  // Compare the derivative significant to the 2nd derivative significance,
1306  // so we don't waste time dealing with small perturbations on large signals
1307  //
1308  if ((sampleSig > 5 && sampleSig > 0.02*m_minDeriv2ndSig) || sampleSig > 0.5*m_minDeriv2ndSig) {
1309  m_preExpTail = true;
1310  if (sampleSig > m_preExpSig) m_preExpSig = sampleSig;
1311  }
1312  }
1313 
1314  // Now we search for maxima before the main pulse
1315  //
1316  int loopLimit = (m_havePulse ? m_minDeriv2ndIndex - 2 : m_peak2ndDerivMinSample - 2);
1317  int loopStart = m_minSampleEvt == 0 ? 1 : m_minSampleEvt;
1318 
1319  float maxPrepulseSig = 0;
1320  unsigned int maxPrepulseSample = 0;
1321 
1322  for (int isample = loopStart; isample <= loopLimit; isample++) {
1323  if (!useSample[isample]) continue;
1324 
1325  //
1326  // If any of the second derivatives prior to the peak are significantly negative, we have a an extra pulse
1327  // prior to the main one -- as opposed to just an expnential tail
1328  //
1329  float prePulseSig = -m_samplesDeriv2nd[isample]/(std::sqrt(6.0)*noiseSig);
1330 
1331  // std::cout << m_tag << ", for sample " << isample << ", 2nd derivative = " << m_samplesDeriv2nd[isample]
1332  // << " 0.05 * m_minDeriv2nd) = " << 0.05 * m_minDeriv2nd
1333  // << ", prePulseSig = " << prePulseSig << std::endl;
1334 
1335  if ((prePulseSig > 6 && m_samplesDeriv2nd[isample] < 0.05 * m_minDeriv2nd) ||
1336  m_samplesDeriv2nd[isample] < 0.5*m_minDeriv2nd)
1337  {
1338  m_prePulse = true;
1339  if (prePulseSig > maxPrepulseSig) {
1340  maxPrepulseSig = prePulseSig;
1341  maxPrepulseSample = isample;
1342  }
1343  }
1344  }
1345 
1346  if (m_prePulse) {
1347  // std::cout << m_tag << ": prepulse sigma = " << m_prePulseSig << ", pre exp sigma = " << m_preExpSig << std::endl;
1348  m_prePulseSig = maxPrepulseSig;
1349 
1350  if (m_preExpTail) {
1351  //
1352  // We have a prepulse. If we already indicated an negative exponential,
1353  // if the prepulse has greater significance, we override the negative exponential
1354  //
1355  if (m_prePulseSig > m_preExpSig) {
1356  m_preExpTail = false;
1357  }
1358  else {
1359  m_prePulse = false;
1360  }
1361  }
1362 
1363  m_initialPrePulseAmp = m_samplesSub[maxPrepulseSample];
1364  m_initialPrePulseT0 = m_deltaTSample * (maxPrepulseSample);
1365  }
1366 
1367  // if (m_preExpTail) m_prePulse = true;
1368 
1369  // -----------------------------------------------------
1370  // Post pulse detection
1371  //
1372  unsigned int postStartIdx = std::max(static_cast<unsigned int>(m_minDeriv2ndIndex + 2),
1373  static_cast<unsigned int>(m_peak2ndDerivMinSample + m_peak2ndDerivMinTolerance + 1));
1374 
1375 
1376  for (int isample = postStartIdx; isample < (int) nSamples - 1; isample++) {
1377  if (!useSample.at(isample)) continue;
1378 
1379  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1380  // BAC 12-01-2024
1381  //
1382  // The following code is commented out as a temporary measure to deal with apparent reflections
1383  // associated with large out-of-time pulses that introduce a "kink" that triggers the derivative
1384  // test. A work-around that doesn't introduce specific code for the 2023 Pb+Pb run but allows
1385  // adaption for this specific issue is going to take some work. For now we leave the 2nd derivative
1386  // test, but will also need to introduce some configurability of the cut -- which we need anyway
1387  //
1388  // Calculate the forward derivative. the pulse should never increase on the tail. If it
1389  // does, we almost certainly have a post-pulse
1390  //
1391  // float deriv = m_samplesSub[isample + 1] - m_samplesSub[isample];
1392  // if (deriv/(std::sqrt(2)*noiseSig) > 6) {
1393  // m_postPulse = true;
1394  // m_maxSampleEvt = isample;
1395  // m_adjTimeRangeEvent = true;
1396  // break;
1397  // }
1398  // else {
1399  //----------------------------------------------------------------------------------------------
1400  //
1401  // Now we check the second derivative which might also indicate a post pulse
1402  // even if the derivative is not sufficiently large
1403  //
1404  // add small 1e-3 in division to avoid floating overflow
1405  //
1406 
1407  float deriv = m_samplesSub.at(isample + 1) - m_samplesSub.at(isample);
1408  float derivSig = deriv/(std::sqrt(2)*noiseSig);
1409  float deriv2ndSig = -m_samplesDeriv2nd.at(isample) / (std::sqrt(6)*noiseSig);
1410 
1411  float deriv2ndTest = m_samplesDeriv2nd.at(isample) / (-m_minDeriv2nd + 1.0e-3);
1412 
1413  if (derivSig > 5) {
1414  //
1415  // Check the 2nd derivative -- we should be at a minimum(?)
1416  //
1417  if (std::abs(deriv2ndTest) > 0.15) {
1418  m_postPulse = true;
1419  m_maxSampleEvt = std::min<int>(isample - (m_2ndDerivStep - 1), m_maxSampleEvt);
1420 
1421  m_adjTimeRangeEvent = true;
1422  break;
1423  }
1424  }
1425 
1426  // The place to apply the cut on samples depends on whether we have found a "minimum" or a "maximum"
1427  // The -m_2ndDerivStep for the minimum accounts for the shift between 2nd derivative and the samples
1428  // if we find a maximum we cut one sample lower
1429  //
1430  if (deriv2ndSig > 5 && deriv2ndTest < -0.1) {
1431  m_postPulse = true;
1432  m_maxSampleEvt = std::min<int>(isample - m_2ndDerivStep, m_maxSampleEvt);
1433 
1434  m_adjTimeRangeEvent = true;
1435  break;
1436  }
1437  }
1438  }
1439 
1440  if (m_postPulse) {
1441  std::ostringstream ostrm;
1442  ostrm << "Post pulse found, m_maxSampleEvt = " << m_maxSampleEvt;
1443  (*m_msgFunc_p)(ZDCMsg::Debug, ostrm.str());
1444  }
1445 
1446 
1447  // -----------------------------------------------------
1448 
1449  // Stop now if we have no pulse or we've detected a failure
1450  //
1451  if (m_fail || !m_havePulse) return false;
1452 
1453  if (!m_useDelayed) DoFit();
1454  else DoFitCombined();
1455 
1456  if (fitFailed()) {
1457  m_fail = true;
1458  }
1459  else {
1460  std::ostringstream ostrm;
1461  // ostrm << "Pulse fit successful with chisquare = " << m_fitChisq;
1462  // (*m_msgFunc_p)(ZDCMsg::Debug, ostrm.str());
1463 
1465 
1466  if (m_timingCorrMode != NoTimingCorr) {
1467  //
1468  // We correct relative to the m_timingCorrRefADC using m_timingCorrScale to scale
1469  //
1470  double t0CorrFact = (m_fitAmplitude - m_timingCorrRefADC) / m_timingCorrScale;
1471  if (m_timingCorrMode == TimingCorrLog) t0CorrFact = std::log(t0CorrFact);
1472 
1473  // Calculate the correction using a polynomial of power determined by the size of the vector.
1474  // For historical reasons we include here a constant term, though it is degenerate with
1475  // the nominal t0 and/or timing calibrations.
1476  //
1477  float correction = 0;
1478 
1479  for (unsigned int ipow = 0; ipow < t0CorrParams.size(); ipow++) {
1480  correction += t0CorrParams[ipow]*std::pow(t0CorrFact, double(ipow));
1481  }
1482 
1483  // The correction represents the offset of the timing value from zero so we subtract the result
1484  //
1486  }
1487 
1488  bool failFixedCut = m_fitTimeCorr < minT0Corr || m_fitTimeCorr > maxT0Corr;
1489 
1490  // Calculate the timing significance. Note this implementation breaks the model for
1491  // how DoAnalysis is currently used by explicitly testing m_useLowGain, but that model
1492  // needs adjustment anyway ... (one step at a time)
1493  //
1494  // Note that to avoid coupling non-linear corrections to the amplitude and the
1495  // timing significance we evaluate the time resolution using the fit amplitude
1496  //
1497  if (m_timeCutMode != 0) {
1498  double timeResolution = 0;
1499  if (m_useLowGain) timeResolution = m_timeResFuncLG_p->Eval(m_fitAmplitude);
1500  else timeResolution = m_timeResFuncHG_p->Eval(m_fitAmplitude);
1501 
1502  m_timeSig = m_fitTimeCorr/timeResolution;
1503  if (std::abs(m_timeSig) > m_t0CutSig) {
1504  //
1505  // We've failed the significance cut. In OR mode (1) we mark the time
1506  // as bad if we've lso failed the fixed cut. In AND mode, we mark it
1507  // as bad regardless of the fixed cut.
1508  //
1509  if (m_timeCutMode == 1) {
1510  if (failFixedCut) m_badT0 = true;
1511  }
1512  else m_badT0 = true;
1513  }
1514  else if (m_timeCutMode == 2 && failFixedCut) m_badT0 = failFixedCut;
1515  }
1516  else {
1517  m_timeSig = -1;
1518  m_badT0 = failFixedCut;
1519  }
1520 
1521  // Now check for valid chisq and valid time
1522  //
1523  if (m_fitChisq/m_fitNDoF > 2 && m_fitChisq / (m_fitAmplitude + 1.0e-6) > maxChisqDivAmp) m_badChisq = true;
1524  }
1525 
1526  return !m_fitFailed;
1527 }
1528 
1529 void ZDCPulseAnalyzer::prepareLGRefit(const std::vector<float>& samplesLG, const std::vector<float>& samplesSig,
1530  const std::vector<bool>& useSamples)
1531 {
1532  m_samplesLGRefit.clear();
1533  m_samplesSigLGRefit.clear();
1534 
1535  float presampleLG = m_ADCSamplesLGSub[m_usedPresampIdx];
1536 
1537  // Do the presample subtraction
1538  //
1539  for (unsigned int idx = 0; idx < samplesLG.size(); idx++) {
1540  m_samplesLGRefit.push_back(samplesLG[idx] - presampleLG);
1541 
1542  if (useSamples[idx]) {
1543  m_samplesSigLGRefit.push_back(samplesSig[idx]);
1544  }
1545  else {
1546  m_samplesSigLGRefit.push_back(0);
1547  }
1548  }
1549 }
1550 
1551 
1552 void ZDCPulseAnalyzer::DoFit(bool refitLG)
1553 {
1554  bool fitLG = m_useLowGain || refitLG;
1555 
1556  TH1* hist_p = nullptr;
1557  FillHistogram(refitLG);
1558 
1559  // Set the initial values
1560  //
1561  float ampInitial, fitAmpMin, fitAmpMax, t0Initial;
1562 
1563  if (fitLG) {
1564  fitAmpMin = m_fitAmpMinLG;
1565  fitAmpMax = m_fitAmpMaxLG;
1566  t0Initial = m_nominalT0LG;
1567  ampInitial = m_ADCPeakLG;
1568  }
1569  else {
1570  ampInitial = m_ADCPeakHG;
1571  fitAmpMin = m_fitAmpMinHG;
1572  fitAmpMax = m_fitAmpMaxHG;
1573  t0Initial = m_nominalT0HG;
1574  }
1575 
1576  if (refitLG) {
1577  hist_p = m_fitHistLGRefit.get();
1578  }
1579  else {
1580  hist_p = m_fitHist.get();
1581  }
1582  if (ampInitial < fitAmpMin) ampInitial = fitAmpMin * 1.5;
1583 
1584 
1585  ZDCFitWrapper* fitWrapper = m_defaultFitWrapper.get();
1586  if (preExpTail()) {
1587  fitWrapper = m_preExpFitWrapper.get();
1588  (static_cast<ZDCPreExpFitWrapper*>(m_preExpFitWrapper.get()))->SetInitialExpPulse(m_initialExpAmp);
1589  }
1590  else if (prePulse()) {
1591  fitWrapper = m_prePulseFitWrapper.get();
1592  (static_cast<ZDCPrePulseFitWrapper*>(fitWrapper))->SetInitialPrePulse(m_initialPrePulseAmp, m_initialPrePulseT0,0,25);
1593  }
1594 
1595  if (m_adjTimeRangeEvent) {
1598 
1599  float fitTReference = m_deltaTSample * m_usedPresampIdx;
1600 
1601  fitWrapper->Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax, m_fitTMin, m_fitTMax, fitTReference);
1602  }
1603  else {
1604  fitWrapper->Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax);
1605  }
1606 
1607  // Now perform the fit
1608  //
1609  std::string options = m_fitOptions + "Ns";
1610  if (m_quietFits) {
1611  options += "Q";
1612  }
1613 
1614  bool fitFailed = false;
1615 
1616  // dumpTF1(fitWrapper->GetWrapperTF1RawPtr());
1617  checkTF1Limits(fitWrapper->GetWrapperTF1RawPtr());
1618 
1619  //
1620  // Fit the data with the function provided by the fit wrapper
1621  //
1622  TFitResultPtr result_ptr = hist_p->Fit(fitWrapper->GetWrapperTF1RawPtr(), options.c_str(), "", m_fitTMin, m_fitTMax);
1623  int fitStatus = result_ptr;
1624 
1625  //
1626  // If the first fit failed, also check the EDM. If sufficiently small, the failure is almost surely due
1627  // to parameter limits and we just accept the result
1628  //
1629  if (fitStatus != 0 && result_ptr->Edm() > 0.001)
1630  {
1631  //
1632  // We contstrain the fit and try again
1633  //
1634  fitWrapper->ConstrainFit();
1635 
1636  TFitResultPtr constrFitResult_ptr = hist_p->Fit(fitWrapper->GetWrapperTF1RawPtr(), options.c_str(), "", m_fitTMin, m_fitTMax);
1637  fitWrapper->UnconstrainFit();
1638 
1639  if ((int) constrFitResult_ptr != 0) {
1640  //
1641  // Even the constrained fit failed, so we quit.
1642  //
1643  fitFailed = true;
1644  }
1645  else {
1646  // Now we try the fit again with the constraint removed
1647  //
1648  TFitResultPtr unconstrFitResult_ptr = hist_p->Fit(fitWrapper->GetWrapperTF1RawPtr(), options.c_str(), "", m_fitTMin, m_fitTMax);
1649  if ((int) unconstrFitResult_ptr != 0) {
1650  //
1651  // The unconstrained fit failed again, so we redo the constrained fit
1652  //
1653  fitWrapper->ConstrainFit();
1654 
1655  TFitResultPtr constrFit2Result_ptr = hist_p->Fit(fitWrapper->GetWrapperTF1RawPtr(), options.c_str(), "", m_fitTMin, m_fitTMax);
1656  if ((int) constrFit2Result_ptr != 0) {
1657  //
1658  // Even the constrained fit failed the second time, so we quit.
1659  //
1660  fitFailed = true;
1661  }
1662 
1663  result_ptr = constrFit2Result_ptr;
1664  fitWrapper->UnconstrainFit();
1665  }
1666  else {
1667  result_ptr = unconstrFitResult_ptr;
1668  }
1669  }
1670  }
1671 
1672  if (!m_fitFailed && m_saveFitFunc) {
1673  hist_p->GetListOfFunctions()->Clear();
1674 
1675  TF1* func = fitWrapper->GetWrapperTF1RawPtr();
1676  std::string name = func->GetName();
1677 
1678  TF1* copyFunc = static_cast<TF1*>(func->Clone((name + "_copy").c_str()));
1679  hist_p->GetListOfFunctions()->Add(copyFunc);
1680  }
1681 
1682  if (!refitLG) {
1684  m_bkgdMaxFraction = fitWrapper->GetBkgdMaxFraction();
1685  m_fitAmplitude = fitWrapper->GetAmplitude();
1686  m_fitAmpError = fitWrapper->GetAmpError();
1687 
1688  if (preExpTail()) {
1689  m_fitExpAmp = (static_cast<ZDCPreExpFitWrapper*>(m_preExpFitWrapper.get()))->GetExpAmp();
1690  }
1691  else {
1692  m_fitExpAmp = 0;
1693  }
1694 
1695  m_fitTime = fitWrapper->GetTime();
1696  m_fitTimeSub = m_fitTime - t0Initial;
1697 
1698  m_fitChisq = result_ptr->Chi2();
1699  m_fitNDoF = result_ptr->Ndf();
1700 
1701  m_fitTau1 = fitWrapper->GetTau1();
1702  m_fitTau2 = fitWrapper->GetTau2();
1703 
1704  // Here we need to check if the fit amplitude is small (close) enough to fitAmpMin.
1705  // with "< 1+epsilon" where epsilon ~ 1%
1706  if (m_fitAmplitude < fitAmpMin * 1.01) {
1707  m_fitMinAmp = true;
1708  }
1709 
1710  float sigMinCut = fitLG ? m_sigMinLG : m_sigMinHG;
1711  if (m_fitAmpError > 1e-6) {
1712  if (m_fitAmplitude/m_fitAmpError < sigMinCut) m_failSigCut = true;
1713  }
1714  }
1715  else {
1716  m_evtLGRefit = true;
1717  m_refitLGFitAmpl = fitWrapper->GetAmplitude();
1718  m_refitLGAmpl = fitWrapper->GetAmplitude() * m_gainFactorLG;
1719  m_refitLGAmpError = fitWrapper->GetAmpError() * m_gainFactorLG;
1720  m_refitLGChisq = result_ptr->Chi2();
1721  m_refitLGTime = fitWrapper->GetTime();
1722  m_refitLGTimeSub = m_refitLGTime - t0Initial;
1723  }
1724 }
1725 
1727 {
1728  bool fitLG = refitLG || m_useLowGain;
1729  TH1* hist_p = nullptr, *delayedHist_p = nullptr;
1730 
1731  FillHistogram(refitLG);
1732  if (refitLG) {
1733  hist_p = m_fitHistLGRefit.get();
1734  delayedHist_p = m_delayedHistLGRefit.get();
1735  }
1736  else {
1737  hist_p = m_fitHist.get();
1738  delayedHist_p = m_delayedHist.get();
1739  }
1740 
1741  float fitAmpMin, fitAmpMax, t0Initial, ampInitial;
1742  if (fitLG) {
1743  ampInitial = m_ADCPeakLG;
1744  fitAmpMin = m_fitAmpMinLG;
1745  fitAmpMax = m_fitAmpMaxLG;
1746  t0Initial = m_nominalT0LG;
1747  }
1748  else {
1749  ampInitial = m_ADCPeakHG;
1750  fitAmpMin = m_fitAmpMinHG;
1751  fitAmpMax = m_fitAmpMaxHG;
1752  t0Initial = m_nominalT0HG;
1753  }
1754 
1755  // Set the initial values
1756  //
1757  if (ampInitial < fitAmpMin) ampInitial = fitAmpMin * 1.5;
1758 
1759  ZDCFitWrapper* fitWrapper = m_defaultFitWrapper.get();
1760  //if (prePulse()) fitWrapper = fitWrapper = m_preExpFitWrapper.get();
1761 
1762  if (preExpTail()) {
1763  fitWrapper = m_preExpFitWrapper.get();
1764  (static_cast<ZDCPreExpFitWrapper*>(m_preExpFitWrapper.get()))->SetInitialExpPulse(m_initialExpAmp);
1765  }
1766  else if (prePulse()) {
1767  fitWrapper = m_prePulseFitWrapper.get();
1768  (static_cast<ZDCPrePulseFitWrapper*>(fitWrapper))->SetInitialPrePulse(m_initialPrePulseAmp, m_initialPrePulseT0,0,25);
1769  }
1770 
1771  // Initialize the fit wrapper for this event, specifying a
1772  // per-event fit range if necessary
1773  //
1774  if (m_adjTimeRangeEvent) {
1777 
1778  float fitTReference = m_deltaTSample * m_usedPresampIdx;
1779 
1780  fitWrapper->Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax, m_fitTMin, m_fitTMax, fitTReference);
1781  }
1782  else {
1783  fitWrapper->Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax);
1784  }
1785 
1786  // Set up the virtual fitter
1787  //
1788  TFitter* theFitter = nullptr;
1789 
1790  if (prePulse()) {
1792 
1793  theFitter = m_prePulseCombinedFitter.get();
1794  }
1795  else {
1797 
1798  theFitter = m_defaultCombinedFitter.get();
1799  }
1800 
1801  // dumpTF1(fitWrapper->GetWrapperTF1RawPtr());
1802 
1803  // Set the static pointers to histograms and function for use in FCN
1804  //
1805  s_undelayedFitHist = hist_p;
1806  s_delayedFitHist = delayedHist_p;
1807  s_combinedFitFunc = fitWrapper->GetWrapperTF1RawPtr();
1810 
1811 
1812  size_t numFitPar = theFitter->GetNumberTotalParameters();
1813 
1814  theFitter->GetMinuit()->fISW[4] = -1;
1815 
1816  // Now perform the fit
1817  //
1818  if (m_quietFits) {
1819  theFitter->GetMinuit()->fISW[4] = -1;
1820 
1821  int ierr= 0;
1822  theFitter->GetMinuit()->mnexcm("SET NOWarnings",nullptr,0,ierr);
1823  }
1824  else theFitter->GetMinuit()->fISW[4] = 0;
1825 
1826  // Only include baseline shift in fit for pre-pulses. Otherwise baseline matching should work
1827  //
1828  if (prePulse()) {
1829  theFitter->SetParameter(0, "delayBaselineAdjust", 0, 0.01, -100, 100);
1830  theFitter->ReleaseParameter(0);
1831  }
1832  else {
1833  theFitter->SetParameter(0, "delayBaselineAdjust", 0, 0.01, -100, 100);
1834  theFitter->FixParameter(0);
1835  }
1836 
1837 
1838  double arglist[100];
1839  arglist[0] = 5000; // number of function calls
1840  arglist[1] = 0.01; // tolerance
1841  int status = theFitter->ExecuteCommand("MIGRAD", arglist, 2);
1842 
1843  double fitAmp = theFitter->GetParameter(1);
1844 
1845  // Capture the chi-square etc.
1846  //
1847  double chi2, edm, errdef;
1848  int nvpar, nparx;
1849 
1850  theFitter->GetStats(chi2, edm, errdef, nvpar, nparx);
1851 
1852  // Here we need to check if fitAmp is small (close) enough to fitAmpMin.
1853  // with "< 1+epsilon" where epsilon ~ 1%
1854  //
1855  if (status || fitAmp < fitAmpMin * 1.01 || edm > 0.01){
1856 
1857  //
1858  // We first retry the fit with no baseline adjust
1859  //
1860  theFitter->SetParameter(0, "delayBaselineAdjust", 0, 0.01, -100, 100);
1861  theFitter->FixParameter(0);
1862 
1863  // Here we need to check if fitAmp is small (close) enough to fitAmpMin.
1864  // with "< 1+epsilon" where epsilon ~ 1%
1865  if (fitAmp < fitAmpMin * 1.01) {
1866  if (m_adjTimeRangeEvent) {
1867  float fitTReference = m_deltaTSample * m_usedPresampIdx;
1868  fitWrapper->Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax, m_fitTMin, m_fitTMax, fitTReference);
1869  }
1870  else {
1871  fitWrapper->Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax);
1872  }
1873  }
1874 
1875  status = theFitter->ExecuteCommand("MIGRAD", arglist, 2);
1876  if (status != 0) {
1877  //
1878  // Fit failed event with no baseline adust, so be it
1879  //
1880  theFitter->ReleaseParameter(0);
1881  m_fitFailed = true;
1882  }
1883  else {
1884  //
1885  // The fit succeeded with no baseline adjust, re-fit allowing for baseline adjust using
1886  // the parameters from previous fit as the starting point
1887  //
1888  theFitter->ReleaseParameter(0);
1889  status = theFitter->ExecuteCommand("MIGRAD", arglist, 2);
1890 
1891  if (status) {
1892  // Since we know the fit can succeed without the baseline adjust, go back to it
1893  //
1894  theFitter->SetParameter(0, "delayBaselineAdjust", 0, 0.01, -100, 100);
1895  theFitter->FixParameter(0);
1896  status = theFitter->ExecuteCommand("MIGRAD", arglist, 2);
1897  }
1898  }
1899  }
1900  else m_fitFailed = false;
1901 
1902  // Check to see if the fit forced the amplitude to the minimum, if so set the corresponding status bit
1903  //
1904  fitAmp = theFitter->GetParameter(1);
1905 
1906  // Here we need to check if fitAmp is small (close) enough to fitAmpMin.
1907  // with "< 1+epsilon" where epsilon ~ 1%
1908  if (fitAmp < fitAmpMin * 1.01) {
1909  m_fitMinAmp = true;
1910  }
1911 
1912  // Check that the amplitude passes minimum significance requirement
1913  //
1914  float sigMinCut = fitLG ? m_sigMinLG : m_sigMinHG;
1915  if (m_fitAmpError > 1e-6) {
1916  if (m_fitAmplitude/m_fitAmpError < sigMinCut) m_failSigCut = true;
1917  }
1918 
1919  if (!m_quietFits) theFitter->GetMinuit()->fISW[4] = -1;
1920 
1921  std::vector<double> funcParams(numFitPar - 1);
1922  std::vector<double> funcParamErrs(numFitPar - 1);
1923 
1924  // Save the baseline shift between delayed and undelayed samples
1925  //
1926  m_delayedBaselineShift = theFitter->GetParameter(0);
1927 
1928  // Capture and store the fit function parameteds and errors
1929  //
1930  for (size_t ipar = 1; ipar < numFitPar; ipar++) {
1931  funcParams[ipar - 1] = theFitter->GetParameter(ipar);
1932  funcParamErrs[ipar - 1] = theFitter->GetParError(ipar);
1933  }
1934 
1935  s_combinedFitFunc->SetParameters(&funcParams[0]);
1936  s_combinedFitFunc->SetParErrors(&funcParamErrs[0]);
1937 
1938  // Capture the chi-square etc.
1939  //
1940  theFitter->GetStats(chi2, edm, errdef, nvpar, nparx);
1941 
1942  int ndf = 2 * m_Nsample - nvpar;
1943 
1944  s_combinedFitFunc->SetChisquare(chi2);
1945  s_combinedFitFunc->SetNDF(ndf);
1946 
1947  // add to list of functions
1948  if (m_saveFitFunc) {
1949  s_undelayedFitHist->GetListOfFunctions()->Clear();
1950  s_undelayedFitHist->GetListOfFunctions()->Add(s_combinedFitFunc);
1951 
1952  s_delayedFitHist->GetListOfFunctions()->Clear();
1953  s_delayedFitHist->GetListOfFunctions()->Add(s_combinedFitFunc);
1954  }
1955 
1956  if (!refitLG) {
1957  // Save the pull values from the last call to FCN
1958  //
1959  arglist[0] = 3; // number of function calls
1960  theFitter->ExecuteCommand("Cal1fcn", arglist, 1);
1962 
1963  m_fitAmplitude = fitWrapper->GetAmplitude();
1964  m_fitTime = fitWrapper->GetTime();
1965  if (prePulse()) {
1966  m_fitPreT0 = (static_cast<ZDCPrePulseFitWrapper*>(m_prePulseFitWrapper.get()))->GetPreT0();
1967  m_fitPreAmp = (static_cast<ZDCPrePulseFitWrapper*>(m_prePulseFitWrapper.get()))->GetPreAmp();
1968  m_fitPostT0 = (static_cast<ZDCPrePulseFitWrapper*>(m_prePulseFitWrapper.get()))->GetPostT0();
1969  m_fitPostAmp = (static_cast<ZDCPrePulseFitWrapper*>(m_prePulseFitWrapper.get()))->GetPostAmp();
1970  }
1971 
1972  if (preExpTail()) {
1973  m_fitExpAmp = (static_cast<ZDCPreExpFitWrapper*>(m_preExpFitWrapper.get()))->GetExpAmp();
1974  }
1975  else {
1976  m_fitExpAmp = 0;
1977  }
1978 
1979  m_fitTimeSub = m_fitTime - t0Initial;
1980  m_fitChisq = chi2;
1981  m_fitNDoF = ndf;
1982 
1983  m_fitTau1 = fitWrapper->GetTau1();
1984  m_fitTau2 = fitWrapper->GetTau2();
1985 
1986  m_fitAmpError = fitWrapper->GetAmpError();
1987  m_bkgdMaxFraction = fitWrapper->GetBkgdMaxFraction();
1988  }
1989  else {
1990  m_evtLGRefit = true;
1991  m_refitLGFitAmpl = fitWrapper->GetAmplitude();
1992  m_refitLGAmpl = fitWrapper->GetAmplitude() * m_gainFactorLG;
1993  m_refitLGAmpError = fitWrapper->GetAmpError() * m_gainFactorLG;
1994  m_refitLGChisq = chi2;
1995  m_refitLGTime = fitWrapper->GetTime();
1996  m_refitLGTimeSub = m_refitLGTime - t0Initial;
1997  }
1998 }
1999 
2001 {
2002  for (int ipar = 0; ipar < func->GetNpar(); ipar++) {
2003  double parLimitLow, parLimitHigh;
2004 
2005  func->GetParLimits(ipar, parLimitLow, parLimitHigh);
2006 
2007  (*m_msgFunc_p)(ZDCMsg::Debug, (
2008  "ZDCPulseAnalyzer name=" + std::string(func->GetName())
2009  + " ipar=" + std::to_string(ipar)
2010  + " parLimitLow=" + std::to_string(parLimitLow)
2011  + " parLimitHigh="+ std::to_string(parLimitHigh)
2012  )
2013  );
2014 
2015  //if (std::abs(parLimitHigh / parLimitLow - 1) > 1e-6) {
2016  if (std::abs(parLimitHigh - parLimitLow) > (1e-6)*std::abs(parLimitLow)) {
2017  double value = func->GetParameter(ipar);
2018  if (value >= parLimitHigh) {
2019  value = parLimitHigh * 0.9;
2020  }
2021  else if (value <= parLimitLow) {
2022  value = parLimitLow + 0.1*std::abs(parLimitLow);
2023  }
2024  func->SetParameter(ipar, value);
2025  }
2026  }
2027 }
2028 
2029 std::unique_ptr<TFitter> ZDCPulseAnalyzer::MakeCombinedFitter(TF1* func)
2030 {
2031  TVirtualFitter::SetDefaultFitter("Minuit");
2032 
2033  size_t nFitParams = func->GetNpar() + 1;
2034  std::unique_ptr<TFitter> fitter = std::make_unique<TFitter>(nFitParams);
2035 
2036  fitter->GetMinuit()->fISW[4] = -1;
2037  fitter->SetParameter(0, "delayBaselineAdjust", 0, 0.01, -100, 100);
2038 
2039  for (size_t ipar = 0; ipar < nFitParams - 1; ipar++) {
2040  double parLimitLow, parLimitHigh;
2041 
2042  func->GetParLimits(ipar, parLimitLow, parLimitHigh);
2043  if (std::abs(parLimitHigh / parLimitLow - 1) < 1e-6) {
2044  double value = func->GetParameter(ipar);
2045  double lowLim = std::min(value * 0.99, value * 1.01);
2046  double highLim = std::max(value * 0.99, value * 1.01);
2047 
2048  fitter->SetParameter(ipar + 1, func->GetParName(ipar), func->GetParameter(ipar), 0.01, lowLim, highLim);
2049  fitter->FixParameter(ipar + 1);
2050  }
2051  else {
2052  double value = func->GetParameter(ipar);
2053  if (value >= parLimitHigh) value = parLimitHigh * 0.99;
2054  else if (value <= parLimitLow) value = parLimitLow * 1.01;
2055 
2056  double step = std::min((parLimitHigh - parLimitLow)/100., (value - parLimitLow)/100.);
2057 
2058  fitter->SetParameter(ipar + 1, func->GetParName(ipar), value, step, parLimitLow, parLimitHigh);
2059  }
2060  }
2061 
2063 
2064  return fitter;
2065 }
2066 
2067 void ZDCPulseAnalyzer::UpdateFitterTimeLimits(TFitter* fitter, ZDCFitWrapper* wrapper, bool prePulse)
2068 {
2069  double parLimitLow, parLimitHigh;
2070 
2071  auto func_p = wrapper->GetWrapperTF1();
2072  func_p->GetParLimits(1, parLimitLow, parLimitHigh);
2073 
2074  fitter->SetParameter(2, func_p->GetParName(1), func_p->GetParameter(1), 0.01, parLimitLow, parLimitHigh);
2075 
2076  if (prePulse) {
2077  unsigned int parIndex = static_cast<ZDCPrePulseFitWrapper*>(wrapper)->GetPreT0ParIndex();
2078 
2079  func_p->GetParLimits(parIndex, parLimitLow, parLimitHigh);
2080  fitter->SetParameter(parIndex + 1, func_p->GetParName(parIndex), func_p->GetParameter(parIndex), 0.01, parLimitLow, parLimitHigh);
2081  }
2082 }
2083 
2085 {
2086  (*m_msgFunc_p)(ZDCMsg::Info, ("ZDCPulseAnalyzer dump for tag = " + m_tag));
2087 
2088  (*m_msgFunc_p)(ZDCMsg::Info, ("Presample index, value = " + std::to_string(m_preSampleIdx) + ", " + std::to_string(m_preSample)));
2089 
2090  if (m_useDelayed) {
2091  (*m_msgFunc_p)(ZDCMsg::Info, ("using delayed samples with delta T = " + std::to_string(m_delayedDeltaT) + ", and pedestalDiff == " +
2093  }
2094 
2095  std::ostringstream message1;
2096  message1 << "samplesSub ";
2097  for (size_t sample = 0; sample < m_samplesSub.size(); sample++) {
2098  message1 << ", [" << sample << "] = " << m_samplesSub[sample];
2099  }
2100  (*m_msgFunc_p)(ZDCMsg::Info, message1.str());
2101 
2102  std::ostringstream message3;
2103  message3 << "samplesDeriv2nd ";
2104  for (size_t sample = 0; sample < m_samplesDeriv2nd.size(); sample++) {
2105  message3 << ", [" << sample << "] = " << m_samplesDeriv2nd[sample];
2106  }
2107  (*m_msgFunc_p)(ZDCMsg::Info, message3.str());
2108 
2109  (*m_msgFunc_p)(ZDCMsg::Info, ("minimum 2nd deriv sample, value = " + std::to_string(m_minDeriv2ndIndex) + ", " + std::to_string(m_minDeriv2nd)));
2110 }
2111 
2112 void ZDCPulseAnalyzer::dumpTF1(const TF1* func) const
2113 {
2114  std::string message = "Dump of TF1: " + std::string(func->GetName());
2115  bool continueDump = (*m_msgFunc_p)(ZDCMsg::Verbose, std::move(message));
2116  if (!continueDump) return;
2117 
2118  unsigned int npar = func->GetNpar();
2119  for (unsigned int ipar = 0; ipar < npar; ipar++) {
2120  std::ostringstream msgstr;
2121 
2122  double parMin = 0, parMax = 0;
2123  func->GetParLimits(ipar, parMin, parMax);
2124 
2125  msgstr << "Parameter " << ipar << ", value = " << func->GetParameter(ipar) << ", error = "
2126  << func->GetParError(ipar) << ", min = " << parMin << ", max = " << parMax;
2127  (*m_msgFunc_p)(ZDCMsg::Verbose, msgstr.str());
2128  }
2129 }
2130 
2132 {
2133  std::ostringstream ostrStream;
2134 
2135  (*m_msgFunc_p)(ZDCMsg::Info, ("ZDCPulserAnalyzer:: settings for instance: " + m_tag));
2136 
2137  ostrStream << "Nsample = " << m_Nsample << " at frequency " << m_freqMHz << " MHz, preSample index = "
2138  << m_preSampleIdx << ", nominal pedestal = " << m_pedestal;
2139 
2140  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2141 
2142  ostrStream << "LG mode = " << m_LGMode << ", gainFactor HG = " << m_gainFactorHG << ", gainFactor LG = " << m_gainFactorLG << ", noise sigma HG = " << m_noiseSigHG << ", noiseSigLG = " << m_noiseSigLG;
2143  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2144 
2145  ostrStream << "peak sample = " << m_peak2ndDerivMinSample << ", tolerance = " << m_peak2ndDerivMinTolerance
2146  << ", 2ndDerivThresh HG, LG = " << m_peak2ndDerivMinThreshHG << ", " << m_peak2ndDerivMinThreshLG
2147  << ", 2nd deriv step = " << m_2ndDerivStep;
2148  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2149 
2150  if (m_useDelayed) {
2151  ostrStream << "using delayed samples with delta T = " << m_delayedDeltaT << ", and default pedestalDiff == "
2153  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2154  }
2155 
2156  ostrStream << "m_fixTau1 = " << m_fixTau1 << ", m_fixTau2 = " << m_fixTau2 << ", m_nominalTau1 = " << m_nominalTau1
2157  << ", m_nominalTau2 = " << m_nominalTau2 << ", m_nominalT0HG = " << m_nominalT0HG
2158  << ", m_nominalT0LG = " << m_nominalT0LG;
2159  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2160 
2161  ostrStream << "m_HGOverflowADC = " << m_HGOverflowADC << ", m_HGUnderflowADC = " << m_HGUnderflowADC
2162  << ", m_LGOverflowADC = "<< m_LGOverflowADC;
2163  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2164 
2165  ostrStream << "m_chisqDivAmpCutLG = " << m_chisqDivAmpCutLG << ", m_chisqDivAmpCutHG=" << m_chisqDivAmpCutHG
2166  << ", t0Cuts HG = [" << m_T0CutLowHG << ", " << m_T0CutHighHG << "], t0Cuts LG = ["
2167  << m_T0CutLowLG << ", " << m_T0CutHighLG << "]";
2168  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2169 
2170  if ( m_enableRepass) {
2171  ostrStream << "Repass enabled with peak2ndDerivMinRepassHG = " << m_peak2ndDerivMinRepassHG << ", peak2ndDerivMinRepassLG = " << m_peak2ndDerivMinRepassLG;
2172  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2173  }
2174 
2175  if (m_enablePreExcl) {
2176  ostrStream << "Pre-exclusion enabled for up to " << m_maxSamplesPreExcl << ", samples with ADC threshold HG = "
2177  << m_preExclHGADCThresh << ", LG = " << m_preExclLGADCThresh;
2178  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2179  }
2180  if (m_enablePostExcl) {
2181  ostrStream << "Post-exclusion enabled for up to " << m_maxSamplesPostExcl << ", samples with ADC threshold HG = "
2182  << m_postExclHGADCThresh << ", LG = " << m_postExclLGADCThresh;
2183  (*m_msgFunc_p)(ZDCMsg::Info, ostrStream.str()); ostrStream.str(""); ostrStream.clear();
2184  }
2185 
2186 }
2187 
2189 {
2190  unsigned int statusMask = 0;
2191 
2192  if (havePulse()) statusMask |= 1 << PulseBit;
2193  if (useLowGain()) statusMask |= 1 << LowGainBit;
2194  if (failed()) statusMask |= 1 << FailBit;
2195  if (HGOverflow()) statusMask |= 1 << HGOverflowBit;
2196 
2197  if (HGUnderflow()) statusMask |= 1 << HGUnderflowBit;
2198  if (PSHGOverUnderflow()) statusMask |= 1 << PSHGOverUnderflowBit;
2199  if (LGOverflow()) statusMask |= 1 << LGOverflowBit;
2200  if (LGUnderflow()) statusMask |= 1 << LGUnderflowBit;
2201 
2202  if (prePulse()) statusMask |= 1 << PrePulseBit;
2203  if (postPulse()) statusMask |= 1 << PostPulseBit;
2204  if (fitFailed()) statusMask |= 1 << FitFailedBit;
2205  if (badChisq()) statusMask |= 1 << BadChisqBit;
2206 
2207  if (badT0()) statusMask |= 1 << BadT0Bit;
2208  if (excludeEarlyLG()) statusMask |= 1 << ExcludeEarlyLGBit;
2209  if (excludeLateLG()) statusMask |= 1 << ExcludeLateLGBit;
2210  if (preExpTail()) statusMask |= 1 << preExpTailBit;
2211  if (fitMinimumAmplitude()) statusMask |= 1 << FitMinAmpBit;
2212  if (repassPulse()) statusMask |= 1 << RepassPulseBit;
2213  if (armSumInclude()) statusMask |= 1 << ArmSumIncludeBit;
2214  if (failSigCut()) statusMask |= 1 << FailSigCutBit;
2215 
2216  return statusMask;
2217 }
2218 
2219 std::shared_ptr<TGraphErrors> ZDCPulseAnalyzer::GetCombinedGraph(bool LGRefit)
2220 {
2221  //
2222  // We defer filling the histogram if we don't have a pulse until the histogram is requested
2223  //
2224  GetHistogramPtr(LGRefit);
2225 
2226  TH1* hist_p = nullptr, *delayedHist_p = nullptr;
2227  if (LGRefit) {
2228  hist_p = m_fitHistLGRefit.get();
2229  delayedHist_p = m_delayedHistLGRefit.get();
2230  }
2231  else {
2232  hist_p = m_fitHist.get();
2233  delayedHist_p = m_delayedHist.get();
2234  }
2235 
2236  std::shared_ptr<TGraphErrors> theGraph = std::make_shared<TGraphErrors>(TGraphErrors(2 * m_Nsample));
2237  size_t npts = 0;
2238 
2239  for (int ipt = 0; ipt < hist_p->GetNbinsX(); ipt++) {
2240  theGraph->SetPoint(npts, hist_p->GetBinCenter(ipt + 1), hist_p->GetBinContent(ipt + 1));
2241  theGraph->SetPointError(npts++, 0, hist_p->GetBinError(ipt + 1));
2242  }
2243 
2244  for (int iDelayPt = 0; iDelayPt < delayedHist_p->GetNbinsX(); iDelayPt++) {
2245  theGraph->SetPoint(npts, delayedHist_p->GetBinCenter(iDelayPt + 1), delayedHist_p->GetBinContent(iDelayPt + 1) - m_delayedBaselineShift);
2246  theGraph->SetPointError(npts++, 0, delayedHist_p->GetBinError(iDelayPt + 1));
2247  }
2248  if (m_havePulse) {
2249  TF1* func_p = static_cast<TF1*>(hist_p->GetListOfFunctions()->Last());
2250  if (func_p) {
2251  theGraph->GetListOfFunctions()->Add(new TF1(*func_p));
2252  hist_p->GetListOfFunctions()->SetOwner (false);
2253  }
2254  }
2255  theGraph->SetName(( std::string(hist_p->GetName()) + "combinaed").c_str());
2256 
2257  theGraph->SetMarkerStyle(20);
2258  theGraph->SetMarkerColor(1);
2259 
2260  return theGraph;
2261 }
2262 
2263 
2264 std::shared_ptr<TGraphErrors> ZDCPulseAnalyzer::GetGraph(bool forceLG)
2265 {
2266  //
2267  // We defer filling the histogram if we don't have a pulse until the histogram is requested
2268  //
2269  const TH1* hist_p = GetHistogramPtr(forceLG);
2270 
2271  std::shared_ptr<TGraphErrors> theGraph = std::make_shared<TGraphErrors>(TGraphErrors(m_Nsample));
2272  size_t npts = 0;
2273 
2274  for (int ipt = 0; ipt < hist_p->GetNbinsX(); ipt++) {
2275  theGraph->SetPoint(npts, hist_p->GetBinCenter(ipt + 1), hist_p->GetBinContent(ipt + 1));
2276  theGraph->SetPointError(npts++, 0, hist_p->GetBinError(ipt + 1));
2277  }
2278 
2279  TF1* func_p = static_cast<TF1*>(hist_p->GetListOfFunctions()->Last());
2280  theGraph->GetListOfFunctions()->Add(func_p);
2281  theGraph->SetName(( std::string(hist_p->GetName()) + "not_combinaed").c_str());
2282 
2283  theGraph->SetMarkerStyle(20);
2284  theGraph->SetMarkerColor(1);
2285 
2286  return theGraph;
2287 }
2288 
2289 
2290 std::vector<float> ZDCPulseAnalyzer::CalculateDerivative(const std::vector <float>& inputData, unsigned int step)
2291 {
2292  unsigned int nSamples = inputData.size();
2293 
2294  // So we pad at the beginning and end based on step (i.e. with step - 1 zeros). Fill out the fill vector with zeros initially
2295  //
2296  unsigned int vecSize = 2*(step - 1) + nSamples - step - 1;
2297  std::vector<float> results(vecSize, 0);
2298 
2299  // Now fill out the values
2300  //
2301  unsigned int fillIdx = step - 1;
2302 
2303  for (unsigned int sample = 0; sample < nSamples - step; sample++) {
2304  int deriv = inputData[sample + step] - inputData[sample];
2305  results.at(fillIdx++) = deriv;
2306  }
2307 
2308  return results;
2309 }
2310 
2311 std::vector<float> ZDCPulseAnalyzer::Calculate2ndDerivative(const std::vector <float>& inputData, unsigned int step)
2312 {
2313  unsigned int nSamples = inputData.size();
2314 
2315  // We start with two zero entries for which we can't calculate the double-step derivative
2316  // and would pad with two zero entries at the end. Start by initializing
2317  //
2318  unsigned int vecSize = 2*step + nSamples - step - 1;
2319  std::vector<float> results(vecSize, 0);
2320 
2321  unsigned int fillIndex = step;
2322  for (unsigned int sample = step; sample < nSamples - step; sample++) {
2323  int deriv2nd = inputData[sample + step] + inputData[sample - step] - 2*inputData[sample];
2324  results.at(fillIndex++) = deriv2nd;
2325  }
2326 
2327  return results;
2328 }
2329 
2330 // Implement a more general method for the nasty problem (Runs 1 & 2 only) of matching
2331 // the baselines on the delayed and undelayed data. Instead of specifically looking
2332 // for early samples or late samples, find the region of the waveform with the smallest
2333 // combination of slope and second derivative in both sets of samples and match there.
2334 //
2335 // Depending on the second derivative
2336 // we match using linear or (negative) exponential interpolation
2337 //
2338 // Note: the samples have already been combined so we distinguish by even or odd index
2339 // we use step = 2 for the derivative and 2nd derivative calculation to handle
2340 // the delayed and undelayed separately.
2341 //
2342 //
2343 float ZDCPulseAnalyzer::obtainDelayedBaselineCorr(const std::vector<float>& samples)
2344 {
2345  const unsigned int nsamples = samples.size();
2346 
2347  std::vector<float> derivVec = CalculateDerivative(samples, 2);
2348  std::vector<float> deriv2ndVec = Calculate2ndDerivative(samples, 2);
2349 
2350  // Now step through and check even and odd samples values for 2nd derivative and derivative
2351  // we start with index 2 since the 2nd derivative calculation has 2 initial zeros with nstep = 2
2352  //
2353  float minScore = 1.0e9;
2354  unsigned int minIndex = 0;
2355 
2356  for (unsigned int idx = 2; idx < nsamples - 1; idx++) {
2357  float deriv = derivVec[idx];
2358  float prevDeriv = derivVec[idx - 1];
2359 
2360  float derivDiff = deriv - prevDeriv;
2361 
2362  float deriv2nd = deriv2ndVec[idx];
2363  if (idx > nsamples - 2) deriv2nd = deriv2ndVec[idx - 1];
2364 
2365  // Calculate a score based on the actual derivatives (squared) and 2nd derivatives (squared)
2366  // and the slope differences (squared). The relative weights are not adjustable for now
2367  //
2368  float score = (deriv*deriv + 2*derivDiff*derivDiff +
2369  0.5*deriv2nd*deriv2nd);
2370 
2371  if (score < minScore) {
2372  minScore = score;
2373  minIndex = idx;
2374  }
2375  }
2376 
2377  // We use four samples, two each of "even" and "odd".
2378  // Because of the way the above analysis is done, we can always
2379  // Go back one even and one odd sample and forward one odd sample.
2380  //
2381  //if minIndex is < 2 or >samples.size() the result is undefined; prevent this:
2382  if (minIndex<2 or (minIndex+1) >=nsamples){
2383  throw std::out_of_range("minIndex out of range in ZDCPulseAnalyzer::obtainDelayedBaselineCorr");
2384  }
2385  float sample0 = samples[minIndex - 2];
2386  float sample1 = samples[minIndex - 1];
2387  float sample2 = samples[minIndex];
2388  float sample3 = samples[minIndex + 1];
2389 
2390  // Possibility -- implement logarithmic interpolation for large 2nd derivative?
2391  //
2392  float baselineCorr = (0.5 * (sample1 - sample0 + sample3 - sample2) -
2393  0.25 * (sample3 - sample1 + sample2 - sample0));
2394 
2395  if (minIndex % 2 != 0) baselineCorr =-baselineCorr;
2396 
2397  return baselineCorr;
2398 }
2399 
2400 std::pair<bool, std::string> ZDCPulseAnalyzer::ValidateJSONConfig(const JSON& config)
2401 {
2402  bool result = true;
2403  std::string resultString = "success";
2404 
2405  for (auto [key, descr] : JSONConfigParams) {
2406  auto iter = config.find(key);
2407  if (iter != config.end()) {
2408  //
2409  // Check type consistency
2410  //
2411  auto jsonType = iter.value().type();
2412  auto paramType = std::get<0>(descr);
2413  if (jsonType != paramType) {
2414  result = false;
2415  resultString = "Bad type for parameter " + key + ", type in JSON = " + std::to_string((unsigned int) jsonType) ;
2416  break;
2417  }
2418 
2419  size_t paramSize = std::get<1>(descr);
2420  size_t jsonSize = iter.value().size();
2421  if (jsonSize != paramSize) {
2422  result = false;
2423  resultString = "Bad length for parameter " + key + ", length in JSON = " + std::to_string(jsonSize) ;
2424  break;
2425  }
2426  }
2427  else {
2428  bool required = std::get<2>(descr);
2429  if (required) {
2430  result = false;
2431  resultString = "Missing required parameter " + key;
2432  break;
2433  }
2434  }
2435  }
2436 
2437  if (result) {
2438  //
2439  // Now check that the parameters in the JSON object are in the master list of parameters
2440  //
2441  for (auto [key, value] : config.items()) {
2442  //
2443  // Look for this key in the list of allowed parameters. Yes, it's a slow
2444  // search but we only do it once at configuration time.
2445  //
2446  // bool found = false;
2447  auto iter = JSONConfigParams.find(key);
2448  if (iter == JSONConfigParams.end()) {
2449  result = false;
2450  resultString = "Unknown parameter, key = " + key;
2451  break;
2452  }
2453  }
2454  }
2455 
2456  return {result, resultString};
2457 }
2458 
2459 std::pair<bool, std::string> ZDCPulseAnalyzer::ConfigFromJSON(const JSON& config)
2460 {
2461  bool result = true;
2462  std::string resultString = "success";
2463 
2464  for (auto [key, value] : config.items()) {
2465  //
2466  // Big if statement to process configuration parameters
2467  //
2468  if (key == "Nsample") m_Nsample = value;
2469  else if (key == "tag") m_tag = value;
2470  else if (key == "LGMode") m_LGMode = value;
2471  else if (key == "Nsample") m_Nsample = value;
2472  else if (key == "useDelayed") m_useDelayed = value;
2473  else if (key == "preSampleIdx") m_preSampleIdx = value;
2474  else if (key == "FADCFreqMHz") m_freqMHz = value;
2475  else if (key == "nominalPedestal") m_pedestal = value;
2476  else if (key == "fitFunction") m_fitFunction = value;
2477  else if (key == "peakSample") m_peak2ndDerivMinSample = value;
2478  else if (key == "peakTolerance") m_peak2ndDerivMinTolerance = value;
2479  else if (key == "2ndDerivThreshHG") m_peak2ndDerivMinThreshHG = value;
2480  else if (key == "2ndDerivThreshLG") m_peak2ndDerivMinThreshLG = value;
2481  else if (key == "2ndDerivStep") m_2ndDerivStep = value;
2482  else if (key == "HGOverflowADC") m_HGOverflowADC = value;
2483  else if (key == "HGUnderflowADC") m_HGUnderflowADC = value;
2484  else if (key == "LGOverflowADC") m_LGOverflowADC = value;
2485  else if (key == "nominalT0HG") m_nominalT0HG = value;
2486  else if (key == "nominalT0LG") m_nominalT0LG = value;
2487  else if (key == "nominalTau1") m_nominalTau1 = value;
2488  else if (key == "nominalTau2") m_nominalTau2 = value;
2489  else if (key == "fixTau1") m_fixTau1 = value;
2490  else if (key == "fixTau2") m_fixTau2 = value;
2491  else if (key == "T0CutsHG") {
2492  m_T0CutLowHG = value[0];
2493  m_T0CutHighHG = value[1];
2494  }
2495  else if (key == "T0CutsLG") {
2496  m_T0CutLowLG = value[0];
2497  m_T0CutHighLG = value[1];
2498  }
2499  else if (key == "chisqDivAmpCutHG") m_chisqDivAmpCutHG = value;
2500  else if (key == "chisqDivAmpCutLG") m_chisqDivAmpCutLG = value;
2501  else if (key == "gainFactorHG") m_gainFactorHG = value;
2502  else if (key == "gainFactorLG") m_gainFactorLG = value;
2503  else if (key == "noiseSigmaHG") m_noiseSigHG = value;
2504  else if (key == "noiseSigmaLG") m_noiseSigLG = value;
2505  else if (key == "enableRepass") m_enableRepass = value;
2506  else if (key == "Repass2ndDerivThreshHG") m_peak2ndDerivMinRepassHG = value;
2507  else if (key == "Repass2ndDerivThreshLG") m_peak2ndDerivMinRepassLG = value;
2508  else if (key == "fitAmpMinMaxHG") {
2509  m_fitAmpMinHG = value[0];
2510  m_fitAmpMaxHG = value[1];
2511  }
2512  else if (key == "fitAmpMinMaxLG") {
2513  m_fitAmpMinLG = value[0];
2514  m_fitAmpMaxLG = value[1];
2515  }
2516  else if (key == "quietFits") {
2517  m_quietFits = value[0];
2518  }
2519  else if (key == "enablePreExclusion") {
2520  m_enablePreExcl = true;
2524  }
2525  else if (key == "enablePostExclusion") {
2526  m_enablePostExcl = true;
2530  }
2531  else if (key == "ampMinSignifHGLG") {
2532  m_haveSignifCuts = true;
2533  m_sigMinHG = value[0];
2534  m_sigMinLG = value[1];
2535  }
2536  else if (key == "enableFADCCorrections") {
2537  auto fileNameJson = value["filename"];
2538  auto doPerSampleCorrJson = value["doPerSampleCorr"];
2539 
2540  if (fileNameJson.is_null() || doPerSampleCorrJson.is_null()) {
2541  result = false;
2542  std::string resultString = "failure processing enableFADCCorrections object";
2543  break;
2544  }
2545 
2546  m_haveFADCCorrections = true;
2547  m_FADCCorrPerSample = doPerSampleCorrJson;
2548  m_fadcCorrFileName = fileNameJson;
2549  }
2550  else {
2551  result = false;
2552  std::string resultString = "unprocessed parameter";
2553  break;
2554  }
2555  }
2556 
2557  return {result, resultString};
2558 }
ZDCPulseAnalyzer::PrePulseBit
@ PrePulseBit
Definition: ZDCPulseAnalyzer.h:38
ZDCFitWrapper::GetAmplitude
virtual float GetAmplitude() const =0
ZDCPulseAnalyzer::SetupFitFunctions
void SetupFitFunctions()
Definition: ZDCPulseAnalyzer.cxx:651
ZDCPulseAnalyzer::m_LGOverflow
bool m_LGOverflow
Definition: ZDCPulseAnalyzer.h:244
ZDCPulseAnalyzer::m_fitTau2
float m_fitTau2
Definition: ZDCPulseAnalyzer.h:314
ZDCPulseAnalyzer::m_fitPostT0
float m_fitPostT0
Definition: ZDCPulseAnalyzer.h:319
ZDCPulseAnalyzer::m_defaultFitWrapper
std::unique_ptr< ZDCFitWrapper > m_defaultFitWrapper
Definition: ZDCPulseAnalyzer.h:207
covarianceTool.ndf
ndf
Definition: covarianceTool.py:678
ZDCPulseAnalyzer::m_failSigCut
bool m_failSigCut
Definition: ZDCPulseAnalyzer.h:260
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
ZDCPulseAnalyzer::m_defaultT0Max
float m_defaultT0Max
Definition: ZDCPulseAnalyzer.h:157
ZDCPulseAnalyzer::m_expAmplitude
float m_expAmplitude
Definition: ZDCPulseAnalyzer.h:328
ZDCPulseAnalyzer::m_minADCSampleLG
int m_minADCSampleLG
Definition: ZDCPulseAnalyzer.h:279
LArSamples::FitterData::fitter
const ShapeFitter * fitter
Definition: ShapeFitter.cxx:23
ZDCPulseAnalyzer::preExpTail
bool preExpTail() const
Definition: ZDCPulseAnalyzer.h:604
ZDCPulseAnalyzer::m_prePulseFitWrapper
std::unique_ptr< ZDCPrePulseFitWrapper > m_prePulseFitWrapper
Definition: ZDCPulseAnalyzer.h:208
ZDCPulseAnalyzer::m_useSampleHG
std::vector< bool > m_useSampleHG
Definition: ZDCPulseAnalyzer.h:351
ZDCPulseAnalyzer::m_enableRepass
bool m_enableRepass
Definition: ZDCPulseAnalyzer.h:110
ZDCPulseAnalyzer::SetGainFactorsHGLG
void SetGainFactorsHGLG(float gainFactorHG, float gainFactorLG)
Definition: ZDCPulseAnalyzer.cxx:445
ZDCPulseAnalyzer::m_ADCSamplesLG
std::vector< float > m_ADCSamplesLG
Definition: ZDCPulseAnalyzer.h:346
ZDCPulseAnalyzer::m_samplesSub
std::vector< float > m_samplesSub
Definition: ZDCPulseAnalyzer.h:356
ZDCPulseAnalyzer::m_fitPostAmp
float m_fitPostAmp
Definition: ZDCPulseAnalyzer.h:320
ZDCPulseAnalyzer::m_chisqDivAmpCutLG
float m_chisqDivAmpCutLG
Definition: ZDCPulseAnalyzer.h:143
ZDCPulseAnalyzer::enableRepass
void enableRepass(float peak2ndDerivMinRepassHG, float peak2ndDerivMinRepassLG)
Definition: ZDCPulseAnalyzer.cxx:227
ZDCPulseAnalyzer::m_NSamplesAna
unsigned int m_NSamplesAna
Definition: ZDCPulseAnalyzer.h:344
ZDCFitExpFermiVariableTausLHCf
Definition: ZDCFitWrapper.h:231
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
ZDCPulseAnalyzer::m_HGOverflowADC
int m_HGOverflowADC
Definition: ZDCPulseAnalyzer.h:127
ZDCPulseAnalyzer::m_enablePreExcl
bool m_enablePreExcl
Definition: ZDCPulseAnalyzer.h:172
ZDCPulseAnalyzer::m_LGT0CorrParams
std::vector< float > m_LGT0CorrParams
Definition: ZDCPulseAnalyzer.h:186
get_generator_info.result
result
Definition: get_generator_info.py:21
ZDCPulseAnalyzer::m_fitAmplitude
float m_fitAmplitude
Definition: ZDCPulseAnalyzer.h:306
ZDCPulseAnalyzer::m_HGOverflow
bool m_HGOverflow
Definition: ZDCPulseAnalyzer.h:240
AddEmptyComponent.histName
string histName
Definition: AddEmptyComponent.py:64
ZDCPulseAnalyzer::m_fitTau1
float m_fitTau1
Definition: ZDCPulseAnalyzer.h:313
ZDCPulseAnalyzer::m_useFixedBaseline
bool m_useFixedBaseline
Definition: ZDCPulseAnalyzer.h:220
ZDCPulseAnalyzer::RepassPulseBit
@ RepassPulseBit
Definition: ZDCPulseAnalyzer.h:49
ZDCPulseAnalyzer::m_postAmplitude
float m_postAmplitude
Definition: ZDCPulseAnalyzer.h:327
ZDCPulseAnalyzer::m_adjTimeRangeEvent
bool m_adjTimeRangeEvent
Definition: ZDCPulseAnalyzer.h:213
ZDCPulseAnalyzer::FillHistogram
void FillHistogram(bool refitLG)
Definition: ZDCPulseAnalyzer.h:405
ZDCPulseAnalyzer::m_haveFADCCorrections
bool m_haveFADCCorrections
Definition: ZDCPulseAnalyzer.h:195
ZDCPulseAnalyzer::m_minDeriv2nd
float m_minDeriv2nd
Definition: ZDCPulseAnalyzer.h:289
ZDCPulseAnalyzer::ReanalyzeData
bool ReanalyzeData()
Definition: ZDCPulseAnalyzer.cxx:821
ZDCPrePulseFitWrapper
Definition: ZDCFitWrapper.h:116
ZDCPulseAnalyzer::m_FADCCorrHG
std::unique_ptr< const TH1 > m_FADCCorrHG
Definition: ZDCPulseAnalyzer.h:198
ZDCFitExpFermiFixedTaus
Definition: ZDCFitWrapper.h:298
ZDCPulseAnalyzer::m_peak2ndDerivMinThreshLG
float m_peak2ndDerivMinThreshLG
Definition: ZDCPulseAnalyzer.h:105
ZDCPulseAnalyzer::m_2ndDerivStep
size_t m_2ndDerivStep
Definition: ZDCPulseAnalyzer.h:102
ZDCPulseAnalyzer::m_quietFits
bool m_quietFits
Definition: ZDCPulseAnalyzer.h:77
ZDCPulseAnalyzer::m_nonLinCorrRefScale
float m_nonLinCorrRefScale
Definition: ZDCPulseAnalyzer.h:191
ZDCPulseAnalyzer::m_timeCutMode
unsigned int m_timeCutMode
Definition: ZDCPulseAnalyzer.h:155
ZDCPulseAnalyzer::GetHistogramPtr
const TH1 * GetHistogramPtr(bool refitLG=false)
Definition: ZDCPulseAnalyzer.h:716
ZDCPulseAnalyzer::MakeCombinedFitter
static std::unique_ptr< TFitter > MakeCombinedFitter(TF1 *func)
Definition: ZDCPulseAnalyzer.cxx:2029
ZDCPulseAnalyzer::m_fitAmpMaxHG
float m_fitAmpMaxHG
Definition: ZDCPulseAnalyzer.h:163
ZDCPulseAnalyzer::m_backToHG_pre
bool m_backToHG_pre
Definition: ZDCPulseAnalyzer.h:264
ZDCFitWrapper
Definition: ZDCFitWrapper.h:19
TRT::Track::chiSquare
@ chiSquare
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:67
ZDCPulseAnalyzer::FailSigCutBit
@ FailSigCutBit
Definition: ZDCPulseAnalyzer.h:51
ZDCPulseAnalyzer.h
ZDCPulseAnalyzer::m_refitLGAmpl
float m_refitLGAmpl
Definition: ZDCPulseAnalyzer.h:333
ZDCPulseAnalyzer::m_fitTimeSub
float m_fitTimeSub
Definition: ZDCPulseAnalyzer.h:309
ZDCPulseAnalyzer::m_delayedPedestalDiff
float m_delayedPedestalDiff
Definition: ZDCPulseAnalyzer.h:222
ZDCPulseAnalyzer::enableTimeSigCut
void enableTimeSigCut(bool AND, float sigCut, const std::string &TF1String, const std::vector< double > &parsHG, const std::vector< double > &parsLG)
Definition: ZDCPulseAnalyzer.cxx:511
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
ZDCPulseAnalyzer::ExcludeLateLGBit
@ ExcludeLateLGBit
Definition: ZDCPulseAnalyzer.h:45
ZDCPulseAnalyzer::DoFitCombined
void DoFitCombined(bool refitLG=false)
Definition: ZDCPulseAnalyzer.cxx:1726
ZDCFitWrapper::ConstrainFit
virtual void ConstrainFit()=0
ZDCPulseAnalyzer::m_sigMinHG
float m_sigMinHG
Definition: ZDCPulseAnalyzer.h:167
ZDCPulseAnalyzer::LGOverflow
bool LGOverflow() const
Definition: ZDCPulseAnalyzer.h:593
ZDCFitWrapper::GetTime
virtual float GetTime() const =0
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
ZDCPulseAnalyzer::m_timingCorrRefADC
float m_timingCorrRefADC
Definition: ZDCPulseAnalyzer.h:184
ZDCPulseAnalyzer::UpdateFitterTimeLimits
void UpdateFitterTimeLimits(TFitter *fitter, ZDCFitWrapper *wrapper, bool prePulse)
Definition: ZDCPulseAnalyzer.cxx:2067
ZDCPulseAnalyzer::GetStatusMask
unsigned int GetStatusMask() const
Definition: ZDCPulseAnalyzer.cxx:2188
ZDCPulseAnalyzer::m_postPulse
bool m_postPulse
Definition: ZDCPulseAnalyzer.h:248
ZDCPulseAnalyzer::m_defaultCombinedFitter
std::unique_ptr< TFitter > m_defaultCombinedFitter
Definition: ZDCPulseAnalyzer.h:227
ZDCPulseAnalyzer::m_nominalT0HG
float m_nominalT0HG
Definition: ZDCPulseAnalyzer.h:131
ZDCPulseAnalyzer::m_minADCLG
float m_minADCLG
Definition: ZDCPulseAnalyzer.h:278
ZDCPulseAnalyzer::m_delayedHist
std::unique_ptr< TH1 > m_delayedHist
Definition: ZDCPulseAnalyzer.h:223
ZDCPulseAnalyzer::SetCutValues
void SetCutValues(float chisqDivAmpCutHG, float chisqDivAmpCutLG, float deltaT0MinHG, float deltaT0MaxHG, float deltaT0MinLG, float deltaT0MaxLG)
Definition: ZDCPulseAnalyzer.cxx:497
ZDCPulseAnalyzer::LGOverflowBit
@ LGOverflowBit
Definition: ZDCPulseAnalyzer.h:35
ZDCPulseAnalyzer::m_fitHistLGRefit
std::unique_ptr< TH1 > m_fitHistLGRefit
Definition: ZDCPulseAnalyzer.h:204
ZDCPulseAnalyzer::m_haveNonlinCorr
bool m_haveNonlinCorr
Definition: ZDCPulseAnalyzer.h:189
ZDCPulseAnalyzer::m_preExpTail
bool m_preExpTail
Definition: ZDCPulseAnalyzer.h:255
ZDCPulseAnalyzer::m_bkgdMaxFraction
float m_bkgdMaxFraction
Definition: ZDCPulseAnalyzer.h:329
ZDCPulseAnalyzer::m_tag
std::string m_tag
Definition: ZDCPulseAnalyzer.h:90
ZDCPulseAnalyzer::ScanAndSubtractSamples
bool ScanAndSubtractSamples()
Definition: ZDCPulseAnalyzer.cxx:833
ZDCFitExpFermiLinearPrePulse
Definition: ZDCFitWrapper.h:850
Root::AND
@ AND
Definition: TGRLCollection.h:32
ZDCPulseAnalyzer::m_sigMinLG
float m_sigMinLG
Definition: ZDCPulseAnalyzer.h:168
ZDCPulseAnalyzer::AnalyzeData
bool AnalyzeData(size_t nSamples, size_t preSample, const std::vector< float > &samples, const std::vector< bool > &useSamples, float peak2ndDerivMinThresh, float noiseSig, const std::vector< float > &toCorrParams, float maxChisqDivAmp, float minT0Corr, float maxT0Corr)
Definition: ZDCPulseAnalyzer.cxx:1123
athena.value
value
Definition: athena.py:124
ZDCPreExpFitWrapper
Definition: ZDCFitWrapper.h:144
ZDCPulseAnalyzer::m_prePulseSig
float m_prePulseSig
Definition: ZDCPulseAnalyzer.h:299
ZDCPulseAnalyzer::m_HGUnderflow
bool m_HGUnderflow
Definition: ZDCPulseAnalyzer.h:242
ZDCPulseAnalyzer::BadChisqBit
@ BadChisqBit
Definition: ZDCPulseAnalyzer.h:41
ZDCPulseAnalyzer::useLowGain
bool useLowGain() const
Definition: ZDCPulseAnalyzer.h:587
ZDCPulseAnalyzer::SetDefaults
void SetDefaults()
Definition: ZDCPulseAnalyzer.cxx:234
ZDCPulseAnalyzer::armSumInclude
bool armSumInclude() const
Definition: ZDCPulseAnalyzer.h:607
ZDCFitWrapper::GetWrapperTF1
virtual std::shared_ptr< TF1 > GetWrapperTF1()
Definition: ZDCFitWrapper.h:110
ZDCPulseAnalyzer::m_fixTau2
bool m_fixTau2
Definition: ZDCPulseAnalyzer.h:138
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
ZDCJSONConfig::JSONParamList
std::map< std::string, JSONParamDescr > JSONParamList
Definition: ZDCJSONConfig.h:12
ZDCPulseAnalyzer::m_defaultFitTMax
float m_defaultFitTMax
Definition: ZDCPulseAnalyzer.h:140
MuonR4::to_string
std::string to_string(const SectorProjector proj)
Definition: MsTrackSeeder.cxx:74
ZDCPulseAnalyzer::m_delayedBaselineShift
float m_delayedBaselineShift
Definition: ZDCPulseAnalyzer.h:330
ZDCPulseAnalyzer::m_maxADCSampleHG
int m_maxADCSampleHG
Definition: ZDCPulseAnalyzer.h:275
ZDCPulseAnalyzer::m_badT0
bool m_badT0
Definition: ZDCPulseAnalyzer.h:252
ZDCPulseAnalyzer::m_fitMinAmp
bool m_fitMinAmp
Definition: ZDCPulseAnalyzer.h:258
ZDCMsg::Info
@ Info
Definition: ZDCMsg.h:20
ZDCPulseAnalyzer::s_delayedFitHist
static TH1 * s_delayedFitHist
Definition: ZDCPulseAnalyzer.h:81
ZDCPulseAnalyzer::HGOverflowBit
@ HGOverflowBit
Definition: ZDCPulseAnalyzer.h:31
ReweightUtils.message
message
Definition: ReweightUtils.py:15
ZDCPulseAnalyzer::m_samplesDeriv2nd
std::vector< float > m_samplesDeriv2nd
Definition: ZDCPulseAnalyzer.h:362
ZDCFitExpFermiLHCfPreExp
Definition: ZDCFitWrapper.h:672
ZDCPulseAnalyzer::repassPulse
bool repassPulse() const
Definition: ZDCPulseAnalyzer.h:606
ZDCFitWrapper::GetTau2
virtual float GetTau2() const =0
ZDCPulseAnalyzer::m_haveData
bool m_haveData
Definition: ZDCPulseAnalyzer.h:235
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
ZDCPulseAnalyzer::badChisq
bool badChisq() const
Definition: ZDCPulseAnalyzer.h:599
ZDCPulseAnalyzer::HGOverflow
bool HGOverflow() const
Definition: ZDCPulseAnalyzer.h:589
ZDCPulseAnalyzer::m_maxADCSampleLG
int m_maxADCSampleLG
Definition: ZDCPulseAnalyzer.h:280
ZDCPulseAnalyzer::s_combinedFitFunc
static TF1 * s_combinedFitFunc
Definition: ZDCPulseAnalyzer.h:82
ZDCPulseAnalyzer::m_ADCPeakHG
float m_ADCPeakHG
Definition: ZDCPulseAnalyzer.h:282
ZDCPulseAnalyzer::m_nominalTau2
float m_nominalTau2
Definition: ZDCPulseAnalyzer.h:135
ZDCPulseAnalyzer::m_prePulse
bool m_prePulse
Definition: ZDCPulseAnalyzer.h:247
ZDCPulseAnalyzer::s_combinedFitTMin
static float s_combinedFitTMin
Definition: ZDCPulseAnalyzer.h:84
ZDCPulseAnalyzer::dumpConfiguration
void dumpConfiguration() const
Definition: ZDCPulseAnalyzer.cxx:2131
ZDCPulseAnalyzer::PulseBit
@ PulseBit
Definition: ZDCPulseAnalyzer.h:28
ZDCPulseAnalyzer::PSHGOverUnderflow
bool PSHGOverUnderflow() const
Definition: ZDCPulseAnalyzer.h:592
ZDCPulseAnalyzer::m_useSampleLG
std::vector< bool > m_useSampleLG
Definition: ZDCPulseAnalyzer.h:350
ZDCPulseAnalyzer::m_ampNoNonLin
float m_ampNoNonLin
Definition: ZDCPulseAnalyzer.h:323
ZDCPulseAnalyzer::m_fitFunction
std::string m_fitFunction
Definition: ZDCPulseAnalyzer.h:101
ZDCPulseAnalyzer::LoadAndAnalyzeData
bool LoadAndAnalyzeData(const std::vector< float > &ADCSamplesHG, const std::vector< float > &ADCSamplesLG)
Definition: ZDCPulseAnalyzer.cxx:744
ZDCPulseAnalyzer::m_preExclHGADCThresh
unsigned int m_preExclHGADCThresh
Definition: ZDCPulseAnalyzer.h:174
ZDCPulseAnalyzer::m_pedestal
int m_pedestal
Definition: ZDCPulseAnalyzer.h:95
ZDCPulseAnalyzer::SampleCIter
std::vector< float >::const_iterator SampleCIter
Definition: ZDCPulseAnalyzer.h:73
ZDCPulseAnalyzer::m_fixPrePulse
bool m_fixPrePulse
Definition: ZDCPulseAnalyzer.h:257
ZDCPulseAnalyzer::m_fitPulls
std::vector< float > m_fitPulls
Definition: ZDCPulseAnalyzer.h:369
tools.zlumi_mc_cf.correction
def correction(mu, runmode, campaign, run=None)
Definition: zlumi_mc_cf.py:4
ZDCPulseAnalyzer::m_preSample
float m_preSample
Definition: ZDCPulseAnalyzer.h:270
ZDCPulseAnalyzer::TimingCorrLog
@ TimingCorrLog
Definition: ZDCPulseAnalyzer.h:61
ZDCPulseAnalyzer::m_fitOptions
std::string m_fitOptions
Definition: ZDCPulseAnalyzer.h:126
ZDCMsg::Verbose
@ Verbose
Definition: ZDCMsg.h:18
ZDCPulseAnalyzer::ValidateJSONConfig
std::pair< bool, std::string > ValidateJSONConfig(const JSON &config)
Definition: ZDCPulseAnalyzer.cxx:2400
ZDCFitWrapper::UnconstrainFit
virtual void UnconstrainFit()=0
ZDCPulseAnalyzer::m_postExclHGADCThresh
unsigned int m_postExclHGADCThresh
Definition: ZDCPulseAnalyzer.h:178
ZDCPulseAnalyzer::m_nominalT0LG
float m_nominalT0LG
Definition: ZDCPulseAnalyzer.h:132
ZDCPulseAnalyzer::m_minADCHG
float m_minADCHG
Definition: ZDCPulseAnalyzer.h:272
ZDCPulseAnalyzer::m_fitAmpMinLG
float m_fitAmpMinLG
Definition: ZDCPulseAnalyzer.h:161
ZDCPulseAnalyzer::m_badChisq
bool m_badChisq
Definition: ZDCPulseAnalyzer.h:250
ZDCPulseAnalyzer::m_t0CutSig
float m_t0CutSig
Definition: ZDCPulseAnalyzer.h:154
ZDCPulseAnalyzer::m_saveFitFunc
bool m_saveFitFunc
Definition: ZDCPulseAnalyzer.h:78
ZDCFitWrapper::GetAmpError
virtual float GetAmpError() const =0
ZDCPulseAnalyzer::m_peak2ndDerivMinRepassHG
float m_peak2ndDerivMinRepassHG
Definition: ZDCPulseAnalyzer.h:112
ZDCPulseAnalyzer::m_initialPrePulseAmp
float m_initialPrePulseAmp
Definition: ZDCPulseAnalyzer.h:302
ZDCPulseAnalyzer::m_evtLGRefit
bool m_evtLGRefit
Definition: ZDCPulseAnalyzer.h:332
ZDCPulseAnalyzer::m_peak2ndDerivMinRepassLG
float m_peak2ndDerivMinRepassLG
Definition: ZDCPulseAnalyzer.h:111
ZDCPulseAnalyzer::m_fitPostT0lo
float m_fitPostT0lo
Definition: ZDCPulseAnalyzer.h:295
FullCPAlgorithmsTest_eljob.sample
sample
Definition: FullCPAlgorithmsTest_eljob.py:116
ZDCPulseAnalyzer::m_fixTau1
bool m_fixTau1
Definition: ZDCPulseAnalyzer.h:137
ZDCFitWrapper::GetWrapperTF1RawPtr
virtual TF1 * GetWrapperTF1RawPtr() const
Definition: ZDCFitWrapper.h:112
ZDCJSONConfig::JSON
nlohmann::json JSON
Definition: ZDCJSONConfig.h:10
xmin
double xmin
Definition: listroot.cxx:60
ZDCPulseAnalyzer::m_fitTMax
float m_fitTMax
Definition: ZDCPulseAnalyzer.h:292
ZDCPulseAnalyzer::PostPulseBit
@ PostPulseBit
Definition: ZDCPulseAnalyzer.h:39
ZDCPulseAnalyzer::m_fitChisq
float m_fitChisq
Definition: ZDCPulseAnalyzer.h:315
ZDCPulseAnalyzer::CombinedPulsesFCN
static void CombinedPulsesFCN(int &numParam, double *, double &f, double *par, int flag)
Definition: ZDCPulseAnalyzer.cxx:84
ZDCPulseAnalyzer::m_noiseSigHG
float m_noiseSigHG
Definition: ZDCPulseAnalyzer.h:121
ZDCPulseAnalyzer::m_maxADCLG
float m_maxADCLG
Definition: ZDCPulseAnalyzer.h:277
ZDCPulseAnalyzer::excludeLateLG
bool excludeLateLG() const
Definition: ZDCPulseAnalyzer.h:603
ZDCPulseAnalyzer::m_fail
bool m_fail
Definition: ZDCPulseAnalyzer.h:239
ZDCPulseAnalyzer::m_fitPreAmp
float m_fitPreAmp
Definition: ZDCPulseAnalyzer.h:318
ZDCPulseAnalyzer::LGUnderflow
bool LGUnderflow() const
Definition: ZDCPulseAnalyzer.h:594
ZDCPulseAnalyzer::m_refitLGChisq
float m_refitLGChisq
Definition: ZDCPulseAnalyzer.h:337
master.flag
bool flag
Definition: master.py:29
ZDCPulseAnalyzer::m_deltaTSample
float m_deltaTSample
Definition: ZDCPulseAnalyzer.h:94
ZDCPulseAnalyzer::m_nonLinCorrParamsLG
std::vector< float > m_nonLinCorrParamsLG
Definition: ZDCPulseAnalyzer.h:193
ZDCPulseAnalyzer::m_gainFactorLG
float m_gainFactorLG
Definition: ZDCPulseAnalyzer.h:117
ZDCPulseAnalyzer::m_minSampleEvt
unsigned int m_minSampleEvt
Definition: ZDCPulseAnalyzer.h:215
ZDCPulseAnalyzer::m_noiseSigLG
float m_noiseSigLG
Definition: ZDCPulseAnalyzer.h:122
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:525
ZDCPulseAnalyzer::m_gainFactorHG
float m_gainFactorHG
Definition: ZDCPulseAnalyzer.h:116
ZDCPulseAnalyzer::m_fitFailed
bool m_fitFailed
Definition: ZDCPulseAnalyzer.h:249
ZDCPulseAnalyzer::fitFailed
bool fitFailed() const
Definition: ZDCPulseAnalyzer.h:598
ZDCPulseAnalyzer::m_maxSampleEvt
unsigned int m_maxSampleEvt
Definition: ZDCPulseAnalyzer.h:216
ZDCPulseAnalyzer::m_timingCorrScale
float m_timingCorrScale
Definition: ZDCPulseAnalyzer.h:185
ZDCPulseAnalyzer::m_initialExpAmp
float m_initialExpAmp
Definition: ZDCPulseAnalyzer.h:288
ZDCPulseAnalyzer::m_maxADCHG
float m_maxADCHG
Definition: ZDCPulseAnalyzer.h:273
ZDCPulseAnalyzer::m_freqMHz
float m_freqMHz
Definition: ZDCPulseAnalyzer.h:93
ZDCPulseAnalyzer::m_ADCSamplesHG
std::vector< float > m_ADCSamplesHG
Definition: ZDCPulseAnalyzer.h:345
ZDCPulseAnalyzer::LGModeForceLG
@ LGModeForceLG
Definition: ZDCPulseAnalyzer.h:57
python.StandardJetMods.pull
pull
Definition: StandardJetMods.py:309
ZDCPulseAnalyzer::m_T0CutLowHG
float m_T0CutLowHG
Definition: ZDCPulseAnalyzer.h:149
ZDCPulseAnalyzer::m_fitNDoF
float m_fitNDoF
Definition: ZDCPulseAnalyzer.h:316
add-xsec-uncert-quadrature-N.results
dictionary results
Definition: add-xsec-uncert-quadrature-N.py:39
ZDCFitWrapper::GetBkgdMaxFraction
virtual float GetBkgdMaxFraction() const =0
hist_file_dump.f
f
Definition: hist_file_dump.py:140
ZDCPulseAnalyzer::GetCombinedGraph
std::shared_ptr< TGraphErrors > GetCombinedGraph(bool forceLG=false)
Definition: ZDCPulseAnalyzer.cxx:2219
ZDCPulseAnalyzer::m_havePulse
bool m_havePulse
Definition: ZDCPulseAnalyzer.h:237
python.TransformConfig.descr
descr
print "%s.properties()" % self.__name__
Definition: TransformConfig.py:359
python.AtlRunQueryLib.options
options
Definition: AtlRunQueryLib.py:378
ZDCPulseAnalyzer::m_refitLGAmplCorr
float m_refitLGAmplCorr
Definition: ZDCPulseAnalyzer.h:335
ZDCPulseAnalyzer::m_nonLinCorrRefADC
float m_nonLinCorrRefADC
Definition: ZDCPulseAnalyzer.h:190
ZDCPulseAnalyzer::m_T0CutHighLG
float m_T0CutHighLG
Definition: ZDCPulseAnalyzer.h:147
ZDCPulseAnalyzer::ConfigFromJSON
std::pair< bool, std::string > ConfigFromJSON(const JSON &config)
Definition: ZDCPulseAnalyzer.cxx:2459
ZDCFitExpFermiPrePulse
Definition: ZDCFitWrapper.h:361
ZDCPulseAnalyzer::m_ampError
float m_ampError
Definition: ZDCPulseAnalyzer.h:324
ZDCFitExpFermiVariableTaus
Definition: ZDCFitWrapper.h:164
ZDCPulseAnalyzer::ZDCPulseAnalyzer
ZDCPulseAnalyzer(ZDCMsg::MessageFunctionPtr msgFunc_p, const std::string &tag, int Nsample, float deltaTSample, size_t preSampleIdx, int pedestal, float gainHG, const std::string &fitFunction, int peak2ndDerivMinSample, float peak2DerivMinThreshHG, float peak2DerivMinThreshLG)
Definition: ZDCPulseAnalyzer.cxx:138
ZDCPulseAnalyzer::SetADCOverUnderflowValues
void SetADCOverUnderflowValues(int HGOverflowADC, int HGUnderflowADC, int LGOverflowADC)
Definition: ZDCPulseAnalyzer.cxx:490
ZDCPulseAnalyzer::m_ExcludeLate
bool m_ExcludeLate
Definition: ZDCPulseAnalyzer.h:254
ZDCPulseAnalyzer::m_preExclLGADCThresh
unsigned int m_preExclLGADCThresh
Definition: ZDCPulseAnalyzer.h:175
ZDCPulseAnalyzer::m_ADCPeakLG
float m_ADCPeakLG
Definition: ZDCPulseAnalyzer.h:283
ZDCPulseAnalyzer::m_refitLGFitAmpl
float m_refitLGFitAmpl
Definition: ZDCPulseAnalyzer.h:334
ZDCPulseAnalyzer::m_enablePostExcl
bool m_enablePostExcl
Definition: ZDCPulseAnalyzer.h:177
perfmonmt-printer.required
required
Definition: perfmonmt-printer.py:184
ZDCPulseAnalyzer::JSONConfigParams
static const ZDCJSONConfig::JSONParamList JSONConfigParams
Definition: ZDCPulseAnalyzer.h:71
ZDCPulseAnalyzer::preExpTailBit
@ preExpTailBit
Definition: ZDCPulseAnalyzer.h:46
ZDCPulseAnalyzer::obtainDelayedBaselineCorr
static float obtainDelayedBaselineCorr(const std::vector< float > &samples)
Definition: ZDCPulseAnalyzer.cxx:2343
ZDCPulseAnalyzer::m_ADCSamplesHGSub
std::vector< float > m_ADCSamplesHGSub
Definition: ZDCPulseAnalyzer.h:347
ZDCPulseAnalyzer::m_fitPreT0
float m_fitPreT0
Definition: ZDCPulseAnalyzer.h:317
ZDCPulseAnalyzer::m_useDelayed
bool m_useDelayed
Definition: ZDCPulseAnalyzer.h:108
lumiFormat.array
array
Definition: lumiFormat.py:91
ZDCMsg::Error
@ Error
Definition: ZDCMsg.h:22
ZDCPulseAnalyzer::SetTauT0Values
void SetTauT0Values(bool fixTau1, bool fixTau2, float tau1, float tau2, float t0HG, float t0LG)
Definition: ZDCPulseAnalyzer.cxx:460
ZDCPulseAnalyzer::HGUnderflow
bool HGUnderflow() const
Definition: ZDCPulseAnalyzer.h:591
ZDCPulseAnalyzer::SetFitMinMaxAmp
void SetFitMinMaxAmp(float minAmpHG, float minAmpLG, float maxAmpHG, float maxAmpLG)
Definition: ZDCPulseAnalyzer.cxx:451
ZDCPulseAnalyzer::m_LGMode
unsigned int m_LGMode
Definition: ZDCPulseAnalyzer.h:97
ZDCPulseAnalyzer::m_HGUnderflowADC
int m_HGUnderflowADC
Definition: ZDCPulseAnalyzer.h:128
ZDCPulseAnalyzer::checkTF1Limits
void checkTF1Limits(TF1 *func)
Definition: ZDCPulseAnalyzer.cxx:2000
ZDCPulseAnalyzer::m_useLowGain
bool m_useLowGain
Definition: ZDCPulseAnalyzer.h:238
ZDCPulseAnalyzer::LowGainBit
@ LowGainBit
Definition: ZDCPulseAnalyzer.h:29
ZDCPulseAnalyzer::m_ADCSSampSigLG
std::vector< float > m_ADCSSampSigLG
Definition: ZDCPulseAnalyzer.h:354
ZDCPulseAnalyzer::Calculate2ndDerivative
static std::vector< float > Calculate2ndDerivative(const std::vector< float > &inputData, unsigned int step)
Definition: ZDCPulseAnalyzer.cxx:2311
ZDCPulseAnalyzer::m_repassPulse
bool m_repassPulse
Definition: ZDCPulseAnalyzer.h:259
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
createCoolChannelIdFile.par
par
Definition: createCoolChannelIdFile.py:28
ZDCPulseAnalyzer::m_ExcludeEarly
bool m_ExcludeEarly
Definition: ZDCPulseAnalyzer.h:253
ZDCPulseAnalyzer::HGUnderflowBit
@ HGUnderflowBit
Definition: ZDCPulseAnalyzer.h:33
ZDCPulseAnalyzer::m_preSampleIdx
unsigned int m_preSampleIdx
Definition: ZDCPulseAnalyzer.h:92
ZDCPulseAnalyzer::m_delayedDeltaT
float m_delayedDeltaT
Definition: ZDCPulseAnalyzer.h:221
ZDCFitWrapper::Initialize
void Initialize(float initialAmp, float initialT0, float ampMin, float ampMax)
Definition: ZDCFitWrapper.cxx:9
ZDCPulseAnalyzer::GetGraph
std::shared_ptr< TGraphErrors > GetGraph(bool forceLG=false)
Definition: ZDCPulseAnalyzer.cxx:2264
ZDCPulseAnalyzer::m_preExpSig
float m_preExpSig
Definition: ZDCPulseAnalyzer.h:298
ZDCPulseAnalyzer::JSON
ZDCJSONConfig::JSON JSON
Definition: ZDCPulseAnalyzer.h:26
ZDCFitWrapper::GetTau1
virtual float GetTau1() const =0
ZDCPulseAnalyzer::m_timeResFuncLG_p
std::unique_ptr< const TF1 > m_timeResFuncLG_p
Definition: ZDCPulseAnalyzer.h:153
ZDCPulseAnalyzer::m_minDeriv2ndSig
float m_minDeriv2ndSig
Definition: ZDCPulseAnalyzer.h:297
ZDCPulseAnalyzer::m_fitTime
float m_fitTime
Definition: ZDCPulseAnalyzer.h:308
ZDCPulseAnalyzer::m_preExpFitWrapper
std::unique_ptr< ZDCPreExpFitWrapper > m_preExpFitWrapper
Definition: ZDCPulseAnalyzer.h:209
ZDCMsg::MessageFunctionPtr
std::shared_ptr< MessageFunction > MessageFunctionPtr
Definition: ZDCMsg.h:14
ZDCPulseAnalyzer::ArmSumIncludeBit
@ ArmSumIncludeBit
Definition: ZDCPulseAnalyzer.h:50
ZDCPulseAnalyzer::m_peak2ndDerivMinSample
size_t m_peak2ndDerivMinSample
Definition: ZDCPulseAnalyzer.h:103
ZDCPulseAnalyzer::SetFitTimeMax
void SetFitTimeMax(float tmax)
Definition: ZDCPulseAnalyzer.cxx:478
ZDCPulseAnalyzer::m_delayedHistLGRefit
std::unique_ptr< TH1 > m_delayedHistLGRefit
Definition: ZDCPulseAnalyzer.h:224
ZDCPulseAnalyzer::failed
bool failed() const
Definition: ZDCPulseAnalyzer.h:588
ZDCFitComplexPrePulse
Definition: ZDCFitWrapper.h:963
ZDCPulseAnalyzer::m_usedPresampIdx
int m_usedPresampIdx
Definition: ZDCPulseAnalyzer.h:269
ZDCPulseAnalyzer::NoTimingCorr
@ NoTimingCorr
Definition: ZDCPulseAnalyzer.h:61
ZDCPulseAnalyzer::badT0
bool badT0() const
Definition: ZDCPulseAnalyzer.h:601
ZDCPulseAnalyzer::m_lastHGOverFlowSample
int m_lastHGOverFlowSample
Definition: ZDCPulseAnalyzer.h:341
ZDCPulseAnalyzer::BadT0Bit
@ BadT0Bit
Definition: ZDCPulseAnalyzer.h:43
xAOD::score
@ score
Definition: TrackingPrimitives.h:514
ZDCPulseAnalyzer::m_samplesLGRefit
std::vector< float > m_samplesLGRefit
Definition: ZDCPulseAnalyzer.h:359
ReadOfcFromCool.nsamples
nsamples
Definition: ReadOfcFromCool.py:115
JSON
ZDCJSONConfig::JSON JSON
Definition: ZDCPulseAnalyzer.cxx:20
ZDCPulseAnalyzer::m_chisqDivAmpCutHG
float m_chisqDivAmpCutHG
Definition: ZDCPulseAnalyzer.h:144
ZDCPulseAnalyzer::m_peak2ndDerivMinTolerance
size_t m_peak2ndDerivMinTolerance
Definition: ZDCPulseAnalyzer.h:104
ZDCPulseAnalyzer::m_baselineCorr
float m_baselineCorr
Definition: ZDCPulseAnalyzer.h:265
ZDCPulseAnalyzer::ExcludeEarlyLGBit
@ ExcludeEarlyLGBit
Definition: ZDCPulseAnalyzer.h:44
ZDCPulseAnalyzer::m_PSHGOverUnderflow
bool m_PSHGOverUnderflow
Definition: ZDCPulseAnalyzer.h:243
ZDCFitExpFermiVariableTausRun3
Definition: ZDCFitWrapper.h:292
ZDCPulseAnalyzer::DoFit
void DoFit(bool refitLG=false)
Definition: ZDCPulseAnalyzer.cxx:1552
ZDCPulseAnalyzer::m_preAmplitude
float m_preAmplitude
Definition: ZDCPulseAnalyzer.h:326
ZDCPulseAnalyzer::m_tmin
float m_tmin
Definition: ZDCPulseAnalyzer.h:98
ZDCPulseAnalyzer::PSHGOverUnderflowBit
@ PSHGOverUnderflowBit
Definition: ZDCPulseAnalyzer.h:34
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
ZDCPulseAnalyzer::prepareLGRefit
void prepareLGRefit(const std::vector< float > &samplesLG, const std::vector< float > &samplesSig, const std::vector< bool > &useSamples)
Definition: ZDCPulseAnalyzer.cxx:1529
ZDCPulseAnalyzer::failSigCut
bool failSigCut() const
Definition: ZDCPulseAnalyzer.h:608
ZDCPulseAnalyzer::m_ADCSSampSigHG
std::vector< float > m_ADCSSampSigHG
Definition: ZDCPulseAnalyzer.h:353
ZDCPulseAnalyzer::m_fitAmpMaxLG
float m_fitAmpMaxLG
Definition: ZDCPulseAnalyzer.h:164
ZDCPulseAnalyzer::DoAnalysis
bool DoAnalysis(bool repass)
Definition: ZDCPulseAnalyzer.cxx:1017
ZDCPulseAnalyzer::Reset
void Reset(bool reanalyze=false)
Definition: ZDCPulseAnalyzer.cxx:297
ZDCPulseAnalyzer::m_minADCSampleHG
int m_minADCSampleHG
Definition: ZDCPulseAnalyzer.h:274
ZDCPulseAnalyzer::LGModeNormal
@ LGModeNormal
Definition: ZDCPulseAnalyzer.h:56
ZDCPulseAnalyzer::m_fitAmpError
float m_fitAmpError
Definition: ZDCPulseAnalyzer.h:307
ZDCPulseAnalyzer::m_fitTimeCorr
float m_fitTimeCorr
Definition: ZDCPulseAnalyzer.h:310
ZDCPulseAnalyzer::m_samplesSigLGRefit
std::vector< float > m_samplesSigLGRefit
Definition: ZDCPulseAnalyzer.h:360
ZDCPulseAnalyzer::m_peak2ndDerivMinThreshHG
float m_peak2ndDerivMinThreshHG
Definition: ZDCPulseAnalyzer.h:106
ZDCPulseAnalyzer::m_timeSig
float m_timeSig
Definition: ZDCPulseAnalyzer.h:311
ZDCPulseAnalyzer::dump
void dump() const
Definition: ZDCPulseAnalyzer.cxx:2084
ZDCPulseAnalyzer::prePulse
bool prePulse() const
Definition: ZDCPulseAnalyzer.h:596
ZDCPulseAnalyzer::m_T0CutLowLG
float m_T0CutLowLG
Definition: ZDCPulseAnalyzer.h:146
ZDCPulseAnalyzer::setMinimumSignificance
void setMinimumSignificance(float sigMinHG, float sigMinLG)
Definition: ZDCPulseAnalyzer.cxx:438
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
ZDCPulseAnalyzer::m_defaultT0Min
float m_defaultT0Min
Definition: ZDCPulseAnalyzer.h:158
ZDCPulseAnalyzer::FitFailedBit
@ FitFailedBit
Definition: ZDCPulseAnalyzer.h:40
xmax
double xmax
Definition: listroot.cxx:61
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
ZDCPulseAnalyzer::m_maxSamplesPostExcl
unsigned int m_maxSamplesPostExcl
Definition: ZDCPulseAnalyzer.h:180
ZDCPulseAnalyzer::m_amplitude
float m_amplitude
Definition: ZDCPulseAnalyzer.h:322
ZDCPulseAnalyzer::m_initializedFits
bool m_initializedFits
Definition: ZDCPulseAnalyzer.h:206
ZDCPulseAnalyzer::excludeEarlyLG
bool excludeEarlyLG() const
Definition: ZDCPulseAnalyzer.h:602
ZDCPulseAnalyzer::m_defaultFitTMin
float m_defaultFitTMin
Definition: ZDCPulseAnalyzer.h:141
ZDCPulseAnalyzer::m_fitTMin
float m_fitTMin
Definition: ZDCPulseAnalyzer.h:293
ZDCPulseAnalyzer::dumpTF1
void dumpTF1(const TF1 *) const
Definition: ZDCPulseAnalyzer.cxx:2112
ZDCPulseAnalyzer::m_minDeriv2ndIndex
int m_minDeriv2ndIndex
Definition: ZDCPulseAnalyzer.h:290
ZDCPulseAnalyzer::m_LGUnderflow
bool m_LGUnderflow
Definition: ZDCPulseAnalyzer.h:245
ZDCPulseAnalyzer::m_LGOverflowADC
int m_LGOverflowADC
Definition: ZDCPulseAnalyzer.h:129
LArCellBinning.step
step
Definition: LArCellBinning.py:158
ZDCPulseAnalyzer::m_ADCSamplesLGSub
std::vector< float > m_ADCSamplesLGSub
Definition: ZDCPulseAnalyzer.h:348
ZDCPulseAnalyzer::LGModeRefitLG
@ LGModeRefitLG
Definition: ZDCPulseAnalyzer.h:58
ZDCPulseAnalyzer::m_T0CutHighHG
float m_T0CutHighHG
Definition: ZDCPulseAnalyzer.h:150
ZDCPulseAnalyzer::m_firstHGOverFlowSample
int m_firstHGOverFlowSample
Definition: ZDCPulseAnalyzer.h:342
ZDCPulseAnalyzer::GetFitPulls
std::vector< float > GetFitPulls(bool forceLG=false) const
Definition: ZDCPulseAnalyzer.cxx:574
ZDCPulseAnalyzer::s_undelayedFitHist
static TH1 * s_undelayedFitHist
Definition: ZDCPulseAnalyzer.h:80
ZDCMsg::Debug
@ Debug
Definition: ZDCMsg.h:19
ZDCPulseAnalyzer::m_fitAmpMinHG
float m_fitAmpMinHG
Definition: ZDCPulseAnalyzer.h:160
ZDCPulseAnalyzer::FitMinAmpBit
@ FitMinAmpBit
Definition: ZDCPulseAnalyzer.h:48
ZDCMsg::Fatal
@ Fatal
Definition: ZDCMsg.h:23
ZDCPulseAnalyzer::m_FADCCorrPerSample
bool m_FADCCorrPerSample
Definition: ZDCPulseAnalyzer.h:197
ZDCPulseAnalyzer::fitMinimumAmplitude
bool fitMinimumAmplitude() const
Definition: ZDCPulseAnalyzer.h:605
ZDCPulseAnalyzer::m_timingCorrMode
unsigned int m_timingCorrMode
Definition: ZDCPulseAnalyzer.h:183
ZDCPulseAnalyzer::m_maxSamplesPreExcl
unsigned int m_maxSamplesPreExcl
Definition: ZDCPulseAnalyzer.h:173
ZDCPulseAnalyzer::enableFADCCorrections
void enableFADCCorrections(bool correctPerSample, std::unique_ptr< const TH1 > &correHistHG, std::unique_ptr< const TH1 > &correHistLG)
Definition: ZDCPulseAnalyzer.cxx:540
LArDigits2NtupleDumper.nSamples
nSamples
Definition: LArDigits2NtupleDumper.py:85
merge.status
status
Definition: merge.py:16
ZDCPulseAnalyzer::m_FADCCorrLG
std::unique_ptr< const TH1 > m_FADCCorrLG
Definition: ZDCPulseAnalyzer.h:199
CaloCondBlobAlgs_fillNoiseFromASCII.tag
string tag
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:23
ZDCPulseAnalyzer::m_initialPostPulseT0
float m_initialPostPulseT0
Definition: ZDCPulseAnalyzer.h:304
ZDCPulseAnalyzer::enableDelayed
void enableDelayed(float deltaT, float pedestalShift, bool fixedBaseline=false)
Definition: ZDCPulseAnalyzer.cxx:204
ZDCPulseAnalyzer::m_fitExpAmp
float m_fitExpAmp
Definition: ZDCPulseAnalyzer.h:321
ZDCPulseAnalyzer::m_prePulseCombinedFitter
std::unique_ptr< TFitter > m_prePulseCombinedFitter
Definition: ZDCPulseAnalyzer.h:226
ZDCPulseAnalyzer::m_fitHist
std::unique_ptr< TH1 > m_fitHist
Definition: ZDCPulseAnalyzer.h:203
ZDCPulseAnalyzer::m_timeResFuncHG_p
std::unique_ptr< const TF1 > m_timeResFuncHG_p
Definition: ZDCPulseAnalyzer.h:152
ZDCPulseAnalyzer::m_preSampleAmp
float m_preSampleAmp
Definition: ZDCPulseAnalyzer.h:325
ZDCPulseAnalyzer::m_nonLinCorrParamsHG
std::vector< float > m_nonLinCorrParamsHG
Definition: ZDCPulseAnalyzer.h:192
ZDCPulseAnalyzer::getAmplitudeCorrection
double getAmplitudeCorrection(bool highGain)
Definition: ZDCPulseAnalyzer.cxx:611
ZDCPulseAnalyzer::m_nominalTau1
float m_nominalTau1
Definition: ZDCPulseAnalyzer.h:134
ZDCPulseAnalyzer::m_fitTCorr2nd
float m_fitTCorr2nd
Definition: ZDCPulseAnalyzer.h:312
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
ZDCPulseAnalyzer::s_combinedFitTMax
static float s_combinedFitTMax
Definition: ZDCPulseAnalyzer.h:83
ZDCPulseAnalyzer::m_postExclLGADCThresh
unsigned int m_postExclLGADCThresh
Definition: ZDCPulseAnalyzer.h:179
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
ZDCPulseAnalyzer::m_refitLGAmpError
float m_refitLGAmpError
Definition: ZDCPulseAnalyzer.h:336
ZDCPulseAnalyzer::m_samplesSig
std::vector< float > m_samplesSig
Definition: ZDCPulseAnalyzer.h:357
ZDCPulseAnalyzer::m_initialPrePulseT0
float m_initialPrePulseT0
Definition: ZDCPulseAnalyzer.h:301
ZDCPulseAnalyzer::postPulse
bool postPulse() const
Definition: ZDCPulseAnalyzer.h:597
ZDCPulseAnalyzer::m_refitLGTimeSub
float m_refitLGTimeSub
Definition: ZDCPulseAnalyzer.h:339
ZDCPulseAnalyzer::m_fadcCorrFileName
std::string m_fadcCorrFileName
Definition: ZDCPulseAnalyzer.h:196
ZDCFitExpFermiLHCfPrePulse
Definition: ZDCFitWrapper.h:465
ZDCPulseAnalyzer::havePulse
bool havePulse() const
Definition: ZDCPulseAnalyzer.h:586
ZDCPulseAnalyzer::m_HGT0CorrParams
std::vector< float > m_HGT0CorrParams
Definition: ZDCPulseAnalyzer.h:187
ZDCPulseAnalyzer::s_pullValues
static std::vector< float > s_pullValues
Definition: ZDCPulseAnalyzer.h:85
ZDCFitExpFermiPreExp
Definition: ZDCFitWrapper.h:581
ZDCPulseAnalyzer::FailBit
@ FailBit
Definition: ZDCPulseAnalyzer.h:30
ZDCFitExpFermiLinearFixedTaus
Definition: ZDCFitWrapper.h:785
ZDCPulseAnalyzer::m_tmax
float m_tmax
Definition: ZDCPulseAnalyzer.h:99
ZDCPulseAnalyzer::m_haveSignifCuts
bool m_haveSignifCuts
Definition: ZDCPulseAnalyzer.h:166
ZDCFitGeneralPulse
Definition: ZDCFitWrapper.h:1078
ZDCPulseAnalyzer::m_refitLGTime
float m_refitLGTime
Definition: ZDCPulseAnalyzer.h:338
ZDCPulseAnalyzer::m_Nsample
unsigned int m_Nsample
Definition: ZDCPulseAnalyzer.h:91
ZDCPulseAnalyzer::CalculateDerivative
static std::vector< float > CalculateDerivative(const std::vector< float > &inputData, unsigned int step)
Definition: ZDCPulseAnalyzer.cxx:2290
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
ZDCPulseAnalyzer::LGUnderflowBit
@ LGUnderflowBit
Definition: ZDCPulseAnalyzer.h:36