295 TH1::AddDirectory(kFALSE);
326 for (
size_t wireIter = 0; wireIter < wireVecHandle->size(); wireIter++) {
335 std::vector<geo::WireID> wids = wireReadoutGeom.ChannelToWire(channel);
340 std::cout << std::endl;
341 std::cout << std::endl;
342 std::cout << std::endl;
343 std::cout <<
"-----------------------------------------------------------------------------" 344 "------------------------------" 346 std::cout <<
"Channel: " << channel << std::endl;
347 std::cout <<
"Cryostat: " << wid.
Cryostat << std::endl;
348 std::cout <<
"TPC: " << wid.
TPC << std::endl;
349 std::cout <<
"Plane: " << wid.
Plane << std::endl;
350 std::cout <<
"Wire: " << wid.
Wire << std::endl;
360 for (
const auto& range : signalROI.
get_ranges()) {
364 const std::vector<float>& signal = range.data();
375 std::vector<float> timeAve;
387 if (timeValsVec.empty())
continue;
406 std::cout << std::endl;
407 std::cout << std::endl;
408 std::cout <<
"-------------------- ROI #" << CountROI <<
" -------------------- " 410 if (timeValsVec.size() == 1)
411 std::cout <<
"ROI #" << CountROI <<
" (" << timeValsVec.size()
412 <<
" peak): ROIStartTick: " << range.offset
413 <<
" ROIEndTick:" << range.offset + range.size() << std::endl;
415 std::cout <<
"ROI #" << CountROI <<
" (" << timeValsVec.size()
416 <<
" peaks): ROIStartTick: " << range.offset
417 <<
" ROIEndTick:" << range.offset + range.size() << std::endl;
423 for (
auto const& timeValsTmp : timeValsVec) {
424 std::cout <<
"Peak #" << CountPeak
425 <<
": PeakStartTick: " << range.offset + std::get<0>(timeValsTmp)
426 <<
" PeakMaxTick: " << range.offset + std::get<1>(timeValsTmp)
427 <<
" PeakEndTick: " << range.offset + std::get<2>(timeValsTmp)
435 if (timeValsVec.empty())
continue;
449 int NumberOfPeaksBeforeFit = 0;
450 unsigned int nExponentialsForFit = 0;
451 double chi2PerNDF = 0.;
454 unsigned int NumberOfMergedVecs = mergedVec.size();
460 for (
unsigned int j = 0; j < NumberOfMergedVecs; j++) {
461 int startT = std::get<0>(mergedVec.at(j));
462 int endT = std::get<1>(mergedVec.at(j));
463 int width = endT + 1 - startT;
466 int NFluctuations = std::get<3>(mergedVec.at(j));
469 std::cout << std::endl;
470 if (peakVals.size() == 1)
471 std::cout <<
"- Group #" << j <<
" (" << peakVals.size()
472 <<
" peak): GroupStartTick: " << range.offset + startT
473 <<
" GroupEndTick: " << range.offset + endT << std::endl;
475 std::cout <<
"- Group #" << j <<
" (" << peakVals.size()
476 <<
" peaks): GroupStartTick: " << range.offset + startT
477 <<
" GroupEndTick: " << range.offset + endT << std::endl;
478 std::cout <<
"Fluctuations in this group: " << NFluctuations << std::endl;
479 int CountPeakInGroup = 0;
480 for (
auto const& peakValsTmp : peakVals) {
481 std::cout <<
"Peak #" << CountPeakInGroup <<
" in group #" << j
482 <<
": PeakInGroupStartTick: " << range.offset + std::get<2>(peakValsTmp)
483 <<
" PeakInGroupMaxTick: " << range.offset + std::get<0>(peakValsTmp)
484 <<
" PeakInGroupEndTick: " << range.offset + std::get<3>(peakValsTmp)
492 (
double)std::accumulate(signal.begin() + startT, signal.begin() + endT + 1, 0) <
494 (
double)
std::accumulate(signal.
begin() + startT, signal.
begin() + endT + 1, 0) /
498 std::cout <<
"Delete this group of peaks because width, integral or width/intergral " 508 NumberOfPeaksBeforeFit = peakVals.size();
509 nExponentialsForFit = peakVals.size();
521 std::cout << std::endl;
522 std::cout <<
"--- First fit ---" << std::endl;
523 if (nExponentialsForFit == 1)
524 std::cout <<
"- Fitted " << nExponentialsForFit <<
" peak in group #" << j <<
":" 527 std::cout <<
"- Fitted " << nExponentialsForFit <<
" peaks in group #" << j <<
":" 529 std::cout <<
"chi2/ndf = " << chi2PerNDF << std::endl;
532 std::cout <<
"tau1 [mus] = " << paramVec[0].first << std::endl;
533 std::cout <<
"tau2 [mus] = " << paramVec[1].first << std::endl;
535 for (
unsigned int i = 0; i < nExponentialsForFit; i++) {
536 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[2 * (i + 1)].first
538 std::cout <<
"Peak #" << i
539 <<
": t0 [ticks] = " << range.offset + paramVec[2 * (i + 1) + 1].first
544 for (
unsigned int i = 0; i < nExponentialsForFit; i++) {
545 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[4 * i + 2].first
547 std::cout <<
"Peak #" << i
548 <<
": t0 [ticks] = " << range.offset + paramVec[4 * i + 3].first
550 std::cout <<
"Peak #" << i <<
": tau1 [mus] = " << paramVec[4 * i].first
552 std::cout <<
"Peak #" << i <<
": tau2 [mus] = " << paramVec[4 * i + 1].first
559 if (!(chi2PerNDF < std::numeric_limits<double>::infinity()))
continue;
570 unsigned int nExponentialsBeforeRefit = nExponentialsForFit;
571 unsigned int nExponentialsAfterRefit = nExponentialsForFit;
572 double oldChi2PerNDF = chi2PerNDF;
577 while ((nExponentialsForFit == 1 &&
578 nExponentialsAfterRefit < 3 * nExponentialsBeforeRefit &&
579 chi2PerNDF > fChi2NDFRetry) ||
580 (nExponentialsForFit > 1 &&
581 nExponentialsAfterRefit < 3 * nExponentialsBeforeRefit &&
583 RefitSuccess =
false;
595 for (
auto& PeakDevCand : PeakDev) {
599 peakValsTemp = peakVals;
601 AddPeak(PeakDevCand, peakValsTemp);
611 if (chi2PerNDF2 < chi2PerNDF) {
612 paramVec = paramVecRefit;
613 peakVals = peakValsTemp;
614 nExponentialsForFit = peakVals.size();
615 chi2PerNDF = chi2PerNDF2;
617 nExponentialsAfterRefit++;
624 if (RefitSuccess ==
false) {
625 for (
auto& PeakDevCand : PeakDev) {
629 peakValsTemp = peakVals;
641 if (chi2PerNDF2 < chi2PerNDF) {
642 paramVec = paramVecRefit;
643 peakVals = peakValsTemp;
644 nExponentialsForFit = peakVals.size();
645 chi2PerNDF = chi2PerNDF2;
647 nExponentialsAfterRefit++;
654 if (RefitSuccess ==
false) {
break; }
658 std::cout << std::endl;
659 std::cout <<
"--- Refit ---" << std::endl;
660 if (chi2PerNDF == oldChi2PerNDF)
661 std::cout <<
"chi2/ndf didn't improve. Keep first fit." << std::endl;
663 std::cout <<
"- Added peaks to group #" << j <<
". This group now has " 664 << nExponentialsForFit <<
" peaks:" << std::endl;
665 std::cout <<
"- Group #" << j <<
" (" << peakVals.size()
666 <<
" peaks): GroupStartTick: " << range.offset + startT
667 <<
" GroupEndTick: " << range.offset + endT << std::endl;
669 int CountPeakInGroup = 0;
670 for (
auto const& peakValsTmp : peakVals) {
671 std::cout <<
"Peak #" << CountPeakInGroup <<
" in group #" << j
672 <<
": PeakInGroupStartTick: " 673 << range.offset + std::get<2>(peakValsTmp)
674 <<
" PeakInGroupMaxTick: " 675 << range.offset + std::get<0>(peakValsTmp)
676 <<
" PeakInGroupEndTick: " 677 << range.offset + std::get<3>(peakValsTmp) << std::endl;
681 std::cout <<
"chi2/ndf = " << chi2PerNDF << std::endl;
684 std::cout <<
"tau1 [mus] = " << paramVec[0].first << std::endl;
685 std::cout <<
"tau2 [mus] = " << paramVec[1].first << std::endl;
687 for (
unsigned int i = 0; i < nExponentialsForFit; i++) {
688 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[2 * (i + 1)].first
690 std::cout <<
"Peak #" << i <<
": t0 [ticks] = " 691 << range.offset + paramVec[2 * (i + 1) + 1].first << std::endl;
695 for (
unsigned int i = 0; i < nExponentialsForFit; i++) {
696 std::cout <<
"Peak #" << i <<
": A [ADC] = " << paramVec[4 * i + 2].first
698 std::cout <<
"Peak #" << i
699 <<
": t0 [ticks] = " << range.offset + paramVec[4 * i + 3].first
701 std::cout <<
"Peak #" << i <<
": tau1 [mus] = " << paramVec[4 * i].first
703 std::cout <<
"Peak #" << i <<
": tau2 [mus] = " << paramVec[4 * i + 1].first
716 for (
unsigned int i = 0; i < nExponentialsForFit; i++) {
724 peakTau1 = paramVec[0].first;
725 peakTau2 = paramVec[1].first;
726 peakAmp = paramVec[2 * (i + 1)].first;
727 peakMean = paramVec[2 * (i + 1) + 1].first;
730 peakTau1 = paramVec[4 * i].first;
731 peakTau2 = paramVec[4 * i + 1].first;
732 peakAmp = paramVec[4 * i + 2].first;
733 peakMean = paramVec[4 * i + 3].first;
737 double peakAmpTrue = signal[std::get<0>(peakVals.at(i))];
738 double peakAmpErr = 1.;
741 TF1 Exponentials(
"Exponentials",
742 "( [0] * exp(0.4*(x-[1])/[2]) / ( 1 + exp(0.4*(x-[1])/[3]) ) )",
745 Exponentials.SetParameter(0, peakAmp);
746 Exponentials.SetParameter(1, peakMean);
747 Exponentials.SetParameter(2, peakTau1);
748 Exponentials.SetParameter(3, peakTau2);
749 double peakMeanTrue = Exponentials.GetMaximumX(startT, endT);
750 Exponentials.Delete();
754 WidthFunc(peakMean, peakAmp, peakTau1, peakTau2, startT, endT, peakMeanTrue);
763 peakMeanErr = paramVec[4 * i + 3].second;
765 double peakWidthErr = 0.1 * peakWidth;
771 std::sqrt(TMath::Pi()) * (peakAmpErr * peakWidthErr + peakWidthErr * peakAmpErr);
774 int startTthisHit = std::get<2>(peakVals.at(i));
775 int endTthisHit = std::get<3>(peakVals.at(i));
780 double sumADC = std::accumulate(sumStartItr, sumEndItr + 1, 0.);
783 if (peakWidth <= 0 || charge <= 0. || charge != charge ||
784 (nExponentialsForFit == 1 && chi2PerNDF >
fChi2NDFMax) ||
785 (nExponentialsForFit >= 2 &&
788 std::cout << std::endl;
789 std::cout <<
"WARNING: For peak #" << i <<
" in this group:" << std::endl;
790 if (peakWidth <= 0 || charge <= 0. || charge != charge)
791 std::cout <<
"Fit function returned width < 0 or charge < 0 or charge = nan." 793 if ((nExponentialsForFit == 1 && chi2PerNDF > fChi2NDFMax) ||
794 (nExponentialsForFit >= 2 &&
796 std::cout << std::endl;
797 std::cout <<
"WARNING: For fit of this group (" << NumberOfPeaksBeforeFit
798 <<
" peaks before refit, " << nExponentialsForFit
799 <<
" peaks after refit): " << std::endl;
800 if (nExponentialsForFit == 1 && chi2PerNDF > fChi2NDFMax)
801 std::cout <<
"chi2/ndf of this fit (" << chi2PerNDF
802 <<
") is higher than threshold (" << fChi2NDFMax <<
")." 804 if (nExponentialsForFit >= 2 &&
806 std::cout <<
"chi2/ndf of this fit (" << chi2PerNDF
807 <<
") is higher than threshold (" 810 std::cout <<
"---> DO NOT create hit object from fit parameters but use peak " 813 std::cout <<
"---> Set fit parameter so that a sharp peak with a width of 1 tick " 814 "is shown in the event display. This indicates that the fit failed." 818 (((double)endTthisHit - (
double)startTthisHit) / 4.) /
820 peakMeanErr = peakWidth / 2;
822 peakMeanTrue = std::get<0>(peakVals.at(i));
825 peakMean = peakMeanTrue;
835 startTthisHit + roiFirstBinTick,
836 endTthisHit + roiFirstBinTick,
838 peakMeanTrue + roiFirstBinTick,
852 std::cout << std::endl;
853 std::cout <<
"- Created hit object for peak #" << i
854 <<
" in this group with the following parameters (obtained from fit):" 856 std::cout <<
"HitStartTick: " << startTthisHit + roiFirstBinTick << std::endl;
857 std::cout <<
"HitEndTick: " << endTthisHit + roiFirstBinTick << std::endl;
858 std::cout <<
"HitWidthTicks: " << peakWidth << std::endl;
859 std::cout <<
"HitMeanTick: " << peakMeanTrue + roiFirstBinTick <<
" +- " 860 << peakMeanErr << std::endl;
861 std::cout <<
"HitAmplitude [ADC]: " << peakAmpTrue <<
" +- " << peakAmpErr
863 std::cout <<
"HitIntegral [ADC*ticks]: " << charge <<
" +- " << chargeErr
865 std::cout <<
"HitADCSum [ADC*ticks]: " << sumADC << std::endl;
866 std::cout <<
"HitMultiplicity: " << nExponentialsForFit << std::endl;
867 std::cout <<
"HitIndex in group: " << numHits << std::endl;
868 std::cout <<
"Hitchi2/ndf: " << chi2PerNDF << std::endl;
869 std::cout <<
"HitNDF: " << NDF << std::endl;
874 hcol.emplace_back(std::move(
hit), wire, rawdigits);
876 std::array<float, 4> fitParams;
877 fitParams[0] = peakMean + roiFirstBinTick;
878 fitParams[1] = peakTau1;
879 fitParams[2] = peakTau2;
880 fitParams[3] = peakAmp;
902 if (nHitsInThisGroup *
fLongPulseWidth < (endT - startT + 1)) nHitsInThisGroup++;
904 int firstTick = startT;
909 std::cout << std::endl;
910 std::cout <<
"WARNING: Number of peaks in this group (" << NumberOfPeaksBeforeFit
911 <<
") is higher than threshold (" <<
fMaxMultiHit <<
")." << std::endl;
913 <<
"---> DO NOT fit. Split group of peaks into hits with equal length instead." 917 std::cout << std::endl;
918 std::cout <<
"WARNING: group of peak is longer (" << width
922 <<
"---> DO NOT fit. Split group of peaks into hits with equal length instead." 926 std::cout << std::endl;
927 std::cout <<
"WARNING: fluctuations (" << NFluctuations
930 <<
"---> DO NOT fit. Split group of peaks into hits with equal length instead." 933 std::cout <<
"---> Group goes from tick " << roiFirstBinTick + startT <<
" to " 934 << roiFirstBinTick + endT <<
". Split group into (" 935 << roiFirstBinTick + endT <<
" - " << roiFirstBinTick + startT <<
")/" 938 <<
" = LongPulseWidth), or maximum LongMaxHits = " <<
fLongMaxHits 939 <<
" peaks." << std::endl;
942 for (
int hitIdx = 0; hitIdx < nHitsInThisGroup; hitIdx++) {
945 ((lastTick - firstTick) / 4.) /
947 double peakMeanTrue = (firstTick + lastTick) / 2.;
948 if (NumberOfPeaksBeforeFit == 1 && nHitsInThisGroup == 1)
949 peakMeanTrue = std::get<0>(peakVals.at(
951 double peakMeanErr = (lastTick - firstTick) / 2.;
953 std::accumulate(signal.begin() + firstTick, signal.begin() + lastTick + 1, 0.);
954 double charge = sumADC;
955 double chargeErr = 0.1 * sumADC;
956 double peakAmpTrue = 0;
959 if (signal[
tick] > peakAmpTrue) peakAmpTrue = signal[
tick];
962 double peakAmpErr = 1.;
963 nExponentialsForFit = nHitsInThisGroup;
967 double peakMean = peakMeanTrue - 2;
968 double peakTau1 = 0.008;
969 double peakTau2 = 0.0065;
970 double peakAmp = 20.;
975 firstTick + roiFirstBinTick,
976 lastTick + roiFirstBinTick,
978 peakMeanTrue + roiFirstBinTick,
992 std::cout << std::endl;
994 <<
"- Created hit object for peak #" << hitIdx
995 <<
" in this group with the following parameters (obtained from waveform):" 997 std::cout <<
"HitStartTick: " << firstTick + roiFirstBinTick << std::endl;
998 std::cout <<
"HitEndTick: " << lastTick + roiFirstBinTick << std::endl;
999 std::cout <<
"HitWidthTicks: " << peakWidth << std::endl;
1000 std::cout <<
"HitMeanTick: " << peakMeanTrue + roiFirstBinTick <<
" +- " 1001 << peakMeanErr << std::endl;
1002 std::cout <<
"HitAmplitude [ADC]: " << peakAmpTrue <<
" +- " << peakAmpErr
1004 std::cout <<
"HitIntegral [ADC*ticks]: " << charge <<
" +- " << chargeErr
1006 std::cout <<
"HitADCSum [ADC*ticks]: " << sumADC << std::endl;
1007 std::cout <<
"HitMultiplicity: " << nExponentialsForFit << std::endl;
1008 std::cout <<
"HitIndex in group: " << hitIdx << std::endl;
1009 std::cout <<
"Hitchi2/ndf: " << chi2PerNDF << std::endl;
1010 std::cout <<
"HitNDF: " << NDF << std::endl;
1013 hcol.emplace_back(std::move(
hit), wire, rawdigits);
1015 std::array<float, 4> fitParams;
1016 fitParams[0] = peakMean + roiFirstBinTick;
1017 fitParams[1] = peakTau1;
1018 fitParams[2] = peakTau2;
1019 fitParams[3] = peakAmp;
1023 firstTick = lastTick + 1;
1028 fChi2->Fill(chi2PerNDF);
void findCandidatePeaks(std::vector< float >::const_iterator startItr, std::vector< float >::const_iterator stopItr, TimeValsVec &timeValsVec, float &PeakMin, int firstTick) const
void mergeCandidatePeaks(const std::vector< float > signalVec, TimeValsVec, MergedTimeWidVec &)
ChannelID_t Channel() const
DAQ channel this raw data was read from.
void FindPeakWithMaxDeviation(const std::vector< float > fSignalVector, int fNPeaks, int fStartTime, int fEndTime, bool fSameShape, ParameterVec fparamVec, PeakTimeWidVec fpeakVals, PeakDevVec &fPeakDev)
CryostatID_t Cryostat
Index of cryostat.
const range_list_t & get_ranges() const
Returns the internal list of non-void ranges.
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
WireID_t Wire
Index of the wire within its plane.
void SplitPeak(std::tuple< double, int, int, int > fPeakDevCand, PeakTimeWidVec &fpeakValsTemp)
double fChi2NDFMaxFactorMultiHits
void addVector(FVector_ID id, std::array< float, N > const &values)
std::vector< std::tuple< int, int, int >> TimeValsVec
int TDCtick_t
Type representing a TDC tick.
Class managing the creation of a new recob::Hit object.
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 fChi2NDFRetryFactorMultiHits
A class handling a collection of hits and its associations.
double fWidthNormalization
anab::FVectorWriter< 4 > fHitParamWriter
std::vector< std::pair< double, double >> ParameterVec
std::vector< std::tuple< int, int, int, int >> PeakTimeWidVec
std::vector< std::tuple< double, int, int, int >> PeakDevVec
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
double ChargeFunc(double fPeakMean, double fPeakAmp, double fPeakTau1, double fPeakTau2, double fChargeNormFactor, double fPeakMeanTrue)
double fMinADCSumOverWidth
PlaneID_t Plane
Index of the plane within its TPC.
void saveOutputs(art::Event &evt)
Check consistency and save all the results in the event.
Detector simulation of raw signals on wires.
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
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
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
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
std::vector< std::tuple< int, int, PeakTimeWidVec, int >> MergedTimeWidVec
second_as<> second
Type of time stored in seconds, in double precision.
art::InputTag fNewHitsTag
double WidthFunc(double fPeakMean, double fPeakAmp, double fPeakTau1, double fPeakTau2, double fStartTime, double fEndTime, double fPeakMeanTrue)