44 #include "art/Framework/Core/ModuleMacros.h"
45 #include "art/Framework/Core/EDProducer.h"
46 #include "art/Framework/Services/Registry/ServiceHandle.h"
47 #include "canvas/Persistency/Common/FindOneP.h"
48 #include "canvas/Utilities/InputTag.h"
49 #include "art/Framework/Principal/Event.h"
50 #include "art_root_io/TFileService.h"
51 #include "art/Framework/Services/System/TriggerNamesService.h"
52 #include "fhiclcpp/ParameterSet.h"
53 #include "messagefacility/MessageLogger/MessageLogger.h"
84 using PeakDevVec = std::vector<std::tuple<double,int,int,int>>;
88 std::vector<float>::const_iterator stopItr,
123 void AddPeak(std::tuple<double,int,int,int> fPeakDevCand,
126 void SplitPeak(std::tuple<double,int,int,int> fPeakDevCand,
135 double fPeakMeanTrue);
141 double fChargeNormFactor,
142 double fPeakMeanTrue);
145 std::vector<double>&
output);
148 std::vector<float>& outputVec,
149 size_t binsToAverage)
const;
151 void reBin(
const std::vector<float>& inputVec,
152 std::vector<float>& outputVec,
153 size_t nBinsToCombine)
const;
161 {
return std::get<0>(
p) < s; }
163 {
return s < std::get<0>(
p); }
215 pset.get<std::string>(
"module_label"),
"",
216 art::ServiceHandle<art::TriggerNamesService const>()->getProcessName()),
217 fHitParamWriter(producesCollector())
219 fLogLevel = pset.get<
int >(
"LogLevel");
220 fCalDataModuleLabel = pset.get< std::string >(
"CalDataModuleLabel");
222 fMaxGroupLength = pset.get<
int >(
"MaxGroupLength");
223 fTryNplus1Fits = pset.get<
bool >(
"TryNplus1Fits");
224 fChi2NDFRetry = pset.get<
double >(
"Chi2NDFRetry");
225 fChi2NDFRetryFactorMultiHits = pset.get<
double >(
"Chi2NDFRetryFactorMultiHits");
226 fChi2NDFMax = pset.get<
double >(
"Chi2NDFMax");
227 fChi2NDFMaxFactorMultiHits = pset.get<
double >(
"Chi2NDFMaxFactorMultiHits");
228 fNumBinsToAverage = pset.get<
size_t >(
"NumBinsToAverage");
229 fMinSig = pset.get<
float >(
"MinSig");
230 fMinWidth = pset.get<
int >(
"MinWidth");
231 fMinADCSum = pset.get<
double >(
"MinADCSum");
232 fMinADCSumOverWidth = pset.get<
double >(
"MinADCSumOverWidth");
233 fChargeNorm = pset.get<
double >(
"ChargeNorm");
234 fTicksToStopPeakFinder = pset.get<
double >(
"TicksToStopPeakFinder");
235 fMinTau = pset.get<
double >(
"MinTau");
236 fMaxTau = pset.get<
double >(
"MaxTau");
237 fFitPeakMeanRange = pset.get<
double >(
"FitPeakMeanRange");
238 fGroupMaxDistance = pset.get<
int >(
"GroupMaxDistance");
239 fGroupMinADC = pset.get<
int >(
"GroupMinADC");
240 fSameShape = pset.get<
bool >(
"SameShape");
241 fDoMergePeaks = pset.get<
bool >(
"DoMergePeaks");
242 fMergeADCSumThreshold = pset.get<
double >(
"MergeADCSumThreshold");
243 fMergeMaxADCThreshold = pset.get<
double >(
"MergeMaxADCThreshold");
244 fMinRelativePeakHeightLeft = pset.get<
double >(
"MinRelativePeakHeightLeft");
245 fMinRelativePeakHeightRight = pset.get<
double >(
"MinRelativePeakHeightRight");
246 fMergeMaxADCLimit = pset.get<
double >(
"MergeMaxADCLimit");
247 fWidthNormalization = pset.get<
double >(
"WidthNormalization");
248 fLongMaxHits = pset.get<
double >(
"LongMaxHits");
249 fLongPulseWidth = pset.get<
double >(
"LongPulseWidth");
250 fMaxFluctuations = pset.get<
double >(
"MaxFluctuations");
259 fHitParamWriter.produces_using<
recob::Hit >();
267 std::vector<double>&
output)
270 throw std::runtime_error(
"DPRawHitFinder::FillOutHitParameterVector ERROR! Input config vector has zero size.");
272 art::ServiceHandle<geo::Geometry const> geom;
273 const unsigned int N_PLANES = geom->Nplanes();
276 output.resize(N_PLANES,input[0]);
277 else if(input.size()==N_PLANES)
280 throw std::runtime_error(
"DPRawHitFinder::FillOutHitParameterVector ERROR! Input config vector size !=1 and !=N_PLANES.");
290 art::ServiceHandle<art::TFileService const>
tfs;
294 fFirstChi2 = tfs->make<TH1F>(
"fFirstChi2",
"#chi^{2}", 10000, 0, 5000);
295 fChi2 = tfs->make<TH1F>(
"fChi2",
"#chi^{2}", 10000, 0, 5000);
302 TH1::AddDirectory(kFALSE);
311 art::ServiceHandle<geo::Geometry const> geom;
326 art::Handle< std::vector<recob::Wire> > wireVecHandle;
327 evt.getByLabel(fCalDataModuleLabel,wireVecHandle);
332 art::FindOneP<raw::RawDigit> RawDigits(wireVecHandle, evt, fCalDataModuleLabel);
339 for(
size_t wireIter = 0; wireIter < wireVecHandle->size(); wireIter++)
344 art::Ptr<recob::Wire> wire(wireVecHandle, wireIter);
345 art::Ptr<raw::RawDigit> rawdigits = RawDigits.at(wireIter);
347 channel = wire->Channel();
349 std::vector<geo::WireID> wids = geom->ChannelToWire(channel);
358 std::cout <<
"-----------------------------------------------------------------------------------------------------------" << std::endl;
359 std::cout <<
"Channel: " << channel << std::endl;
373 for(
const auto& range : signalROI.
get_ranges())
378 const std::vector<float>& signal = range.data();
388 if (fNumBinsToAverage > 1)
390 std::vector<float> timeAve;
402 if (timeValsVec.empty())
continue;
425 std::cout <<
"-------------------- ROI #" << CountROI <<
" -------------------- " << std::endl;
426 if(timeValsVec.size() == 1)
std::cout <<
"ROI #" << CountROI <<
" (" << timeValsVec.size() <<
" peak): ROIStartTick: " << range.offset <<
" ROIEndTick:" << range.offset+range.size() << std::endl;
427 else std::cout <<
"ROI #" << CountROI <<
" (" << timeValsVec.size() <<
" peaks): ROIStartTick: " << range.offset <<
" ROIEndTick:" << range.offset+range.size() << std::endl;
434 for(
auto const& timeValsTmp : timeValsVec )
436 std::cout <<
"Peak #" << CountPeak <<
": PeakStartTick: " << range.offset + std::get<0>(timeValsTmp) <<
" PeakMaxTick: " << range.offset + std::get<1>(timeValsTmp) <<
" PeakEndTick: " << range.offset + std::get<2>(timeValsTmp) << std::endl;
443 if (timeValsVec.empty())
continue;
458 int NumberOfPeaksBeforeFit=0;
459 unsigned int nExponentialsForFit=0;
460 double chi2PerNDF=0.;
463 unsigned int NumberOfMergedVecs = mergedVec.size();
469 for(
unsigned int j=0; j < NumberOfMergedVecs; j++)
471 int startT = std::get<0>(mergedVec.at(j));
472 int endT = std::get<1>(mergedVec.at(j));
473 int width = endT + 1 - startT;
476 int NFluctuations = std::get<3>(mergedVec.at(j));
481 if(peakVals.size() == 1)
std::cout <<
"- Group #" << j <<
" (" << peakVals.size() <<
" peak): GroupStartTick: " << range.offset + startT <<
" GroupEndTick: " << range.offset + endT << std::endl;
482 else std::cout <<
"- Group #" << j <<
" (" << peakVals.size() <<
" peaks): GroupStartTick: " << range.offset + startT <<
" GroupEndTick: " << range.offset + endT << std::endl;
483 std::cout <<
"Fluctuations in this group: " << NFluctuations << std::endl;
484 int CountPeakInGroup=0;
485 for(
auto const& peakValsTmp : peakVals )
487 std::cout <<
"Peak #" << CountPeakInGroup <<
" in group #" << j <<
": PeakInGroupStartTick: " << range.offset + std::get<2>(peakValsTmp) <<
" PeakInGroupMaxTick: " << range.offset + std::get<0>(peakValsTmp) <<
" PeakInGroupEndTick: " << range.offset + std::get<3>(peakValsTmp) << std::endl;
493 if (width < fMinWidth || (
double)std::accumulate(signal.begin()+startT, signal.begin()+endT+1, 0) < fMinADCSum || (
double)std::accumulate(signal.begin()+startT, signal.begin()+endT+1, 0)/width < fMinADCSumOverWidth)
497 std::cout <<
"Delete this group of peaks because width, integral or width/intergral is too small." << std::endl;
506 NumberOfPeaksBeforeFit = peakVals.size();
507 nExponentialsForFit = peakVals.size();
510 if(NumberOfPeaksBeforeFit <= fMaxMultiHit && width <= fMaxGroupLength && NFluctuations <= fMaxFluctuations)
516 FitExponentials(signal, peakVals, startT, endT, paramVec, chi2PerNDF, NDF, fSameShape);
521 std::cout <<
"--- First fit ---" << std::endl;
522 if (nExponentialsForFit == 1)
std::cout <<
"- Fitted " << nExponentialsForFit <<
" peak in group #" << j <<
":" << std::endl;
523 else std::cout <<
"- Fitted " << nExponentialsForFit <<
" peaks in group #" << j <<
":" << std::endl;
524 std::cout <<
"chi2/ndf = " << chi2PerNDF << std::endl;
528 std::cout <<
"tau1 [mus] = " << paramVec[0].first << std::endl;
529 std::cout <<
"tau2 [mus] = " << paramVec[1].first << std::endl;
531 for(
unsigned int i = 0; i < nExponentialsForFit; i++)
533 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[2*(i+1)].
first << std::endl;
534 std::cout <<
"Peak #" << i <<
": t0 [ticks] = " << range.offset + paramVec[2*(i+1)+1].
first << std::endl;
539 for(
unsigned int i = 0; i < nExponentialsForFit; i++)
541 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[4*i+2].first << std::endl;
542 std::cout <<
"Peak #" << i <<
": t0 [ticks] = " << range.offset + paramVec[4*i+3].first << std::endl;
543 std::cout <<
"Peak #" << i <<
": tau1 [mus] = " << paramVec[4*i].first << std::endl;
544 std::cout <<
"Peak #" << i <<
": tau2 [mus] = " << paramVec[4*i+1].first << std::endl;
550 if (!(chi2PerNDF < std::numeric_limits<double>::infinity()))
continue;
558 if( (fTryNplus1Fits && nExponentialsForFit == 1 && chi2PerNDF > fChi2NDFRetry) ||
559 (fTryNplus1Fits && nExponentialsForFit > 1 && chi2PerNDF > fChi2NDFRetryFactorMultiHits*fChi2NDFRetry) )
561 unsigned int nExponentialsBeforeRefit=nExponentialsForFit;
562 unsigned int nExponentialsAfterRefit=nExponentialsForFit;
563 double oldChi2PerNDF = chi2PerNDF;
568 while( (nExponentialsForFit == 1 && nExponentialsAfterRefit < 3*nExponentialsBeforeRefit && chi2PerNDF > fChi2NDFRetry) ||
569 (nExponentialsForFit > 1 && nExponentialsAfterRefit < 3*nExponentialsBeforeRefit && chi2PerNDF > fChi2NDFRetryFactorMultiHits*fChi2NDFRetry) )
571 RefitSuccess =
false;
576 for(
auto& PeakDevCand : PeakDev)
581 peakValsTemp = peakVals;
583 AddPeak(PeakDevCand, peakValsTemp);
584 FitExponentials(signal, peakValsTemp, startT, endT, paramVecRefit, chi2PerNDF2, NDF2, fSameShape);
586 if (chi2PerNDF2 < chi2PerNDF)
588 paramVec = paramVecRefit;
589 peakVals = peakValsTemp;
590 nExponentialsForFit = peakVals.size();
591 chi2PerNDF = chi2PerNDF2;
593 nExponentialsAfterRefit++;
600 if(RefitSuccess ==
false)
602 for(
auto& PeakDevCand : PeakDev)
607 peakValsTemp=peakVals;
610 FitExponentials(signal, peakValsTemp, startT, endT, paramVecRefit, chi2PerNDF2, NDF2, fSameShape);
612 if (chi2PerNDF2 < chi2PerNDF)
614 paramVec = paramVecRefit;
615 peakVals = peakValsTemp;
616 nExponentialsForFit = peakVals.size();
617 chi2PerNDF = chi2PerNDF2;
619 nExponentialsAfterRefit++;
626 if(RefitSuccess ==
false)
635 std::cout <<
"--- Refit ---" << std::endl;
636 if( chi2PerNDF == oldChi2PerNDF)
std::cout <<
"chi2/ndf didn't improve. Keep first fit." << std::endl;
639 std::cout <<
"- Added peaks to group #" << j <<
". This group now has " << nExponentialsForFit <<
" peaks:" << std::endl;
640 std::cout <<
"- Group #" << j <<
" (" << peakVals.size() <<
" peaks): GroupStartTick: " << range.offset + startT <<
" GroupEndTick: " << range.offset + endT << std::endl;
642 int CountPeakInGroup=0;
643 for(
auto const& peakValsTmp : peakVals )
645 std::cout <<
"Peak #" << CountPeakInGroup <<
" in group #" << j <<
": PeakInGroupStartTick: " << range.offset + std::get<2>(peakValsTmp) <<
" PeakInGroupMaxTick: " << range.offset + std::get<0>(peakValsTmp) <<
" PeakInGroupEndTick: " << range.offset + std::get<3>(peakValsTmp) << std::endl;
649 std::cout <<
"chi2/ndf = " << chi2PerNDF << std::endl;
653 std::cout <<
"tau1 [mus] = " << paramVec[0].first << std::endl;
654 std::cout <<
"tau2 [mus] = " << paramVec[1].first << std::endl;
656 for(
unsigned int i = 0; i < nExponentialsForFit; i++)
658 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[2*(i+1)].
first << std::endl;
659 std::cout <<
"Peak #" << i <<
": t0 [ticks] = " << range.offset + paramVec[2*(i+1)+1].
first << std::endl;
664 for(
unsigned int i = 0; i < nExponentialsForFit; i++)
666 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[4*i+2].first << std::endl;
667 std::cout <<
"Peak #" << i <<
": t0 [ticks] = " << range.offset + paramVec[4*i+3].first << std::endl;
668 std::cout <<
"Peak #" << i <<
": tau1 [mus] = " << paramVec[4*i].first << std::endl;
669 std::cout <<
"Peak #" << i <<
": tau2 [mus] = " << paramVec[4*i+1].first << std::endl;
681 for(
unsigned int i = 0; i < nExponentialsForFit; i++)
691 peakTau1 = paramVec[0].first;
692 peakTau2 = paramVec[1].first;
693 peakAmp = paramVec[2*(i+1)].
first;
694 peakMean = paramVec[2*(i+1)+1].
first;
698 peakTau1 = paramVec[4*i].first;
699 peakTau2 = paramVec[4*i+1].first;
700 peakAmp = paramVec[4*i+2].first;
701 peakMean = paramVec[4*i+3].first;
705 double peakAmpTrue = signal[std::get<0>(peakVals.at(i))];
706 double peakAmpErr = 1.;
709 TF1 Exponentials(
"Exponentials",
"( [0] * exp(0.4*(x-[1])/[2]) / ( 1 + exp(0.4*(x-[1])/[3]) ) )",startT,endT);
710 Exponentials.SetParameter(0, peakAmp);
711 Exponentials.SetParameter(1, peakMean);
712 Exponentials.SetParameter(2, peakTau1);
713 Exponentials.SetParameter(3, peakTau2);
714 double peakMeanTrue = Exponentials.GetMaximumX(startT,endT);
715 Exponentials.Delete();
718 double peakWidth =
WidthFunc(peakMean, peakAmp, peakTau1, peakTau2, startT, endT, peakMeanTrue);
727 peakMeanErr = paramVec[2*(i+1)+1].
second;
731 peakMeanErr = paramVec[4*i+3].second;
733 double peakWidthErr = 0.1*peakWidth;
736 double charge =
ChargeFunc(peakMean, peakAmp, peakTau1, peakTau2, fChargeNorm, peakMeanTrue);
737 double chargeErr = std::sqrt(TMath::Pi()) * (peakAmpErr*peakWidthErr + peakWidthErr*peakAmpErr);
740 int startTthisHit = std::get<2>(peakVals.at(i));
741 int endTthisHit = std::get<3>(peakVals.at(i));
742 std::vector<float>::const_iterator sumStartItr = signal.begin() + startTthisHit;
743 std::vector<float>::const_iterator sumEndItr = signal.begin() + endTthisHit;
746 double sumADC = std::accumulate(sumStartItr, sumEndItr + 1, 0.);
750 if(peakWidth <= 0 || charge <= 0. || charge != charge || ( nExponentialsForFit == 1 && chi2PerNDF > fChi2NDFMax ) || ( nExponentialsForFit >= 2 && chi2PerNDF > fChi2NDFMaxFactorMultiHits*fChi2NDFMax ) )
755 std::cout <<
"WARNING: For peak #" << i <<
" in this group:" << std::endl;
756 if( peakWidth <= 0 || charge <= 0. || charge != charge)
std::cout <<
"Fit function returned width < 0 or charge < 0 or charge = nan." << std::endl;
757 if( ( nExponentialsForFit == 1 && chi2PerNDF > fChi2NDFMax ) || ( nExponentialsForFit >= 2 && chi2PerNDF > fChi2NDFMaxFactorMultiHits*fChi2NDFMax ) )
760 std::cout <<
"WARNING: For fit of this group (" << NumberOfPeaksBeforeFit <<
" peaks before refit, " << nExponentialsForFit <<
" peaks after refit): " << std::endl;
761 if ( nExponentialsForFit == 1 && chi2PerNDF > fChi2NDFMax )
std::cout <<
"chi2/ndf of this fit (" << chi2PerNDF <<
") is higher than threshold (" << fChi2NDFMax <<
")." << std::endl;
762 if ( nExponentialsForFit >= 2 && chi2PerNDF > fChi2NDFMaxFactorMultiHits*fChi2NDFMax )
std::cout <<
"chi2/ndf of this fit (" << chi2PerNDF <<
") is higher than threshold (" << fChi2NDFMaxFactorMultiHits*fChi2NDFMax <<
")." << std::endl;
764 std::cout <<
"---> DO NOT create hit object from fit parameters but use peak values instead." << std::endl;
765 std::cout <<
"---> Set fit parameter so that a sharp peak with a width of 1 tick is shown in the event display. This indicates that the fit failed." << std::endl;
768 peakMeanErr=peakWidth/2;
770 peakMeanTrue = std::get<0>(peakVals.at(i));
773 peakMean = peakMeanTrue;
782 startTthisHit+roiFirstBinTick,
783 endTthisHit+roiFirstBinTick,
785 peakMeanTrue+roiFirstBinTick,
801 std::cout <<
"- Created hit object for peak #" << i <<
" in this group with the following parameters (obtained from fit):" << std::endl;
802 std::cout <<
"HitStartTick: " << startTthisHit+roiFirstBinTick << std::endl;
803 std::cout <<
"HitEndTick: " << endTthisHit+roiFirstBinTick << std::endl;
804 std::cout <<
"HitWidthTicks: " << peakWidth << std::endl;
805 std::cout <<
"HitMeanTick: " << peakMeanTrue+roiFirstBinTick <<
" +- " << peakMeanErr << std::endl;
806 std::cout <<
"HitAmplitude [ADC]: " << peakAmpTrue <<
" +- " << peakAmpErr << std::endl;
807 std::cout <<
"HitIntegral [ADC*ticks]: " << charge <<
" +- " << chargeErr << std::endl;
808 std::cout <<
"HitADCSum [ADC*ticks]: " << sumADC << std::endl;
809 std::cout <<
"HitMultiplicity: " << nExponentialsForFit << std::endl;
810 std::cout <<
"HitIndex in group: " << numHits << std::endl;
811 std::cout <<
"Hitchi2/ndf: " << chi2PerNDF << std::endl;
812 std::cout <<
"HitNDF: " << NDF << std::endl;
819 std::array<float, 4> fitParams;
820 fitParams[0] = peakMean+roiFirstBinTick;
821 fitParams[1] = peakTau1;
822 fitParams[2] = peakTau2;
823 fitParams[3] = peakAmp;
836 if( NumberOfPeaksBeforeFit > fMaxMultiHit || (width > fMaxGroupLength) || NFluctuations > fMaxFluctuations)
839 int nHitsInThisGroup = (endT - startT + 1) / fLongPulseWidth;
841 if (nHitsInThisGroup > fLongMaxHits)
844 fLongPulseWidth = (endT - startT + 1) / nHitsInThisGroup;
847 if (nHitsInThisGroup * fLongPulseWidth < (endT - startT + 1) ) nHitsInThisGroup++;
849 int firstTick = startT;
850 int lastTick = std::min(endT,firstTick+fLongPulseWidth-1);
854 if( NumberOfPeaksBeforeFit > fMaxMultiHit)
857 std::cout <<
"WARNING: Number of peaks in this group (" << NumberOfPeaksBeforeFit <<
") is higher than threshold (" << fMaxMultiHit <<
")." << std::endl;
858 std::cout <<
"---> DO NOT fit. Split group of peaks into hits with equal length instead." << std::endl;
860 if( width > fMaxGroupLength)
863 std::cout <<
"WARNING: group of peak is longer (" << width <<
" ticks) than threshold (" << fMaxGroupLength <<
" ticks)." << std::endl;
864 std::cout <<
"---> DO NOT fit. Split group of peaks into hits with equal length instead." << std::endl;
866 if( NFluctuations > fMaxFluctuations)
869 std::cout <<
"WARNING: fluctuations (" << NFluctuations <<
") higher than threshold (" << fMaxFluctuations <<
")." << std::endl;
870 std::cout <<
"---> DO NOT fit. Split group of peaks into hits with equal length instead." << std::endl;
881 std::cout <<
"---> Group goes from tick " << roiFirstBinTick+startT <<
" to " << roiFirstBinTick+endT <<
". Split group into (" << roiFirstBinTick+endT <<
" - " << roiFirstBinTick+startT <<
")/" << fLongPulseWidth <<
" = " << (endT - startT) <<
"/" << fLongPulseWidth <<
" = " << nHitsInThisGroup <<
" peaks (" << fLongPulseWidth <<
" = LongPulseWidth), or maximum LongMaxHits = " << fLongMaxHits <<
" peaks." << std::endl;
885 for(
int hitIdx = 0; hitIdx < nHitsInThisGroup; hitIdx++)
889 double peakMeanTrue = (firstTick + lastTick) / 2.;
890 if( NumberOfPeaksBeforeFit == 1 && nHitsInThisGroup == 1) peakMeanTrue = std::get<0>(peakVals.at(0));
891 double peakMeanErr = (lastTick - firstTick) / 2.;
892 double sumADC = std::accumulate(signal.begin() + firstTick, signal.begin() + lastTick + 1, 0.);
893 double charge = sumADC;
894 double chargeErr = 0.1*sumADC;
895 double peakAmpTrue = 0;
899 if(signal[
tick] > peakAmpTrue) peakAmpTrue = signal[
tick];
902 double peakAmpErr = 1.;
903 nExponentialsForFit = nHitsInThisGroup;
907 double peakMean = peakMeanTrue-2;
908 double peakTau1 = 0.008;
909 double peakTau2 = 0.0065;
910 double peakAmp = 20.;
914 firstTick+roiFirstBinTick,
915 lastTick+roiFirstBinTick,
917 peakMeanTrue+roiFirstBinTick,
934 std::cout <<
"- Created hit object for peak #" << hitIdx <<
" in this group with the following parameters (obtained from waveform):" << std::endl;
935 std::cout <<
"HitStartTick: " << firstTick+roiFirstBinTick << std::endl;
936 std::cout <<
"HitEndTick: " << lastTick+roiFirstBinTick << std::endl;
937 std::cout <<
"HitWidthTicks: " << peakWidth << std::endl;
938 std::cout <<
"HitMeanTick: " << peakMeanTrue+roiFirstBinTick <<
" +- " << peakMeanErr << std::endl;
939 std::cout <<
"HitAmplitude [ADC]: " << peakAmpTrue <<
" +- " << peakAmpErr << std::endl;
940 std::cout <<
"HitIntegral [ADC*ticks]: " << charge <<
" +- " << chargeErr << std::endl;
941 std::cout <<
"HitADCSum [ADC*ticks]: " << sumADC << std::endl;
942 std::cout <<
"HitMultiplicity: " << nExponentialsForFit << std::endl;
943 std::cout <<
"HitIndex in group: " << hitIdx << std::endl;
944 std::cout <<
"Hitchi2/ndf: " << chi2PerNDF << std::endl;
945 std::cout <<
"HitNDF: " << NDF << std::endl;
950 std::array<float, 4> fitParams;
951 fitParams[0] = peakMean+roiFirstBinTick;
952 fitParams[1] = peakTau1;
953 fitParams[2] = peakTau2;
954 fitParams[3] = peakAmp;
958 firstTick = lastTick+1;
959 lastTick = std::min(firstTick + fLongPulseWidth - 1, endT);
963 fChi2->Fill(chi2PerNDF);
983 std::vector<float>::const_iterator stopItr,
992 auto maxItr = std::max_element(startItr, stopItr);
994 float maxValue = *maxItr;
997 if (maxValue >= PeakMin)
1000 auto firstItr =
std::distance(startItr,maxItr) > 2 ? maxItr - 1 : startItr;
1001 bool PeakStartIsHere =
true;
1003 while(firstItr != startItr)
1006 PeakStartIsHere =
true;
1007 for(
int i=1; i <= fTicksToStopPeakFinder; i++)
1009 if( *firstItr >= *(firstItr-i) )
1011 PeakStartIsHere =
false;
1016 if (*firstItr <= 0 || PeakStartIsHere)
break;
1023 findCandidatePeaks(startItr, firstItr - 1, timeValsVec, PeakMin, firstTick);
1026 auto lastItr =
std::distance(maxItr,stopItr) > 2 ? maxItr + 1 : stopItr - 1;
1027 bool PeakEndIsHere =
true;
1029 while(lastItr != stopItr)
1032 PeakEndIsHere =
true;
1033 for(
int i=1; i <= fTicksToStopPeakFinder; i++)
1035 if( *lastItr >= *(lastItr+i) )
1037 PeakEndIsHere =
false;
1041 if (*lastItr <= 0 || PeakEndIsHere)
break;
1048 timeValsVec.push_back(std::make_tuple(firstTick+firstTime,firstTick+maxTime,firstTick+lastTime));
1051 findCandidatePeaks(lastItr + 1, stopItr, timeValsVec, PeakMin, firstTick +
std::distance(startItr,lastItr + 1));
1067 auto timeValsVecItr = timeValsVec.begin();
1068 unsigned int PeaksInThisMergedPeak = 0;
1070 while(timeValsVecItr != timeValsVec.end())
1075 auto& timeVal = *timeValsVecItr++;
1076 int startT = std::get<0>(timeVal);
1077 int maxT = std::get<1>(timeVal);
1078 int endT = std::get<2>(timeVal);
1079 int widT = endT - startT;
1080 int FinalStartT=startT;
1083 int NFluctuations=EstimateFluctuations(signalVec, startT, maxT, endT);
1085 peakVals.emplace_back(maxT,widT,startT,endT);
1089 bool checkNextHit = timeValsVecItr != timeValsVec.end();
1095 int NextStartT = std::get<0>(*timeValsVecItr);
1097 double MinADC = signalVec[endT];
1098 for(
int i = endT; i <= NextStartT; i++)
1100 if(signalVec[i]<MinADC)
1102 MinADC = signalVec[i];
1107 if( MinADC >= fGroupMinADC && NextStartT - endT <= fGroupMaxDistance )
1109 int CurrentStartT=startT;
1110 int CurrentMaxT=maxT;
1111 int CurrentEndT=endT;
1114 timeVal = *timeValsVecItr++;
1115 int NextMaxT = std::get<1>(timeVal);
1116 int NextEndT = std::get<2>(timeVal);
1117 int NextWidT = NextEndT - NextStartT;
1120 NFluctuations += EstimateFluctuations(signalVec, NextStartT, NextMaxT, NextEndT);
1122 int CurrentSumADC = 0;
1123 for(
int i = CurrentStartT; i<= CurrentEndT; i++)
1125 CurrentSumADC+=signalVec[i];
1129 for (
int i = NextStartT; i<= NextEndT; i++)
1131 NextSumADC+=signalVec[i];
1137 if( signalVec[NextMaxT] <= signalVec[CurrentMaxT] && ( ( signalVec[NextMaxT] < fMergeMaxADCThreshold*signalVec[CurrentMaxT] && NextSumADC < fMergeADCSumThreshold*CurrentSumADC ) || (signalVec[NextMaxT]-signalVec[NextStartT]) < fMinRelativePeakHeightRight*signalVec[CurrentMaxT] ) && ( signalVec[NextMaxT] <= fMergeMaxADCLimit ) )
1140 startT=CurrentStartT;
1143 peakVals.pop_back();
1144 peakVals.emplace_back(maxT,widT,startT,endT);
1146 else if( signalVec[NextMaxT] > signalVec[CurrentMaxT] && ( ( signalVec[CurrentMaxT] < fMergeMaxADCThreshold*signalVec[NextMaxT] && CurrentSumADC < fMergeADCSumThreshold*NextSumADC ) || (signalVec[CurrentMaxT]-signalVec[CurrentEndT]) < fMinRelativePeakHeightLeft*signalVec[NextMaxT] ) && ( signalVec[CurrentMaxT] <= fMergeMaxADCLimit ) )
1149 startT=CurrentStartT;
1152 peakVals.pop_back();
1153 peakVals.emplace_back(maxT,widT,startT,endT);
1161 peakVals.emplace_back(maxT,widT,startT,endT);
1162 PeaksInThisMergedPeak++;
1171 peakVals.emplace_back(maxT,widT,startT,endT);
1172 PeaksInThisMergedPeak++;
1174 checkNextHit = timeValsVecItr != timeValsVec.end();
1178 checkNextHit =
false;
1179 PeaksInThisMergedPeak = 0;
1184 mergedVec.emplace_back(FinalStartT, FinalEndT, peakVals, NFluctuations);
1197 int NFluctuations=0;
1199 for(
int j = peakMean-1; j >= peakStart; j--)
1201 if(fsignalVec[j] < 5)
break;
1203 if(fsignalVec[j] > fsignalVec[j+1])
1209 for(
int j = peakMean+1; j <= peakEnd; j++)
1211 if(fsignalVec[j] < 5)
break;
1213 if(fsignalVec[j] > fsignalVec[j-1])
1219 return NFluctuations;
1230 double& fchi2PerNDF,
1234 int size = fEndTime - fStartTime + 1;
1235 int NPeaks = fPeakVals.size();
1240 if(fEndTime - fStartTime < 0){size = 0;}
1243 TH1F hitSignal(
"hitSignal",
"",std::max(size,1),fStartTime,fEndTime+1);
1249 for(
int i = fStartTime; i < fEndTime+1; i++)
1251 hitSignal.Fill(i,fSignalVector[i]);
1252 hitSignal.SetBinError(i,0.288675);
1258 std::string eqn = CreateFitFunction(NPeaks, fSameShape);
1264 TF1 Exponentials(
"Exponentials",eqn.c_str(),fStartTime,fEndTime+1);
1269 std::cout <<
"--- Preparing fit ---" << std::endl;
1270 std::cout <<
"--- Lower limits, seed, upper limit:" << std::endl;
1275 Exponentials.SetParameter(0, 0.5);
1276 Exponentials.SetParameter(1, 0.5);
1277 Exponentials.SetParLimits(0, fMinTau, fMaxTau);
1278 Exponentials.SetParLimits(1, fMinTau, fMaxTau);
1282 double peakMeanShift=2;
1283 double peakMeanSeed=0;
1284 double peakMeanRangeLow=0;
1285 double peakMeanRangeHi=0;
1289 for(
int i = 0; i < NPeaks; i++)
1291 peakMean = std::get<0>(fPeakVals.at(i));
1292 peakStart = std::get<2>(fPeakVals.at(i));
1293 peakEnd = std::get<3>(fPeakVals.at(i));
1294 peakMeanSeed=peakMean-peakMeanShift;
1295 peakMeanRangeLow = std::max(peakStart-peakMeanShift, peakMeanSeed-fFitPeakMeanRange);
1296 peakMeanRangeHi = std::min(peakEnd, peakMeanSeed+fFitPeakMeanRange);
1297 amplitude = fSignalVector[peakMean];
1299 Exponentials.SetParameter(2*(i+1), 1.65*amplitude);
1300 Exponentials.SetParLimits(2*(i+1), 0.3*1.65*amplitude, 2*1.65*amplitude);
1301 Exponentials.SetParameter(2*(i+1)+1, peakMeanSeed);
1305 Exponentials.SetParLimits(2*(i+1)+1, peakMeanRangeLow, peakMeanRangeHi);
1307 else if(NPeaks >= 2 && i == 0)
1309 double HalfDistanceToNextMean = 0.5*(std::get<0>(fPeakVals.at(i+1)) - peakMean);
1310 Exponentials.SetParLimits( 2*(i+1)+1, peakMeanRangeLow, std::min(peakMeanRangeHi, peakMeanSeed+HalfDistanceToNextMean) );
1312 else if(NPeaks >= 2 && i == NPeaks-1)
1314 double HalfDistanceToPrevMean = 0.5*(peakMean - std::get<0>(fPeakVals.at(i-1)));
1315 Exponentials.SetParLimits(2*(i+1)+1, std::max(peakMeanRangeLow, peakMeanSeed-HalfDistanceToPrevMean), peakMeanRangeHi );
1319 double HalfDistanceToNextMean = 0.5*(std::get<0>(fPeakVals.at(i+1)) - peakMean);
1320 double HalfDistanceToPrevMean = 0.5*(peakMean - std::get<0>(fPeakVals.at(i-1)));
1321 Exponentials.SetParLimits(2*(i+1)+1, std::max(peakMeanRangeLow, peakMeanSeed-HalfDistanceToPrevMean), std::min(peakMeanRangeHi, peakMeanSeed+HalfDistanceToNextMean) );
1326 double t0low, t0high;
1327 Exponentials.GetParLimits(2*(i+1)+1, t0low, t0high);
1328 std::cout <<
"Peak #" << i <<
": A [ADC] = " << 0.3*1.65*amplitude <<
" , " << 1.65*amplitude <<
" , " << 2*1.65*amplitude << std::endl;
1329 std::cout <<
"Peak #" << i <<
": t0 [ticks] = " << t0low <<
" , " << peakMeanSeed <<
" , " << t0high << std::endl;
1338 double peakMeanShift=2;
1339 double peakMeanSeed=0;
1340 double peakMeanRangeLow=0;
1341 double peakMeanRangeHi=0;
1346 for(
int i = 0; i < NPeaks; i++)
1348 Exponentials.SetParameter(4*i, 0.5);
1349 Exponentials.SetParameter(4*i+1, 0.5);
1350 Exponentials.SetParLimits(4*i, fMinTau, fMaxTau);
1351 Exponentials.SetParLimits(4*i+1, fMinTau, fMaxTau);
1353 peakMean = std::get<0>(fPeakVals.at(i));
1354 peakStart = std::get<2>(fPeakVals.at(i));
1355 peakEnd = std::get<3>(fPeakVals.at(i));
1356 peakMeanSeed=peakMean-peakMeanShift;
1357 peakMeanRangeLow = std::max(peakStart-peakMeanShift, peakMeanSeed-fFitPeakMeanRange);
1358 peakMeanRangeHi = std::min(peakEnd, peakMeanSeed+fFitPeakMeanRange);
1359 amplitude = fSignalVector[peakMean];
1361 Exponentials.SetParameter(4*i+2, 1.65*amplitude);
1362 Exponentials.SetParLimits(4*i+2, 0.3*1.65*amplitude, 2*1.65*amplitude);
1363 Exponentials.SetParameter(4*i+3, peakMeanSeed);
1367 Exponentials.SetParLimits(4*i+3, peakMeanRangeLow, peakMeanRangeHi);
1369 else if(NPeaks >= 2 && i == 0)
1371 double HalfDistanceToNextMean = 0.5*(std::get<0>(fPeakVals.at(i+1)) - peakMean);
1372 Exponentials.SetParLimits( 4*i+3, peakMeanRangeLow, std::min(peakMeanRangeHi, peakMeanSeed+HalfDistanceToNextMean) );
1374 else if(NPeaks >= 2 && i == NPeaks-1)
1376 double HalfDistanceToPrevMean = 0.5*(peakMean - std::get<0>(fPeakVals.at(i-1)));
1377 Exponentials.SetParLimits(4*i+3, std::max(peakMeanRangeLow, peakMeanSeed-HalfDistanceToPrevMean), peakMeanRangeHi );
1381 double HalfDistanceToNextMean = 0.5*(std::get<0>(fPeakVals.at(i+1)) - peakMean);
1382 double HalfDistanceToPrevMean = 0.5*(peakMean - std::get<0>(fPeakVals.at(i-1)));
1383 Exponentials.SetParLimits(4*i+3, std::max(peakMeanRangeLow, peakMeanSeed-HalfDistanceToPrevMean), std::min(peakMeanRangeHi, peakMeanSeed+HalfDistanceToNextMean) );
1388 double t0low, t0high;
1389 Exponentials.GetParLimits(4*i+3, t0low, t0high);
1390 std::cout <<
"Peak #" << i <<
": A [ADC] = " << 0.3*1.65*amplitude <<
" , " << 1.65*amplitude <<
" , " << 2*1.65*amplitude << std::endl;
1391 std::cout <<
"Peak #" << i <<
": t0 [ticks] = " << t0low <<
" , " << peakMeanSeed <<
" , " << t0high << std::endl;
1401 { hitSignal.Fit(&Exponentials,
"QNRWM",
"", fStartTime, fEndTime+1);}
1403 {mf::LogWarning(
"DPRawHitFinder") <<
"Fitter failed finding a hit";}
1408 fchi2PerNDF = (Exponentials.GetChisquare() / Exponentials.GetNDF());
1409 fNDF = Exponentials.GetNDF();
1413 fparamVec.emplace_back(Exponentials.GetParameter(0),Exponentials.GetParError(0));
1414 fparamVec.emplace_back(Exponentials.GetParameter(1),Exponentials.GetParError(1));
1416 for(
int i = 0; i < NPeaks; i++)
1418 fparamVec.emplace_back(Exponentials.GetParameter(2*(i+1)),Exponentials.GetParError(2*(i+1)));
1419 fparamVec.emplace_back(Exponentials.GetParameter(2*(i+1)+1),Exponentials.GetParError(2*(i+1)+1));
1424 for(
int i = 0; i < NPeaks; i++)
1426 fparamVec.emplace_back(Exponentials.GetParameter(4*i),Exponentials.GetParError(4*i));
1427 fparamVec.emplace_back(Exponentials.GetParameter(4*i+1),Exponentials.GetParError(4*i+1));
1428 fparamVec.emplace_back(Exponentials.GetParameter(4*i+2),Exponentials.GetParError(4*i+2));
1429 fparamVec.emplace_back(Exponentials.GetParameter(4*i+3),Exponentials.GetParError(4*i+3));
1432 Exponentials.Delete();
1450 std::string eqn = CreateFitFunction(fNPeaks, fSameShape);
1452 TF1 Exponentials(
"Exponentials",eqn.c_str(),fStartTime,fEndTime+1);
1454 for(
size_t i=0; i < fparamVec.size(); i++)
1456 Exponentials.SetParameter(i, fparamVec[i].
first);
1462 double Chi2PerNDFPeak;
1463 double MaxPosDeviation;
1464 double MaxNegDeviation;
1465 int BinMaxPosDeviation;
1466 int BinMaxNegDeviation;
1467 for(
int i = 0; i < fNPeaks; i++)
1469 Chi2PerNDFPeak = 0.;
1472 BinMaxPosDeviation=0;
1473 BinMaxNegDeviation=0;
1475 for(
int j = std::get<2>(fpeakVals.at(i)); j < std::get<3>(fpeakVals.at(i))+1; j++)
1477 if( (Exponentials(j+0.5)-fSignalVector[j]) > MaxPosDeviation && j != std::get<0>(fpeakVals.at(i)) )
1479 MaxPosDeviation = Exponentials(j+0.5)-fSignalVector[j];
1480 BinMaxPosDeviation = j;
1482 if( (Exponentials(j+0.5)-fSignalVector[j]) < MaxNegDeviation && j != std::get<0>(fpeakVals.at(i)) )
1484 MaxNegDeviation = Exponentials(j+0.5)-fSignalVector[j];
1485 BinMaxNegDeviation = j;
1487 Chi2PerNDFPeak += pow((Exponentials(j+0.5)-fSignalVector[j])/sqrt(fSignalVector[j]),2);
1490 if(BinMaxNegDeviation != 0)
1492 Chi2PerNDFPeak /=
static_cast<double>((std::get<3>(fpeakVals.at(i))-std::get<2>(fpeakVals.at(i))));
1493 fPeakDev.emplace_back(Chi2PerNDFPeak,i,BinMaxNegDeviation,BinMaxPosDeviation);
1497 std::sort(fPeakDev.begin(),fPeakDev.end(), [](std::tuple<double,int,int,int>
const &t1, std::tuple<double,int,int,int>
const &t2) {
return std::get<0>(t1) > std::get<0>(t2);} );
1498 Exponentials.Delete();
1504 std::string feqn =
"";
1505 std::stringstream numConv;
1509 for(
int i = 0; i < fNPeaks; i++)
1511 feqn.append(
"+( [");
1514 feqn.append(numConv.str());
1515 feqn.append(
"] * exp(0.4*(x-[");
1517 numConv << 2*(i+1)+1;
1518 feqn.append(numConv.str());
1519 feqn.append(
"])/[");
1522 feqn.append(numConv.str());
1523 feqn.append(
"]) / ( 1 + exp(0.4*(x-[");
1525 numConv << 2*(i+1)+1;
1526 feqn.append(numConv.str());
1527 feqn.append(
"])/[");
1530 feqn.append(numConv.str());
1531 feqn.append(
"]) ) )");
1536 for(
int i = 0; i < fNPeaks; i++)
1538 feqn.append(
"+( [");
1541 feqn.append(numConv.str());
1542 feqn.append(
"] * exp(0.4*(x-[");
1545 feqn.append(numConv.str());
1546 feqn.append(
"])/[");
1549 feqn.append(numConv.str());
1550 feqn.append(
"]) / ( 1 + exp(0.4*(x-[");
1552 numConv << 2*(i+1)+1;
1553 feqn.append(numConv.str());
1554 feqn.append(
"])/[");
1557 feqn.append(numConv.str());
1558 feqn.append(
"]) ) )");
1569 int PeakNumberWithNewPeak = std::get<1>(fPeakDevCand);
1570 int NewPeakMax = std::get<2>(fPeakDevCand);
1571 int OldPeakMax = std::get<0>(fpeakValsTemp.at(PeakNumberWithNewPeak));
1572 int OldPeakOldStart = std::get<2>(fpeakValsTemp.at(PeakNumberWithNewPeak));
1573 int OldPeakOldEnd = std::get<3>(fpeakValsTemp.at(PeakNumberWithNewPeak));
1577 int OldPeakNewStart=0;
1578 int OldPeakNewEnd=0;
1579 int DistanceBwOldAndNewPeak=0;
1581 if(NewPeakMax<OldPeakMax)
1583 NewPeakStart = OldPeakOldStart;
1584 OldPeakNewEnd = OldPeakOldEnd;
1585 DistanceBwOldAndNewPeak = OldPeakMax - NewPeakMax;
1586 NewPeakEnd = NewPeakMax+0.5*(DistanceBwOldAndNewPeak-(DistanceBwOldAndNewPeak%2));
1587 if(DistanceBwOldAndNewPeak%2 == 0) NewPeakEnd -= 1;
1588 OldPeakNewStart = NewPeakEnd+1;
1590 else if(OldPeakMax<NewPeakMax)
1592 NewPeakEnd = OldPeakOldEnd;
1593 OldPeakNewStart = OldPeakOldStart;
1594 DistanceBwOldAndNewPeak = NewPeakMax - OldPeakMax;
1595 OldPeakNewEnd = OldPeakMax+0.5*(DistanceBwOldAndNewPeak-(DistanceBwOldAndNewPeak%2));
1596 if(DistanceBwOldAndNewPeak%2 == 0) OldPeakNewEnd -= 1;
1597 NewPeakStart = OldPeakNewEnd+1;
1599 else if(OldPeakMax==NewPeakMax){
return;}
1601 fpeakValsTemp.at(PeakNumberWithNewPeak) = std::make_tuple(OldPeakMax,0,OldPeakNewStart,OldPeakNewEnd);
1602 fpeakValsTemp.emplace_back(NewPeakMax,0,NewPeakStart,NewPeakEnd);
1603 std::sort(fpeakValsTemp.begin(),fpeakValsTemp.end(), [](std::tuple<int,int,int,int>
const &t1, std::tuple<int,int,int,int>
const &t2) {
return std::get<0>(t1) < std::get<0>(t2);} );
1613 int PeakNumberWithNewPeak = std::get<1>(fPeakDevCand);
1614 int OldPeakOldStart = std::get<2>(fpeakValsTemp.at(PeakNumberWithNewPeak));
1615 int OldPeakOldEnd = std::get<3>(fpeakValsTemp.at(PeakNumberWithNewPeak));
1616 int WidthOldPeakOld = OldPeakOldEnd - OldPeakOldStart;
1618 if(WidthOldPeakOld<3) {
return;}
1621 int NewPeakStart = 0;
1623 int OldPeakNewMax = 0;
1624 int OldPeakNewStart = 0;
1625 int OldPeakNewEnd = 0;
1628 OldPeakNewStart = OldPeakOldStart;
1629 NewPeakEnd = OldPeakOldEnd;
1631 OldPeakNewEnd = OldPeakNewStart + 0.5*(WidthOldPeakOld + (WidthOldPeakOld%2));
1632 NewPeakStart = OldPeakNewEnd+1;
1634 int WidthOldPeakNew = OldPeakNewEnd-OldPeakNewStart;
1635 int WidthNewPeak = NewPeakEnd-NewPeakStart;
1637 OldPeakNewMax = OldPeakNewStart + 0.5*(WidthOldPeakNew - (WidthOldPeakNew%2));
1638 NewPeakMax = NewPeakStart + 0.5*(WidthNewPeak - (WidthNewPeak%2));
1640 fpeakValsTemp.at(PeakNumberWithNewPeak) = std::make_tuple(OldPeakNewMax,0,OldPeakNewStart,OldPeakNewEnd);
1641 fpeakValsTemp.emplace_back(NewPeakMax,0,NewPeakStart,NewPeakEnd);
1642 std::sort(fpeakValsTemp.begin(),fpeakValsTemp.end(), [](std::tuple<int,int,int,int>
const &t1, std::tuple<int,int,int,int>
const &t2) {
return std::get<0>(t1) < std::get<0>(t2);} );
1654 double fPeakMeanTrue)
1656 double MaxValue = ( fPeakAmp *
exp(0.4*(fPeakMeanTrue-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(fPeakMeanTrue-fPeakMean)/fPeakTau2) );
1657 double FuncValue = 0.;
1658 double HalfMaxLeftTime = 0.;
1659 double HalfMaxRightTime = 0.;
1663 for(
double x = fPeakMeanTrue;
x > fStartTime-1000.;
x--)
1665 FuncValue = ( fPeakAmp *
exp(0.4*(
x-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x-fPeakMean)/fPeakTau2) );
1666 if( FuncValue < 0.5*MaxValue )
1668 HalfMaxLeftTime =
x;
1673 for(
double x = fPeakMeanTrue;
x < fEndTime+1000.;
x++)
1675 FuncValue = ( fPeakAmp *
exp(0.4*(
x-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x-fPeakMean)/fPeakTau2) );
1676 if( FuncValue < 0.5*MaxValue )
1678 HalfMaxRightTime =
x;
1684 for(
double x = HalfMaxLeftTime+1;
x > HalfMaxLeftTime;
x-=(1/ReBin))
1686 FuncValue = ( fPeakAmp *
exp(0.4*(
x-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x-fPeakMean)/fPeakTau2) );
1687 if( FuncValue < 0.5*MaxValue )
1689 HalfMaxLeftTime =
x;
1694 for(
double x = HalfMaxRightTime-1;
x < HalfMaxRightTime;
x+=(1/ReBin))
1696 FuncValue = ( fPeakAmp *
exp(0.4*(
x-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x-fPeakMean)/fPeakTau2) );
1697 if( FuncValue < 0.5*MaxValue )
1699 HalfMaxRightTime =
x;
1705 for(
double x = HalfMaxLeftTime+1/ReBin;
x > HalfMaxLeftTime;
x-=1/(ReBin*ReBin))
1707 FuncValue = ( fPeakAmp *
exp(0.4*(
x-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x-fPeakMean)/fPeakTau2) );
1708 if( FuncValue < 0.5*MaxValue )
1710 HalfMaxLeftTime =
x;
1715 for(
double x = HalfMaxRightTime-1/ReBin;
x < HalfMaxRightTime;
x+=1/(ReBin*ReBin))
1717 FuncValue = ( fPeakAmp *
exp(0.4*(
x-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x-fPeakMean)/fPeakTau2) );
1718 if( FuncValue < 0.5*MaxValue )
1720 HalfMaxRightTime =
x;
1725 return HalfMaxRightTime-HalfMaxLeftTime;
1733 double fChargeNormFactor,
1734 double fPeakMeanTrue)
1737 double ChargeSum = 0.;
1741 bool ChargeBigEnough=
true;
1742 for(
double x = fPeakMeanTrue - 1/ReBin; ChargeBigEnough &&
x > fPeakMeanTrue-1000.;
x-=1.)
1744 for(
double i=0.; i > -1.; i-=(1/ReBin))
1746 Charge = ( fPeakAmp *
exp(0.4*(
x+i-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x+i-fPeakMean)/fPeakTau2) );
1747 ChargeSum += Charge;
1749 if(Charge < 0.01) ChargeBigEnough =
false;
1752 ChargeBigEnough=
true;
1753 for(
double x = fPeakMeanTrue; ChargeBigEnough &&
x < fPeakMeanTrue+1000.;
x+=1.)
1755 for(
double i=0.; i < 1.; i+=(1/ReBin))
1757 Charge = ( fPeakAmp *
exp(0.4*(
x+i-fPeakMean)/fPeakTau1)) / ( 1 +
exp(0.4*(
x+i-fPeakMean)/fPeakTau2) );
1758 ChargeSum += Charge;
1760 if(Charge < 0.01) ChargeBigEnough =
false;
1764 return ChargeSum*fChargeNormFactor/ReBin;
1769 std::vector<float>& outputVec,
1770 size_t binsToAverage)
const
1772 size_t halfBinsToAverage(binsToAverage/2);
1774 float runningSum(0.);
1776 for(
size_t idx = 0; idx < halfBinsToAverage; idx++) runningSum += inputVec[idx];
1778 outputVec.resize(inputVec.size());
1779 std::vector<float>::iterator outputVecItr = outputVec.begin();
1782 for(std::vector<float>::const_iterator inputItr = inputVec.begin(); inputItr != inputVec.end(); inputItr++)
1784 size_t startOffset =
std::distance(inputVec.begin(),inputItr);
1786 size_t count = std::min(2 * halfBinsToAverage, std::min(startOffset + halfBinsToAverage + 1, halfBinsToAverage + stopOffset - 1));
1788 if (startOffset >= halfBinsToAverage) runningSum -= *(inputItr - halfBinsToAverage);
1789 if (stopOffset > halfBinsToAverage) runningSum += *(inputItr + halfBinsToAverage);
1791 *outputVecItr++ = runningSum / float(count);
1799 std::vector<float>& outputVec,
1800 size_t nBinsToCombine)
const
1802 size_t nNewBins = inputVec.size() / nBinsToCombine;
1804 if (inputVec.size() % nBinsToCombine > 0) nNewBins++;
1806 outputVec.resize(nNewBins, 0.);
1808 size_t outputBin = 0;
1810 for(
size_t inputIdx = 0; inputIdx < inputVec.size();)
1812 outputVec[outputBin] += inputVec[inputIdx++];
1814 if (inputIdx % nBinsToCombine == 0) outputBin++;
1816 if (outputBin > outputVec.size())
1818 std::cout <<
"***** DISASTER!!! ****** outputBin: " << outputBin <<
", inputIdx = " << inputIdx << std::endl;
void findCandidatePeaks(std::vector< float >::const_iterator startItr, std::vector< float >::const_iterator stopItr, TimeValsVec &timeValsVec, float &PeakMin, int firstTick) const
int fTicksToStopPeakFinder
process_name opflash particleana ie x
double fMergeADCSumThreshold
void mergeCandidatePeaks(const std::vector< float > signalVec, TimeValsVec, MergedTimeWidVec &)
bool operator()(std::tuple< int, int, int, int > p, int s) const
fMaxMultiHit(pset.get< int >("MaxMultiHit"))
Declaration of signal hit object.
std::vector< std::tuple< int, int, PeakTimeWidVec, int >> MergedTimeWidVec
void produce(art::Event &evt) override
void FindPeakWithMaxDeviation(const std::vector< float > fSignalVector, int fNPeaks, int fStartTime, int fEndTime, bool fSameShape, ParameterVec fparamVec, PeakTimeWidVec fpeakVals, PeakDevVec &fPeakDev)
std::vector< std::tuple< double, int, int, int >> PeakDevVec
CryostatID_t Cryostat
Index of cryostat.
std::size_t size(FixedBins< T, C > const &) noexcept
const range_list_t & get_ranges() const
Returns the internal list of non-void ranges.
WireID_t Wire
Index of the wire within its plane.
void SplitPeak(std::tuple< double, int, int, int > fPeakDevCand, PeakTimeWidVec &fpeakValsTemp)
double fChi2NDFMaxFactorMultiHits
static void declare_products(art::ProducesCollector &collector, std::string instance_name="", bool doWireAssns=true, bool doRawDigitAssns=true)
Declares the hit products we are going to fill.
DPRawHitFinder(fhicl::ParameterSet const &pset)
void addVector(FVector_ID id, std::array< float, N > const &values)
int TDCtick_t
Type representing a TDC tick.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::vector< std::tuple< int, int, int, int >> PeakTimeWidVec
Class managing the creation of a new recob::Hit object.
void FillOutHitParameterVector(const std::vector< double > &input, std::vector< double > &output)
Helper functions to create a hit.
FVector_ID initOutputs(std::string const &dataTag, size_t dataSize, std::vector< std::string > const &names=std::vector< std::string >(N,""))
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
void AddPeak(std::tuple< double, int, int, int > fPeakDevCand, PeakTimeWidVec &fpeakValsTemp)
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
double fChi2NDFRetryFactorMultiHits
A class handling a collection of hits and its associations.
std::vector< std::pair< double, double >> ParameterVec
double fMergeMaxADCThreshold
double fWidthNormalization
anab::FVectorWriter< 4 > fHitParamWriter
std::string CreateFitFunction(int fNPeaks, bool fSameShape)
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
double ChargeFunc(double fPeakMean, double fPeakAmp, double fPeakTau1, double fPeakTau2, double fChargeNormFactor, double fPeakMeanTrue)
void emplace_back(recob::Hit &&hit, art::Ptr< recob::Wire > const &wire=art::Ptr< recob::Wire >(), art::Ptr< raw::RawDigit > const &digits=art::Ptr< raw::RawDigit >())
Adds the specified hit to the data collection.
double fMinADCSumOverWidth
double fMinRelativePeakHeightLeft
PlaneID_t Plane
Index of the plane within its TPC.
void put_into(art::Event &)
Moves the data into an event.
void saveOutputs(art::Event &evt)
Check consistency and save all the results in the event.
void FitExponentials(const std::vector< float > fSignalVector, const PeakTimeWidVec fPeakVals, int fStartTime, int fEndTime, ParameterVec &fparamVec, double &fchi2PerNDF, int &fNDF, bool fSameShape)
std::string fCalDataModuleLabel
std::vector< std::tuple< int, int, int >> TimeValsVec
then echo File list $list not found else cat $list while read file do echo $file sed s
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG simSlidingORM6O6 effSlidingORW output
Declaration of basic channel signal object.
int EstimateFluctuations(const std::vector< float > fsignalVec, int peakStart, int peakMean, int peakEnd)
void doBinAverage(const std::vector< float > &inputVec, std::vector< float > &outputVec, size_t binsToAverage) const
2D representation of charge deposited in the TDC/wire plane
art::ServiceHandle< art::TFileService > tfs
std::size_t count(Cont const &cont)
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
recob::Hit && move()
Prepares the constructed hit to be moved away.
art::InputTag fNewHitsTag
double WidthFunc(double fPeakMean, double fPeakAmp, double fPeakTau1, double fPeakTau2, double fStartTime, double fEndTime, double fPeakMeanTrue)
void reBin(const std::vector< float > &inputVec, std::vector< float > &outputVec, size_t nBinsToCombine) const
art framework interface to geometry description
BEGIN_PROLOG could also be cout
double fMinRelativePeakHeightRight
bool operator()(int s, std::tuple< int, int, int, int > p) const