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