8#ifndef fourierCovariance_hpp
9#define fourierCovariance_hpp
11#include <gsl/gsl_integration.h>
12#include <gsl/gsl_errno.h>
14#include "../../math/constants.hpp"
49template <
typename realT,
typename aosysT>
50struct fourierCovariance;
62template <
typename realT,
typename aosysT>
68 realT D = Pp->
aosys->D();
80 realT cosp = cos( phi );
81 realT sinp = sin( phi );
85 realT Ji_mn_p, Ji_mn_m;
88 kmn_p = sqrt( pow( k * cosp + m / D, 2 ) + pow( k * sinp + n / D, 2 ) );
89 kmn_m = sqrt( pow( k * cosp - m / D, 2 ) + pow( k * sinp - n / D, 2 ) );
96 Q_mn = N * ( Ji_mn_p + p * Ji_mn_m );
99 realT kmpnp_p, kmpnp_m;
100 realT Ji_mpnp_p, Ji_mpnp_m;
103 kmpnp_p = sqrt( pow( k * cosp + mp / D, 2 ) + pow( k * sinp + np / D, 2 ) );
104 kmpnp_m = sqrt( pow( k * cosp - mp / D, 2 ) + pow( k * sinp - np / D, 2 ) );
111 Q_mpnp = Np * ( Ji_mpnp_p + pp * Ji_mpnp_m );
113 realT P = Pp->
aosys->psd( Pp->
aosys->atm, 0, k, 1.0 );
115 return P * k * ( Q_mn * Q_mpnp );
126template <
typename realT,
typename aosysT>
133 realT D = Pp->
aosys->D();
145 realT mnCon = Pp->
mnCon;
147 realT cosp = cos( phi );
148 realT sinp = sin( phi );
152 realT Ji_mn_p, Ji_mn_m;
154 kmn_p = sqrt( pow( k * cosp + m / D, 2 ) + pow( k * sinp + n / D, 2 ) );
155 kmn_m = sqrt( pow( k * cosp - m / D, 2 ) + pow( k * sinp - n / D, 2 ) );
161 realT kmpnp_p, kmpnp_m;
162 realT Ji_mpnp_p, Ji_mpnp_m;
164 kmpnp_p = sqrt( pow( k * cosp + mp / D, 2 ) + pow( k * sinp + np / D, 2 ) );
165 kmpnp_m = sqrt( pow( k * cosp - mp / D, 2 ) + pow( k * sinp - np / D, 2 ) );
174 QQ = 2.0 * ( Ji_mn_p * Ji_mpnp_p + Ji_mn_m * Ji_mpnp_m );
178 QQ = 2.0 * ( Ji_mn_p * Ji_mpnp_m + Ji_mn_m * Ji_mpnp_p );
181 realT P = Pp->
aosys->psd(
182 Pp->
aosys->atm, 0, k, 1.0 );
204template <
typename realT,
typename aosysT>
205realT
kInt( realT k,
void *params )
238template <
typename realT,
typename aosysT>
282 gsl_integration_workspace *
k_w;
287 phi_w = gsl_integration_workspace_alloc(
WSZ );
288 k_w = gsl_integration_workspace_alloc(
WSZ );
294 gsl_integration_workspace_free(
phi_w );
295 gsl_integration_workspace_free(
k_w );
310 gsl_set_error_handler_off();
320template <
typename realT,
typename aosysT>
321int fourierVarVec(
const std::string &fname,
int N, aosysT &aosys, realT absTol, realT relTol,
bool modifed =
true )
324 std::vector<realT> var( N, 0 );
329 if( aosys.d_min( 0 ) > 0 )
331 mnCon = floor( aosys.D() / aosys.d_min( 0 ) / 2.0 );
345#pragma omp for schedule( dynamic, 5 )
346 for(
int i = 0; i < N; ++i )
368 realT r_0 = aosys.atm.r_0();
369 realT tot = 1.0299 * pow( D / r_0, 5. / 3. );
373 std::cout << 0 <<
" " << 0 <<
" " << 0 <<
" " << tot <<
"\n";
374 for(
int i = 0; i < N; ++i )
376 realT k = ( i + 1 ) / D;
378 realT P = aosys.psd( aosys.atm, 0, k, 1.0 );
384 P *= pow(
math::two_pi<realT>() * aosys.atm.v_wind() * k * ( aosys.minTauWFS( 0 ) + aosys.deltaTau() ),
390 fout << i + 1 <<
" " << var[i] <<
" " << P / pow( D, 2 ) <<
" " << tot - sum <<
"\n";
404template <
typename realT,
typename aosysT>
413 psd.resize( 2 * N + 1, 2 * N + 1 );
416 if( aosys.d_min() > 0 )
418 mnCon = floor( aosys.D() / aosys.d_min() / 2.0 );
421 for(
int i = 0; i <= N; ++i )
423 for(
int j = -N; j <= N; ++j )
427 realT k = sqrt( pow( i, 2 ) + pow( j, 2 ) ) / D / overSample;
429 realT P = aosys.psd( aosys.atm, k, aosys.lam_sci(), 0, aosys.lam_wfs(), 1.0 );
435 P *= pow(
math::two_pi<realT>() * aosys.atm.v_wind() * k * ( aosys.minTauWFS() + aosys.deltaTau() ),
440 psd( N + i, N + j ) = P / pow( D * overSample, 2 );
441 psd( N - i, N - j ) = P / pow( D * overSample, 2 );
446 Eigen::Array<realT, -1, -1> psf;
447 psf.resize( 2 * N + 3, 2 * N + 3 );
448 for(
int i = 0; i < psf.rows(); ++i )
450 for(
int j = 0; j < psf.cols(); ++j )
453 sqrt( pow( i - floor( .5 * psf.rows() ), 2 ) + pow( j - floor( .5 * psf.cols() ), 2 ) ) / overSample );
462template <
typename realT>
464 const std::string &fname,
474 std::vector<mx::sigproc::fourierModeDef> ml;
482 aosys.atm.
r_0( 1.0, 0.5e-6 );
485 aosys.atm.
L_0( L_0 );
486 aosys.psd.subPiston( subPist );
487 aosys.psd.subTipTilt( subTilt );
491 Eigen::Array<realT, -1, -1> covar( psz, psz );
498 std::cerr <<
"Starting . . .\n";
511#pragma omp for schedule( static, 5 )
512 for(
int i = 0; i < psz; ++i )
514 for(
int j = i; j < psz; ++j )
525 covar( i, j ) = result;
532 head.
append(
"DIAMETER", aosys.
D(),
"Diameter in meters" );
533 head.
append(
"NSUBAP", N,
"Linear number of s.f. sampled" );
534 head.
append(
"L0", aosys.atm.
L_0( 0 ),
"Outer scale (L_0) in meters" );
535 head.
append(
"SUBPIST", aosys.psd.subPiston(),
"Piston subtractioon true/false flag" );
536 head.
append(
"SUBTILT", aosys.psd.subTipTilt(),
"Tip/Tilt subtractioon true/false flag" );
537 head.
append(
"ABSTOL", absTol,
"Absolute tolerance in qagiu" );
538 head.
append(
"RELTOL", relTol,
"Relative tolerance in qagiu" );
540 fitsHeaderGitStatus( head,
"mxlib", mxlib_comp_current_sha1(), mxlib_comp_repo_modified() );
543 ff.
write( fname +
".fits", covar, head );
548template <
typename realT,
typename aosysT>
549int fourierCovarMapSeparated(
550 const std::string &fname,
int N, aosysT &aosys, realT absTol, realT relTol,
bool modified =
true )
552 std::vector<mx::sigproc::fourierModeDef> ml;
555 int psz = 0.5 * ml.size();
557 Eigen::Array<realT, -1, -1> covar_pp( (
int)( 0.5 * psz ), (
int)( .5 * psz ) ),
558 covar_ppp( (
int)( 0.5 * psz ), (
int)( 0.5 * psz ) );
563 if( aosys.d_min() > 0 )
565 mnCon = floor( aosys.D() / aosys.d_min() / 2.0 );
573 fourierCovariance<realT, aosysT> Pp;
585#pragma omp for schedule( dynamic, 5 )
586 for(
int i = 0; i < psz; i += 2 )
588 for(
int j = 0; j <= 0.5 * i; ++j )
590 for(
int k = 0; k < 2; ++k )
596 Pp.pp = ml[2 * j + k].p;
597 Pp.mp = ml[2 * j + k].m;
598 Pp.np = ml[2 * j + k].n;
599 result = Pp.getVariance(
error );
603 covar_pp( i / 2, j ) = result;
607 covar_ppp( i / 2, j ) = result;
609 watcher.incrementAndOutputStatus();
615 fits::fitsHeader head;
616 head.append(
"DIAMETER", aosys.D(),
"Diameter in meters" );
617 head.append(
"L0", aosys.atm.L_0(),
"Outer scale (L_0) in meters" );
618 head.append(
"SUBPIST", aosys.psd.subPiston(),
"Piston subtractioon true/false flag" );
619 head.append(
"SUBTILT", aosys.psd.subTipTilt(),
"Tip/Tilt subtractioon true/false flag" );
620 head.append(
"ABSTOL", absTol,
"Absolute tolerance in qagiu" );
621 head.append(
"RELTOL", relTol,
"Relative tolerance in qagiu" );
623 fitsHeaderGitStatus( head,
"mxlib", mxlib_comp_current_sha1(), mxlib_comp_repo_modified() );
625 fits::fitsFile<realT> ff;
626 ff.write( fname +
"_pp.fits", covar_pp, head );
627 ff.write( fname +
"_ppp.fits", covar_ppp, head );
632template <
typename realT>
633void calcKLCoeffs(
const std::string &outFile,
const std::string &cvFile )
635 fits::fitsFile<realT> ff;
637 Eigen::Array<realT, -1, -1> cvT, cv, evecs, evals;
639 ff.read( cv, cvFile );
643 std::cerr << cvT.rows() <<
" " << cvT.cols() <<
"\n";
645 math::syevrMem<double> mem;
657 std::cerr <<
"info =" << info <<
"\n";
661 std::cerr <<
"Time = " << t1 - t0 <<
" secs\n";
664 for(
int i = 0; i < evecs.cols(); ++i )
666 evecs.col( i ) = evecs.col( i ) / sqrt( fabs( evals( i ) ) );
669 ff.write( outFile, evecs );
672template <
typename eigenArrT1,
typename eigenArrT2,
typename eigenArrT3>
673void makeKL( eigenArrT1 &kl, eigenArrT2 &evecs, eigenArrT3 &&rvecs )
676 int tNims = evecs.rows();
677 int tNpix = rvecs.rows();
701template <
typename realT>
702void makeFKL(
const std::string &outFile,
const std::string &coeffs,
int N,
int pupSize )
704 fits::fitsFile<realT> ff;
705 Eigen::Array<realT, -1, -1> evecs;
707 ff.read( evecs, coeffs );
709 improc::eigenCube<realT> Rims;
712 std::cout << Rims.planes() <<
" " << evecs.cols() <<
"\n";
714 Eigen::Array<realT, -1, -1> kl;
715 kl.resize( Rims.planes(), Rims.rows() * Rims.cols() );
717 std::cerr << 1 <<
"\n";
718 makeKL( kl, evecs, Rims.cube() );
719 std::cerr << 2 <<
"\n";
721 Eigen::Array<realT, -1, -1> klT = kl.transpose();
726 improc::eigenCube<realT> klims( klT.data(), Rims.rows(), Rims.cols(), Rims.planes() );
728 improc::eigenCube<realT> klimsR;
729 klimsR.resize( klims.rows(), klims.cols(), klims.planes() );
731 for(
int i = 0; i < klims.planes(); ++i )
733 klimsR.image( i ) = klims.image( klims.planes() - 1 - i );
736 ff.write( outFile, klimsR );
737 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.
realT L_0(const size_t &n)
Get the value of the outer scale for a single layer.
realT r_0()
Get the value of Fried's parameter r_0 at the reference wavelength lam_0.
Describes an analytic adaptive optics (AO) system.
void loadMagAOX()
Load parameters corresponding to the MagAO-X system.
void D(realT nD)
Set the value of the primary mirror diameter.
Class to manage interactions with a FITS file.
error_t write(const dataT *im, int d1, int d2, int d3, fitsHeader< verboseT > *head)
Write the contents of a raw array to the FITS file.
A class to track the number of iterations in an OMP parallelized loop.
void incrementAndOutputStatus()
Increment and output status.
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.
realT phiInt_mod(realT phi, void *params)
Worker for the azimuthal integral (in phi) for the modified Fourier mode covariance.
int fourierPSDMap(improc::eigenImage< realT > &var, improc::eigenImage< realT > &psd, int N, int overSample, aosysT &aosys)
Calculate a map of Fourier variances by convolution with the PSD.
int fourierCovarMap(const std::string &fname, int N, realT D, realT L_0, bool subPist, bool subTilt, realT absTol, realT relTol, bool modified=true)
#define WSZ
The size of the gsl_integration workspaces.
int fourierVarVec(const std::string &fname, int N, aosysT &aosys, realT absTol, realT relTol, bool modifed=true)
Calculate a vector of Fourier mode variances.
realT kInt(realT k, void *params)
Worker function for the radial integral in the covariance calculation.
Functions for generating 2D Fourier modes.
@ modified
The modified Fourier basis from males_guyon_2018.
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.
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.
int makeFourierBasis_Rect(cubeT &cube, int dim, int N, int basisType, typename cubeT::Scalar ang=0)
Generate a rectangular Fourier basis.
int makeFourierModeFreqs_Rect(std::vector< fourierModeDef > &spf, int N)
Generate a rectangular spatial frequency grid.
#define MX_FOURIER_MODIFIED
Signifies the modified Fourier basis.
realT airyPattern(realT x)
The classical Airy pattern.
T jinc(const T &x)
The Jinc function.
constexpr T pi()
Get the value of pi.
constexpr T two_pi()
Get the value of 2pi.
realT phiInt_basic(realT phi, void *params)
Worker for the azimuthal integral (in phi) for the basic Fourier mode covariance.
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 Fourier mode covariance calculation, passed to integration functions.
realT m
The m-index of the unprimed mode, corresponding to the component of spatial frequency.
int p
p-index of the unprimed mode. +/-1 for modified modes. If basic, then +1==>cosine,...
realT n
The n-indexof the unprimed mode, corresponding to the component of spatial frequency.
realT getVariance(realT &error)
Calculate the covariance between the two modes.
fourierCovariance()
Constructor.
realT absTol
Absolute tolerance for the radial integral. Default is 1e-7.
~fourierCovariance()
Destructor.
int pp
p-index of the primed mode. +/-1 for modified modes. If basic, then +1==>cosine, -1==>sine.
aosysT * aosys
Pointer to an AO system, which contains the relevant spatial PSD of turbulence.
realT np
The n-indexof the primed mode, corresponding to the component of spatial frequency.
gsl_integration_workspace * phi_w
Working memory for the azimuthal integral.
gsl_integration_workspace * k_w
Working memory for the radial integral.
realT relTol
Relative tolerance for the radial integral. Default is 1e-7.
realT mnCon
The maximum controlled value of spatial frequency (k*D). If < 0 then not controlled.
realT mp
The m-index of the primed mode, corresponding to the component of spatial frequency.
realT k
Spatial frequency being calculated, passed for use in the integrand worker functions.
Utilities for working with time.
A utility to convert a wavefront variance map to an intensity image.