FFT2D.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: FFT2D.h,v 1.16.16.1 2007/03/25 21:23:44 oliver Exp $
00005 //
00006 
00007 #ifndef BALL_MATHS_TFFT2D_H
00008 #define BALL_MATHS_TFFT2D_H
00009 
00010 #ifndef BALL_COMMON_EXCEPTION_H
00011 # include <BALL/COMMON/exception.h>
00012 #endif
00013 
00014 #ifndef BALL_DATATYPE_REGULARDATA2D_H
00015 # include <BALL/DATATYPE/regularData2D.h>
00016 #endif
00017 
00018 #ifndef BALL_MATHS_VECTOR2_H
00019 # include <BALL/MATHS/vector2.h>
00020 #endif
00021 
00022 #include <math.h>
00023 #include <complex>
00024 #include <fftw3.h>
00025 
00026 #include <BALL/MATHS/fftwCommon.h>
00027 
00028 
00029 namespace BALL
00030 {
00042   template <typename ComplexTraits>
00043   class TFFT2D 
00044     : public TRegularData2D<std::complex<typename ComplexTraits::ComplexPrecision> >
00045   {
00046     public:
00047     
00048       typedef std::complex<typename ComplexTraits::ComplexPrecision> Complex;
00049       typedef TRegularData2D<std::complex<typename ComplexTraits::ComplexPrecision> > ComplexVector;
00050       typedef typename TRegularData2D<std::complex<typename ComplexTraits::ComplexPrecision> >::IndexType IndexType;
00051 
00052       BALL_CREATE(TFFT2D)
00053 
00054       
00057  
00058       
00059       TFFT2D();
00060 
00062       TFFT2D(const TFFT2D &data);
00063 
00073        // AR: ldn is not any longer the binary logarithm but the absolute number of grid points
00074       TFFT2D(Size nX, Size nY, double stepPhysX=1., double stepPhysY=1., Vector2 origin=Vector2(0.,0.), bool inFourierSpace=false);
00075 
00077       virtual ~TFFT2D();
00078       
00080 
00084 
00086       const TFFT2D& operator = (const TFFT2D& fft_2d);
00087       
00090       virtual void clear();
00091       
00094       virtual void destroy();
00095 
00097 
00101 
00104       bool operator == (const TFFT2D& fft_2d) const;
00106       
00107       // @name Accessors
00108       
00111       void doFFT();
00112 
00115       void doiFFT();
00116 
00122       bool translate(const Vector2& trans_origin);
00123 
00129       bool setPhysStepWidth(double new_width_x, double new_width_y);
00130 
00133       double getPhysStepWidthX() const;
00134 
00137       double getPhysStepWidthY() const;
00138 
00141       double getFourierStepWidthX() const;
00142 
00145       double getFourierStepWidthY() const;
00146 
00149       double getPhysSpaceMinX() const;
00150 
00153       double getPhysSpaceMinY() const;
00154 
00157       double getPhysSpaceMaxX() const;
00158 
00161       double getPhysSpaceMaxY() const;
00162 
00165       double getFourierSpaceMinX() const;
00166 
00169       double getFourierSpaceMinY() const;
00170 
00173       double getFourierSpaceMaxX() const;
00174 
00177       double getFourierSpaceMaxY() const;
00178         
00184       Size getMaxXIndex() const;
00185 
00191       Size getMaxYIndex() const;
00192         
00196       Size getNumberOfInverseTransforms() const;
00197 
00200       Vector2 getGridCoordinates(Position position) const;
00201 
00206       Complex getData(const Vector2& pos) const
00207         throw(Exception::OutOfGrid);
00208 
00214       Complex getInterpolatedValue(const Vector2& pos) const
00215         throw(Exception::OutOfGrid);
00216 
00222       void setData(const Vector2& pos, Complex val)
00223         throw(Exception::OutOfGrid);
00224 
00228       Complex& operator[](const Vector2& pos)
00229         throw(Exception::OutOfGrid);
00230 
00234       const Complex& operator[](const Vector2& pos) const
00235         throw(Exception::OutOfGrid);
00236         
00237 
00242       const Complex& operator [] (const IndexType& index) const { return TRegularData2D<Complex>::operator [](index); }
00243 
00248       Complex& operator [] (const IndexType& index) {  return TRegularData2D<Complex>::operator [](index); }
00249       
00252       Complex& operator[](const Position& pos)
00253         throw(Exception::OutOfGrid)
00254       {
00255         return TRegularData2D<Complex>::operator [] (pos);
00256       }
00257 
00260       const Complex& operator[](const Position& pos) const
00261         throw(Exception::OutOfGrid)
00262       {
00263         return TRegularData2D<Complex>::operator [] (pos);
00264       }
00265       
00266       // AR:
00267       void setNumberOfFFTTransforms(Size num)
00268       {
00269         numPhysToFourier_ = num;
00270       }
00271       
00272       // AR:
00273       void setNumberOfiFFTTransforms(Size num)
00274       {
00275         numFourierToPhys_ = num;
00276       }
00277       
00282       Complex phase(const Vector2& pos) const;
00283         
00287       bool isInFourierSpace() const;
00288 
00289     protected:
00290       Size lengthX_, lengthY_;
00291       bool inFourierSpace_;
00292       Size numPhysToFourier_;
00293       Size numFourierToPhys_;
00294       Vector2 origin_;
00295       double stepPhysX_, stepPhysY_;
00296       double stepFourierX_, stepFourierY_;
00297       Vector2 minPhys_, maxPhys_;
00298       Vector2 minFourier_, maxFourier_;
00299       
00300       // AR: new version for FFTW3
00301       typename ComplexTraits::FftwPlan planForward_;
00302       typename ComplexTraits::FftwPlan planBackward_;
00303 
00304       
00305       // AR: to control plan calculation with new fftw3
00306       Size dataLength_;
00307       Complex *dataAdress_;
00308       bool planCalculated_;
00309       
00310   };
00311   
00314   typedef TFFT2D<BALL_FFTW_DEFAULT_TRAITS> FFT2D;
00315   
00316   // AR:
00319   template <typename ComplexTraits>
00320   const TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& operator<< 
00321       (TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& to, const TFFT2D<ComplexTraits>& from);
00322   
00327   template <typename ComplexTraits>
00328   const RegularData2D& operator << (RegularData2D& to, const TFFT2D<ComplexTraits>& from);
00329   
00330   template <typename ComplexTraits>
00331   TFFT2D<ComplexTraits>::TFFT2D()
00332     : TRegularData2D<Complex>(),
00333       dataLength_(0),
00334       dataAdress_(0),
00335       planCalculated_(false)
00336   {
00337   }
00338   
00339   template <typename ComplexTraits>
00340   bool TFFT2D<ComplexTraits>::operator == (const TFFT2D<ComplexTraits>& fft2D) const
00341   {
00342     // AR: test whether data_.size() == fft2D.data_.size()
00343     //     instead of testing 2 lengths. Better for vector handling.
00344     
00345     if (lengthX_ == fft2D.lengthX_ &&
00346         lengthY_ == fft2D.lengthY_ &&
00347         origin_ == fft2D.origin_ &&
00348         stepPhysX_ == fft2D.stepPhysX_ &&
00349         stepPhysY_ == fft2D.stepPhysY_ &&
00350         stepFourierX_ == fft2D.stepFourierX_ &&
00351         stepFourierY_ == fft2D.stepFourierY_ &&
00352         minPhys_ == fft2D.minPhys_ &&
00353         maxPhys_ == fft2D.maxPhys_ &&
00354         minFourier_ == fft2D.minFourier_ &&
00355         maxFourier_ == fft2D.maxFourier_ &&
00356         numPhysToFourier_ == fft2D.numPhysToFourier_ &&
00357         numFourierToPhys_ == fft2D.numFourierToPhys_)
00358     {
00359       Vector2 min  = inFourierSpace_ ?  minFourier_  :   minPhys_;
00360       Vector2 max  = inFourierSpace_ ?  maxFourier_  :   maxPhys_;
00361       double stepX = inFourierSpace_ ? stepFourierX_ : stepPhysX_;
00362       double stepY = inFourierSpace_ ? stepFourierY_ : stepPhysY_;  
00363       
00364       for (double posX=min.x; posX<=max.x; posX+=stepX)
00365       {
00366         for (double posY=min.y; posY<=max.y; posY+=stepY)
00367         {
00368           if (getData(Vector2(posX,posY)) != fft2D.getData(Vector2(posX,posY)))
00369           {
00370             return false;
00371           }
00372         }
00373       }
00374       
00375       return true;
00376     }
00377   
00378     return false;
00379   }
00380   
00381   template <typename ComplexTraits>
00382   bool TFFT2D<ComplexTraits>::translate(const Vector2& trans_origin)
00383   {
00384     Position internalOriginX = (Position) Maths::rint(trans_origin.x*stepPhysX_);
00385     Position internalOriginY = (Position) Maths::rint(trans_origin.y*stepPhysY_);
00386     
00387     if ((internalOriginX <= lengthX_) && (internalOriginY <= lengthY_))
00388     {
00389       origin_.x = trans_origin.x;
00390       origin_.y = trans_origin.y;
00391       
00392       minPhys_ = Vector2(-origin_.x,-origin_.y);
00393       maxPhys_ = Vector2(((lengthX_-1)*stepPhysX_)-origin_.x,((lengthY_-1)*stepPhysY_)-origin_.y);
00394       minFourier_ = Vector2(-(lengthX_/2.-1)*stepFourierX_,-(lengthY_/2.-1)*stepFourierY_);
00395       maxFourier_ = Vector2((lengthX_/2.)*stepFourierX_,(lengthY_/2.)*stepFourierY_);
00396      
00397       return true;
00398     }
00399     else
00400     {
00401       return false;
00402     }
00403   }
00404 
00405   template <typename ComplexTraits>
00406   bool TFFT2D<ComplexTraits>::setPhysStepWidth(double new_width_x, double new_width_y)
00407   {
00408     if ((new_width_x <= 0) || (new_width_y <= 0))
00409     {
00410       return false;
00411     }
00412     else
00413     {
00414       stepPhysX_ = new_width_x;
00415       stepPhysY_ = new_width_y;
00416       stepFourierX_ = 2.*M_PI/(stepPhysX_*lengthX_);
00417       stepFourierY_ = 2.*M_PI/(stepPhysY_*lengthY_);
00418 
00419       minPhys_ = Vector2(-origin_.x,-origin_.y);
00420       maxPhys_ = Vector2(((lengthX_-1)*stepPhysX_)-origin_.x,((lengthY_-1)*stepPhysY_)-origin_.y);
00421       minFourier_ = Vector2(-(lengthX_/2.-1)*stepFourierX_,-(lengthY_/2.-1)*stepFourierY_);
00422       maxFourier_ = Vector2((lengthX_/2.)*stepFourierX_,(lengthY_/2.)*stepFourierY_);
00423   
00424       return true;
00425     }
00426   }
00427   
00428   template <typename ComplexTraits>
00429   double TFFT2D<ComplexTraits>::getPhysStepWidthX() const
00430   {
00431     return stepPhysX_;
00432   }
00433 
00434   template <typename ComplexTraits>
00435   double TFFT2D<ComplexTraits>::getPhysStepWidthY() const
00436   {
00437     return stepPhysY_;
00438   }
00439 
00440   template <typename ComplexTraits>
00441   double TFFT2D<ComplexTraits>::getFourierStepWidthX() const
00442   {
00443     return stepFourierX_;
00444   }
00445 
00446   template <typename ComplexTraits>
00447   double TFFT2D<ComplexTraits>::getFourierStepWidthY() const
00448   {
00449     return stepFourierY_;
00450   }
00451 
00452   template <typename ComplexTraits>
00453   double TFFT2D<ComplexTraits>::getPhysSpaceMinX() const
00454   {
00455     return minPhys_.x;
00456   }
00457 
00458   template <typename ComplexTraits>
00459   double TFFT2D<ComplexTraits>::getPhysSpaceMinY() const
00460   {
00461     return minPhys_.y;
00462   }
00463 
00464   template <typename ComplexTraits>
00465   double TFFT2D<ComplexTraits>::getPhysSpaceMaxX() const
00466   {
00467     return maxPhys_.x;
00468   }
00469 
00470   template <typename ComplexTraits>
00471   double TFFT2D<ComplexTraits>::getPhysSpaceMaxY() const
00472   {
00473     return maxPhys_.y;
00474   }
00475 
00476   template <typename ComplexTraits>
00477   double TFFT2D<ComplexTraits>::getFourierSpaceMinX() const
00478   {
00479     return minFourier_.x;
00480   }
00481 
00482   template <typename ComplexTraits>
00483   double TFFT2D<ComplexTraits>::getFourierSpaceMinY() const
00484   {
00485     return minFourier_.y;
00486   }
00487 
00488   template <typename ComplexTraits>
00489   double TFFT2D<ComplexTraits>::getFourierSpaceMaxX() const
00490   {
00491     return maxFourier_.x;
00492   }
00493 
00494   template <typename ComplexTraits>
00495   double TFFT2D<ComplexTraits>::getFourierSpaceMaxY() const
00496   {
00497     return maxFourier_.y;
00498   }
00499   
00500   template <typename ComplexTraits>
00501   Size TFFT2D<ComplexTraits>::getMaxXIndex() const
00502   {
00503     return (lengthX_ - 1);
00504   }
00505   
00506   template <typename ComplexTraits>
00507   Size TFFT2D<ComplexTraits>::getMaxYIndex() const
00508   {
00509     return (lengthY_ - 1);
00510   }
00511   
00512   template <typename ComplexTraits>
00513   Size TFFT2D<ComplexTraits>::getNumberOfInverseTransforms() const
00514   {
00515     return numFourierToPhys_;
00516   }
00517   
00518   // AR: new for compatibility with FFT3D
00519   template <typename ComplexTraits>
00520   Vector2 TFFT2D<ComplexTraits>::getGridCoordinates(Position position) const
00521   {
00522     if (!inFourierSpace_)
00523     {
00524       if (position >= ComplexVector::size())
00525       {
00526         throw Exception::OutOfGrid(__FILE__, __LINE__);
00527       }
00528     
00529       Vector2 r;
00530       Position  x, y;
00531 
00532 
00533       // AR: ??????
00534       y = position % lengthY_;
00535       x = position / lengthY_;
00536 
00537       r.set(-origin_.x + (float)x * stepPhysX_,
00538             -origin_.y + (float)y * stepPhysY_);
00539 
00540       return r;
00541     }
00542     else
00543     {
00544       if (position >= ComplexVector::size())
00545       {
00546         throw Exception::OutOfGrid(__FILE__, __LINE__);
00547       }
00548     
00549       Vector2 r;
00550       Index x, y;
00551   
00552       // AR: ??????
00553       y = position % lengthY_;
00554       x = position / lengthY_;
00555 
00556       if (x>=lengthX_/2.)
00557       {
00558         x-=lengthX_;
00559       }
00560       
00561       if (y>=lengthY_/2.)
00562       {
00563         y-=lengthY_;
00564       }
00565 
00566       r.set((float)x * stepFourierX_,
00567             (float)y * stepFourierY_);
00568 
00569       return r;
00570     }
00571   }
00572   
00573   
00574   
00575   template <typename ComplexTraits>
00576   typename TFFT2D<ComplexTraits>::Complex TFFT2D<ComplexTraits>::getData(const Vector2& pos) const
00577     throw(Exception::OutOfGrid)
00578   {
00579     Complex result;
00580     double normalization=1.;
00581 
00582     if (!inFourierSpace_)
00583     {
00584       result = (*this)[pos];
00585       normalization=1./((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_));
00586     }
00587     else
00588     {
00589       result = (*this)[pos] * phase(pos);
00590       normalization=1./(2.*M_PI)*(stepPhysX_*stepPhysY_)/((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_));
00591     }
00592 
00593     result *= normalization;
00594     
00595     return result;
00596   }
00597 
00598   template <typename ComplexTraits>
00599   typename TFFT2D<ComplexTraits>::Complex TFFT2D<ComplexTraits>::getInterpolatedValue(const Vector2& pos) const
00600     throw(Exception::OutOfGrid)
00601   {
00602     Complex result;
00603     
00604     Vector2 min  = inFourierSpace_ ? minFourier_   :   minPhys_;
00605     Vector2 max  = inFourierSpace_ ? maxFourier_   :   maxPhys_;
00606     double stepX = inFourierSpace_ ? stepFourierX_ : stepPhysX_;
00607     double stepY = inFourierSpace_ ? stepFourierY_ : stepPhysY_;
00608     
00609     if (    (pos.x < min.x) || (pos.y < min.y)
00610          || (pos.x > max.x) || (pos.y > max.y)  )
00611     {
00612       throw Exception::OutOfGrid(__FILE__, __LINE__);
00613     }
00614 
00615     Vector2 h(pos.x - min.x, pos.y - min.y);
00616     double modX = fmod((double)h.x,stepX);
00617     double modY = fmod((double)h.y,stepY);
00618 
00619     if (modX==0 && modY ==0) // we are on the grid
00620     {
00621       return getData(pos);
00622     }
00623 
00624     double beforeX = floor(h.x/stepX)*stepX+ min.x;
00625     double beforeY = floor(h.y/stepY)*stepY+ min.y;
00626     double afterX  =  ceil(h.x/stepX)*stepX+ min.x;
00627     double afterY  =  ceil(h.y/stepY)*stepY+ min.y;
00628       
00629     double tx = (pos.x - beforeX)/stepX;
00630     double ty = (pos.y - beforeY)/stepY;
00631 
00632     result  = getData(Vector2(beforeX,beforeY))*(typename ComplexTraits::ComplexPrecision)((1.-tx)*(1.-ty));
00633     result += getData(Vector2(afterX, beforeY))*(typename ComplexTraits::ComplexPrecision)(    tx *(1.-ty));
00634     result += getData(Vector2(beforeX,afterY ))*(typename ComplexTraits::ComplexPrecision)((1.-tx)*    ty );
00635     result += getData(Vector2(afterX, afterY ))*(typename ComplexTraits::ComplexPrecision)(    tx *    ty );
00636 
00637     return result;
00638   }
00639 
00640   template <typename ComplexTraits>
00641   void TFFT2D<ComplexTraits>::setData(const Vector2& pos, Complex val)
00642     throw(Exception::OutOfGrid)
00643   {
00644     Complex dummy;
00645   
00646     if (!inFourierSpace_)
00647     {
00648       dummy = Complex(val.real()*((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_)),
00649                         val.imag()*((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_)));
00650   
00651       (*this)[pos]=dummy;
00652     }
00653     else
00654     {
00655       val*=phase(pos)*(typename ComplexTraits::ComplexPrecision)((2*M_PI/(stepPhysX_*stepPhysY_)))
00656                      *(typename ComplexTraits::ComplexPrecision)pow((typename ComplexTraits::ComplexPrecision)(lengthX_*lengthY_),(int)numFourierToPhys_);
00657       
00658       dummy = val;
00659     
00660       (*this)[pos]=dummy;
00661     }
00662   }
00663 
00664   template <typename ComplexTraits>
00665   typename TFFT2D<ComplexTraits>::Complex& TFFT2D<ComplexTraits>::operator[](const Vector2& pos)
00666     throw(Exception::OutOfGrid)
00667   {
00668     Index internalPos;
00669 
00670     if (!inFourierSpace_)
00671     {
00672       Index i, j;
00673       
00674       i = (Index) Maths::rint((pos.x+origin_.x)/stepPhysX_);
00675       j = (Index) Maths::rint((pos.y+origin_.y)/stepPhysY_);
00676 
00677       internalPos = j + i*lengthY_;
00678     }
00679     else
00680     {
00681       Index i, j;
00682 
00683       i = (Index) Maths::rint(pos.x/stepFourierX_);
00684       j = (Index) Maths::rint(pos.y/stepFourierY_);
00685 
00686       if (i<0)
00687       {
00688         i+=lengthX_;
00689       }
00690 
00691       if (j<0)
00692       {
00693         j+=lengthY_;
00694       }
00695 
00696       internalPos = (j + i*lengthY_);
00697     }
00698 
00699     if ((internalPos < 0) || (internalPos>=(Index) (lengthX_*lengthY_)))
00700     {
00701       throw Exception::OutOfGrid(__FILE__, __LINE__);
00702     }
00703     
00704     return operator [] (internalPos);
00705   }
00706 
00707   template <typename ComplexTraits>
00708   const typename TFFT2D<ComplexTraits>::Complex& TFFT2D<ComplexTraits>::operator[](const Vector2& pos) const
00709     throw(Exception::OutOfGrid)
00710   {
00711     Index internalPos;
00712 
00713     if (!inFourierSpace_)
00714     {
00715       Index i, j;
00716       
00717       i = (Index) Maths::rint((pos.x+origin_.x)/stepPhysX_);
00718       j = (Index) Maths::rint((pos.y+origin_.y)/stepPhysY_);
00719 
00720       internalPos = j + i*lengthY_;
00721     }
00722     else
00723     {
00724       Index i, j;
00725 
00726       i = (Index) Maths::rint(pos.x/stepFourierX_);
00727       j = (Index) Maths::rint(pos.y/stepFourierY_);
00728 
00729       if (i<0)
00730       {
00731         i+=lengthX_;
00732       }
00733 
00734       if (j<0)
00735       {
00736         j+=lengthY_;
00737       }
00738 
00739       internalPos = (j + i*lengthY_);
00740     }
00741 
00742     if ((internalPos < 0) || (internalPos>=(Index) (lengthX_*lengthY_)))
00743     {
00744       throw Exception::OutOfGrid(__FILE__, __LINE__);
00745     }
00746     
00747     return operator [] (internalPos);
00748   }
00749   
00750   template <typename ComplexTraits>
00751   typename TFFT2D<ComplexTraits>::Complex TFFT2D<ComplexTraits>::phase(const Vector2& pos) const
00752   {
00753     double phase = 2.*M_PI*(  Maths::rint(pos.x/stepFourierX_)*Maths::rint(origin_.x/stepPhysX_)
00754                               /lengthX_
00755                             + Maths::rint(pos.y/stepFourierY_)*Maths::rint(origin_.y/stepPhysY_)
00756                               /lengthY_ );
00757 
00758     Complex result = Complex(cos(phase), sin(phase));
00759             
00760     return result;
00761   }
00762   
00763   template <typename ComplexTraits>
00764   bool TFFT2D<ComplexTraits>::isInFourierSpace() const
00765   {
00766     return inFourierSpace_;
00767   }
00768   
00769   template <typename ComplexTraits>
00770   const TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& operator << 
00771     (TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& to, const TFFT2D<ComplexTraits>& from)
00772   {
00773     // first decide if the FFT3D data is in Fourier space.
00774     if (!from.isInFourierSpace())
00775     {
00776       // create a new grid
00777       Size lengthX = from.getMaxXIndex()+1;
00778       Size lengthY = from.getMaxYIndex()+1;
00779       
00780       TRegularData2D<typename TFFT2D<ComplexTraits>::Complex> newGrid(TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>::IndexType(lengthX, lengthY),
00781                                       Vector2(from.getPhysSpaceMinX(), from.getPhysSpaceMinY()),
00782                                       Vector2(from.getPhysSpaceMaxX(), from.getPhysSpaceMaxY()));
00783 
00784       // and fill it
00785       double normalization=1./(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00786       typename TFFT2D<ComplexTraits>::Complex dataIn;
00787       typename TFFT2D<ComplexTraits>::Complex dataOut;
00788       
00789       for (Position i = 0; i < from.size(); i++)
00790       {
00791         Position x, y;
00792 
00793         y =  i % lengthY;
00794         x =  i / lengthY;
00795 
00796         dataIn  = from[i];
00797         dataOut = dataIn;
00798         
00799         newGrid[x + y*lengthY] = dataOut*(typename ComplexTraits::ComplexPrecision)normalization;
00800       }
00801 
00802       to = newGrid;
00803 
00804       return to;
00805     }
00806     else
00807     {
00808       // we are in Fourier space
00809       
00810       // create a new grid
00811       Size lengthX = from.getMaxXIndex()+1;
00812       Size lengthY = from.getMaxYIndex()+1;
00813       //float stepPhysX = from.getPhysStepWidthX();
00814       //float stepPhysY = from.getPhysStepWidthY();
00815       float stepFourierX = from.getFourierStepWidthX();
00816       float stepFourierY = from.getFourierStepWidthY();
00817 
00818 
00819       
00820       TRegularData2D<typename TFFT2D<ComplexTraits>::Complex> newGrid(TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>::IndexType(lengthX, lengthY),
00821                                       Vector2(from.getFourierSpaceMinX(), 
00822                                               from.getFourierSpaceMinY()),
00823                                       Vector2(from.getFourierSpaceMaxX(),
00824                                               from.getFourierSpaceMaxY()));
00825 
00826       // and fill it
00827       // AR: old double normalization=1./(sqrt(2.*M_PI))*(stepPhysX*stepPhysY*stepPhysZ)/(pow((float)(lengthX*lengthY*lengthZ),from.getNumberOfInverseTransforms()));
00828       double normalization=1./(2.*M_PI)/(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00829       
00830       
00831       Index x, y;
00832       Vector2 r;
00833       typename TFFT2D<ComplexTraits>::Complex dataIn;
00834       typename TFFT2D<ComplexTraits>::Complex dataOut;
00835   
00836       for (Position i = 0; i < from.size(); i++)
00837       {
00838         y =  i % lengthY;
00839         x =  i / lengthY;
00840 
00841         if (x>lengthX/2.)
00842         {
00843           x-=lengthX;
00844         }
00845 
00846         if (y>lengthY/2.)
00847         {
00848           y-=lengthY;
00849         }
00850 
00851         r.set((float)x * stepFourierX,
00852               (float)y * stepFourierY);
00853 
00854         dataIn = from[i];
00855         dataOut = dataIn;
00856         
00857         newGrid[x + y*lengthY] = dataOut*(typename ComplexTraits::ComplexPrecision)normalization*from.phase(r);
00858       }
00859 
00860       to = newGrid;
00861 
00862       return to;
00863     }
00864   }
00865   
00866   template <typename ComplexTraits>
00867   const RegularData2D& operator << (RegularData2D& to, const TFFT2D<ComplexTraits>& from)
00868   {
00869     // first decide if the FFT2D data is in Fourier space.
00870     if (!from.isInFourierSpace())
00871     {
00872       // create a new grid
00873       Size lengthX = from.getMaxXIndex()+1;
00874       Size lengthY = from.getMaxYIndex()+1;
00875       
00876       RegularData2D newGrid(RegularData2D::IndexType(lengthX, lengthY),
00877                             Vector2(from.getPhysSpaceMinX(), 
00878                                     from.getPhysSpaceMinY()),
00879                             Vector2(from.getPhysSpaceMaxX(),
00880                                     from.getPhysSpaceMaxY()));
00881 
00882       // and fill it
00883       double normalization = 1./(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00884       typename TFFT2D<ComplexTraits>::Complex dataIn;
00885       typename TFFT2D<ComplexTraits>::Complex dataOut;
00886 
00887       typename TFFT2D<ComplexTraits>::IndexType current_index;
00888       typename RegularData2D::IndexType regdat_index;
00889       for (current_index.x = 0; current_index.x < lengthX; current_index.x++)
00890       {
00891         for (current_index.y = 0; current_index.y < lengthY; current_index.y++)
00892         {
00893           regdat_index.x = current_index.x;
00894           regdat_index.y = current_index.y;
00895 
00896           dataIn  = from[current_index];
00897           dataOut = dataIn;
00898         
00899           newGrid[regdat_index] = dataOut.real()*normalization;
00900         }
00901       }
00902 
00903       to = newGrid;
00904 
00905       return to;
00906     }
00907     else
00908     {
00909       // we are in Fourier space
00910       
00911       // create a new grid
00912       Size lengthX = from.getMaxXIndex()+1;
00913       Size lengthY = from.getMaxYIndex()+1;
00914       //float stepPhysX = from.getPhysStepWidthX();
00915       //float stepPhysY = from.getPhysStepWidthY();
00916       float stepFourierX = from.getFourierStepWidthX();
00917       float stepFourierY = from.getFourierStepWidthY();
00918   
00919       RegularData2D newGrid(RegularData2D::IndexType(lengthX, lengthY), Vector2(from.getFourierSpaceMinX(), from.getFourierSpaceMinY()), Vector2(from.getFourierSpaceMaxX(), from.getFourierSpaceMaxY()));
00920 
00921       // and fill it
00922       // AR: old version double normalization=1./(sqrt(2.*M_PI))*(stepPhysX*stepPhysY*stepPhysZ)/(pow((float)(lengthX*lengthY*lengthZ),from.getNumberOfInverseTransforms()));
00923       double normalization=1./(2.*M_PI)/(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00924       
00925       Index x, y;
00926       signed int xp, yp;
00927       Vector2 r;
00928       typename TFFT2D<ComplexTraits>::Complex dataIn;
00929       typename TFFT2D<ComplexTraits>::Complex dataOut;
00930   
00931       RegularData2D::IndexType current_index;
00932       for (Position i = 0; i < from.size(); i++)
00933       {
00934         y =  i % lengthY;
00935         x =  i / lengthY;
00936         
00937         xp = x;
00938         yp = y;
00939 
00940         if (xp>=lengthX/2.)
00941         {
00942           xp-=(int)lengthX;
00943         }
00944         if (yp>=lengthY/2.)
00945         {
00946           yp-=(int)lengthY;
00947         }
00948 
00949         if (x>=lengthX/2.)
00950         {
00951           x-=(int)(lengthX/2.);
00952         }
00953         else
00954         {
00955           x+=(int)(lengthX/2.);
00956         }
00957 
00958         if (y>=lengthY/2.)
00959         {
00960           y-=(int)(lengthY/2.);
00961         }
00962         else
00963         {
00964           y+=(int)(lengthY/2.);
00965         }
00966 
00967 
00968         r.set((float)xp * stepFourierX,
00969               (float)yp * stepFourierY);
00970 
00971         dataIn = from[i];
00972         dataOut = dataIn;
00973 
00974         current_index.x = x;
00975         current_index.y = y;
00976 
00977         newGrid[current_index] = (dataOut*(typename ComplexTraits::ComplexPrecision)normalization*from.phase(r)).real();
00978       }
00979 
00980       to = newGrid;
00981 
00982       return to;
00983     }
00984   }
00985   
00986   
00987   
00988 }
00989 
00990 #endif // BALL_MATHS_TFFT2D_H