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 CONIC_MIRROR_H
00032 #define CONIC_MIRROR_H
00033
00034 #include <iomanip>
00035 #include "optic.h"
00036 #include "diffractive_wavefront.h"
00037 #include "conic_section.h"
00038
00039 namespace Arroyo {
00040
00041
00042 class conic_mirror_base :
00043 public one_to_one_optic,
00044 public conic_section {
00045
00046 public:
00047
00050 conic_mirror_base(){};
00051
00054 virtual ~conic_mirror_base(){};
00055
00058 virtual void read(const char * filename) = 0;
00059
00062 virtual void read(const iofits & iof) = 0;
00063
00066 virtual void write(const char * filename) const = 0;
00067
00070 virtual void write(iofits & iof) const = 0;
00071
00074 virtual void print(ostream & os, const char * prefix="") const = 0;
00075
00083 virtual three_point get_point_of_intersection(const three_point & tp,
00084 const three_vector & tv) const = 0;
00085
00086 };
00087
00088
00095
00096 template<class aperture_type>
00097 class conic_mirror :
00098 public conic_mirror_base {
00099
00100 private:
00101
00102 static const bool factory_registration;
00103
00106 string unique_name() const {return(string("conic mirror"));};
00107
00108 protected:
00109
00110
00111 aperture_type ap;
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 bool raytrace_policy;
00125
00131 conic_mirror(){};
00132
00140 template<class T>
00141 void private_transform(diffractive_wavefront<T> & wf) const;
00142
00143 public:
00144
00147 conic_mirror(const conic_mirror & cmr);
00148
00151 conic_mirror(const char * filename);
00152
00155 conic_mirror(const iofits & iof);
00156
00176 conic_mirror(const three_point & vertex,
00177 const three_point & focus,
00178 double eccty,
00179 const aperture_type & in_ap);
00180
00183 ~conic_mirror(){};
00184
00187 conic_mirror & operator=(const conic_mirror & cmr);
00188
00191 void read(const char * filename);
00192
00195 void read(const iofits & iof);
00196
00199 void write(const char * filename) const;
00200
00203 void write(iofits & iof) const;
00204
00207 void print(ostream & os, const char * prefix="") const;
00208
00218 bool get_raytrace_policy() const {
00219 return(this->raytrace_policy);
00220 };
00221
00224 void set_raytrace_policy(bool raytrace_policy){
00225 this->raytrace_policy = raytrace_policy;
00226 };
00227
00240 rectangular_region get_covering_region(const three_frame & tf) const;
00241
00249 three_point get_point_of_intersection(const three_point & tp,
00250 const three_vector & tv) const;
00251
00254 void transform(diffractive_wavefront<float> & wf) const;
00255
00258 void transform(diffractive_wavefront<double> & wf) const;
00259
00260 };
00261
00262
00263 template<class aperture_type>
00264 conic_mirror<aperture_type>::conic_mirror(const conic_mirror & cmr) {
00265 this->operator=(cmr);
00266 }
00267
00268 template<class aperture_type>
00269 conic_mirror<aperture_type>::conic_mirror(const char * filename){
00270 this->read(filename);
00271 }
00272
00273 template<class aperture_type>
00274 conic_mirror<aperture_type>::conic_mirror(const iofits & iof){
00275 this->read(iof);
00276 }
00277
00278 template<class aperture_type>
00279 conic_mirror<aperture_type>::conic_mirror(const three_point & vtx,
00280 const three_point & focus,
00281 double eccty,
00282 const aperture_type & in_ap) : ap(in_ap){
00283
00284 this->conic_section::operator=(conic_section(vtx,focus,eccty));
00285
00286 this->raytrace_policy = true;
00287
00288 if((this->get_point_of_intersection(ap, ap.z()) - ap).length()>three_frame::precision){
00289 cerr << "conic_mirror::conic_mirror error - "
00290 << "aperture center does not lie on the surface of the conic mirror\n";
00291 throw(string("conic_mirror::conic_mirror"));
00292 }
00293 }
00294
00295 template<class aperture_type>
00296 conic_mirror<aperture_type> & conic_mirror<aperture_type>::operator=(const conic_mirror & cmr) {
00297 if(this==&cmr) return(*this);
00298 this->conic_section::operator=(cmr);
00299 this->ap = cmr.ap;
00300 this->raytrace_policy=cmr.raytrace_policy;
00301 return(*this);
00302 }
00303
00304 template<class aperture_type>
00305 void conic_mirror<aperture_type>::read(const char * filename) {
00306 iofits iof;
00307 try{iof.open(filename);}
00308 catch(...){
00309 cerr << "conic_mirror::read - "
00310 << "error opening file " << filename << endl;
00311 throw(string("conic_mirror::read"));
00312 }
00313 try{this->read(iof);}
00314 catch(...){
00315 cerr << "conic_mirror::read - "
00316 << "error reading "
00317 << this->unique_name() << " from file "
00318 << filename << endl;
00319 throw(string("conic_mirror::read"));
00320 }
00321 }
00322
00323 template<class aperture_type>
00324 void conic_mirror<aperture_type>::read(const iofits & iof) {
00325 if(!iof.key_exists("TYPE")){
00326 cerr << "conic_mirror::read error - "
00327 << "no power law type specified\n";
00328 throw(string("conic_mirror::read"));
00329 } else {
00330 string type, comment;
00331 iof.read_key("TYPE", type, comment);
00332 if(type!=this->unique_name()){
00333 cerr << "conic_mirror::read error - outer scale of type "
00334 << type << " rather than type "
00335 << this->unique_name() << endl;
00336 throw(string("conic_mirror::read"));
00337 } else {
00338
00339 iof.read_key("RAYPLCY", this->raytrace_policy, comment);
00340
00341
00342 try{
00343 iof.movrel_hdu(1);
00344 } catch(...){
00345 cerr << "conic_mirror::read - error moving to aperture hdu\n";
00346 throw(string("conic_mirror::read"));
00347 }
00348
00349 try{
00350 this->ap.read(iof);
00351 } catch(...){
00352 cerr << "conic_mirror::read - error reading aperture\n";
00353 throw(string("conic_mirror::read"));
00354 }
00355
00356 try{
00357 this->conic_section::read(iof);
00358 } catch(...){
00359 cerr << "conic_mirror::read - error reading conic section\n";
00360 throw(string("conic_mirror::read"));
00361 }
00362 }
00363 }
00364
00365 }
00366
00367 template<class aperture_type>
00368 void conic_mirror<aperture_type>::write(const char * filename) const {
00369 iofits iof;
00370 try{iof.create(filename);}
00371 catch(...){
00372 cerr << "conic_mirror::write - "
00373 << "error opening file " << filename << endl;
00374 throw(string("conic_mirror::write"));
00375 }
00376
00377 try{this->write(iof);}
00378 catch(...){
00379 cerr << "conic_mirror::write - "
00380 << "error writing "
00381 << this->unique_name() << " to file "
00382 << filename << endl;
00383 throw(string("conic_mirror::write"));
00384 }
00385 }
00386
00387 template<class aperture_type>
00388 void conic_mirror<aperture_type>::write(iofits & iof) const {
00389 Arroyo::fits_header_data<char> tmphdr;
00390 tmphdr.write(iof);
00391
00392 string type = this->unique_name();
00393 string comment = "object type";
00394 iof.write_key("TYPE", type, comment);
00395 iof.write_key("RAYPLCY", this->raytrace_policy, string("raytrace policy"));
00396
00397 this->ap.write(iof);
00398 this->conic_section::write(iof);
00399 }
00400
00401 template<class aperture_type>
00402 void conic_mirror<aperture_type>::print(ostream & os, const char * prefix) const {
00403 int vlspc = 30;
00404 os.setf(std::ios::left, std::ios::adjustfield);
00405 os << prefix << "TYPE = " << setw(vlspc) << this->unique_name()
00406 << "/" << "object type" << endl;
00407 os << prefix << "RAYPLCY = " << setw(vlspc) << this->raytrace_policy
00408 << "/" << "raytrace policy" << endl;
00409 this->conic_section::print(os, prefix);
00410 this->ap.print(os, prefix);
00411 }
00412
00413 template<class aperture_type>
00414 rectangular_region conic_mirror<aperture_type>::get_covering_region(const three_frame & tf) const {
00415 return(this->ap.get_covering_region(tf));
00416 }
00417
00418 template<class aperture_type>
00419 three_point conic_mirror<aperture_type>::get_point_of_intersection(const three_point & tp,
00420 const three_vector & tv) const {
00421
00422 double distance_to_conic, R_squared, V;
00423 three_vector conic_unit_normal;
00424 three_point point_of_intersection;
00425
00426 this->conic_section::raytrace(tp,
00427 tv,
00428 distance_to_conic,
00429 point_of_intersection,
00430 conic_unit_normal,
00431 R_squared,
00432 V);
00433
00434 return(point_of_intersection);
00435 }
00436
00437 template<class aperture_type>
00438 void conic_mirror<aperture_type>::transform(diffractive_wavefront<float> & wf) const {
00439 try{this->private_transform(wf);}
00440 catch(...){
00441 cerr << "conic_mirror::transform error - "
00442 << "error transforming a float instantiation of diffractive_wavefront\n";
00443 throw(string("conic_mirror::transform"));
00444 }
00445 }
00446
00447 template<class aperture_type>
00448 void conic_mirror<aperture_type>::transform(diffractive_wavefront<double> & wf) const {
00449 try{this->private_transform(wf);}
00450 catch(...){
00451 cerr << "conic_mirror::transform error - "
00452 << "error transforming a double instantiation of diffractive_wavefront\n";
00453 throw(string("conic_mirror::transform"));
00454 }
00455 }
00456
00457 template<class aperture_type>
00458 template<class T>
00459 void conic_mirror<aperture_type>::private_transform(diffractive_wavefront<T> & wf) const {
00460
00461
00462
00463
00464
00465
00466
00467 double init_wf_to_conic_OPD, conic_to_final_wf_OPD, conic_R_squared, conic_V;
00468 three_vector conic_unit_normal;
00469 three_point conic_point_of_intersection;
00470
00471 try{
00472 this->conic_section::raytrace(wf,
00473 wf.z(),
00474 init_wf_to_conic_OPD,
00475 conic_point_of_intersection,
00476 conic_unit_normal,
00477 conic_R_squared,
00478 conic_V);
00479 } catch(...) {
00480 cerr << "conic_mirror::private_transform - error tracing central ray\n";
00481 throw(string("conic_mirror::private_transform"));
00482 }
00483
00484 if(fabs(init_wf_to_conic_OPD)>three_frame::precision){
00485 cerr << "conic_mirror::private_transform error - wavefront does not lie on conic surface\n";
00486 cerr << "distance to conic " << init_wf_to_conic_OPD << endl;
00487
00488 throw(string("conic_mirror::private_transform"));
00489 }
00490
00491
00492
00493
00494
00495 three_frame final_wf_tf(wf);
00496 three_vector perpendicular_vector;
00497
00498 try{
00499 perpendicular_vector = cross_product(wf.z(),
00500 conic_unit_normal);
00501
00502 if(perpendicular_vector.length()>three_frame::precision){
00503 three_rotation trot(wf,
00504 perpendicular_vector,
00505 -2*perpendicular_vector.length());
00506 trot.transform(final_wf_tf);
00507 }
00508 final_wf_tf = three_frame(final_wf_tf,
00509 final_wf_tf.x(),
00510 final_wf_tf.y(),
00511 -1*final_wf_tf.z());
00512 } catch(...) {
00513 cerr << "conic_mirror::private_transform - error forming final three frame\n";
00514 throw(string("conic_mirror::private_transform"));
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 double initial_wavefront_curvature = wf.get_curvature();
00527 double final_wavefront_curvature =
00528 initial_wavefront_curvature -
00529 2*this->conic_section::get_local_curvature(wf);
00530
00531 if(optic::verbose_level)
00532 cout << "conic_mirror::private_transform: "
00533 << "initial curvature " << initial_wavefront_curvature
00534 << " local curvature " << this->conic_section::get_local_curvature(wf)
00535 << " final curvature " << final_wavefront_curvature
00536 << endl;
00537
00538
00539 three_point final_focus;
00540 conic_section final_wavefront_conic;
00541 if(fabs(final_wavefront_curvature)<three_frame::precision){
00542 final_focus = final_wf_tf + 1e15*wf.z();
00543 final_wavefront_conic = conic_section(wf,
00544 final_focus,
00545 0);
00546 } else {
00547 final_focus = final_wf_tf - (1/final_wavefront_curvature)*final_wf_tf.z();
00548 final_wavefront_conic = conic_section(wf,
00549 final_focus,
00550 0);
00551 }
00552
00553 try{
00554
00555
00556
00557 bool interleaved_storage = is_interleaved_storage(wf);
00558 this->wavefront_amp_phase_conversion(wf);
00559 T * wfdata = get_wavefront_data(wf);
00560
00561
00562 vector<long> wf_axes = wf.get_axes();
00563 long nelem = wf_axes[0]*wf_axes[1];
00564 double x_halfpix=0, y_halfpix=0;
00565 int x_extrapix=1, y_extrapix=1;
00566 if(wf_axes[1]%2==0){
00567 x_halfpix = .5;
00568 x_extrapix = 0;
00569 }
00570 if(wf_axes[0]%2==0){
00571 y_halfpix = .5;
00572 y_extrapix = 0;
00573 }
00574
00575 int index;
00576 double residual_OPD;
00577 double wavelength_meters = wf.get_wavelength();
00578 double arc_length_meters;
00579 double twopi = 2*M_PI;
00580 double final_wf_R_squared, final_wf_V;
00581
00582 three_vector rotation_vector;
00583 three_point initial_pixel_tp, final_pixel_tp;
00584 three_vector initial_pixel_tv, final_pixel_tv;
00585 three_vector perpendicular_vector;
00586 three_point final_wf_point_of_intersection;
00587 three_vector final_wf_unit_normal;
00588
00589 for(int i=-wf_axes[1]/2; i<wf_axes[1]/2+x_extrapix; i++){
00590 for(int j=-wf_axes[0]/2; j<wf_axes[0]/2+y_extrapix; j++){
00591
00592 try{
00593 if(fabs(initial_wavefront_curvature)<three_frame::precision){
00594
00595 initial_pixel_tv = wf.z();
00596 initial_pixel_tp =
00597 wf +
00598 (i+x_halfpix)*wf.get_pixel_scale()*wf.x()+
00599 (j+y_halfpix)*wf.get_pixel_scale()*wf.y();
00600
00601 } else {
00602
00603 initial_pixel_tv = wf.z();
00604
00605 three_point wavefront_center_of_curvature =
00606 wf - fabs(1/initial_wavefront_curvature)*wf.z();
00607
00608
00609 arc_length_meters =
00610 sqrt((i+x_halfpix)*(i+x_halfpix)+
00611 (j+y_halfpix)*(j+y_halfpix))*
00612 wf.get_pixel_scale();
00613
00614
00615
00616
00617 if(fabs(arc_length_meters)>three_frame::precision){
00618 rotation_vector = cross_product(wf.z(),
00619 (i+x_halfpix)*wf.x()+
00620 (j+y_halfpix)*wf.y());
00621
00622 three_rotation trot(wavefront_center_of_curvature,
00623 rotation_vector,
00624 -1*initial_wavefront_curvature*arc_length_meters);
00625
00626 trot.transform(initial_pixel_tv);
00627 }
00628
00629 initial_pixel_tp =
00630 wavefront_center_of_curvature +
00631 (1/fabs(initial_wavefront_curvature))*initial_pixel_tv;
00632 }
00633 } catch(...) {
00634 cerr << "conic_mirror::private_transform - error finding initial point on wavefront\n";
00635 throw(string("conic_mirror::private_transform"));
00636 }
00637
00638
00639
00640
00641 if(this->conic_section::on_conic(initial_pixel_tp))
00642 continue;
00643
00644 residual_OPD = 0;
00645
00646 try{
00647 this->conic_section::raytrace(initial_pixel_tp,
00648 initial_pixel_tv,
00649 init_wf_to_conic_OPD,
00650 conic_point_of_intersection,
00651 conic_unit_normal,
00652 conic_R_squared,
00653 conic_V);
00654
00655 residual_OPD += init_wf_to_conic_OPD;
00656 final_pixel_tp = conic_point_of_intersection;
00657
00658 } catch(...) {
00659 cerr << "conic_mirror::private_transform - error tracing initial rays\n";
00660 throw(string("conic_mirror::private_transform"));
00661 }
00662
00663
00664 try{
00665 if(this->raytrace_policy){
00666
00667 final_pixel_tv = initial_pixel_tv;
00668
00669 three_reflection tref(conic_point_of_intersection,
00670 conic_unit_normal);
00671
00672 tref.transform(final_pixel_tv);
00673
00674
00675 if(fabs(dot_product(initial_pixel_tv,
00676 conic_unit_normal) +
00677 dot_product(final_pixel_tv,
00678 conic_unit_normal))>three_frame::precision){
00679 cerr << "conic_mirror::private_transform - error forming final ray vector\n";
00680
00681 three_vector tmp = -1*initial_pixel_tv;
00682
00683 tmp.print(cerr, "\treflected initial tv ");
00684 conic_unit_normal.print(cerr, "\tconic normal tv ");
00685 perpendicular_vector.print(cerr, "\tperp tv ");
00686 final_pixel_tv.print(cerr, "\tfinal tv ");
00687
00688 cout << "\tlengths: init "
00689 << initial_pixel_tv.length()
00690 << "\treflected "
00691 << tmp.length()
00692 << "\tconic unit normal "
00693 << conic_unit_normal.length()
00694 << "\tfinal "
00695 << final_pixel_tv.length()
00696 << endl;
00697
00698 cout << "\tdot products: "
00699 << dot_product(tmp,conic_unit_normal)
00700 << "\t"
00701 << dot_product(conic_unit_normal, final_pixel_tv)
00702 << "\t"
00703 << dot_product(tmp,conic_unit_normal) - dot_product(conic_unit_normal, final_pixel_tv)
00704 << endl;
00705
00706 throw(string("conic_mirror::private_transform"));
00707 }
00708
00709 } else {
00710
00711
00712 final_pixel_tv = final_focus - conic_point_of_intersection;
00713 final_pixel_tv = (1/final_pixel_tv.length())*final_pixel_tv;
00714 }
00715 } catch (...){
00716 cerr << "conic_mirror::private_transform - error finding final pixel vector\n";
00717 throw(string("conic_mirror::private_transform"));
00718 }
00719
00720 try{
00721 final_wavefront_conic.raytrace(final_pixel_tp,
00722 final_pixel_tv,
00723 conic_to_final_wf_OPD,
00724 final_wf_point_of_intersection,
00725 final_wf_unit_normal,
00726 final_wf_R_squared,
00727 final_wf_V);
00728
00729 residual_OPD += conic_to_final_wf_OPD;
00730 } catch(...) {
00731 cerr << "conic_mirror::private_transform - error tracing final rays\n";
00732 final_pixel_tv.print(cerr, "fpv ");
00733 final_focus.print(cerr, "ffocus ");
00734 final_wf_point_of_intersection.print(cerr, "cnc pt int");
00735 throw(string("conic_mirror::private_transform"));
00736 }
00737
00738
00739 if(optic::verbose_level){
00740 cout << "conic_mirror::private_transform - "
00741 << (i+x_halfpix)*wf.get_pixel_scale()
00742 << "\t"
00743 << (j+y_halfpix)*wf.get_pixel_scale()
00744 << "\tinitial OPD "
00745 << init_wf_to_conic_OPD
00746 << "\tfinal OPD "
00747 << conic_to_final_wf_OPD
00748 << " net OPD "
00749 << residual_OPD
00750 << " phase "
00751 << twopi*fmod(residual_OPD/wavelength_meters, 1.)
00752 << endl;
00753 }
00754
00755
00756 if(cross_product(.5*(final_pixel_tv - initial_pixel_tv),conic_unit_normal).length()/1e6>
00757 three_frame::precision){
00758 cout << "conic_mirror::private_transform error - cross product "
00759 << cross_product(.5*(final_pixel_tv - initial_pixel_tv),conic_unit_normal).length()
00760 << " indicates initial, final, and conic normal vectors are not coplanar\n";
00761
00762 initial_pixel_tp.print(cout, "\tinitial pixel tp ");
00763 initial_pixel_tv.print(cout, "\tinitial pixel tv ");
00764 final_pixel_tp.print(cout, "\tfinal pixel tp ");
00765 final_pixel_tv.print(cout, "\tfinal pixel tv ");
00766 conic_point_of_intersection.print(cout, "\tconic pt of intersection ");
00767 conic_unit_normal.print(cout, "\tconic unit normal ");
00768 final_wf_point_of_intersection.print(cout, "\tfinal wf pt of intersection ");
00769 final_wf_unit_normal.print(cout, "\tfinal wf unit normal ");
00770 cout << "\tconic params: R_squared " << conic_R_squared << "\tV " << conic_V << endl;
00771 cout << "\tfinal wf params: R_squared " << final_wf_R_squared << "\tV " << final_wf_V << endl;
00772 cout << endl << endl;
00773 three_vector tmp = .5*(final_pixel_tv - initial_pixel_tv);
00774
00775 tmp.print(cout, "\t.5*(final - initial tv) ");
00776 tmp = (1/tmp.length())*tmp;
00777 tmp.print(cout, "\tnormalized .5*(final - initial tv) ");
00778 conic_unit_normal.print(cout, "\tconic unit normal ");
00779 (tmp-conic_unit_normal).print(cout, "\tdiff vector ");
00780
00781 cross_product(.5*(final_pixel_tv - initial_pixel_tv),conic_unit_normal).print(cout, "\txproduct " );
00782 cout << "\tInit length " << initial_pixel_tv.length() << endl;
00783 cout << "\tFinal length " << final_pixel_tv.length() << endl;
00784 cout << "\tDiff length " << .5*(final_pixel_tv - initial_pixel_tv).length() << endl;
00785 cout << "\tConic normal length " << conic_unit_normal.length() << endl;
00786
00787 throw(string("conic_mirror::private_transform"));
00788 }
00789
00790
00791
00792
00793
00794
00795
00796 try{
00797 index = (i+wf_axes[1]/2)*wf_axes[0]+j+wf_axes[0]/2;
00798 if(interleaved_storage){
00799 wfdata[2*index+1] =
00800 fmod(wfdata[2*index+1]+twopi*residual_OPD/wavelength_meters, twopi);
00801 if(wfdata[2*index+1]<0) wfdata[2*index+1]+=twopi;
00802 } else {
00803 wfdata[index+nelem] =
00804 fmod(wfdata[index+nelem]+twopi*residual_OPD/wavelength_meters, twopi);
00805 if(wfdata[index+nelem]<0) wfdata[index+nelem]+=twopi;
00806 }
00807 } catch(...) {
00808 cerr << "conic_mirror::private_transform - error updating phases\n";
00809 throw(string("conic_mirror::private_transform"));
00810 }
00811
00812
00813
00814 wf.set_curvature(final_wavefront_curvature);
00815
00816 }
00817 }
00818 } catch(...) {
00819 cerr << "conic_mirror::private_transform - error raytracing wavefront\n";
00820 throw(string("conic_mirror::private_transform"));
00821 }
00822
00823
00824
00825
00826 try{
00827 three_point wf_ap_intsctn_pt =
00828 ap.get_point_of_intersection(wf,
00829 ap.z());
00830
00831 three_point orig_wf_pt(wf);
00832
00833 wf.three_point::operator=(wf_ap_intsctn_pt);
00834 ap.transform(wf);
00835
00836 wf.three_point::operator=(orig_wf_pt);
00837
00838 } catch(...) {
00839 cerr << "conic_mirror::private_transform - error aperturing wavefront\n";
00840 throw(string("conic_mirror::private_transform"));
00841 }
00842
00843
00844 wf.three_frame::operator=(final_wf_tf);
00845
00846
00847 }
00848 }
00849 #endif