5 #ifndef BALL_MATHS_TFFT3D_H
6 #define BALL_MATHS_TFFT3D_H
8 #ifndef BALL_COMMON_EXCEPTION_H
13 #ifndef BALL_DATATYPE_REGULARDATA3D_H
38 template <
typename ComplexTraits>
40 :
public TRegularData3D<std::complex<typename ComplexTraits::ComplexPrecision> >
44 typedef std::complex<typename ComplexTraits::ComplexPrecision>
Complex;
57 TFFT3D(const TFFT3D &data);
73 TFFT3D(
Size ldnX,
Size ldnY,
Size ldnZ,
double stepPhysX=1.,
double stepPhysY=1.,
double stepPhysZ=1.,
Vector3 origin=
Vector3(0.,0.,0),
bool inFourierSpace=false);
85 const TFFT3D& operator = (const TFFT3D& fft_3d);
103 bool operator == (const TFFT3D& fft3d) const;
122 bool translate(const Vector3& trans_origin);
129 bool setPhysStepWidth(
double new_width_x,
double new_width_y,
double new_width_z);
265 Complex& operator[](const Vector3& pos);
272 const
Complex& operator[](const Vector3& pos) const;
351 template <
typename ComplexTraits>
359 template <
typename ComplexTraits>
360 const RegularData3D& operator << (RegularData3D& to, const TFFT3D<ComplexTraits>& from);
363 template <
typename ComplexTraits>
368 planCalculated_(false)
372 template <
typename ComplexTraits>
397 Vector3 min = inFourierSpace_ ? minFourier_ : minPhys_;
398 Vector3 max = inFourierSpace_ ? maxFourier_ : maxPhys_;
399 double stepX = inFourierSpace_ ? stepFourierX_ : stepPhysX_;
400 double stepY = inFourierSpace_ ? stepFourierY_ : stepPhysY_;
401 double stepZ = inFourierSpace_ ? stepFourierZ_ : stepPhysZ_;
403 for (
double posX=min.
x; posX<=max.
x; posX+=stepX)
405 for (
double posY=min.
y; posY<=max.
y; posY+=stepY)
407 for (
double posZ=min.
z; posZ<=max.
z; posZ+=stepZ)
423 template <
typename ComplexTraits>
430 if ((internalOriginX <= lengthX_) && (internalOriginY <= lengthY_) && (internalOriginZ <= lengthZ_))
432 origin_.x = trans_origin.
x;
433 origin_.y = trans_origin.
y;
434 origin_.z = trans_origin.
z;
436 minPhys_ =
Vector3(-origin_.x,-origin_.y,-origin_.z);
437 maxPhys_ =
Vector3(((lengthX_-1)*stepPhysX_)-origin_.x,((lengthY_-1)*stepPhysY_)-origin_.y,((lengthZ_-1)*stepPhysZ_)-origin_.z);
438 minFourier_ =
Vector3(-(lengthX_/2.-1)*stepFourierX_,-(lengthY_/2.-1)*stepFourierY_,-(lengthZ_/2.-1)*stepFourierZ_);
439 maxFourier_ =
Vector3((lengthX_/2.)*stepFourierX_,(lengthY_/2.)*stepFourierY_,(lengthZ_/2.)*stepFourierZ_);
449 template <
typename ComplexTraits>
452 if ((new_width_x <= 0) || (new_width_y <= 0) || (new_width_z <= 0))
458 stepPhysX_ = new_width_x;
459 stepPhysY_ = new_width_y;
460 stepPhysZ_ = new_width_z;
461 stepFourierX_ = 2.*M_PI/(stepPhysX_*lengthX_);
462 stepFourierY_ = 2.*M_PI/(stepPhysY_*lengthY_);
463 stepFourierZ_ = 2.*M_PI/(stepPhysZ_*lengthZ_);
465 minPhys_ =
Vector3(-origin_.x,-origin_.y,-origin_.z);
466 maxPhys_ =
Vector3(((lengthX_-1)*stepPhysX_)-origin_.x,((lengthY_-1)*stepPhysY_)-origin_.y,((lengthZ_-1)*stepPhysZ_)-origin_.z);
467 minFourier_ =
Vector3(-(lengthX_/2.-1)*stepFourierX_,-(lengthY_/2.-1)*stepFourierY_,-(lengthZ_/2.-1)*stepFourierZ_);
468 maxFourier_ =
Vector3((lengthX_/2.)*stepFourierX_,(lengthY_/2.)*stepFourierY_,(lengthZ_/2.)*stepFourierZ_);
474 template <
typename ComplexTraits>
480 template <
typename ComplexTraits>
486 template <
typename ComplexTraits>
492 template <
typename ComplexTraits>
495 return stepFourierX_;
498 template <
typename ComplexTraits>
501 return stepFourierY_;
504 template <
typename ComplexTraits>
507 return stepFourierZ_;
510 template <
typename ComplexTraits>
516 template <
typename ComplexTraits>
522 template <
typename ComplexTraits>
528 template <
typename ComplexTraits>
534 template <
typename ComplexTraits>
540 template <
typename ComplexTraits>
546 template <
typename ComplexTraits>
550 return minFourier_.x;
553 template <
typename ComplexTraits>
556 return minFourier_.y;
559 template <
typename ComplexTraits>
562 return minFourier_.z;
565 template <
typename ComplexTraits>
568 return maxFourier_.x;
571 template <
typename ComplexTraits>
574 return maxFourier_.y;
577 template <
typename ComplexTraits>
580 return maxFourier_.z;
583 template <
typename ComplexTraits>
586 return (lengthX_ - 1);
589 template <
typename ComplexTraits>
592 return (lengthY_ - 1);
595 template <
typename ComplexTraits>
598 return (lengthZ_ - 1);
601 template <
typename ComplexTraits>
604 return numFourierToPhys_;
607 template <
typename ComplexTraits>
610 if (!inFourierSpace_)
612 if (position >= ComplexVector::size())
620 z = position % lengthZ_;
621 y = (position % (lengthY_ * lengthZ_)) / lengthZ_;
622 x = position / (lengthY_ * lengthZ_);
624 r.
set(-origin_.x + (
float)x * stepPhysX_,
625 -origin_.y + (
float)y * stepPhysY_,
626 -origin_.z + (
float)z * stepPhysZ_);
632 if (position >= ComplexVector::size())
640 z = position % lengthZ_;
641 y = (position % (lengthY_ * lengthZ_)) / lengthZ_;
642 x = position / (lengthY_ * lengthZ_);
659 r.
set((
float)x * stepFourierX_,
660 (
float)y * stepFourierY_,
661 (
float)z * stepFourierZ_);
667 template <
typename ComplexTraits>
671 double normalization=1.;
673 if (!inFourierSpace_)
675 result = (*this)[pos];
676 normalization=1./((
float)pow((
float)(lengthX_*lengthY_*lengthZ_),(
int)numFourierToPhys_));
682 result = (*this)[pos]*phase(pos);
686 normalization=1./pow(sqrt(2.*M_PI),3)/((
float)pow((
float)(lengthX_*lengthY_*lengthZ_),(
int)numFourierToPhys_));
690 result *= normalization;
695 template <
typename ComplexTraits>
700 Vector3 min = inFourierSpace_ ? minFourier_ : minPhys_;
701 Vector3 max = inFourierSpace_ ? maxFourier_ : maxPhys_;
702 double stepX = inFourierSpace_ ? stepFourierX_ : stepPhysX_;
703 double stepY = inFourierSpace_ ? stepFourierY_ : stepPhysY_;
704 double stepZ = inFourierSpace_ ? stepFourierZ_ : stepPhysZ_;
706 if ( (pos.
x < min.
x) || (pos.
y < min.
y) || (pos.
z < min.
z)
707 || (pos.
x > max.
x) || (pos.
y > max.
y) || (pos.
z > max.
z) )
713 double modX = fmod((
double)h.
x,stepX);
714 double modY = fmod((
double)h.
y,stepY);
715 double modZ = fmod((
double)h.
z,stepZ);
717 if (modX==0 && modY==0 && modZ==0)
722 double beforeX =
floor(h.
x/stepX)*stepX+min.
x;
723 double beforeY =
floor(h.
y/stepY)*stepY+min.
y;
724 double beforeZ =
floor(h.
z/stepZ)*stepZ+min.
z;
725 double afterX = ceil(h.
x/stepX)*stepX+min.
x;
726 double afterY = ceil(h.
y/stepY)*stepY+min.
y;
727 double afterZ = ceil(h.
z/stepZ)*stepZ+min.
z;
729 double tx = (pos.
x - beforeX)/stepX;
730 double ty = (pos.
y - beforeY)/stepY;
731 double tz = (pos.
z - beforeZ)/stepZ;
733 result = getData(
Vector3(beforeX,beforeY,beforeZ))*(
typename ComplexTraits::ComplexPrecision)((1.-tx)*(1.-ty)*(1.-tz));
734 result += getData(
Vector3(afterX, beforeY,beforeZ))*(
typename ComplexTraits::ComplexPrecision)( tx *(1.-ty)*(1.-tz));
735 result += getData(
Vector3(beforeX,afterY, beforeZ))*(
typename ComplexTraits::ComplexPrecision)((1.-tx)* ty *(1.-tz));
736 result += getData(
Vector3(beforeX,beforeY,afterZ ))*(
typename ComplexTraits::ComplexPrecision)((1.-tx)*(1.-ty)* tz );
737 result += getData(
Vector3(afterX, afterY, beforeZ))*(
typename ComplexTraits::ComplexPrecision)( tx * ty *(1.-tz));
738 result += getData(
Vector3(afterX, beforeY,afterZ ))*(
typename ComplexTraits::ComplexPrecision)( tx *(1.-ty)* tz );
739 result += getData(
Vector3(beforeX,afterY, afterZ ))*(
typename ComplexTraits::ComplexPrecision)((1.-tx)* ty * tz );
740 result += getData(
Vector3(afterX, afterY, afterZ ))*(
typename ComplexTraits::ComplexPrecision)( tx * ty * tz );
745 template <
typename ComplexTraits>
750 if (!inFourierSpace_)
752 dummy =
Complex(val.real()*((
typename ComplexTraits::ComplexPrecision)pow((
typename ComplexTraits::ComplexPrecision)(lengthX_*lengthY_*lengthZ_),(
int)numFourierToPhys_)),
753 val.imag()*((
typename ComplexTraits::ComplexPrecision)pow((
typename ComplexTraits::ComplexPrecision)(lengthX_*lengthY_*lengthZ_),(
int)numFourierToPhys_)));
759 val*=phase(pos)*(
typename ComplexTraits::ComplexPrecision)((pow(sqrt(2*M_PI),3)/(stepPhysX_*stepPhysY_*stepPhysZ_)))
760 *((
typename ComplexTraits::ComplexPrecision)pow((
typename ComplexTraits::ComplexPrecision)(lengthX_*lengthY_*lengthZ_),(
int)numFourierToPhys_));
770 template <
typename ComplexTraits>
775 if (!inFourierSpace_)
783 internalPos = (k + (j + i*lengthY_)*lengthZ_);
814 internalPos = (k + (j + i*lengthY_)*lengthZ_);
817 if ((internalPos < 0) || (internalPos>=(
Index) (lengthX_*lengthY_*lengthZ_)))
825 template <
typename ComplexTraits>
830 if (!inFourierSpace_)
838 internalPos = (k + (j + i*lengthY_)*lengthZ_);
869 internalPos = (k + (j + i*lengthY_)*lengthZ_);
872 if ((internalPos < 0) || (internalPos>=(
Index) (lengthX_*lengthY_*lengthZ_)))
890 template <
typename ComplexTraits>
920 template <
typename ComplexTraits>
923 return inFourierSpace_;
926 template <
typename ComplexTraits>
931 if (!from.isInFourierSpace())
934 Size lengthX = from.getMaxXIndex()+1;
935 Size lengthY = from.getMaxYIndex()+1;
936 Size lengthZ = from.getMaxZIndex()+1;
939 Vector3(from.getPhysSpaceMinX(), from.getPhysSpaceMinY(), from.getPhysSpaceMinZ()),
940 Vector3(from.getPhysSpaceMaxX(), from.getPhysSpaceMaxY(), from.getPhysSpaceMaxZ()));
943 double normalization=1./(pow((
float)(lengthX*lengthY*lengthZ),(
int)from.getNumberOfInverseTransforms()));
947 for (
Position i = 0; i < from.size(); i++)
952 y = (i % (lengthY * lengthZ)) / lengthZ;
953 x = i / (lengthY * lengthZ);
958 newGrid[x + (y + z*lengthY)*lengthZ] = dataOut*(
typename ComplexTraits::ComplexPrecision)normalization;
970 Size lengthX = from.getMaxXIndex()+1;
971 Size lengthY = from.getMaxYIndex()+1;
972 Size lengthZ = from.getMaxZIndex()+1;
976 float stepFourierX = from.getFourierStepWidthX();
977 float stepFourierY = from.getFourierStepWidthY();
978 float stepFourierZ = from.getFourierStepWidthZ();
983 Vector3(from.getFourierSpaceMinX(),
984 from.getFourierSpaceMinY(),
985 from.getFourierSpaceMinZ()),
986 Vector3(from.getFourierSpaceMaxX(),
987 from.getFourierSpaceMaxY(),
988 from.getFourierSpaceMaxZ()));
992 double normalization=1./pow(sqrt(2.*M_PI),3)/(pow((
float)(lengthX*lengthY*lengthZ),(
int)from.getNumberOfInverseTransforms()));
1000 for (
Position i = 0; i < from.size(); i++)
1003 y = (i % (lengthY * lengthZ)) / lengthZ;
1004 x = i / (lengthY * lengthZ);
1021 r.
set((
float)x * stepFourierX,
1022 (
float)y * stepFourierY,
1023 (
float)z * stepFourierZ);
1028 newGrid[x + (y + z*lengthY)*lengthZ] = dataOut*(
typename ComplexTraits::ComplexPrecision)normalization*from.phase(r);
1037 template <
typename ComplexTraits>
1038 const RegularData3D& operator << (RegularData3D& to, const TFFT3D<ComplexTraits>& from)
1041 if (!from.isInFourierSpace())
1044 Size lengthX = from.getMaxXIndex()+1;
1045 Size lengthY = from.getMaxYIndex()+1;
1046 Size lengthZ = from.getMaxZIndex()+1;
1048 RegularData3D newGrid(RegularData3D::IndexType(lengthX, lengthY, lengthZ),
Vector3(from.getPhysSpaceMinX(), from.getPhysSpaceMinY(), from.getPhysSpaceMinZ()),
1049 Vector3(from.getPhysSpaceMaxX(), from.getPhysSpaceMaxY(), from.getPhysSpaceMaxZ()));
1052 double normalization = 1./(pow((
float)(lengthX*lengthY*lengthZ),(
int)from.getNumberOfInverseTransforms()));
1056 for (
Position i = 0; i < from.size(); i++)
1061 y = (i % (lengthY * lengthZ)) / lengthZ;
1062 x = i / (lengthY * lengthZ);
1067 newGrid[x + (y + z*lengthY)*lengthZ] = dataOut.real()*normalization;
1079 Size lengthX = from.getMaxXIndex()+1;
1080 Size lengthY = from.getMaxYIndex()+1;
1081 Size lengthZ = from.getMaxZIndex()+1;
1085 float stepFourierX = from.getFourierStepWidthX();
1086 float stepFourierY = from.getFourierStepWidthY();
1087 float stepFourierZ = from.getFourierStepWidthZ();
1091 RegularData3D newGrid(RegularData3D::IndexType(lengthX, lengthY, lengthZ),
Vector3(from.getFourierSpaceMinX(), from.getFourierSpaceMinY(), from.getFourierSpaceMinZ()),
Vector3(from.getFourierSpaceMaxX(), from.getFourierSpaceMaxY(), from.getFourierSpaceMaxZ()));
1095 double normalization=1./pow(sqrt(2.*M_PI),3)/(pow((
float)(lengthX*lengthY*lengthZ),(
int)from.getNumberOfInverseTransforms()));
1098 signed int xp, yp, zp;
1103 for (
Position i = 0; i < from.size(); i++)
1106 y = (i % (lengthY * lengthZ)) / lengthZ;
1107 x = i / (lengthY * lengthZ);
1128 x-=(int)(lengthX/2.);
1132 x+=(int)(lengthX/2.);
1137 y-=(int)(lengthY/2.);
1141 y+=(int)(lengthY/2.);
1146 z-=(int)(lengthZ/2.);
1150 z+=(int)(lengthZ/2.);
1153 r.
set((
float)xp * stepFourierX,
1154 (
float)yp * stepFourierY,
1155 (
float)zp * stepFourierZ);
1160 newGrid[x + (y + z*lengthY)*lengthZ] = (dataOut*(
typename ComplexTraits::ComplexPrecision)normalization*from.phase(r)).real();
1170 #endif // BALL_MATHS_TFFT3D_H
Vector3 getGridCoordinates(Position position) const
const ValueType & operator[](const IndexType &index) const
double getFourierSpaceMinX() const
bool isInFourierSpace() const
ComplexTraits::FftwPlan planForward_
#define BALL_CREATE(name)
Complex phase(const Vector3 &pos) const
std::complex< typename ComplexTraits::ComplexPrecision > Complex
double getFourierSpaceMinY() const
double getPhysSpaceMaxZ() const
Size getMaxXIndex() const
Size getMaxZIndex() const
std::complex< BALL_COMPLEX_PRECISION > Complex
double getPhysSpaceMinZ() const
bool setPhysStepWidth(double new_width_x, double new_width_y, double new_width_z)
TFFT3D()
Default constructor.
double getFourierSpaceMaxY() const
BALL_EXTERN_VARIABLE const double h
double getPhysSpaceMinX() const
bool operator==(const TFFT3D &fft3d) const
double rint(double x)
round to integral value in floating-point format
Complex & operator[](const Vector3 &pos)
double getPhysSpaceMaxX() const
double getFourierSpaceMaxX() const
void setNumberOfFFTTransforms(Size num)
double getFourierSpaceMaxZ() const
void setData(const Vector3 &pos, Complex val)
TFFT3D< BALL_FFTW_DEFAULT_TRAITS > FFT3D
double getPhysStepWidthX() const
BALL_EXTERN_VARIABLE const double k
double getFourierStepWidthZ() const
T max(const T &a, const T &b)
TVector3< float > Vector3
Size getMaxYIndex() const
double getFourierSpaceMinZ() const
double getFourierStepWidthY() const
void setNumberOfiFFTTransforms(Size num)
Size getNumberOfInverseTransforms() const
TRegularData3D< std::complex< typename ComplexTraits::ComplexPrecision > > ComplexVector
double getPhysStepWidthZ() const
const Complex & operator[](const Position &pos) const
ComplexTraits::FftwPlan planBackward_
const vector< std::complex< ComplexTraits::ComplexPrecision > > & getData() const
Get the full data.
double getFourierStepWidthX() const
double getPhysStepWidthY() const
Complex getData(const Vector3 &pos) const
bool translate(const Vector3 &trans_origin)
double getPhysSpaceMinY() const
double getPhysSpaceMaxY() const
Complex getInterpolatedValue(const Vector3 &pos) const
T min(const T &a, const T &b)