All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PeakFitterICARUS_tool.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file PeakFitterICARUS.cc
3 /// \author T. Usher
4 ////////////////////////////////////////////////////////////////////////
5 
7 
8 #include "art/Utilities/ToolMacros.h"
9 #include "art/Utilities/make_tool.h"
10 #include "messagefacility/MessageLogger/MessageLogger.h"
11 #include "cetlib_except/exception.h"
14 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
15 
16 #include <cmath>
17 #include <fstream>
18 #include "TH1F.h"
19 #include "TF1.h"
20 
21 namespace reco_tool
22 {
23 
25 {
26 public:
27  explicit PeakFitterICARUS(const fhicl::ParameterSet& pset);
28 
29  void configure(const fhicl::ParameterSet& pset) override;
30 
31  void findPeakParameters(const std::vector<float>&,
34  double&,
35  int&) const override;
36 
37  static Double_t fitf(Double_t *x, Double_t *par);
38 
39 private:
40  // Member variables from the fhicl file
41  double fMinWidth; ///< minimum initial width for ICARUS fit
42  double fMaxWidthMult; ///< multiplier for max width for ICARUS fit
43  double fPeakRange; ///< set range limits for peak center
44  double fAmpRange; ///< set range limit for peak amplitude
45 
46  mutable TH1F fHistogram;
47  mutable TF1 fFit; ///< Cache of fit functions (one so far).
48 
49  const geo::GeometryCore* fGeometry = lar::providerFrom<geo::Geometry>();
50 };
51 
52 //----------------------------------------------------------------------
53 // Constructor.
54 PeakFitterICARUS::PeakFitterICARUS(const fhicl::ParameterSet& pset)
55  : fFit("ICARUSfunc", fitf, 0.0, 1.0, 5) // 5 parameters, fake range
56 {
57  configure(pset);
58 }
59 
60 void PeakFitterICARUS::configure(const fhicl::ParameterSet& pset)
61 {
62  // Start by recovering the parameters
63  fMinWidth = pset.get<double>("MinWidth", 0.5);
64  fMaxWidthMult = pset.get<double>("MaxWidthMult", 3.);
65  fPeakRange = pset.get<double>("PeakRangeFact", 2.);
66  fAmpRange = pset.get<double>("PeakAmpRange", 2.);
67 
68  fHistogram = TH1F("PeakFitterHitSignal","",500,0.,500.);
69 
70  fHistogram.Sumw2();
71 
72  return;
73 }
74 
75 // --------------------------------------------------------------------------------------------
76 void PeakFitterICARUS::findPeakParameters(const std::vector<float>& roiSignalVec,
77  const ICandidateHitFinder::HitCandidateVec& hitCandidateVec,
78  PeakParamsVec& peakParamsVec,
79  double& chi2PerNDF,
80  int& NDF) const
81 {
82  // The following is a translation of the original FitICARUSs function in the original
83  // GausHitFinder module originally authored by Jonathan Asaadi
84  //
85  // *** NOTE: this algorithm assumes the reference time for input hit candidates is to
86  // the first tick of the input waveform (ie 0)
87  //
88  if (hitCandidateVec.empty()) return;
89 
90  // in case of a fit failure, set the chi-square to infinity
91  chi2PerNDF = std::numeric_limits<double>::infinity();
92 
93  int startTime = hitCandidateVec.front().startTick;
94  int endTime = hitCandidateVec.back().stopTick;
95  int roiSize = endTime - startTime;
96 
97  // Check to see if we need a bigger histogram for fitting
98  if (roiSize > fHistogram.GetNbinsX())
99  {
100  std::string histName = "PeakFitterHitSignal_" + std::to_string(roiSize);
101  fHistogram = TH1F(histName.c_str(),"",roiSize,0.,roiSize);
102  fHistogram.Sumw2();
103  }
104 
105  for(int idx = 0; idx < roiSize; idx++) fHistogram.SetBinContent(idx+1,roiSignalVec.at(startTime+idx));
106 
107  // for(int idx = 0; idx < roiSize; idx++)
108  // std::cout << " bin " << idx << " fHistogram " << fHistogram.GetBinContent(idx+1) << std::endl;
109 
110 
111  // ### Setting the parameters for the ICARUS Fit ###
112  //int parIdx(0);
113  for(auto& candidateHit : hitCandidateVec)
114  {
115  double peakMean = candidateHit.hitCenter - float(startTime);
116  double peakWidth = candidateHit.hitSigma;
117  // std::cout << " peakWidth " << peakWidth << std::endl;
118  // std::cout << " hitcenter " << candidateHit.hitCenter << " starttime " << startTime <<std::endl;
119 
120 
121  double amplitude = candidateHit.hitHeight;
122  double meanLowLim = std::max(peakMean - fPeakRange * peakWidth, 0.);
123  double meanHiLim = std::min(peakMean + fPeakRange * peakWidth, double(roiSize));
124  // std::cout << " amplitude " << amplitude << std::endl;
125  // std::cout << " peakMean " << peakMean << std::endl;
126 
127  fFit.SetParameter(0,0);
128  fFit.SetParameter(1, amplitude);
129  fFit.SetParameter(2, peakMean);
130  fFit.SetParameter(3,peakWidth/2);
131  fFit.SetParameter(4,peakWidth/2);
132 
133  fFit.SetParLimits(0, -5, 5);
134  fFit.SetParLimits(1, 0.1 * amplitude, 10. * amplitude);
135  fFit.SetParLimits(2, meanLowLim,meanHiLim);
136  fFit.SetParLimits(3, std::max(fMinWidth, 0.1 * peakWidth), fMaxWidthMult * peakWidth);
137  fFit.SetParLimits(4, std::max(fMinWidth, 0.1 * peakWidth), fMaxWidthMult * peakWidth);
138 
139  // std::cout << " peakWidth limits " << std::max(fMinWidth, 0.1 * peakWidth) <<" " << fMaxWidthMult * peakWidth << std::endl;
140  // std::cout << " peakMean limits " << meanLowLim <<" " << meanHiLim << std::endl;
141 
142  }
143 
144  int fitResult(-1);
145 
146  // the range of the fit does not matter since we specify the fitting range
147  // explicitly (we do NOT use option "R")
148  try
149  { fitResult = fHistogram.Fit(&fFit,"QNWB","", 0., roiSize);}
150  catch(...)
151  {mf::LogWarning("GausHitFinder") << "Fitter failed finding a hit";}
152 
153  if(fitResult!=0)
154 // std::cout << " fit cannot converge " << std::endl;
155  // ##################################################
156  // ### Getting the fitted parameters from the fit ###
157  // ##################################################
158  NDF = roiSize-5;
159  chi2PerNDF = (fFit.GetChisquare() / NDF);
160 
161  // std::cout << " chi2 " << fFit.GetChisquare() << std::endl;
162  // std::cout << " ndf " << NDF << std::endl;
163 
164  // std::cout << " chi2ndf " << chi2PerNDF<< std::endl;
165  //parIdx = 0;
166  for(size_t idx = 0; idx < hitCandidateVec.size(); idx++)
167  {
168  PeakFitParams_t peakParams;
169 
170  peakParams.peakAmplitude = fFit.GetParameter(1);
171  peakParams.peakAmplitudeError = fFit.GetParError(1);
172  peakParams.peakCenter = fFit.GetParameter(2) + float(startTime);
173  peakParams.peakCenterError = fFit.GetParError(2);
174  //std::cout << " rising time " << fFit.GetParameter(3) << " falling time " <<fFit.GetParameter(4) << std::endl;
175  peakParams.peakTauLeft = fFit.GetParameter(3);
176  peakParams.peakTauLeftError = fFit.GetParError(3);
177  peakParams.peakTauRight = fFit.GetParameter(4);
178  peakParams.peakTauRightError = fFit.GetParError(4);
179  peakParams.peakBaseline = fFit.GetParameter(0);
180  peakParams.peakBaselineError = fFit.GetParError(0);
181 
182  peakParamsVec.emplace_back(peakParams);
183 
184  }
185 
186 }
187 
188 Double_t PeakFitterICARUS::fitf(Double_t *x, Double_t *par)
189  {
190  // Double_t arg = 0;
191 
192  Double_t fitval = par[0]+par[1]*TMath::Exp(-(x[0]-par[2])/par[3])/(1+TMath::Exp(-(x[0]-par[3])/par[4]));
193  return fitval;
194  }
195 DEFINE_ART_CLASS_TOOL(PeakFitterICARUS)
196 }
double fAmpRange
set range limit for peak amplitude
Utilities related to art service access.
process_name opflash particleana ie x
void configure(const fhicl::ParameterSet &pset) override
double fMinWidth
minimum initial width for ICARUS fit
PeakFitterICARUS(const fhicl::ParameterSet &pset)
static Double_t fitf(Double_t *x, Double_t *par)
double fPeakRange
set range limits for peak center
void findPeakParameters(const std::vector< float > &, const ICandidateHitFinder::HitCandidateVec &, PeakParamsVec &, double &, int &) const override
double fMaxWidthMult
multiplier for max width for ICARUS fit
Description of geometry of one entire detector.
std::string to_string(WindowPattern const &pattern)
const geo::GeometryCore * fGeometry
TF1 fFit
Cache of fit functions (one so far).
art framework interface to geometry description
std::vector< HitCandidate > HitCandidateVec