PeakFitterMrqdt_tool.cc
Go to the documentation of this file.
1 #include "larvecutils/MarqFitAlg/MarqFitAlg.h" //marqfit functions
3 #include "larreco/RecoAlg/GausFitCache.h" // hit::GausFitCache
4 
7 #include "art_root_io/TFileService.h"
8 #include "cetlib_except/exception.h"
11 
12 #include <cassert>
13 #include <cmath>
14 #include <fstream>
15 
17 
18 namespace reco_tool {
19 
21  public:
22  explicit PeakFitterMrqdt(const fhicl::ParameterSet& pset);
23 
24  void findPeakParameters(const std::vector<float>&,
27  double&,
28  int&) const override;
29 
30  private:
31  //Variables from the fhicl file
32  const double fMinWidth;
33  const double fMaxWidthMult;
34  const double fPeakRange;
35  const double fAmpRange;
36 
37  std::unique_ptr<gshf::MarqFitAlg> fMarqFitAlg;
38 
39  const geo::GeometryCore* fGeometry = lar::providerFrom<geo::Geometry>();
40  };
41 
42  //--------------------------
43  //constructor
44 
46  : fMinWidth(pset.get<double>("MinWidth", 0.5))
47  , fMaxWidthMult(pset.get<double>("MaxWidthMult", 3.))
48  , fPeakRange(pset.get<double>("PeakRangeFact", 2.))
49  , fAmpRange(pset.get<double>("PeakAmpRange", 2.))
50  {}
51 
52  //------------------------
53  //output parameters should be replaced with a returned value
54  void
55  PeakFitterMrqdt::findPeakParameters(const std::vector<float>& signal,
57  PeakParamsVec& mhpp_vec,
58  double& chi2PerNDF,
59  int& NDF) const
60  {
61  if (fhc_vec.empty()) return;
62 
63  const float chiCut = 1e-3;
64  float lambda = 0.001; /* Marquardt damping parameter */
66  int nParams = 0;
67 
68  int startTime = fhc_vec.front().startTick;
69  int endTime = fhc_vec.back().stopTick;
70 
71  int roiSize = endTime - startTime;
72 
73  // init to a large number in case the fit fails
74  chi2PerNDF = chiSqr;
75 
76  std::vector<float> y(roiSize);
77  std::vector<float> p(3 * fhc_vec.size());
78  std::vector<float> plimmin(3 * fhc_vec.size());
79  std::vector<float> plimmax(3 * fhc_vec.size());
80  std::vector<float> perr(3 * fhc_vec.size());
81 
82  /* choose the fit function and set the parameters */
83  nParams = 0;
84 
85  for (size_t ih = 0; ih < fhc_vec.size(); ih++) {
86  float const peakMean =
87  fhc_vec[ih].hitCenter - 0.5 - (float)startTime; //shift by 0.5 to account for bin width
88  float const peakWidth = fhc_vec[ih].hitSigma;
89  float const amplitude = fhc_vec[ih].hitHeight;
90  float const meanLowLim = fmax(peakMean - fPeakRange * peakWidth, 0.);
91  float const meanHiLim = fmin(peakMean + fPeakRange * peakWidth, (float)roiSize);
92  p[0 + nParams] = amplitude;
93  p[1 + nParams] = peakMean;
94  p[2 + nParams] = peakWidth;
95 
96  plimmin[0 + nParams] = amplitude * 0.1;
97  plimmin[1 + nParams] = meanLowLim;
98  plimmin[2 + nParams] = std::max(fMinWidth, 0.1 * peakWidth);
99 
100  plimmax[0 + nParams] = amplitude * fAmpRange;
101  plimmax[1 + nParams] = meanHiLim;
102  plimmax[2 + nParams] = fMaxWidthMult * peakWidth;
103 
104  nParams += 3;
105  }
106  int fitResult = -1;
107 
108  for (size_t idx = 0; idx < size_t(roiSize); idx++) {
109  y[idx] = signal[startTime + idx];
110  }
111 
112  int trial = 0;
113  lambda = -1.; /* initialize lambda on first call */
114  do {
115  fitResult = fMarqFitAlg->gshf::MarqFitAlg::mrqdtfit(
116  lambda, &p[0], &plimmin[0], &plimmax[0], &y[0], nParams, roiSize, chiSqr, dchiSqr);
117  trial++;
118  if (fitResult || (trial > 100)) break;
119  } while (fabs(dchiSqr) >= chiCut);
120 
121  if (!fitResult) {
122  int fitResult2 =
123  fMarqFitAlg->gshf::MarqFitAlg::cal_perr(&p[0], &y[0], nParams, roiSize, &perr[0]);
124  if (!fitResult2) {
125  NDF = roiSize - nParams;
126  chi2PerNDF = chiSqr / NDF;
127  int parIdx = 0;
128  for (size_t i = 0; i < fhc_vec.size(); i++) {
129 
130  /* stand alone method
131  mhpp_vec[i].peakAmplitude = p[parIdx + 0];
132  mhpp_vec[i].peakAmplitudeError = perr[parIdx + 0];
133  mhpp_vec[i].peakCenter = p[parIdx + 1] + 0.5 + float(startTime);
134  mhpp_vec[i].peakCenterError = perr[parIdx + 1];
135  mhpp_vec[i].peakSigma = p[parIdx + 2];
136  mhpp_vec[i].peakSigmaError = perr[parIdx + 2];
137  */
138 
139  PeakFitParams_t mhpp;
140  mhpp.peakAmplitude = p[parIdx + 0];
141  mhpp.peakAmplitudeError = perr[parIdx + 0];
142  mhpp.peakCenter =
143  p[parIdx + 1] + 0.5 + float(startTime); //shift by 0.5 to account for bin width
144  mhpp.peakCenterError = perr[parIdx + 1];
145  mhpp.peakSigma = std::abs(p[parIdx + 2]);
146  mhpp.peakSigmaError = perr[parIdx + 2];
147 
148  mhpp_vec.emplace_back(mhpp);
149 
150  parIdx += 3;
151  }
152 
153  // fitStat=0;
154  }
155  }
156  return;
157  }
158 
160 }
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
std::unique_ptr< gshf::MarqFitAlg > fMarqFitAlg
art framework interface to geometry description
T abs(T value)
const double e
PeakFitterMrqdt(const fhicl::ParameterSet &pset)
p
Definition: test.py:223
static int max(int a, int b)
Description of geometry of one entire detector.
std::vector< PeakFitParams_t > PeakParamsVec
Definition: IPeakFitter.h:37
This provides an interface for tools which are tasked with fitting peaks on input waveforms...
void findPeakParameters(const std::vector< float > &, const ICandidateHitFinder::HitCandidateVec &, PeakParamsVec &, double &, int &) const override
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.
const geo::GeometryCore * fGeometry
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
std::vector< HitCandidate > HitCandidateVec