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