00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef ARROYO_LEAST_SQUARES_RECONSTRUCTOR_H
00032 #define ARROYO_LEAST_SQUARES_RECONSTRUCTOR_H
00033
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <unistd.h>
00037 #include <iostream>
00038 #include <region_base.h>
00039 #include <linear_algebra.h>
00040 #include "zernike_projected_zonal_reconstructor.h"
00041 #include "aperture.h"
00042 #include "lenslet_array.h"
00043
00044 namespace Arroyo {
00048
00049 template<class T>
00050 class arroyo_least_squares_reconstructor :
00051 public zernike_projected_zonal_reconstructor,
00052 public Arroyo::pixel_array<T> {
00053
00054 private:
00055
00056 static const bool factory_registration;
00057
00060 std::string unique_name() const {return(std::string("arroyo least squares reconstructor"));};
00061
00062 protected:
00063
00065 vector<long> actuator_axes;
00066
00068 vector<long> centroid_axes;
00069
00071 zernike projected_modes;
00072
00073
00074
00075 bool eigenmodes_stored_in_instance;
00076
00077
00078 double eigenvalue_threshold;
00079
00080
00081
00082 bool geometry_matrix_stored_in_instance;
00083
00084
00085 bool app_sign_convention;
00086
00087
00088 double subaperture_illumination_threshold;
00089
00091 pixel_array<T> geometry_matrix;
00092
00094 pixel_array<T> g_gtranspose_eigenmodes;
00095
00097 pixel_array<T> gtranspose_g_eigenmodes;
00098
00100 pixel_array<T> sqrt_eigenvalues;
00101
00102
00105 arroyo_least_squares_reconstructor(){};
00106
00107 public:
00108
00111 arroyo_least_squares_reconstructor(const arroyo_least_squares_reconstructor & arroyo_lsq_recon);
00112
00115 arroyo_least_squares_reconstructor(const char * filename);
00116
00119 arroyo_least_squares_reconstructor(const Arroyo::iofits & iof);
00120
00149 template<class aperture_type, class dm_ap>
00150 arroyo_least_squares_reconstructor(const aperture_type & ap,
00151 const ideal_deformable_mirror<dm_ap> & idm,
00152 const square_lenslet_array & sq_lnslt_arr,
00153 const zernike & projection_modes,
00154 bool modal_projection_in_actuator_space,
00155 double subaperture_illumination_threshold,
00156 double eigenvalue_threshold,
00157 bool aplusplus_sign_convention = false,
00158 bool store_eigenmodes = false,
00159 bool store_geometry_matrix = false);
00160
00163 ~arroyo_least_squares_reconstructor(){};
00164
00167 arroyo_least_squares_reconstructor &
00168 operator=(const arroyo_least_squares_reconstructor & arroyo_lsq_recon);
00169
00172 void read(const char * filename);
00173
00176 void read(const Arroyo::iofits & iof);
00177
00180 void write(const char * filename) const;
00181
00184 void write(Arroyo::iofits & iof) const;
00185
00188 void print(std::ostream & os, const char * prefix="") const;
00189
00193 double get_eigenvalue_threshold() const;
00194
00198 double get_subaperture_illumination_threshold() const;
00199
00203 vector<long> get_centroid_axes() const;
00204
00208 vector<long> get_actuator_axes() const;
00209
00218 Arroyo::zernike get_zernike_modes() const;
00219
00222 bool geometry_matrix_stored() const;
00223
00226 bool eigenmodes_stored() const;
00227
00234 pixel_array<T> get_geometry_matrix() const;
00235
00241 int get_nactuator_eigenmodes() const;
00242
00248 int get_ncentroid_eigenmodes() const;
00249
00259 double get_eigenvalue(int mode_number) const;
00260
00270 template<class U>
00271 double get_actuator_eigenmode(int mode_number,
00272 pixel_array<U> & actuator_mode) const;
00273
00283 double get_centroid_eigenmode(int mode_number,
00284 Shack_Hartmann_centroids & centroid_mode) const;
00285
00292 void reconstruct_zernike_residuals(const Arroyo::Shack_Hartmann_centroids & shcentroids,
00293 Arroyo::zernike & znke) const;
00294
00298 void reconstruct_zonal_residuals(const Arroyo::Shack_Hartmann_centroids & shcentroids,
00299 Arroyo::pixel_array<double> & pixarr) const;
00300
00308 void reconstruct_residuals(const Arroyo::Shack_Hartmann_centroids & shcentroids,
00309 Arroyo::zernike & znke,
00310 Arroyo::pixel_array<double> & pixarr) const;
00311 };
00312
00313 template<class T>
00314 arroyo_least_squares_reconstructor<T>::
00315 arroyo_least_squares_reconstructor(const arroyo_least_squares_reconstructor & arroyo_lsq_recon){
00316 this->operator=(arroyo_lsq_recon);
00317 }
00318
00319 template<class T>
00320 arroyo_least_squares_reconstructor<T>::
00321 arroyo_least_squares_reconstructor(const char * filename){
00322 this->axes.resize(2);
00323 this->read(filename);
00324 }
00325
00326 template<class T>
00327 arroyo_least_squares_reconstructor<T>::
00328 arroyo_least_squares_reconstructor(const iofits & iof){
00329 this->axes.resize(2);
00330 this->read(iof);
00331 }
00332
00333 template<class T>
00334 arroyo_least_squares_reconstructor<T> &
00335 arroyo_least_squares_reconstructor<T>::
00336 operator=(const arroyo_least_squares_reconstructor & arroyo_lsq_recon){
00337 if(this==&arroyo_lsq_recon)
00338 return(*this);
00339 actuator_axes = arroyo_lsq_recon.actuator_axes;
00340 centroid_axes = arroyo_lsq_recon.centroid_axes;
00341 projected_modes = arroyo_lsq_recon.projected_modes;
00342 eigenmodes_stored_in_instance = arroyo_lsq_recon.eigenmodes_stored_in_instance;
00343 geometry_matrix_stored_in_instance = arroyo_lsq_recon.geometry_matrix_stored_in_instance;
00344 geometry_matrix = arroyo_lsq_recon.geometry_matrix;
00345 app_sign_convention = arroyo_lsq_recon.app_sign_convention;
00346 g_gtranspose_eigenmodes = arroyo_lsq_recon.g_gtranspose_eigenmodes;
00347 gtranspose_g_eigenmodes = arroyo_lsq_recon.gtranspose_g_eigenmodes;
00348 sqrt_eigenvalues = arroyo_lsq_recon.sqrt_eigenvalues;
00349
00350 this->pixel_array<T>::operator=(arroyo_lsq_recon);
00351 return(*this);
00352 }
00353
00354 template<class T>
00355 void arroyo_least_squares_reconstructor<T>::read(const char * filename){
00356 iofits iof;
00357 try{iof.open(filename);}
00358 catch(...){
00359 cerr << "arroyo_least_squares_reconstructor::read - "
00360 << "error opening file " << filename << endl;
00361 throw(string("arroyo_least_squares_reconstructor::read"));
00362 }
00363 try{this->read(iof);}
00364 catch(...){
00365 cerr << "arroyo_least_squares_reconstructor::read - "
00366 << "error reading "
00367 << this->unique_name() << " from file "
00368 << filename << endl;
00369 throw(string("arroyo_least_squares_reconstructor::read"));
00370 }
00371 }
00372
00373 template<class T>
00374 void arroyo_least_squares_reconstructor<T>::read(const iofits & iof) {
00375 if(!iof.key_exists("TYPE")){
00376 cerr << "arroyo_least_squares_reconstructor::read error - "
00377 << "unrecognized type of file\n";
00378 throw(string("arroyo_least_squares_reconstructor::read"));
00379 }
00380 string type, comment;
00381 iof.read_key("TYPE", type, comment);
00382 if(type!=this->unique_name()){
00383 cerr << "arroyo_least_squares_reconstructor::read error - file of type "
00384 << type << " rather than of type "
00385 << this->unique_name() << endl;
00386 throw(string("arroyo_least_squares_reconstructor::read"));
00387 }
00388
00389 actuator_axes.resize(2);
00390 centroid_axes.resize(2);
00391
00392 iof.read_key("ACTUATR1", actuator_axes[0], comment);
00393 iof.read_key("ACTUATR2", actuator_axes[1], comment);
00394
00395 iof.read_key("CNTROID1", centroid_axes[0], comment);
00396 iof.read_key("CNTROID2", centroid_axes[1], comment);
00397
00398 iof.read_key("EGNTHRSH", eigenvalue_threshold, comment);
00399 iof.read_key("SBPTHRSH", subaperture_illumination_threshold, comment);
00400
00401 if(iof.key_exists("EIGENMDS"))
00402 iof.read_key("EIGENMDS", eigenmodes_stored_in_instance, comment);
00403 else eigenmodes_stored_in_instance = false;
00404
00405 if(iof.key_exists("GEOMETRY"))
00406 iof.read_key("GEOMETRY", geometry_matrix_stored_in_instance, comment);
00407 else geometry_matrix_stored_in_instance = false;
00408
00409 if(iof.key_exists("APPSIGN"))
00410 iof.read_key("APPSIGN", app_sign_convention, comment);
00411 else app_sign_convention = false;
00412
00413 this->pixel_array<T>::read(iof);
00414
00415
00416
00417 int nelem = this->pixel_array<T>::total_space();
00418 nelem -= actuator_axes[0]*actuator_axes[1]*centroid_axes[0]*centroid_axes[1];
00419 if(nelem%(centroid_axes[0]*centroid_axes[1])!=0){
00420 cerr << "arroyo_least_squares_reconstructor::read error - "
00421 << "unexpected number of elements " << nelem << " in the matrix\n";
00422 throw(string("arroyo_least_squares_reconstructor::read"));
00423 }
00424
00425 int nmodes = nelem/(centroid_axes[0]*centroid_axes[1]);
00426 int zernike_order = -1;
00427 while(nmodes>0){
00428 zernike_order++;
00429 if(zernike_order%2)
00430 nmodes -= 2*(zernike_order/2+1);
00431 else
00432 nmodes -= (zernike_order+1);
00433 }
00434
00435 if(zernike_order>=0)
00436 projected_modes = zernike(zernike_order);
00437
00438 if(geometry_matrix_stored_in_instance){
00439 try{
00440 geometry_matrix.read(iof);
00441 } catch(...) {
00442 cerr << "arroyo_least_squares_reconstructor::read - error reading geometry matrix\n";
00443 throw(string("arroyo_least_squares_reconstructor::read"));
00444 }
00445 }
00446
00447 if(eigenmodes_stored_in_instance){
00448
00449 try{
00450 sqrt_eigenvalues.read(iof);
00451 } catch(...) {
00452 cerr << "arroyo_least_squares_reconstructor::read - error reading eigenvalues\n";
00453 throw(string("arroyo_least_squares_reconstructor::read"));
00454 }
00455
00456 try{
00457 g_gtranspose_eigenmodes.read(iof);
00458 gtranspose_g_eigenmodes.read(iof);
00459 } catch(...) {
00460 cerr << "arroyo_least_squares_reconstructor::read - error reading GGtranspose matrices\n";
00461 throw(string("arroyo_least_squares_reconstructor::read"));
00462 }
00463 }
00464
00465
00466 if(iof.get_hdu_num()!=iof.get_num_hdus())
00467 iof.movrel_hdu(1);
00468 }
00469
00470 template<class T>
00471 void arroyo_least_squares_reconstructor<T>::write(const char * filename) const {
00472
00473 iofits iof;
00474 try{iof.create(filename);}
00475 catch(...){
00476 cerr << "arroyo_least_squares_reconstructor::write - "
00477 << "error opening file " << filename << endl;
00478 throw(string("arroyo_least_squares_reconstructor::write"));
00479 }
00480
00481 try{this->write(iof);}
00482 catch(...){
00483 cerr << "arroyo_least_squares_reconstructor::write - "
00484 << "error writing "
00485 << this->unique_name() << " to file "
00486 << filename << endl;
00487 throw(string("arroyo_least_squares_reconstructor::write"));
00488 }
00489 }
00490
00491 template<class T>
00492 void arroyo_least_squares_reconstructor<T>::write(iofits & iof) const {
00493 fits_header_data<T> fhd(this->axes);
00494 fhd.write(iof);
00495 string type = this->unique_name();
00496 string comment = "object type";
00497 iof.write_key("TYPE", type, comment);
00498
00499 iof.write_key("ACTUATR1", actuator_axes[0], "length of actuator axis 1");
00500 iof.write_key("ACTUATR2", actuator_axes[1], "length of actuator axis 2");
00501
00502 iof.write_key("CNTROID1", centroid_axes[0], "length of centroid axis 1");
00503 iof.write_key("CNTROID2", centroid_axes[1], "length of centroid axis 2");
00504
00505 iof.write_key("EGNTHRSH", eigenvalue_threshold, "threshold for keeping eigenvalues");
00506 iof.write_key("SBPTHRSH", subaperture_illumination_threshold, "threshold for keeping partially illuminated subaps");
00507
00508 iof.write_key("APPSIGN", app_sign_convention, "A++ sign convention");
00509
00510 if(sqrt_eigenvalues.get_axes().size())
00511 iof.write_key("EIGENMDS", true, "eigenmodes stored");
00512 else
00513 iof.write_key("EIGENMDS", false, "eigenmodes stored");
00514
00515 if(geometry_matrix.get_axes().size())
00516 iof.write_key("GEOMETRY", true, "geometry matrix stored");
00517 else
00518 iof.write_key("GEOMETRY", false, "geometry matrix stored");
00519
00520 this->pixel_array<T>::write(iof);
00521
00522 if(geometry_matrix.get_axes().size()){
00523 fits_header_data<T> fhd(geometry_matrix.get_axes());
00524 fhd.write(iof);
00525 geometry_matrix.write(iof);
00526 }
00527
00528 if(sqrt_eigenvalues.get_axes().size()){
00529 fits_header_data<T> fhd1(sqrt_eigenvalues.get_axes());
00530 fhd1.write(iof);
00531 sqrt_eigenvalues.write(iof);
00532
00533 fits_header_data<T> fhd2(g_gtranspose_eigenmodes.get_axes());
00534 fhd2.write(iof);
00535 g_gtranspose_eigenmodes.write(iof);
00536
00537 fits_header_data<T> fhd3(gtranspose_g_eigenmodes.get_axes());
00538 fhd3.write(iof);
00539 gtranspose_g_eigenmodes.write(iof);
00540 }
00541 }
00542
00543 template<class T>
00544 void arroyo_least_squares_reconstructor<T>::print(ostream & os, const
00545 char * prefix) const {
00546 int vlspc = 30;
00547 os.setf(std::ios::left, std::ios::adjustfield);
00548 os << prefix << "TYPE = " << setw(vlspc) << this->unique_name()
00549 << "/" << "object type" << endl;
00550 fits_header_data<T> fhd(this->axes);
00551 fhd.print(os, prefix);
00552 os << prefix << "ACTUATR1 = " << setw(vlspc) << this->actuator_axes[0]
00553 << "/" << "length of actuator axis 1" << endl;
00554 os << prefix << "ACTUATR2 = " << setw(vlspc) << this->actuator_axes[1]
00555 << "/" << "length of actuator axis 2" << endl;
00556 os << prefix << "CNTROID1 = " << setw(vlspc) << this->centroid_axes[0]
00557 << "/" << "length of centroid axis 1" << endl;
00558 os << prefix << "CNTROID2 = " << setw(vlspc) << this->centroid_axes[1]
00559 << "/" << "length of centroid axis 2" << endl;
00560 os << prefix << "EGNTHRSH = " << setw(vlspc) << this->eigenvalue_threshold
00561 << "/" << "threshold for keeping eigenvalues" << endl;
00562 os << prefix << "APPSIGN = " << setw(vlspc) << this->app_sign_convention
00563 << "/" << "A++ sign convention" << endl;
00564 os << prefix << "SBPTHRSH = " << setw(vlspc) << this->subaperture_illumination_threshold
00565 << "/" << "threshold for keeping partially illuminated subaps" << endl;
00566 os << prefix << "GEOMETRY = " << setw(vlspc) << this->geometry_matrix_stored_in_instance
00567 << "/" << "geometry matrix storage flag" << endl;
00568 os << prefix << "EIGENMDS = " << setw(vlspc) << this->eigenmodes_stored_in_instance
00569 << "/" << "eigenmodes storage flag" << endl;
00570 }
00571
00572 template<class T>
00573 vector<long> arroyo_least_squares_reconstructor<T>::get_centroid_axes() const {
00574 return(centroid_axes);
00575 }
00576
00577 template<class T>
00578 vector<long> arroyo_least_squares_reconstructor<T>::get_actuator_axes() const {
00579 return(actuator_axes);
00580 }
00581
00582 template<class T>
00583 zernike arroyo_least_squares_reconstructor<T>::get_zernike_modes() const {
00584 return(projected_modes);
00585 }
00586
00587 template<class T>
00588 double arroyo_least_squares_reconstructor<T>::get_eigenvalue_threshold() const {
00589 return(eigenvalue_threshold);
00590 }
00591
00592 template<class T>
00593 double arroyo_least_squares_reconstructor<T>::get_subaperture_illumination_threshold() const {
00594 return(subaperture_illumination_threshold);
00595 }
00596
00597 template<class T>
00598 int arroyo_least_squares_reconstructor<T>::get_nactuator_eigenmodes() const {
00599 return(actuator_axes[0]*actuator_axes[1]);
00600 }
00601
00602 template<class T>
00603 int arroyo_least_squares_reconstructor<T>::get_ncentroid_eigenmodes() const {
00604 return(centroid_axes[0]*centroid_axes[1]);
00605 }
00606
00607 template<class T>
00608 bool arroyo_least_squares_reconstructor<T>::
00609 geometry_matrix_stored() const {
00610 return(this->geometry_matrix_stored_in_instance);
00611 };
00612
00613 template<class T>
00614 bool arroyo_least_squares_reconstructor<T>::
00615 eigenmodes_stored() const {
00616 return(this->eigenmodes_stored_in_instance);
00617 };
00618
00619 template<class T>
00620 pixel_array<T> arroyo_least_squares_reconstructor<T>::
00621 get_geometry_matrix() const {
00622 if(this->geometry_matrix_stored())
00623 return(this->geometry_matrix);
00624 else {
00625 cerr << "arroyo_least_squares_reconstructor::get_geometry_matrix error - "
00626 << "this class instance generated without saving geometry matrix\n";
00627 throw(string("arroyo_least_squares_reconstructor::get_geometry_matrix"));
00628 }
00629 };
00630
00631 template<class T>
00632 double arroyo_least_squares_reconstructor<T>::
00633 get_eigenvalue(int mode_number) const {
00634
00635 if(!this->eigenmodes_stored_in_instance){
00636 cerr << "arroyo_least_squares_reconstructor::get_eigenvalue error - "
00637 << " this class instance was constructed without saving the eigenmodes\n";
00638 throw(string("arroyo_least_squares_reconstructor::get_eigenvalue"));
00639 }
00640
00641 if(mode_number<0 || mode_number>this->get_nactuator_eigenmodes()){
00642 cerr << "arroyo_least_squares_reconstructor::get_eigenvalue error - "
00643 << " mode number " << mode_number << " out of range\n";
00644 throw(string("arroyo_least_squares_reconstructor::get_eigenvalue"));
00645 }
00646
00647 return(sqrt_eigenvalues.data(mode_number)*sqrt_eigenvalues.data(mode_number));
00648 }
00649
00650 template<class T>
00651 template<class U>
00652 double arroyo_least_squares_reconstructor<T>::
00653 get_actuator_eigenmode(int mode_number, pixel_array<U> & actuators) const {
00654
00655 if(!this->eigenmodes_stored_in_instance){
00656 cerr << "arroyo_least_squares_reconstructor::get_actuator_eigenmode error - "
00657 << " this class instance was constructed without saving the eigenmodes\n";
00658 throw(string("arroyo_least_squares_reconstructor::get_actuator_eigenmode"));
00659 }
00660
00661 if(mode_number<0 || mode_number>this->get_nactuator_eigenmodes()){
00662 cerr << "arroyo_least_squares_reconstructor::get_actuator_eigenmode error - "
00663 << " mode number " << mode_number << " out of range\n";
00664 throw(string("arroyo_least_squares_reconstructor::get_actuator_eigenmode"));
00665 }
00666
00667 if(actuators.get_axes()!=actuator_axes){
00668 cerr << "arroyo_least_squares_reconstructor::get_actuator_eigenmode error - "
00669 << "pixel array instance passed to this function "
00670 << "has a different dimensionality than expected\n";
00671 cerr << "\texpected " << actuator_axes[0] << "x" << actuator_axes[1] << endl;
00672 cerr << "\tgot " << actuators.get_axes()[0] << "x" << actuators.get_axes()[1] << endl;
00673 throw(string("arroyo_least_squares_reconstructor::get_actuator_eigenmode"));
00674 }
00675
00676 int nactuators = actuator_axes[0]*actuator_axes[1];
00677 for(int i=0; i<nactuators; i++)
00678 actuators.set_data(i, gtranspose_g_eigenmodes.data(mode_number+i*nactuators));
00679
00680 return(sqrt_eigenvalues.data(mode_number)*sqrt_eigenvalues.data(mode_number));
00681 }
00682
00683 template<class T>
00684 double arroyo_least_squares_reconstructor<T>::
00685 get_centroid_eigenmode(int mode_number, Shack_Hartmann_centroids & shcentroids) const {
00686
00687 if(!this->eigenmodes_stored_in_instance){
00688 cerr << "arroyo_least_squares_reconstructor::get_centroid_eigenmode error - "
00689 << " this class instance was constructed without saving the eigenmodes\n";
00690 throw(string("arroyo_least_squares_reconstructor::get_centroid_eigenmode"));
00691 }
00692
00693 if(mode_number<0 || mode_number>this->get_ncentroid_eigenmodes()){
00694 cerr << "arroyo_least_squares_reconstructor::get_centroid_eigenmode error - "
00695 << " mode number " << mode_number << " out of range\n";
00696 throw(string("arroyo_least_squares_reconstructor::get_centroid_eigenmode"));
00697 }
00698
00699 if(shcentroids.get_axes()!=centroid_axes){
00700 cerr << "arroyo_least_squares_reconstructor::get_centroid_eigenmode error - "
00701 << "Shack Hartmann centroid instance passed to this function "
00702 << "has a different dimensionality than expected\n";
00703 cerr << "\texpected " << centroid_axes[0] << "x" << centroid_axes[1] << endl;
00704 cerr << "\tgot " << shcentroids.get_axes()[0] << "x" << shcentroids.get_axes()[1] << endl;
00705 throw(string("arroyo_least_squares_reconstructor::get_centroid_eigenmode"));
00706 }
00707
00708 int ncentroids = centroid_axes[0]*centroid_axes[1];
00709 for(int i=0; i<ncentroids; i++)
00710 shcentroids.set_data(i, g_gtranspose_eigenmodes.data(mode_number*ncentroids+i));
00711
00712 if(mode_number<sqrt_eigenvalues.get_axes()[0])
00713 return(sqrt_eigenvalues.data(mode_number)*sqrt_eigenvalues.data(mode_number));
00714 else
00715 return(0);
00716 }
00717
00718 template<class T>
00719 void arroyo_least_squares_reconstructor<T>::
00720 reconstruct_zernike_residuals(const Arroyo::Shack_Hartmann_centroids & shcentroids,
00721 zernike & znke) const {
00722
00723 if(shcentroids.total_space()!=this->axes[0]){
00724 cerr << "arroyo_least_squares_reconstructor::reconstruct_zernike_residuals error - "
00725 << " Shack Hartmann centroids instance supplied to this function has "
00726 << shcentroids.total_space() << " elements, whereas "
00727 << this->axes[0] << " were expected by the reconstructor\n";
00728 throw(string("arroyo_least_squares_reconstructor::reconstruct_zernike_residuals"));
00729 }
00730
00731 if(znke.get_order()!=projected_modes.get_order()){
00732 cerr << "arroyo_least_squares_reconstructor::reconstruct_zernike_residuals error - "
00733 << " zernike order supplied to this function "
00734 << znke.get_order() << " does not match that expected by the reconstructor "
00735 << projected_modes.get_order() << endl;
00736 throw(string("arroyo_least_squares_reconstructor::reconstruct_zernike_residuals"));
00737 }
00738
00739
00740
00741
00742 int xindex = centroid_axes[0]*centroid_axes[1]*(actuator_axes[0]*actuator_axes[1]+1);
00743 int yindex = xindex + centroid_axes[0]*centroid_axes[1];
00744 double xresid, yresid;
00745 xresid = yresid = 0;
00746
00747 for(int j=0; j<this->axes[0]; j++){
00748 xresid -= this->pixeldata[xindex+j]*shcentroids.data(j);
00749 yresid -= this->pixeldata[yindex+j]*shcentroids.data(j);
00750 }
00751
00752 znke.set_cos_coeff(1,1,xresid);
00753 znke.set_sin_coeff(1,1,yresid);
00754 }
00755
00756 template<class T>
00757 void arroyo_least_squares_reconstructor<T>::
00758 reconstruct_zonal_residuals(const Arroyo::Shack_Hartmann_centroids & shcentroids,
00759 pixel_array<double> & pixarr) const {
00760
00761 vector<long> pixarr_axes = pixarr.get_axes();
00762 if(pixarr_axes[0]!=actuator_axes[0] ||
00763 pixarr_axes[1]!=actuator_axes[1]){
00764 cerr << "arroyo_least_squares_reconstructor::reconstruct_zonal_residuals error - " << endl
00765 << "pixel array instance passed to reconstructor has axes "
00766 << pixarr_axes[0] << "x" << pixarr_axes[1]
00767 << " elements, rather than axes "
00768 << actuator_axes[0] << "x" << actuator_axes[1]
00769 << " expected by this reconstructor\n";
00770 throw(string("arroyo_least_squares_reconstructor::reconstruct_zonal_residuals"));
00771 }
00772
00773 long index = 0;
00774 double resid;
00775 long nsubaps = centroid_axes[0]*centroid_axes[1]/2;
00776 int nactuators = actuator_axes[0]*actuator_axes[1];
00777 int app_sign = app_sign_convention ? -1 : 1;
00778
00779 for(int i=0; i<actuator_axes[1]; i++){
00780 for(int j=0; j<actuator_axes[0]; j++){
00781 resid = 0;
00782 for(int k=0; k<nsubaps; k++){
00783
00784 resid -= app_sign*this->pixeldata[index+k]*shcentroids.data(k);
00785 resid -= this->pixeldata[index+nsubaps+k]*shcentroids.data(k+nsubaps);
00786 }
00787 pixarr.set_data(j*actuator_axes[1]+i, resid);
00788 index += this->axes[0];
00789 }
00790 }
00791 }
00792
00793 template<class T>
00794 void arroyo_least_squares_reconstructor<T>::
00795 reconstruct_residuals(const Arroyo::Shack_Hartmann_centroids & shcentroids,
00796 zernike & znke,
00797 pixel_array<double> & pixarr) const {
00798 this->reconstruct_zernike_residuals(shcentroids, znke);
00799 this->reconstruct_zonal_residuals(shcentroids, pixarr);
00800 }
00801
00802 template<class T>
00803 template<class pupil_aperture, class dm_aperture>
00804 arroyo_least_squares_reconstructor<T>::
00805 arroyo_least_squares_reconstructor(const pupil_aperture & ap,
00806 const ideal_deformable_mirror<dm_aperture> & ideal_dm,
00807 const square_lenslet_array & sq_lnslt_arr,
00808 const zernike & projected_modes,
00809 bool modal_projection_in_actuator_space,
00810 double subaperture_illumination_threshold,
00811 double eigenvalue_threshold,
00812 bool aplusplus_sign_convention,
00813 bool store_eigenmodes,
00814 bool store_geometry_matrix){
00815
00816 this->projected_modes = projected_modes;
00817 this->actuator_axes = ideal_dm.get_axes();
00818 this->centroid_axes = sq_lnslt_arr.get_axes();
00819 this->centroid_axes[1]*=2;
00820 this->subaperture_illumination_threshold = subaperture_illumination_threshold;
00821 this->eigenvalue_threshold = eigenvalue_threshold;
00822 this->eigenmodes_stored_in_instance = store_eigenmodes;
00823 this->geometry_matrix_stored_in_instance = store_geometry_matrix;
00824 this->app_sign_convention = aplusplus_sign_convention;
00825
00826
00827 if(fabs(sq_lnslt_arr.three_point::z(ap))>three_frame::precision){
00828 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - \n"
00829 << "lenslet array does not lie in the plane of the aperture\n";
00830 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00831 }
00832
00833
00834 if(fabs(ideal_dm.three_point::z(ap))>three_frame::precision){
00835 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - \n"
00836 << "deformable mirror does not lie in the plane of the aperture\n";
00837 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00838 }
00839
00840
00841 if(fabs(1-dot_product(ap.z(), sq_lnslt_arr.z()))>three_frame::precision){
00842 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - \n"
00843 << "cannot construct reconstructor with aperture and lenslet axes misaligned\n";
00844 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00845 }
00846
00847
00848 if(fabs(1-dot_product(ap.z(), ideal_dm.z()))>three_frame::precision){
00849 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - \n"
00850 << "cannot construct reconstructor with aperture and deformable mirror misaligned\n";
00851 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00852 }
00853
00854 if(projected_modes.get_order()>1){
00855 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - "
00856 << "projections for modes other than tip and tilt are not yet supported\n";
00857 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00858 }
00859
00860
00861 if(subaperture_illumination_threshold<0 || subaperture_illumination_threshold>1){
00862 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - "
00863 << "invalid subaperture illumination threshold " << subaperture_illumination_threshold << endl;
00864 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00865 }
00866
00867
00868 if(eigenvalue_threshold<0 || eigenvalue_threshold>1){
00869 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - "
00870 << "invalid eigenvalue threshold " << eigenvalue_threshold << endl;
00871 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00872 }
00873
00874
00875 three_vector lenslet_array_origin_offset = sq_lnslt_arr - ap;
00876 three_vector lenslet_dx = sq_lnslt_arr.get_lenslet_pitch()*sq_lnslt_arr.x();
00877 three_vector lenslet_dy = sq_lnslt_arr.get_lenslet_pitch()*sq_lnslt_arr.y();
00878 three_vector lenslet_dx_unit_vector = lenslet_dx*(1/lenslet_dx.length());
00879 three_vector lenslet_dy_unit_vector = lenslet_dy*(1/lenslet_dy.length());
00880
00881 double lenslet_buffer = (lenslet_dy+lenslet_dx).length() > (lenslet_dy-lenslet_dx).length() ?
00882 .5*(lenslet_dy+lenslet_dx).length() : .5*(lenslet_dy-lenslet_dx).length();
00883
00884
00885
00886 three_vector dm_origin_offset = ideal_dm - ap;
00887 three_vector dm_dx = ideal_dm.get_actuator_pitch()*ideal_dm.x();
00888 three_vector dm_dy = ideal_dm.get_actuator_pitch()*ideal_dm.y();
00889
00890 double dm_buffer = (dm_dy+dm_dx).length() > (dm_dy-dm_dx).length() ?
00891 .5*(dm_dy+dm_dx).length() : .5*(dm_dy-dm_dx).length();
00892
00893 double geometry_matrix_buffer = 2*(lenslet_buffer+dm_buffer)*(lenslet_buffer+dm_buffer);
00894
00895
00896 vector<long> lenslet_axes = sq_lnslt_arr.get_axes();
00897 double lenslet_x_halfpix = lenslet_axes[1]%2==1 ? 0 : .5;
00898 double lenslet_y_halfpix = lenslet_axes[0]%2==1 ? 0 : .5;
00899 int lenslet_x_extrapix = lenslet_axes[1]%2==1 ? 1 : 0;
00900 int lenslet_y_extrapix = lenslet_axes[0]%2==1 ? 1 : 0;
00901
00902
00903 vector<long> dm_axes = ideal_dm.get_axes();
00904 double dm_x_halfpix = dm_axes[1]%2==1 ? 0 : .5;
00905 double dm_y_halfpix = dm_axes[0]%2==1 ? 0 : .5;
00906 int dm_x_extrapix = dm_axes[1]%2==1 ? 1 : 0;
00907 int dm_y_extrapix = dm_axes[0]%2==1 ? 1 : 0;
00908
00909 long nlenslets = lenslet_axes[0]*lenslet_axes[1];
00910 long nactuators = dm_axes[0]*dm_axes[1];
00911
00912
00914
00916
00917 vector<long> geometry_matrix_axes(2,2*nlenslets);
00918 geometry_matrix_axes[1] = nactuators;
00919
00920 T * geometry_matrix_data;
00921
00922 try{
00923 int nelem = geometry_matrix_axes[0]*geometry_matrix_axes[1];
00924 geometry_matrix_data = new T[nelem];
00925 for(int i=0; i<nelem; i++)
00926 geometry_matrix_data[i] = 0;
00927 } catch(...){
00928 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - "
00929 << "unable to allocate memory for a geometry matrix with "
00930 << geometry_matrix_axes[0]*geometry_matrix_axes[1] << " elements\n";
00931 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
00932 }
00933
00934 three_point subaperture_center_point;
00935 three_vector subap_corner_offset_a = .5*(lenslet_dy+lenslet_dx);
00936 three_vector subap_corner_offset_b = .5*(lenslet_dy-lenslet_dx);
00937 three_vector actuator_offset_a = dm_dy+dm_dx;
00938 three_vector actuator_offset_b = dm_dy-dm_dx;
00939
00940 vector<three_point> subaperture_vertices(4);
00941 vector<three_point> actuator_influence_function_vertices(4);
00942 vector<three_point> intersection_vertices;
00943
00944
00945 long index;
00946 double overlap;
00947 double subaperture_area = cross_product(lenslet_dx, lenslet_dy).length();
00948 double sign_convention = aplusplus_sign_convention ? -1 : 1;
00949
00950 three_frame local_actuator_frame, local_subap_frame;
00951 vector<long> unilluminated_subaps;
00952
00953 double lenslet_pitch = sq_lnslt_arr.get_lenslet_pitch();
00954 double norm = 1/(lenslet_pitch*lenslet_pitch*lenslet_pitch);
00955
00956
00957 double a_0 = dot_product(ideal_dm.x(), sq_lnslt_arr.x());
00958 double a_1 = dot_product(ideal_dm.x(), sq_lnslt_arr.y());
00959 double b_0 = dot_product(ideal_dm.y(), sq_lnslt_arr.x());
00960 double b_1 = dot_product(ideal_dm.y(), sq_lnslt_arr.y());
00961 double a_2, b_2;
00962
00963
00964 double S_0, S_x, S_y;
00965
00966
00967 double s_u, s_v;
00968
00969 try{
00970
00971 for(int l=-lenslet_axes[1]/2; l<lenslet_axes[1]/2+lenslet_x_extrapix; l++){
00972 for(int m=-lenslet_axes[0]/2; m<lenslet_axes[0]/2+lenslet_y_extrapix; m++){
00973
00974 subaperture_center_point = ap +
00975 (lenslet_array_origin_offset + (l+lenslet_x_halfpix)*lenslet_dx + (m+lenslet_y_halfpix)*lenslet_dy);
00976
00977 subaperture_vertices[0] = subaperture_center_point + subap_corner_offset_a;
00978 subaperture_vertices[1] = subaperture_center_point + subap_corner_offset_b;
00979 subaperture_vertices[2] = subaperture_center_point - subap_corner_offset_a;
00980 subaperture_vertices[3] = subaperture_center_point - subap_corner_offset_b;
00981
00982
00983
00984
00985
00986
00987
00988
00989 overlap = ap.convex_polygon_overlap(subaperture_vertices);
00990
00991 if(overlap<subaperture_area*subaperture_illumination_threshold){
00992 unilluminated_subaps.push_back((l+lenslet_axes[1]/2)*lenslet_axes[0]+m+lenslet_axes[0]/2);
00993 continue;
00994 }
00995
00996 local_subap_frame = sq_lnslt_arr;
00997 local_subap_frame.three_point::operator=(subaperture_vertices[2]);
00998
00999
01000 for(int i=-dm_axes[1]/2; i<dm_axes[1]/2+dm_x_extrapix; i++){
01001 for(int j=-dm_axes[0]/2; j<dm_axes[0]/2+dm_y_extrapix; j++){
01002
01003
01004 actuator_influence_function_vertices[0] = ap +
01005 (dm_origin_offset + (i+dm_x_halfpix)*dm_dx + (j+dm_y_halfpix)*dm_dy);
01006
01007 if((actuator_influence_function_vertices[0]-subaperture_center_point).length_squared()>geometry_matrix_buffer)
01008 continue;
01009
01010
01011 for(int k=0; k<4; k++){
01012
01013 if(k==0){
01014 actuator_influence_function_vertices[1] = actuator_influence_function_vertices[0] + dm_dx;
01015 actuator_influence_function_vertices[2] = actuator_influence_function_vertices[1] + dm_dy;
01016 actuator_influence_function_vertices[3] = actuator_influence_function_vertices[2] - dm_dx;
01017 s_u = s_v = -1;
01018 } else if(k==1){
01019 actuator_influence_function_vertices[1] = actuator_influence_function_vertices[0] + dm_dy;
01020 actuator_influence_function_vertices[2] = actuator_influence_function_vertices[1] - dm_dx;
01021 actuator_influence_function_vertices[3] = actuator_influence_function_vertices[2] - dm_dy;
01022 s_u = 1; s_v = -1;
01023 } else if(k==2){
01024 actuator_influence_function_vertices[1] = actuator_influence_function_vertices[0] - dm_dx;
01025 actuator_influence_function_vertices[2] = actuator_influence_function_vertices[1] - dm_dy;
01026 actuator_influence_function_vertices[3] = actuator_influence_function_vertices[2] + dm_dx;
01027 s_u = s_v = 1;
01028 } else if(k==3){
01029 actuator_influence_function_vertices[1] = actuator_influence_function_vertices[0] - dm_dy;
01030 actuator_influence_function_vertices[2] = actuator_influence_function_vertices[1] + dm_dx;
01031 actuator_influence_function_vertices[3] = actuator_influence_function_vertices[2] + dm_dy;
01032 s_u = -1; s_v = 1;
01033 }
01034
01035 intersection_vertices =
01036 get_convex_polygon_intersection(actuator_influence_function_vertices, subaperture_vertices);
01037
01038 overlap = 0;
01039 if(intersection_vertices.size()>2){
01040 try{overlap = ap.convex_polygon_overlap(intersection_vertices);}
01041 catch(...) {
01042 cerr << "facet " << k << endl;
01043 for(int i=0; i<actuator_influence_function_vertices.size(); i++)
01044 actuator_influence_function_vertices[i].print(cerr, "aif ");
01045 cerr << endl;
01046 for(int i=0; i<subaperture_vertices.size(); i++)
01047 subaperture_vertices[i].print(cerr, "subap ");
01048 cerr << endl;
01049 for(int i=0; i<intersection_vertices.size(); i++)
01050 intersection_vertices[i].print(cerr, "int ");
01051 cerr << endl;
01052 throw(string("overlap"));
01053 }
01054 }
01055
01056 if(overlap>0){
01057 index = ((i+dm_axes[1]/2)*dm_axes[0]+j+dm_axes[0]/2)*2*nlenslets +
01058 (l+lenslet_axes[1]/2)*lenslet_axes[0]+m+lenslet_axes[0]/2;
01059
01060
01061 local_actuator_frame = three_frame(ideal_dm);
01062 local_actuator_frame.three_point::operator=(actuator_influence_function_vertices[0]);
01063 a_2 = local_subap_frame.three_point::x(local_actuator_frame);
01064 b_2 = local_subap_frame.three_point::y(local_actuator_frame);
01065
01066 S_0 = get_area_of_polygon(intersection_vertices);
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076 convex_polygon_integration(local_subap_frame,
01077 intersection_vertices,
01078 S_x,
01079 S_y);
01080
01081 geometry_matrix_data[index] +=
01082 -1*sign_convention*norm*((s_u*a_0*(lenslet_pitch+s_v*b_2)+s_v*b_0*(lenslet_pitch+s_u*a_2))*S_0 +
01083 2*s_u*s_v*a_0*b_0*S_x + s_u*s_v*(a_0*b_1+a_1*b_0)*S_y);
01084
01085 geometry_matrix_data[index+nlenslets] +=
01086 -1*norm*((s_u*a_1*(lenslet_pitch+s_v*b_2)+s_v*b_1*(lenslet_pitch+s_u*a_2))*S_0 +
01087 s_u*s_v*(a_0*b_1+a_1*b_0)*S_x + 2*s_u*s_v*a_1*b_1*S_y);
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114 }
01115 }
01116 }
01117 }
01118 }
01119 }
01120 } catch(...){
01121 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - "
01122 << "could not form geometry matrix\n";
01123 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
01124 }
01125
01126
01127
01128 if(store_geometry_matrix)
01129 geometry_matrix = pixel_array<T>(geometry_matrix_axes, geometry_matrix_data);
01130
01131
01132
01133
01135
01137
01138 char jobu[1];
01139 char jobvt[1];
01140 if(store_eigenmodes)
01141 jobu[0] = jobvt[0] = 'A';
01142 else
01143 jobu[0] = jobvt[0] = 'S';
01144 int lwork=-1, info;
01145 T optimal_workspace_size;
01146 T *singular_values, *g_gtranspose_eigenmode_data, *gtranspose_g_eigenmode_data, *work;
01147
01148 int geo_mtx_axes_0 = geometry_matrix_axes[0];
01149 int geo_mtx_axes_1 = geometry_matrix_axes[1];
01150
01151 singular_value_decomposition<T>(jobu,
01152 jobvt,
01153 geo_mtx_axes_0,
01154 geo_mtx_axes_1,
01155 geometry_matrix_data,
01156 geo_mtx_axes_0,
01157 singular_values,
01158 g_gtranspose_eigenmode_data,
01159 geo_mtx_axes_0,
01160 gtranspose_g_eigenmode_data,
01161 geo_mtx_axes_1,
01162 &optimal_workspace_size,
01163 lwork,
01164 info);
01165
01166 lwork = (int)optimal_workspace_size;
01167
01168 try{
01169 singular_values = new T[geometry_matrix_axes[1]];
01170 if(store_eigenmodes)
01171 g_gtranspose_eigenmode_data = new T[geometry_matrix_axes[0]*geometry_matrix_axes[0]];
01172 else
01173 g_gtranspose_eigenmode_data = new T[geometry_matrix_axes[0]*geometry_matrix_axes[1]];
01174 gtranspose_g_eigenmode_data = new T[geometry_matrix_axes[1]*geometry_matrix_axes[1]];
01175 work = new T[(int)(optimal_workspace_size)];
01176 } catch(...) {
01177 cerr << "arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor error - "
01178 << "unable to allocate memory to perform the singular value decomposition\n";
01179 throw(string("arroyo_least_squares_reconstructor::arroyo_least_squares_reconstructor"));
01180 }
01181
01182 singular_value_decomposition<T>(jobu,
01183 jobvt,
01184 geo_mtx_axes_0,
01185 geo_mtx_axes_1,
01186 geometry_matrix_data,
01187 geo_mtx_axes_0,
01188 singular_values,
01189 g_gtranspose_eigenmode_data,
01190 geo_mtx_axes_0,
01191 gtranspose_g_eigenmode_data,
01192 geo_mtx_axes_1,
01193 work,
01194 lwork,
01195 info);
01196
01197 delete [] work;
01198 delete [] geometry_matrix_data;
01199
01200
01201
01202
01203
01204 vector<long> reconstructor_axes(geometry_matrix_axes);
01205 reconstructor_axes[1] += projected_modes.get_axes()[0];
01206 this->pixel_array<T>::set_axes(reconstructor_axes);
01207
01208
01209
01210 int limit = 0;
01211 double scaled_singular_value_threshold =
01212 sqrt(eigenvalue_threshold*singular_values[0]*singular_values[0]);
01213 while(limit<geometry_matrix_axes[1] &&
01214 singular_values[limit]>scaled_singular_value_threshold)
01215 limit++;
01216
01217 int indexa;
01218 double tmp;
01219
01220 for(int i=0; i<geometry_matrix_axes[1]; i++){
01221 for(int j=0; j<geometry_matrix_axes[0]; j++){
01222 tmp = 0;
01223 indexa = i*geometry_matrix_axes[1];
01224 for(int k=0; k<limit; k++)
01225 tmp += gtranspose_g_eigenmode_data[indexa+k]*
01226 g_gtranspose_eigenmode_data[j+k*geometry_matrix_axes[0]]/singular_values[k];
01227
01228 this->pixeldata[i*geometry_matrix_axes[0]+j]=tmp;
01229 }
01230 }
01231
01232 if(store_eigenmodes)
01233 sqrt_eigenvalues = pixel_array<T>(vector<long>(1,geometry_matrix_axes[1]), singular_values);
01234 delete [] singular_values;
01235
01236 if(store_eigenmodes)
01237 gtranspose_g_eigenmodes = pixel_array<T>(vector<long>(2,geometry_matrix_axes[1]), gtranspose_g_eigenmode_data);
01238 delete [] gtranspose_g_eigenmode_data;
01239
01240 if(store_eigenmodes)
01241 g_gtranspose_eigenmodes = pixel_array<T>(vector<long>(2,geometry_matrix_axes[0]), g_gtranspose_eigenmode_data);
01242 delete [] g_gtranspose_eigenmode_data;
01243
01244
01246
01247
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01262
01264
01265 if(projected_modes.get_order()>0){
01266
01267 int array_index = 2*nactuators*nlenslets;
01268
01269 array_index+=2*nlenslets;
01270
01271 int nunilluminated_subaps = unilluminated_subaps.size();
01272 int subap_index;
01273
01274 if(modal_projection_in_actuator_space){
01275
01276 for(int i=0; i<nunilluminated_subaps; i++)
01277 unilluminated_subaps.push_back(unilluminated_subaps[i]+nlenslets);
01278
01279
01280 subap_index = 0;
01281 for(int i=0; i<geometry_matrix_axes[0]; i++){
01282 while(i>unilluminated_subaps[subap_index] &&
01283 subap_index<nunilluminated_subaps)
01284 subap_index++;
01285 if(i!=unilluminated_subaps[subap_index]){
01286 for(int j=0; j<nactuators; j++){
01287 this->pixeldata[array_index+i] +=
01288 (2*(j%dm_axes[0])/(double)dm_axes[0] - 1)*this->pixeldata[i+j*geometry_matrix_axes[0]];
01289 this->pixeldata[array_index+2*nlenslets+i] +=
01290 (2*(j/dm_axes[0])/(double)dm_axes[0] - 1)*this->pixeldata[i+j*geometry_matrix_axes[0]];
01291 }
01292 }
01293 }
01294
01295
01296
01297
01298
01299 } else {
01300
01301 double tmp, mean_fac = 1/(double)(nlenslets - unilluminated_subaps.size());
01302
01303 if(projected_modes.get_cos_coeff(1,1)!=0){
01304
01305
01306 for(int i=0; i<geometry_matrix_axes[1]; i++){
01307 subap_index = 0;
01308 tmp = 0;
01309 for(int j=0; j<nlenslets; j++)
01310 tmp += this->pixeldata[i*geometry_matrix_axes[0]+j];
01311
01312 tmp *= mean_fac;
01313
01314 for(int j=0; j<nlenslets; j++){
01315 while(j>unilluminated_subaps[subap_index] &&
01316 subap_index<nunilluminated_subaps)
01317 subap_index++;
01318 if(j!=unilluminated_subaps[subap_index])
01319 this->pixeldata[i*geometry_matrix_axes[0]+j] -= tmp;
01320
01321 }
01322 }
01323
01324
01325 subap_index = 0;
01326 for(int j=0; j<nlenslets; j++){
01327 while(j>unilluminated_subaps[subap_index] &&
01328 subap_index<nunilluminated_subaps)
01329 subap_index++;
01330 if(j!=unilluminated_subaps[subap_index])
01331 this->pixeldata[array_index+j] = 2*mean_fac;
01332 }
01333 array_index += 2*nlenslets;
01334 }
01335
01336 if(projected_modes.get_sin_coeff(1,1)!=0){
01337
01338
01339 for(int i=0; i<geometry_matrix_axes[1]; i++){
01340 subap_index = 0;
01341 tmp = 0;
01342 for(int j=nlenslets; j<geometry_matrix_axes[0]; j++)
01343 tmp += this->pixeldata[i*geometry_matrix_axes[0]+j];
01344
01345 tmp *= mean_fac;
01346
01347 for(int j=nlenslets; j<geometry_matrix_axes[0]; j++){
01348 while(j>(unilluminated_subaps[subap_index]+nlenslets) &&
01349 subap_index<nunilluminated_subaps)
01350 subap_index++;
01351 if(j!=(unilluminated_subaps[subap_index]+nlenslets))
01352 this->pixeldata[i*geometry_matrix_axes[0]+j] -= tmp;
01353
01354 }
01355 }
01356
01357
01358 subap_index = 0;
01359 for(int j=nlenslets; j<geometry_matrix_axes[0]; j++){
01360 while(j>(unilluminated_subaps[subap_index]+nlenslets) &&
01361 subap_index<nunilluminated_subaps)
01362 subap_index++;
01363 if(j!=(unilluminated_subaps[subap_index]+nlenslets))
01364 this->pixeldata[array_index+j] = 2*mean_fac;
01365 }
01366 array_index += 2*nlenslets;
01367 }
01368 }
01369 }
01370 }
01371 }
01372
01373 #endif