All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RFFHitFitter.cxx
Go to the documentation of this file.
1 /*!
2  * Title: RFFHitFitter Class
3  * Author: Wes Ketchum (wketchum@lanl.gov)
4  *
5  * Description:
6  * Class that does the base RFF algorithm. RFF works by simplifiying a Gaussian
7  * fit by dividing a pulse by its derivative. for a Gaussian, the result is a
8  * line, with the slope and intercept related to the sigma and mean of the
9  * Gaussian.
10  *
11  * Input: Signal (vector of floats)
12  * Output: Guassian means and sigmas
13 */
14 
15 #include "RFFHitFitter.h"
16 #include <iostream>
17 #include <cmath>
18 #include "cetlib_except/exception.h"
19 
20 hit::RFFHitFitter::RFFHitFitter(float step, float max):
21  fGEAlg(step,max)
22 {}
23 
25  unsigned int min_multi,
26  float threshold,
27  float step,
28  float max):
29  fGEAlg(step,max)
30 {
31  SetFitterParams(max_mean,min_multi,threshold);
32 }
33 
35  unsigned int min_multi,
36  float threshold)
37 {
38  fMeanMatchThreshold = max_mean;
39  fMinMergeMultiplicity = min_multi;
40 
41  if(fMinMergeMultiplicity==0) fMinMergeMultiplicity=1;
42 
43  fFinalAmpThreshold = threshold;
44 
45  ClearResults();
46 }
47 
48 void hit::RFFHitFitter::RunFitter(const std::vector<float>& signal)
49 {
50  ClearResults();
51  CalculateAllMeansAndSigmas(signal);
52  CreateMergeVector();
53  CalculateMergedMeansAndSigmas(signal.size());
54  CalculateAmplitudes(signal);
55 }
56 
57 void hit::RFFHitFitter::CalculateAllMeansAndSigmas(const std::vector<float>& signal)
58 {
59  if(signal.size()<=2) return;
60 
61  float prev_dev=0,this_dev=0;;
62  float slope=0; float sigma=0;
63  float intercept=0; float mean=0;
64 
65  for(size_t i_tick=1; i_tick < signal.size()-1; i_tick++)
66  {
67  this_dev = 0.5*(signal[i_tick+1]-signal[i_tick-1])/signal[i_tick];
68  slope = this_dev - prev_dev;
69 
70  prev_dev = this_dev;
71 
72  if(slope>=0) continue;
73 
74  sigma = std::sqrt(-1/slope);
75  intercept = 0.5*(signal[i_tick+1]-signal[i_tick-1])/signal[i_tick] - slope*i_tick;
76  mean = -1*intercept/slope;
77 
78  fSignalSet.insert(std::make_pair(mean,sigma));
79  }
80 }
81 
83 {
84  fMergeVector.clear(); fMergeVector.reserve( fSignalSet.size() );
85 
86  float prev_mean=-9e6;
87  for(std::multiset<MeanSigmaPair>::iterator it=fSignalSet.begin(); it!=fSignalSet.end(); it++)
88  {
89  if( std::abs(it->first - prev_mean) > fMeanMatchThreshold || fMergeVector.size()==0 )
90  fMergeVector.push_back( std::vector< std::multiset<MeanSigmaPair>::iterator >(1,it) );
91  else
92  fMergeVector.back().push_back(it);
93  prev_mean = it->first;
94  }
95 }
96 
98 {
99  fMeanVector.reserve(fMergeVector.size());
100  fSigmaVector.reserve(fMergeVector.size());
101  fMeanErrorVector.reserve(fMergeVector.size());
102  fSigmaErrorVector.reserve(fMergeVector.size());
103 
104  for(size_t i_col=0; i_col<fMergeVector.size(); i_col++)
105  {
106  if(fMergeVector[i_col].size()<fMinMergeMultiplicity) continue;
107 
108  fMeanVector.push_back(0.0);
109  fSigmaVector.push_back(0.0);
110 
111  for(auto const& sigpair : fMergeVector[i_col])
112  {
113  fMeanVector.back() += sigpair->first;
114  fSigmaVector.back() += sigpair->second;
115  }
116 
117  fMeanVector.back() /= fMergeVector[i_col].size();
118  fSigmaVector.back() /= fMergeVector[i_col].size();
119 
120  if(fMeanVector.back() < 0 || fMeanVector.back()>signal_size-1)
121  {
122  fMeanVector.pop_back();
123  fSigmaVector.pop_back();
124  continue;
125  }
126 
127  fMeanErrorVector.push_back(0.0);
128  fSigmaErrorVector.push_back(0.0);
129 
130  for(auto const& sigpair : fMergeVector[i_col])
131  {
132  fMeanErrorVector.back() +=
133  (sigpair->first-fMeanVector.back())*(sigpair->first-fMeanVector.back());
134  fSigmaErrorVector.back() +=
135  (sigpair->second-fSigmaVector.back())*(sigpair->second-fSigmaVector.back());
136  }
137 
138  fMeanErrorVector.back() = std::sqrt(fMeanErrorVector.back()) / fMergeVector[i_col].size();
139  fSigmaErrorVector.back() = std::sqrt(fSigmaErrorVector.back()) / fMergeVector[i_col].size();
140 
141  }
142 
143 }
144 
145 void hit::RFFHitFitter::CalculateAmplitudes(const std::vector<float>& signal)
146 {
147  std::vector<float> heightVector(fMeanVector.size());
148  size_t bin=0;
149 
150  for(size_t i=0; i<fMeanVector.size(); i++)
151  {
152  if (fMeanVector[i]<0) bin=0;
153  else if(fMeanVector[i]+1 > signal.size()) bin=signal.size()-2;
154  else bin = std::floor(fMeanVector[i]);
155 
156  if(bin >= signal.size()-1)
157  throw cet::exception("RFFHitFitter") << "Error in CalculatAmplitudes! bin is out of range!\n"
158  << "\tFor element " << i << " bin is " << bin << "(" << fMeanVector[i] << ")"
159  << " but size is " << signal.size() << ".\n";
160 
161  heightVector[i] = signal[bin] - (fMeanVector[i]-(float)bin)*(signal[bin]-signal[bin+1]);
162  }
163 
164  fAmpVector = fGEAlg.SolveEquations(fMeanVector,fSigmaVector,heightVector);
165 
166  while(HitsBelowThreshold())
167  {
168  for(size_t i=0; i<fAmpVector.size(); i++)
169  {
170  if(fAmpVector[i] < fFinalAmpThreshold)
171  {
172  fMeanVector.erase(fMeanVector.begin()+i);
173  fMeanErrorVector.erase(fMeanErrorVector.begin()+i);
174  fSigmaVector.erase(fSigmaVector.begin()+i);
175  fSigmaErrorVector.erase(fSigmaErrorVector.begin()+i);
176  fAmpVector.erase(fAmpVector.begin()+i);
177  heightVector.erase(heightVector.begin()+i);
178  }
179  }
180  fAmpVector = fGEAlg.SolveEquations(fMeanVector,fSigmaVector,heightVector);
181  }
182 
183  fAmpErrorVector.resize(fAmpVector.size(),0.0);
184 }
185 
187 {
188  for(auto const& amp : fAmpVector)
189  if(amp < fFinalAmpThreshold) return true;
190  return false;
191 }
192 
194 {
195  fMeanVector.clear();
196  fSigmaVector.clear();
197  fMeanErrorVector.clear();
198  fSigmaErrorVector.clear();
199  fAmpVector.clear();
200  fAmpErrorVector.clear();
201  fSignalSet.clear();
202  fMergeVector.clear();
203 }
204 
206 {
207  std::cout << "InitialSignalSet" << std::endl;
208 
209  for(auto const& sigpair : fSignalSet)
210  std::cout << "\t" << sigpair.first << " / " << sigpair.second << std::endl;
211 
212  std::cout << "\nNHits = " << NHits() << std::endl;
213  std::cout << "\tMean / Sigma / Amp" << std::endl;
214  for(size_t i=0; i<NHits(); i++)
215  std::cout << "\t"
216  << fMeanVector[i] << " +- " << fMeanErrorVector[i] << " / "
217  << fSigmaVector[i] << " +- " << fSigmaErrorVector[i] << " / "
218  << fAmpVector[i] << " +- " << fAmpErrorVector[i]
219  << std::endl;
220 }
void RunFitter(const std::vector< float > &signal)
void SetFitterParams(float, unsigned int, float)
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
void CalculateMergedMeansAndSigmas(std::size_t signal_size)
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
void CalculateAllMeansAndSigmas(const std::vector< float > &signal)
T abs(T value)
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Definition: UtilFunc.cxx:13
RFFHitFitter(float, unsigned int, float, float step=0.1, float max=5.0)
void CalculateAmplitudes(const std::vector< float > &signal)
BEGIN_PROLOG could also be cout