LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LArFFT.h
Go to the documentation of this file.
1 #ifndef LARFFT_H
9 #define LARFFT_H
10 
11 #include "TComplex.h"
12 #include "TF1.h"
13 #include "TFFTComplexReal.h"
14 #include "TFFTRealComplex.h"
15 #include "TH1D.h"
16 #include <string>
17 #include <vector>
18 
22 #include "fhiclcpp/ParameterSet.h"
23 
25 namespace util {
26  class LArFFT {
27  public:
29  ~LArFFT();
30 
31  template <class T>
32  void DoFFT(std::vector<T>& input, std::vector<TComplex>& output);
33 
34  template <class T>
35  void DoInvFFT(std::vector<TComplex>& input, std::vector<T>& output);
36 
37  template <class T>
38  void Deconvolute(std::vector<T>& input, std::vector<T>& respFunc);
39 
40  template <class T>
41  void Deconvolute(std::vector<T>& input, std::vector<TComplex>& kern);
42 
43  template <class T>
44  void Convolute(std::vector<T>& input, std::vector<T>& respFunc);
45 
46  template <class T>
47  void Convolute(std::vector<T>& input, std::vector<TComplex>& kern);
48 
49  template <class T>
50  void Correlate(std::vector<T>& input, std::vector<T>& respFunc);
51 
52  template <class T>
53  void Correlate(std::vector<T>& input, std::vector<TComplex>& kern);
54 
55  template <class T>
56  void AlignedSum(std::vector<T>& input, std::vector<T>& output, bool add = true);
57 
58  void ShiftData(std::vector<TComplex>& input, double shift);
59 
60  template <class T>
61  void ShiftData(std::vector<T>& input, double shift);
62 
63  template <class T>
64  T PeakCorrelation(std::vector<T>& shape1, std::vector<T>& shape2);
65 
66  int FFTSize() const { return fSize; }
67  std::string FFTOptions() const { return fOption; }
68  int FFTFitBins() const { return fFitBins; }
69 
70  void ReinitializeFFT(int, std::string, int);
71 
72  private:
73  int fSize; //size of transform
74  int fFreqSize; //size of frequency space
75  std::string fOption; //FFTW setting
76  int fFitBins; //Bins used for peak fit
77  TF1* fPeakFit; //Gaussian peak function
78  TH1D* fConvHist; //Fit data histogram
79  std::vector<TComplex> fCompTemp; //temporary complex data
80  std::vector<TComplex> fKern; //transformed response function
81 
82  TFFTRealComplex* fFFT;
83  TFFTComplexReal* fInverseFFT;
84 
85  void InitializeFFT();
86  void resetSizePerRun(art::Run const&);
87 
88  }; // class LArFFT
89 
90 } //namespace util
91 
92 // "Forward" Fourier Transform
93 //--------------------------------------------------------
94 template <class T>
95 inline void util::LArFFT::DoFFT(std::vector<T>& input, std::vector<TComplex>& output)
96 {
97  double real = 0.; //real value holder
98  double imaginary = 0.; //imaginary value hold
99 
100  // set the points
101  for (size_t p = 0; p < input.size(); ++p)
102  fFFT->SetPoint(p, input[p]);
103 
104  fFFT->Transform();
105 
106  for (int i = 0; i < fFreqSize; ++i) {
107  fFFT->GetPointComplex(i, real, imaginary);
108  output[i] = TComplex(real, imaginary);
109  }
110 
111  return;
112 }
113 
114 //Inverse Fourier Transform
115 //-------------------------------------------------
116 template <class T>
117 inline void util::LArFFT::DoInvFFT(std::vector<TComplex>& input, std::vector<T>& output)
118 {
119  for (int i = 0; i < fFreqSize; ++i)
120  fInverseFFT->SetPointComplex(i, input[i]);
121 
122  fInverseFFT->Transform();
123  double factor = 1.0 / (double)fSize;
124 
125  for (int i = 0; i < fSize; ++i)
126  output[i] = factor * fInverseFFT->GetPointReal(i, false);
127 
128  return;
129 }
130 
131 //Deconvolution scheme taking all time-domain
132 //information
133 //--------------------------------------------------
134 template <class T>
135 inline void util::LArFFT::Deconvolute(std::vector<T>& input, std::vector<T>& respFunction)
136 {
137  DoFFT(respFunction, fKern);
138  DoFFT(input, fCompTemp);
139 
140  for (int i = 0; i < fFreqSize; i++)
141  fCompTemp[i] /= fKern[i];
142 
143  DoInvFFT(fCompTemp, input);
144 
145  return;
146 }
147 
148 //Deconvolution scheme using an already transformed
149 //response function
150 //saves cpu time if same response function is used
151 //for many consecutive transforms
152 //--------------------------------------------------
153 template <class T>
154 inline void util::LArFFT::Deconvolute(std::vector<T>& input, std::vector<TComplex>& kern)
155 {
156  DoFFT(input, fCompTemp);
157 
158  for (int i = 0; i < fFreqSize; i++)
159  fCompTemp[i] /= kern[i];
160 
161  DoInvFFT(fCompTemp, input);
162 
163  return;
164 }
165 
166 //Convolution scheme taking all time-domain
167 //information
168 //--------------------------------------------------
169 template <class T>
170 inline void util::LArFFT::Convolute(std::vector<T>& shape1, std::vector<T>& shape2)
171 {
172  DoFFT(shape1, fKern);
173  DoFFT(shape2, fCompTemp);
174 
175  for (int i = 0; i < fFreqSize; i++)
176  fCompTemp[i] *= fKern[i];
177 
178  DoInvFFT(fCompTemp, shape1);
179 
180  return;
181 }
182 
183 //Convolution scheme using an already transformed
184 //response function
185 //saves cpu time if same response function is used
186 //for many consecutive transforms
187 //--------------------------------------------------
188 template <class T>
189 inline void util::LArFFT::Convolute(std::vector<T>& input, std::vector<TComplex>& kern)
190 {
191  DoFFT(input, fCompTemp);
192 
193  for (int i = 0; i < fFreqSize; i++)
194  fCompTemp[i] *= kern[i];
195 
196  DoInvFFT(fCompTemp, input);
197 
198  return;
199 }
200 
201 //Correlation taking all time domain data
202 //--------------------------------------------------
203 template <class T>
204 inline void util::LArFFT::Correlate(std::vector<T>& shape1, std::vector<T>& shape2)
205 {
206  DoFFT(shape1, fKern);
207  DoFFT(shape2, fCompTemp);
208 
209  for (int i = 0; i < fFreqSize; i++)
210  fCompTemp[i] *= TComplex::Conjugate(fKern[i]);
211 
212  DoInvFFT(fCompTemp, shape1);
213 
214  return;
215 }
216 
217 //Convolution scheme using an already transformed
218 //response function
219 //saves cpu time if same response function is used
220 //for many consecutive transforms
221 //--------------------------------------------------
222 template <class T>
223 inline void util::LArFFT::Correlate(std::vector<T>& input, std::vector<TComplex>& kern)
224 {
225  DoFFT(input, fCompTemp);
226 
227  for (int i = 0; i < fFreqSize; i++)
228  fCompTemp[i] *= TComplex::Conjugate(kern[i]);
229 
230  DoInvFFT(fCompTemp, input);
231 
232  return;
233 }
234 
235 //Scheme for adding two signals which have an arbitrary
236 //relative translation. Shape1 is translated over shape2
237 //and is replaced with the sum, or the translated result
238 //if add = false
239 //--------------------------------------------------
240 template <class T>
241 inline void util::LArFFT::AlignedSum(std::vector<T>& shape1, std::vector<T>& shape2, bool add)
242 {
243  double shift = PeakCorrelation(shape1, shape2);
244 
245  ShiftData(shape1, shift);
246 
247  if (add)
248  for (int i = 0; i < fSize; i++)
249  shape1[i] += shape2[i];
250 
251  return;
252 }
253 
254 //Shifts real vectors using above function
255 //--------------------------------------------------
256 template <class T>
257 inline void util::LArFFT::ShiftData(std::vector<T>& input, double shift)
258 {
259  DoFFT(input, fCompTemp);
260  ShiftData(fCompTemp, shift);
261  DoInvFFT(fCompTemp, input);
262 
263  return;
264 }
265 
266 //Returns the length of the translation at which the correlation
267 //of 2 signals is maximal.
268 //--------------------------------------------------
269 template <class T>
270 inline T util::LArFFT::PeakCorrelation(std::vector<T>& shape1, std::vector<T>& shape2)
271 {
272  fConvHist->Reset("ICE");
273  std::vector<T> holder = shape1;
274  Correlate(holder, shape2);
275 
276  int maxT = max_element(holder.begin(), holder.end()) - holder.begin();
277  float startT = maxT - fFitBins / 2;
278  int offset = 0;
279 
280  for (int i = 0; i < fFitBins; i++) {
281  if (startT + i < 0)
282  offset = fSize;
283  else if (startT + i > fSize)
284  offset = -fSize;
285  else
286  offset = 0;
287  fConvHist->Fill(i, holder[i + startT + offset]);
288  }
289 
290  fPeakFit->SetParameters(fConvHist->GetMaximum(), fFitBins / 2, fFitBins / 2);
291  fConvHist->Fit(fPeakFit, "QWNR", "", 0, fFitBins);
292  return fPeakFit->GetParameter(1) + startT;
293 }
294 
296 #endif // LARFFT_H
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
void resetSizePerRun(art::Run const &)
Definition: LArFFT.cc:39
void ShiftData(std::vector< TComplex > &input, double shift)
Definition: LArFFT.cc:116
int fSize
Definition: LArFFT.h:73
std::vector< TComplex > fKern
Definition: LArFFT.h:80
void DoFFT(std::vector< T > &input, std::vector< TComplex > &output)
Definition: LArFFT.h:95
int FFTFitBins() const
Definition: LArFFT.h:68
T PeakCorrelation(std::vector< T > &shape1, std::vector< T > &shape2)
Definition: LArFFT.h:270
Definition: Run.h:37
void DoInvFFT(std::vector< TComplex > &input, std::vector< T > &output)
Definition: LArFFT.h:117
TFFTRealComplex * fFFT
object to do FFT
Definition: LArFFT.h:82
int FFTSize() const
Definition: LArFFT.h:66
#define DECLARE_ART_SERVICE(svc, scope)
void Correlate(std::vector< T > &input, std::vector< T > &respFunc)
Definition: LArFFT.h:204
LArFFT(fhicl::ParameterSet const &pset, art::ActivityRegistry &reg)
Definition: LArFFT.cc:18
void Convolute(std::vector< T > &input, std::vector< T > &respFunc)
Definition: LArFFT.h:170
void Deconvolute(std::vector< T > &input, std::vector< T > &respFunc)
Definition: LArFFT.h:135
void AlignedSum(std::vector< T > &input, std::vector< T > &output, bool add=true)
Definition: LArFFT.h:241
TF1 * fPeakFit
Definition: LArFFT.h:77
std::vector< TComplex > fCompTemp
Definition: LArFFT.h:79
std::string FFTOptions() const
Definition: LArFFT.h:67
std::string fOption
Definition: LArFFT.h:75
TFFTComplexReal * fInverseFFT
object to do Inverse FF
Definition: LArFFT.h:83
TH1D * fConvHist
Definition: LArFFT.h:78
int fFitBins
Definition: LArFFT.h:76
void InitializeFFT()
Definition: LArFFT.cc:48
void ReinitializeFFT(int, std::string, int)
Definition: LArFFT.cc:85
int fFreqSize
Definition: LArFFT.h:74