1 #ifndef ICARUSHitFINDER_H
2 #define ICARUSHitFINDER_H
18 #include "fhiclcpp/ParameterSet.h"
19 #include "messagefacility/MessageLogger/MessageLogger.h"
20 #include "art/Framework/Core/ModuleMacros.h"
21 #include "art/Framework/Core/EDProducer.h"
22 #include "art/Framework/Principal/Event.h"
23 #include "art/Framework/Principal/Handle.h"
24 #include "canvas/Persistency/Common/Ptr.h"
25 #include "art/Framework/Services/Registry/ServiceHandle.h"
26 #include "canvas/Utilities/InputTag.h"
27 #include "canvas/Persistency/Common/FindOneP.h"
28 #include "art_root_io/TFileService.h"
29 #include "art/Utilities/ToolMacros.h"
30 #include "art/Utilities/make_tool.h"
63 #include "TDecompSVD.h"
77 static Double_t
fitf(Double_t
const*
x, Double_t
const* par);
84 unsigned int const nPeaks = nFunc;
86 auto* pF =
new TF1(func_name.c_str(),
fitf, 0.0, 1.0, 1 + nFunc * 5);
87 pF->SetParName(0,
"NPeaks");
88 pF->FixParameter(0, (
double) nPeaks);
104 static Double_t
fitlong(Double_t
const*
x, Double_t
const* par);
111 unsigned int const nPeaks = nFunc;
113 auto* pF =
new TF1(func_name.c_str(),
fitlong, 0.0, 1.0, 1 + nFunc * 7);
114 pF->SetParName(0,
"NPeaks");
115 pF->FixParameter(0, (
double) nPeaks);
255 fChi2NDF = p.get<
double >(
"Chi2NDF");
256 fLongPulseWidthVec = p.get< std::vector<int>>(
"LongPulseWidth", std::vector<int>() = {16,16,16});
257 fLongMaxHitsVec = p.get< std::vector<int>>(
"LongMaxHits", std::vector<int>() = {25,25,25});
265 fHitFinderTool = art::make_tool<reco_tool::ICandidateHitFinder>(p.get<fhicl::ParameterSet>(
"CandidateHits"));
268 mf::LogInfo(
"ICARUSHitFinder_module") <<
"fDigitModuleLabel: " << fDigitModuleLabel << std::endl;
275 art::ServiceHandle<art::TFileService>
tfs;
280 fFirstChi2 = tfs->make<TH1F>(
"fFirstChi2",
"#chi^{2}", 10000, 0, 1000);
281 fNullChi2 = tfs->make<TH1F>(
"fNullChi2",
"#chi^{2}", 100, 0, 10);
283 fChi2 = tfs->make<TH1F>(
"fChi2",
"#chi^{2}", 10000, 0, 1000);
284 fHeightC = tfs->make<TH1F>(
"fHeightC",
"height(ADC#)", 100, 0, 100);
285 fWidthC = tfs->make<TH1F>(
"fWidthC",
"width(samples)", 200, 0, 200);
286 fNoiseC = tfs->make<TH1F>(
"fNoiseC",
"Noise Area(ADC#)", 100, 0, 100);
287 fAreaC = tfs->make<TH1F>(
"fAreaC",
"", 150, 0, 1500);
288 fAreaC->GetXaxis()->SetTitle(
"Area(ADC#*ticks)");
289 fAreaC->GetYaxis()->SetTitle(
"events");
291 fWire2771 = tfs->make<TH1F>(
"fWire2771",
"", 4096, -0.5, 4095.5);
295 fIntegralC = tfs->make<TH1F>(
"fIntegralC",
"", 500, 0, 3000);
296 fIntegralC->GetXaxis()->SetTitle(
"Area(ADC#*ticks)");
298 fBaselineC = tfs->make<TH1F>(
"fBaselineC",
"", 500, -10., 10.);
299 fBaselineC->GetXaxis()->SetTitle(
"Area(ADC#*ticks)");
301 fAreaInt = tfs->make<TH1F>(
"fAreaInt",
"Area/Int", 100,0.,2.);
303 fnhwC = tfs->make<TH1F>(
"fnhwC",
"", 10, 0, 10);
304 fnhwC->GetXaxis()->SetTitle(
"n hits per wire");
305 fnhwC->GetYaxis()->SetTitle(
"wires");
306 fHeightI2 = tfs->make<TH1F>(
"fHeightI2",
"height(ADC#)", 100, 0, 100);
307 fWidthI2 = tfs->make<TH1F>(
"fWidthI2",
"width(samples)", 100, 0, 100);
308 fNoiseI2 = tfs->make<TH1F>(
"fNoiseI2",
"Noise Area(ADC#)", 100, 0, 100);
309 fHeightI1 = tfs->make<TH1F>(
"fHeightI1",
"height(ADC#)", 100, 0, 100);
310 fWidthI1 = tfs->make<TH1F>(
"fWidthI1",
"width(samples)", 100, 0, 100);
311 fNoiseI1 = tfs->make<TH1F>(
"fNoiseI1",
"Noise Area(ADC#)", 100, 0, 100);
328 std::ofstream
output(
"areaFit.out");
333 art::ServiceHandle<geo::Geometry> geom;
349 art::Handle< std::vector<recob::Wire> > wireVecHandle;
355 art::FindOneP<raw::RawDigit> RawDigits
362 std::vector<float> holder;
363 std::vector<short> rawadc;
365 std::vector<float> startTimes;
366 std::vector<float> maxTimes;
367 std::vector<float> endTimes;
368 std::vector<float> peakHeight;
369 std::vector<float> hitrms;
370 std::vector<double> charge;
373 std::stringstream numConv;
375 unsigned int hwC(0),lwC(5728);
376 unsigned int hwI2(0),lwI2(5728);
377 unsigned int hwI1(0),lwI1(2112);
379 unsigned int nw1hitC(0),nw1hitI2(0),nw1hitI1(0);
381 for(
int jw=0;jw<5600;jw++)
384 for(
int jw=0;jw<5600;jw++)
387 for(
int jw=0;jw<5600;jw++)
391 unsigned int nhitsC(0),nhitsI1(0),nhitsI2(0);
393 unsigned int nnhitsC(0),nnhitsI1(0),nnhitsI2(0);
396 unsigned int minWireC,maxWireC;
397 if(
fThetaAngle==45) {minWireC=2539; maxWireC=3142;}
399 if(
fThetaAngle==20) {minWireC=2539; maxWireC=4000;}
400 if(
fThetaAngle==40) {minWireC=2539; maxWireC=3190;}
401 if(
fThetaAngle==60) {minWireC=2539; maxWireC=2905;}
402 if(
fThetaAngle==70) {minWireC=2539; maxWireC=2805;}
403 if(
fThetaAngle==80) {minWireC=2539; maxWireC=2740;}
407 = art::ServiceHandle<lariov::ChannelStatusService>()->GetProvider();
412 unsigned int minWireI2=2539;
413 unsigned int maxWireI2=4700;
414 unsigned int minDrift=850;
415 unsigned int maxDrift=1500;
419 for(
size_t wireIter = 0; wireIter < wireVecHandle->size(); wireIter++)
424 art::Ptr<recob::Wire> wire(wireVecHandle, wireIter);
425 art::Ptr<raw::RawDigit> rawdigits = RawDigits.at(wireIter);
428 channel = wire->Channel();
430 std::vector<float> signal(wire->Signal());
434 std::vector<geo::WireID> wids = geom->ChannelToWire(channel);
448 channel = rawdigits->Channel();
451 std::vector<geo::WireID> widVec = geom->ChannelToWire(channel);
452 size_t iwire = widVec[0].Wire;
461 int pedestal = (int)rawdigits->GetPedestal();
462 raw::Uncompress(rawdigits->ADCs(), rawadc, pedestal, rawdigits->Compression());
468 mf::LogDebug(
"ICARUSHitFinder") <<
" pedestal " <<rawdigits->GetPedestal() << std::endl;
475 if(plane == 0) holder[
bin]=-holder[
bin];
480 if(plane==0&&iwire<lwI1) lwI1=iwire;
481 if(plane==0&&iwire>hwI1) hwI1=iwire;
482 if(plane==1&&iwire<lwI2) lwI2=iwire;
483 if(plane==1&&iwire>hwI2) hwI2=iwire;
484 if(plane==2&&iwire<lwC) lwC=iwire;
485 if(plane==2&&iwire>hwC) hwC=iwire;
498 bool channelSwitch =
false;
500 for(
auto it = BadChannels.begin(); it != BadChannels.end(); it++)
504 channelSwitch =
true;
509 if(channelSwitch==
false)
527 std::vector<geo::WireID> wids = geom->ChannelToWire(channel);
529 std::vector<float> tempVec = holder;
530 recob::Wire::RegionsOfInterest_t::datarange_t rangeData(
size_t(0),std::move(tempVec));
532 fHitFinderTool->findHitCandidates(rangeData, 0,channel,0,hitCandidateVec);
534 for(
auto& hitCand : hitCandidateVec) {
535 expandHit(hitCand,holder,hitCandidateVec);
541 fHitFinderTool->MergeHitCandidates(rangeData, hitCandidateVec, mergedCandidateHitVec);
556 for(
auto& mergedCands : mergedCandidateHitVec)
567 mf::LogDebug(
"ICARUSHitFinder") <<
" adding localmean " << mean << std::endl;
571 if (endT - startT < 5)
continue;
578 int nGausForFit = mergedCands.size();
583 double chi2PerNDF(0.);
587 const int npk=mergedCands.size();
589 peakParamsVec.clear();
600 if (!(chi2PerNDF < std::numeric_limits<double>::infinity()))
610 if (chi2PerNDF < 10.)
611 fChi2->Fill(chi2PerNDF);
615 peakParamsLong.clear();
621 if(chi2Long<chi2PerNDF&&chi2Long>0.1) {
622 fChi2->Fill(chi2Long);
623 peakParamsVec=peakParamsLong;
625 else {
fChi2->Fill(chi2PerNDF);
635 for(
unsigned int jhit=0;jhit<mergedCands.size(); jhit++)
642 if(jhit>=1&&startInt<mergedCands[jhit-1].stopTick) startInt=mergedCands[jhit-1].stopTick;
643 if(jhit<mergedCands.size()-1&&endInt>mergedCands[jhit+1].startTick) endInt=mergedCands[jhit+1].startTick;
646 float peakAmp, peakMean, peakLeft, peakRight,
peakBaseline;
648 float peakMeanErr, peakAmpErr;
653 Func.SetParameter(0, mergedCands.size());
660 peakAmp = peakParams.peakAmplitude;
661 peakMean = peakParams.peakCenter;
663 peakLeft = peakParams.peakTauLeft;
664 peakRight = peakParams.peakTauRight;
665 peakBaseline = peakParams.peakBaseline;
669 if (std::isnan(peakAmp))
676 peakAmpErr = peakParams.peakAmplitudeError;
677 peakMeanErr = peakParams.peakCenterError;
679 Func.SetParameter(1+5*jhit,peakBaseline);
680 Func.SetParameter(2+5*jhit,peakAmp);
681 Func.SetParameter(3+5*jhit,peakMean);
682 Func.SetParameter(4+5*jhit,peakRight);
683 Func.SetParameter(5+5*jhit,peakLeft);
685 intBaseline+=(endInt-startInt)*peakBaseline;
689 fitCharge=Func.Integral(startInt,endInt)-(endInt-startInt)*
localmeans[jhit];
693 mf::LogWarning(
"ICARUSHitFinder") <<
"Icarus numerical 32 failed";
694 fitCharge=std::accumulate(holder.begin() + (int) startInt, holder.begin() + (int) endInt, 0.)-(endInt-startInt)*
localmeans[jhit];
701 FuncLong.SetParameter(0, mergedCands.size());
709 peakAmp = peakParams.peakAmplitude;
710 peakMean = peakParams.peakCenter;
712 peakLeft = peakParams.peakTauLeft;
713 peakRight = peakParams.peakTauRight;
714 peakBaseline = peakParams.peakBaseline;
715 intBaseline+=(endInt-startInt)*peakBaseline;
716 peakAmpErr = peakParams.peakAmplitudeError;
717 peakMeanErr = peakParams.peakCenterError;
719 FuncLong.SetParameter(1+7*jhit,peakBaseline);
720 FuncLong.SetParameter(2+7*jhit,peakAmp);
721 FuncLong.SetParameter(3+7*jhit,peakMean);
722 FuncLong.SetParameter(4+7*jhit,peakRight);
723 FuncLong.SetParameter(5+7*jhit,peakLeft);
725 FuncLong.SetParameter(7+7*jhit,peakSlope);
729 { fitCharge=FuncLong.Integral(startInt,endInt)-(endInt-startInt)*
localmeans[jhit];
733 {mf::LogWarning(
"ICARUSHitFinder") <<
"Icarus numerical integration failed";
734 fitCharge=std::accumulate(holder.begin() + (int) startInt, holder.begin() + (int) endInt, 0.)-(endInt-startInt)*
localmeans[jhit];
737 if(isnan(fitCharge)&&!islong) fitCharge=std::accumulate(holder.begin() + (int) startInt, holder.begin() + (int) endInt, 0.);
738 if(isnan(fitCharge)&&islong) fitCharge=std::accumulate(holder.begin() + (int) startInt, holder.begin() + (int) endInt, 0.);
743 float totSig=std::accumulate(holder.begin()+ (int) startInt, holder.begin()+ (int) endInt, 0.)-(endInt-startInt)*
localmeans[jhit];
756 (peakLeft+peakRight)/2.,
770 mf::LogDebug(
"ICARUSHitFinder") <<
" fitcharge " << fitCharge <<
" totSig " << totSig << std::endl;
776 bool wireWindowC=iWire>=minWireC&&iWire<=maxWireC;
777 bool outWireWindowC=iWire<=minWireC||iWire>=maxWireC;
781 if(nghC==1) nw1hitC++;
786 wCharge[
iWire]+=fitCharge;
794 if(tpc==0&&cryostat==0&&outWireWindowC) {
795 nnhitsC++;
fNoiseC->Fill(peakAmp); }
799 if(cryostat==0&&tpc==0)
801 fAreaC->Fill(wCharge[iwire]);
802 if(cryostat==0&&tpc==0)
805 if(cryostat==0&&tpc==0)
807 output << iwire <<
" " <<wInt[iwire] << std::endl;
808 if(wInt[iwire]>0&&cryostat==0&&tpc==0)
809 fAreaInt->Fill(wCharge[iwire]/wInt[iwire]);
818 if(plane==0||plane==1) {
819 for(
auto& mergedCands : mergedCandidateHitVec)
821 for(
size_t jh=0;jh<mergedCands.size();jh++) {
827 mergedCands[jh].startTick,
828 mergedCands[jh].stopTick,
829 mergedCands[jh].hitSigma,
830 mergedCands[jh].hitCenter,
832 mergedCands[jh].hitHeight,
834 std::accumulate(holder.begin() + (int) mergedCands[jh].startTick, holder.begin() + (int) mergedCands[jh].stopTick, 0.),
836 std::accumulate(holder.begin() + (int) mergedCands[jh].startTick, holder.begin() + (int) mergedCands[jh].stopTick, 0.),
840 int(mergedCands[jh].stopTick-mergedCands[jh].startTick+1)
844 bool driftWindow=(mergedCands[jh].hitCenter)>=minDrift&&(mergedCands[jh].hitCenter)<=maxDrift;
845 bool wireWindowI2=iWire>=minWireI2&&iWire<=maxWireI2;
846 bool outDriftWindow=(mergedCands[jh].hitCenter)<=minDrift||(mergedCands[jh].hitCenter)>=maxDrift;
847 bool outWireWindowI2=iWire<=minWireI2||iWire>=maxWireI2;
850 if(plane==0&&driftWindow) {
853 if(nghI1==1) nw1hitI1++;
856 fHeightI1->Fill(mergedCands[jh].hitHeight);
857 fWidthI1->Fill(mergedCands[jh].hitSigma);
859 if(plane==1&&wireWindowI2) {
862 if(nghI2==1) nw1hitI2++;
864 fHeightI2->Fill(mergedCands[jh].hitHeight);
865 fWidthI2->Fill(mergedCands[jh].hitSigma);
869 if(plane==0) nhitsI1++;
870 if(plane==1) nhitsI2++;
872 if(plane==0&&tpc==0&&cryostat==0&&outDriftWindow) {nnhitsI1++;
fNoiseI1->Fill(mergedCands[jh].hitHeight); }
873 if(plane==1&&tpc==0&&cryostat==0&&outWireWindowI2) { nnhitsI2++;
fNoiseI2->Fill(mergedCands[jh].hitHeight); }
886 for(
unsigned int jw=minWireC;jw<maxWireC;jw++)
887 fnhwC->Fill(nhWire[jw]);
907 std::vector<reco_tool::ICandidateHitFinder::HitCandidate>::iterator hiter;
908 std::vector<reco_tool::ICandidateHitFinder::HitCandidate> hlist;
911 for(
unsigned int j=0;j<how.size();j++)
925 for(hiter=hlist.begin();hiter!=hlist.end();hiter++)
935 for(
int l=0;l<nsamp/2;l++)
937 if(first-nsamp/2+l<4095) {
938 if(holder[first-nsamp/2+l+1]-holder[first-nsamp/2+l]>0) upordown++;
939 else if(holder[first-nsamp/2+l+1]-holder[first-nsamp/2+l]<0) upordown--;
958 for(hiter=hlist.begin();hiter!=hlist.end();hiter++)
968 for(
int l=0;l<nsamp/2;l++)
970 if(last+nsamp/2-l>0) {
971 if(holder[last+nsamp/2-l]-holder[last+nsamp/2-l-1]>0) upordown++;
972 else if(holder[last+nsamp/2-l]-holder[last+nsamp/2-l-1]<0) upordown--;
988 const int outofbounds=9999;
990 float samples1[bigw];
991 float samples2[bigw];
997 int startTick=h.front().startTick;
998 int stopTick=h.back().stopTick;
1001 unsigned int shift1=0;
1002 unsigned int shift2=0;
1007 for(
unsigned int j=0;j<how.size();j++)
1009 std::vector<reco_tool::ICandidateHitFinder::HitCandidate> h2=how[j];
1010 if(h2.front().startTick!=h.front().startTick)
1011 hlist.push_back(h2);
1015 for(
unsigned int i=0;i<bigw;i++)
1018 for(
unsigned int j=0;j<hlist.size();j++)
1020 std::vector<reco_tool::ICandidateHitFinder::HitCandidate> h2=hlist[j];
1021 if(startTick-i-shift1 >= h2.front().startTick && startTick-i-shift1 <= h2.back().stopTick)
1022 shift1+=h2.back().stopTick-h2.front().startTick+1;
1023 else if(stopTick+i+shift2 >= h2.front().startTick && stopTick+i+shift2 <= h2.back().stopTick)
1024 shift2+=h2.back().stopTick-h2.front().startTick+1;
1029 samples1[i]=holder[h.front().startTick-i-shift1];
1033 if(stopTick+i+shift2<=4095)
1034 samples2[i]=holder[h.back().stopTick+i+shift2];
1036 samples2[i]=outofbounds;
1040 for(
int j=0;j<meanw;j++)
1042 if(samples1[j]==outofbounds) foundborder1=1;
1043 if(samples2[j]==outofbounds) foundborder2=1;
1045 if(!foundborder1) count1+=samples1[j];
1046 if(!foundborder2) count2+=samples2[j];
1052 for(
int j=0;j<bigw-meanw;j++)
1054 if(count1<min1) min1=count1;
1055 if(samples1[j+meanw]==outofbounds) foundborder1=1;
1056 if(!foundborder1) count1+=samples1[j+meanw]-samples1[j];
1058 if(count2<min2) min2=count2;
1059 if(samples2[j+meanw]==outofbounds) foundborder2=1;
1060 if(!foundborder2) count2+=samples2[j+meanw]-samples2[j];
1062 if(foundborder1 && foundborder2)
break;
1064 if(count1<min1) min1=count1;
1065 if(count2<min2) min2=count2;
1069 if((foundborder1 && !foundborder2) || (shift1 && !shift2))
1070 localmean=((float) min2)/meanw;
1071 else if((!foundborder1 && foundborder2) || (!shift1 && shift2))
1072 localmean=((float) min1)/meanw;
1074 localmean=(min1>min2)?((
float) min1)/meanw :((
float) min2)/meanw;
1083 int& NDF,
int iWire)
const
1087 TH1F* fHistogram=
new TH1F(
"",
"",roiSignalVec.size(),0.,roiSignalVec.size());;
1089 std::string wireName =
"PeakFitterHitSignal_" +
std::to_string(iWire);
1090 fHistogram->SetName(wireName.c_str());
1092 if (hitCandidateVec.empty())
return;
1095 chi2PerNDF = std::numeric_limits<double>::infinity();
1097 int startTime = hitCandidateVec.front().startTick-
fFittingRange;
1098 int endTime = hitCandidateVec.back().stopTick+
fFittingRange;
1099 if(startTime<0) startTime=0;
1100 if(endTime>4095) endTime=4095;
1101 int roiSize = endTime - startTime;
1106 if (roiSize > fHistogram->GetNbinsX())
1108 std::string histName =
"PeakFitterHitSignal_" +
std::to_string(iWire);
1109 fHistogram =
new TH1F(histName.c_str(),
"",roiSize,0.,roiSize);
1113 fHistogram->Reset();
1114 for(
int idx = 0; idx < roiSize; idx++)
1115 fHistogram->SetBinContent(idx+1,roiSignalVec.at(startTime+idx));
1116 for(
int idx = 0; idx < roiSize; idx++)
1117 fHistogram->SetBinError(idx+1,2.4);
1128 Func.FixParameter(0, hitCandidateVec.size());
1131 for(
auto const& candidateHit : hitCandidateVec)
1133 double const peakMean = candidateHit.hitCenter - float(startTime);
1134 double const peakWidth = candidateHit.hitSigma;
1139 double const amplitude = candidateHit.hitHeight;
1143 Func.SetParameter(1+parIdx,0);
1144 Func.SetParameter(2+parIdx, amplitude);
1145 Func.SetParameter(3+parIdx, peakMean);
1146 Func.SetParameter(4+parIdx,peakWidth);
1147 Func.SetParameter(5+parIdx,peakWidth);
1149 Func.SetParLimits(1+parIdx, -5, 5);
1150 Func.SetParLimits(2+parIdx, 0.1 * amplitude, 10. * amplitude);
1151 Func.SetParLimits(3+parIdx, peakMean-peakWidth,peakMean+peakWidth);
1162 { fitResult = fHistogram->Fit(&Func,
"QNWB",
"", 0., roiSize);
1165 {mf::LogWarning(
"GausHitFinder") <<
"Fitter failed finding a hit";}
1175 NDF = roiSize-5*hitCandidateVec.size();
1176 chi2PerNDF = (Func.GetChisquare() / NDF);
1189 peakParamsVec0.clear();
1191 for(
size_t idx = 0; idx < hitCandidateVec.size(); idx++)
1195 peakParams.peakAmplitude = Func.GetParameter(2+parIdx);
1196 peakParams.peakAmplitudeError = Func.GetParError(2+parIdx);
1197 peakParams.peakCenter = Func.GetParameter(3+parIdx) + float(startTime);
1198 peakParams.peakCenterError = Func.GetParError(3+parIdx);
1200 peakParams.peakTauRight = Func.GetParameter(4+parIdx);
1201 peakParams.peakTauRightError = Func.GetParError(4+parIdx);
1202 peakParams.peakTauLeft = Func.GetParameter(5+parIdx);
1203 peakParams.peakTauLeftError = Func.GetParError(5+parIdx);
1204 peakParams.peakBaseline = Func.GetParameter(1+parIdx);
1205 peakParams.peakBaselineError = Func.GetParError(1+parIdx);
1206 peakParams.peakFitWidth =0;
1207 peakParams.peakFitWidthError = 0;
1208 peakParams.peakSlope = 0;
1209 peakParams.peakSlopeError = 0;
1210 peakParamsVec.emplace_back(peakParams);
1218 bool writeWaveform=
false;
1220 TFile *f =
new TFile(
"fitICARUS.root",
"UPDATE");
1221 fHistogram->Write();
1226 fHistogram->Delete();
1234 int& NDF,
int iWire)
const
1236 TH1F* fHistogram=
new TH1F(
"",
"",roiSignalVec.size(),0.,roiSignalVec.size());;
1237 std::string wireName =
"PeakFitterHitSignal_" +
std::to_string(iWire);
1238 fHistogram->SetName(wireName.c_str());
1240 if (hitCandidateVec.empty())
return;
1243 chi2PerNDF = std::numeric_limits<double>::infinity();
1245 int startTime = hitCandidateVec.front().startTick-
fFittingRange;
1246 int endTime = hitCandidateVec.back().stopTick+
fFittingRange;
1247 if(startTime<0) startTime=0;
1248 if(endTime>4095) endTime=4095;
1250 int roiSize = endTime - startTime;
1255 if (roiSize > fHistogram->GetNbinsX())
1257 std::string histName =
"PeakFitterHitSignal_" +
std::to_string(iWire);
1258 fHistogram =
new TH1F(histName.c_str(),
"",roiSize,0.,roiSize);
1259 fHistogram->Sumw2();
1262 fHistogram->Reset();
1263 for(
int idx = 0; idx < roiSize; idx++)
1264 fHistogram->SetBinContent(idx+1,roiSignalVec.at(startTime+idx));
1267 std::string equation =
"gaus(0)";
1277 Func.FixParameter(0,hitCandidateVec.size());
1280 for(
auto const& candidateHit : hitCandidateVec)
1282 double const peakMean = candidateHit.hitCenter - float(startTime);
1283 double const peakWidth = candidateHit.hitSigma;
1284 double const amplitude = candidateHit.hitHeight;
1286 Func.SetParameter(1+parIdx,0);
1287 Func.SetParameter(2+parIdx, amplitude);
1288 Func.SetParameter(3+parIdx, peakMean);
1289 Func.SetParameter(4+parIdx,peakWidth);
1290 Func.SetParameter(5+parIdx,peakWidth);
1291 Func.SetParameter(6+parIdx,2*peakWidth);
1292 Func.SetParameter(7+parIdx,0);
1295 Func.SetParLimits(1+parIdx, -5, 5);
1296 Func.SetParLimits(2+parIdx, 0.1 * amplitude, 10. * amplitude);
1297 Func.SetParLimits(3+parIdx, peakMean-peakWidth,peakMean+peakWidth);
1299 Func.SetParLimits(5+parIdx, std::max(
fMinWidth, 0.01 * peakWidth), 4 * peakWidth);
1300 Func.SetParLimits(6+parIdx, 0,4*peakWidth);
1301 Func.SetParLimits(7+parIdx, -1,1);
1306 int fitResult { -1 };
1308 { fitResult = fHistogram->Fit(&Func,
"QNWB",
"", 0., roiSize);
1311 {mf::LogWarning(
"GausHitFinder") <<
"Fitter failed finding a hit";}
1314 std::cout <<
" long fit cannot converge " << iWire << std::endl;
1318 NDF = roiSize-7*hitCandidateVec.size();
1319 chi2PerNDF = (Func.GetChisquare() / NDF);
1322 peakParamsVec.clear();
1323 for(
size_t idx = 0; idx < hitCandidateVec.size(); idx++)
1327 peakParams.peakAmplitude = Func.GetParameter(2+parIdx);
1328 peakParams.peakAmplitudeError = Func.GetParError(2+parIdx);
1329 peakParams.peakCenter = Func.GetParameter(3+parIdx) + float(startTime);
1330 peakParams.peakCenterError = Func.GetParError(3+parIdx);
1332 peakParams.peakTauRight = Func.GetParameter(4+parIdx);
1333 peakParams.peakTauRightError = Func.GetParError(4+parIdx);
1334 peakParams.peakTauLeft = Func.GetParameter(5+parIdx);
1335 peakParams.peakTauLeftError = Func.GetParError(5+parIdx);
1336 peakParams.peakFitWidth = Func.GetParameter(6+parIdx);
1337 peakParams.peakFitWidthError = Func.GetParError(6+parIdx);
1338 peakParams.peakSlope = Func.GetParameter(7+parIdx);
1339 peakParams.peakSlopeError = Func.GetParError(7+parIdx);
1340 peakParams.peakBaseline = Func.GetParameter(1+parIdx);
1341 peakParams.peakBaselineError = Func.GetParError(1+parIdx);
1343 peakParamsVec.emplace_back(peakParams);
1351 bool writeWaveform=
false;
1353 TFile *f =
new TFile(
"fitICARUS.root",
"UPDATE");
1354 fHistogram->Write();
1359 fHistogram->Delete();
1366 int const npeaks=(int)(par[0]);
1368 for(
int jp=0;jp<npeaks;jp++)
1369 fitval += par[5*jp+1]+par[5*jp+2]*TMath::Exp(-(x[0]-par[5*jp+3])/par[5*jp+4])/(1+TMath::Exp(-(x[0]-par[5*jp+3])/par[5*jp+5]));
1374 auto const nPeaks =
static_cast<std::size_t
>(par[0]);
1375 Double_t fitval = 0.0;
1376 for(std::size_t jp = 0; jp < nPeaks; ++jp) {
1377 Double_t
const* parj = par + (7 * jp);
1378 int const smax = std::floor(parj[6]);
1379 if (smax == 0)
continue;
1380 double const neg_dxj = -(x[0] - parj[3]);
1381 fitval += (smax + parj[7] * (smax*(smax-1)/2))
1383 parj[1]+parj[2]*
std::exp(neg_dxj/parj[4])
1384 / (1.0 +
std::exp(neg_dxj/parj[5]))
1393 int nb=histo->GetNbinsX();
1394 double wb=histo->GetBinWidth(0);
1397 for( jp=1;jp<nb;jp++) {
1398 if(histo->GetBinContent(jp)==0)
break;
1400 double fv=(func)(xb);
1401 double hv=histo->GetBinContent(jp);
1403 double cv=dv/(histo->GetBinError(jp));
1418 for( jp=1;jp<nb;jp++) {
1420 double hv=holder[jp];
1438 #endif //ICARUSHitFinder_H
const geo::GeometryCore * fGeometry
size_t fMaxMultiHit
maximum hits for multi fit
virtual TF1 * CreateFunction(size_t nFunc) const
Creates and returns the function with specified number of peaks.
Utilities related to art service access.
std::set< raw::ChannelID_t > ChannelSet_t
Type of set of channel IDs.
std::vector< int > fLongPulseWidthVec
Sets width of hits used to describe long pulses.
Encapsulate the construction of a single cyostat.
process_name opflash particleana ie x
Declaration of signal hit object.
unsigned int PlaneID_t
Type for the ID number.
struct ICARUSPeakFitParams{float peakCenter ICARUSPeakFitParams_t
CryostatID_t Cryostat
Index of cryostat.
Definition of basic raw digits.
void produce(art::Event &evt)
void reconfigure(fhicl::ParameterSet const &p)
WireID_t Wire
Index of the wire within its plane.
double fMinWidth
minimum initial width for ICARUS fit
ICARUShitFitCache(std::string const &new_name="ICARUShitFitCache")
Constructor (see base class constructor).
virtual ChannelSet_t BadChannels() const =0
Returns a copy of set of bad channel IDs for the current run.
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.
art::InputTag fDigitModuleLabel
void computeBestLocalMean(std::vector< reco_tool::ICandidateHitFinder::HitCandidate > h, std::vector< float > holder, reco_tool::ICandidateHitFinder::MergeHitCandidateVec how, float &localmean)
double fMaxWidthMult
multiplier for max width for ICARUS fit
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
double ComputeNullChiSquare(std::vector< float >) const
A set of TF1 linear sum of base functions (Gaussians)
ICARUSlongHitFitCache fLongFitCache
Cached functions for long hits.
Class managing the creation of a new recob::Hit object.
Helper functions to create a hit.
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
A class handling a collection of hits and its associations.
int fFittingRange
semi-width of interval where to fit hit
std::unique_ptr< reco_tool::ICandidateHitFinder > fHitFinderTool
For finding candidate hits.
Collect all the RawData header files together.
ICARUSlongHitFitCache(std::string const &new_name="ICARUSlongHitFitCache")
Constructor (see base class constructor).
std::vector< double > localmeans
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.
Class providing information about the quality of channels.
virtual TF1 * Get(size_t nFunc)
Returns a function sum of nFunc base functions.
PlaneID_t Plane
Index of the plane within its TPC.
ICARUSHitFinder(fhicl::ParameterSet const &pset)
Description of geometry of one entire detector.
static Double_t fitlong(Double_t const *x, Double_t const *par)
ICARUS hit shape.
Definition of data types for geometry description.
void put_into(art::Event &)
Moves the data into an event.
ICARUShitFitCache fFitCache
Cached functions for multi-peak fits.
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
virtual TF1 * CreateFunction(size_t nFunc) const
Creates and returns the function with specified number of peaks.
Encapsulate the construction of a single detector plane.
std::vector< ICARUSPeakFitParams_t > ICARUSPeakParamsVec
std::string to_string(WindowPattern const &pattern)
virtual std::string FunctionName(size_t nFunc) const
Returns a name for the function with nFunc base functions.
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG simSlidingORM6O6 effSlidingORW output
void expandHit(reco_tool::ICandidateHitFinder::HitCandidate &h, std::vector< float > holder, std::vector< reco_tool::ICandidateHitFinder::HitCandidate > how)
Interface for experiment-specific channel quality info provider.
This provides an interface for tools which are tasked with finding candidate hits on input waveforms...
Provide caches for TF1 functions to be used with ROOT fitters.
double ComputeChiSquare(TF1 func, TH1 *histo) const
std::vector< int > fLongMaxHitsVec
maximum Chisquared / NDF allowed for a hit to be saved
Customized function cache for ICARUS long hit shape.
Customized function cache for ICARUS hit shape.
art::ServiceHandle< art::TFileService > tfs
unsigned int ChannelID_t
Type representing the ID of a readout channel.
void findLongPeakParameters(const std::vector< float > &, const reco_tool::ICandidateHitFinder::HitCandidateVec &, ICARUSPeakParamsVec &, double &, int &, int) const
TPCID_t TPC
Index of the TPC within its cryostat.
Interface for experiment-specific service for channel quality info.
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
std::string fHitLabelName
int fIntegratingRange
semi-width of interval where to integrate fitting function
recob::Hit && move()
Prepares the constructed hit to be moved away.
void findMultiPeakParameters(const std::vector< float > &, const reco_tool::ICandidateHitFinder::HitCandidateVec &, ICARUSPeakParamsVec &, double &, int &, int) const
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::string fCalDataModuleLabel
Encapsulate the construction of a single detector plane.
static Double_t fitf(Double_t const *x, Double_t const *par)
ICARUS hit shape.