Diana Software
QRealComplexFFTGSL.cc
Go to the documentation of this file.
1 /*
2 *
3 * Class QRealComplexFFTGSL
4 *
5 * Computes the FFT of the double array data[] The result is stored in
6 * the array result, which must be twice the size N of data. The
7 * storage arrangement of the transform is the following:
8 * the first N elements of result are the real elememants of the FFT, while
9 * the remaining ones are the imaginary ones
10 *
11 * This algorithm uses GSL libraries to perform the FFT.
12 */
13 
14 #include "QRealComplexFFTGSL.hh"
15 #include <stdio.h>
16 #include <iostream>
17 #include "QVectorC.hh"
18 #include <gsl/gsl_fft_halfcomplex.h>
19 
20 ClassImp(Diana::QRealComplexFFTGSL);
21 
23 
24 using namespace std;
25 
27  {
28  fWaveTable = gsl_fft_real_wavetable_alloc(size);
29  fWork = gsl_fft_real_workspace_alloc(size);
30  fHCWaveTable = gsl_fft_halfcomplex_wavetable_alloc(size);
31  fWindow = NULL;
33  IsPowerOf2();
34 }
35 
37 {
38  fWaveTable = 0;
39  fWork = 0;
40  fHCWaveTable = 0;
41  fData = 0;
42  fWindow = NULL;
44 
45 }
46 
48  if(fWaveTable){
49  gsl_fft_real_wavetable_free(fWaveTable);
50  }
51  if(fHCWaveTable){
52  gsl_fft_halfcomplex_wavetable_free(fHCWaveTable);
53  }
54  if(fWork){
55  gsl_fft_real_workspace_free(fWork);
56  }
57  if(fData){
58  delete [] fData;
59  fData = 0;
60  }
61  if(fWindow)
62  delete [] fWindow;
63  fWindow = 0;
64 }
65 
66 int QRealComplexFFTGSL::TransformToFreq(const QVector& origData, QVectorC& FT,
67  bool compress){
68  Resize(origData.Size());
69  SetForward(true);
70  SetNormalized(false);
71  QVector res(2*origData.Size());
72  int r=Transform(origData,res);
73  if(compress){
74  FT.Resize(fSize/2+1);
75  for(size_t i=0;i<=fSize/2;i++){
76  FT[i].SetRe(res[i]);
77  FT[i].SetIm(res[i+fSize]);
78  }
79  }
80  else{
81  FT.Resize(fSize);
82  for(size_t i=0;i<fSize;i++){
83  FT[i].SetRe(res[i]);
84  FT[i].SetIm(res[i+fSize]);
85  }
86  }
87  return r;
88 }
89 
90 int QRealComplexFFTGSL::TransformFromFreq(const QVectorC& origFT,QVector& data,
91  bool compress){
92  if(compress)
93  Resize(2*(origFT.Size()-1));
94  else
95  Resize(origFT.Size());
96  SetForward(false);
97  SetNormalized(true);
98  QVectorC fullFT(fSize);
99  int ret=0;
100  if(compress){
101  for(size_t i=0;i<fSize/2;i++){
102  fullFT[i]=origFT[i];
103  fullFT[fSize/2+i]=origFT[fSize/2-i].Conj();
104  }
105  ret = Transform(fullFT.SingleVector(),data);
106  }
107  else{
108  ret = Transform(origFT.SingleVector(),data);
109  }
110  return ret;
111 }
112 
113 int QRealComplexFFTGSL::Transform(const QVector& origData, QVector& result){
114  if(fDirection==kForward)
115  result.Resize(fSize*2);
116  else
117  result.Resize(fSize);
118 
119  // readjust the window if not appropriate
121 
122  if(fWindow && (fDirection==kForward)){
123  for(size_t i = 0; i < fSize; i++){
124  fData[i] = origData[i]*fWindow[i];
125  }
126  }
127  else {
128  for(size_t i = 0; i < fSize; i++){
129  fData[i] = origData[i];
130  }
131  }
132 
133  int rval = -1;
134  if(fDirection == kForward && fNormalized == false){
135  if (fIsPowerOf2){
136  rval = gsl_fft_real_radix2_transform(fData,1,fSize);
137  if(rval == GSL_SUCCESS){
138  //real elements
139  for (size_t i = 0; i <= fSize/2; i++){
140  result[i] = fData[i];
141  }
142  for (size_t i = fSize/2 + 1; i < fSize; i++){
143  result[i] = fData[fSize - i];
144  }
145  //first complex element
146  size_t s32=size_t(1.5*fSize);
147  result[fSize] = 0;result[s32]=0;
148  for (size_t i = fSize + 1; i < s32; i++){
149  result[i] = fData[2*fSize - i];
150  }
151  for (size_t i = s32+1; i < 2*fSize; i++){
152  result[i] = -fData[i - fSize];
153  }
154  return 0;
155  }
156  //error
157  else if(rval != GSL_EDOM)
158  return -1;
159  }
160  //fData size is not power of 2
161  rval = gsl_fft_real_transform(fData, 1, fSize, fWaveTable, fWork);
162  if(rval == GSL_SUCCESS){
163  if (fSize%2){
164  printf("QRealComplexFFTGSL::Transform(forward): odd lenght data size"
165  " (%zd) not implemented yet\n",fSize);
166  return -1;
167  } else {
168  size_t imOff = fSize;
169  result[0] = fData[0];
170  result[imOff] = 0.;
171  for(size_t i = 1; i < fSize/2; i++) {
172  //real elements
173  result[fSize-i] = result[i] = fData[i*2-1];
174  //imag elements
175  result[imOff+fSize-i] = -(result[imOff+i] = fData[i*2]);
176  }
177  result[fSize/2] = fData[fSize-1];
178  result[imOff + fSize/2] = 0.;
179  return 0;
180  }
181  }
182  //error
183  else if(rval != GSL_EDOM)
184  return -1;
185 
186  }
187 
188  if(fDirection == kBackward){
189  if(fIsPowerOf2) {
190  // fData size is power of 2
191  fData[0]=origData[0];
192  fData[fSize/2]=origData[fSize/2];
193  for (size_t i=1;i<fSize/2;i++){
194  fData[i]=origData[i];
195  fData[fSize-i]=origData[fSize+i];
196  }
197  int rval = fNormalized ?
198  gsl_fft_halfcomplex_radix2_inverse(fData,1,fSize) :
199  gsl_fft_halfcomplex_radix2_backward(fData,1,fSize);
200  if(rval == GSL_SUCCESS)result.SetArray(fData,fSize);
201  return rval;
202  } else {
203  if (fSize%2){
204  //fData size not multiple of 2
205  printf("QRealComplexFFTGSL::Transform(backward): odd lenght data size"
206  " (%zd) not implemented yet\n",fSize);
207  return -1;
208  } else {
209  //fData size is multiple of 2
210  fData[0] = origData[0];
211  fData[fSize-1] = origData[fSize/2];
212  for(size_t i = 1; i < fSize/2; i++) {
213  // real
214  fData[i*2-1] = origData[i];
215  //imag
216  fData[i*2] = origData[fSize + i];
217  }
218 
219  int rval =
220  gsl_fft_halfcomplex_inverse(fData, 1, fSize,fHCWaveTable, fWork);
221  if(rval == GSL_SUCCESS)result.SetArray(fData,fSize);
222  return rval;
223  }
224 
225  }
226  }
227  return rval;
228 }
230  if (n != fSize){
231  if(fWaveTable)
232  gsl_fft_real_wavetable_free(fWaveTable);
233  if(fHCWaveTable)
234  gsl_fft_halfcomplex_wavetable_free(fHCWaveTable);
235  if(fWork)
236  gsl_fft_real_workspace_free(fWork);
237  if(fData)
238  delete [] fData;
239 
240  fData = new double[n];
241  fWaveTable = gsl_fft_real_wavetable_alloc(n);
242  fWork = gsl_fft_real_workspace_alloc(n);
243  fHCWaveTable = gsl_fft_halfcomplex_wavetable_alloc(n);
244  fSize = n;
245  IsPowerOf2();
246  if(fWindow){
248  }
249  }
250  return true;
251 }
252 
254  if(w != fWindowType || fWindowSize != fSize){
255  QVector tmp = GetWindow(w,fSize,0,coherent);
256  size_t wsize = tmp.Size();
257  if(wsize > 0 ) {
258  fWindow = tmp.GetArray();
259  fWindowSize = fSize;
260  } else {
261  fWindow = NULL;
262  fWindowSize = 0;
263  }
264  fWindowType = w;
265  }
266 }
267 
#define Q_END_NAMESPACE
Definition: QDiana.hh:22
#define Q_BEGIN_NAMESPACE
Definition: QDiana.hh:20
ClassImp(Diana::QRealComplexFFTGSL)
Interface for ffts in Diana analysis.
Definition: QFFT.hh:26
bool fIsPowerOf2
Definition: QFFT.hh:175
size_t fWindowSize
Definition: QFFT.hh:178
void SetNormalized(bool isNormalized)
virtual method. Must be implemented by daughter classes set the normalization of the transform.
Definition: QFFT.hh:149
void SetForward(bool isForward)
virtual method. Must be implemented by daughter classes set the direction of the transform.
Definition: QFFT.hh:142
double * fData
Definition: QFFT.hh:176
WindowType
window type
Definition: QFFT.hh:30
@ WT_None
Definition: QFFT.hh:31
FFTDirection fDirection
Definition: QFFT.hh:173
WindowType fWindowType
Definition: QFFT.hh:179
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
double * fWindow
Definition: QFFT.hh:177
size_t fSize
Definition: QFFT.hh:172
@ kBackward
Definition: QFFT.hh:48
@ kForward
Definition: QFFT.hh:47
bool fNormalized
Definition: QFFT.hh:174
QRealComplexFFTGSL()
empty constructor
virtual int TransformFromFreq(const QVectorC &FT, QVector &spectrum, bool compress=false)
transform from the frequencies to the times
gsl_fft_halfcomplex_wavetable * fHCWaveTable
virtual int TransformToFreq(const QVector &data, QVectorC &FFT, bool compress=false)
transform from the times to the frequencies
virtual int Transform(const QVector &data, QVector &result)
virtual method. Must be implemented by daughter classes.
virtual ~QRealComplexFFTGSL()
destructor
virtual void SetWindowType(WindowType wt, int coherent=0)
resize working table and space
virtual bool Resize(size_t s)
virtual method. Must be implemented by daughter classes
gsl_fft_real_workspace * fWork
gsl_fft_real_wavetable * fWaveTable
set the window type.