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 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
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
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
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
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
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
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
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
01143
01144
01145
01146 double norm = sqrt(xfreq_interval*yfreq_interval);
01147
01148
01149
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
01160
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
01191
01192
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
01263
01264
01265
01266
01267
01268
01269
01270
01272
01273
01275
01276
01278
01279
01280
01281
01284
01285
01288
01289
01292
01293
01296
01297
01298
01301
01302
01305
01306
01309
01310
01313
01314
01317
01318
01319
01322
01323
01324
01325
01329
01330
01331
01332
01333
01334
01335
01336
01337 }
01338
01339 #endif