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 REFRACTIVE_ATMOSPHERIC_LAYER_H
00032 #define REFRACTIVE_ATMOSPHERIC_LAYER_H
00033
00034 #include <iostream>
00035 #include <region_base.h>
00036 #include "power_spectrum.h"
00037 #include "pixel_array.h"
00038 #include "optic.h"
00039 #include "diffractive_wavefront.h"
00040
00041 namespace Arroyo {
00042
00043 using std::string;
00044 using std::vector;
00045 using std::ostream;
00046
00047 template<typename U> class diffractive_wavefront;
00048
00049
00053
00054 template<class T>
00055 class refractive_atmospheric_layer :
00056 public plane_optic,
00057 public one_to_one_optic,
00058 public pixel_array<T> {
00059
00060 private:
00061
00062 static const bool factory_registration;
00063
00066 string unique_name() const {return(string("refractive atmospheric layer"));};
00067
00068 protected:
00070 double pixel_scale;
00071
00075 three_vector wind_vector;
00076
00083 template<class U>
00084 void private_transform(diffractive_wavefront<U> & wf) const;
00085
00096 template<class U>
00097 void aligned_private_transform(diffractive_wavefront<U> & wf) const;
00098
00099 public:
00100
00103 refractive_atmospheric_layer();
00104
00107 refractive_atmospheric_layer(const refractive_atmospheric_layer<T> & ref_atm_layer);
00108
00112 refractive_atmospheric_layer(const refractive_atmospheric_layer<T> & ref_atm_layer,
00113 const rectangular_region & subregion);
00114
00117 refractive_atmospheric_layer<T>(const char * filename);
00118
00121 refractive_atmospheric_layer<T>(const iofits & iof);
00122
00125 refractive_atmospheric_layer<T>(const pixel_array<T> & pixarr,
00126 double pixel_scale);
00127
00131 refractive_atmospheric_layer(const power_spectrum * pspectrum,
00132 const subharmonic_method & subm,
00133 const vector<long> & axes,
00134 double pixscale);
00135
00142 refractive_atmospheric_layer<T>(
00143 const refractive_atmospheric_layer<T> & ref_atm_layer,
00144 vector<three_point> & corners);
00145
00148 ~refractive_atmospheric_layer(){};
00149
00152 refractive_atmospheric_layer<T> & operator=(
00153 const refractive_atmospheric_layer<T> & ref_atm_layer);
00154
00157 void read(const char * filename);
00158
00161 void read(const iofits & iof);
00162
00165 void write(const char * filename) const;
00166
00169 void write(iofits & iof) const;
00170
00173 void print(ostream & os, const char * prefix="") const;
00174
00187 rectangular_region get_covering_region(const three_frame & tf) const;
00188
00191 virtual void transform(diffractive_wavefront<float> & wf) const;
00192
00195 virtual void transform(diffractive_wavefront<double> & wf) const;
00196
00199
00200
00203 void rotate_by_fft(double angle, bool window=true);
00204
00207 double get_pixel_scale() const {return(pixel_scale);};
00208
00211 void set_pixel_scale(double pscale) {pixel_scale = pscale;};
00212
00215 vector<long> get_axes() const {return(this->axes);};
00216
00221 void set_axes(const vector<long> & in_axes);
00222
00225 three_vector get_wind_vector() const {return(wind_vector);};
00226
00229 void set_wind_vector(const three_vector & wvec) {wind_vector = wvec;};
00230
00231 };
00232
00233 template<class T>
00234 refractive_atmospheric_layer<T>::refractive_atmospheric_layer() {
00235 pixel_scale = 0;
00236 }
00237
00238 template<class T>
00239 refractive_atmospheric_layer<T>::
00240 refractive_atmospheric_layer(
00241 const refractive_atmospheric_layer<T> & ref_atm_layer){
00242 this->operator=(ref_atm_layer);
00243 }
00244
00245 template<class T>
00246 refractive_atmospheric_layer<T>::
00247 refractive_atmospheric_layer(
00248 const refractive_atmospheric_layer<T> & ref_atm_layer,
00249 const rectangular_region & subregion) {
00250
00251 rectangular_region arg_layer_region(ref_atm_layer,
00252 ref_atm_layer.get_axes(),
00253 ref_atm_layer.get_pixel_scale());
00254
00255 if(!subregion.aligned(arg_layer_region)){
00256 cerr << "refractive_atmospheric_layer::refractive_atmospheric_layer error - "
00257 << "regions not aligned\n";
00258 subregion.print(cerr, "this region ");
00259 arg_layer_region.print(cerr, "arg region ");
00260 throw(string("refractive_atmospheric_layer::refractive_atmospheric_layer"));
00261 }
00262
00263 if(!arg_layer_region.contains(subregion)){
00264 cerr << "refractive_atmospheric_layer::refractive_atmospheric_layer error - "
00265 << "requested region not contained in layer\n";
00266 subregion.print(cerr, "subregion ");
00267 arg_layer_region.print(cerr, "arg region ");
00268 throw(string("refractive_atmospheric_layer::refractive_atmospheric_layer"));
00269 }
00270
00271
00272
00273 rectangular_region integral_pixel_subregion(subregion,
00274 ref_atm_layer.get_pixel_scale());
00275
00276
00277 three_point arg_layer_center = arg_layer_region.get_center();
00278 three_point integral_pixel_subregion_center =
00279 integral_pixel_subregion.get_center();
00280
00281 three_vector delta_center =
00282 integral_pixel_subregion_center - arg_layer_center;
00283
00284 double delta_center_length = delta_center.length();
00285 three_vector subpixel_shift;
00286 if(delta_center_length>three_frame::precision) {
00287 subpixel_shift =
00288 (fmod(delta_center_length, ref_atm_layer.get_pixel_scale()) /
00289 delta_center_length)*delta_center;
00290 }
00291
00292
00293 if(fabs(subpixel_shift.x(ref_atm_layer))<three_frame::precision)
00294 subpixel_shift = three_vector(0, subpixel_shift.y(ref_atm_layer),
00295 0, ref_atm_layer);
00296 if(fabs(subpixel_shift.y(ref_atm_layer))<three_frame::precision)
00297 subpixel_shift = three_vector(subpixel_shift.x(ref_atm_layer),
00298 0, 0, ref_atm_layer);
00299
00300 if(optic::verbose_level)
00301 cout << "refractive_atmospheric_layer::refractive_atmospheric_layer - "
00302 << "subpixel_shift "
00303 << subpixel_shift.x(ref_atm_layer) << "\t"
00304 << subpixel_shift.y(ref_atm_layer) << endl;
00305
00306
00307 vector<three_point> integral_pixel_subregion_corners =
00308 integral_pixel_subregion.get_corners();
00309 for(int i=0; i<4; i++)
00310 integral_pixel_subregion_corners[i] -= subpixel_shift;
00311
00312
00313 double pixscale = ref_atm_layer.get_pixel_scale();
00314 vector<long> arg_layer_axes = ref_atm_layer.get_axes();
00315 three_vector corner_vec(pixscale*arg_layer_axes[0]/2.0,
00316 pixscale*arg_layer_axes[1]/2.0,
00317 0, ref_atm_layer);
00318 three_translation ttrans(corner_vec);
00319 three_frame local_frame(ref_atm_layer);
00320 ttrans.transform(local_frame);
00321
00322
00323 vector<long> coord_limits(4);
00324 coord_limits[0] = coord_limits[1] =
00325 (long)(ceil(integral_pixel_subregion_corners[0].x(local_frame)/pixscale));
00326 coord_limits[2] = coord_limits[3] =
00327 (long)(ceil(integral_pixel_subregion_corners[0].y(local_frame)/pixscale));
00328 long tx, ty;
00329 for(int i=1; i<4; i++){
00330 tx = (long)(ceil(integral_pixel_subregion_corners[i].x(local_frame)/pixscale));
00331 ty = (long)(ceil(integral_pixel_subregion_corners[i].y(local_frame)/pixscale));
00332 if(tx<coord_limits[0]) coord_limits[0] = tx;
00333 if(tx>coord_limits[1]) coord_limits[1] = tx;
00334 if(ty<coord_limits[2]) coord_limits[2] = ty;
00335 if(ty>coord_limits[3]) coord_limits[3] = ty;
00336 }
00337
00338 if(optic::verbose_level)
00339 cout << "refractive_atmospheric_layer::refractive_atmospheric_layer - "
00340 << "extracting range "
00341 << coord_limits[0] << " - " << coord_limits[1] << " "
00342 << coord_limits[2] << " - " << coord_limits[3] << endl;
00343
00344
00345
00346 this->pixel_array<T>::operator=(pixel_array<T>(ref_atm_layer,coord_limits));
00347 this->shift_by_fft(subpixel_shift.x(local_frame),
00348 subpixel_shift.y(local_frame));
00349
00350
00351
00352 this->three_point::operator=(subregion.get_center());
00353
00354
00355 this->pixel_scale = pixscale;
00356 }
00357
00358 template<class T>
00359 refractive_atmospheric_layer<T>::
00360 refractive_atmospheric_layer(const char * filename){
00361 iofits iof;
00362 try{iof.open(filename);}
00363 catch(...){
00364 cerr << "refractive_atmospheric_layer::refractive_atmospheric_layer - "
00365 << "error opening file " << filename << endl;
00366 throw(string("refractive_atmospheric_layer::refractive_atmospheric_layer"));
00367 }
00368 this->read(iof);
00369 }
00370
00371 template<class T>
00372 refractive_atmospheric_layer<T>::refractive_atmospheric_layer(const iofits & iof){
00373 this->read(iof);
00374 }
00375
00376 template<class T>
00377 refractive_atmospheric_layer<T>::
00378 refractive_atmospheric_layer(const refractive_atmospheric_layer & ref_atm_layer,
00379 vector<three_point> & corners) {
00380 pixel_scale = ref_atm_layer.pixel_scale;
00381 wind_vector = ref_atm_layer.wind_vector;
00382 this->three_frame::operator=(ref_atm_layer);
00383 }
00384
00385 template<class T>
00386 refractive_atmospheric_layer<T>::
00387 refractive_atmospheric_layer(const pixel_array<T> & pixarr,
00388 double pixscale)
00389 : pixel_array<T>(pixarr) {
00390
00391 if(pixarr.get_axes().size()!=2){
00392 cerr << "refractive_atmospheric_layer::refractive_atmospheric_layer error - "
00393 << "cannot allocate layer with dimension "
00394 << pixarr.get_axes().size() << endl;
00395 throw(string("refractive_atmospheric_layer::refractive_atmospheric_layer"));
00396 }
00397 pixel_scale = pixscale;
00398 }
00399
00400 template<class T>
00401 refractive_atmospheric_layer<T> & refractive_atmospheric_layer<T>::
00402 operator=(const refractive_atmospheric_layer<T> & ref_atm_layer){
00403 if(this==&ref_atm_layer)
00404 return(*this);
00405
00406 pixel_scale = ref_atm_layer.pixel_scale;
00407 wind_vector = ref_atm_layer.wind_vector;
00408 this->plane_optic::operator=(ref_atm_layer);
00409 this->pixel_array<T>::operator=(ref_atm_layer);
00410 return(*this);
00411 }
00412
00413 template<class T>
00414 refractive_atmospheric_layer<T>::
00415 refractive_atmospheric_layer(const power_spectrum * pspectrum,
00416 const subharmonic_method & subm,
00417 const vector<long> & axes,
00418 double pixscale){
00419
00420 if(axes.size()!=2){
00421 cerr << "refractive_atmospheric_layer<T>::refractive_atmospheric_layer error - "
00422 << "cannot construct refractive atmospheric layer with "
00423 << axes.size() << "axes\n";
00424 throw(string("refractive_atmospheric_layer<T>::refractive_atmospheric_layer"));
00425 }
00426
00427 for(int i=0; i<axes.size(); i++){
00428 if(axes[i]<=0){
00429 cerr << "refractive_atmospheric_layer<T>::"
00430 << "refractive_atmospheric_layer error - "
00431 << " axis " << i << " has value " << axes[i]
00432 << ", which is less than zero - can't make a "
00433 << "refractive atmospheric layer with this dimension\n";
00434 throw(string("refractive_atmospheric_layer<T>::refractive_atmospheric_layer"));
00435 }
00436 }
00437
00438 if(pixscale<=0){
00439 cerr << "refractive_atmospheric_layer<T>::refractive_atmospheric_layer error -\n"
00440 << "invalid pixel scale " << pixscale << endl;
00441 throw(string("refractive_atmospheric_layer<T>::refractive_atmospheric_layer"));
00442 }
00443
00444
00445
00446
00447 vector<long> working_axes = axes;
00448 if(subm.intrinsic_dimensionality()!=-1){
00449 if(working_axes[0]%2!=subm.intrinsic_dimensionality()) working_axes[0]++;
00450 if(working_axes[1]%2!=subm.intrinsic_dimensionality()) working_axes[1]++;
00451 }
00452
00453 T * data;
00454
00455 alloc_size sz(working_axes[0], working_axes[1], 2);
00456 try{
00457 data = new T[sz];
00458 }
00459 catch(...){
00460 cerr << "refractive_atmospheric_layer<T>::refractive_atmospheric_layer error - "
00461 << "unable to allocate memory: " << sz << " bytes\n";
00462 throw;
00463 }
00464
00465 initialize_frequency_array<T>(data, pspectrum, working_axes, pixscale, true, subm);
00466
00467 fft_manager<T> fft_mgr;
00468 halfpixel_fft<T>(working_axes, data, fft_mgr);
00469
00470
00471
00472
00473 for(int i=0; i<working_axes[1]; i++)
00474 for(int j=0; j<working_axes[0]; j++)
00475 data[i*working_axes[0]+j] = data[2*(i*working_axes[0]+j)];
00476
00477
00478 if(axes!=working_axes){
00479 for(int i=0; i<axes[1]; i++)
00480 for(int j=0; j<axes[0]; j++)
00481 data[i*axes[0]+j] = data[i*working_axes[0]+j];
00482 }
00483
00484 pixel_array<T> pixarr(axes, data);
00485 delete [] data;
00486 this->operator=(refractive_atmospheric_layer<T>(pixarr, pixscale));
00487 }
00488
00489 template<class T>
00490 void refractive_atmospheric_layer<T>::set_axes(const vector<long> & in_axes){
00491 if(in_axes.size()!=2){
00492 cerr << "refractive_atmospheric_layer::set_axes error - "
00493 << "cannot set axes to dimension "
00494 << in_axes.size() << " - must be 2 dimensional\n";
00495 throw(string("refractive_atmospheric_layer::set_axes"));
00496 }
00497 pixel_array<T>::set_axes(in_axes);
00498 }
00499
00500 template<class T>
00501 void refractive_atmospheric_layer<T>::read(const char * filename){
00502 iofits iof;
00503 try{iof.open(filename);}
00504 catch(...){
00505 cerr << "refractive_atmospheric_layer::read - "
00506 << "error opening file " << filename << endl;
00507 throw(string("refractive_atmospheric_layer::read"));
00508 }
00509 try{this->read(iof);}
00510 catch(...){
00511 cerr << "refractive_atmospheric_layer::read - "
00512 << "error reading "
00513 << this->unique_name() << " from file "
00514 << filename << endl;
00515 throw(string("refractive_atmospheric_layer::read"));
00516 }
00517 }
00518
00519 template<class T>
00520 void refractive_atmospheric_layer<T>::read(const iofits & iof){
00521
00522 if(!iof.key_exists("TYPE")){
00523 cerr << "refractive_atmospheric_layer::read error - "
00524 << "unrecognized type of file\n";
00525 iof.print_header(cerr, "hdr dump");
00526 cerr << "hdu num " << iof.get_hdu_num() << " of "
00527 << iof.get_num_hdus() << endl;
00528 throw(string("refractive_atmospheric_layer::read"));
00529 }
00530 string type, comment;
00531 iof.read_key("TYPE", type, comment);
00532 if(type!=this->unique_name()){
00533 cerr << "refractive_atmospheric_layer::read error - file of type "
00534 << type << " rather than of type "
00535 << this->unique_name() << endl;
00536 throw(string("refractive_atmospheric_layer::read"));
00537 }
00538
00539 iof.read_key("PIXSCALE", pixel_scale, comment);
00540 wind_vector.read(iof);
00541 this->plane_optic::read(iof);
00542
00543 this->pixel_array<T>::read(iof);
00544
00545 if(iof.get_hdu_num()<iof.get_num_hdus())
00546 iof.movrel_hdu(1);
00547 }
00548
00549 template<class T>
00550 void refractive_atmospheric_layer<T>::write(const char * filename) const {
00551 iofits iof;
00552 try{iof.create(filename);}
00553 catch(...){
00554 cerr << "refractive_atmospheric_layer::write - "
00555 << "error opening file " << filename << endl;
00556 throw(string("refractive_atmospheric_layer::write"));
00557 }
00558 try{this->write(iof);}
00559 catch(...){
00560 cerr << "refractive_atmospheric_layer::write - "
00561 << "error writing "
00562 << this->unique_name() << " to file "
00563 << filename << endl;
00564 throw(string("refractive_atmospheric_layer::write"));
00565 }
00566 }
00567
00568 template<class T>
00569 void refractive_atmospheric_layer<T>::write(iofits & iof) const {
00570
00571 fits_header_data<double> fhd(this->get_axes());
00572 fhd.write(iof);
00573 string type = this->unique_name();
00574 string comment = "object type";
00575 iof.write_key("TYPE", type, comment);
00576 type = "pixel scale (meters)";
00577 iof.write_key("PIXSCALE", pixel_scale, type);
00578 wind_vector.write(iof);
00579 this->plane_optic::write(iof);
00580 this->pixel_array<T>::write(iof);
00581 }
00582
00583 template<class T>
00584 void refractive_atmospheric_layer<T>::
00585 print(ostream & os, const char * prefix) const {
00586 int vlspc = 30;
00587 os.setf(ios::left, ios::adjustfield);
00588 os << prefix << "TYPE = " << setw(vlspc) << this->unique_name()
00589 << "/" << "object type" << endl;
00590 fits_header_data<double> fhd(this->get_axes());
00591 fhd.print(os, prefix);
00592 os << prefix << "PIXSCALE = " << setw(vlspc) << pixel_scale
00593 << "/" << "pixel scale (meters)" << endl;
00594 three_frame tf;
00595 wind_vector.print(os, tf, prefix);
00596 this->plane_optic::print(cout, prefix);
00597 }
00598
00599 template<class T>
00600 void refractive_atmospheric_layer<T>::rotate_by_fft(double angle, bool window){
00601 this->pixel_array<T>::rotate_by_fft(angle, window);
00602 three_rotation trot(*this, this->z(), -angle);
00603 trot.transform(*this);
00604 }
00605
00606 template<class T>
00607 rectangular_region
00608 refractive_atmospheric_layer<T>::get_covering_region(
00609 const three_frame & tf) const {
00610
00611
00612
00613
00614
00615 if(fabs(dot_product(tf.z(), this->z()))<three_frame::precision){
00616 cerr << "refractive_atmospheric_layer::get_covering_region error - "
00617 << "z axes of this aperture and three frame provided "
00618 << "to this function are orthogonal\n";
00619 throw(string("refractive_atmospheric_layer::get_covering_region"));
00620 }
00621
00622 vector<double> size(2, pixel_scale*this->axes[0]);
00623 size[1] = pixel_scale*this->axes[1];
00624
00625 vector<three_point> tp(4);
00626 tp[0] = *this + .5*size[0]*this->x() + .5*size[1]*this->y();
00627 tp[1] = *this - .5*size[0]*this->x() + .5*size[1]*this->y();
00628 tp[2] = *this - .5*size[0]*this->x() - .5*size[1]*this->y();
00629 tp[3] = *this + .5*size[0]*this->x() - .5*size[1]*this->y();
00630
00631 if(foreshortening){
00632
00633
00634 int aligned = 1;
00635 if(dot_product(this->z(), tf.z())<1) aligned = -1;
00636 for(int i=0; i<4; i++)
00637 tp[i] -= aligned*dot_product(tp[i]-*this, tf.z())*tf.z();
00638 } else {
00639 three_vector rotation_axis = cross_product(this->z(), tf.z());
00640 if(rotation_axis.length() > three_frame::precision){
00641 three_rotation trot(*this, rotation_axis, rotation_axis.length());
00642 for(int i=0; i<4; i++)
00643 trot.transform(tp[i]);
00644 }
00645 }
00646
00647
00648
00649 double xmin = tp[0].x(tf);
00650 double xmax = xmin;
00651 double ymin = tp[0].y(tf);
00652 double ymax = ymin;
00653 for(int i=1; i<4; i++){
00654 if(tp[i].x(tf)>xmax) xmax = tp[i].x(tf);
00655 if(tp[i].x(tf)<xmin) xmin = tp[i].x(tf);
00656 if(tp[i].y(tf)>ymax) ymax = tp[i].y(tf);
00657 if(tp[i].y(tf)<ymin) ymin = tp[i].y(tf);
00658 }
00659
00660
00661 tp[0] = three_point(xmin, ymin, 0, tf);
00662 tp[1] = three_point(xmax, ymin, 0, tf);
00663 tp[2] = three_point(xmax, ymax, 0, tf);
00664 tp[3] = three_point(xmin, ymax, 0, tf);
00665 return(rectangular_region(tp));
00666
00667 }
00668
00669 template<class T>
00670 void refractive_atmospheric_layer<T>::transform(
00671 diffractive_wavefront<float> & wf) const {
00672 try{this->private_transform(wf);}
00673 catch(...){
00674 cerr << "refractive_atmospheric_layer::transform error - "
00675 << "error transforming a float instantiation of "
00676 << "diffractive_wavefront\n";
00677 throw(string("refractive_atmospheric_layer::transform"));
00678 }
00679 }
00680
00681 template<class T>
00682 void refractive_atmospheric_layer<T>::transform(
00683 diffractive_wavefront<double> & wf) const {
00684 try{this->private_transform(wf);}
00685 catch(...){
00686 cerr << "refractive_atmospheric_layer::transform error - "
00687 << "error transforming a float instantiation "
00688 << "of diffractive_wavefront\n";
00689 throw(string("refractive_atmospheric_layer::transform"));
00690 }
00691 }
00692
00693 template<class T> template<class U>
00694 void refractive_atmospheric_layer<T>::private_transform(
00695 diffractive_wavefront<U> & wf) const {
00696
00697
00698
00699
00700 three_frame wf_frame(wf);
00701 if(!foreshortening){
00702 three_vector rotation_axis = cross_product(this->z(), wf.z());
00703 if(rotation_axis.length()>three_frame::precision){
00704 three_rotation trot(wf, rotation_axis, rotation_axis.length());
00705 trot.transform(wf_frame);
00706 }
00707 }
00708
00709
00710
00711 if(fabs(dot_product(wf_frame.x(), this->y()))<three_frame::precision &&
00712 fabs(dot_product(wf_frame.y(), this->x()))<three_frame::precision){
00713 if(optic::verbose_level)
00714 cerr << "refractive_atmospheric_layer::private_transform"
00715 << " - calling aligned_private_transform directly...";
00716 try{this->aligned_private_transform(wf);}
00717 catch(...){
00718 cerr << "refractive_atmospheric_layer::private_transform error - "
00719 << "could not perform transform\n";
00720 throw(string("refractive_atmospheric_layer::private_transform"));
00721 }
00722 if(optic::verbose_level) cout << "returning\n";
00723 return;
00724 }
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 double dot_xz = dot_product(wf_frame.x(), this->z());
00737 double dot_yz = dot_product(wf_frame.y(), this->z());
00738 if(fabs(dot_xz)>three_frame::precision
00739 && fabs(dot_yz)>three_frame::precision){
00740 cerr << "refractive_atmospheric_layer::private_transform error - "
00741 << "at least one of the transverse axes of the wavefront must lie "
00742 << "in the plane of the layer.\n";
00743 wf_frame.three_frame::print(cerr, "wf three_frame ");
00744 this->three_frame::print(cerr, "layer three_frame ");
00745 throw(string("refractive_atmospheric_layer::private_transform"));
00746 }
00747
00748
00749
00750
00751 double rotation_angle;
00752 if(fabs(dot_xz)<three_frame::precision)
00753 rotation_angle = -acos(dot_product(wf_frame.x(), this->x()));
00754 else
00755 rotation_angle = -acos(dot_product(wf_frame.y(), this->y()));
00756
00757
00758
00759
00760
00761
00762
00763 rectangular_region wf_region(*this, wf.get_axes(), wf.get_pixel_scale());
00764 if(this->foreshortening){
00765 wf_region = rectangular_region(wf_frame, wf.get_axes(),
00766 wf.get_pixel_scale());
00767 wf_region = rectangular_region(wf_region, this->z(), false);
00768 }
00769
00770 vector<three_point> wf_projected_corners = wf_region.get_corners();
00771
00772
00773
00774
00775
00776
00777
00778
00779 double x_min = wf_projected_corners[0].x(*this);
00780 double x_max = x_min;
00781 double y_min = wf_projected_corners[0].y(*this);
00782 double y_max = y_min;
00783 double tmp;
00784 for(int i=1; i<4; i++){
00785 tmp = wf_projected_corners[i].x(*this);
00786 if(tmp<x_min) x_min = tmp;
00787 if(tmp>x_max) x_max = tmp;
00788 tmp = wf_projected_corners[i].y(*this);
00789 if(tmp<y_min) y_min = tmp;
00790 if(tmp>y_max) y_max = tmp;
00791 }
00792
00793
00794
00795
00796 three_vector wind_vector = wf.get_timestamp()*this->get_wind_vector();
00797
00798 vector<three_point> layer_extraction_corners(4);
00799 layer_extraction_corners[0] =
00800 three_point(x_min, y_min, 0, *this) - wind_vector;
00801 layer_extraction_corners[1] =
00802 three_point(x_max, y_min, 0, *this) - wind_vector;
00803 layer_extraction_corners[2] =
00804 three_point(x_max, y_max, 0, *this) - wind_vector;
00805 layer_extraction_corners[3] =
00806 three_point(x_min, y_max, 0, *this) - wind_vector;
00807
00808 rectangular_region layer_extraction_region(layer_extraction_corners);
00809
00810
00811
00812
00813
00814 refractive_atmospheric_layer<T> xtrctd_layer(*this, layer_extraction_region);
00815 xtrctd_layer.rotate_by_fft(rotation_angle, false);
00816 xtrctd_layer.aligned_private_transform(wf);
00817 }
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 template<class T> template<class U>
01064 void refractive_atmospheric_layer<T>::
01065 aligned_private_transform(diffractive_wavefront<U> & wf) const {
01066
01067
01068
01069 if(operator!=(static_cast<three_point>(wf),
01070 static_cast<three_point>(*this))){
01071 three_vector origin_offset =
01072 static_cast<three_point>(wf) - static_cast<three_point>(*this);
01073
01074 if(fabs(dot_product(origin_offset,
01075 this->three_frame::z()))>three_frame::precision){
01076 cerr << "refractive_atmospheric_layer::aligned_private_transform error - "
01077 << "diffractive_wavefront center not in transverse plane of layer\n";
01078 wf.three_point::print(cerr, *this, "wavefront center in frame of layer ");
01079 throw(string("refractive_atmospheric_layer::aligned_private_transform"));
01080 }
01081 }
01082
01083
01084
01085
01086 if(fabs(dot_product(wf.x(), this->y()))>three_frame::precision &&
01087 fabs(dot_product(wf.y(), this->x()))<three_frame::precision){
01088 cerr << "refractive_atmospheric_layer::aligned_private_transform error - "
01089 << "the wavefront transverse axes are not aligned "
01090 << "with those of the layer\n";
01091 throw(string("refractive_atmospheric_layer::aligned_private_transform"));
01092 }
01093
01094 three_frame wind_blown_frame(*this);
01095 wind_blown_frame += wf.get_timestamp()*this->get_wind_vector();
01096
01097
01098
01099
01100 rectangular_region layer_region, wf_region, modified_wf_region;
01101
01102 try{
01103 layer_region = rectangular_region(wind_blown_frame,
01104 this->get_axes(),
01105 this->get_pixel_scale());
01106 } catch(...) {
01107 cerr << "refractive_atmospheric_layer::aligned_private_transform error - "
01108 << "could not get layer region\n";
01109 throw(string("refractive_atmospheric_layer::aligned_private_transform"));
01110 }
01111
01112 try{
01113 wf_region = rectangular_region(wf,
01114 wf.get_axes(),
01115 wf.get_pixel_scale());
01116 } catch(...) {
01117 cerr << "refractive_atmospheric_layer::aligned_private_transform error - "
01118 << "could not get layer region\n";
01119 throw(string("refractive_atmospheric_layer::aligned_private_transform"));
01120 }
01121
01122 if(this->foreshortening){
01123 modified_wf_region = rectangular_region(wf_region,
01124 this->z(),
01125 false);
01126 } else {
01127 three_frame tmp_frame;
01128 if(dot_product(wf.z(), this->z())>0)
01129 tmp_frame = three_frame(wf, this->x(), this->y(), this->z());
01130 else
01131 tmp_frame = three_frame(wf, this->x(), this->y(), -1*this->z());
01132 modified_wf_region = rectangular_region(tmp_frame,
01133 wf.get_axes(),
01134 wf.get_pixel_scale());
01135 }
01136
01137 if(!layer_region.contains(modified_wf_region)){
01138 cerr << "refractive_atmospheric_layer::aligned_private_transform error - "
01139 << "layer does not contain wavefront\n";
01140 layer_region.print(cerr, "layer region ");
01141 modified_wf_region.print(cerr, "wfrnt region ");
01142 throw(string("refractive_atmospheric_layer::aligned_private_transform"));
01143 }
01144
01145
01146
01147
01148 vector<long> wf_axes = wf.get_axes();
01149 double wf_x_halfpix=0, wf_y_halfpix=0;
01150 double layer_x_halfpix=0, layer_y_halfpix=0;
01151 int wf_x_extrapix=1, wf_y_extrapix=1;
01152 int layer_x_extrapix=1, layer_y_extrapix=1;
01153 if(wf_axes[1]%2==0){
01154 wf_x_halfpix = .5;
01155 wf_x_extrapix = 0;
01156 }
01157 if(wf_axes[0]%2==0){
01158 wf_y_halfpix = .5;
01159 wf_y_extrapix = 0;
01160 }
01161 if(this->axes[1]%2==0){
01162 layer_x_halfpix = .5;
01163 layer_x_extrapix = 0;
01164 }
01165 if(this->axes[0]%2==0){
01166 layer_y_halfpix = .5;
01167 layer_y_extrapix = 0;
01168 }
01169
01170 double x_sign = 1;
01171 if(dot_product(wf.x(),this->x())<0)
01172 x_sign = -1;
01173 double y_sign = 1;
01174 if(dot_product(wf.y(),this->y())<0)
01175 y_sign = -1;
01176
01177
01178
01179
01180
01181
01182
01183
01184 double wf_x_pixscale = wf.get_pixel_scale();
01185 double wf_y_pixscale = wf.get_pixel_scale();
01186 double dp;
01187 if(this->get_foreshortening()){
01188 dp = dot_product(wf.x(), this->x());
01189 wf_x_pixscale /= (dp*dp);
01190 dp = dot_product(wf.y(), this->y());
01191 wf_y_pixscale /= (dp*dp);
01192 if(optic::verbose_level)
01193 cout << "refractive_atmospheric_layer::aligned_private_transform -\n"
01194 << "\twavefront pixel scale " << wf.get_pixel_scale() << endl
01195 << "\tprojected x pixel scale " << wf_x_pixscale << endl
01196 << "\tprojected y pixel scale " << wf_y_pixscale << endl;
01197 }
01198
01199
01200
01201 this->wavefront_amp_phase_conversion(wf);
01202 U * wfdata = this->get_wavefront_data(wf);
01203
01204
01205
01206
01207
01208
01209 double wf_wavelength = wf.get_wavelength();
01210 double lower_wf_x_pixel_coord, lower_wf_y_pixel_coord;
01211 double upper_wf_x_pixel_coord, upper_wf_y_pixel_coord;
01212 long index_wf_x_pixel_coord, index_wf_y_pixel_coord;
01213
01214 double min_wf_x_pixel_coord, min_wf_y_pixel_coord;
01215 double max_wf_x_pixel_coord, max_wf_y_pixel_coord;
01216
01217 double area, refractive_optical_path;
01218
01219 three_vector origin_offset = wf - wind_blown_frame;
01220 bool is_real_imag = this->is_real_imag_storage(wf);
01221 bool is_interleaved = this->is_interleaved_storage(wf);
01222 double tmp;
01223 int index, wf_nelem = wf_axes[0]*wf_axes[1],
01224 layer_nelem = this->axes[0]*this->axes[1];
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237 for(int i=-wf_axes[1]/2; i<wf_axes[1]/2+wf_x_extrapix; i++){
01238 for(int j=-wf_axes[0]/2; j<wf_axes[0]/2+wf_y_extrapix; j++){
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 min_wf_x_pixel_coord = (((j+wf_x_halfpix)*x_sign - .5)*wf_x_pixscale +
01249 origin_offset.x(wind_blown_frame))/this->pixel_scale;
01250 min_wf_y_pixel_coord = (((i+wf_y_halfpix)*y_sign - .5)*wf_y_pixscale +
01251 origin_offset.y(wind_blown_frame))/this->pixel_scale;
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 max_wf_x_pixel_coord = min_wf_x_pixel_coord + wf_x_pixscale/this->pixel_scale;
01262 max_wf_y_pixel_coord = min_wf_y_pixel_coord + wf_y_pixscale/this->pixel_scale;
01263
01264
01265
01266
01267
01268
01269
01270
01271 refractive_optical_path = 0;
01272
01273 index_wf_x_pixel_coord = (long)floor(min_wf_x_pixel_coord);
01274 while(index_wf_x_pixel_coord < max_wf_x_pixel_coord){
01275 index_wf_y_pixel_coord = (long)floor(min_wf_y_pixel_coord);
01276 while(index_wf_y_pixel_coord < max_wf_y_pixel_coord){
01277
01278
01279 index =
01280 (index_wf_y_pixel_coord+layer_y_extrapix+this->axes[1]/2)*this->axes[0] +
01281 index_wf_x_pixel_coord+layer_x_extrapix+this->axes[0]/2;
01282
01283 lower_wf_x_pixel_coord =
01284 index_wf_x_pixel_coord < min_wf_x_pixel_coord ?
01285 min_wf_x_pixel_coord : index_wf_x_pixel_coord;
01286
01287 lower_wf_y_pixel_coord =
01288 index_wf_y_pixel_coord < min_wf_y_pixel_coord ?
01289 min_wf_y_pixel_coord : index_wf_y_pixel_coord;
01290
01291 upper_wf_x_pixel_coord =
01292 index_wf_x_pixel_coord + 1 < max_wf_x_pixel_coord ?
01293 index_wf_x_pixel_coord + 1 : max_wf_x_pixel_coord;
01294
01295 upper_wf_y_pixel_coord =
01296 index_wf_y_pixel_coord + 1 < max_wf_y_pixel_coord ?
01297 index_wf_y_pixel_coord + 1 : max_wf_y_pixel_coord;
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319 area = (upper_wf_x_pixel_coord - lower_wf_x_pixel_coord)
01320 *(upper_wf_y_pixel_coord - lower_wf_y_pixel_coord);
01321
01322
01323
01324
01325
01326
01327
01328 if(index<0 || index>=layer_nelem || area<=0){
01329 cerr << "\nrefractive_atmospheric_layer::aligned_private_transform"
01330 << " - error transforming wavefront\n";
01331 cerr << "indices "
01332 << i
01333 << "\t" << j
01334 << "\t" << index
01335 << "\t" << layer_nelem
01336 << endl;
01337 cerr << "x coords "
01338 << "\tlower " << lower_wf_x_pixel_coord
01339 << "\tupper " << upper_wf_x_pixel_coord
01340 << "\tmin " << min_wf_x_pixel_coord
01341 << "\tmax " << max_wf_x_pixel_coord
01342 << endl;
01343 cerr << "y coords "
01344 << "\tlower " << lower_wf_y_pixel_coord
01345 << "\tupper " << upper_wf_y_pixel_coord
01346 << "\tmin " << min_wf_y_pixel_coord
01347 << "\tmax " << max_wf_y_pixel_coord
01348 << endl;
01349 cerr << "layer axes "
01350 << this->axes[0]
01351 << "\t" << this->axes[1]
01352 << endl;
01353 cerr << "wavefront axes "
01354 << wf_axes[0]
01355 << "\t" << wf_axes[1]
01356 << endl;
01357 cerr << "area "
01358 << area
01359 << endl;
01360 throw(string("refractive_atmospheric_layer::aligned_private_transform"));
01361 }
01362
01363 refractive_optical_path +=
01364 this->pixeldata[index]*area;
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378 index_wf_y_pixel_coord++;
01379 }
01380 index_wf_x_pixel_coord++;
01381 }
01382
01383
01384 tmp = refractive_optical_path*2*M_PI/wf_wavelength;
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395 if(is_interleaved){
01396 index = (i+wf_axes[1]/2)*wf_axes[0] + j + wf_axes[0]/2;
01397 wfdata[2*index+1] += tmp;
01398 } else if(!is_interleaved){
01399 index = (i+wf_axes[1]/2)*wf_axes[0] + j + wf_axes[0]/2;
01400 wfdata[index+wf_nelem] += tmp;
01401 }
01402 }
01403 }
01404 }
01405 }
01406
01407 #endif