ODIN
complexdata.h
1 /***************************************************************************
2  complexdata.h - description
3  -------------------
4  begin : Fri Apr 6 2001
5  copyright : (C) 2000-2021 by Thies Jochimsen & Michael von Mengershausen
6  email : thies@jochimsen.de mengers@cns.mpg.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifndef COMPLEXDATA_H
19 #define COMPLEXDATA_H
20 
21 
22 #include <odindata/data.h>
23 #include <odindata/utils.h>
24 
25 
34 
35 
42 template <int N_rank>
43 class ComplexData : public Data<STD_complex,N_rank> {
44 
45  public:
46 
51 
52 
56  ComplexData(const TinyVector<int,N_rank>& dimvec) : Data<STD_complex,N_rank>(dimvec) {(*this)=STD_complex(0.0);}
57 
58 
63  // resolve ambiguities due to other constructors
64  ComplexData(int extent1) : Data<STD_complex,N_rank>(extent1) {}
65  ComplexData(int extent1, int extent2) : Data<STD_complex,N_rank>(extent1,extent2) {}
66  ComplexData(int extent1, int extent2,int extent3) : Data<STD_complex,N_rank>(extent1,extent2,extent3) {}
67  ComplexData(int extent1, int extent2,int extent3,int extent4) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4) {}
68  ComplexData(int extent1, int extent2,int extent3,int extent4,int extent5) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4,extent5) {}
69 // ComplexData(int extent1, int extent2,int extent3,int extent4,int extent5,int extent6) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4,extent5,extent6) {}
70 // ComplexData(int extent1, int extent2,int extent3,int extent4,int extent5,int extent6,int extent7) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4,extent5,extent6,extent7) {}
71 // ComplexData(int extent1, int extent2,int extent3,int extent4,int extent5,int extent6,int extent7,int extent8) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4,extent5,extent6,extent7,extent8) {}
72 // ComplexData(int extent1, int extent2,int extent3,int extent4,int extent5,int extent6,int extent7,int extent8,int extent9) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4,extent5,extent6,extent7,extent8,extent9) {}
73 
74 
78  ComplexData(const ComplexData<N_rank>& cd) : Data<STD_complex,N_rank>(cd) {}
79 
80 
84  ComplexData(const Data<STD_complex,N_rank>& a) : Data<STD_complex,N_rank>(a) {}
85 
86 
87 #ifdef BLITZ_REPLACEMENT
91  template<int M_rank>
92  ComplexData(const Array<STD_complex,M_rank>& a) : Data<STD_complex,N_rank>(a) {}
93 #else
97  template<class T_expr>
98  ComplexData(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr) : Data<STD_complex,N_rank>(expr) {}
99 #endif
100 
105 
106 
110  ComplexData<N_rank>& operator = (const Array<STD_complex,N_rank>& a) {Array<STD_complex,N_rank>::operator=(a); return *this;}
111 
112 
116  ComplexData<N_rank>& operator = (const STD_complex& val) {Data<STD_complex,N_rank>::operator=(val); return *this;}
117 
118 
119 #ifdef BLITZ_REPLACEMENT
120  // Reimplemented Blitz::Array functions
121  void reference(ComplexData<N_rank>& rhs) {
123  }
124  template<int M_rank>
125  void reference(const RectView<Array<STD_complex,M_rank>&,STD_complex,M_rank>& rhs) {
127  Array<STD_complex,N_rank>::reference(rhs);
128  }
129 #else
133  template<class T_expr>
134  inline ComplexData<N_rank>& operator = (BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr) {
135  ComplexData<N_rank>::reference(ComplexData<N_rank>(expr)); // forwarding to constructor
136  return *this;
137  }
138 #endif
139 
140 
141 
142  // resolve ambiguities, appears to be obsolete with blitz-0.9 and later versions
143 // Array<STD_complex,N_rank> operator + (const ComplexData<N_rank>& b) const {return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)+Array<STD_complex,N_rank>(b));}
144 // Array<STD_complex,N_rank> operator - (const ComplexData<N_rank>& b) const {return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)-Array<STD_complex,N_rank>(b));}
145 // Array<STD_complex,N_rank> operator * (const ComplexData<N_rank>& b) const {return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)*Array<STD_complex,N_rank>(b));}
146 // Array<STD_complex,N_rank> operator / (const ComplexData<N_rank>& b) const {return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)/Array<STD_complex,N_rank>(b));}
147 
148 
155  void fft(bool forward=true, bool cyclic_shift=true);
156 
164  void partial_fft(const TinyVector<bool,N_rank>& do_fft, bool forward=true, bool cyclic_shift=true);
165 
166 
173  void modulate_offset(const TinyVector<float,N_rank>& rel_offset);
174 
179  void shift_subpixel(const TinyVector<float,N_rank>& shiftvec);
180 
181 
186 
187 
188 };
189 
190 
196 
197 
198 template <int N_rank>
199 void ComplexData<N_rank>::fft(bool forward, bool cyclic_shift) {
200  Log<OdinData> odinlog("ComplexData","fft");
201 
202  TinyVector<bool,N_rank> do_fft=true;
203  ComplexData<N_rank>::partial_fft(do_fft, forward, cyclic_shift);
204 }
205 
206 
208 
209 // call FFT of GSL
210 
211 struct GslFftWorkSpace; // forward declaration
212 
213 class GslFft {
214  public:
215  GslFft(int length);
216  ~GslFft();
217  void fft1d(double* complex_data, bool forward_fft);
218 
219  private:
220  GslFftWorkSpace* ws;
221 };
222 
224 
225 template <int N_rank>
226 void ComplexData<N_rank>::partial_fft(const TinyVector<bool,N_rank>& do_fft, bool forward, bool cyclic_shift) {
227  Log<OdinData> odinlog("ComplexData","partial_fft");
228 
229  TinyVector<int,N_rank> myshape(Array<STD_complex,N_rank>::shape());
230 
231  TinyVector<int,N_rank> cyclshift=(ComplexData<N_rank>::shape())/2;
232 
233  // Shift (back) prior to FFT to get flat phasemap
234  if(cyclic_shift) {
235  for(int irank=0; irank<N_rank; irank++) {
236  if(do_fft(irank)) ComplexData<N_rank>::shift(irank,-cyclshift(irank));
237  }
238  }
239 
240  TinyVector<int,N_rank> indexvec;
241  for(int irank=0; irank<N_rank; irank++) {
242  if(do_fft(irank)) {
243 
244  // This holds the the shape of the subspace which is orthogonal to direction 'irank'
245  TinyVector<int,N_rank> ortho_shape(myshape);
246  ortho_shape(irank)=1;
247 
248  int oneline_size=myshape(irank);
249  double *complex_data= new double[2*oneline_size];
250 
251  GslFft gslfft(oneline_size);
252 
253  // The total number of elements in the orthogonal subspace
254  unsigned long n_ortho=product(ortho_shape);
255  ODINLOG(odinlog,normalDebug) << "oneline_size/irank/n_ortho=" << oneline_size << "/" << irank << "/" << n_ortho << STD_endl;
256 
257  for(unsigned long iortho=0; iortho<n_ortho; iortho++) {
258  indexvec=index2extent<N_rank>(ortho_shape,iortho);
259 
260  for(int j=0; j<oneline_size; j++) {
261  indexvec(irank)=j;
262  complex_data[2*j]= (*this)(indexvec).real();
263  complex_data[2*j+1]=(*this)(indexvec).imag();
264  }
265 
266  gslfft.fft1d(complex_data, forward);
267 
268  for(int j=0; j<oneline_size; j++) {
269  indexvec(irank)=j;
270  float scale=1.0/sqrt(double(oneline_size));
271  (*this)(indexvec)=scale*STD_complex(complex_data[2*j],complex_data[2*j+1]);
272  }
273 
274  }
275  delete[] complex_data;
276  }
277  }
278 
279  // Shift after FFT
280  if(cyclic_shift) {
281  for(int irank=0; irank<N_rank; irank++) {
282  if(do_fft(irank)) {
283  ODINLOG(odinlog,normalDebug) << "Cyclic shift in dim=" << irank << STD_endl;
284  ComplexData<N_rank>::shift(irank,cyclshift(irank)); // scope reuired by GCC 4.7
285  }
286  }
287  }
288 
289 
290 }
291 
292 
294 
295 
296 template <int N_rank>
297 void ComplexData<N_rank>::modulate_offset(const TinyVector<float,N_rank>& rel_offset) {
298  Log<OdinData> odinlog("ComplexData","modulate_offset");
299 
300  TinyVector<int, N_rank> index;
301  TinyVector<float, N_rank> findex;
302  for(unsigned int i=0; i<Array<STD_complex,N_rank>::numElements(); i++) {
304  for(int irank=0; irank<N_rank; irank++) findex(irank)=index(irank);
305  (*this)(index)*=expc(float2imag(-2.0*PII*sum(rel_offset*findex)));
306  }
307 }
308 
310 
311 template <int N_rank>
312 void ComplexData<N_rank>::shift_subpixel(const TinyVector<float,N_rank>& shiftvec) {
313  fft(true);
314 
315  unsigned int totalsize=Array<STD_complex,N_rank>::numElements();
316  TinyVector<int, N_rank> index;
317 
318  for(unsigned int i=0; i<totalsize; i++) {
320  float im=0.0;
321  for(int idim=0; idim<N_rank; idim++) {
322  im+=-2.0*PII*(shiftvec(idim)*float(index(idim))/Array<STD_complex,N_rank>::extent(idim));
323  }
324  STD_complex phase(0,im);
325  (*this)(index)*=exp(phase);
326  }
327 
328 
329  fft(false);
330 }
331 
332 
334 
335 
336 
337 template <int N_rank>
339 
340  const ComplexData<N_rank>& indata=*this;
341 
342  TinyVector<int,N_rank> myshape(indata.shape());
343  Data<float,N_rank> result(myshape);
344 
345  TinyVector<int,N_rank> ortho_shape(myshape);
346  ortho_shape(N_rank-1)=1;
347 
348  int nlast=myshape(N_rank-1);
349  Data<float,1> phasevec(nlast);
350  Data<float,1> unwrapped(nlast);
351 
352  TinyVector<int,N_rank> indexvec;
353 
354  for(int iortho=0; iortho<product(ortho_shape); iortho++) {
355  indexvec=index2extent<N_rank>(ortho_shape,iortho);
356  int ilast;
357  for(ilast=0; ilast<nlast; ilast++) {
358  indexvec(N_rank-1)=ilast;
359  phasevec(ilast)=phase(indata(indexvec));
360  }
361  unwrapped=unwrap_phase(phasevec, nlast/2);
362  for(ilast=0; ilast<nlast; ilast++) {
363  indexvec(N_rank-1)=ilast;
364  result(indexvec)=unwrapped(ilast);
365  }
366  }
367 
368  return result;
369 }
370 
371 
372 
373 #endif
void partial_fft(const TinyVector< bool, N_rank > &do_fft, bool forward=true, bool cyclic_shift=true)
Definition: complexdata.h:226
ComplexData(int extent1)
Definition: complexdata.h:64
void modulate_offset(const TinyVector< float, N_rank > &rel_offset)
Definition: complexdata.h:297
Data< float, N_rank > phasemap() const
Definition: complexdata.h:338
ComplexData(const ComplexData< N_rank > &cd)
Definition: complexdata.h:78
ComplexData(BZ_ETPARM(_bz_ArrayExpr< T_expr >) expr)
Definition: complexdata.h:98
ComplexData< N_rank > & operator=(const ComplexData< N_rank > &d)
Definition: complexdata.h:104
ComplexData(const TinyVector< int, N_rank > &dimvec)
Definition: complexdata.h:56
void shift_subpixel(const TinyVector< float, N_rank > &shiftvec)
Definition: complexdata.h:312
void fft(bool forward=true, bool cyclic_shift=true)
Definition: complexdata.h:199
ComplexData(const Data< STD_complex, N_rank > &a)
Definition: complexdata.h:84
Data< T, N_rank > & operator=(const Data< T, N_rank > &d)
void shift(unsigned int shift_dim, int shift)
TinyVector< int, N_rank > create_index(unsigned long index) const
Definition: tjlog.h:218
Data< float, 1 > unwrap_phase(const Data< float, 1 > &phase, int startindex=0)
fvector phase(const cvector &cv)
fvector real(const cvector &cv)
fvector imag(const cvector &cv)