12using namespace mx::fits;
22using namespace mx::improc;
23using namespace mx::sigproc;
26using namespace mx::math;
37template <
typename realT>
39 const std::string &basisName,
40 const std::string &pupilName,
45 std::string rawFName = mx::AO::path::basis::modes( basisName );
46 ff.
read( modes, rawFName );
49 Eigen::Array<realT, -1, -1> pupil;
50 ff.
read( pupil, pupilFName );
52 Eigen::Array<realT, -1, -1> im, pim, fim;
54 for(
int i = 0; i < modes.planes(); ++i )
57 modes.image( i ) = modes.image( i ) * pupil;
61 im = modes.image( i );
67 modes.image( i ) += fim * ( pupil - 1 ).abs();
81#define MXAO_ORTHO_METHOD_SGS 0
86#define MXAO_ORTHO_METHOD_SVD 1
88template <
typename realT,
typename spectRealT>
90 Eigen::Array<spectRealT, -1, -1> &spect,
98 ortho.resize( modes.rows(), modes.cols(), modes.planes() );
99 Eigen::Map<Eigen::Array<realT, -1, -1>> gsout( ortho.data(), ortho.rows() * ortho.cols(), ortho.planes() );
105 Eigen::Array<realT, -1, -1> U, S, VT, A;
107 A = modes.asVectors();
112 std::cerr <<
"Some error occurred in SVD\n";
118 eigenCube<realT> omodes( U.data(), modes.rows(), modes.cols(), modes.planes() );
120 ortho.resize( modes.rows(), modes.cols(), modes.planes() );
125 std::cerr <<
"Invalid orthogonalization method.\n";
142template <
typename realT>
143void orthogonalizeBasis(
const std::string &orthoName,
144 const std::string &basisName,
145 const std::string &pupilName,
155 Eigen::Array<realT, -1, -1> spect;
157 orthogonalizeBasis( ortho, spect, modes, method );
159 modes.resize( 1, 1, 1 );
162 Eigen::Array<realT, -1, -1> pupil;
163 ff.
read( pupil, pupilFName );
165 realT psum = pupil.sum();
168 for(
int i = 0; i < ortho.planes(); ++i )
170 norm = ortho.
image( i ).square().sum() / psum;
171 ortho.
image( i ) /= sqrt( norm );
181 std::string orthoFName = mx::AO::path::basis::modes( orthoName,
true );
183 std::string orthm =
"UNK";
189 head.
append(
"ORTHMETH", orthm,
"Orthogonalization method." );
190 head.
append(
"ORTHPUP", pupilName,
"Pupil used for orthogonalization" );
192 ff.
write( orthoFName, ortho, head );
196 std::string orthoFName = mx::AO::path::basis::spectrum( orthoName,
true );
197 ff.
write( orthoFName, spect, head );
201template <
typename spectRealT,
typename realT>
207 int nModes = modes.planes();
209 std::vector<realT> w( nModes );
211 size_t psum = pupil.sum();
215 std::vector<realT> amps( nModes, 0.0 );
216 std::vector<realT> uwAmps( nModes );
217 std::vector<realT> rat( psum );
220 for(
int k = 0; k < nModes; ++k )
224 for(
int j = 0; j < nModes; ++j )
228 for(
int i = j; i < nModes; ++i )
230 uwAmps[j] += amps[i] * spectrum( i, j );
237 for(
int i = 0; i < nModes; ++i )
238 uwp += uwAmps[i] * modes.image( i );
241 for(
int r = 0; r < pupil.rows(); ++r )
243 for(
int c = 0;
c < pupil.cols(); ++
c )
245 if( pupil( r, c ) == 1 )
246 rat[idx++] = ( uwp( r, c ) / ortho.
image( k )( r,
c ) );
253 std::cout << w[
k] <<
"\n";
259 for(
int i = 0; i < nModes; ++i )
260 spectrum.row( i ) /= w[i];
265template <
typename realT>
266int slaveBasis(
const std::string &outputBasisN,
267 const std::string &inputBasisN,
268 const std::string &pupilN,
269 const std::string &dmN,
279 eigenCube<realT> inf;
280 ff.
read( dmFName, inf );
282 int dmSz = inf.rows();
287 std::string basisFName = mx::AO::path::basis::modes( inputBasisN );
288 eigenCube<realT> modes;
289 ff.
read( basisFName, modes );
293 Eigen::Array<realT, -1, -1> pupil;
294 ff.
read( pupilFName, pupil );
296 Eigen::Array<realT, -1, -1> im, ppim, pim, fim, ppupil;
303 int cutw = 0.5 * ( dmSz - modes.rows() );
310 eigenCube<realT> oModes;
312 oModes.resize( modes.rows() + 2 * cutw, modes.cols() + 2 * cutw, modes.planes() );
314 if( modes.rows() > pupil.rows() )
316 padImage( ppupil, pupil, 0.5 * ( modes.rows() - pupil.rows() ) );
322 for(
int i = 0; i < firstMode; ++i )
324 im = modes.image( i );
326 cutPaddedImage( im, ppim, 0.5 * ppim.rows() - ( 0.5 * modes.rows() + cutw ) );
328 oModes.
image( i ) = im;
331 for(
int i = firstMode; i < modes.planes(); ++i )
334 if( fwhm > 0 || fsmooth > 0 )
337 im = modes.image( i ) * pupil;
343 filterImage( fim, pim, gaussKernel<Eigen::Array<realT, -1, -1>>( fwhm ) );
344 fim = ppim + fim * ( ppupil - 1 ).abs();
355 filterImage( fim, pim, gaussKernel<Eigen::Array<realT, -1, -1>>( fsmooth ) );
358 cutPaddedImage( im, fim, 0.5 * fim.rows() - ( 0.5 * modes.rows() + cutw ) );
360 oModes.
image( i ) = im;
364 std::string oFName = mx::AO::path::basis::modes( outputBasisN,
true );
365 ff.
write( oFName, oModes );
370template <
typename realT>
371int apodizeBasis(
const std::string &outputBasisN,
372 const std::string &inputBasisN,
381 std::string basisFName = mx::AO::path::basis::modes( inputBasisN );
382 eigenCube<realT> modes;
383 ff.
read( basisFName, modes );
385 realT cen = 0.5 * ( modes.rows() - 1.0 );
387 Eigen::Array<realT, -1, -1> pupil;
388 pupil.resize( modes.rows(), modes.cols() );
390 if( centralObs == 0 )
397 pupil.data(), modes.rows(), modes.rows() + overScan, centralObs, tukeyAlpha, cen, cen );
400 for(
int i = firstMode; i < modes.planes(); ++i )
402 modes.image( i ) = modes.image( i ) * pupil;
405 std::string oFName = mx::AO::path::basis::modes( outputBasisN,
true );
406 ff.
write( oFName, modes );
411template <
typename realT>
412int subtractBasis(
const std::string &basisName,
413 const std::string &basisName1,
414 const std::string &basisName2,
415 const std::string &pupilName,
421 std::string basisFName1 = mx::AO::path::basis::modes( basisName1 );
422 eigenCube<realT> modes1;
423 ff.
read( basisFName1, modes1 );
425 std::string basisFName2 = mx::AO::path::basis::modes( basisName2 );
426 eigenCube<realT> modes2;
427 ff.
read( basisFName2, modes2, head );
428 realT fwhm = head[
"FWHM"].value<realT>();
430 eigenCube<realT> modes;
431 modes.resize( modes1.rows(), modes1.cols(), modes1.planes() + modes2.planes() );
434 Eigen::Array<realT, -1, -1> pupil;
435 ff.
read( pupilFName, pupil );
437 for(
int i = 0; i < modes1.planes(); ++i )
439 modes.image( i ) = modes1.
image( i ) * pupil;
442 for(
int i = 0; i < modes2.planes(); ++i )
444 modes.image( modes1.planes() + i ) = modes2.
image( i ) * pupil;
447 eigenCube<realT> ortho;
449 orthogonalizeBasis( ortho, modes, method );
453 Eigen::Array<realT, -1, -1> im, ppim, pim, fim, ppupil;
455 modes.resize( ortho.rows(), ortho.cols(), modes2.planes() );
461 for(
int i = 0; i < modes2.planes(); ++i )
463 modes.image( i ) = ortho.
image( modes1.planes() + i ) * pupil;
467 im = modes.image( i );
471 filterImage( fim, pim, gaussKernel<Eigen::Array<realT, -1, -1>>( fwhm ) );
472 fim = ppim + fim * ( ppupil - 1 ).abs();
477 filterImage( fim, pim, gaussKernel<Eigen::Array<realT, -1, -1>>( fsmooth ) );
481 modes.image( i ) = im;
485 std::string orthoFName = mx::AO::path::basis::modes( basisName,
true );
486 ff.
write( orthoFName, modes );
Standardized paths for the mx::AO system.
std::string pupilFile(const std::string &pupilName, bool create=false)
The path for the pupil FITS file.
std::string influenceFunctions(const std::string &dmName, bool create=false)
The path for the deformable mirror (DM) influence functions.
void applyPupil2Basis(eigenCube< realT > &modes, const std::string &basisName, const std::string &pupilName, realT fwhm=0)
Multiply a raw modal basis by a pupil mask.
#define MXAO_ORTHO_METHOD_SVD
Constant to specify using the singular value decomposition (SVD) for orthogonalizing a modal basis.
#define MXAO_ORTHO_METHOD_SGS
Constant to specify using the stabilized Gramm Schmidt (SGS) orthogonalization procedure.
Class to manage interactions with a FITS file.
error_t read(dataT *data)
Read the contents of the FITS file into an array.
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.
An image cube with an Eigen-like API.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > image(Index n)
Returns a 2D Eigen::Eigen::Map pointed at the specified image.
An image cube with an Eigen API.
Interfaces to Lapack and BLAS for Eigen-like arrays.
Declares and defines a class to work with a FITS file.
Functions for generating 2D Fourier modes.
Procedures to orthogonalize vector basis sets.
constexpr units::realT c()
The speed of light.
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 eigenGESDD(Eigen::Array< dataT, -1, -1 > &U, Eigen::Array< dataT, -1, -1 > &S, Eigen::Array< dataT, -1, -1 > &VT, Eigen::Array< dataT, -1, -1 > &A)
Compute the SVD of an Eigen::Array using LAPACK's xgesdd.
error_t filterImage(imageOutT &fim, imageInT im, const kernelT &kernel, int maxr=0)
Filter an image with a mean kernel.
int padImage(imOutT &imOut, imInT &imIn, unsigned int padSz, typename imOutT::Scalar value)
Pad an image with a constant value.
int cutPaddedImage(imOutT &imOut, const imInT &imIn, unsigned int padSz)
Cut down a padded image.
void gramSchmidtSpectrum(eigenTout &out, eigenTout2 &spect, const eigenTin &in, typename eigenTin::Scalar normPix=0.0)
Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result, while recording the s...
void tukey2d(realT *filt, int rows, int cols, realT D, realT alpha, realT xc, realT yc)
Create a 2-D Tukey window.
void tukey2dAnnulus(realT *filt, int rows, int cols, realT D, realT eps, realT alpha, realT xc, realT yc)
Create a 2-D Tukey window on an annulus.
vectorT::value_type vectorMedianInPlace(vectorT &vec)
Calculate median of a vector in-place, altering the vector.
Image filters (smoothing, radial profiles, etc.).
Procedures to calculate window functions for signal processing.
Symetric Gaussian smoothing kernel.