27#ifndef fourierModes_hpp
28#define fourierModes_hpp
33#include "../mxlib.hpp"
35#include "../math/constants.hpp"
36#include "../math/geo.hpp"
55#define MX_FOURIER_BASIC 0
60#define MX_FOURIER_MODIFIED 1
79 typename typeN::Scalar m,
80 typename typeN::Scalar n
83 typedef typename typeN::Scalar realT;
88 realT uc, vc, u, v, D;
90 uc = 0.5 * ( dim1 - 1.0 );
91 vc = 0.5 * ( dim2 - 1.0 );
93 D = std::max( dim1, dim2 );
95 for(
int i = 0; i < dim1; ++i )
98 for(
int j = 0; j < dim2; ++j )
127template <
class typeN>
130 typedef typename typeN::Scalar realT;
132 int dim1 = im.cols();
133 int dim2 = im.rows();
135 realT uc, vc, u, v, D;
137 uc = 0.5 * ( dim1 - 1.0 );
138 vc = 0.5 * ( dim2 - 1.0 );
140 D = std::max( dim1, dim2 );
142 for(
int i = 0; i < dim1; ++i )
145 for(
int j = 0; j < dim2; ++j )
168template <
class typeN>
169int makeFourierMode( typeN im,
typename typeN::Scalar m,
typename typeN::Scalar n,
int p )
199template <
class typeN>
201 typeN im,
typename typeN::Scalar m,
typename typeN::Scalar n,
int p,
typename typeN::Scalar ang = 0 )
203 typedef typename typeN::Scalar realT;
205 if( p != 1 && p != -1 )
211 int dim1 = im.cols();
212 int dim2 = im.rows();
214 realT xc, yc, x, y, arg, D;
216 xc = 0.5 * ( dim1 - 1.0 );
217 yc = 0.5 * ( dim2 - 1.0 );
219 D = std::max( dim1, dim2 );
228 for(
int i = 0; i < dim1; ++i )
231 for(
int j = 0; j < dim2; ++j )
238 realT x0 = x * c_ang - y * s_ang;
239 realT y0 = x * s_ang + y * c_ang;
247 im( i, j ) = cos( arg ) + p * sin( arg );
263template <
class typeN>
265 typename typeN::Scalar m,
266 typename typeN::Scalar n,
267 typename typeN::Scalar ang = 0 )
281template <
class typeN>
283 typename typeN::Scalar m,
284 typename typeN::Scalar n,
285 typename typeN::Scalar ang = 0 )
316 double fr1 = spf1.
m * spf1.
m + spf1.
n * spf1.
n;
317 double fr2 = spf2.
m * spf2.
m + spf2.
n * spf2.
n;
321 if( spf1.
n == spf2.
n )
323 if( spf1.
m == spf2.
m )
324 return ( spf1.
p < spf2.
p );
326 return ( spf1.
m < spf2.
m );
328 return ( spf1.
n < spf2.
n );
332 return ( fr1 < fr2 );
345 spf.resize( Nmodes );
349 for(
int ll = 0; ll <= N; ++ll )
351 for(
int l = ll, k = 0; l >= 0; --l, ++k )
353 if( modeCount >= Nmodes )
359 if( k == 0 && l > .5 * N )
362 if( k > .5 * N && ( l == 0 || l >= N - k ) )
376 spf[modeCount].m = _k;
377 spf[modeCount].n = _l;
378 spf[modeCount].p = 1;
383 if( !( ( k == 0 && l == 0 ) || ( k == 0.5 * N && l == 0 ) || ( k == 0 && l == 0.5 * N ) ||
384 ( k == 0.5 * N && l == 0.5 * N ) ) )
386 spf[modeCount].m = _k;
387 spf[modeCount].n = _l;
388 spf[modeCount].p = -1;
411 double k1 = spf1.
m * spf1.
m + spf1.
n * spf1.
n;
412 double k2 = spf2.
m * spf2.
m + spf2.
n * spf2.
n;
417 double a1 = atan2( spf1.
n, spf1.
m );
419 a1 += math::two_pi<double>();
421 double a2 = atan2( spf2.
n, spf2.
m );
423 a2 += math::two_pi<double>();
426 return ( spf1.
p < spf2.
p );
446 krad = floor( 0.5 * N );
448 Nmodes = 0.25 * math::pi<double>() * N * N * 1.1;
450 spf.resize( Nmodes );
454 for(
int m = -krad; m <= krad; ++m )
456 int nmax = sqrt( krad * krad - m * m );
458 for(
int n = 0; n <= nmax; ++n )
460 if( n == 0 && m <= 0 )
463 for(
int p = -1; p <= 1; p += 2 )
465 if( modeCount >= Nmodes )
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 )
507 if( m == 0 && n == 0 )
513 int m0 = std::max( abs( m ), abs( n ) );
515 int i0 = 2 * ( m0 * m0 - m0 );
534 return 2 * ( i0 + di ) + ( 1 + p ) / 2;
561 while( 2 * ( m0 * m0 - m0 ) <= ii )
565 int di = ii - 2 * ( m0 * m0 - m0 );
572 else if( di <= 3 * m0 )
583 p = -1 + 2 * ( i % 2 );
595 int Ndx = floor( 0.5 * ( N ) );
597 int Nmodes = 2 * ( ( 2 * Ndx + 1 ) * ( Ndx + 1 ) - ( Ndx + 1 ) );
599 spf.resize( Nmodes );
603 for(
int i = 0; i < Nmodes; ++i )
621template <
typename cubeT>
625 std::vector<fourierModeDef> spf,
628 typename cubeT::Scalar ang = 0
631 int Nmodes = spf.size();
633 cube.resize( dim, dim, Nmodes );
635 for(
int j = 0; j < Nmodes; ++j )
644 if(
makeFourierMode( cube.image( j ), spf[j].m, spf[j].n, spf[j].p ) < 0 )
664template <
typename cubeT>
667 std::vector<fourierModeDef> spf;
688template <
typename cubeT>
691 std::vector<fourierModeDef> spf;
712template <
typename cubeT>
715 std::vector<fourierModeDef> spf;
@ sizeerr
A size was invalid or calculated incorrectly.
@ invalidarg
An argument was invalid.
error_t mxlib_error_report(const error_t &code, const std::string &expl, const std::source_location &loc=std::source_location::current())
Print a report to stderr given an mxlib error_t code and explanation and return the code.
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.
#define MX_FOURIER_MODIFIED
Signifies the modified Fourier basis.
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 floatT six_fifths()
Return 6/5 in the specified precision.
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.