7 #include "TFitResult.h"
8 #include "TFitResultPtr.h"
9 #include "TVirtualFitter.h"
43 float delayBaselineAdjust =
par[0];
47 for (
int isample = 0; isample <
nSamples; isample++) {
57 double pull = (histValue - funcVal) / histError;
65 for (
int isample = 0; isample <
nSamples; isample++) {
74 double pull = (histValue - funcVal) / histError;
85 float gainHG,
const std::string& fitFunction,
int peak2ndDerivMinSample,
86 float peak2ndDerivMinThreshHG,
float peak2ndDerivMinThreshLG) :
87 m_msgFunc_p(std::move(msgFunc_p)),
88 m_tag(
tag), m_Nsample(Nsample),
89 m_preSampleIdx(preSampleIdx),
90 m_deltaTSample(deltaTSample),
91 m_pedestal(pedestal), m_gainHG(gainHG), m_fitFunction(fitFunction),
92 m_peak2ndDerivMinSample(peak2ndDerivMinSample),
93 m_peak2ndDerivMinThreshLG(peak2ndDerivMinThreshLG),
94 m_peak2ndDerivMinThreshHG(peak2ndDerivMinThreshHG),
95 m_ADCSamplesHGSub(Nsample, 0), m_ADCSamplesLGSub(Nsample, 0),
96 m_ADCSSampSigHG(Nsample, 0), m_ADCSSampSigLG(Nsample, 0),
97 m_samplesSub(Nsample, 0)
101 m_tmin = -deltaTSample / 2;
105 std::string histNameLGRefit =
"ZDCFitHist" +
tag +
"_LGRefit";
128 std::string delayedHGName = std::string(
m_fitHist->GetName()) +
"delayed";
129 std::string delayedLGName = std::string(
m_fitHistLGRefit->GetName()) +
"delayed";
377 std::ostringstream ostrm;
407 float deltaT0MinHG,
float deltaT0MaxHG,
408 float deltaT0MinLG,
float deltaT0MaxLG)
421 const std::vector<double>& parsHG,
422 const std::vector<double>& parsLG)
429 std::string timeResHGName =
"TimeResFuncHG_" +
m_tag;
430 std::string timeResLGName =
"TimeResFuncLG_" +
m_tag;
432 TF1* funcHG_p =
new TF1(timeResHGName.c_str(), TF1String.c_str(), 0,
m_HGOverflowADC);
433 TF1* funcLG_p =
new TF1(timeResLGName.c_str(), TF1String.c_str(), 0,
m_LGOverflowADC);
435 if (parsHG.size() !=
static_cast<unsigned int>(funcHG_p->GetNpar()) ||
436 parsLG.size() !=
static_cast<unsigned int>(funcLG_p->GetNpar())) {
441 funcHG_p->SetParameters(&parsHG[0]);
442 funcLG_p->SetParameters(&parsLG[0]);
456 auto getXmin=[](
const TH1 * pH){
457 return pH->GetXaxis()->GetXmin();
459 auto getXmax=[](
const TH1 * pH){
460 return pH->GetXaxis()->GetXmax();
462 auto xmin= getXmin(correHistHG.get());
463 auto xmax= getXmax(correHistHG.get());
464 if (std::abs(
xmin+0.5) > 1
e-3 || std::abs(
xmax - 4095.5) > 1
e-3) {
465 (*m_msgFunc_p)(
ZDCMsg::Error,
"ZDCPulseAnalyzer::enableFADCCorrections:: invalid high gain correction histogram range: xmin, xmax = " +
471 xmin= getXmin(correHistLG.get());
472 xmax= getXmax(correHistLG.get());
473 if (std::abs(
xmin+0.5) > 1
e-3 ||
474 std::abs(
xmax - 4095.5) > 1
e-3) {
475 (*m_msgFunc_p)(
ZDCMsg::Error,
"ZDCPulseAnalyzer::enableFADCCorrections:: invalid low gain correction histogram range: xmin, xmax = " +
502 std::vector<float> pulls(
m_Nsample, -100);
505 const TF1* fit_p =
static_cast<const TF1*
>(dataHist_p->GetListOfFunctions()->Last());
507 for (
size_t ibin = 0; ibin <
m_Nsample ; ibin++) {
508 float t = dataHist_p->GetBinCenter(ibin + 1);
509 float fitVal = fit_p->Eval(
t);
510 float histVal = dataHist_p->GetBinContent(ibin + 1);
511 float histErr = dataHist_p->GetBinError(ibin + 1);
512 float pull = (histVal - fitVal)/histErr;
522 double amplCorrFactor = 1;
528 amplCorrFactor *= fadcCorr;
540 float invNLCorr = 1.0;
554 amplCorrFactor /= invNLCorr;
557 return amplCorrFactor;
562 float prePulseTMin = 0;
656 (*m_msgFunc_p)(
ZDCMsg::Fatal,
"ZDCPulseAnalyzer::LoadAndAnalyzeData:: Wrong LoadAndAnalyzeData called -- expecting both delayed and undelayed samples");
679 const std::vector<float>& ADCSamplesHGDelayed,
const std::vector<float>& ADCSamplesLGDelayed)
682 (*m_msgFunc_p)(
ZDCMsg::Fatal,
"ZDCPulseAnalyzer::LoadAndAnalyzeData:: Wrong LoadAndAnalyzeData called -- expecting only undelayed samples");
704 for (
size_t isample = 0; isample <
m_Nsample; isample++) {
705 float ADCHG = ADCSamplesHG[isample];
706 float ADCLG = ADCSamplesLG[isample];
747 bool doDump = (*m_msgFunc_p)(
ZDCMsg::Verbose,
"Dumping all samples before subtraction: ");
749 std::ostringstream dumpStringHG;
750 dumpStringHG <<
"HG: ";
752 dumpStringHG << std::setw(4) <<
val <<
" ";
760 std::ostringstream dumpStringLG;
761 dumpStringLG <<
"LG: " << std::setw(4) << std::setfill(
' ');
763 dumpStringLG << std::setw(4) <<
val <<
" ";
785 for (
size_t isample = 0; isample <
m_NSamplesAna; isample++) {
885 std::ostringstream dumpStringUseHG;
886 dumpStringUseHG <<
"HG: ";
888 dumpStringUseHG <<
val <<
" ";
892 std::ostringstream dumpStringUseLG;
893 dumpStringUseLG <<
"LG: ";
895 dumpStringUseLG <<
val <<
" ";
907 if (m_lastHGOverFlowSample < 2 && m_lastHGOverFlowSample > -1) {
922 (*m_msgFunc_p)(
ZDCMsg::Verbose,
"ZDCPulseAnalyzer:: " +
m_tag +
": ScanAndSubtractSamples done");
929 float deriv2ndThreshHG = 0;
930 float deriv2ndThreshLG = 0;
1034 const std::vector<float>& samples,
1035 const std::vector<bool>& useSample,
1036 float peak2ndDerivMinThresh,
1038 const std::vector<float>& t0CorrParams,
1039 float maxChisqDivAmp,
1040 float minT0Corr,
float maxT0Corr
1053 bool haveFirst =
false;
1054 unsigned int lastUsed = 0;
1092 std::ostringstream pedMessage;
1114 std::ostringstream baselineMsg;
1115 baselineMsg <<
"Delayed samples baseline correction = " <<
m_baselineCorr << std::endl;
1121 for (
size_t isample = 0; isample <
nSamples; isample++) {
1132 std::for_each(
m_samplesSub.begin(),
m_samplesSub.end(), [ = ] (
float & adcUnsub) {return adcUnsub -= m_preSample;} );
1207 if (derivPresampleSig < -5) {
1213 if (!useSample[isample])
continue;
1215 float sampleSig = -
m_samplesSub[isample]/(std::sqrt(2.0)*noiseSig);
1218 if ((sampleSig > 5 && sigRatio > 0.02) || sigRatio > 0.5) {
1229 float maxPrepulseSig = 0;
1230 unsigned int maxPrepulseSample = 0;
1232 for (
int isample = loopStart; isample <= loopLimit; isample++) {
1233 if (!useSample[isample])
continue;
1249 if (prePulseSig > maxPrepulseSig) {
1250 maxPrepulseSig = prePulseSig;
1251 maxPrepulseSample = isample;
1286 for (
int isample = postStartIdx; isample < (
int)
nSamples - 1; isample++) {
1287 if (!useSample.at(isample))
continue;
1318 float derivSig = deriv/(std::sqrt(2)*noiseSig);
1327 if (std::abs(deriv2ndTest) > 0.15) {
1340 if (deriv2ndSig > 5 && deriv2ndTest < -0.1) {
1351 std::ostringstream ostrm;
1352 ostrm <<
"Post pulse found, m_maxSampleEvt = " <<
m_maxSampleEvt;
1370 std::ostringstream ostrm;
1371 ostrm <<
"Pulse fit successful with chisquare = " <<
m_fitChisq;
1389 for (
unsigned int ipow = 0; ipow < t0CorrParams.size(); ipow++) {
1398 bool failFixedCut = m_fitTimeCorr < minT0Corr || m_fitTimeCorr > maxT0Corr;
1408 double timeResolution = 0;
1420 if (failFixedCut)
m_badT0 =
true;
1440 const std::vector<bool>& useSamples)
1449 for (
unsigned int idx = 0;
idx < samplesLG.size();
idx++) {
1452 if (useSamples[
idx]) {
1466 TH1* hist_p =
nullptr;
1471 float ampInitial, fitAmpMin, fitAmpMax, t0Initial;
1492 if (ampInitial < fitAmpMin) ampInitial = fitAmpMin * 1.5;
1514 fitWrapper->
Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax);
1532 int fitStatus = result_ptr;
1538 if (fitStatus != 0 && result_ptr->Edm() > 0.001)
1548 if ((
int) constrFitResult_ptr != 0) {
1558 if ((
int) unconstrFitResult_ptr != 0) {
1565 if ((
int) constrFit2Result_ptr != 0) {
1572 result_ptr = constrFit2Result_ptr;
1576 result_ptr = unconstrFitResult_ptr;
1582 hist_p->GetListOfFunctions()->Clear();
1585 std::string
name = func->GetName();
1587 TF1* copyFunc =
static_cast<TF1*
>(func->Clone((
name +
"_copy").c_str()));
1588 hist_p->GetListOfFunctions()->Add(copyFunc);
1633 TH1* hist_p =
nullptr, *delayedHist_p =
nullptr;
1645 float fitAmpMin, fitAmpMax, t0Initial, ampInitial;
1661 if (ampInitial < fitAmpMin) ampInitial = fitAmpMin * 1.5;
1687 fitWrapper->
Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax);
1692 TFitter* theFitter =
nullptr;
1716 size_t numFitPar = theFitter->GetNumberTotalParameters();
1718 theFitter->GetMinuit()->fISW[4] = -1;
1723 theFitter->GetMinuit()->fISW[4] = -1;
1726 theFitter->GetMinuit()->mnexcm(
"SET NOWarnings",
nullptr,0,ierr);
1728 else theFitter->GetMinuit()->fISW[4] = 0;
1733 theFitter->SetParameter(0,
"delayBaselineAdjust", 0, 0.01, -100, 100);
1734 theFitter->ReleaseParameter(0);
1737 theFitter->SetParameter(0,
"delayBaselineAdjust", 0, 0.01, -100, 100);
1738 theFitter->FixParameter(0);
1742 double arglist[100];
1745 int status = theFitter->ExecuteCommand(
"MIGRAD", arglist, 2);
1747 double fitAmp = theFitter->GetParameter(1);
1751 double chi2, edm, errdef;
1754 theFitter->GetStats(
chi2, edm, errdef, nvpar, nparx);
1759 if (
status || fitAmp < fitAmpMin * 1.01 || edm > 0.01){
1764 theFitter->SetParameter(0,
"delayBaselineAdjust", 0, 0.01, -100, 100);
1765 theFitter->FixParameter(0);
1769 if (fitAmp < fitAmpMin * 1.01) {
1775 fitWrapper->
Initialize(ampInitial, t0Initial, fitAmpMin, fitAmpMax);
1779 status = theFitter->ExecuteCommand(
"MIGRAD", arglist, 2);
1784 theFitter->ReleaseParameter(0);
1792 theFitter->ReleaseParameter(0);
1793 status = theFitter->ExecuteCommand(
"MIGRAD", arglist, 2);
1798 theFitter->SetParameter(0,
"delayBaselineAdjust", 0, 0.01, -100, 100);
1799 theFitter->FixParameter(0);
1800 status = theFitter->ExecuteCommand(
"MIGRAD", arglist, 2);
1808 fitAmp = theFitter->GetParameter(1);
1812 if (fitAmp < fitAmpMin * 1.01) {
1816 if (!
s_quietFits) theFitter->GetMinuit()->fISW[4] = -1;
1818 std::vector<double> funcParams(numFitPar - 1);
1819 std::vector<double> funcParamErrs(numFitPar - 1);
1827 for (
size_t ipar = 1; ipar < numFitPar; ipar++) {
1828 funcParams[ipar - 1] = theFitter->GetParameter(ipar);
1829 funcParamErrs[ipar - 1] = theFitter->GetParError(ipar);
1837 theFitter->GetStats(
chi2, edm, errdef, nvpar, nparx);
1857 theFitter->ExecuteCommand(
"Cal1fcn", arglist, 1);
1900 TVirtualFitter::SetDefaultFitter(
"Minuit");
1902 size_t nFitParams = func->GetNpar() + 1;
1903 std::unique_ptr<TFitter>
fitter = std::make_unique<TFitter>(nFitParams);
1905 fitter->GetMinuit()->fISW[4] = -1;
1906 fitter->SetParameter(0,
"delayBaselineAdjust", 0, 0.01, -100, 100);
1908 for (
size_t ipar = 0; ipar < nFitParams - 1; ipar++) {
1909 double parLimitLow, parLimitHigh;
1911 func->GetParLimits(ipar, parLimitLow, parLimitHigh);
1912 if (std::abs(parLimitHigh / parLimitLow - 1) < 1
e-6) {
1913 double value = func->GetParameter(ipar);
1917 fitter->SetParameter(ipar + 1, func->GetParName(ipar), func->GetParameter(ipar), 0.01, lowLim, highLim);
1918 fitter->FixParameter(ipar + 1);
1921 double value = func->GetParameter(ipar);
1922 if (
value >= parLimitHigh)
value = parLimitHigh * 0.99;
1923 else if (
value <= parLimitLow)
value = parLimitLow * 1.01;
1925 double step =
std::min((parLimitHigh - parLimitLow)/100., (
value - parLimitLow)/100.);
1927 fitter->SetParameter(ipar + 1, func->GetParName(ipar),
value,
step, parLimitLow, parLimitHigh);
1938 double parLimitLow, parLimitHigh;
1941 func_p->GetParLimits(1, parLimitLow, parLimitHigh);
1943 fitter->SetParameter(2, func_p->GetParName(1), func_p->GetParameter(1), 0.01, parLimitLow, parLimitHigh);
1948 func_p->GetParLimits(parIndex, parLimitLow, parLimitHigh);
1949 fitter->SetParameter(parIndex + 1, func_p->GetParName(parIndex), func_p->GetParameter(parIndex), 0.01, parLimitLow, parLimitHigh);
1964 std::ostringstream message1;
1965 message1 <<
"samplesSub ";
1971 std::ostringstream message3;
1972 message3 <<
"samplesDeriv2nd ";
1983 std::string
message =
"Dump of TF1: " + std::string(func->GetName());
1985 if (!continueDump)
return;
1987 unsigned int npar = func->GetNpar();
1988 for (
unsigned int ipar = 0; ipar < npar; ipar++) {
1989 std::ostringstream msgstr;
1991 double parMin = 0, parMax = 0;
1992 func->GetParLimits(ipar, parMin, parMax);
1994 msgstr <<
"Parameter " << ipar <<
", value = " << func->GetParameter(ipar) <<
", error = "
1995 << func->GetParError(ipar) <<
", min = " << parMin <<
", max = " << parMax;
2019 unsigned int statusMask = 0;
2053 TH1* hist_p =
nullptr, *delayedHist_p =
nullptr;
2063 std::shared_ptr<TGraphErrors> theGraph = std::make_shared<TGraphErrors>(TGraphErrors(2 *
m_Nsample));
2066 for (
int ipt = 0; ipt < hist_p->GetNbinsX(); ipt++) {
2067 theGraph->SetPoint(npts, hist_p->GetBinCenter(ipt + 1), hist_p->GetBinContent(ipt + 1));
2068 theGraph->SetPointError(npts++, 0, hist_p->GetBinError(ipt + 1));
2071 for (
int iDelayPt = 0; iDelayPt < delayedHist_p->GetNbinsX(); iDelayPt++) {
2072 theGraph->SetPoint(npts, delayedHist_p->GetBinCenter(iDelayPt + 1), delayedHist_p->GetBinContent(iDelayPt + 1) -
m_delayedBaselineShift);
2073 theGraph->SetPointError(npts++, 0, delayedHist_p->GetBinError(iDelayPt + 1));
2076 TF1* func_p =
static_cast<TF1*
>(hist_p->GetListOfFunctions()->Last());
2078 theGraph->GetListOfFunctions()->Add(
new TF1(*func_p));
2079 hist_p->GetListOfFunctions()->SetOwner (
false);
2082 theGraph->SetName(( std::string(hist_p->GetName()) +
"combinaed").c_str());
2084 theGraph->SetMarkerStyle(20);
2085 theGraph->SetMarkerColor(1);
2098 std::shared_ptr<TGraphErrors> theGraph = std::make_shared<TGraphErrors>(TGraphErrors(
m_Nsample));
2101 for (
int ipt = 0; ipt < hist_p->GetNbinsX(); ipt++) {
2102 theGraph->SetPoint(npts, hist_p->GetBinCenter(ipt + 1), hist_p->GetBinContent(ipt + 1));
2103 theGraph->SetPointError(npts++, 0, hist_p->GetBinError(ipt + 1));
2106 TF1* func_p =
static_cast<TF1*
>(hist_p->GetListOfFunctions()->Last());
2107 theGraph->GetListOfFunctions()->Add(func_p);
2108 theGraph->SetName(( std::string(hist_p->GetName()) +
"not_combinaed").c_str());
2110 theGraph->SetMarkerStyle(20);
2111 theGraph->SetMarkerColor(1);
2119 unsigned int nSamples = inputData.size();
2124 std::vector<float>
results(vecSize, 0);
2128 unsigned int fillIdx =
step - 1;
2132 results.at(fillIdx++) = deriv;
2140 unsigned int nSamples = inputData.size();
2146 std::vector<float>
results(vecSize, 0);
2148 unsigned int fillIndex =
step;
2151 results.at(fillIndex++) = deriv2nd;
2172 const unsigned int nsamples = samples.size();
2180 float minScore = 1.0e9;
2181 unsigned int minIndex = 0;
2184 float deriv = derivVec[
idx];
2185 float prevDeriv = derivVec[
idx - 1];
2187 float derivDiff = deriv - prevDeriv;
2189 float deriv2nd = deriv2ndVec[
idx];
2195 float score = (deriv*deriv + 2*derivDiff*derivDiff +
2196 0.5*deriv2nd*deriv2nd);
2198 if (
score < minScore) {
2209 if (minIndex<2 or (minIndex+1) >=
nsamples){
2210 throw std::out_of_range(
"minIndex out of range in ZDCPulseAnalyzer::obtainDelayedBaselineCorr");
2212 float sample0 = samples[minIndex - 2];
2213 float sample1 = samples[minIndex - 1];
2214 float sample2 = samples[minIndex];
2215 float sample3 = samples[minIndex + 1];
2219 float baselineCorr = (0.5 * (sample1 - sample0 + sample3 - sample2) -
2220 0.25 * (sample3 - sample1 + sample2 - sample0));
2222 if (minIndex % 2 != 0) baselineCorr =-baselineCorr;
2224 return baselineCorr;