11 #include "../ioutils/fits/fitsFile.hpp"
12 using namespace mx::fits;
14 #include "../sigproc/fourierModes.hpp"
15 #include "../sigproc/gramSchmidt.hpp"
17 #include "../improc/imageFilters.hpp"
18 #include "../improc/imagePads.hpp"
19 #include "../improc/eigenCube.hpp"
21 #include "../sigproc/signalWindows.hpp"
22 using namespace mx::improc;
23 using namespace mx::sigproc;
25 #include "../math/eigenLapack.hpp"
26 using namespace mx::math;
37 template<
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);
48 std::string pupilFName = mx::AO::path::pupil::pupilFile(pupilName);
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;
67 modes.image(i) += fim* (pupil - 1).abs();
83 #define MXAO_ORTHO_METHOD_SGS 0
88 #define MXAO_ORTHO_METHOD_SVD 1
91 template<
typename realT,
typename spectRealT>
93 Eigen::Array<spectRealT, -1, -1> & spect,
101 if(method == MXAO_ORTHO_METHOD_SGS)
103 ortho.resize(modes.rows(), modes.cols(), modes.planes());
104 Eigen::Map< Eigen::Array<realT, -1, -1>> gsout(ortho.data(), ortho.rows()*ortho.cols(), ortho.planes());
106 gramSchmidtSpectrum<1>(gsout, spect, modes.asVectors(), psum);
109 else if (method == MXAO_ORTHO_METHOD_SVD)
111 Eigen::Array<realT, -1, -1> U, S, VT, A;
113 A = modes.asVectors();
118 std::cerr <<
"Some error occurred in SVD\n";
126 ortho.resize(modes.rows(), modes.cols(), modes.planes());
132 std::cerr <<
"Invalid orthogonalization method.\n";
151 template<
typename realT>
152 void orthogonalizeBasis(
const std::string & orthoName,
153 const std::string & basisName,
154 const std::string & pupilName,
165 Eigen::Array<realT, -1, -1> spect;
167 orthogonalizeBasis(ortho, spect, modes, method);
171 std::string pupilFName = mx::AO::path::pupil::pupilFile(pupilName);
172 Eigen::Array<realT, -1, -1> pupil;
173 ff.
read(pupil, pupilFName);
175 realT psum = pupil.sum();
178 for(
int i=0; i< ortho.planes(); ++i)
180 norm = ortho.
image(i).square().sum()/psum;
181 ortho.
image(i)/= sqrt(norm);
183 if(method == MXAO_ORTHO_METHOD_SGS)
191 std::string orthoFName = mx::AO::path::basis::modes(orthoName,
true);
193 std::string orthm =
"UNK";
194 if(method == MXAO_ORTHO_METHOD_SGS) orthm =
"SGS";
195 if(method == MXAO_ORTHO_METHOD_SVD) orthm =
"SVD";
197 head.
append(
"ORTHMETH", orthm,
"Orthogonalization method.");
198 head.
append(
"ORTHPUP", pupilName,
"Pupil used for orthogonalization");
201 ff.
write(orthoFName, ortho, head);
203 if(method == MXAO_ORTHO_METHOD_SGS)
205 std::string orthoFName = mx::AO::path::basis::spectrum(orthoName,
true);
206 ff.
write(orthoFName, spect, head);
211 template<
typename spectRealT,
typename realT>
218 int nModes = modes.planes();
220 std::vector<realT> w(nModes);
222 size_t psum = pupil.sum();
226 std::vector<realT> amps( nModes, 0.0 );
227 std::vector<realT> uwAmps(nModes);
228 std::vector<realT> rat(psum);
231 for(
int k=0;
k< nModes; ++
k)
235 for(
int j=0; j< nModes; ++j)
239 for(
int i= j; i < nModes; ++i)
241 uwAmps[j] += amps[i]*spectrum(i,j);
248 for(
int i=0;i<nModes; ++i) uwp+= uwAmps[i]*modes.image(i);
251 for(
int r=0; r< pupil.rows(); ++r)
253 for(
int c=0;
c < pupil.cols(); ++
c)
255 if(pupil(r,
c) == 1) rat[idx++] = ( uwp(r,
c) / ortho.
image(
k)(r,
c));
261 if(
k == 1200) std::cout << w[
k] <<
"\n";
267 for(
int i=0; i< nModes; ++i) spectrum.row(i)/= w[i];
272 template<
typename realT>
273 int slaveBasis(
const std::string & outputBasisN,
274 const std::string & inputBasisN,
275 const std::string & pupilN,
276 const std::string & dmN,
288 ff.
read(dmFName, inf);
290 int dmSz = inf.rows();
295 std::string basisFName = mx::AO::path::basis::modes(inputBasisN);
297 ff.
read(basisFName, modes);
301 Eigen::Array<realT, -1, -1> pupil;
302 ff.
read(pupilFName, pupil);
304 Eigen::Array<realT, -1, -1> im, ppim, pim, fim, ppupil;
308 if(fwhm ==0 ) padw = 2*fsmooth;
310 int cutw = 0.5*(dmSz - modes.rows());
319 oModes.resize( modes.rows()+2*cutw, modes.cols()+2*cutw, modes.planes());
322 if(modes.rows() > pupil.rows())
324 padImage(ppupil, pupil, 0.5*(modes.rows()-pupil.rows()));
332 for(
int i=0;i<firstMode; ++i)
336 cutPaddedImage(im, ppim, 0.5*ppim.rows() - (0.5*modes.rows()+cutw));
338 oModes.
image(i) = im;
341 for(
int i=firstMode; i< modes.planes(); ++i)
344 if(fwhm > 0 || fsmooth > 0)
347 im = modes.image(i)*pupil;
355 fim = ppim + fim*(ppupil - 1).abs();
370 cutPaddedImage(im, fim, 0.5*fim.rows() - (0.5*modes.rows()+cutw));
372 oModes.
image(i) = im;
376 std::string oFName = mx::AO::path::basis::modes(outputBasisN,
true);
377 ff.
write(oFName, oModes);
383 template<
typename realT>
384 int apodizeBasis(
const std::string & outputBasisN,
385 const std::string & inputBasisN,
394 std::string basisFName = mx::AO::path::basis::modes(inputBasisN);
396 ff.
read(basisFName, modes);
398 realT cen = 0.5*(modes.rows() - 1.0);
400 Eigen::Array<realT, -1, -1> pupil;
401 pupil.resize( modes.rows(), modes.cols());
405 window::tukey2d<realT>(pupil.data(), modes.rows(), modes.rows() + overScan, tukeyAlpha, cen,cen);
409 window::tukey2dAnnulus<realT>(pupil.data(), modes.rows(), modes.rows() + overScan, centralObs, tukeyAlpha, cen,cen);
414 for(
int i=firstMode; i< modes.planes(); ++i)
416 modes.image(i) = modes.image(i)*pupil;
419 std::string oFName = mx::AO::path::basis::modes(outputBasisN,
true);
420 ff.
write(oFName, modes);
426 template<
typename realT>
427 int subtractBasis(
const std::string & basisName,
428 const std::string & basisName1,
429 const std::string & basisName2,
430 const std::string & pupilName,
436 std::string basisFName1 = mx::AO::path::basis::modes(basisName1);
438 ff.
read(basisFName1, modes1);
440 std::string basisFName2 = mx::AO::path::basis::modes(basisName2);
442 ff.
read(basisFName2, modes2, head);
443 realT fwhm = head[
"FWHM"].value<realT>();
446 modes.resize( modes1.rows(), modes1.cols(), modes1.planes() + modes2.planes());
449 Eigen::Array<realT, -1, -1> pupil;
450 ff.
read(pupilFName, pupil);
452 for(
int i=0; i < modes1.planes(); ++i)
454 modes.image(i) = modes1.
image(i)*pupil;
457 for(
int i=0; i < modes2.planes(); ++i)
459 modes.image( modes1.planes() + i) = modes2.
image(i)*pupil;
464 orthogonalizeBasis(ortho, modes, method);
468 Eigen::Array<realT, -1, -1> im, ppim, pim, fim, ppupil;
470 modes.resize(ortho.rows(), ortho.cols(), modes2.planes());
476 for(
int i=0; i< modes2.planes(); ++i)
478 modes.image(i) = ortho.
image( modes1.planes() + i)*pupil;
487 fim = ppim + fim*(ppupil - 1).abs();
502 std::string orthoFName = mx::AO::path::basis::modes(basisName,
true);
503 ff.
write(orthoFName, modes);
Standardized paths for the mx::AO system.
std::string U(const std::string &sysName, const std::string &dmName, const std::string &wfsName, const std::string &pupilName, const std::string &basisName, const std::string &id, bool create=false)
Path for the system response interaction matrix.
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.
Class to manage interactions with a FITS file.
int write(const dataT *im, int d1, int d2, int d3, fitsHeader *head)
Write the contents of a raw array to the FITS file.
int read(dataT *data)
Read the contents of the FITS file into an array.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > image(Index n)
Returns a 2D Eigen::Eigen::Map pointed at the specified image.
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.
void filterImage(imageOutT &fim, imageInT im, 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.
vectorT::value_type vectorMedianInPlace(vectorT &vec)
Calculate median of a vector in-place, altering the vector.
Symetric Gaussian smoothing kernel.