00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef COMPLEXDATA_H
00019 #define COMPLEXDATA_H
00020
00021
00022 #include <odindata/data.h>
00023 #include <odindata/utils.h>
00024
00025
00033
00034
00035
00042 template <int N_rank>
00043 class ComplexData : public Data<STD_complex,N_rank> {
00044
00045 public:
00046
00050 ComplexData() {}
00051
00052
00056 ComplexData(const TinyVector<int,N_rank>& dimvec, const STD_complex& val=0) : Data<STD_complex,N_rank>(dimvec) {(*this)=val;}
00057
00058
00063
00064 ComplexData(int extent1) : Data<STD_complex,N_rank>(extent1) {}
00065 ComplexData(int extent1, int extent2) : Data<STD_complex,N_rank>(extent1,extent2) {}
00066 ComplexData(int extent1, int extent2,int extent3) : Data<STD_complex,N_rank>(extent1,extent2,extent3) {}
00067 ComplexData(int extent1, int extent2,int extent3,int extent4) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4) {}
00068 ComplexData(int extent1, int extent2,int extent3,int extent4,int extent5) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4,extent5) {}
00069 ComplexData(int extent1, int extent2,int extent3,int extent4,int extent5,int extent6) : Data<STD_complex,N_rank>(extent1,extent2,extent3,extent4,extent5,extent6) {}
00070 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) {}
00071 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) {}
00072 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) {}
00073
00074
00078 ComplexData(const ComplexData<N_rank>& cd) : Data<STD_complex,N_rank>(cd) {}
00079
00080
00084 ComplexData(const Data<STD_complex,N_rank>& a) : Data<STD_complex,N_rank>(a) {}
00085
00086
00090 ComplexData<N_rank>& operator = (const ComplexData<N_rank>& d) {Data<STD_complex,N_rank>::operator=(d); return *this;}
00091
00092
00096 ComplexData<N_rank>& operator = (const Array<STD_complex,N_rank>& a) {Array<STD_complex,N_rank>::operator=(a); return *this;}
00097
00098
00102 ComplexData<N_rank>& operator = (const STD_complex& val) {Data<STD_complex,N_rank>::operator=(val); return *this;}
00103
00104
00108 template<class T_expr>
00109 inline ComplexData<N_rank>& operator = (BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr) {
00110 typedef _bz_typename T_expr::T_numtype T_numtype;
00111 evaluate(expr, _bz_update<T_numtype, _bz_typename T_expr::T_numtype>());
00112 return *this;
00113 }
00114
00115
00119 Array<STD_complex,N_rank> operator + (const ComplexData<N_rank>& b) const {
00120 return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)+Array<STD_complex,N_rank>(b));
00121 }
00122
00126 Array<STD_complex,N_rank> operator - (const ComplexData<N_rank>& b) const {
00127 return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)-Array<STD_complex,N_rank>(b));
00128 }
00129
00133 Array<STD_complex,N_rank> operator * (const ComplexData<N_rank>& b) const {
00134 return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)*Array<STD_complex,N_rank>(b));
00135 }
00136
00140 Array<STD_complex,N_rank> operator / (const ComplexData<N_rank>& b) const {
00141 return Array<STD_complex,N_rank>(Array<STD_complex,N_rank>(*this)/Array<STD_complex,N_rank>(b));
00142 }
00143
00144
00151 void fft(bool forward=true, bool cyclic_shift=true);
00152
00160 void partial_fft(const TinyVector<bool,N_rank>& do_fft, bool forward=true, bool cyclic_shift=true);
00161
00162
00169 void modulate_offset(const TinyVector<float,N_rank>& rel_offset);
00170
00175 void shift_subpixel(const TinyVector<float,N_rank>& shiftvec);
00176
00177
00181 Data<float,N_rank> phasemap() const;
00182
00183
00184 };
00185
00186
00191
00192
00193
00194 template <int N_rank>
00195 void ComplexData<N_rank>::fft(bool forward, bool cyclic_shift) {
00196 Log<OdinData> odinlog("ComplexData","fft");
00197
00198 TinyVector<bool,N_rank> do_fft=true;
00199 ComplexData<N_rank>::partial_fft(do_fft, forward, cyclic_shift);
00200 }
00201
00202
00204
00205
00206
00207 struct GslFftWorkSpace;
00208
00209 class GslFft {
00210 public:
00211 GslFft(int length);
00212 ~GslFft();
00213 void fft1d(double* complex_data, bool forward_fft);
00214
00215 private:
00216 int length_cache;
00217 GslFftWorkSpace* ws;
00218 };
00219
00221
00222 template <int N_rank>
00223 void ComplexData<N_rank>::partial_fft(const TinyVector<bool,N_rank>& do_fft, bool forward, bool cyclic_shift) {
00224 Log<OdinData> odinlog("ComplexData","partial_fft");
00225
00226 TinyVector<int,N_rank> myshape(Array<STD_complex,N_rank>::shape());
00227
00228 TinyVector<int,N_rank> cyclshift=(ComplexData<N_rank>::shape())/2;
00229
00230
00231 if(cyclic_shift) {
00232 for(int irank=0; irank<N_rank; irank++) {
00233 if(do_fft(irank)) ComplexData<N_rank>::shift(irank,-cyclshift(irank));
00234 }
00235 }
00236
00237 TinyVector<int,N_rank> indexvec;
00238 for(int irank=0; irank<N_rank; irank++) {
00239 if(do_fft(irank)) {
00240
00241
00242 TinyVector<int,N_rank> ortho_shape(myshape);
00243 ortho_shape(irank)=1;
00244
00245 int oneline_size=myshape(irank);
00246 double *complex_data= new double[2*oneline_size];
00247
00248 GslFft gslfft(oneline_size);
00249
00250
00251 unsigned long n_ortho=product(ortho_shape);
00252 ODINLOG(odinlog,normalDebug) << "oneline_size/irank/n_ortho=" << oneline_size << "/" << irank << "/" << n_ortho << STD_endl;
00253
00254 for(unsigned long iortho=0; iortho<n_ortho; iortho++) {
00255 indexvec=index2extent<N_rank>(ortho_shape,iortho);
00256
00257 for(int j=0; j<oneline_size; j++) {
00258 indexvec(irank)=j;
00259 complex_data[2*j]= (*this)(indexvec).real();
00260 complex_data[2*j+1]=(*this)(indexvec).imag();
00261 }
00262
00263 gslfft.fft1d(complex_data, forward);
00264
00265 for(int j=0; j<oneline_size; j++) {
00266 indexvec(irank)=j;
00267 float scale=1.0/sqrt(double(oneline_size));
00268 (*this)(indexvec)=scale*STD_complex(complex_data[2*j],complex_data[2*j+1]);
00269 }
00270
00271 }
00272 delete[] complex_data;
00273 }
00274 }
00275
00276
00277 if(cyclic_shift) {
00278 for(int irank=0; irank<N_rank; irank++) {
00279 if(do_fft(irank)) {
00280 ODINLOG(odinlog,normalDebug) << "Cyclic shift in dim=" << irank << STD_endl;
00281 shift(irank,cyclshift(irank));
00282 }
00283 }
00284 }
00285
00286
00287 }
00288
00289
00291
00292
00293 template <int N_rank>
00294 void ComplexData<N_rank>::modulate_offset(const TinyVector<float,N_rank>& rel_offset) {
00295 Log<OdinData> odinlog("ComplexData","modulate_offset");
00296
00297 TinyVector<int, N_rank> index;
00298 for(int i=0; i<Array<STD_complex,N_rank>::numElements(); i++) {
00299 index=Data<STD_complex,N_rank>::create_index(i);
00300 (*this)(index)*=exp(float2imag(-2.0*PII*sum(rel_offset*index)));
00301 }
00302 }
00303
00305
00306 template <int N_rank>
00307 void ComplexData<N_rank>::shift_subpixel(const TinyVector<float,N_rank>& shiftvec) {
00308 fft(true);
00309
00310 unsigned int totalsize=Array<STD_complex,N_rank>::numElements();
00311 TinyVector<int, N_rank> index;
00312
00313 for(unsigned int i=0; i<totalsize; i++) {
00314 index=Data<STD_complex,N_rank>::create_index(i);
00315 float im=0.0;
00316 for(int idim=0; idim<N_rank; idim++) {
00317 im+=-2.0*PII*(shiftvec(idim)*float(index(idim))/Array<STD_complex,N_rank>::extent(idim));
00318 }
00319 STD_complex phase(0,im);
00320 (*this)(index)*=exp(phase);
00321 }
00322
00323
00324 fft(false);
00325 }
00326
00327
00329
00330
00331
00332 template <int N_rank>
00333 Data<float,N_rank> ComplexData<N_rank>::phasemap() const {
00334 Data<float,N_rank> phasemap_result(phase(*this));
00335 unwrapPhase1d(phasemap_result);
00336 return phasemap_result;
00337 }
00338
00339
00340
00341 #endif