Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

deformable_mirror.h

Go to the documentation of this file.
00001 /*
00002 Arroyo - software for the simulation of electromagnetic wave propagation
00003 through turbulence and optics.
00004 
00005 Copyright (c) 2000-2004 California Institute of Technology.  Written by
00006 Dr. Matthew Britton.  For comments or questions about this software,
00007 please contact the author at mbritton@astro.caltech.edu.
00008 
00009 This program is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as  published by the
00011 Free Software Foundation; either version 2 of the License, or (at your
00012 option) any later version.
00013 
00014 This program is provided "as is" and distributed in the hope that it
00015 will be useful, but WITHOUT ANY WARRANTY; without even the implied
00016 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  In no
00017 event shall California Institute of Technology be liable to any party
00018 for direct, indirect, special, incidental or consequential damages,
00019 including lost profits, arising out of the use of this software and its
00020 documentation, even if the California Institute of Technology has been
00021 advised of the possibility of such damage.   The California Institute of
00022 Technology has no obligation to provide maintenance, support, updates,
00023 enhancements or modifications.  See the GNU General Public License for
00024 more details.
00025 
00026 You should have received a copy of the GNU General Public License along
00027 with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00029 */
00030 
00031 #ifndef DEFORMABLE_MIRROR_H
00032 #define DEFORMABLE_MIRROR_H
00033 
00034 #include <iostream>
00035 #include <string>
00036 #include <iomanip>
00037 #include <complex>
00038 #include <region_base.h>
00039 #include <three_transformation.h>
00040 #include "aperture.h"
00041 #include "diffractive_wavefront.h"
00042 
00043 namespace Arroyo 
00044 {
00045   using std::string;
00046   using std::vector;
00047   using std::ostream;
00048 
00052 
00053   class deformable_mirror_base : 
00054     virtual public plane_optic, 
00055     virtual public one_to_one_optic {
00056     
00057     public:
00058 
00061     deformable_mirror_base(){};
00062 
00065     virtual ~deformable_mirror_base(){};
00066 
00068     // Pure virtual functions, need to be 
00069     // defined in derived classes.
00071 
00074     virtual void read(const char* filename) = 0;
00075 
00078     virtual void read(const iofits& iof) = 0;
00079 
00082     virtual void write(const char* filename) const = 0;
00083 
00086     virtual void write(iofits& iof) const = 0;
00087 
00090     virtual void print(ostream& os, const char* prefix="") const = 0;
00091 
00094     static deformable_mirror_base* deformable_mirror_base_factory(const char* filename);
00095 
00098     static deformable_mirror_base* deformable_mirror_base_factory(const iofits& iof);
00099   };
00100 
00143 
00144   template<class aperture_type> 
00145     class ideal_deformable_mirror : 
00146     public deformable_mirror_base,
00147     public aperture_type {
00148 
00149     private:
00150 
00151     static const bool factory_registration;
00152     string unique_name() const
00153       {
00154         return(string("ideal deformable mirror"));
00155       };
00156 
00157     protected:
00158 
00160     double mirror_actuator_pitch;
00161 
00166     double mirror_timestamp;
00167 
00169     double mirror_actuator_velocity;
00170 
00176     pixel_array<double> mirror_actuator_commands;
00177 
00180     pixel_array<double> mirror_actuator_positions;
00181       
00188     template<class T> 
00189       void private_transform(diffractive_wavefront<T>& wf) const;
00190     
00193     ideal_deformable_mirror();
00194 
00195     public:
00196 
00199     ideal_deformable_mirror(const ideal_deformable_mirror& ideal_dm);
00200 
00203     ideal_deformable_mirror(const aperture& ap, 
00204                             const vector<long> & nact,
00205                             const double pitch, 
00206                             const double vel, 
00207                             const double ts=0);
00208       
00211     ideal_deformable_mirror(const char *filename);
00212 
00215     ideal_deformable_mirror(const iofits &iof);
00216 
00219     virtual ~ideal_deformable_mirror(){};
00220 
00223     ideal_deformable_mirror& operator=(const ideal_deformable_mirror& ideal_dm);
00224 
00227     virtual void read(const char* filename);
00228 
00231     virtual void read(const iofits& iof);
00232  
00235     void write(const char* filename) const;
00236 
00239     void write(iofits& iof) const;
00240 
00243     void print(ostream& os, const char* prefix="") const;
00244 
00249     vector<long> get_axes(void) const 
00250       {
00251         return mirror_actuator_commands.get_axes();
00252       }
00253 
00258     double get_actuator_pitch(void) const 
00259       {
00260         return mirror_actuator_pitch;
00261       }
00262 
00267     void set_actuator_pitch(double act_pitch);
00268 
00273     double get_actuator_velocity(void) const
00274       {
00275         return mirror_actuator_velocity;
00276       }
00277 
00282     void set_actuator_velocity(double act_velocity);
00283 
00286     pixel_array<double> get_actuator_commands() const {
00287       return(mirror_actuator_commands);
00288     }
00289 
00296     pixel_array<double> get_actuator_positions(double timestamp) const;
00297 
00301     void update(const pixel_array<double>& pixarr, double timestamp);
00302 
00305     void transform(diffractive_wavefront<float> & wf) const;
00306 
00309     void transform(diffractive_wavefront<double> & wf) const;
00310 
00315     double get_timestamp() const {return(mirror_timestamp);};
00316 
00317   };
00318 
00319   template<class aperture_type> 
00320     ideal_deformable_mirror<aperture_type>::
00321     ideal_deformable_mirror()
00322     {
00323       mirror_actuator_pitch     = 0.;
00324       mirror_actuator_velocity  = 0.;
00325       mirror_timestamp          = 0.;
00326     }
00327 
00328   template<class aperture_type> 
00329     ideal_deformable_mirror<aperture_type>::
00330     ideal_deformable_mirror(const ideal_deformable_mirror<aperture_type> &ideal_dm)
00331     {
00332       this->operator=(ideal_dm);
00333     }
00334 
00335   template<class aperture_type> 
00336     ideal_deformable_mirror<aperture_type>::
00337     ideal_deformable_mirror(const char *filename)
00338     {
00339       this->read(filename);
00340     }
00341 
00342   template<class aperture_type> 
00343     ideal_deformable_mirror<aperture_type>::
00344     ideal_deformable_mirror(const iofits &iof)
00345     {
00346       this->read(iof);
00347     }
00348 
00349   template<class aperture_type> 
00350     ideal_deformable_mirror<aperture_type>::
00351     ideal_deformable_mirror(const aperture& ap, 
00352                             const vector<long> & actuator_dimensions,
00353                             const double actuator_pitch, 
00354                             const double actuator_velocity, 
00355                             const double actuator_timestamp)
00356     {
00357       const aperture_type* aptype;
00358       try{aptype = dynamic_cast<const aperture_type*>(&ap);}
00359       catch(...) {
00360         cerr << "ideal_deformable_mirror::ideal_deformable_mirror error -\n"
00361              << "clash between instantiated type of "
00362              << "mirror and aperture " << endl;
00363         cerr << "provided to constructor" << endl;
00364         ap.print(cerr,"ap provided to constructor");
00365         throw(this->unique_name() + string("::ideal_deformable_mirror constructor"));
00366       }
00367       this->aperture_type::operator=(*aptype);
00368 
00369 
00370       if(actuator_dimensions.size()!=2){
00371         cerr << "ideal_deformable_mirror::ideal_deformable_mirror error -\n"
00372              << " cannot instantiate deformable mirror with " 
00373              << actuator_dimensions.size() << " actuator dimensions\n";
00374         throw(string("ideal_deformable_mirror::ideal_deformable_mirror"));
00375       }
00376       if(actuator_dimensions[0]<=0 || actuator_dimensions[1]<=0){
00377         cerr << "ideal_deformable_mirror::ideal_deformable_mirror error -\n"
00378              << " cannot instantiate deformable mirror with actuator dimensions "
00379              << actuator_dimensions[0] << "x" << actuator_dimensions[1] << endl;
00380         throw(string("ideal_deformable_mirror::ideal_deformable_mirror"));
00381       }
00382 
00383       mirror_actuator_pitch     = actuator_pitch;
00384       mirror_actuator_velocity  = actuator_velocity;
00385       mirror_timestamp          = actuator_timestamp;
00386 
00387       mirror_actuator_positions = pixel_array<double>(actuator_dimensions);
00388       mirror_actuator_commands = pixel_array<double>(actuator_dimensions);
00389     }
00390   
00391   template<class aperture_type> 
00392     ideal_deformable_mirror<aperture_type> & 
00393     ideal_deformable_mirror<aperture_type>::
00394     operator=(const ideal_deformable_mirror<aperture_type>& ideal_dm)
00395     {
00396       if(this == &ideal_dm) return(*this);
00397       this->aperture_type::operator=(*this);
00398       mirror_actuator_pitch     = ideal_dm.mirror_actuator_pitch;
00399       mirror_actuator_velocity  = ideal_dm.mirror_actuator_velocity;
00400       mirror_timestamp          = ideal_dm.mirror_timestamp;
00401       mirror_actuator_positions = ideal_dm.mirror_actuator_positions;
00402       mirror_actuator_commands  = ideal_dm.mirror_actuator_commands;
00403       return(*this);
00404     }
00405 
00406   template<class aperture_type> 
00407     void ideal_deformable_mirror<aperture_type>::
00408     read(const char* filename)
00409     { 
00410       iofits iof;
00411       try
00412         {
00413           iof.open(filename);
00414         }
00415       catch(...)
00416         {
00417           cerr << this->unique_name() << "::read - error opening file " 
00418                << filename << endl;
00419           throw(this->unique_name() + string("::read"));
00420         }
00421     
00422       try
00423         {
00424           this->read(iof);
00425         }
00426       catch(...)
00427         {
00428           cerr << this->unique_name() << "::read - error reading " 
00429                << this->unique_name() << " from file " << filename << endl;
00430           throw(this->unique_name() + string("::read"));
00431         }
00432     }
00433 
00434   template<class aperture_type>
00435     void ideal_deformable_mirror<aperture_type>::
00436     read(const iofits& iof)
00437     { 
00438       string type, comment;
00439       if (!iof.key_exists("TYPE"))
00440         {
00441           cerr << this->unique_name() << "::read error - unrecognized "
00442                << "file type" << endl;
00443           throw(this->unique_name() + string("::read"));
00444         }
00445       iof.read_key("TYPE",type,comment);
00446       if (type != "ideal_deformable_mirror")
00447         {
00448           cerr << this->unique_name() << "::read error - file of type: " 
00449                << type << " rather than type " << this->unique_name() << endl;
00450           throw(this->unique_name() + string("::read"));
00451         }
00452     
00453       iof.read_key("ACTPITCH",mirror_actuator_pitch,comment);
00454       iof.read_key("ACT_VEL",mirror_actuator_velocity,comment);
00455       iof.read_key("TIMESTMP",mirror_timestamp,comment);
00456     
00457       mirror_actuator_positions.read(iof);
00458 
00459       // Here we advance to the next HDU, where the mirror actuator 
00460       // commands are stored.
00461       mirror_actuator_commands.read(iof);
00462 
00463       // Here we advance to the next HDU, where the aperture is stored.
00464       // This is stored here to avoid fits header key nameclashes with
00465       // the pixel_array that holds the last actuator positions
00466       this->aperture_type::read(iof);
00467     
00468       // leave iof pointing to the next header, if it exists
00469       if(iof.get_hdu_num()!=iof.get_num_hdus()) iof.movrel_hdu(1);
00470     }
00471   
00472   template<class aperture_type>
00473     void ideal_deformable_mirror<aperture_type>::
00474     write(const char* filename) const 
00475     {
00476       iofits iof;
00477       try
00478         {
00479           iof.create(filename);
00480         }
00481       catch(...)
00482         {
00483           cerr << this->unique_name() << "::write - error creating file " 
00484                << filename << endl;
00485           throw(this->unique_name() + string("::write"));
00486         }
00487     
00488       try
00489         {
00490           this->write(iof);
00491         }
00492       catch(...)
00493         {
00494           cerr << this->unique_name() << "::write - error writing " 
00495                << this->unique_name() << " to file " << filename << endl;
00496           throw(this->unique_name() + string("::write"));
00497         }
00498     }
00499 
00500   template<class aperture_type>
00501     void ideal_deformable_mirror<aperture_type>::
00502     write(iofits & iof) const 
00503     {
00504       string type, comment;
00505       vector<long> axes = mirror_actuator_positions.get_axes();
00506     
00507       fits_header_data<double> tmphdr(axes);
00508       tmphdr.write(iof);
00509     
00510       type    = "ideal_deformable_mirror";
00511       comment = "object type";
00512       iof.write_key("TYPE", type, comment);
00513       comment = "actuator pitch (meters)";
00514       iof.write_key("ACTPITCH",mirror_actuator_pitch,comment);
00515       comment = "actuator velocity (meters/secs)";
00516       iof.write_key("ACT_VEL",mirror_actuator_velocity,comment);
00517       comment = "timestamp (secs)";
00518       iof.write_key("TIMESTMP",mirror_timestamp,comment);
00519     
00520       mirror_actuator_positions.write(iof);
00521         
00522       // Write the mirror actuator commands to the next HDU
00523       tmphdr.write(iof);
00524       mirror_actuator_commands.write(iof);
00525     
00526       // Write the aperture to the next HDU
00527       this->aperture_type::write(iof);
00528  
00529     }
00530   
00531   template<class aperture_type>
00532     void ideal_deformable_mirror<aperture_type>::
00533     print(ostream & os, const char * prefix) const 
00534     {
00535       int vlspc = 30;
00536       vector<long> axes = mirror_actuator_positions.get_axes();
00537 
00538       os.setf(std::ios::left, std::ios::adjustfield); 
00539       os << prefix << "TYPE       = " << setw(vlspc) 
00540          << this->unique_name() << "/" << "object type" << endl;
00541       fits_header_data<double> tmphdr(axes);
00542       tmphdr.print(os, prefix);
00543       os << prefix << "ACTPITCH   = " << setw(vlspc) << mirror_actuator_pitch
00544          << "   actuator pitch (meters)" << endl;
00545       os << prefix << "ACT_VEL    = " << setw(vlspc) << mirror_actuator_velocity
00546          << "   actuator velocity (meters/secs)" << endl;
00547       os << prefix << "TIMESTMP   = " << setw(vlspc)
00548          << mirror_timestamp
00549          << "   actuators time_stamp (secs)" << endl;
00550       this->aperture_type::print(os, prefix);
00551     }
00552 
00553   template<class aperture_type>
00554     void ideal_deformable_mirror<aperture_type>::
00555     set_actuator_pitch(double actuator_pitch)
00556     {
00557       if(actuator_pitch<0){
00558         cerr << "ideal_deformable_mirror::set_actuator_pitch error - "
00559              << " cannot set actuator pitch to value " << actuator_pitch << endl;
00560         throw(string("ideal_deformable_mirror::set_actuator_pitch"));
00561       }
00562       mirror_actuator_pitch = actuator_pitch;
00563     }
00564 
00565   template<class aperture_type>
00566     void ideal_deformable_mirror<aperture_type>::
00567     set_actuator_velocity(double actuator_velocity)
00568     {
00569       if(actuator_velocity<0){
00570         cerr << "ideal_deformable_mirror::set_actuator_velocity error - "
00571              << " cannot set actuator velocity to value " << actuator_velocity << endl;
00572         throw(string("ideal_deformable_mirror::set_actuator_velocity"));
00573       }
00574       mirror_actuator_velocity = actuator_velocity;
00575     }
00576 
00577   template<class aperture_type> 
00578     pixel_array<double> ideal_deformable_mirror<aperture_type>::
00579     get_actuator_positions(double timestamp) const
00580     {
00581       if (timestamp < this->mirror_timestamp)
00582         {
00583           cerr << this->unique_name() << "::get_actuator_positions error - timestamp: " 
00584                << timestamp << " predates the internal ideal_deformable_mirror timestamp "
00585                << mirror_timestamp << endl;
00586           throw(this->unique_name() + string("::get_actuator_positions"));
00587         }
00588 
00589       vector<long> axes = mirror_actuator_positions.get_axes();
00590       pixel_array<double> new_actuator_positions(axes);
00591 
00592       double displacement_magnitude = mirror_actuator_velocity*(timestamp-mirror_timestamp);
00593       double last_actuator_position, actuator_command_position, new_actuator_position;
00594       int nelem = mirror_actuator_positions.total_space();
00595       for (int i=0; i<nelem; i++)
00596         {
00597           last_actuator_position = mirror_actuator_positions.data(i);
00598           actuator_command_position = mirror_actuator_commands.data(i);
00599           if(last_actuator_position<actuator_command_position)
00600             new_actuator_position = 
00601               last_actuator_position+displacement_magnitude<actuator_command_position ?
00602               last_actuator_position+displacement_magnitude : actuator_command_position;
00603           else 
00604             new_actuator_position = 
00605               last_actuator_position-displacement_magnitude>actuator_command_position ?
00606               last_actuator_position-displacement_magnitude : actuator_command_position;
00607           
00608           new_actuator_positions.set_data(i,new_actuator_position);
00609         }
00610       return(new_actuator_positions);
00611     }
00612 
00613   template<class aperture_type> 
00614     void ideal_deformable_mirror<aperture_type>::
00615     update(const pixel_array<double>& act_cmds, double timestamp)
00616     {
00617       mirror_actuator_positions = this->get_actuator_positions(timestamp);
00618       mirror_actuator_commands = act_cmds;
00619       mirror_timestamp = timestamp;
00620     }
00621 
00622   template<class aperture_type>
00623     void ideal_deformable_mirror<aperture_type>::
00624     transform(diffractive_wavefront<float> & wf) const 
00625     {
00626       try
00627         {
00628           this->private_transform(wf);
00629         }
00630       catch(...)
00631         {
00632           cerr << this->unique_name() << "::transform error - "
00633                << "error transforming a float instantiation " << endl;
00634           cerr << "of diffractive_wavefront" << endl;
00635           throw(this->unique_name() + string("::transform"));
00636         }
00637     }
00638 
00639   template<class aperture_type>
00640     void ideal_deformable_mirror<aperture_type>::
00641     transform(diffractive_wavefront<double> & wf) const 
00642     {
00643       try
00644         {
00645           this->private_transform(wf);
00646         }
00647       catch(...)
00648         {
00649           cerr << this->unique_name() << "::transform error - "
00650                << "error transforming a double instantiation " << endl;
00651           cerr << "of diffractive_wavefront" << endl;
00652           throw(this->unique_name() + string("::transform"));
00653         }
00654     }
00655 
00656 
00657   template<class aperture_type>
00658     template<class T> void 
00659     ideal_deformable_mirror<aperture_type>::
00660     private_transform(diffractive_wavefront<T> & wf) const {
00661     three_vector origin_offset, dx, dy;
00662 
00663     // For the time being assume that the wavefront is normally
00664     // incident to the deformable_mirror.  The next code snipet tries to
00665     // insure this case for now.
00666     if (cross_product(this->z(),wf.z()).length() > 
00667         three_frame::precision && foreshortening) {
00668         cerr << this->unique_name() << "::private_transform error - "
00669              << "The wavefront is not normally " << endl;
00670         cerr << "incident onto the deformable_mirror.  Aborting..." << endl;
00671         wf.z().print(cerr, "wf z ");
00672         this->z().print(cerr, "tt z ");
00673         throw(this->unique_name()+string("::private_transform"));
00674     }
00675 
00676     if (dot_product(wf.z(),this->z()) >= 0.) {
00677         cerr << this->unique_name() << "::private_transform error - "
00678              << "The wavefront provided to this function is " << endl;
00679         cerr << "travelling in the wrong direction, i.e., is "
00680              << "not incident on the reflective side of "
00681              << "the mirror." << endl;
00682         wf.z().print(cerr, "wf z ");
00683         this->z().print(cerr, "tt z ");
00684         throw(this->unique_name()+string("::private_transform"));
00685       }
00686 
00687     if (wf.get_timestamp() < mirror_timestamp) {
00688         cerr << this->unique_name() << "::private_transform error - "
00689              << "deformable_mirror last timestamp postdates wavefront " << endl;
00690         cerr << "timestamp: " << wf.get_timestamp() << " provided "
00691              << "to this function." << endl;
00692         throw(string(this->unique_name()+"::private_transform"));
00693       }
00694 
00695     if (wf.get_pixel_scale() > mirror_actuator_pitch) {
00696         cerr << this->unique_name() << "::private_transform error - "
00697              << "actuator pitch: " << mirror_actuator_pitch
00698              << " is larger than " << endl;
00699         cerr << "the wavefront pixel scale: " << wf.get_pixel_scale()
00700              << endl;
00701         throw(this->unique_name()+string("::private_transform"));
00702       }
00703 
00704     try{get_projected_wavefront_pixel_spacing(wf, origin_offset, dx, dy);} 
00705     catch(...){
00706       cerr << this->unique_name()
00707            << "::get_projected_wavefront_pixel_spacing error - "
00708            << endl;
00709       cerr << "could not get a projected pixel scale" << endl;
00710       throw(this->unique_name()+string("::private_transform"));
00711     }
00712 
00713     // Do the transformation now:
00714 
00715     // a) First apply the aperture:
00716     //
00717     // Do the aperture transformation which it would zero out the
00718     // wavefront if it is incident outside the optic.
00719 
00720     this->aperture_type::transform(wf);
00721 
00722     // b) apply the actuators.
00723     //
00724     // Move the actuators from the store positions to the 
00725     // position corresponding to the wf.timestamp.
00726 
00727     pixel_array<double> current_actuator_positions(this->get_actuator_positions(wf.get_timestamp()));
00728 
00729     // The halfpixel information
00730     vector<long> wf_axes  = wf.get_axes();
00731     vector<long> dm_axes  = mirror_actuator_positions.get_axes();
00732 
00733     int wf_X_min     = -wf_axes[1]/2;
00734     int wf_X_max     =  wf_axes[1]/2 + wf_axes[1]%2;
00735     int wf_Y_min     = -wf_axes[0]/2;
00736     int wf_Y_max     =  wf_axes[0]/2 + wf_axes[0]%2;
00737     double wf_X_hpix = ((wf_axes[1]%2==0) ? 0.5 : 0.);
00738     double wf_Y_hpix = ((wf_axes[0]%2==0) ? 0.5 : 0.);
00739 
00740     wavefront_amp_phase_conversion(wf);
00741     T *wfdata = get_wavefront_data(wf);
00742 
00743     three_point center_pixel; 
00744     double act_X_hpix = ((dm_axes[1]%2==0) ? 0.5 : 0.);
00745     int act_X_extrapix = ((dm_axes[1]%2==0) ? 0 : 1);
00746     double act_Y_hpix = ((dm_axes[0]%2==0) ? 0.5 : 0.);
00747     int act_Y_extrapix = ((dm_axes[0]%2==0) ? 0 : 1);
00748 
00749     int iact, jact;
00750     int stride = is_interleaved_storage(wf) ? 2 : 1;
00751     int wf_amp_index = -stride;
00752     int wf_phase_index  = is_interleaved_storage(wf) ? 1-stride : wf_axes[0]*wf_axes[1]-stride;
00753     double a, b, x, y;
00754     vector<int> actuator_index(4);
00755     vector<double> actuator_weight(4);
00756     double kvector = 2*M_PI/wf.get_wavelength();
00757 
00758     for(int i=wf_X_min; i<wf_X_max; i++){
00759       for(int j=wf_Y_min; j<wf_Y_max; j++){
00760           
00761         wf_amp_index += stride;
00762         wf_phase_index += stride;
00763           
00764         // Don't bother with the phase if the amplitude is zero
00765         if(wfdata[wf_amp_index]==0) continue;
00766           
00767         center_pixel  = *this+(origin_offset + +(i+wf_X_hpix)*dx + (j+wf_Y_hpix)*dy);
00768         // Coordinates of wf pixel center in dm frame, measured
00769         // in units of the mirror actuator pitch
00770         x = center_pixel.x(*this)/mirror_actuator_pitch;
00771         y = center_pixel.y(*this)/mirror_actuator_pitch;
00772           
00773         // Condition for the wf pixel to lie beyond the
00774         // rectangular boundary defined by the limits of the
00775         // pyramidal influence functions of the dm edge
00776         // actuators.  In this case we may skip this pixel.
00777         if(fabs(x)>dm_axes[1]/2+act_X_extrapix+act_X_hpix ||
00778            fabs(y)>dm_axes[0]/2+act_Y_extrapix+act_Y_hpix){
00779           continue;
00780         }
00781           
00782         // Condition for the wf pixel to lie within the
00783         // rectangular boundary defined by the centers of the dm
00784         // edge actuators.  This is the case in which 4
00785         // actuators contribute to the wf phase.
00786         if(fabs(x)<dm_axes[1]/2-act_X_hpix &&
00787            fabs(y)<dm_axes[0]/2-act_Y_hpix){
00788             
00789           iact = (int)(x+dm_axes[1]/2-act_X_hpix);
00790           jact = (int)(y+dm_axes[0]/2-act_Y_hpix);
00791             
00792           a = fabs(x+dm_axes[1]/2-act_X_hpix-iact);
00793           b = fabs(y+dm_axes[0]/2-act_Y_hpix-jact);
00794             
00795           actuator_weight[0] = (1-a)*(1-b);
00796           actuator_weight[1] = a*(1-b);
00797           actuator_weight[2] = (1-a)*b;
00798           actuator_weight[3] = a*b;
00799           actuator_index[0] = jact*dm_axes[0]+iact;
00800           actuator_index[1] = actuator_index[0]+1;
00801           actuator_index[2] = (jact+1)*dm_axes[0]+iact;
00802           actuator_index[3] = actuator_index[2]+1;
00803 
00804           try{
00805             for(int k=0; k<4; k++){
00806               wfdata[wf_phase_index] -= 
00807                 2*kvector*current_actuator_positions.data(actuator_index[k])*actuator_weight[k];
00808             }
00809           } catch(...) {
00810             cerr << "ideal_deformable_mirror::private_transform error - first error\n";
00811             for(int k=0; k<4; k++)
00812               cerr << "actuator " << k
00813                    << "\tindex " << actuator_index[k]
00814                    << "\tactuator position axes " << current_actuator_positions.get_axes()[0]
00815                    << "x" << current_actuator_positions.get_axes()[1]
00816                    << endl;
00817             throw(string("ideal_deformable_mirror::private_transform"));
00818           }
00819         } else {
00820           // In the remaining cases, the wf pixel lies outside
00821           // the boundary defined by the centers of the dm edge
00822           // actuators, but inside the boundary defined by the
00823           // pyramidal influence functions of the dm edge
00824           // actuators.  In these cases, one or two actuators
00825           // contribute to the wf phase.
00826             
00827           // In these 4 cases, only the corner actuator contributes to the wf phase
00828           try{
00829             if(x<-dm_axes[1]/2+act_X_hpix && y<-dm_axes[0]/2+act_Y_hpix){
00830               wfdata[wf_phase_index] -= 
00831                 2*kvector*current_actuator_positions.data(0)*
00832                 (1+dm_axes[1]/2-act_X_hpix+x)*(1+dm_axes[0]/2-act_Y_hpix+y);
00833             } else if(x<-dm_axes[1]/2+act_X_hpix && y>dm_axes[0]/2-act_Y_hpix){
00834               wfdata[wf_phase_index] -= 
00835                 2*kvector*current_actuator_positions.data(dm_axes[1]*(dm_axes[0]-1))*
00836                 (1+dm_axes[1]/2-act_X_hpix+x)*(1+dm_axes[0]/2-act_Y_hpix-y);
00837             } else if(x>dm_axes[1]/2-act_X_hpix && y<-dm_axes[0]/2+act_Y_hpix){
00838               wfdata[wf_phase_index] -= 
00839                 2*kvector*current_actuator_positions.data(dm_axes[0]-1)*
00840                 (1+dm_axes[1]/2-act_X_hpix-x)*(1+dm_axes[0]/2-act_Y_hpix+y);
00841             } else if(x>dm_axes[1]/2-act_X_hpix && y>dm_axes[0]/2-act_Y_hpix){
00842               wfdata[wf_phase_index] -= 
00843                 2*kvector*current_actuator_positions.data(dm_axes[0]*dm_axes[1]-1)*
00844                 (1+dm_axes[1]/2-act_X_hpix-x)*(1+dm_axes[0]/2-act_Y_hpix-y);
00845             }
00846           
00847             // In these 4 cases, two edge actuators contribute to the wf phase
00848             else {
00849               if(x<-dm_axes[0]/2+act_X_hpix){
00850                 jact = (int)(y+dm_axes[0]/2-act_Y_hpix);
00851                 a = -dm_axes[1]/2+act_X_hpix-x;
00852                 b = fabs(y+dm_axes[0]/2-act_Y_hpix-jact);
00853                 actuator_weight[0] = (1-a)*(1-b);
00854                 actuator_weight[1] = (1-a)*b;
00855                 actuator_index[0] = jact*dm_axes[0];
00856                 actuator_index[1] = (jact+1)*dm_axes[0];
00857               } else if(x>dm_axes[1]/2-act_X_hpix){
00858                 jact = (int)(y+dm_axes[0]/2-act_Y_hpix);
00859                 a = -dm_axes[1]/2+act_X_hpix+x;
00860                 b = fabs(y+dm_axes[0]/2-act_Y_hpix-jact);
00861                 actuator_weight[0] = (1-a)*(1-b);
00862                 actuator_weight[1] = (1-a)*b;
00863                 actuator_index[0] = (jact+1)*dm_axes[0]-1;
00864                 actuator_index[1] = (jact+2)*dm_axes[0]-1;
00865               } else if(y<-dm_axes[0]/2+act_Y_hpix){
00866                 iact = (int)(x+dm_axes[1]/2-act_X_hpix);
00867                 a = fabs(x+dm_axes[1]/2-act_X_hpix-iact);
00868                 b = -dm_axes[0]/2+act_Y_hpix-y;
00869                 actuator_weight[0] = (1-a)*(1-b);
00870                 actuator_weight[1] = a*(1-b);
00871                 actuator_index[0] = iact;
00872                 actuator_index[1] = iact+1;
00873               } else if(y>dm_axes[0]/2-act_Y_hpix){
00874                 iact = (int)(x+dm_axes[1]/2-act_X_hpix);
00875                 a = fabs(x+dm_axes[1]/2-act_X_hpix-iact);
00876                 b = -dm_axes[0]/2+act_Y_hpix+y;
00877                 actuator_weight[0] = (1-a)*(1-b);
00878                 actuator_weight[1] = a*(1-b);
00879                 actuator_index[0] = (dm_axes[1]-1)*dm_axes[0]+iact;
00880                 actuator_index[1] = (dm_axes[1]-1)*dm_axes[0]+iact+1;
00881               }
00882 
00883               for(int k=0; k<2; k++)
00884                 wfdata[wf_phase_index] -= 
00885                   2*kvector*current_actuator_positions.data(actuator_index[k])*actuator_weight[k];                
00886             }
00887           } catch(...) {
00888             cerr << "ideal_deformable_mirror::private_transform error - third error\n";
00889             throw(string("ideal_deformable_mirror::private_transform"));
00890           }  
00891         }
00892       }
00893     }
00894     // Reflect the wavefront
00895     three_reflection tref(wf, this->z());
00896     tref.transform(wf);
00897   }
00898 }
00899 #endif

Generated on Thu Nov 29 17:16:29 2007 for arroyo by  doxygen 1.3.9.1