30 #ifndef math_zernike_hpp
31 #define math_zernike_hpp
37 #include "../math/func/bessel.hpp"
38 #include "../math/func/jinc.hpp"
39 #include "../math/func/factorial.hpp"
40 #include "../math/func/sign.hpp"
41 #include "../math/constants.hpp"
42 #include "../mxError.hpp"
102 template<
typename realT>
112 mxError(
"zernikeRCoeffs", MXE_INVALIDARG,
"n cannot be less than m in the Zernike polynomials");
123 int ul = 0.5*(n-m) + 1;
127 for(
int k=0;
k < ul; ++
k)
129 c[
k] = pow(-1.0,
k) * math::func::factorial<realT>(n -
k) / ( math::func::factorial<realT>(
k) * math::func::factorial<realT>(0.5*(n+m) -
k)* math::func::factorial<realT>(0.5*(n-m) -
k));
137 int zernikeRCoeffs<float>( std::vector<float> &
c,
int n,
int m);
140 int zernikeRCoeffs<double>( std::vector<double> &
c,
int n,
int m);
143 int zernikeRCoeffs<long double>( std::vector<long double> &
c,
int n,
int m);
147 int zernikeRCoeffs<__float128>( std::vector<__float128> &
c,
int n,
int m);
159 template<
typename realT,
typename calcRealT>
163 std::vector<calcRealT> &
c
175 if(
c.size() != 0.5*(n-m) + 1)
177 mxError(
"zernikeR", MXE_INVALIDARG,
"c vector has incorrect length for n and m.");
182 for(
size_t k=0;
k<
c.size(); ++
k)
184 R +=
c[
k] * pow(rho, n-2*
k);
192 float zernikeR<float,double>(
float rho,
int n,
int m, std::vector<double> &
c);
195 double zernikeR<double,double>(
double rho,
int n,
int m, std::vector<double> &
c);
198 long double zernikeR<long double, long double>(
long double rho,
int n,
int m, std::vector<long double> &
c);
202 __float128 zernikeR<__float128,__float128>(__float128 rho,
int n,
int m, std::vector<__float128> &
c);
213 template<
typename realT,
typename calcRealT>
227 std::vector<calcRealT>
c;
231 return zernikeR<realT, calcRealT>(rho, n, m,
c);
236 float zernikeR<float, double>(
float rho,
int n,
int m);
239 double zernikeR<double, double>(
double rho,
int n,
int m);
242 long double zernikeR<long double, long double>(
long double rho,
int n,
int m);
246 __float128 zernikeR<__float128,__float128>( __float128 rho,
int n,
int m);
263 template<
typename realT,
typename calcRealT>
268 std::vector<calcRealT> &
c
273 if( n == 0 && m == 0)
280 azt = math::root_two<realT>()*sin(-m*phi);
284 azt = math::root_two<realT>()*cos(m*phi);
291 return sqrt((realT) n+1) * zernikeR<realT, calcRealT>(rho, n, m,
c) * azt;
296 float zernike<float, double>(
float rho,
float phi,
int n,
int m, std::vector<double> &
c);
299 double zernike<double, double>(
double rho,
double phi,
int n,
int m, std::vector<double> &
c);
302 long double zernike<long double, long double>(
long double rho,
long double phi,
int n,
int m, std::vector<long double> &
c);
306 __float128 zernike<__float128,__float128>(__float128 rho, __float128 phi,
int n,
int m, std::vector<__float128> &
c);
318 template<
typename realT,
typename calcRealT>
326 std::vector<calcRealT>
c;
328 if( zernikeRCoeffs<calcRealT>(
c, n, m) < 0)
return -9999;
330 return zernike<realT,calcRealT>(rho, phi, n, m,
c);
334 float zernike<float,double>(
float rho,
float phi,
int n,
int m);
337 double zernike<double,double>(
double rho,
double phi,
int n,
int m);
340 long double zernike<long double, long double>(
long double rho,
long double phi,
int n,
int m);
344 __float128 zernike<__float128,__float128>( __float128 rho, __float128 phi,
int n,
int m);
355 template<
typename realT,
typename calcRealT>
364 if(
noll_nm(n, m, j) < 0)
return -9999;
366 return zernike<realT, calcRealT>(rho, phi, n, m);
370 float zernike<float, double>(
float rho,
float phi,
int j);
373 double zernike<double, double>(
double rho,
double phi,
int j);
376 long double zernike<long double, long double>(
long double rho,
long double phi,
int j);
380 __float128 zernike<__float128, __float128>(__float128 rho, __float128 phi,
int j);
396 template<
typename arrayT,
typename calcRealT,
int overscan=2>
400 typename arrayT::Scalar xcen,
401 typename arrayT::Scalar ycen,
402 typename arrayT::Scalar rad = -1 )
404 typedef typename arrayT::Scalar realT;
410 std::vector<calcRealT>
c;
414 size_t l0 = arr.rows();
415 size_t l1 = arr.cols();
417 if(rad <= 0) rad = 0.5*std::min(l0-1, l1-1);
419 for(
size_t i=0; i < l0; ++i)
421 for(
size_t j=0; j < l1; ++j)
427 r = std::sqrt( x*x + y*y );
430 if(r > rad && r <= rad+(1.0/overscan)) r = rad;
436 phi = std::atan2( y, x);
437 arr(i,j) =
zernike(rho, phi, n, m,
c);
460 template<
typename arrayT,
typename calcRealT>
463 typename arrayT::Scalar xcen,
464 typename arrayT::Scalar ycen,
465 typename arrayT::Scalar rad = -1 )
467 typedef typename arrayT::Scalar realT;
471 if(
noll_nm(n, m, j) < 0)
return -1;
473 return zernike<arrayT, calcRealT>(arr, n, m, xcen, ycen, rad);
487 template<
typename arrayT,
typename calcRealT>
491 typename arrayT::Scalar rad = -1 )
493 typename arrayT::Scalar xcen = 0.5*(arr.rows()-1.0);
494 typename arrayT::Scalar ycen = 0.5*(arr.cols()-1.0);
496 return zernike<arrayT, calcRealT>(arr, n, m, xcen, ycen, rad);
510 template<
typename arrayT,
typename calcRealT>
513 typename arrayT::Scalar rad = -1 )
515 typename arrayT::Scalar xcen = 0.5*( arr.rows()-1.0);
516 typename arrayT::Scalar ycen = 0.5*( arr.cols()-1.0);
518 return zernike<arrayT, calcRealT>(arr, j, xcen, ycen, rad);
530 template<
typename cubeT,
typename calcRealT>
532 typename cubeT::Scalar rad = -1,
536 typedef typename cubeT::imageT arrayT;
538 typename cubeT::imageT im;
540 im.resize(cube.rows(), cube.cols());
543 for(
int i=0; i < cube.planes(); ++i)
545 rv = zernike<arrayT,calcRealT>( im, minj+i, rad);
568 template<
typename realT>
581 if( n == 0 ) B = 1.0;
589 realT Q2 = (n+1) * (B * B);
593 Q2 = 2*Q2 * pow(cos(m*phi), 2);
597 Q2 = 2*Q2 * pow(sin(-m*phi), 2);
604 float zernikeQNorm<float>(
float k,
float phi,
int n,
int m);
607 double zernikeQNorm<double>(
double k,
double phi,
int n,
int m);
610 long double zernikeQNorm<long double>(
long double k,
long double phi,
int n,
int m);
614 __float128 zernikeQNorm<__float128>(__float128
k, __float128 phi,
int n,
int m);
626 template<
typename realT>
649 template<
typename arrayT>
656 if(arr.rows() !=
k.rows() || arr.cols() !=
k.cols())
658 mxError(
"zernikeQNorm", MXE_INVALIDARG,
"output array and input k are not the same size");
662 if(arr.rows() != phi.rows() || arr.cols() != phi.cols())
664 mxError(
"zernikeQNorm", MXE_INVALIDARG,
"output array and input phi are not the same size");
669 if(
noll_nm(n,m,j) < 0)
return -1;
671 for(
size_t i=0; i < arr.rows(); ++i)
673 for(
size_t j=0; j < arr.cols(); ++j)
682 template<
typename realT>
689 template<
typename realT>
696 template<
typename realT>
703 template<
typename realT>
710 template<
typename realT>
717 template<
typename realT>
constexpr units::realT c()
The speed of light.
constexpr units::realT k()
Boltzmann Constant.
T2 bessel_j(T1 v, T2 x)
Bessel Functions of the First Kind.
T2 jincN(const T1 &v, const T2 &x)
The JincN function.
T jinc(const T &x)
The Jinc function.
int noll_j(unsigned n, int m)
Get the Noll index j corresponding to Zernike coefficients n,m.
realT zernikePPiston(const realT &kD)
Calculate the spatial power spectrum of Piston.
realT zernikePDefocus(const realT &kD)
Calculate the spatial power spectrum of Defocus.
realT zernikeR(realT rho, int n, int m)
Calculate the value of a Zernike radial polynomial at a given separation.
realT zernikePTrefoil(const realT &kD)
Calculate the spatial power spectrum of Trefoil.
int nZernRadOrd(unsigned n)
Get the number of Zernikes up to and including a radial order.
realT zernikePTipTilt(const realT &kD)
Calculate the spatial power spectrum of Tip & Tilt.
int noll_nm(int &n, int &m, int j)
Get the Zernike coefficients n,m corrresponding the Noll index j.
int zernike(arrayT &arr, int j, typename arrayT::Scalar rad=-1)
Fill in an Eigen-like array with a Zernike polynomial.
realT zernikePAstig(const realT &kD)
Calculate the spatial power spectrum of Astigmatism.
realT zernikePComa(const realT &kD)
Calculate the spatial power spectrum of Coma.
int zernikeQNorm(arrayT &arr, arrayT &k, arrayT &phi, int j)
Fill in an Eigen-like array with the square-normed Fourier transform of a Zernike polynomial.
int zernikeRCoeffs(std::vector< realT > &c, int n, int m)
Calculate the coefficients of a Zernike radial polynomial.
int zernikeBasis(cubeT &cube, typename cubeT::Scalar rad=-1, int minj=2)
Fill in an Eigencube-like array with Zernike polynomials in Noll order.