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

power_spectrum.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 POWER_SPECTRUM_H
00032 #define POWER_SPECTRUM_H
00033 
00034 #include <cmath>
00035 #include <iostream>
00036 #include <fft_manager.h>
00037 #include <AO_algo.h>
00038 #include "AO_sim_base.h"
00039 #include "fits_header_data.h"
00040 #include "AO_algo.h"
00041 #include "subharmonic_method.h"
00042 
00043 namespace Arroyo {
00044 
00045   using std::ostream;
00046   using std::cerr;
00047   using std::endl;
00048   using std::string;
00049   using std::vector;
00050 
00051   // class forward declarations
00052   class structure_function;
00053   
00057 
00058   class inner_scale :
00059     virtual public AO_sim_base {
00060 
00061   public:
00062   
00065     inner_scale(){};
00066 
00069     virtual ~inner_scale(){};
00070 
00073     virtual void read(const char * filename) = 0;
00074 
00077     virtual void read(const iofits & iof) = 0;
00078 
00081     virtual void write(const char * filename) const = 0;
00082 
00085     virtual void write(iofits & iof) const = 0;
00086 
00089     virtual void print(ostream & os, const char * prefix="") const = 0;
00090 
00093     virtual double value(double spatial_frequency) const = 0;
00094 
00097     static inner_scale * inner_scale_factory(const char * filename); 
00098 
00101     static inner_scale * inner_scale_factory(const iofits & iof); 
00102 
00103   };
00104 
00108 
00109   class null_inner_scale :
00110     public inner_scale {
00111 
00112     private:
00113   
00114     static const bool factory_registration;
00115 
00118     string unique_name() const {return(string("null inner scale"));};
00119 
00120     public:
00121 
00124     null_inner_scale(){};
00125 
00128     null_inner_scale(const null_inner_scale & nullinscle);
00129 
00132     null_inner_scale(const char * filename);
00133 
00136     null_inner_scale(const iofits & iof);
00137 
00140     ~null_inner_scale(){};
00141 
00144     null_inner_scale &
00145       operator=(const null_inner_scale & nullinscle);
00146 
00149     void read(const char * filename);
00150 
00153     void read(const iofits & iof);
00154 
00157     void write(const char * filename) const;
00158 
00161     void write(iofits & iof) const;
00162 
00165     void print(ostream & os, const char * prefix="") const;
00166 
00169     double value(double spatial_frequency) const {
00170       return(1);
00171     };
00172 
00175     friend bool operator==(const null_inner_scale & nis1, const null_inner_scale & nis2);
00176   };
00177 
00180   bool operator!=(const null_inner_scale & eis1, const null_inner_scale & eis2);
00181 
00182 
00186 
00187   class exponential_inner_scale :
00188     public inner_scale {
00189 
00190     private:
00191   
00192     static const bool factory_registration;
00193 
00196     string unique_name() const {return(string("exponential inner scale"));};
00197 
00198     protected:
00199 
00201     double inner_scale_value;
00202   
00203     public:
00204 
00207     exponential_inner_scale();
00208 
00211     exponential_inner_scale(const exponential_inner_scale & expinscle);
00212 
00215     exponential_inner_scale(const char * filename);
00216 
00219     exponential_inner_scale(const iofits & iof);
00220 
00223     exponential_inner_scale(double inscle);
00224 
00227     ~exponential_inner_scale(){};
00228 
00231     exponential_inner_scale &
00232       operator=(const exponential_inner_scale & expinscle);
00233 
00236     void read(const char * filename);
00237 
00240     void read(const iofits & iof);
00241 
00244     void write(const char * filename) const;
00245 
00248     void write(iofits & iof) const;
00249 
00252     void print(ostream & os, const char * prefix="") const;
00253 
00256     double value(double spatial_frequency) const {
00257       if(spatial_frequency<0) {
00258         cerr << "exponential_inner_scale::value error - cannot return value for negative spatial frequency " 
00259                   << spatial_frequency << endl;
00260         throw(string("exponential_inner_scale::value"));
00261       }
00262       // see Sasiela eq 2.25, Hardy eq 3.96 for the factor 5.91
00263       return(exp(-spatial_frequency*spatial_frequency*inner_scale_value*inner_scale_value/(5.91*5.91)));
00264     };
00265 
00268     friend bool operator==(const exponential_inner_scale & eis1, const exponential_inner_scale & eis2);
00269   };
00270 
00273   bool operator!=(const exponential_inner_scale & eis1, const exponential_inner_scale & eis2);
00274 
00278 
00279   class frehlich_inner_scale : 
00280     public inner_scale {
00281 
00282     private:
00283 
00284     static const bool factory_registration;
00285 
00288     string unique_name() const {return(string("frehlich inner scale"));};
00289 
00290     protected:
00291 
00293     double inner_scale_value;
00294 
00295     public:
00296 
00299     frehlich_inner_scale();
00300 
00303     frehlich_inner_scale(const frehlich_inner_scale & frehlich_inscle);
00304 
00307     frehlich_inner_scale(const char * filename);
00308 
00311     frehlich_inner_scale(const iofits & iof);
00312 
00315     frehlich_inner_scale(double inscle);
00316 
00319     ~frehlich_inner_scale(){};
00320 
00323     frehlich_inner_scale &
00324       operator=(const frehlich_inner_scale & frehlich_inscle);
00325 
00328     void read(const char * filename);
00329 
00332     void read(const iofits & iof);
00333 
00336     void write(const char * filename) const;
00337 
00340     void write(iofits & iof) const;
00341 
00344     void print(ostream & os, const char * prefix="") const;
00345 
00348     double value(double spatial_frequency) const {
00349       if(spatial_frequency<0) {
00350         cerr << "frehlich_inner_scale::value error - cannot return value for negative spatial frequency " 
00351                   << spatial_frequency << endl;
00352         throw(string("frehlich_inner_scale::value"));
00353       }
00354     
00355       double delta = 1.109;
00356       double a[4] = {.70937, 2.8235, -.28086, -.08277};
00357       double d = exp(-delta * spatial_frequency * inner_scale_value);
00358       double s = 0;
00359       for(int i=0; i<4; i++)
00360         s += a[i]*pow(spatial_frequency*inner_scale_value, i);
00361     
00362       return(d*s);
00363     };
00364     
00367     friend bool operator==(const frehlich_inner_scale & fis1, const frehlich_inner_scale & fis2);
00368 
00369   };
00370 
00373   bool operator!=(const frehlich_inner_scale & fis1, const frehlich_inner_scale & fis2);
00374 
00378 
00379   class power_law :
00380     virtual public AO_sim_base {
00381 
00382   private:
00383 
00384     static const bool factory_registration;
00385 
00388     string unique_name() const {return(string("power law"));};
00389 
00390   protected:
00393     double exponent;
00394 
00397     double coefficient;
00398 
00399   public:
00400 
00403     power_law();
00404 
00407     power_law(const power_law & plaw);
00408 
00411     power_law(const char * filename);
00412 
00415     power_law(const iofits & iof);
00416 
00419     power_law(double expnt, double coeff);
00420 
00423     power_law(double expnt, 
00424               double r_0_meters,
00425               double r_0_ref_wavelength_meters);
00426 
00429     ~power_law(){};
00430 
00433     power_law & operator=(const power_law & plaw);
00434 
00437     void read(const char * filename);
00438 
00441     void read(const iofits & iof);
00442 
00445     void write(const char * filename) const;
00446 
00449     void write(iofits & iof) const;
00450 
00453     virtual double value(double spatial_frequency) const {
00454       if(spatial_frequency<0) {
00455         cerr << "power_law::value error - cannot return value for negative spatial frequency " 
00456                   << spatial_frequency << endl;
00457         throw(string("power_law::value"));
00458       }
00459       return(coefficient*pow(spatial_frequency, exponent));
00460     };
00461 
00464     virtual void print(ostream & os, const char * prefix="") const;
00465 
00469     virtual bool pole_at_zero_spatial_frequency() const {return true;};
00470 
00473     double get_coefficient() const {return coefficient;};
00474  
00477     double get_exponent() const {return exponent;};
00478 
00481     static power_law * power_law_factory(const char * filename); 
00482 
00485     static power_law * power_law_factory(const iofits & iof); 
00486 
00489     friend bool operator==(const power_law & plaw1, 
00490                            const power_law & plaw2);
00491 
00492   };
00493 
00496   bool operator!=(const power_law & plaw1, 
00497                   const power_law & plaw2);
00498 
00502 
00503   class von_karman_power_law :
00504     public power_law {
00505 
00506     private:
00507 
00508     static const bool factory_registration;
00509 
00512     string unique_name() const {return(string("von karman power law"));};
00513 
00514     protected:
00515 
00517     double outer_scale_value;
00518 
00519     public:
00520 
00523     von_karman_power_law();
00524 
00527     von_karman_power_law(const von_karman_power_law & vk_power_law);
00528 
00531     von_karman_power_law(const char * filename);
00532 
00535     von_karman_power_law(const iofits & iof);
00536 
00539     von_karman_power_law(double expnt, 
00540                          double coeff,
00541                          double outscle);
00542 
00545     von_karman_power_law(double expnt, 
00546                          double r_0_meters,
00547                          double r_0_ref_wavelength_meters,
00548                          double outscle);
00549 
00552     ~von_karman_power_law(){};
00553 
00556     von_karman_power_law &
00557       operator=(const von_karman_power_law & vk_power_law);
00558  
00561     void read(const char * filename);
00562 
00565     void read(const iofits & iof);
00566 
00569     void write(const char * filename) const;
00570 
00573     void write(iofits & iof) const;
00574 
00577     void print(ostream & os, const char * prefix="") const;
00578 
00582     bool pole_at_zero_spatial_frequency() const {return false;};
00583 
00586     double value(double spatial_frequency) const {
00587       if(spatial_frequency<0) {
00588         cerr << "von_karman_power_law::value error - cannot return value for negative spatial frequency " 
00589                   << spatial_frequency << endl;
00590         throw(string("von_karman_power_law::value"));
00591       }  
00592       return(coefficient * pow((spatial_frequency*spatial_frequency + 
00593                                 4*M_PI*M_PI/(outer_scale_value*outer_scale_value)),
00594                                exponent/2)); 
00595     };
00596 
00599     double get_outer_scale() const {return outer_scale_value;};
00600   
00603     friend bool operator==(const von_karman_power_law & vkplaw1, const von_karman_power_law & vkplaw2);
00604   };
00605 
00608   bool operator!=(const von_karman_power_law & vkplaw1, const von_karman_power_law & vkplaw2);
00609 
00613 
00614   class greenwood_power_law :
00615     public power_law {
00616 
00617     private:
00618 
00619     static const bool factory_registration;
00620 
00623     string unique_name() const {return(string("greenwood power law"));};
00624 
00625     protected:
00626 
00628     double outer_scale_value;
00629 
00630     public:
00631 
00634     greenwood_power_law();
00635 
00638     greenwood_power_law(const greenwood_power_law & gw_power_law);
00639 
00642     greenwood_power_law(const char * filename);
00643 
00646     greenwood_power_law(const iofits & iof);
00647 
00650     greenwood_power_law(double expnt, 
00651                         double coeff, 
00652                         double outscle);
00653 
00656     greenwood_power_law(double expnt, 
00657                         double r_0_meters,
00658                         double r_0_ref_wavelength_meters,
00659                         double outscle);
00660 
00663     ~greenwood_power_law(){};
00664 
00667     greenwood_power_law &
00668       operator=(const greenwood_power_law & gw_power_law);
00669 
00672     void read(const char * filename);
00673 
00676     void read(const iofits & iof);
00677 
00680     void write(const char * filename) const;
00681 
00684     void write(iofits & iof) const;
00685 
00688     void print(ostream & os, const char * prefix="") const;
00689 
00693     bool pole_at_zero_spatial_frequency() const {return false;};
00694 
00697     double value(double spatial_frequency) const {
00698       if(spatial_frequency<0) {
00699         cerr << "greenwood_power_law::value error - cannot return value for negative spatial frequency " 
00700                   << spatial_frequency << endl;
00701         throw(string("greenwood_power_law::value"));
00702       }  
00703       return(coefficient * pow((spatial_frequency*(spatial_frequency + 2*M_PI/outer_scale_value)),exponent/2)); 
00704     };
00705 
00708     double get_outer_scale() const {return outer_scale_value;};
00709 
00712     friend bool operator==(const greenwood_power_law & gwplaw1, const greenwood_power_law & gwplaw2);
00713   };
00714 
00717   bool operator!=(const greenwood_power_law & gwplaw1, const greenwood_power_law & gwplaw2);
00718 
00719 
00721   template<class T>
00722   class refractive_atmospheric_layer;
00723 
00727 
00728   class power_spectrum :
00729     virtual public AO_sim_base {
00730 
00731     private:
00732 
00735     virtual power_spectrum * clone() const = 0;
00736 
00737     public:
00738 
00741     power_spectrum(){};
00742 
00745     virtual ~power_spectrum(){};
00746 
00749     virtual void read(const char * filename) = 0;
00750 
00753     virtual void read(const iofits & iof) = 0;
00754 
00757     virtual void write(const char * filename) const = 0;
00758 
00761     virtual void write(iofits & iof) const = 0;
00762 
00765     virtual void print(ostream & os, const char * prefix="") const = 0;
00766 
00769     virtual double value(double spatial_frequency) const = 0;
00770 
00773     virtual double get_coefficient() const = 0;
00774 
00778     virtual bool pole_at_zero_spatial_frequency() const = 0;
00779 
00782     static power_spectrum * power_spectrum_factory(const char * filename); 
00783 
00786     static power_spectrum * power_spectrum_factory(const iofits & iof); 
00787 
00790     static power_spectrum * power_spectrum_factory(const power_spectrum * pspec){
00791       return pspec->clone(); 
00792     }; 
00793 
00795     static int verbose_level;
00796 
00797   };
00798 
00803 
00804   template <class power_law_type, class inner_scale_type>
00805     class isotropic_power_law_spectrum :
00806     public power_spectrum {
00807     
00808     private:
00809     
00810     static const bool factory_registration;
00811 
00814     string unique_name() const {return(string("isotropic power law spectrum"));};
00815 
00818     isotropic_power_law_spectrum(){};
00819 
00822     isotropic_power_law_spectrum * clone() const {
00823       return new isotropic_power_law_spectrum(*this);
00824     }
00825 
00826     protected:
00827 
00828     power_law_type plaw;
00829     
00830     inner_scale_type inscle;
00831 
00832     public:
00833 
00836     isotropic_power_law_spectrum(const isotropic_power_law_spectrum & ipls);
00837 
00840     isotropic_power_law_spectrum(const iofits & iof);
00841 
00844     isotropic_power_law_spectrum(const char * filename);
00845 
00848     isotropic_power_law_spectrum(const power_law_type & plaw_type, 
00849                                  const inner_scale_type & inscle_type);
00850 
00853     ~isotropic_power_law_spectrum(){};
00854 
00857     isotropic_power_law_spectrum &
00858       operator=(const isotropic_power_law_spectrum & ipls);
00859 
00862     void read(const char * filename);
00863 
00866     void read(const iofits & iof);
00867 
00870     void write(const char * filename) const;
00871 
00874     void write(iofits & iof) const;
00875 
00878     void print(ostream & os, const char * prefix="") const;
00879 
00882     double get_coefficient() const {return plaw.get_coefficient();};
00883 
00886     double value(double spatial_frequency) const {
00887       return(inscle.value(spatial_frequency)*plaw.value(spatial_frequency));
00888     };
00889 
00892     power_law_type get_power_law() const {return plaw;};
00893     
00896     inner_scale_type get_inner_scale() const {return inscle;};
00897     
00901     bool pole_at_zero_spatial_frequency() const {
00902         return plaw.pole_at_zero_spatial_frequency();
00903     }
00904 
00905   };
00906 
00909   template<class power_law_type, class inner_scale_type>
00910     bool operator==(const isotropic_power_law_spectrum<power_law_type, inner_scale_type> & iso1,
00911                     const isotropic_power_law_spectrum<power_law_type, inner_scale_type> & iso2){
00912     if(iso1.get_power_law()!=iso2.get_power_law()) return(false);
00913     if(iso1.get_inner_scale()!=iso2.get_inner_scale()) return(false);
00914     return(true);
00915   }
00916 
00919   template<class power_law_type, class inner_scale_type>
00920     bool operator!=(const isotropic_power_law_spectrum<power_law_type, inner_scale_type> & iso1,
00921                     const isotropic_power_law_spectrum<power_law_type, inner_scale_type> & iso2){
00922     return(!operator==(iso1, iso2));
00923   }
00924 
00925   template<class power_law_type, class inner_scale_type> 
00926     isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
00927     isotropic_power_law_spectrum(const isotropic_power_law_spectrum<power_law_type, inner_scale_type> & ipls) {
00928     this->operator=(ipls);
00929   }
00930 
00931   template<class power_law_type, class inner_scale_type> 
00932   isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
00933   isotropic_power_law_spectrum(const iofits & iof) {
00934     this->read(iof);
00935   }
00936 
00937   template<class power_law_type, class inner_scale_type> 
00938   isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
00939   isotropic_power_law_spectrum(const char * filename) {
00940     this->read(filename);
00941   }
00942 
00943   template<class power_law_type, class inner_scale_type> 
00944   isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
00945   isotropic_power_law_spectrum(const power_law_type & plaw, 
00946                                const inner_scale_type & inscle) {
00947 
00948     // Check the args
00949     try{dynamic_cast<const power_law &>(plaw);}
00950     catch(...){
00951       cerr << "isotropic_power_law_spectrum::isotropic_power_law_spectrum error - argument not of type power law\n";
00952       throw(string("isotropic_power_law_spectrum::isotropic_power_law_spectrum"));
00953     }
00954     try{dynamic_cast<const inner_scale &>(inscle);}
00955     catch(...){
00956       cerr << "isotropic_power_law_spectrum::isotropic_power_law_spectrum error - argument not of type inner scale\n";
00957       throw(string("isotropic_power_law_spectrum::isotropic_power_law_spectrum"));
00958     }
00959   
00960     this->plaw = plaw;
00961     this->inscle = inscle;
00962   }
00963 
00964   template<class power_law_type, class inner_scale_type> 
00965   isotropic_power_law_spectrum<power_law_type, inner_scale_type> & 
00966     isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
00967     operator=(const isotropic_power_law_spectrum<power_law_type, inner_scale_type> & ipls){
00968 
00969     if(this==&ipls)
00970       return(*this);
00971     plaw = ipls.plaw;
00972     inscle = ipls.inscle;
00973     return(*this);
00974   }
00975 
00976   template<class power_law_type, class inner_scale_type> 
00977   void isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
00978     read(const char * filename){
00979     iofits iof;
00980     try{iof.open(filename);}
00981     catch(...){
00982       cerr << "isotropic_power_law_spectrum::read - "
00983            << "error opening file " << filename << endl;
00984       throw(string("isotropic_power_law_spectrum::read"));
00985     }
00986     try{this->read(iof);}
00987     catch(...){
00988       cerr << "isotropic_power_law_spectrum::read - "
00989            << "error reading "
00990            << this->unique_name() << " from file "
00991            << filename << endl;
00992       throw(string("isotropic_power_law_spectrum::read"));
00993     }
00994   }
00995   
00996   template<class power_law_type, class inner_scale_type> 
00997   void isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
00998     read(const iofits & iof){
00999 
01000     if(!iof.key_exists("TYPE")){
01001       cerr << "isotropic_power_law_spectrum::read error - "
01002            << "unrecognized type\n";
01003       throw(string("isotropic_power_law_spectrum::read"));
01004     }
01005 
01006     string type, comment;
01007     iof.read_key("TYPE", type, comment);
01008     if(type!=this->unique_name()){
01009       cerr << "isotropic_power_law_spectrum::read error - file of type " 
01010            << type << " rather than of type "
01011            << this->unique_name() << endl;
01012       throw(string("isotropic_power_law_spectrum::read"));
01013     }
01014 
01015     // Move to the power law header
01016     iof.movrel_hdu(1);
01017     try{plaw.read(iof);}
01018     catch(...){
01019       cerr << "isotropic_power_law_spectrum::read error - "
01020            << "could not read power law\n";
01021       throw(string("isotropic_power_law_spectrum::read"));
01022     }
01023 
01024     // Move to the inner scale header
01025     iof.movrel_hdu(1);
01026     try{inscle.read(iof);}
01027     catch(...){
01028       cerr << "isotropic_power_law_spectrum::read error - "
01029            << "could not read inner scale\n";
01030       throw(string("isotropic_power_law_spectrum::read"));
01031     }
01032 
01033     // leave iof pointing to the next header, if it exists
01034     if(iof.get_hdu_num()!=iof.get_num_hdus())
01035       iof.movrel_hdu(1);
01036   }
01037 
01038   template<class power_law_type, class inner_scale_type> 
01039   void isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
01040     write(const char * filename) const {
01041 
01042     iofits iof;
01043     try{iof.create(filename);}
01044     catch(...){
01045       cerr << "isotropic_power_law_spectrum::write - "
01046            << "error opening file " << filename << endl;
01047       throw(string("isotropic_power_law_spectrum::write"));
01048     }
01049 
01050     try{this->write(iof);}
01051     catch(...){
01052       cerr << "isotropic_power_law_spectrum::write - "
01053            << "error writing "
01054            << this->unique_name() << " to file " 
01055            << filename << endl;
01056       throw(string("isotropic_power_law_spectrum::write"));
01057     }
01058   }
01059 
01060   template<class power_law_type, class inner_scale_type>  
01061     void isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
01062     write(iofits & iof) const {
01063     
01064     fits_header_data<char> tmphdr;
01065     tmphdr.write(iof);
01066 
01067     string type = this->unique_name();
01068     string comment = "object type";
01069     iof.write_key("TYPE", type, comment);
01070 
01071     try{plaw.write(iof);}
01072     catch(...){
01073       cerr << "isotropic_power_law_spectrum::write error - "
01074            << "could not write power law\n";
01075       throw(string("isotropic_power_law_spectrum::write"));
01076     }
01077     try{inscle.write(iof);}
01078     catch(...){
01079       cerr << "isotropic_power_law_spectrum::write error - "
01080            << "could not write inner scale\n";
01081       throw(string("isotropic_power_law_spectrum::write"));
01082     } 
01083   }
01084 
01085   template<class power_law_type, class inner_scale_type>  
01086     void isotropic_power_law_spectrum<power_law_type, inner_scale_type>::
01087     print(ostream & os, const char * prefix) const {
01088     int vlspc = 30;
01089     os.setf(ios::left, ios::adjustfield); 
01090     os << prefix << "TYPE       = " << setw(vlspc) << this->unique_name()
01091        << "/" << "object type" << endl;
01092     plaw.print(os, prefix);
01093     inscle.print(os, prefix);
01094   }
01095 
01096 
01097   template<class T>
01098   void initialize_frequency_array(T * data, 
01099                                   const power_spectrum * pspectrum,
01100                                   const vector<long> & axes, 
01101                                   double pixscale, bool random, 
01102                                   const subharmonic_method & subm) {
01103     
01104     if(axes.size()!=2){
01105       cerr << "isotropic_power_law_spectrum::initialize_frequency_array error -\n"
01106            << "axes of dimension " << axes.size()
01107            << " but must be of dimension 2" << endl;
01108       throw(string("isotropic_power_law_spectrum::initialize_frequency_array"));
01109     }
01110 
01111     if(axes[0]<=0 || axes[1]<=0){
01112       cerr << "isotropic_power_law_spectrum::initialize_frequency_array error -\n"
01113            << "invalid axes " << axes[0] << "\t" << axes[1] << endl;
01114       throw(string("isotropic_power_law_spectrum::initialize_frequency_array"));
01115     }
01116 
01117     if(pixscale<=0){
01118       cerr << "isotropic_power_law_spectrum::initialize_frequency_array error -\n"
01119            << "invalid pixel scale " << pixscale << endl;
01120       throw(string("isotropic_power_law_spectrum::initialize_frequency_array"));
01121     }
01122 
01123     // the coordinate locations of pixels and subpixels
01124     double pixel_location[2];
01125 
01126     double x_halfpix=0, y_halfpix=0;
01127     int x_extrapix=1, y_extrapix=1;
01128     if(axes[1]%2==0){
01129       x_halfpix = .5;
01130       x_extrapix = 0;
01131     }
01132     if(axes[0]%2==0){
01133       y_halfpix = .5;
01134       y_extrapix = 0;
01135     }
01136   
01137     int index;
01138     double xfreq_interval = 2*M_PI/(pixscale*axes[1]);
01139     double yfreq_interval = 2*M_PI/(pixscale*axes[0]);
01140     double val, r1, r2;
01141 
01142     // The factor to fix the units on the delta function
01143     // contribution to make it look like a smooth probability
01144     // distribution.
01145     // See Johansson & Gavel
01146     double norm = sqrt(xfreq_interval*yfreq_interval);
01147 
01148     // Here if the zero frequency value of the power spectrum
01149     // is infinite, we will not fill it in
01150     bool skip_zero_frequency = false;
01151     if(pspectrum->pole_at_zero_spatial_frequency()) skip_zero_frequency = true;
01152 
01153     for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01154       for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01155 
01156         pixel_location[0] = (i+x_halfpix)*xfreq_interval;
01157         pixel_location[1] = (j+y_halfpix)*yfreq_interval;
01158       
01159         // Here, if both axes are odd we have to skip the middle pixel,
01160         // since its nominal value is infinite.
01161         if(pixel_location[0]==0 && pixel_location[1]==0 && skip_zero_frequency){
01162           index = (axes[1]/2)*axes[0] + axes[0]/2;
01163           data[2*index] = data[2*index+1] = 0;
01164           continue;
01165         } 
01166 
01167         val = norm*sqrt(pspectrum->value(sqrt(pixel_location[0]*pixel_location[0]+
01168                                          pixel_location[1]*pixel_location[1])));
01169 
01170         index = (i+axes[1]/2)*axes[0] + j + axes[0]/2;
01171         if(random){
01172           box_mueller(r1,r2);
01173           data[2*index] = r1*val;
01174           data[2*index+1] = r2*val;
01175         } else {
01176           data[2*index] = val*val;
01177           data[2*index+1] = 0;
01178         } 
01179       }
01180     }
01181 
01182     if(random)
01183       subm.apply_subharmonic_correction(*pspectrum, axes, pixscale, true, data);
01184     else {                                                        
01185       subm.apply_subharmonic_correction(*pspectrum, axes, pixscale, false, data);
01186     }   
01187 
01188   }
01189 
01190   // Here we compensate for the halfpixel shift that arises if
01191   // the axes are even.  This shift was discussed in the comments
01192   // to the function diffractive_wavefront<T>::far_field_propagator
01193   template<class T>
01194     void halfpixel_fft(const vector<long> & axes, 
01195                        T * data,
01196                        fft_manager<T> & fft_mgr){
01197 
01198     double x_halfpix=0, y_halfpix=0;
01199     int x_extrapix=1, y_extrapix=1;
01200     if(axes[1]%2==0){
01201       x_halfpix = .5;
01202       x_extrapix = 0;
01203     }
01204     if(axes[0]%2==0){
01205       y_halfpix = .5;
01206       y_extrapix = 0;
01207     }
01208     int index;
01209     double xslope = M_PI/(double)axes[1];
01210     double yslope = M_PI/(double)axes[0];
01211     double cp, sp, tmp;
01212     if(axes[1]%2==1) xslope = 0;
01213     if(axes[0]%2==1) yslope = 0;
01214 
01215     if(xslope!=0 || yslope!=0){
01216       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01217         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01218           cp = cos(xslope*(i+x_halfpix) + yslope*(j+y_halfpix));
01219           sp = sin(xslope*(i+x_halfpix) + yslope*(j+y_halfpix));
01220           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01221           tmp = cp*data[2*index] + sp*data[2*index+1];
01222           data[2*index+1] = -sp*data[2*index] + cp*data[2*index+1];
01223           data[2*index] = tmp;
01224         }
01225       }
01226     }
01227 
01228     complex_cyclic_permutation(axes, axes[1]/2, axes[0]/2, data);
01229       
01230     vector<long> flipped_axes(2, axes[1]);
01231     flipped_axes[1]=axes[0];
01232       
01233     fft_mgr.forward_fft(flipped_axes, true, true, data);
01234       
01235     complex_cyclic_permutation(axes, -axes[1]/2, -axes[0]/2, data);
01236       
01237     if(xslope!=0 || yslope!=0){
01238       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01239         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01240           cp = cos(xslope*(i+x_halfpix) + yslope*(j+y_halfpix));
01241           sp = sin(xslope*(i+x_halfpix) + yslope*(j+y_halfpix));
01242           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01243           tmp = cp*data[2*index] + sp*data[2*index+1];
01244           data[2*index+1] = -sp*data[2*index] + cp*data[2*index+1];
01245           data[2*index] = tmp;
01246         }
01247       }
01248     }
01249   }
01250 
01251 
01260 
01261   /*
01262     CLASS 
01263     generic_power_spectrum
01264   
01265     class to represent generic power spectra
01266 
01267     class generic_power_spectrum {
01268 
01269     protected:
01270 
01272     long npts;
01273 
01275     float * pspec_values;
01276 
01278     float * pspec_freqs;
01279 
01280     public:
01281 
01284     generic_power_spectrum();
01285 
01288     generic_power_spectrum(const generic_power_spectrum & gps);
01289 
01292     ~generic_power_spectrum();
01293 
01296     generic_power_spectrum &
01297     operator=(const generic_power_spectrum & gps);
01298 
01301     void read(const char * filename);
01302 
01305     void read(const iofits & iof);
01306 
01309     void write(const char * filename);
01310 
01313     void write(iofits & iof);
01314 
01317     one_d_structure_function 
01318     get_one_d_structure_function(long npts, double spacing) const;
01319 
01322     two_d_structure_function 
01323     get_two_d_structure_function(vector<long> & npts, 
01324     vector<double> & spacing) const;
01325 
01329     refractive_atmospheric_layer 
01330     get_random_layer(double pixel_scale,
01331     vector<long> pixel_dimensions) const;
01332   
01333 
01334     }
01335   */
01336 
01337 }
01338 
01339 #endif

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