mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
fourierModes.hpp
Go to the documentation of this file.
1 /** \file fourierModes.hpp
2  * \author Jared R. Males
3  * \brief Functions for generating 2D Fourier modes
4  * \ingroup signal_processing_files
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef fourierModes_hpp
28 #define fourierModes_hpp
29 
30 #include <vector>
31 #include <algorithm>
32 
33 
34 #include "../mxError.hpp"
35 
36 #include "../math/constants.hpp"
37 #include "../math/geo.hpp"
38 
39 namespace mx
40 {
41 
42 namespace sigproc
43 {
44 
45 /**
46  * \ingroup fourier_basis
47  *
48  * \todo need to handle references and r-values so this works directly with Eigen arrays.
49  *
50  * @{
51  */
52 
53 /** \def MX_FOURIER_BASIC
54  * \brief Signifies the basic sine/cosine Fourier basis.
55  */
56 #define MX_FOURIER_BASIC 0
57 
58 /** \def MX_FOURIER_MODIFIED
59  * \brief Signifies the modified Fourier basis.
60  */
61 #define MX_FOURIER_MODIFIED 1
62 
63 ///Populate a single cosine mode
64 /** Makes a 2D image of the cosine mode:
65  \f[
66  M_c(\vec{q}) = \cos\left( 2\pi\frac{m}{D}u + 2\pi\frac{n}{D}v \right)
67  \f]
68  * where
69  \f[
70  \vec{q} = u \hat{u} + v \hat{v}
71  \f]
72  * and \f$ D \f$ is taken to be the maximum of the number of columns and rows in the image.
73  *
74  * \retval 0 on success
75  *
76  * \tparam typeN is an Eigen-like reference type.
77  */
78 template<class typeN>
79 int makeFourierModeC( typeN im, ///< [out] is an Eigen-like image
80  typename typeN::Scalar m, ///< [in] specifies the spatial frequency in the u direction
81  typename typeN::Scalar n ///< [in] n specifies the spatial frequency in the v direction
82  )
83 {
84  typedef typename typeN::Scalar realT;
85 
86  int dim1 = im.cols();
87  int dim2 = im.rows();
88 
89  realT uc, vc, u, v, D;
90 
91  uc = 0.5*(dim1-1.0);
92  vc = 0.5*(dim2-1.0);
93 
94  D = std::max( dim1, dim2);
95 
96  for(int i=0;i<dim1; ++i)
97  {
98  u = i - uc;
99  for(int j=0;j<dim2; ++j)
100  {
101  v = j-vc;
102 
103  im(i,j) = cos(math::two_pi<realT>()/D*(m*u + n*v));
104  }
105  }
106 
107  return 0;
108 }
109 
110 ///Populate a single sine mode
111 /** Makes a 2D image of the cosine mode:
112  \f[
113  M_s(\vec{q}) = \sin\left( 2\pi\frac{m}{D}u + 2\pi\frac{n}{D}v \right)
114  \f]
115  * where
116  \f[
117  \vec{q} = u \hat{u} + v \hat{v}
118  \f]
119  * and \f$ D \f$ is taken to be the maximum of the number of columns and rows in the image.
120  * \param [out] im is an Eigen-like image
121  * \param [in] m specifies the spatial frequency in the u direction
122  * \param [in] n specifies the spatial frequency in the v direction
123  *
124  * \retval 0 on success
125  *
126  * \tparam typeN is an Eigen-like reference type.
127  */
128 template<class typeN>
129 int makeFourierModeS(typeN im, typename typeN::Scalar m, typename typeN::Scalar n)
130 {
131  typedef typename typeN::Scalar realT;
132 
133  int dim1 = im.cols();
134  int dim2 = im.rows();
135 
136  realT uc, vc, u, v, D;
137 
138  uc = 0.5*(dim1-1.0);
139  vc = 0.5*(dim2-1.0);
140 
141  D = std::max(dim1, dim2);
142 
143  for(int i=0;i<dim1; ++i)
144  {
145  u = i - uc;
146  for(int j=0;j<dim2; ++j)
147  {
148  v = j-vc;
149 
150  im(i,j) = sin(math::two_pi<realT>()/D*(m*u + n*v));
151  }
152  }
153 
154  return 0;
155 }
156 
157 ///Populate a single basic Fourier mode
158 /** Makes a 2D image of the basic sine or cosine mode. Calls \ref makeFourierModeC and \ref makeFourierModeS.
159  *
160  * \param [out] im is an Eigen-like image
161  * \param [in] m specifies the spatial frequency in the u direction
162  * \param [in] n specifies the spatial frequency in the v direction
163  * \param [in] p species sine (-1) or cosine (+1)
164  *
165  * \retval 0 on success
166  *
167  * \tparam typeN is an Eigen-like reference type.
168  */
169 template<class typeN>
170 int makeFourierMode(typeN im, typename typeN::Scalar m, typename typeN::Scalar n, int p)
171 {
172  if( p == -1) return makeFourierModeS(im, m, n);
173 
174  if( p == 1) return makeFourierModeC(im, m, n);
175 
176  mxError("makeFourierMode", MXE_INVALIDARG, "p must be +1 (cosine) or -1 (sine).");
177 
178  return -1;
179 }
180 
181 ///Populate a single modified Fourier mode
182 /** Makes a 2D image of the modified fourier mode:
183  \f[
184  M_p(\vec{q}) = \cos\left( 2\pi \frac{m}{D}u + 2\pi\frac{n}{D}v \right) + p \sin\left( 2\pi\frac{m}{D}u + 2\pi\frac{n}{D}v \right)
185  \f]
186  * where \f$ p = \pm 1 \f$, \f$ \vec{q} = u \hat{u} + v \hat{v} \f$,
187  * and \f$ D \f$ is taken to be the maximum of the number of columns in the image.
188  *
189  * \param [out] im is an Eigen-like image
190  * \param [in] m specifies the spatial frequency in the u direction
191  * \param [in] n specifies the spatial frequency in the v direction
192  * \param [in] p is +/- 1 specifying which modified Fourier mode
193  *
194  * \retval 0 on success
195  *
196  * \tparam typeN is an Eigen-like reference type.
197  */
198 template<class typeN>
200  typename typeN::Scalar m,
201  typename typeN::Scalar n,
202  int p,
203  typename typeN::Scalar ang = 0
204  )
205 {
206  typedef typename typeN::Scalar realT;
207 
208  if(p != 1 && p != -1)
209  {
210  mxError("makeModifiedFourierMode", MXE_INVALIDARG, "p must be +1 or -1.");
211  }
212 
213  int dim1 = im.cols();
214  int dim2 = im.rows();
215 
216  realT xc, yc, x, y, arg, D;
217 
218  xc = 0.5*(dim1-1.0);
219  yc = 0.5*(dim2-1.0);
220 
221  D = std::max(dim1, dim2);
222 
223  realT c_ang, s_ang;
224  if(ang != 0)
225  {
226  c_ang = cos( math::dtor(ang));
227  s_ang = sin( math::dtor(ang));
228  }
229 
230  for(int i=0;i<dim1; ++i)
231  {
232 
233  for(int j=0;j<dim2; ++j)
234  {
235  x = i - xc;
236  y = j - yc;
237 
238  if(ang != 0)
239  {
240  realT x0 = x*c_ang - y*s_ang;
241  realT y0 = x*s_ang + y*c_ang;
242 
243  x=x0;
244  y=y0;
245  }
246 
247  arg = math::two_pi<realT>()/D*(m*x + n*y);
248 
249  im(i,j) = cos(arg) + p*sin(arg);
250  }
251  }
252 
253  return 0;
254 
255 }
256 
257 ///Populate a single modified Fourier +1 mode
258 /** See \ref makeModifiedFourierMode.
259  *
260  * \param [out] im is an Eigen-like image
261  * \param [in] m specifies the spatial frequency in the u direction
262  * \param [in] n specifies the spatial frequency in the v direction
263  *
264  * \tparam typeN is an Eigen-like reference type.
265  */
266 template<class typeN>
268  typename typeN::Scalar m,
269  typename typeN::Scalar n,
270  typename typeN::Scalar ang = 0
271  )
272 {
273  return makeModifiedFourierMode(im, m, n, 1, ang);
274 }
275 
276 ///Populate a single modified Fourier -1 mode
277 /** See \ref makeModifiedFourierMode.
278  *
279  * \param [out] im is an Eigen-like image
280  * \param [in] m specifies the spatial frequency in the u direction
281  * \param [in] n specifies the spatial frequency in the v direction
282  *
283  * \tparam typeN is an Eigen-like reference type.
284  */
285 template<class typeN>
287  typename typeN::Scalar m,
288  typename typeN::Scalar n,
289  typename typeN::Scalar ang = 0
290  )
291 {
292  return makeModifiedFourierMode(im, m, n, -1, ang);
293 }
294 
295 
296 ///Structure to contain the parameters of a Fourier mode.
298 {
299  int m; ///< Spatial frequency m index
300  int n; ///< Spatial frequency n index
301  int p; ///< +/- 1 for modified Fourier modes, -1==>sine, +1==>cosine for basic Fourier modes.
302 
303  ///Constructor
305  {
306  m = 0;
307  n = 0;
308  p = 0;
309  }
310 };
311 
312 
313 /// Sorting functor for modes according to the Poyner and Veran (2005) standard.
314 /** Follows the conventions of Poyneer & Veran (2005) \cite poyneer_and_veran_2005
315  *
316  * \param[in] spf1 is an object of type \ref fourierModeDef to compare with spf2
317  * \param[in] spf2 is an object of type \ref fourierModeDef to compare with spf1
318  *
319  * \returns the result of (spf1 < spf2) according to the above rules.
320  */
321 bool comp_fourierModeDef_PandV (const fourierModeDef & spf1, const fourierModeDef & spf2)
322 {
323  double fr1 = spf1.m*spf1.m + spf1.n*spf1.n;
324  double fr2 = spf2.m*spf2.m + spf2.n*spf2.n;
325 
326  if(fr1 == fr2)
327  {
328  if(spf1.n == spf2.n)
329  {
330  if(spf1.m == spf2.m) return (spf1.p < spf2.p);
331  else return (spf1.m < spf2.m);
332  }
333  return (spf1.n < spf2.n);
334  }
335 
336  //Otherwise sort by lowest absolute value
337  return (fr1 < fr2);
338 }
339 
340 
341 ///Generate a Poyneer and Veran spatial frequency grid.
342 /** Follows the convention of Poyneer and Veran (2005) \cite poyneer_and_veran_2005
343  * \todo use push_back instead of resize
344  * \param spf
345  * \param N is the linear number of degrees of freedom.
346  */
347 int makeFourierModeFreqs_PandV(std::vector<fourierModeDef> & spf, int N)
348 {
349  int Nmodes = N*N;
350 
351  spf.resize(Nmodes);
352 
353  int _k, _l;
354  int modeCount = 0;
355  for(int ll=0; ll<=N; ++ll)
356  {
357  for(int l=ll, k=0; l>=0; --l, ++k)
358  {
359  if(modeCount >= Nmodes)
360  {
361  mxError("makeFourierModeFreqs_PandV", MXE_SIZEERR, "mode count exceeded expected number of modes");
362  return -1;
363  }
364 
365 
366  if(k==0 && l > .5*N) continue;
367 
368  if(k > .5*N && (l == 0 || l>= N-k)) continue;
369 
370  if(k > 0.5*N) _k = k-N;
371  else _k = k;
372 
373  if(l > 0.5*N) _l = l-N;
374  else _l = l;
375 
376  //There is always a cosine mode
377  spf[modeCount].m = _k;
378  spf[modeCount].n = _l;
379  spf[modeCount].p = 1;
380 
381  ++modeCount;
382 
383  //Make sure it isn't one of the corners, then populate the sine mode
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)))
385  {
386  spf[modeCount].m = _k;
387  spf[modeCount].n = _l;
388  spf[modeCount].p = -1;
389  ++modeCount;
390 
391  }
392  }
393  }
394 
395  std::sort(spf.begin(), spf.end(), comp_fourierModeDef_PandV);
396 
397  return 0;
398 }
399 
400 /// Sorting functor for modes according to the mx::AO standard.
401 /** Given a spatial frequency vector \f$ \vec{k} = k_u \hat{u} + k_v \hat{v} \f$, sorts first by
402  * \f$ | \vec{k} | \f$, then by the angle from the u axis. Results in mode numbers increasing radially
403  * and counter-clockwise from the \f$ u \f$ axis.
404  *
405  * \param[in] spf1 is an object of type \ref fourierModeDef to compare with spf2
406  * \param[in] spf2 is an object of type \ref fourierModeDef to compare with spf1
407  *
408  * \returns the result of (spf1 < spf2) according to the above rules.
409  */
410 bool comp_fourierModeDef (const fourierModeDef & spf1, const fourierModeDef & spf2)
411 {
412  double k1 = spf1.m*spf1.m + spf1.n*spf1.n;
413  double k2 = spf2.m*spf2.m + spf2.n*spf2.n;
414 
415  if(k1 == k2)
416  {
417  //Now compare by angle
418  double a1 = atan2(spf1.n, spf1.m);
419  if(a1 < 0) a1 += math::two_pi<double>();
420 
421  double a2 = atan2(spf2.n, spf2.m);
422  if(a2 < 0) a2 += math::two_pi<double>();
423 
424  if( a1 == a2 ) return (spf1.p < spf2.p);
425 
426  return ( a1 < a2);
427 
428  }
429 
430  //Otherwise sort by lowest absolute value
431  return (k1 < k2);
432 }
433 
434 
435 ///Generate a circular spatial frequency grid.
436 /** \todo use push_back instead of resize
437  *
438  * \param spf
439  * \param N is the linear number of degrees of freedom. The number of modes is ((N+1)(N+1) - 1).
440  */
441 int makeFourierModeFreqs_Circ( std::vector<fourierModeDef> & spf,
442  int N )
443 {
444  int krad;
445  int Nmodes;
446 
447  krad = floor(0.5*N);
448 
449  Nmodes = 0.25*math::pi<double>()*N*N*1.1;//The 1.1 is a buffer
450 
451  spf.resize(Nmodes);
452 
453  int modeCount = 0;
454 
455  for(int m=-krad; m <= krad; ++m)
456  {
457  int nmax = sqrt(krad*krad-m*m);
458 
459  for(int n=0; n <= nmax; ++n)
460  {
461  if( n==0 && m <=0 ) continue;
462 
463  for(int p=-1; p<=1; p+=2)
464  {
465  if(modeCount >= Nmodes)
466  {
467  mxError("makeFourierModeFreqs_Circ", MXE_SIZEERR, "mode count exceeded expected number of modes");
468  return -1;
469  }
470 
471  spf[modeCount].m = m;
472  spf[modeCount].n = n;
473  spf[modeCount].p = p;
474  ++modeCount;
475  }
476  }
477  }
478 
479  //Erase any extra modes (there will bedue to the buffer).
480  spf.erase(spf.begin()+modeCount, spf.end());
481 
482  //And now sort it
483  std::sort(spf.begin(), spf.end(), comp_fourierModeDef);
484 
485  return 0;
486 }
487 
488 ///Calculate the index of a Fourier mode given its (m,n,p) coordinates.
489 /** The index increases counter-clockwise from the m axis in squares, with p==-1 being even and p==1 being odd.
490  *
491  * \param [in] m is the m spatial frequency coordinate
492  * \param [in] n is the n spatial frequency coordinage
493  * \param [in] p is the parity, +/-1, for sine or cosine or specifiying the modified Fourier mode.
494  *
495  * \returns the index of the Fourier mode on success
496  * \returns -1 on an error.
497  */
498 int fourierModeNumber(int m, int n, int p)
499 {
500 
501  if( p != -1 && p != 1)
502  {
503  mxError("fourierModeCoordinates", MXE_INVALIDARG, "p must +/-1");
504  return -1;
505  }
506 
507  if(m ==0 && n == 0)
508  {
509  mxError("fourierModeCoordinates", MXE_INVALIDARG, "piston is ignored");
510  return -1;
511  }
512 
513 
514  int m0 = std::max(abs(m),abs(n));
515 
516  int i0 = 2*(m0*m0 - m0);
517 
518  //int di0= 4*m0;
519 
520  int di;
521 
522  if( m == m0 )
523  {
524  di = n;
525  }
526  else if( m == - m0 )
527  {
528  di = 4*m0 - n;
529  }
530  else
531  {
532  di = 2*m0 - m;
533 
534  }
535 
536  return 2*(i0 + di) + (1 + p)/2;
537 }
538 
539 
540 ///Calculate the (m,n,p) coordinates of a Fourier mode given its index.
541 /** The index increases counter-clockwise from the m axis in squares, with p==-1 being even and p==1 being odd.
542  *
543  * \returns 0 on success, a negative number otherwise
544  */
545 int fourierModeCoordinates( int & m, ///< [out] is the m spatial frequency coordinate
546  int & n, ///< [out] is the n spatial frequency coordinage
547  int & p, ///< [out] is the parity, +/-1, for sine or cosine or specifiying the modified Fourier mode.
548  int i ) ///< [in] is the mode index.
549 {
550  if(i < 0)
551  {
552  mxError("fourierModeCoordinates", MXE_INVALIDARG, "i must be >= 0");
553  m = 0;
554  n = 0;
555  p = 0;
556  return -1; /// \retval -1 if i < 0
557  }
558 
559 
560  int ii = (i)/2;
561 
562  int m0 = 1;
563 
564  while( 2*(m0*m0-m0) <= ii) ++m0;
565  --m0;
566 
567  int di = ii - 2*(m0*m0-m0);
568 
569  if( di <= m0 )
570  {
571  m = m0;
572  n = di;
573  }
574  else if( di <= 3*m0 )
575  {
576  m = 2*m0 - di;
577  n = m0;
578  }
579  else
580  {
581  m = -m0;
582  n = 4*m0 - di;
583  }
584 
585  p = -1 + 2*(i%2);
586 
587  return 0;
588 }
589 
590 
591 
592 
593 
594 
595 
596 
597 ///Generate a rectangular spatial frequency grid.
598 /**
599  * \param spf is a vector of fourierModeDef structures, which will be resized and populated.
600  * \param N is the linear number of degrees of freedom. The number of modes is ((N+1)(N+1) - 1).
601  */
602 int makeFourierModeFreqs_Rect( std::vector<fourierModeDef> & spf,
603  int N )
604 {
605  int Ndx = floor(0.5*(N));
606 
607  int Nmodes = 2*((2*Ndx + 1)*(Ndx + 1) - (Ndx+1));
608 
609  spf.resize(Nmodes);
610 
611  int m, n, p;
612 
613  for(int i=0; i< Nmodes; ++i)
614  {
615  fourierModeCoordinates(m, n, p, i);
616 
617  spf[i].m = m;
618  spf[i].n = n;
619  spf[i].p = p;
620  }
621 
622  return 0;
623 
624 
625 }
626 
627 
628 /// Fill in a cube with a Fourier basis.
629 /** Fills the cube with either the basic or modified Fourier basis for the modes specified.
630  *
631  * \param[out] cube will be allocated to hold and will be filled with the modes
632  * \param[in] dim is the linear size of the maps, each is
633  * \param[in] spf is a vector of mode definitions to use for each mode
634  * \param[in] basisType is either MX_FOURIER_MODIFIED or MX_FOURIER_BASIC
635  *
636  * \tparam cubeT is an eigen-like cube, e.g. \ref mx::eigenCube.
637  */
638 template<typename cubeT>
639 int fillFourierBasis( cubeT & cube,
640  int dim,
641  std::vector<fourierModeDef> spf,
642  int basisType,
643  typename cubeT::Scalar ang = 0
644  )
645 {
646  int Nmodes = spf.size();
647 
648  cube.resize(dim,dim,Nmodes);
649 
650  for(int j=0; j < Nmodes; ++j)
651  {
652  if(basisType == MX_FOURIER_MODIFIED)
653  {
654  if( makeModifiedFourierMode( cube.image(j), spf[j].m, spf[j].n, spf[j].p, ang) < 0) return -1;
655  }
656  else
657  {
658  if( makeFourierMode(cube.image(j), spf[j].m, spf[j].n, spf[j].p) < 0) return -1;
659  }
660  }
661 
662  return 0;
663 }
664 
665 /// Generate a rectangular modified Fourier basis with the Poyneer and Veran ordering.
666 /** Fills the cube with modes generated by \ref makeFourierMode or \ref makeModifiedFourierMode using the mode grid generated by \ref makeFourierModeFreqs_PandV.
667  * This follows the convention of Poyneer and Veran (2005) \cite poyneer_and_veran_2005 for mode numbering.
668  *
669  * \param[out] cube will be allocated to hold and will be filled with the modes
670  * \param[in] dim is the linear size of the maps, each is
671  * \param[in] N is the linear number of degrees of freedom. The number of modes is ((N+1)(N+1) - 1).
672  * \param[in] basisType is either MX_FOURIER_MODIFIED or MX_FOURIER_BASIC
673  *
674  * \tparam cubeT is an eigen-like cube, e.g. \ref mx::eigenCube.
675  */
676 template<typename cubeT>
677 int makeFourierBasis_PandV( cubeT & cube,
678  int dim,
679  int N,
680  int basisType )
681 {
682  std::vector<fourierModeDef> spf;
683 
684  if( makeFourierModeFreqs_PandV(spf, N) < 0)
685  {
686  return -1;
687  }
688 
689  return fillFourierBasis(cube, dim, spf, basisType);
690 }
691 
692 /// Generate a circular Fourier basis.
693 /** Fills the cube with modes generated by \ref makeFourierMode or \ref makeModifiedFourierMode using the mode grid generated by \ref makeFourierModeFreqs_Circ.
694  *
695  * \param[out] cube will be allocated to hold and will be filled with the modes
696  * \param[in] dim is the linear size of the maps, each is
697  * \param[in] N is the linear number of degrees of freedom. The number of modes is ((N+1)(N+1) - 1).
698  * \param[in] basisType is either MX_FOURIER_MODIFIED or MX_FOURIER_BASIC
699  *
700  * \tparam cubeT is an eigen-like cube, e.g. \ref mx::eigenCube.
701  */
702 template<typename cubeT>
703 int makeFourierBasis_Circ(cubeT & cube,
704  int dim,
705  int N,
706  int basisType )
707 {
708  std::vector<fourierModeDef> spf;
709 
710  if( makeFourierModeFreqs_Circ(spf, N) < 0 )
711  {
712  return -1;
713  }
714 
715  return fillFourierBasis(cube, dim, spf, basisType);
716 }
717 
718 
719 /// Generate a rectangular Fourier basis.
720 /** Fills the cube with modes generated by \ref makeFourierMode or \ref makeModifiedFourierMode using the mode grid generated by \ref makeFourierModeFreqs_Rect.
721  *
722  * \param[out] cube will be allocated to hold and will be filled with the modes
723  * \param[in] dim is the linear size of the maps, each is
724  * \param[in] N is the linear number of degrees of freedom. The number of modes is ((N+1)(N+1) - 1).
725  * \param[in] basisType is either MX_FOURIER_MODIFIED or MX_FOURIER_BASIC
726  *
727  * \tparam cubeT is an eigen-like cube, e.g. \ref mx::eigenCube.
728  */
729 template<typename cubeT>
730 int makeFourierBasis_Rect( cubeT & cube,
731  int dim,
732  int N,
733  int basisType,
734  typename cubeT::Scalar ang = 0
735  )
736 {
737  std::vector<fourierModeDef> spf;
738 
739  if( makeFourierModeFreqs_Rect(spf, N) < 0 )
740  {
741  return -1;
742  }
743 
744  return fillFourierBasis(cube, dim, spf, basisType, ang);
745 }
746 
747 ///@}
748 
749 } //namespace sigproc
750 } //namespace mx
751 
752 #endif //fourierModes_hpp
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.
Definition: constants.hpp:71
realT dtor(realT q)
Convert from degrees to radians.
Definition: geo.hpp:132
The mxlib c++ namespace.
Definition: mxError.hpp:107
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.