8#ifndef zernikeCovariance_hpp
9#define zernikeCovariance_hpp
11#include <gsl/gsl_integration.h>
12#include <gsl/gsl_errno.h>
14#include "../../math/constants.hpp"
21#include "../../error/mxExceptionOld.hpp"
45template <
typename realT,
typename aosysT>
79 size_t m_workspaceSize{ 1000000 };
91 m_workspacePhi = gsl_integration_workspace_alloc( m_workspaceSize );
92 m_workspaceK = gsl_integration_workspace_alloc( m_workspaceSize );
102 void workspaceSize(
size_t wsz )
107 m_workspacePhi = gsl_integration_workspace_alloc( m_workspaceSize );
108 m_workspaceK = gsl_integration_workspace_alloc( m_workspaceSize );
111 size_t workspaceSize()
113 return m_workspaceSize;
116 gsl_integration_workspace *workspacePhi()
132 err::paramnotset,
"zernikeCovariance::getCovariance",
"AO system not setup (aosys is nullptr)" );
136 func.function = &
kInt;
139 gsl_set_error_handler_off();
141 int ec = gsl_integration_qagiu(
151 static realT
kInt( realT k,
159 static realT
phiInt( realT phi,
164template <
typename realT,
typename aosysT>
179 gsl_integration_qag( &func,
193template <
typename realT,
typename aosysT>
206 std::complex<realT> Q_mn = zernikeQ( k * D / 2.0, phi, n, m );
212 std::complex<realT> Q_mpnp = zernikeQ( k * D / 2.0, phi, np, mp );
215 realT QQ = real( conj( Q_mn ) * Q_mpnp );
225template<
typename realT,
typename aosysT>
226int zernikeVarVec(
const std::string & fname,
235 std::vector<realT> var(N,0);
240 if( aosys.d_min(0) > 0)
242 mnCon = floor( aosys.D()/aosys.d_min(0)/2.0);
247 zernikeCovariance<realT, aosysT> Pp;
256#pragma omp for schedule( dynamic, 5 )
257 for(
int i=0; i< N; ++i)
267 result = Pp.getVariance(
error);
271 watcher.incrementAndOutputStatus();
279 realT r_0 = aosys.atm.r_0();
280 realT tot = 1.0299*pow(D/r_0, 5./3.);
284 std::cout << 0 <<
" " << 0 <<
" " << 0 <<
" " << tot <<
"\n";
285 for(
int i=0; i<N; ++i)
289 realT P = aosys.psd(aosys.atm, 0, k, 1.0);
295 P *= pow(
math::two_pi<realT>()*aosys.atm.v_wind()* k * (aosys.minTauWFS(0)+aosys.deltaTau()),2);
300 fout << i+1 <<
" " << var[i] <<
" " << P/pow(D,2) <<
" " << tot-sum <<
"\n";
314template<
typename realT,
typename aosysT>
323 psd.resize(2*N + 1, 2*N+1);
326 if( aosys.d_min() > 0)
328 mnCon = floor( aosys.D()/aosys.d_min()/2.0);
331 for(
int i=0; i<=N; ++i)
333 for(
int j=-N; j<=N; ++j)
337 realT
k = sqrt( pow(i,2) + pow(j,2))/D/overSample;
339 realT P = aosys.psd(aosys.atm, k, aosys.lam_sci(), 0, aosys.lam_wfs(), 1.0);
345 P *= pow(
math::two_pi<realT>()*aosys.atm.v_wind()* k * (aosys.minTauWFS()+aosys.deltaTau()),2);
349 psd(N+i, N + j) = P/pow(D*overSample,2);
350 psd(N-i, N - j) = P/pow(D*overSample,2);
355 Eigen::Array<realT, -1,-1> psf;
356 psf.resize(2*N+3,2*N+3);
357 for(
int i=0;i<psf.rows();++i)
359 for(
int j=0;j<psf.cols();++j)
370template<
typename realT>
371int zernikeCovarMap(
const std::string & fname,
382 std::vector<mx::sigproc::zernikeModeDef> ml;
383 mx::sigproc::makezernikeModeFreqs_Rect(ml, N);
391 aosys.atm.r_0(1.0, 0.5e-6);
394 aosys.atm.L_0( L_0 );
395 aosys.psd.subPiston( subPist );
396 aosys.psd.subTipTilt( subTilt );
400 Eigen::Array<realT,-1,-1> covar( psz, psz);
405 ipc::ompLoopWatcher<> watcher(psz, std::cout);
407 std::cerr <<
"Starting . . .\n";
419#pragma omp for schedule( static, 5 )
420 for(
int i=0; i< psz; ++i)
422 for(
int j=i; j< psz; ++j)
431 result = Pp.getVariance(
error);
436 watcher.incrementAndOutputStatus();
440 fits::fitsHeader head;
441 head.append(
"DIAMETER", aosys.D(),
"Diameter in meters");
442 head.append(
"NSUBAP", N,
"Linear number of s.f. sampled");
443 head.append(
"L0", aosys.atm.L_0(0),
"Outer scale (L_0) in meters");
444 head.append(
"SUBPIST", aosys.psd.subPiston(),
"Piston subtractioon true/false flag");
445 head.append(
"SUBTILT", aosys.psd.subTipTilt(),
"Tip/Tilt subtractioon true/false flag");
446 head.append(
"ABSTOL", absTol,
"Absolute tolerance in qagiu");
447 head.append(
"RELTOL", relTol,
"Relative tolerance in qagiu");
449 fitsHeaderGitStatus( head,
"mxlib", mxlib_comp_current_sha1(), mxlib_comp_repo_modified() );
451 fits::fitsFile<realT> ff;
452 ff.write(fname +
".fits", covar, head);
460template<
typename realT,
typename aosysT>
461int zernikeCovarMapSeparated(
const std::string & fname,
468 std::vector<mx::sigproc::zernikeModeDef> ml;
469 mx::sigproc::makezernikeModeFreqs_Rect(ml, N);
471 int psz = 0.5*ml.size();
473 Eigen::Array<realT,-1,-1> covar_pp( (
int) (0.5*psz), (
int)(.5*psz)), covar_ppp( (
int) (0.5*psz), (
int)(0.5*psz));
478 if( aosys.d_min() > 0)
480 mnCon = floor( aosys.D()/aosys.d_min()/2.0);
483 ipc::ompLoopWatcher<> watcher((psz+1)*0.125*(psz+1)*2, std::cout);
499#pragma omp for schedule( dynamic, 5 )
500 for(
int i=0; i< psz; i+=2)
502 for(
int j=0; j<= 0.5*i; ++j)
504 for(
int k=0;
k< 2; ++
k)
510 Pp.pp = ml[2*j +
k].p;
511 Pp.mp = ml[2*j +
k].m;
512 Pp.np = ml[2*j +
k].n;
513 result = Pp.getVariance(
error);
517 covar_pp(i/2, j) = result;
521 covar_ppp(i/2, j) = result;
523 watcher.incrementAndOutputStatus();
529 fits::fitsHeader head;
530 head.append(
"DIAMETER", aosys.D(),
"Diameter in meters");
531 head.append(
"L0", aosys.atm.L_0(),
"Outer scale (L_0) in meters");
532 head.append(
"SUBPIST", aosys.psd.subPiston(),
"Piston subtractioon true/false flag");
533 head.append(
"SUBTILT", aosys.psd.subTipTilt(),
"Tip/Tilt subtractioon true/false flag");
534 head.append(
"ABSTOL", absTol,
"Absolute tolerance in qagiu");
535 head.append(
"RELTOL", relTol,
"Relative tolerance in qagiu");
537 fitsHeaderGitStatus( head,
"mxlib", mxlib_comp_current_sha1(), mxlib_comp_repo_modified() );
539 fits::fitsFile<realT> ff;
540 ff.write(fname +
"_pp.fits", covar_pp, head);
541 ff.write(fname +
"_ppp.fits", covar_ppp, head);
546template<
typename realT>
547void calcKLCoeffs(
const std::string & outFile,
548 const std::string & cvFile )
550 fits::fitsFile<realT> ff;
552 Eigen::Array<realT,-1,-1> cvT, cv, evecs, evals;
558 std::cerr << cvT.rows() <<
" " << cvT.cols() <<
"\n";
560 math::syevrMem<double> mem;
572 std::cerr <<
"info =" << info <<
"\n";
576 std::cerr <<
"Time = " << t1-t0 <<
" secs\n";
579 for(
int i=0;i< evecs.cols(); ++i)
581 evecs.col(i) = evecs.col(i)/sqrt(fabs(evals(i)));
584 ff.write(outFile, evecs);
587template<
typename eigenArrT1,
typename eigenArrT2,
typename eigenArrT3>
588void makeKL( eigenArrT1 & kl,
590 eigenArrT3 && rvecs )
593 int tNims = evecs.rows();
594 int tNpix = rvecs.rows();
603 tNims, 1., evecs.data(), evecs.rows(), rvecs.data(), rvecs.rows(),
604 0., kl.data(), kl.rows());
608template<
typename realT>
609void makeFKL(
const std::string & outFile,
610 const std::string & coeffs,
614 fits::fitsFile<realT> ff;
615 Eigen::Array<realT, -1, -1> evecs;
617 ff.read(evecs, coeffs);
619 improc::eigenCube<realT> Rims;
620 sigproc::makezernikeBasis_Rect(Rims, pupSize, N, MX_zernike_MODIFIED);
622 std::cout << Rims.planes() <<
" " << evecs.cols() <<
"\n";
624 Eigen::Array<realT,-1,-1> kl;
625 kl.resize( Rims.planes(), Rims.rows()*Rims.cols());
627 std::cerr << 1 <<
"\n";
628 makeKL( kl, evecs, Rims.cube());
629 std::cerr << 2 <<
"\n";
631 Eigen::Array<realT,-1,-1> klT = kl.transpose();
636 improc::eigenCube<realT> klims(klT.data(), Rims.rows(), Rims.cols(), Rims.planes());
638 improc::eigenCube<realT> klimsR;
639 klimsR.resize( klims.rows(), klims.cols(), klims.planes());
641 for(
int i=0; i< klims.planes(); ++i)
643 klimsR.image(i) = klims.image(klims.planes()-1-i);
646 ff.write(outFile, klimsR);
647 std::cerr << 3 <<
"\n";
Utilities related to the Airy pattern point spread function.
Provides a class to specify atmosphere parameters.
Spatial power spectra used in adaptive optics.
Declares and defines an analytical AO system.
Describes an analytic adaptive optics (AO) system.
void loadMagAOX()
Load parameters corresponding to the MagAO-X system.
mxException for parameters which aren't set
A class to track the number of iterations in an OMP parallelized loop.
An image cube with an Eigen API.
Tools for using the eigen library for image processing.
Interfaces to Lapack and BLAS for Eigen-like arrays.
Declares and defines a class to work with a FITS file.
@ modified
The modified Fourier basis from males_guyon_2018.
constexpr units::realT k()
Boltzmann Constant.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
MXLAPACK_INT eigenSYEVR(arrT &eigvec, arrT &eigval, arrT &X, int ev0=0, int ev1=-1, char UPLO='L', syevrMem< typename arrT::Scalar > *mem=0)
Calculate select eigenvalues and eigenvectors of an Eigen Array.
@ error
A general error has occurred.
#define mxThrowException(extype, src, expl)
Throw an exception. This macro takes care of the file and line.
void fitsHeaderGitStatus(fitsHeaderT &head, const std::string &repoName, const char *sha1, int modified)
Write the status of a Git repository to HISTORY in a FITS header.
realT airyPattern(realT x)
The classical Airy pattern.
constexpr T two_pi()
Get the value of 2pi.
void varmapToImage(imageT &im, imageT &varmap, imageT &psf)
Convert a wavefront variance map to an intensity image by convolving with the PSF.
void gemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const dataT &alpha, const dataT *A, const int lda, const dataT *B, const int ldb, const dataT &beta, dataT *C, const int ldc)
Template Wrapper for cblas xGEMM.
typeT get_curr_time()
Get the current system time in seconds.
Declares and defines the Jinc and Jinc2 functions.
Declarations of some libarary wide utilities.
Track iterations in an OMP parallelized looop.
Structure to manage the zernike mode covariance calculation, passed to integration functions.
zernikeCovariance()
Constructor.
realT m_kIntEpsAbs
Absolute tolerance for the radial integral. Default is 1e-10.
aosysT * m_aosys
Pointer to an AO system, which contains the relevant spatial PSD of turbulence.
realT m_k
Spatial frequency being calculated, passed for use in the integrand worker functions.
realT m_m
The m-index of the unprimed mode.
realT m_mp
The m-index of the primed mode, corresponding to the component of spatial frequency.
realT m_np
The n-indexof the primed mode, corresponding to the component of spatial frequency.
gsl_integration_workspace * m_workspacePhi
Working memory for the azimuthal integral.
realT m_phiIntEpsRel
Relative tolerance for the azimuthal integral. Default is 0, meaning absolute is used.
static realT phiInt(realT phi, void *params)
Worker for the azimuthal integral (in phi) for the zernike mode covariance.
realT getCovariance(realT &error)
Calculate the covariance between the two modes.
realT m_n
The n-index of the unprimed mode.
realT m_phiIntEpsAbs
Absolute tolerance for the azimuthal integral. Default is 1e-10.
~zernikeCovariance()
Destructor.
gsl_integration_workspace * m_workspaceK
Working memory for the radial integral.
realT m_kIntEpsRel
Relative tolerance for the radial integral. Default is 0, meaning absolute is used.
static realT kInt(realT k, void *params)
Worker function for the radial integral in the covariance calculation.
Utilities for working with time.
A utility to convert a wavefront variance map to an intensity image.
Working with the Zernike polynomials.