27 #ifndef fourierModes_hpp
28 #define fourierModes_hpp
34 #include "../mxError.hpp"
36 #include "../math/constants.hpp"
37 #include "../math/geo.hpp"
56 #define MX_FOURIER_BASIC 0
61 #define MX_FOURIER_MODIFIED 1
80 typename typeN::Scalar m,
81 typename typeN::Scalar n
84 typedef typename typeN::Scalar realT;
89 realT uc, vc, u, v, D;
94 D = std::max( dim1, dim2);
96 for(
int i=0;i<dim1; ++i)
99 for(
int j=0;j<dim2; ++j)
103 im(i,j) = cos(math::two_pi<realT>()/D*(m*u + n*v));
128 template<
class typeN>
131 typedef typename typeN::Scalar realT;
133 int dim1 = im.cols();
134 int dim2 = im.rows();
136 realT uc, vc, u, v, D;
141 D = std::max(dim1, dim2);
143 for(
int i=0;i<dim1; ++i)
146 for(
int j=0;j<dim2; ++j)
150 im(i,j) = sin(math::two_pi<realT>()/D*(m*u + n*v));
169 template<
class typeN>
170 int makeFourierMode(typeN im,
typename typeN::Scalar m,
typename typeN::Scalar n,
int p)
176 mxError(
"makeFourierMode", MXE_INVALIDARG,
"p must be +1 (cosine) or -1 (sine).");
198 template<
class typeN>
200 typename typeN::Scalar m,
201 typename typeN::Scalar n,
203 typename typeN::Scalar ang = 0
206 typedef typename typeN::Scalar realT;
208 if(p != 1 && p != -1)
210 mxError(
"makeModifiedFourierMode", MXE_INVALIDARG,
"p must be +1 or -1.");
213 int dim1 = im.cols();
214 int dim2 = im.rows();
216 realT xc, yc, x, y, arg, D;
221 D = std::max(dim1, dim2);
230 for(
int i=0;i<dim1; ++i)
233 for(
int j=0;j<dim2; ++j)
240 realT x0 = x*c_ang - y*s_ang;
241 realT y0 = x*s_ang + y*c_ang;
247 arg = math::two_pi<realT>()/D*(m*x + n*y);
249 im(i,j) = cos(arg) + p*sin(arg);
266 template<
class typeN>
268 typename typeN::Scalar m,
269 typename typeN::Scalar n,
270 typename typeN::Scalar ang = 0
285 template<
class typeN>
287 typename typeN::Scalar m,
288 typename typeN::Scalar n,
289 typename typeN::Scalar ang = 0
323 double fr1 = spf1.
m*spf1.
m + spf1.
n*spf1.
n;
324 double fr2 = spf2.
m*spf2.
m + spf2.
n*spf2.
n;
330 if(spf1.
m == spf2.
m)
return (spf1.
p < spf2.
p);
331 else return (spf1.
m < spf2.
m);
333 return (spf1.
n < spf2.
n);
355 for(
int ll=0; ll<=N; ++ll)
357 for(
int l=ll,
k=0; l>=0; --l, ++
k)
359 if(modeCount >= Nmodes)
361 mxError(
"makeFourierModeFreqs_PandV", MXE_SIZEERR,
"mode count exceeded expected number of modes");
366 if(
k==0 && l > .5*N)
continue;
368 if(
k > .5*N && (l == 0 || l>= N-
k))
continue;
370 if(
k > 0.5*N) _k =
k-N;
373 if(l > 0.5*N) _l = l-N;
377 spf[modeCount].m = _k;
378 spf[modeCount].n = _l;
379 spf[modeCount].p = 1;
384 if(! ((
k==0 && l==0) || (
k ==0.5*N && l==0) || (
k==0 && l==0.5*N) || (
k==0.5*N && l==0.5*N)))
386 spf[modeCount].m = _k;
387 spf[modeCount].n = _l;
388 spf[modeCount].p = -1;
412 double k1 = spf1.
m*spf1.
m + spf1.
n*spf1.
n;
413 double k2 = spf2.
m*spf2.
m + spf2.
n*spf2.
n;
418 double a1 = atan2(spf1.
n, spf1.
m);
419 if(a1 < 0) a1 += math::two_pi<double>();
421 double a2 = atan2(spf2.
n, spf2.
m);
422 if(a2 < 0) a2 += math::two_pi<double>();
424 if( a1 == a2 )
return (spf1.
p < spf2.
p);
449 Nmodes = 0.25*math::pi<double>()*N*N*1.1;
455 for(
int m=-krad; m <= krad; ++m)
457 int nmax = sqrt(krad*krad-m*m);
459 for(
int n=0; n <= nmax; ++n)
461 if( n==0 && m <=0 )
continue;
463 for(
int p=-1; p<=1; p+=2)
465 if(modeCount >= Nmodes)
467 mxError(
"makeFourierModeFreqs_Circ", MXE_SIZEERR,
"mode count exceeded expected number of modes");
471 spf[modeCount].m = m;
472 spf[modeCount].n = n;
473 spf[modeCount].p = p;
480 spf.erase(spf.begin()+modeCount, spf.end());
501 if( p != -1 && p != 1)
503 mxError(
"fourierModeCoordinates", MXE_INVALIDARG,
"p must +/-1");
509 mxError(
"fourierModeCoordinates", MXE_INVALIDARG,
"piston is ignored");
514 int m0 = std::max(abs(m),abs(n));
516 int i0 = 2*(m0*m0 - m0);
536 return 2*(i0 + di) + (1 + p)/2;
552 mxError(
"fourierModeCoordinates", MXE_INVALIDARG,
"i must be >= 0");
564 while( 2*(m0*m0-m0) <= ii) ++m0;
567 int di = ii - 2*(m0*m0-m0);
574 else if( di <= 3*m0 )
605 int Ndx = floor(0.5*(N));
607 int Nmodes = 2*((2*Ndx + 1)*(Ndx + 1) - (Ndx+1));
613 for(
int i=0; i< Nmodes; ++i)
638 template<
typename cubeT>
641 std::vector<fourierModeDef> spf,
643 typename cubeT::Scalar ang = 0
646 int Nmodes = spf.size();
648 cube.resize(dim,dim,Nmodes);
650 for(
int j=0; j < Nmodes; ++j)
652 if(basisType == MX_FOURIER_MODIFIED)
658 if(
makeFourierMode(cube.image(j), spf[j].m, spf[j].n, spf[j].p) < 0)
return -1;
676 template<
typename cubeT>
682 std::vector<fourierModeDef> spf;
702 template<
typename cubeT>
708 std::vector<fourierModeDef> spf;
729 template<
typename cubeT>
734 typename cubeT::Scalar ang = 0
737 std::vector<fourierModeDef> spf;
int makeFourierModeS(typeN im, typename typeN::Scalar m, typename typeN::Scalar n)
Populate a single sine mode.
int makeFourierBasis_Rect(cubeT &cube, int dim, int N, int basisType, typename cubeT::Scalar ang=0)
Generate a rectangular Fourier basis.
int fourierModeCoordinates(int &m, int &n, int &p, int i)
Calculate the (m,n,p) coordinates of a Fourier mode given its index.
int makeModifiedFourierModeP(typeN im, typename typeN::Scalar m, typename typeN::Scalar n, typename typeN::Scalar ang=0)
Populate a single modified Fourier +1 mode.
int makeFourierBasis_Circ(cubeT &cube, int dim, int N, int basisType)
Generate a circular Fourier basis.
int makeModifiedFourierModeM(typeN im, typename typeN::Scalar m, typename typeN::Scalar n, typename typeN::Scalar ang=0)
Populate a single modified Fourier -1 mode.
int makeFourierModeFreqs_Rect(std::vector< fourierModeDef > &spf, int N)
Generate a rectangular spatial frequency grid.
int makeFourierBasis_PandV(cubeT &cube, int dim, int N, int basisType)
Generate a rectangular modified Fourier basis with the Poyneer and Veran ordering.
int makeModifiedFourierMode(typeN im, typename typeN::Scalar m, typename typeN::Scalar n, int p, typename typeN::Scalar ang=0)
Populate a single modified Fourier mode.
bool comp_fourierModeDef(const fourierModeDef &spf1, const fourierModeDef &spf2)
Sorting functor for modes according to the mx::AO standard.
int fourierModeNumber(int m, int n, int p)
Calculate the index of a Fourier mode given its (m,n,p) coordinates.
int fillFourierBasis(cubeT &cube, int dim, std::vector< fourierModeDef > spf, int basisType, typename cubeT::Scalar ang=0)
Fill in a cube with a Fourier basis.
int makeFourierModeFreqs_Circ(std::vector< fourierModeDef > &spf, int N)
Generate a circular spatial frequency grid.
int makeFourierMode(typeN im, typename typeN::Scalar m, typename typeN::Scalar n, int p)
Populate a single basic Fourier mode.
int makeFourierModeFreqs_PandV(std::vector< fourierModeDef > &spf, int N)
Generate a Poyneer and Veran spatial frequency grid.
int makeFourierModeC(typeN im, typename typeN::Scalar m, typename typeN::Scalar n)
Populate a single cosine mode.
bool comp_fourierModeDef_PandV(const fourierModeDef &spf1, const fourierModeDef &spf2)
Sorting functor for modes according to the Poyner and Veran (2005) standard.
constexpr units::realT k()
Boltzmann Constant.
realT dtor(realT q)
Convert from degrees to radians.
Structure to contain the parameters of a Fourier mode.
int m
Spatial frequency m index.
int n
Spatial frequency n index.
int p
+/- 1 for modified Fourier modes, -1==>sine, +1==>cosine for basic Fourier modes.
fourierModeDef()
Constructor.