NSCL DDAS  1.0
Support for XIA DDAS at the NSCL
 All Classes Namespaces Files Functions Variables Macros Pages
CFD.hpp
1 // CFD.hpp
2 //
3 // Author : Jeromy Tompkins
4 // Date : 8/14/2013
5 
6 #ifndef CFD_H
7 #define CFD_H
8 
9 #include <deque>
10 #include <cmath>
11 #include "TrapFilter.hpp"
12 #include "Solver.h"
13 #include "TObject.h"
14 
15 namespace TrAnal
16 {
17 
19 
42 template<class T>
43 struct CFDResult
44 {
46  double fraction;
47 
48  // ROOT dictionary generation
50  ClassDef(CFDResult,0);
52 };
53 
54 
56 
97 template<class T>
98 CFDResult<T> CFD(const TrRange<T>& range,
99  int rise_len,
100  int gap_len,
101  int delay,
102  int scale_factor,
103  const Solver& solver=LinearSolver() )
104 
105 {
106  // TrapFilters are defined from their lower bound. First locate the
107  // the location of the lead filter
108  TrIterator<T> lead_start = range.begin()+delay;
109  // Verify that it is in range
110  if (lead_start>=range.end() ) return CFDResult<T>();
111 
112  // Construct the two trap filters
113  TrapFilter<T> lead_filter (lead_start, rise_len, gap_len);
114  TrapFilter<T> dely_filter (range.begin(), rise_len, gap_len);
115 
117 
118  // initialize the queue
119  std::deque<double> cfd_res;
120  for (unsigned int i=0; i<solver.npoints() && lead_filter<range.end(); ++i) {
121 
122  // Compute the CFD value
123  cfd_res.push_back((*lead_filter) - (*dely_filter)/pow(2.0,scale_factor+1));
124 
125  ++lead_filter;
126  ++dely_filter;
127  }
128 
129  // Initialize the counter for number of negative points
130  unsigned int nneg=0;
131  while (lead_filter<range.end()) {
132  // Compute new CFD values
133  cfd_res.push_back((*lead_filter) - (*dely_filter)/pow(2.0,scale_factor+1));
134 
135  // Have we crossed over zero?
136  if (cfd_res.back() < 0) ++nneg;
137 
138  // Do we have enough points to determine the zero crossing?
139  // if so, stop!
140  if (nneg>=solver.npoints()-1) break;
141 
142  ++lead_filter;
143  ++dely_filter;
144 
145  cfd_res.pop_front();
146  }
147 
148  // If not enough data exists to find a zero crossing, return a null result
149  if (nneg!=solver.npoints()-1) return CFDResult<T>();
150 
151  // This will return the fraction index of the zero crossing with respect to the
152  // front of the queue
153  double trig = solver(cfd_res);
154  int floortrig = static_cast<int>(::floor(trig));
155 
156  // trig location happened at ceiltrig from end
157  int n_from_end=static_cast<int>(cfd_res.size())-floortrig;
158  TrIterator<T> trigit = lead_filter.max_extent()-n_from_end;
159  double frac = trig - floortrig;
160 
161  // Construct the result and move return it
162  CFDResult<T> res;
163  res.trig = trigit;
164  res.fraction = frac;
165 
166  return res;
167 
168 } // end CFD function
169 
170 } // end namespace
171 
172 #endif
double fraction
fractional distance to the zero crossing beyond trig iterator
Definition: CFD.hpp:46
TrIterator template class.
Definition: TrIterator.hpp:24
TrIterator< T > end() const
Get value of end iterator.
Definition: TrIterator.hpp:224
A simple fast filter (lead sum - trail sum)
Definition: TrapFilter.hpp:29
TrRange class.
Definition: TrIterator.hpp:173
TrIterator< T > trig
TrIterator pointing to element immediately before zero crossing.
Definition: CFD.hpp:45
Pure abstract base class for root-finding algorithms.
Definition: Solver.h:22
TrIterator< T > begin() const
Get value of begin iterator.
Definition: TrIterator.hpp:222
Definition: AlgoIterator.hpp:12
Result for a CFD computation.
Definition: CFD.hpp:43
Root finder based on linear interpolation.
Definition: Solver.h:45
Definition: CFD.h:6