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 DIFFRACTIVE_WAVEFRONT_H
00032 #define DIFFRACTIVE_WAVEFRONT_H
00033
00034 #include <complex>
00035 #include <fstream>
00036 #include <colormap.h>
00037 #include <fft_manager.h>
00038 #include <pixel_amp_array.h>
00039 #include <pixel_phase_array.h>
00040 #include "sim_utils.h"
00041 #include "wavefront.h"
00042
00043 namespace Arroyo {
00044
00045 using std::string;
00046 using std::vector;
00047 using std::ostream;
00048 using std::cerr;
00049 using std::endl;
00050
00051
00052 template <class T> class diffractive_wavefront;
00053 template <class T> bool operator == (const diffractive_wavefront<T> &p1, const diffractive_wavefront<T> &p2);
00054 template <class T> bool operator != (const diffractive_wavefront<T> &p1, const diffractive_wavefront<T> &p2);
00055 class optic;
00056
00060
00061 template <class T>
00062 class diffractive_wavefront :
00063 virtual public wavefront,
00064 virtual public diffractive_wavefront_header<T>,
00065 protected fft_manager<T> {
00066
00067 private:
00068
00075 friend class one_to_one_optic;
00076
00083 friend class one_to_many_optic;
00084
00087 template<class U>
00088 void multiply(const pixel_amp_array<U> & pixamparr);
00089
00092 template<class U>
00093 void add(const pixel_phase_array<U> & pixpharr);
00094
00095 protected:
00096
00098 mutable T * wfdata;
00099
00108
00110 mutable bool real_imag;
00111
00113 mutable bool interleaved;
00114
00118 void real_imag_conversion() const ;
00119
00123 void amp_phase_conversion() const ;
00124
00134 void interleaved_conversion() const;
00135
00145 void non_interleaved_conversion() const;
00146
00147 private:
00148
00149 static const bool factory_registration;
00150
00155 void cyclic_permutation(long xshift, long yshift) const;
00156
00170 void near_field_propagator(double distance, bool fresnel);
00171
00196 void far_field_propagator(double distance, bool fresnel,
00197 double final_pixel_scale=-1,
00198 vector<long> final_axes = vector<long>());
00199
00205 void update_timestamp(double dist) {timestamp += dist/299792458;};
00206
00214 void forward_fft();
00215
00223 void backward_fft();
00224
00225 public:
00226
00229 diffractive_wavefront();
00230
00233 diffractive_wavefront(const diffractive_wavefront<T> & dwf);
00234
00237 diffractive_wavefront(const char * filename);
00238
00241 diffractive_wavefront(const iofits & iof);
00242
00245 diffractive_wavefront(const diffractive_wavefront_header<T> & dwfh, T * data = NULL,
00246 bool rl_img = true, bool intrlvd = true);
00247
00250 ~diffractive_wavefront();
00251
00254 diffractive_wavefront & operator=(const diffractive_wavefront<T> & dwf);
00255
00258 void resize(const vector<long> & axes);
00259
00263 void mask();
00264
00267 template<class U>
00268 void install(const pixel_amp_array<U> & pixamparr);
00269
00272 template<class U>
00273 void install(const pixel_phase_array<U> & pixpharr);
00274
00277 pixel_amp_array<T> extract_amps() const;
00278
00281 pixel_phase_array<T> extract_phases() const;
00282
00286 void wrap_phases(){
00287
00288 pixel_phase_array<T> pixpharr = this->extract_phases();
00289 pixpharr.wrap();
00290 this->install(pixpharr);
00291 };
00292
00296
00299 void read(const char * filename);
00300
00303 void read(const iofits & iof);
00304
00320 void write(const char * filename) const;
00321
00333 void write(iofits & iof) const;
00334
00348 void write_amps_to_ppm(double min, double max,
00349 bool logscale,
00350 bool colorbar,
00351 colormap * cmap,
00352 const char * filename,
00353 long min_dimen=-1) const;
00354
00368 void write_phases_to_ppm(double min, double max,
00369 bool colorbar,
00370 colormap * cmap,
00371 const char * filename,
00372 long min_dimen=-1) const;
00373
00376 void print(ostream & os, const char * prefix) const;
00377
00386 std::complex<T> data(int n) const;
00387
00396 void set_data(int n, std::complex<T> & dat);
00397
00404 void set_propagation_direction(const three_vector & prop_dir);
00405
00409 void set_wavefront_curvature(double curvature);
00410
00435 void exact_propagator(double distance, double final_pixel_scale=-1,
00436 vector<long> final_axes=vector<long>());
00437
00438
00444 void geometric_propagator(double distance);
00445
00459 void near_field_angular_propagator(double distance);
00460
00477 void near_field_fresnel_propagator(double distance);
00478
00490 void far_field_fresnel_propagator(double distance);
00491
00504 void far_field_fraunhoffer_propagator(double distance);
00505
00526 void far_field_fresnel_goertzel_reinsch_propagator(double distance,
00527 double final_pixel_scale,
00528 vector<long> final_axes);
00529
00550 void far_field_fraunhoffer_goertzel_reinsch_propagator(double distance,
00551 double final_pixel_scale,
00552 vector<long> final_axes);
00553
00560 void finite_difference_method_propagator(double distance);
00561
00568 void rotate(double angle);
00569
00572 double total_power() const;
00573
00577 template<class U>
00578 void pad_array(int npad, std::complex<U> value);
00579
00582 void clip_array(int nclip);
00583
00586 template<class U, class V>
00587 friend diffractive_wavefront<U> & operator+=(diffractive_wavefront<U> & lhs_dwf, const diffractive_wavefront<V> & rhs_dwf);
00588
00591 template<class U, class V>
00592 friend diffractive_wavefront<U> & operator-=(diffractive_wavefront<U> & lhs_dwf, const diffractive_wavefront<V> & rhs_dwf);
00593
00596 template<class U, class V>
00597 friend diffractive_wavefront<U> & operator*=(diffractive_wavefront<U> & lhs_dwf, const diffractive_wavefront<V> & rhs_dwf);
00598
00601 template<class U, class V>
00602 friend diffractive_wavefront<U> & operator/=(diffractive_wavefront<U> & lhs_dwf, const diffractive_wavefront<V> & rhs_dwf);
00603
00606 template<class U>
00607 diffractive_wavefront<T> & operator +=(std::complex<U> c);
00608
00611 template<class U>
00612 diffractive_wavefront<T> & operator -=(std::complex<U> c);
00613
00616 template<class U>
00617 diffractive_wavefront<T> & operator *=(std::complex<U> c);
00618
00621 template<class U>
00622 diffractive_wavefront<T> & operator /=(std::complex<U> c);
00623
00626 friend bool operator ==(const diffractive_wavefront<T> & dwf1, const diffractive_wavefront<T> & dwf2) {
00627 if(operator!=(static_cast<const diffractive_wavefront_header<T> >(dwf1),
00628 static_cast<const diffractive_wavefront_header<T> >(dwf2)))
00629 return(false);
00630 int nelem = dwf1.total_space();
00631 for(int i=0; i<nelem; i++)
00632 if(dwf1.wfdata[i]!=dwf2.wfdata[i]) return(false);
00633 return(true);
00634 };
00635
00636 };
00637
00638
00639 template<class T>
00640 void diffractive_wavefront<T>::resize(const vector<long> & in_axes) {
00641
00642 if(in_axes.size()!=2){
00643 cerr << "diffractive_wavefront::resize error - axes argument does not have 2 dimensions\n";
00644 throw(string("diffractive_wavefront::resize"));
00645 }
00646 int nelem = 1;
00647 for(int i=0; i<in_axes.size(); i++) {
00648 if(in_axes[i]<0){
00649 cerr << "diffractive_wavefront::resize error - cannot resize using an axis dimension " << in_axes[i]
00650 << " less than or equal to zero\n";
00651 throw(string("diffractive_wavefront::resize"));
00652 }
00653 nelem *= in_axes[i];
00654 }
00655
00656 if(nelem != this->diffractive_wavefront_header<T>::total_space()){
00657 if(wavefront::verbose_level>1){
00658 cerr << "diffractive_wavefront::resize - resizing diffractive_wavefront from "
00659 << this->axes[0] << "x" << this->axes[1] << " to "
00660 << in_axes[0] << "x" << in_axes[1]
00661 << " for a total of " << nelem << " elements\n";
00662 }
00663
00664 if(wfdata!=NULL) delete [] wfdata;
00665 try{wfdata = new T[2*nelem];}
00666 catch(...) {
00667 cerr << "diffractive_wavefront::resize - unable to allocate memory\n";
00668 throw(string("diffractive_wavefront::resize"));
00669 }
00670 }
00671
00672 int tmp = 2*nelem;
00673 for(int i=0; i<tmp; i++)
00674 wfdata[i] = 0;
00675
00676 this->axes = in_axes;
00677 }
00678
00679 template<class T>
00680 void diffractive_wavefront<T>::cyclic_permutation(long xshift, long yshift) const {
00681 this->interleaved_conversion();
00682 Arroyo::complex_cyclic_permutation(this->axes, xshift, yshift, wfdata);
00683 }
00684
00685 template<class T>
00686 void diffractive_wavefront<T>::real_imag_conversion() const {
00687
00688 if(real_imag) return;
00689
00690 int nelem = this->diffractive_wavefront_header<T>::total_space();
00691 int index;
00692 T tmpamp, tmpphase;
00693 if(interleaved){
00694 for(int i=0; i<nelem; i++){
00695 index = 2*i;
00696 tmpamp = wfdata[index];
00697 tmpphase = wfdata[index+1];
00698 wfdata[index] = tmpamp * cos(tmpphase);
00699 wfdata[index+1] = tmpamp * sin(tmpphase);
00700 }
00701 } else {
00702 for(int i=0; i<nelem; i++){
00703 tmpamp = wfdata[i];
00704 tmpphase = wfdata[i+nelem];
00705 wfdata[i] = tmpamp * cos(tmpphase);
00706 wfdata[i+nelem] = tmpamp * sin(tmpphase);
00707 }
00708 }
00709
00710 real_imag = true;
00711 }
00712
00713 template<class T>
00714 void diffractive_wavefront<T>::amp_phase_conversion() const {
00715
00716 if(!real_imag) return;
00717
00718 int nelem = this->diffractive_wavefront_header<T>::total_space();
00719 int index;
00720 T tmpreal, tmpimag;
00721 if(interleaved){
00722 for(int i=0; i<nelem; i++){
00723 index = 2*i;
00724 tmpreal = wfdata[index];
00725 tmpimag = wfdata[index+1];
00726 wfdata[index] = sqrt(tmpreal*tmpreal + tmpimag*tmpimag);
00727 wfdata[index+1] = atan2(tmpimag,tmpreal);
00728 }
00729 } else {
00730 for(int i=0; i<nelem; i++){
00731 tmpreal = wfdata[i];
00732 tmpimag = wfdata[i+nelem];
00733 wfdata[i] = sqrt(tmpreal*tmpreal + tmpimag*tmpimag);
00734 wfdata[i+nelem] = atan2(tmpimag,tmpreal);
00735 }
00736 }
00737
00738 real_imag = false;
00739 }
00740
00741 template<class T>
00742 void diffractive_wavefront<T>::interleaved_conversion() const {
00743
00744
00745
00746
00747 if(interleaved) return;
00748
00749 int nelem = diffractive_wavefront_header<T>::total_space();
00750 T * tmp;
00751
00752 try{tmp=new T[2*nelem];}
00753 catch(...){
00754 cerr << "diffractive_wavefront::interleaved_conversion error - "
00755 << "unable to allocate memory\n";
00756 throw(string("diffractive_wavefront::interleaved_conversion"));
00757 }
00758
00759 memcpy(tmp, wfdata, sizeof(T)*nelem*2);
00760 for(int i=0; i<nelem; i++){
00761 wfdata[2*i] = tmp[i];
00762 wfdata[2*i+1] = tmp[i+nelem];
00763 }
00764
00765 interleaved = true;
00766 delete [] tmp;
00767 }
00768
00769 template<class T>
00770 void diffractive_wavefront<T>::non_interleaved_conversion() const {
00771
00772
00773
00774
00775 if(!interleaved) return;
00776
00777 int nelem = diffractive_wavefront_header<T>::total_space();
00778 T * tmp;
00779
00780 try{tmp= new T[nelem];}
00781 catch(...){
00782 cerr << "diffractive_wavefront::non_interleaved_conversion error - "
00783 << "unable to allocate memory\n";
00784 throw(string("diffractive_wavefront::non_interleaved_conversion"));
00785 }
00786
00787 for(int i=0; i<nelem; i++)
00788 tmp[i] = wfdata[2*i+1];
00789
00790 for(int i=0; i<nelem; i++)
00791 wfdata[i] = wfdata[2*i];
00792
00793 for(int i=0; i<nelem; i++)
00794 wfdata[i+nelem] = tmp[i];
00795
00796 interleaved = false;
00797 delete [] tmp;
00798 }
00799
00800 template<class T>
00801 diffractive_wavefront<T>::diffractive_wavefront(){
00802 wfdata = NULL;
00803 real_imag = true;
00804 interleaved = true;
00805 }
00806
00807 template<class T>
00808 diffractive_wavefront<T>::diffractive_wavefront(const diffractive_wavefront<T> & dwf){
00809 wfdata = NULL;
00810 this->operator=(dwf);
00811 }
00812
00813 template<class T>
00814 diffractive_wavefront<T>::diffractive_wavefront(const char * filename){
00815 wfdata = NULL;
00816 interleaved = false;
00817 this->read(filename);
00818 }
00819
00820 template<class T>
00821 diffractive_wavefront<T>::diffractive_wavefront(const iofits & iof){
00822
00823 wfdata = NULL;
00824 interleaved = false;
00825 this->read(iof);
00826 }
00827
00828 template<class T>
00829 diffractive_wavefront<T>::diffractive_wavefront(const diffractive_wavefront_header<T> & dwfh,
00830 T * data, bool rl_img, bool intrlvd) {
00831
00832 real_imag = rl_img;
00833 interleaved = intrlvd;
00834
00835 wfdata = NULL;
00836 vector<long> tmp = dwfh.get_axes();
00837 this->resize(dwfh.get_axes());
00838 if(data!=NULL){
00839 int nelem = 2*dwfh.get_axes()[0]*dwfh.get_axes()[1];
00840 for(int i=0; i<nelem; i++) wfdata[i] = data[i];
00841 }
00842 this->diffractive_wavefront_header<T>::operator=(dwfh);
00843 }
00844
00845 template<class T>
00846 diffractive_wavefront<T>::~diffractive_wavefront(){
00847 delete [] wfdata;
00848 }
00849
00850 template<class T>
00851 diffractive_wavefront<T> & diffractive_wavefront<T>::operator=(const diffractive_wavefront<T> & dwf){
00852
00853 if(this==&dwf)
00854 return(*this);
00855
00856 real_imag = dwf.real_imag;
00857 interleaved = dwf.interleaved;
00858 if(this->diffractive_wavefront_header<T>::total_space()!=dwf.diffractive_wavefront_header<T>::total_space())
00859 this->resize(dwf.get_axes());
00860
00861 int nelem = dwf.diffractive_wavefront_header<T>::total_space();
00862 for(int i=0; i<2*nelem; i++)
00863 wfdata[i] = dwf.wfdata[i];
00864
00865 this->diffractive_wavefront_header<T>::operator=(dwf);
00866 this->fft_manager<T>::operator=(dwf);
00867 return(*this);
00868 }
00869
00870 template<class T>
00871 void diffractive_wavefront<T>::mask(){
00872
00873 int nelem = diffractive_wavefront_header<T>::total_space();
00874 if(interleaved){
00875 for(int i=0; i<nelem; i++)
00876 if(wfdata[2*i]==0) wfdata[2*i+1] = 0;
00877 } else {
00878 for(int i=0; i<nelem; i++)
00879 if(wfdata[i]==0) wfdata[i+nelem] = 0;
00880 }
00881 }
00882
00883 template<class T>
00884 template<class U>
00885 void diffractive_wavefront<T>::install(const pixel_amp_array<U> & pixamparr){
00886
00887 int nelem = diffractive_wavefront_header<T>::total_space();
00888 if(diffractive_wavefront_header<T>::axes!=pixamparr.get_axes()){
00889 cerr << "diffractive_wavefront::install error - "
00890 << "mismatched axes\n";
00891 cerr << "diffractive wavefront axes " << this->axes[0] << ", " << this->axes[1] << endl;
00892 cerr << "pixel amp array axes " << pixamparr.get_axes()[0] << ", " << pixamparr.get_axes()[1] << endl;
00893 throw(string("diffractive_wavefront::install"));
00894 }
00895
00896 this->amp_phase_conversion();
00897
00898 if(interleaved){
00899 for(int i=0; i<nelem; i++)
00900 wfdata[2*i] = pixamparr.data(i);
00901 } else {
00902 for(int i=0; i<nelem; i++)
00903 wfdata[i] = pixamparr.data(i);
00904 }
00905 }
00906
00907 template<class T>
00908 template<class U>
00909 void diffractive_wavefront<T>::install(const pixel_phase_array<U> & pixpharr){
00910
00911 int nelem = diffractive_wavefront_header<T>::total_space();
00912 if(diffractive_wavefront_header<T>::axes!=pixpharr.get_axes()){
00913 cerr << "diffractive_wavefront::install error - "
00914 << "mismatched axes\n";
00915 cerr << "diffractive wavefront axes " << this->axes[0] << ", " << this->axes[1] << endl;
00916 cerr << "pixel phase array axes " << pixpharr.get_axes()[0] << ", " << pixpharr.get_axes()[1] << endl;
00917 throw(string("diffractive_wavefront::install"));
00918 }
00919
00920 this->amp_phase_conversion();
00921
00922 if(interleaved){
00923 for(int i=0; i<nelem; i++) {
00924 if(wfdata[2*i]==0) wfdata[2*i+1]=0;
00925 else wfdata[2*i+1] = pixpharr.data(i);
00926 }
00927 } else {
00928 for(int i=0; i<nelem; i++){
00929 if(wfdata[i]==0) wfdata[i+nelem]=0;
00930 else wfdata[i+nelem] = pixpharr.data(i);
00931 }
00932 }
00933 }
00934
00935 template<class T>
00936 pixel_amp_array<T> diffractive_wavefront<T>::extract_amps() const {
00937
00938 int nelem = this->diffractive_wavefront_header<T>::total_space();
00939 T * amps;
00940 try{amps = new T[nelem];}
00941 catch(...){
00942 cerr << "diffractive_wavefront::extract_amps error - "
00943 << "unable to allocate memory\n";
00944 throw(string("diffractive_wavefront::extract_amps"));
00945 }
00946 this->amp_phase_conversion();
00947
00948 if(interleaved){
00949 for(int i=0; i<nelem; i++)
00950 amps[i] = wfdata[2*i];
00951 } else {
00952 for(int i=0; i<nelem; i++)
00953 amps[i] = wfdata[i];
00954 }
00955
00956 pixel_amp_array<T> pixamparr(this->diffractive_wavefront_header<T>::axes, amps);
00957 delete [] amps;
00958 return(pixamparr);
00959 }
00960
00961 template<class T>
00962 pixel_phase_array<T> diffractive_wavefront<T>::extract_phases() const {
00963
00964 int nelem = this->diffractive_wavefront_header<T>::total_space();
00965 T * phases;
00966 try{phases = new T[nelem];}
00967 catch(...){
00968 cerr << "diffractive_wavefront::extract_phases error - "
00969 << "unable to allocate memory\n";
00970 throw(string("diffractive_wavefront::extract_phases"));
00971 }
00972
00973 this->amp_phase_conversion();
00974
00975 if(interleaved){
00976 for(int i=0; i<nelem; i++)
00977 phases[i] = wfdata[2*i+1];
00978 } else {
00979 for(int i=0; i<nelem; i++)
00980 phases[i] = wfdata[i+nelem];
00981 }
00982
00983 pixel_phase_array<T> pixpharr(this->diffractive_wavefront_header<T>::axes, phases);
00984 delete [] phases;
00985 return(pixpharr);
00986 }
00987
00988 template<class T>
00989 template<class U>
00990 void diffractive_wavefront<T>::multiply(const pixel_amp_array<U> & pixamparr) {
00991
00992 int nelem = diffractive_wavefront_header<T>::total_space();
00993 if(diffractive_wavefront_header<T>::axes!=pixamparr.get_axes()){
00994 cerr << "diffractive_wavefront::multiply error - "
00995 << "mismatched axes\n";
00996 throw(string("diffractive_wavefront::multiply"));
00997 }
00998
00999 this->amp_phase_conversion();
01000
01001 if(interleaved){
01002 for(int i=0; i<nelem; i++)
01003 wfdata[2*i] *= pixamparr.data(i);
01004 } else {
01005 for(int i=0; i<nelem; i++)
01006 wfdata[i] *= pixamparr.data(i);
01007 }
01008 }
01009
01010 template<class T>
01011 template<class U>
01012 void diffractive_wavefront<T>::add(const pixel_phase_array<U> & pixpharr) {
01013
01014 int nelem = diffractive_wavefront_header<T>::total_space();
01015 if(diffractive_wavefront_header<T>::axes!=pixpharr.get_axes()){
01016 cerr << "diffractive_wavefront::add error - "
01017 << "mismatched axes\n";
01018 throw(string("diffractive_wavefront::add"));
01019 }
01020
01021 this->amp_phase_conversion();
01022
01023 if(interleaved){
01024 for(int i=0; i<nelem; i++) {
01025 if(wfdata[2*i]==0) wfdata[2*i+1]=0;
01026 else wfdata[2*i+1] += pixpharr.data(i);
01027 }
01028 } else {
01029 for(int i=0; i<nelem; i++){
01030 if(wfdata[i]==0) wfdata[i+nelem]=0;
01031 else wfdata[i+nelem] += pixpharr.data(i);
01032 }
01033 }
01034 }
01035
01036 template<class T>
01037 void diffractive_wavefront<T>::read(const char * filename) {
01038 iofits iof;
01039 try{iof.open(filename);}
01040 catch(...){
01041 cerr << "diffractive_wavefront::read - "
01042 << "error opening file " << filename << endl;
01043 throw(string("diffractive_wavefront::read"));
01044 }
01045 try{this->read(iof);}
01046 catch(...){
01047 cerr << "diffractive_wavefront::read - "
01048 << "error reading diffractive wavefront from file "
01049 << filename << endl;
01050 throw(string("diffractive_wavefront::read"));
01051 }
01052 }
01053
01054 template<class T>
01055 void diffractive_wavefront<T>::read(const iofits & iof) {
01056
01057
01058
01059
01060 diffractive_wavefront_header<T> wfhdr(iof);
01061 this->resize(wfhdr.get_axes());
01062 this->operator=(wfhdr);
01063
01064 if(wavefront::verbose_level>1)
01065 cout << "diffractive_wavefront::read - reading amplitudes\n";
01066 pixel_amp_array<T> pixamparr(iof);
01067 this->install(pixamparr);
01068
01069 if(wavefront::verbose_level>1)
01070 cout << "diffractive_wavefront::read - reading phases\n";
01071 pixel_phase_array<T> pixpharr(iof);
01072 this->install(pixpharr);
01073
01074 }
01075
01076 template<class T>
01077 void diffractive_wavefront<T>::write(const char * filename) const {
01078 iofits iof;
01079 try{iof.create(filename);}
01080 catch(...){
01081 cerr << "diffractive_wavefront::write - "
01082 << "error opening file " << filename << endl;
01083 throw(string("diffractive_wavefront::write"));
01084 }
01085 try{this->write(iof);}
01086 catch(...){
01087 cerr << "diffractive_wavefront::write - "
01088 << "error writing diffractive wavefront to file "
01089 << filename << endl;
01090 iof.print_header(cerr, "error");
01091 throw(string("diffractive_wavefront::write"));
01092 }
01093 }
01094
01095 template<class T>
01096 void diffractive_wavefront<T>::write(iofits & iof) const {
01097
01098 try{this->diffractive_wavefront_header<T>::write(iof);}
01099 catch(...){
01100 cerr << "diffractive_wavefront::write error - could not write header\n";
01101 throw(string("diffractive_wavefront::write"));
01102 }
01103
01104 try{this->extract_amps().write(iof);}
01105 catch(...){
01106 cerr << "diffractive_wavefront::write error - could not write amps\n";
01107 throw(string("diffractive_wavefront::write"));
01108 }
01109
01110
01111
01112
01113 fits_header_data<T> fhd(this->get_axes());
01114 fhd.write(iof);
01115
01116 try{this->extract_phases().write(iof);}
01117 catch(...){
01118 cerr << "diffractive_wavefront::write error - could not write phases\n";
01119 throw(string("diffractive_wavefront::write"));
01120 }
01121 }
01122
01123 template<class T>
01124 void diffractive_wavefront<T>::print(ostream & os, const char * prefix) const {
01125 this->diffractive_wavefront_header<T>::print(os, prefix);
01126 }
01127
01128 template<class T>
01129 std::complex<T> diffractive_wavefront<T>::data(int n) const {
01130
01131 if(n<0 || n>=this->diffractive_wavefront_header<T>::total_space()){
01132 cerr << "diffractive_wavefront<T>::data error - index " << n
01133 << " supplied to this function is out of range 0 - "
01134 << this->diffractive_wavefront_header<T>::total_space()-1 << endl;
01135 throw(string("diffractive_wavefront<T>::data"));
01136 }
01137
01138
01139
01140
01141 std::complex<T> c;
01142 if(real_imag && interleaved) {
01143 c = std::complex<T>(wfdata[2*n], wfdata[2*n+1]);
01144 } else if(real_imag && !interleaved) {
01145 c = std::complex<T>(wfdata[n], wfdata[n+this->diffractive_wavefront_header<T>::total_space()]);
01146 } else if(!real_imag && interleaved) {
01147 double tmp = wfdata[2*n];
01148 double angle = wfdata[2*n+1];
01149 c = std::complex<T>(tmp*cos(angle), tmp*sin(angle));
01150 } else if(!real_imag && !interleaved) {
01151 double tmp = wfdata[n];
01152 double angle = wfdata[n+this->diffractive_wavefront_header<T>::total_space()];
01153 c = std::complex<T>(tmp*cos(angle), tmp*sin(angle));
01154 }
01155
01156 return(c);
01157 }
01158
01159 template<class T>
01160 void diffractive_wavefront<T>::set_data(int n, std::complex<T> & dat) {
01161
01162 if(n<0 || n>=this->diffractive_wavefront_header<T>::total_space()){
01163 cerr << "diffractive_wavefront<T>::set_data error - index " << n
01164 << " supplied to this function is out of range 0 - "
01165 << this->diffractive_wavefront_header<T>::total_space()-1 << endl;
01166 throw(string("diffractive_wavefront<T>::set_data"));
01167 }
01168
01169
01170
01171
01172 if(real_imag && interleaved) {
01173 wfdata[2*n] = dat.real();
01174 wfdata[2*n+1] = dat.imag();
01175 } else if(real_imag && !interleaved) {
01176 wfdata[n] = dat.real();
01177 wfdata[n+this->diffractive_wavefront_header<T>::total_space()] = dat.imag();
01178 } else if(!real_imag && interleaved) {
01179 wfdata[2*n] = abs(dat);
01180 wfdata[2*n+1] = arg(dat);
01181 } else if(!real_imag && !interleaved) {
01182 wfdata[n] = abs(dat);
01183 wfdata[n+this->diffractive_wavefront_header<T>::total_space()] = arg(dat);
01184 }
01185 }
01186
01187 template<class T>
01188 void diffractive_wavefront<T>::set_propagation_direction(const three_vector & prop_dir){
01189
01190 if(prop_dir.length()<three_frame::precision){
01191 cerr << "diffractive_wavefront::update error - "
01192 << "propagation direction vector provided to this function is null\n";
01193 throw(string("diffractive_wavefront::update"));
01194 }
01195
01196 three_vector normalized_prop_dir = prop_dir * (1/prop_dir.length());
01197
01198 if(cross_product(normalized_prop_dir, this->z()).length()<three_frame::precision)
01199 return;
01200
01201 this->amp_phase_conversion();
01202
01203
01204
01205 double x_halfpix=0, y_halfpix=0;
01206 int x_extrapix=1, y_extrapix=1;
01207 if(this->axes[1]%2==0){
01208 x_halfpix = .5;
01209 x_extrapix = 0;
01210 }
01211 if(this->axes[0]%2==0){
01212 y_halfpix = .5;
01213 y_extrapix = 0;
01214 }
01215
01216
01217 double xslope = 2*M_PI*this->get_pixel_scale()/this->get_wavelength()*
01218 dot_product(normalized_prop_dir, this->x());
01219 double yslope = 2*M_PI*this->get_pixel_scale()/this->get_wavelength()*
01220 dot_product(normalized_prop_dir, this->y());
01221
01222
01223
01224
01225
01226 if(interleaved) {
01227 for(int i=-this->axes[1]/2; i<this->axes[1]/2+x_extrapix; i++)
01228 for(int j=-this->axes[0]/2; j<this->axes[0]/2+y_extrapix; j++)
01229 if(wfdata[2*((i+this->axes[1]/2)*this->axes[0]+j+this->axes[0]/2)]!=0)
01230 wfdata[2*((i+this->axes[1]/2)*this->axes[0]+j+this->axes[0]/2)+1] +=
01231 (i+x_halfpix)*xslope + (j+y_halfpix)*yslope;
01232 } else {
01233 int nelem = this->axes[0]*this->axes[1];
01234 for(int i=-this->axes[1]/2; i<this->axes[1]/2+x_extrapix; i++)
01235 for(int j=-this->axes[0]/2; j<this->axes[0]/2+y_extrapix; j++)
01236 if(wfdata[(i+this->axes[1]/2)*this->axes[0]+j+this->axes[0]/2]!=0)
01237 wfdata[(i+this->axes[1]/2)*this->axes[0]+j+this->axes[0]/2+nelem+1] +=
01238 (i+x_halfpix)*xslope + (j+y_halfpix)*yslope;
01239 }
01240
01241
01242 three_vector axis_of_rotation = cross_product(this->z(), normalized_prop_dir);
01243 double rotation_angle = asin(axis_of_rotation.length());
01244
01245 Arroyo::three_rotation trot(*this, axis_of_rotation, rotation_angle);
01246 trot.transform(*this);
01247
01248 }
01249
01250 template<class T>
01251 void diffractive_wavefront<T>::set_wavefront_curvature(double curvature){
01252
01253 this->amp_phase_conversion();
01254 this->interleaved_conversion();
01255
01256
01257
01258 double x_halfpix=0, y_halfpix=0;
01259 int x_extrapix=1, y_extrapix=1;
01260 if(this->axes[1]%2==0){
01261 x_halfpix = .5;
01262 x_extrapix = 0;
01263 }
01264 if(this->axes[0]%2==0){
01265 y_halfpix = .5;
01266 y_extrapix = 0;
01267 }
01268
01269
01270
01271 double curvature_term =
01272 (this->get_curvature() - curvature)*M_PI*this->get_pixel_scale()*this->get_pixel_scale()/this->wavelength;
01273
01274 int index;
01275 double twopi = 2*M_PI;
01276
01277 for(int i=-this->axes[1]/2; i<this->axes[1]/2+x_extrapix; i++){
01278 for(int j=-this->axes[0]/2; j<this->axes[0]/2+y_extrapix; j++){
01279 index = 2*((i+this->axes[1]/2)*this->axes[0]+j+this->axes[0]/2);
01280 if(wfdata[index]!=0)
01281 wfdata[index+1] =
01282 fmod(wfdata[index+1] +
01283 curvature_term*((i+x_halfpix)*(i+x_halfpix)+(j+y_halfpix)*(j+y_halfpix)),
01284 twopi);
01285 }
01286 }
01287
01288 this->set_curvature(curvature);
01289 }
01290
01291 template<class T>
01292 void diffractive_wavefront<T>::write_amps_to_ppm(double min, double max,
01293 bool logscale,
01294 bool colorbar,
01295 colormap * cmap,
01296 const char * filename,
01297 long min_dimen) const {
01298
01299 this->extract_amps().write_to_ppm(min, max, logscale, colorbar, cmap, filename, min_dimen);
01300 }
01301
01302 template<class T>
01303 void diffractive_wavefront<T>::write_phases_to_ppm(double min, double max,
01304 bool colorbar,
01305 colormap * cmap,
01306 const char * filename,
01307 long min_dimen) const {
01308
01309 this->extract_phases().write_to_ppm(min, max, false, colorbar, cmap, filename, min_dimen);
01310 }
01311
01312 template<class T>
01313 void diffractive_wavefront<T>::geometric_propagator(double distance) {
01314 this->three_point::operator+=(distance*this->z());
01315 if(this->curvature!=0){
01316 double initial_position = 1/this->curvature;
01317 this->pixel_scale *= (initial_position+distance)/initial_position;
01318 this->curvature = 1/(initial_position+distance);
01319 }
01320 }
01321
01322 template<class T>
01323 void diffractive_wavefront<T>::exact_propagator(double distance,
01324 double final_pixel_scale,
01325 vector<long> final_axes) {
01326
01327 int nelem = this->diffractive_wavefront_header<T>::total_space();
01328 if(nelem==0){
01329 cerr << "diffractive_wavefront::exact_propagator error - "
01330 << "cannot propagate this diffractive_wavefront, as it has no data\n";
01331 throw(string("diffractive_wavefront::exact_propagator"));
01332 }
01333
01334 if(final_pixel_scale==-1){
01335 final_pixel_scale = this->pixel_scale;
01336 final_axes = this->axes;
01337 }
01338
01339 if(this->pixel_scale<0){
01340 cerr << "diffractive_wavefront::exact_propagator error - "
01341 << "requested pixel scale " << this->pixel_scale
01342 << " less than zero\n";
01343 throw(string("diffractive_wavefront::exact_propagator"));
01344 }
01345
01346 if(final_axes.size()!=2 || final_axes[0]<=0 || final_axes[1]<=0){
01347 cerr << "diffractive_wavefront::exact_propagator error - "
01348 << "requested axes invalid\n";
01349 for(int i=0; i<this->axes.size(); i++)
01350 cerr << "\taxis " << i << "\t" << final_axes[i] << endl;
01351 throw(string("diffractive_wavefront::exact_propagator"));
01352 }
01353
01354
01355
01356 int new_nelem = final_axes[0]*final_axes[1];
01357 T * newdata;
01358 try{newdata = new T[2*new_nelem];}
01359 catch(...){
01360 cerr << "diffractive_wavefront::exact_propagator error - "
01361 << "could not allocate memory\n";
01362 throw(string("diffractive_wavefront::exact_propagator"));
01363 }
01364
01365 double initial_power;
01366
01367 if(wavefront::verbose_level) initial_power = this->total_power();
01368
01369
01370
01371
01372 double old_x_halfpix=0, old_y_halfpix=0;
01373 double new_x_halfpix=0, new_y_halfpix=0;
01374 int old_x_extrapix=1, old_y_extrapix=1;
01375 int new_x_extrapix=1, new_y_extrapix=1;
01376 if(this->axes[1]%2==0){
01377 old_x_halfpix = .5;
01378 old_x_extrapix = 0;
01379 }
01380 if(this->axes[0]%2==0){
01381 old_y_halfpix = .5;
01382 old_y_extrapix = 0;
01383 }
01384
01385 if(final_axes[1]%2==0){
01386 new_x_halfpix = .5;
01387 new_x_extrapix = 0;
01388 }
01389 if(final_axes[0]%2==0){
01390 new_y_halfpix = .5;
01391 new_y_extrapix = 0;
01392 }
01393
01394 this->real_imag_conversion();
01395 this->interleaved_conversion();
01396
01397
01398
01399
01400
01401
01402
01403 double pixel_to_pixel_distance;
01404 double phase, cos_phase, sin_phase;
01405 double distance_squared = distance*distance;
01406 double real, imag;
01407 double wavenumber = 2*M_PI/this->wavelength;
01408 double fac, obliquity;
01409 double twopi = M_PI * 2;
01410 int curvature_sign = this->curvature>0 ? 1 : -1;
01411
01412 for(int i=-final_axes[1]/2; i<final_axes[1]/2+new_x_extrapix; i++){
01413 for(int j=-final_axes[0]/2; j<final_axes[0]/2+new_y_extrapix; j++){
01414
01415 real = imag = 0;
01416
01417 for(int k=-this->axes[1]/2; k<this->axes[1]/2+old_x_extrapix; k++){
01418 for(int l=-this->axes[0]/2; l<this->axes[0]/2+old_y_extrapix; l++){
01419
01420 if(wfdata[2*((k+this->axes[1]/2)*this->axes[0]+l+this->axes[0]/2)]==0 &&
01421 wfdata[2*((k+this->axes[1]/2)*this->axes[0]+l+this->axes[0]/2)+1]==0)
01422 continue;
01423
01424 pixel_to_pixel_distance =
01425 sqrt(distance_squared +
01426 ((i+new_x_halfpix)*final_pixel_scale-(k+old_x_halfpix)*this->pixel_scale)*
01427 ((i+new_x_halfpix)*final_pixel_scale-(k+old_x_halfpix)*this->pixel_scale) +
01428 ((j+new_y_halfpix)*final_pixel_scale-(l+old_y_halfpix)*this->pixel_scale)*
01429 ((j+new_y_halfpix)*final_pixel_scale-(l+old_y_halfpix)*this->pixel_scale));
01430
01431 obliquity = distance/pixel_to_pixel_distance;
01432 phase = pixel_to_pixel_distance*wavenumber - M_PI_2;
01433
01434
01435
01436
01437
01438 if(this->curvature)
01439 phase += curvature_sign*
01440 (sqrt(this->pixel_scale*this->pixel_scale*((k+old_x_halfpix)*(k+old_x_halfpix)+
01441 (l+old_y_halfpix)*(l+old_y_halfpix)) +
01442 1/(this->curvature*this->curvature)) - 1/this->curvature)/this->wavelength;
01443
01444 cos_phase = cos(phase);
01445 sin_phase = sin(phase);
01446 fac = obliquity*this->pixel_scale*this->pixel_scale/pixel_to_pixel_distance/this->wavelength;
01447
01448 real += fac *
01449 (wfdata[2*((k+this->axes[1]/2)*this->axes[0]+l+this->axes[0]/2)]*cos_phase -
01450 wfdata[2*((k+this->axes[1]/2)*this->axes[0]+l+this->axes[0]/2)+1]*sin_phase);
01451 imag += fac *
01452 (wfdata[2*((k+this->axes[1]/2)*this->axes[0]+l+this->axes[0]/2)]*sin_phase +
01453 wfdata[2*((k+this->axes[1]/2)*this->axes[0]+l+this->axes[0]/2)+1]*cos_phase);
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466 }
01467 }
01468
01469 newdata[2*((i+final_axes[1]/2)*final_axes[0]+j+final_axes[0]/2)] = real;
01470 newdata[2*((i+final_axes[1]/2)*final_axes[0]+j+final_axes[0]/2)+1] = imag;
01471
01472 }
01473 }
01474
01475 delete [] this->wfdata;
01476 this->wfdata = newdata;
01477 this->axes = final_axes;
01478
01479 if(wavefront::verbose_level) {
01480 double final_power = this->total_power();
01481 cout << "initial power " << initial_power << " final power " << final_power
01482 << " ratio " << final_power / initial_power << endl;
01483 }
01484
01485 this->pixel_scale = final_pixel_scale;
01486 this->curvature = 0;
01487
01488 three_translation tt(distance*this->three_frame::z());
01489 tt.transform(*this);
01490 update_timestamp(distance);
01491 }
01492
01493 template<class T>
01494 void diffractive_wavefront<T>::forward_fft() {
01495 vector<long> flipped_axes(2, this->axes[0]);
01496 flipped_axes[0] = this->axes[1];
01497
01498 this->real_imag_conversion();
01499 this->interleaved_conversion();
01500 this->fft_manager<T>::forward_fft(flipped_axes, false, true, wfdata);
01501 }
01502
01503 template<class T>
01504 void diffractive_wavefront<T>::backward_fft(){
01505 vector<long> flipped_axes(2, this->axes[0]);
01506 flipped_axes[0] = this->axes[1];
01507
01508 this->real_imag_conversion();
01509 this->interleaved_conversion();
01510 this->fft_manager<T>::backward_fft(flipped_axes, false, true, wfdata);
01511 }
01512
01513 namespace {
01514
01515
01516
01517
01518
01519 template<class T>
01520 void apply_transfer_function(double axial_phase, vector<long> axes,
01521 vector<double> phase_coefficient, bool fresnel, T * wfdata){
01522
01523 double twopi = 2*M_PI;
01524 double x_halfpix=0, y_halfpix=0;
01525 int x_extrapix=1, y_extrapix=1;
01526 if(axes[1]%2==0){
01527 x_halfpix = .5;
01528 x_extrapix = 0;
01529 }
01530 if(axes[0]%2==0){
01531 y_halfpix = .5;
01532 y_extrapix = 0;
01533 }
01534
01535 int index;
01536 double tmp_val, xfer_fn_phase;
01537 Arroyo::complex_cyclic_permutation(axes, axes[0]/2, axes[1]/2, wfdata);
01538 for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01539 for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01540 index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01541 tmp_val = phase_coefficient[1]*(i+x_halfpix)*(i+x_halfpix) +
01542 phase_coefficient[0]*(j+y_halfpix)*(j+y_halfpix);
01543
01544 if(tmp_val>1){
01545 wfdata[2*i*axes[0]] = 0;
01546 wfdata[2*(axes[1]-i)*axes[0]] = 0;
01547 } else {
01548 if(fresnel) xfer_fn_phase = fmod((axial_phase*(1 - .5*tmp_val)),twopi);
01549 else xfer_fn_phase = fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01550 wfdata[2*index+1] += xfer_fn_phase;
01551 }
01552 }
01553 }
01554 Arroyo::complex_cyclic_permutation(axes, -axes[0]/2, -axes[1]/2, wfdata);
01555 }
01556
01557
01558
01559
01560
01561 template<class T>
01562 void optimized_apply_transfer_function(double axial_phase, vector<long> axes,
01563 vector<double> phase_coefficient, bool fresnel, T * wfdata){
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 bool odd_zero = axes[0]%2;
01574 int lim_one = axes[1]/2+axes[1]%2;
01575 double xfer_fn_phase;
01576 double tmp_val;
01577 double twopi = 2*M_PI;
01578
01579 for(int i=1; i<lim_one; i++){
01580
01581 tmp_val = phase_coefficient[1]*i*i;
01582 if(tmp_val>1){
01583 wfdata[2*i*axes[0]] = 0;
01584 wfdata[2*(axes[1]-i)*axes[0]] = 0;
01585 } else {
01586 if(fresnel) xfer_fn_phase = fmod((axial_phase*(1 - .5*tmp_val)), twopi);
01587 else xfer_fn_phase = fmod((axial_phase*sqrt(1 - tmp_val)), twopi);
01588 wfdata[2*i*axes[0]+1] += xfer_fn_phase;
01589 wfdata[2*(axes[1]-i)*axes[0]+1] += xfer_fn_phase;
01590 }
01591
01592 if(!odd_zero){
01593 tmp_val = phase_coefficient[1]*i*i + phase_coefficient[0]*axes[0]/2*axes[0]/2;
01594 if(tmp_val>1){
01595 wfdata[2*(i*axes[0]+axes[0]/2)] = 0;
01596 wfdata[2*((axes[1]-i)*axes[0]+axes[0]/2)] = 0;
01597 } else {
01598 if(fresnel) xfer_fn_phase = fmod((axial_phase*(1 - .5*tmp_val)), twopi);
01599 else xfer_fn_phase = fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01600 wfdata[2*(i*axes[0]+axes[0]/2)+1] += xfer_fn_phase;
01601 wfdata[2*((axes[1]-i)*axes[0]+axes[0]/2)+1] += xfer_fn_phase;
01602 }
01603 }
01604 }
01605
01606 bool odd_one = axes[1]%2;
01607 int lim_zero = axes[0]/2+axes[0]%2;
01608 for(int j=1; j<lim_zero; j++){
01609
01610 tmp_val = phase_coefficient[0]*j*j;
01611 if(tmp_val>1){
01612 wfdata[2*j] = 0;
01613 wfdata[2*(axes[0]-j)] = 0;
01614 } else {
01615 if(fresnel) xfer_fn_phase = fmod((axial_phase*(1 - .5*tmp_val)),twopi);
01616 else xfer_fn_phase = fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01617 wfdata[2*j+1] += xfer_fn_phase;
01618 wfdata[2*(axes[0]-j)+1] += xfer_fn_phase;
01619 }
01620
01621 if(!odd_one){
01622 tmp_val = phase_coefficient[0]*j*j + phase_coefficient[1]*axes[1]/2*axes[1]/2;
01623 if(tmp_val>1){
01624 wfdata[2*(axes[1]/2*axes[0]+j)] = 0;
01625 wfdata[2*(axes[1]/2*axes[0]+axes[0]-j)] = 0;
01626 } else {
01627 if(fresnel) xfer_fn_phase = fmod((axial_phase*(1 - .5*tmp_val)),twopi);
01628 else xfer_fn_phase = fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01629 wfdata[2*(axes[1]/2*axes[0]+j)+1] += xfer_fn_phase;
01630 wfdata[2*(axes[1]/2*axes[0]+axes[0]-j)+1] += xfer_fn_phase;
01631 }
01632 }
01633 }
01634
01635
01636
01637
01638
01639
01640 wfdata[1] += axial_phase;
01641 if(!odd_zero){
01642 tmp_val = phase_coefficient[0]*axes[0]/2*axes[0]/2;
01643 if(tmp_val>1) wfdata[axes[0]] = 0;
01644 else {
01645 if(fresnel) wfdata[axes[0]+1] += fmod((axial_phase*(1 - .5*tmp_val)),twopi);
01646 else wfdata[axes[0]+1] += fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01647 }
01648 }
01649 if(!odd_one){
01650 tmp_val = phase_coefficient[1]*axes[1]/2*axes[1]/2;
01651 if(tmp_val>1) wfdata[2*(axes[1]/2*axes[0])] = 0;
01652 else {
01653 if(fresnel) wfdata[2*(axes[1]/2*axes[0])+1] += fmod((axial_phase*(1 - .5*tmp_val)),twopi);
01654 else wfdata[2*(axes[1]/2*axes[0])+1] += fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01655 }
01656 }
01657 if(!odd_zero && !odd_one){
01658 tmp_val = phase_coefficient[0]*axes[0]/2*axes[0]/2 + phase_coefficient[1]*axes[1]/2*axes[1]/2;
01659 if(tmp_val>1) wfdata[2*(axes[1]/2*axes[0]+axes[0]/2)] = 0;
01660 else {
01661 if(fresnel) wfdata[2*(axes[1]/2*axes[0]+axes[0]/2)+1] += fmod((axial_phase*(1 - .5*tmp_val)),twopi);
01662 else wfdata[2*(axes[1]/2*axes[0]+axes[0]/2)+1] += fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01663 }
01664 }
01665
01666
01667
01668
01669 for(int i=1; i<lim_one; i++){
01670 for(int j=1; j<lim_zero; j++){
01671 tmp_val = phase_coefficient[1]*i*i + phase_coefficient[0]*j*j;
01672 if(tmp_val>1){
01673 wfdata[2*(i*axes[0]+j)] = 0;
01674 wfdata[2*((axes[1]-i)*axes[0]+j)] = 0;
01675 wfdata[2*(i*axes[0]+axes[0]-j)] = 0;
01676 wfdata[2*((axes[1]-i)*axes[0]+axes[0]-j)] = 0;
01677 } else {
01678 if(fresnel) xfer_fn_phase = fmod((axial_phase*(1 - .5*tmp_val)),twopi);
01679 else xfer_fn_phase = fmod((axial_phase*sqrt(1 - tmp_val)),twopi);
01680 wfdata[2*(i*axes[0]+j)+1] += xfer_fn_phase;
01681 wfdata[2*((axes[1]-i)*axes[0]+j)+1] += xfer_fn_phase;
01682 wfdata[2*(i*axes[0]+axes[0]-j)+1] += xfer_fn_phase;
01683 wfdata[2*((axes[1]-i)*axes[0]+axes[0]-j)+1] += xfer_fn_phase;
01684 }
01685 }
01686 }
01687 }
01688 }
01689
01690 template<class T>
01691 void diffractive_wavefront<T>::near_field_propagator(double distance, bool fresnel) {
01692
01693
01694
01695
01696
01697
01698
01699 if(wavefront::verbose_level>2){
01700 string fname = "angular_pre_backwards_fft_diffractive_wavefront.fits";
01701 if(fresnel)
01702 fname = "fresnel_pre_backwards_fft_diffractive_wavefront.fits";
01703 cout << "diffractive_wavefront::near_field_propagator - writing initial diffractive_wavefront to file "
01704 << fname << endl;
01705 this->write(fname.c_str());
01706 }
01707
01708
01709 if(diffractive_wavefront::wavefront::verbose_level)
01710 cout << "diffractive_wavefront::near_field_propagator - performing backwards fft\n";
01711
01712 this->forward_fft();
01713
01714 this->amp_phase_conversion();
01715 this->interleaved_conversion();
01716
01717
01718
01719
01720
01721
01722
01723 vector<double> phase_coefficient(2);
01724 phase_coefficient[0] = this->wavelength*this->wavelength/(this->pixel_scale*this->pixel_scale*this->axes[0]*this->axes[0]);
01725 phase_coefficient[1] = this->wavelength*this->wavelength/(this->pixel_scale*this->pixel_scale*this->axes[1]*this->axes[1]);
01726
01727
01728 double axial_phase = 2*M_PI*distance/this->wavelength;
01729 double effective_distance = distance/(this->curvature*distance+1);
01730
01731 if(this->curvature)
01732 axial_phase = 2*M_PI*effective_distance/this->wavelength;
01733
01734 int nelem = this->axes[0]*this->axes[1];
01735
01736
01737 optimized_apply_transfer_function(axial_phase, this->axes, phase_coefficient, fresnel, wfdata);
01738
01739
01740 this->backward_fft();
01741
01742 if(wavefront::verbose_level>2){
01743 string fname = "angular_forwards_fft_xfer_diffractive_wavefront.fits";
01744 if(fresnel) fname = "fresnel_post_backwards_fft_diffractive_wavefront.fits";
01745 cout << "diffractive_wavefront::near_field_propagator - "
01746 << "writing back-transformed diffractive_wavefront with transfer function applied to file "
01747 << fname << endl;
01748 this->write(fname.c_str());
01749 }
01750
01751
01752
01753 double inv = 1/(1+distance*this->curvature)/(double)(this->axes[0]*this->axes[1]);
01754 for(int i=0; i<2*nelem; i++)
01755 wfdata[i] *= inv;
01756
01757 if(this->curvature){
01758 this->pixel_scale *= (1+distance*this->curvature);
01759 this->curvature = 1/(distance+1/this->curvature);
01760 }
01761
01762 this->three_point::operator+=(distance*this->three_frame::z());
01763 update_timestamp(distance);
01764 }
01765
01766 template<class T>
01767 void diffractive_wavefront<T>::near_field_angular_propagator(double distance) {
01768 this->near_field_propagator(distance, false);
01769 }
01770
01771 template<class T>
01772 void diffractive_wavefront<T>::near_field_fresnel_propagator(double distance) {
01773 this->near_field_propagator(distance, true);
01774 }
01775
01776
01777
01778
01779
01780
01781
01782 template<class T>
01783 void diffractive_wavefront<T>::far_field_propagator(double distance,
01784 bool fresnel,
01785 double final_pixel_scale,
01786 vector<long> final_axes) {
01787
01788
01789 bool goertzel_reinsch = false;
01790 if(final_axes.size()==2 && final_pixel_scale>0)
01791 goertzel_reinsch = true;
01792 else if((final_axes.size()!=0 && final_axes.size()!=2) ||
01793 final_pixel_scale!=-1){
01794 cout << "diffractive_wavefront::far_field_propagator error - "
01795 << "this function was invoked by implicitly requesting " << endl
01796 << "propagation using the Goertzel-Reinsch algorithm - " << endl
01797 << "but this invocation was corrupt." << endl
01798 << "Specifically, the requested final pixel scale was "
01799 << final_pixel_scale << " and the requested axes were\n";
01800 for(int i=0; i<final_axes.size(); i++)
01801 cout << final_axes[i] << endl;
01802 throw(string("diffractive_wavefront::far_field_propagator"));
01803 }
01804
01805 if(wavefront::verbose_level){
01806 if(fresnel && goertzel_reinsch)
01807 cout << "diffractive_wavefront::far_field_propagator - applying fresnel goertzel reinsch propagator\n";
01808 else if(!fresnel && goertzel_reinsch)
01809 cout << "diffractive_wavefront::far_field_propagator - applying fraunhoffer goertzel reinsch propagator\n";
01810 else if(fresnel && !goertzel_reinsch)
01811 cout << "diffractive_wavefront::far_field_propagator - applying fresnel propagator\n";
01812 else
01813 cout << "diffractive_wavefront::far_field_propagator - applying fraunhoffer propagator\n";
01814 }
01815
01816 if(!goertzel_reinsch && (this->axes[0]!=this->axes[1])){
01817 cerr << "diffractive_wavefront::far_field_propagator error - "
01818 << "cannot perform a far field propagation via fft " << endl
01819 << "on an input array with axes of different size, "
01820 << "because the software can only handle square pixels\n";
01821 cerr << "If you need to do this, try the Goertzel-Reinsch propagators\n";
01822 throw(string("diffractive_wavefront::far_field_propagator"));
01823 }
01824
01825 this->interleaved_conversion();
01826 this->amp_phase_conversion();
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848 vector<long> initial_axes(this->axes);
01849
01850 double initial_x_halfpix=0, initial_y_halfpix=0;
01851 int initial_x_extrapix=1, initial_y_extrapix=1;
01852 if(initial_axes[1]%2==0){
01853 initial_x_halfpix = .5;
01854 initial_x_extrapix = 0;
01855 }
01856 if(initial_axes[0]%2==0){
01857 initial_y_halfpix = .5;
01858 initial_y_extrapix = 0;
01859 }
01860
01861 if(final_axes.size()==0) final_axes = initial_axes;
01862
01863 double final_x_halfpix=0, final_y_halfpix=0;
01864 int final_x_extrapix=1, final_y_extrapix=1;
01865 if(final_axes[1]%2==0){
01866 final_x_halfpix = .5;
01867 final_x_extrapix = 0;
01868 }
01869 if(final_axes[0]%2==0){
01870 final_y_halfpix = .5;
01871 final_y_extrapix = 0;
01872 }
01873
01874
01875 double initial_pixel_scale = this->get_pixel_scale();
01876 double nyquist_pixel_scale = this->wavelength * distance / (double) initial_axes[0] / initial_pixel_scale;
01877 if(final_pixel_scale==-1) final_pixel_scale = nyquist_pixel_scale;
01878 double xslope = final_axes[1]%2==1 ? 0 : M_PI*final_pixel_scale/nyquist_pixel_scale/(double)initial_axes[1];
01879 double yslope = final_axes[0]%2==1 ? 0 : M_PI*final_pixel_scale/nyquist_pixel_scale/(double)initial_axes[0];
01880
01881
01882
01883
01884
01885
01886 int index;
01887 double twopi = 2*M_PI;
01888 double initial_curvature_term = M_PI*initial_pixel_scale*initial_pixel_scale*this->curvature/this->wavelength;
01889 double quadratic_coefficient = 0;
01890 if(fresnel)
01891 quadratic_coefficient = M_PI*initial_pixel_scale*initial_pixel_scale/this->wavelength/distance;
01892
01893 for(int i=-initial_axes[1]/2; i<initial_axes[1]/2+initial_x_extrapix; i++){
01894 for(int j=-initial_axes[0]/2; j<initial_axes[0]/2+initial_y_extrapix; j++){
01895 index = (i+initial_axes[1]/2)*initial_axes[0]+j+initial_axes[0]/2;
01896
01897 wfdata[2*index+1] +=
01898 fmod(((quadratic_coefficient + initial_curvature_term)*
01899 ((i+initial_x_halfpix)*(i+initial_x_halfpix)+(j+initial_y_halfpix)*(j+initial_y_halfpix))
01900 - xslope*(i+initial_x_halfpix) - yslope*(j+initial_y_halfpix)), twopi);
01901 }
01902 }
01903
01904 if(wavefront::verbose_level>2){
01905 string fname = "far_field_fraunhoffer_xfer_diffractive_wavefront.fits";
01906 if(fresnel && goertzel_reinsch) fname = "far_field_fresnel_goertzel_reinsch_xfer_diffractive_wavefront.fits";
01907 else if(!fresnel && goertzel_reinsch) fname = "far_field_fraunhoffer_goertzel_reinsch_xfer_diffractive_wavefront.fits";
01908 else if(fresnel && !goertzel_reinsch) fname = "far_field_fresnel_xfer_diffractive_wavefront.fits";
01909 cout << "diffractive_wavefront::far_field_propagator - "
01910 << "writing diffractive_wavefront with transfer function applied to file "
01911 << fname << endl;
01912 this->write(fname.c_str());
01913 }
01914
01915
01916
01917
01918
01919 double normalization_factor =
01920 fabs((double)(initial_pixel_scale*initial_pixel_scale/this->wavelength/distance));
01921
01922 if(goertzel_reinsch){
01923 long dimen = 2*final_axes[0]*final_axes[1];
01924 T * newdata;
01925 try{newdata = new T[dimen];}
01926 catch(...){
01927 cerr << "diffractive_wavefront::far_field_propagator error - "
01928 << "unable to allocate memory\n";
01929 throw(string("diffractive_wavefront::far_field_propagator"));
01930 }
01931
01932 this->real_imag_conversion();
01933
01934 double sampling_factor = -initial_pixel_scale*final_pixel_scale / this->wavelength / distance;
01935 goertzel_reinsch_transform(initial_axes, final_axes, sampling_factor, wfdata, newdata);
01936 delete [] wfdata;
01937 wfdata = newdata;
01938 this->axes = final_axes;
01939 } else {
01940 this->cyclic_permutation(initial_axes[0]/2, initial_axes[1]/2);
01941
01942 if(wavefront::verbose_level)
01943 cout << "diffractive_wavefront::far_field_propagator - performing backwards fft\n";
01944 this->forward_fft();
01945 this->cyclic_permutation(-initial_axes[0]/2, -initial_axes[1]/2);
01946 }
01947
01948 if(wavefront::verbose_level>2){
01949 string fname = "far_field_fraunhoffer_xformed_diffractive_wavefront.fits";
01950 if(fresnel && goertzel_reinsch) fname = "far_field_fresnel_goertzel_reinsch_xformed_diffractive_wavefront.fits";
01951 else if(!fresnel && goertzel_reinsch) fname = "far_field_fraunhoffer_goertzel_reinsch_xformed_diffractive_wavefront.fits";
01952 else if(fresnel && !goertzel_reinsch) fname = "far_field_fresnel_xformed_diffractive_wavefront.fits";
01953 cout << "diffractive_wavefront::far_field_propagator - "
01954 << "writing transformed diffractive_wavefront to file "
01955 << fname << endl;
01956 this->write(fname.c_str());
01957 }
01958
01959
01960
01961 nyquist_pixel_scale = this->wavelength * distance / (double) final_axes[0] / final_pixel_scale;
01962 xslope = initial_axes[1]%2==1 ? 0 : M_PI*initial_pixel_scale/nyquist_pixel_scale/(double)final_axes[1];
01963 yslope = initial_axes[0]%2==1 ? 0 : M_PI*initial_pixel_scale/nyquist_pixel_scale/(double)final_axes[0];
01964
01965
01966
01967
01968
01969 this->amp_phase_conversion();
01970 quadratic_coefficient = final_pixel_scale*final_pixel_scale*M_PI/this->wavelength/distance;
01971 double constant_phase = 2*M_PI*fmod(distance/this->wavelength,1.0) - M_PI_2;
01972 for(int i=-final_axes[1]/2; i<final_axes[1]/2+final_x_extrapix; i++){
01973 for(int j=-final_axes[0]/2; j<final_axes[0]/2+final_y_extrapix; j++){
01974 index = (i+final_axes[1]/2)*final_axes[0]+j+final_axes[0]/2;
01975 wfdata[2*index] *= normalization_factor;
01976 wfdata[2*index+1] += constant_phase - xslope*(i + final_x_halfpix) - yslope*(j + final_y_halfpix);
01977 if(fresnel)
01978 wfdata[2*index+1] =
01979 fmod(wfdata[2*index+1] + M_PI + quadratic_coefficient*
01980 ((i+final_x_halfpix)*(i+final_x_halfpix)+(j+final_y_halfpix)*(j+final_y_halfpix)), twopi) - M_PI_2;
01981 }
01982 }
01983
01984 this->pixel_scale = final_pixel_scale;
01985 this->three_point::operator+=(distance*this->three_frame::z());
01986 this->curvature = 0;
01987 update_timestamp(distance);
01988 }
01989
01990 template<class T>
01991 void diffractive_wavefront<T>::far_field_fresnel_propagator(double distance) {
01992 this->far_field_propagator(distance, true);
01993 }
01994
01995 template<class T>
01996 void diffractive_wavefront<T>::far_field_fraunhoffer_propagator(double distance) {
01997 this->far_field_propagator(distance, false);
01998 }
01999
02000 template<class T>
02001 void diffractive_wavefront<T>::far_field_fresnel_goertzel_reinsch_propagator(double distance,
02002 double final_pixel_scale,
02003 vector<long> final_axes) {
02004 this->far_field_propagator(distance, true, final_pixel_scale, final_axes);
02005 }
02006
02007 template<class T>
02008 void diffractive_wavefront<T>::far_field_fraunhoffer_goertzel_reinsch_propagator(double distance,
02009 double final_pixel_scale,
02010 vector<long> final_axes) {
02011 this->far_field_propagator(distance, false, final_pixel_scale, final_axes);
02012 }
02013
02014 template<class T>
02015 void diffractive_wavefront<T>::finite_difference_method_propagator(double distance) {
02016
02017
02018 cerr << "diffractive_wavefront::finite_difference_method_propagator error - "
02019 << "this function has not yet been coded\n";
02020 throw(string("diffractive_wavefront::finite_difference_method_propagator"));
02021
02022 }
02023
02024 template<class T>
02025 void diffractive_wavefront<T>::rotate(double angle) {
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043 cerr << "diffractive_wavefront::rotate not yet coded\n";
02044 throw(string("diffractive_wavefront::rotate"));
02045
02046 }
02047
02048 template<class T>
02049 template<class U>
02050 void diffractive_wavefront<T>::pad_array(int npad, std::complex<U> value) {
02051
02052
02053
02054
02055 if(npad==0) return;
02056 if(npad<0){
02057 cerr << "diffractive_wavefront::pad_array error - cannot pad by " << npad << " pixels\n";
02058 throw(string("diffractive_wavefront::pad_array"));
02059 }
02060
02061 vector<long> new_axes = this->axes;
02062 int old_nelem = diffractive_wavefront_header<T>::total_space();
02063 int nelem=1;
02064 for(int i=0; i<new_axes.size(); i++){
02065 new_axes[i] += 2*npad;
02066 nelem *= new_axes[i];
02067 }
02068
02069 if(wavefront::verbose_level)
02070 cout << "diffractive_wavefront::pad_array - padding by " << npad
02071 << " from " << this->axes[0] << "x" << this->axes[1]
02072 << " to " << new_axes[0] << "x" << new_axes[1] << endl;
02073
02074 this->interleaved_conversion();
02075
02076 T * olddata = wfdata;
02077 try{wfdata = new T[2*nelem];}
02078 catch(...){
02079 cerr << "diffractive_wavefront::pad_array error - "
02080 << "unable to allocate memory\n";
02081 throw(string("diffractive_wavefront::pad_array"));
02082 }
02083
02084 if(this->real_imag){
02085 U real = value.real();
02086 U imag = value.imag();
02087 for(int i=0; i<nelem; i++){
02088 wfdata[2*i] = real;
02089 wfdata[2*i+1] = imag;
02090 }
02091 } else {
02092 U amp = abs(value);
02093 U phase = arg(value);
02094 for(int i=0; i<nelem; i++){
02095 wfdata[2*i] = amp;
02096 wfdata[2*i+1] = phase;
02097 }
02098 }
02099
02100
02101 for(int i=0; i<this->axes[1]; i++)
02102 for(int j=0; j<this->axes[0]; j++){
02103 wfdata[2*((i+npad)*new_axes[0]+npad+j)] =
02104 olddata[2*(i*this->axes[0]+j)];
02105 wfdata[2*((i+npad)*new_axes[0]+npad+j)+1] =
02106 olddata[2*(i*this->axes[0]+j)+1];
02107 }
02108
02109 delete [] olddata;
02110 this->axes = new_axes;
02111 }
02112
02113 template<class T>
02114 void diffractive_wavefront<T>::clip_array(int nclip) {
02115
02116 if(nclip==0) return;
02117 if(nclip<0){
02118 cerr << "diffractive_wavefront::clip_array error - cannot clip by " << nclip << " pixels\n";
02119 throw(string("diffractive_wavefront::clip_array"));
02120 }
02121
02122 vector<long> new_axes = this->axes;
02123 int nelem = 1;
02124 for(int i=0; i<new_axes.size(); i++){
02125 new_axes[i] -= 2*nclip;
02126 if(new_axes[i]<=0){
02127 cerr << "diffractive_wavefront::clip_array error - clipping original array by "
02128 << nclip << " pixels leaves non-positive array size\n";
02129 throw(string("diffractive_wavefront::clip_array"));
02130 }
02131 nelem *= new_axes[i];
02132 }
02133
02134 if(wavefront::verbose_level)
02135 cout << "diffractive_wavefront::clip_array - clipping by " << nclip
02136 << " from " << this->axes[0] << "x" << this->axes[1]
02137 << " to " << new_axes[0] << "x" << new_axes[1] << endl;
02138
02139 T * newdata;
02140 try{newdata = new T[2*nelem];}
02141 catch(...){
02142 cerr << "diffractive_wavefront::pad_array error - "
02143 << "unable to allocate memory\n";
02144 throw(string("diffractive_wavefront::clip_array"));
02145 }
02146
02147 this->interleaved_conversion();
02148
02149
02150 for(int i=0; i<new_axes[1]; i++)
02151 for(int j=0; j<new_axes[0]; j++){
02152 newdata[2*(i*new_axes[0]+j)] =
02153 wfdata[2*((i+nclip)*this->axes[0]+nclip+j)];
02154 newdata[2*(i*new_axes[0]+j)+1] =
02155 wfdata[2*((i+nclip)*this->axes[0]+nclip+j)+1];
02156 }
02157
02158
02159 delete [] wfdata;
02160 wfdata = newdata;
02161
02162 this->axes = new_axes;
02163 }
02164
02165 template<class T>
02166 double diffractive_wavefront<T>::total_power() const {
02167
02168 double total_power = 0;
02169 int nelem = diffractive_wavefront_header<T>::total_space();
02170 if(real_imag){
02171 for(int i=0; i<2*nelem; i++)
02172 total_power += wfdata[i]*wfdata[i];
02173 } else {
02174 if(interleaved)
02175 for(int i=0; i<nelem; i++)
02176 total_power += wfdata[2*i]*wfdata[2*i];
02177 else
02178 for(int i=0; i<nelem; i++)
02179 total_power += wfdata[i]*wfdata[i];
02180 }
02181 return(total_power);
02182 }
02183
02184 template<class T, class U>
02185 diffractive_wavefront<T> & operator+=(diffractive_wavefront<T> & lhs_wf, const diffractive_wavefront<U> & rhs_wf) {
02186
02187 if(lhs_wf.get_axes()!=rhs_wf.get_axes()){
02188 cerr << "operator+= error - mismatched arrays in diffractive_wavefronts\n";
02189 throw(string("diffractive_wavefront::operator+="));
02190 }
02191
02192 lhs_wf.real_imag_conversion();
02193 rhs_wf.real_imag_conversion();
02194 if(lhs_wf.interleaved && !rhs_wf.interleaved) rhs_wf.interleaved_conversion();
02195 if(!lhs_wf.interleaved && rhs_wf.interleaved) rhs_wf.non_interleaved_conversion();
02196
02197 int nelem = lhs_wf.diffractive_wavefront_header<T>::total_space();
02198 for(int i=0; i<2*nelem; i++)
02199 lhs_wf.wfdata[i] += rhs_wf.wfdata[i];
02200
02201 return(lhs_wf);
02202 }
02203
02204 template<class T, class U>
02205 diffractive_wavefront<T> & operator-=(diffractive_wavefront<T> & lhs_wf, const diffractive_wavefront<U> & rhs_wf) {
02206
02207 if(lhs_wf.get_axes()!=rhs_wf.get_axes()){
02208 cerr << "operator-= error - mismatched arrays in diffractive_wavefronts\n";
02209 throw(string("diffractive_wavefront::operator-="));
02210 }
02211
02212 lhs_wf.real_imag_conversion();
02213 rhs_wf.real_imag_conversion();
02214 if(lhs_wf.interleaved && !rhs_wf.interleaved) rhs_wf.interleaved_conversion();
02215 if(!lhs_wf.interleaved && rhs_wf.interleaved) rhs_wf.non_interleaved_conversion();
02216
02217 int nelem = lhs_wf.diffractive_wavefront_header<T>::total_space();
02218 for(int i=0; i<2*nelem; i++)
02219 lhs_wf.wfdata[i] -= rhs_wf.wfdata[i];
02220
02221 return(lhs_wf);
02222 }
02223
02224 template<class T, class U>
02225 diffractive_wavefront<T> & operator*=(diffractive_wavefront<T> & lhs_wf, const diffractive_wavefront<U> & rhs_wf) {
02226
02227 if(lhs_wf.get_axes()!=rhs_wf.get_axes()){
02228 cerr << "operator*= error - mismatched arrays in diffractive_wavefronts\n";
02229 throw(string("diffractive_wavefront::operator*="));
02230 }
02231
02232 lhs_wf.amp_phase_conversion();
02233 rhs_wf.amp_phase_conversion();
02234 if(lhs_wf.interleaved && !rhs_wf.interleaved) rhs_wf.interleaved_conversion();
02235 if(!lhs_wf.interleaved && rhs_wf.interleaved) rhs_wf.non_interleaved_conversion();
02236
02237
02238
02239 if(lhs_wf.interleaved) rhs_wf.interleaved_conversion();
02240 if(!lhs_wf.interleaved) rhs_wf.non_interleaved_conversion();
02241
02242 int nelem = lhs_wf.diffractive_wavefront_header<T>::total_space();
02243 if(lhs_wf.interleaved){
02244 for(int i=0; i<nelem; i++){
02245 lhs_wf.wfdata[2*i] *= rhs_wf.wfdata[2*i];
02246 lhs_wf.wfdata[2*i+1] += rhs_wf.wfdata[2*i+1];
02247 }
02248 } else {
02249 for(int i=0; i<nelem; i++){
02250 lhs_wf.wfdata[i] *= rhs_wf.wfdata[i];
02251 lhs_wf.wfdata[i+nelem] += rhs_wf.wfdata[i+nelem];
02252 }
02253 }
02254
02255 return(lhs_wf);
02256 }
02257
02258 template<class T, class U>
02259 diffractive_wavefront<T> & operator/=(diffractive_wavefront<T> & lhs_wf, const diffractive_wavefront<U> & rhs_wf) {
02260
02261 if(lhs_wf.get_axes()!=rhs_wf.get_axes()){
02262 cerr << "operator/= error - mismatched arrays in diffractive_wavefronts\n";
02263 throw(string("diffractive_wavefront::operator/="));
02264 }
02265
02266 lhs_wf.amp_phase_conversion();
02267 rhs_wf.amp_phase_conversion();
02268 if(lhs_wf.interleaved) rhs_wf.interleaved_conversion();
02269 if(!lhs_wf.interleaved) rhs_wf.non_interleaved_conversion();
02270
02271 int nelem = lhs_wf.diffractive_wavefront_header<T>::total_space();
02272 if(lhs_wf.interleaved){
02273 for(int i=0; i<nelem; i++){
02274 if(rhs_wf.wfdata[2*i] == 0) lhs_wf.wfdata[2*i] = 0;
02275 else lhs_wf.wfdata[2*i] /= rhs_wf.wfdata[2*i];
02276 lhs_wf.wfdata[2*i+1] += rhs_wf.wfdata[2*i+1];
02277 }
02278 } else {
02279 for(int i=0; i<nelem; i++){
02280 if(rhs_wf.wfdata[i] == 0) lhs_wf.wfdata[i] = 0;
02281 else lhs_wf.wfdata[i] /= rhs_wf.wfdata[i];
02282 lhs_wf.wfdata[i+nelem] -= rhs_wf.wfdata[i+nelem];
02283 }
02284 }
02285
02286 return(lhs_wf);
02287 }
02288
02289 template<class T>
02290 template<class U>
02291 diffractive_wavefront<T> & diffractive_wavefront<T>::operator+=(std::complex<U> c) {
02292
02293 this->real_imag_conversion();
02294
02295 int nelem = this->diffractive_wavefront_header<T>::total_space();
02296 double real = c.real();
02297 double imag = c.imag();
02298 if(interleaved){
02299 for(int i=0; i<nelem; i++){
02300 this->wfdata[2*i] += real;
02301 this->wfdata[2*i+1] += imag;
02302 }
02303 } else {
02304 for(int i=0; i<nelem; i++){
02305 this->wfdata[i] += real;
02306 this->wfdata[i+nelem] += imag;
02307 }
02308 }
02309
02310 return(*this);
02311 }
02312
02313 template<class T>
02314 template<class U>
02315 diffractive_wavefront<T> & diffractive_wavefront<T>::operator-=(std::complex<U> c) {
02316
02317 this->real_imag_conversion();
02318
02319 int nelem = this->diffractive_wavefront_header<T>::total_space();
02320 double real = c.real();
02321 double imag = c.imag();
02322 if(interleaved){
02323 for(int i=0; i<nelem; i++){
02324 this->wfdata[2*i] -= real;
02325 this->wfdata[2*i+1] -= imag;
02326 }
02327 } else {
02328 for(int i=0; i<nelem; i++){
02329 this->wfdata[i] -= real;
02330 this->wfdata[i+nelem] -= imag;
02331 }
02332 }
02333
02334 return(*this);
02335 }
02336
02337 template<class T>
02338 template<class U>
02339 diffractive_wavefront<T> & diffractive_wavefront<T>::operator*=(std::complex<U> c) {
02340
02341 this->amp_phase_conversion();
02342
02343 int nelem = this->diffractive_wavefront_header<T>::total_space();
02344 double abs_val = abs(c);
02345 double arg_val = arg(c);
02346 if(interleaved){
02347 for(int i=0; i<nelem; i++){
02348 this->wfdata[2*i] *= abs_val;
02349 this->wfdata[2*i+1] += arg_val;
02350 }
02351 } else {
02352 for(int i=0; i<nelem; i++){
02353 this->wfdata[i] *= abs_val;
02354 this->wfdata[i+nelem] += arg_val;
02355 }
02356 }
02357
02358 return(*this);
02359 }
02360
02361 template<class T>
02362 template<class U>
02363 diffractive_wavefront<T> & diffractive_wavefront<T>::operator/=(std::complex<U> c) {
02364
02365 this->amp_phase_conversion();
02366
02367 int nelem = this->diffractive_wavefront_header<T>::total_space();
02368 double abs = c.abs();
02369 double arg = c.arg();
02370 if(interleaved){
02371 for(int i=0; i<nelem; i++){
02372 if(abs==0) this->wfdata[2*i] = 0;
02373 else this->wfdata[2*i] /= abs;
02374 this->wfdata[2*i+1] -= arg;
02375 }
02376 } else {
02377 for(int i=0; i<nelem; i++){
02378 if(abs==0) this->wfdata[i] = 0;
02379 else this->wfdata[i] /= abs;
02380 this->wfdata[i+nelem] -= arg;
02381 }
02382 }
02383
02384 return(*this);
02385 }
02386
02387 template<class T, class U>
02388 diffractive_wavefront<T> operator+(const diffractive_wavefront<T> & wf1, const diffractive_wavefront<U> & wf2) {
02389 diffractive_wavefront<T> tmpwf(wf1);
02390 tmpwf+=wf2;
02391 return(tmpwf);
02392 }
02393
02394 template<class T, class U>
02395 diffractive_wavefront<T> operator-(const diffractive_wavefront<T> & wf1, const diffractive_wavefront<U> & wf2) {
02396 diffractive_wavefront<T> tmpwf(wf1);
02397 tmpwf-=wf2;
02398 return(tmpwf);
02399 }
02400
02401 template<class T, class U>
02402 diffractive_wavefront<T> operator*(const diffractive_wavefront<T> & wf1, const diffractive_wavefront<U> & wf2) {
02403 diffractive_wavefront<T> tmpwf(wf1);
02404 tmpwf*=wf2;
02405 return(tmpwf);
02406 }
02407
02408 template<class T, class U>
02409 diffractive_wavefront<T> operator/(const diffractive_wavefront<T> & wf1, const diffractive_wavefront<U> & wf2) {
02410 diffractive_wavefront<T> tmpwf(wf1);
02411 tmpwf/=wf2;
02412 return(tmpwf);
02413 }
02414
02415 template<class T, class U>
02416 diffractive_wavefront<T> operator+(const diffractive_wavefront<T> & wf1, std::complex<U> c) {
02417 diffractive_wavefront<T> tmpwf(wf1);
02418 tmpwf+=c;
02419 return(tmpwf);
02420 }
02421
02422 template<class T, class U>
02423 diffractive_wavefront<T> operator-(const diffractive_wavefront<T> & wf1, std::complex<U> c) {
02424 diffractive_wavefront<T> tmpwf(wf1);
02425 tmpwf-=c;
02426 return(tmpwf);
02427 }
02428
02429 template<class T, class U>
02430 diffractive_wavefront<T> operator*(const diffractive_wavefront<T> & wf1, std::complex<U> c) {
02431 diffractive_wavefront<T> tmpwf(wf1);
02432 tmpwf*=c;
02433 return(tmpwf);
02434 }
02435
02436 template<class T, class U>
02437 diffractive_wavefront<T> operator/(const diffractive_wavefront<T> & wf1, std::complex<U> c) {
02438 diffractive_wavefront<T> tmpwf(wf1);
02439 tmpwf/=c;
02440 return(tmpwf);
02441 }
02442
02443 template<class T>
02444 bool operator !=(const diffractive_wavefront<T> & wf1, const diffractive_wavefront<T> & wf2) {
02445 return(!(wf1==wf2));
02446 }
02447
02448 }
02449
02450 #endif