Diana Software
QFFT.cc
Go to the documentation of this file.
1 /*
2 *
3 * Class QFFT
4 *
5 */
6 
7 #include "QFFT.hh"
8 #include "QVectorView.hh"
9 
10 ClassImp(Diana::QFFT);
11 
13 
14 QFFT::QFFT(const size_t size):fSize(size) {
16  fNormalized = false;
17  IsPowerOf2();
18  fData = new double[size];
19  fWindow = 0;
20  fWindowSize = 0;
22 }
23 
25  fSize = 0;
27  fNormalized = false;
28  fIsPowerOf2 = false;
29  fData = NULL;
30  fWindow = 0;
31  fWindowSize = 0;
33 }
34 
36  if(fData){
37  delete [] fData;
38  fData = 0;
39  }
40  if(fWindow){
41  delete [] fWindow;
42  fWindow = 0;
43  }
44 }
45 bool QFFT::IsPowerOf2(UInt_t Value,UInt_t &Power,UInt_t &Remainder){
46  Power=Remainder=0;
47  if(Value == 0) { Power=0;Remainder=0;return false; }
48  size_t Comp=2*sizeof(size_t);
49  while(Comp>0){
50  if(Value>(size_t)((1<<Comp)-1))
51  {Power+=Comp; Remainder+=(Value&((1<<Comp)-1)); Value = Value>>Comp; }
52  Comp/=2;
53  }
54  if(Remainder) return false;
55  return true;
56 }
57 bool QFFT::IsPowerOf2(UInt_t Value){
58  UInt_t P,R;
59  return IsPowerOf2(Value,P,R);
60 }
63 }
64 QFFT::WindowType QFFT::StrToWindowType(const std::string& winName)
65 {
66 
67  WindowType wType;
68 
69  if (!winName.compare("rectangular")) wType=WT_Rect;
70  else if(!winName.compare("welch")) wType=WT_Welch;
71  else if(!winName.compare("hann")) wType=WT_Hann;
72  else if(!winName.compare("hamming")) wType=WT_Hamming;
73  else if(!winName.compare("cosinus")) wType=WT_Cosinus;
74  else if(!winName.compare("blackman-harris")) wType=WT_BlackmanHarris;
75  else if(!winName.compare("kaiser3")) wType=WT_Kaiser3;
76  else wType = WT_None;
77 
78  return wType;
79 
80 }
81 
82 QVector QFFT::GetWindow(WindowType wt, size_t size, size_t zeros, int coherent, int param )
83 {
84 
85  size_t winSize = size-zeros;
86  QVector window(winSize);
87 
88  switch(wt) {
89  case WT_Rect:
90  {
91  for(size_t i = 0; i < winSize; i++) {
92  window[i] = 1.;
93  }
94  break;
95  }
96  case WT_Welch:
97  {
98  for(size_t i = 0; i < winSize; i++) {
99  window[i] = 1.- pow( (i-winSize/2.) / (winSize/2.),2.);
100  }
101  break;
102  }
103  case WT_Hann:
104  {
105  for(size_t i = 0; i < winSize; i++) {
106  window[i] = 0.5*(1 - gsl_sf_cos(2*M_PI*(i+1)/winSize));
107  }
108  break;
109  }
110  case WT_Hamming:
111  {
112  for(size_t i = 0; i < winSize; i++) {
113  window[i] = 0.53836 - 0.46164*gsl_sf_cos(2*M_PI*(i+1)/(winSize));
114  }
115  break;
116  }
117  case WT_Cosinus:
118  {
119  size_t risetime = 30;
120  if(param > 0) risetime = param;
121  for(size_t i = 0; i < winSize; i++) {
122  if(i< risetime)
123  window[i] = 0.5 - 0.5*cos(M_PI/(risetime)*double(i+1));
124  else if(i < winSize-risetime)
125  window[i] = 1.;
126  else
127  window[i] = 0.5 + 0.5*cos(M_PI/(risetime)*double(i+1-(winSize-risetime)));
128  }
129  break;
130  }
131  case WT_BlackmanHarris:
132  {
133  double a0 = 0.35875;
134  double a1 = 0.48829;
135  double a2 = 0.14128;
136  double a3 = 0.01168;
137  for(size_t i = 0; i < winSize; i++) {
138  window[i] = a0 - a1*cos(2*M_PI*i/winSize) + a2*cos(4*M_PI*i/winSize) - a3*cos(6*M_PI*i/winSize);
139  }
140  break;
141  }
142  case WT_Kaiser3:
143  {
144  double arg;
145  double alpha = 3.;
146  for(size_t i = 0; i < winSize; i++) {
147  arg = alpha*sqrt(1.-pow(2.*i/winSize-1.,2.));
148  window[i] = gsl_sf_bessel_I0(arg)/gsl_sf_bessel_I0(alpha);
149  }
150  break;
151  }
152  case WT_None:
153  default:
154  {
155  window.Resize(0);
156  break;
157  }
158 
159  }
160  double corrFactor = 0.;
161  if(coherent == 1) {
162  for(size_t i = 0; i < window.Size(); i++) {
163  corrFactor += window[i];
164  }
165  corrFactor /= window.Size();
166  } else if(coherent == 2){
167  for(size_t i = 0; i < window.Size(); i++) {
168  corrFactor += window[i]*window[i];
169  }
170  corrFactor /= window.Size();
171  corrFactor = sqrt(corrFactor);
172  } else {
173  corrFactor = 1.;
174  }
175  for(size_t i = 0; i < window.Size(); i++) {
176  window[i] /= corrFactor;
177  }
178 
179 
180  QVector retwin;
181  if(zeros > 0 && window.Size() > 0) {
182  retwin.Resize(size);
183  // fill left and right side with zeros
184  size_t start = zeros/2;
185  size_t stop = start + window.Size();
186  for(size_t j = 0; j < start; j++) {
187  retwin[j] = 0.;
188  }
189  for(size_t j = start, i = 0; j < stop ; j++,i++) {
190  retwin[j] = window[i];
191  }
192  for(size_t j = stop; j < size; j++) {
193  retwin[j] = 0.;
194  }
195  } else {
196  retwin = window;
197  }
198  return retwin;
199 }
200 
202 {
203  Diana::QVector antiSym(input);
204  size_t size=antiSym.Size()/2-1;
205  antiSym.Shift(-size);
206  return antiSym;
207 }
209 {
210  Diana::QVector sym(input);
211  size_t size=sym.Size()/2-1;
212  sym.Shift(size);
213  return sym;
214 }
215 
216 QVector QFFT::ZeroPad(const QVector& input,size_t n_zeros,int isSym,
217  double zeroVal){
218  // Calculate the new size of the array
219  size_t totsize = input.Size() + n_zeros;
220  // Offset for the input array
221  size_t offset=(isSym == kMiddle ? input.Size()/2+1 : 0);
222  // New array
223  QVector zeroPadded(totsize);
224 
225  // Put the zeros at the front
226  for(size_t i = 0; i < n_zeros; i++) {
227  zeroPadded[i] = zeroVal;
228  }
229  // Put the input array at the end of the new array
230  // If we are using kMiddle, the offset will tell this for loop
231  // to start in the middle of the input array
232  for(size_t i=n_zeros,j=0;j<input.Size();i++,j++){
233  zeroPadded[i]=input[(offset+j) % input.Size()];
234  }
235  // If we are symmetric, shift half the zeros to the back of the
236  // array
237  if(isSym==kSymmetric)
238  zeroPadded.Shift(-(n_zeros/2));
239  // If we are right padding, shift ALL the zeros to the back of the
240  // array
241  else if(isSym==kRight)
242  zeroPadded.Shift(-n_zeros);
243  // If we are left or middle padding, then shift the array by
244  // offset, for kLeft this is zero, for kMiddle this is
245  // input.Size()/2+1 (effectively undoing the offset that was done
246  // before)
247  else if(isSym==kMiddle)
248  zeroPadded.Shift(offset);
249  // Return the new array
250  return zeroPadded;
251 }
252 
253 QVectorC QFFT::ZeroPad(const QVectorC& input,size_t n_zeros,int isSym,
254  Diana::QComplex zeroVal){
255  // Calculate the new size of the array
256  size_t totsize = input.Size() + n_zeros;
257  // Offset for the input array
258  size_t offset=(isSym == kMiddle ? input.Size()/2+1 : 0);
259  // New array
260  QVectorC zeroPadded(totsize);
261 
262  // Put the zeros at the front
263  for(size_t i = 0; i < n_zeros; i++) {
264  zeroPadded[i] = zeroVal;
265  }
266  // Put the input array at the end of the new array
267  // If we are using kMiddle, the offset will tell this for loop
268  // to start in the middle of the input array
269  for(size_t i=n_zeros,j=0;j<input.Size();i++,j++){
270  zeroPadded[i]=input[(offset+j) % input.Size()];
271  }
272  // If we are symmetric, shift half the zeros to the back of the
273  // array
274  if(isSym==kSymmetric)
275  zeroPadded.Shift(-(n_zeros/2));
276  // If we are right padding, shift ALL the zeros to the back of the
277  // array
278  else if(isSym==kRight)
279  zeroPadded.Shift(-n_zeros);
280  // If we are left or middle padding, then shift the array by
281  // offset, for kLeft this is zero, for kMiddle this is
282  // input.Size()/2+1 (effectively undoing the offset that was done
283  // before)
284  else if(isSym==kMiddle)
285  zeroPadded.Shift(offset);
286  // Return the new array
287  return zeroPadded;
288 }
289 
290 QVector QFFT::CutSides(const QVector& input, size_t ncut, bool isSym)
291 {
292  size_t totsize = input.Size() - ncut;
293  QVector theInput;
294  if(isSym) {
295  theInput = input;
296  } else {
297  theInput = FFTSym(input);
298  }
299  QVectorConstView subv(theInput,ncut/2,totsize);
300 
301  return FFTAntiSym(subv.GetVector());
302 }
303 
Diana::QComplex pow(const Diana::QComplex &z, double a)
Raise a complex number to a real power.
Definition: QComplex.cc:246
#define Q_END_NAMESPACE
Definition: QDiana.hh:22
#define Q_BEGIN_NAMESPACE
Definition: QDiana.hh:20
ClassImp(Diana::QFFT)
Diana::QVector cos(const Diana::QVector &v)
Definition: QVector.cc:821
bool fIsPowerOf2
Definition: QFFT.hh:175
static WindowType StrToWindowType(const std::string &winName)
Convert string to window type.
Definition: QFFT.cc:64
size_t fWindowSize
Definition: QFFT.hh:178
virtual ~QFFT()
destructor
Definition: QFFT.cc:35
double * fData
Definition: QFFT.hh:176
WindowType
window type
Definition: QFFT.hh:30
@ WT_Rect
Definition: QFFT.hh:33
@ WT_Hann
Definition: QFFT.hh:34
@ WT_Welch
Definition: QFFT.hh:32
@ WT_Kaiser3
Definition: QFFT.hh:38
@ WT_Cosinus
Definition: QFFT.hh:36
@ WT_Hamming
Definition: QFFT.hh:35
@ WT_None
Definition: QFFT.hh:31
@ WT_BlackmanHarris
Definition: QFFT.hh:37
FFTDirection fDirection
Definition: QFFT.hh:173
WindowType fWindowType
Definition: QFFT.hh:179
static QVector ZeroPad(const QVector &input, size_t n_zeros, int Side=kMiddle, double zeroVal=0.)
Add zeros to the input.
Definition: QFFT.cc:216
static QVector CutSides(const QVector &input, size_t ncut, bool isSym)
cut left and right sides by ncut/2
Definition: QFFT.cc:290
static QVector FFTAntiSym(const QVector &input)
antisimmetrize time domain vector
Definition: QFFT.cc:201
void IsPowerOf2()
Definition: QFFT.cc:61
static QVector GetWindow(WindowType wt, size_t size, size_t zeros=0, int coherent=0, int param=0)
create window and add zeros/2 to the left and zeros/2 to the right
Definition: QFFT.cc:82
QFFT()
empty constructor with its size
Definition: QFFT.cc:24
@ kMiddle
Definition: QFFT.hh:41
@ kSymmetric
Definition: QFFT.hh:42
@ kRight
Definition: QFFT.hh:44
static QVector FFTSym(const QVector &input)
simmetrize time domain vector
Definition: QFFT.cc:208
double * fWindow
Definition: QFFT.hh:177
size_t fSize
Definition: QFFT.hh:172
@ kForward
Definition: QFFT.hh:47
bool fNormalized
Definition: QFFT.hh:174
Interface for complex vectors in Diana analysis.
Definition: QVectorC.hh:25
const QVectorC & Shift(const int nstep)
Cyclic shift of vector.
Definition: QVectorC.cc:240
UInt_t Size() const
size of QVector
Definition: QVectorC.hh:82
QVectorView for const QVector.
Definition: QVectorView.hh:52
const QVector & GetVector() const
Get subview QVector.
Definition: QVectorView.hh:66
Interface for vectors in Diana analysis.
Definition: QVector.hh:30
UInt_t Size() const
size of QVector
Definition: QVector.hh:54
const QVector & Shift(const int nstep)
Cyclic shift of vector.
Definition: QVector.cc:395
void Resize(const UInt_t newsize)
resize a QVector
Definition: QVector.cc:170