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