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