8 #ifndef __pyramidSensor_hpp__
9 #define __pyramidSensor_hpp__
12 #include "mx/imagingUtils.hpp"
13 #include "mx/fraunhoferImager.hpp"
14 #include "mx/timeUtils.hpp"
15 #include "mx/fitsFile.hpp"
17 #include "../../math/constants.hpp"
19 #include "wavefront.hpp"
21 #include "mx/imageTransforms.hpp"
24 #define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
37 template<
typename _
floatT,
typename _detectorT>
42 typedef _floatT floatT;
44 typedef std::complex<floatT> complexT;
47 typedef wavefront<floatT> wavefrontT;
50 typedef mx::imagingArray<std::complex<floatT>,fftwAllocator<std::complex<floatT> >, 0> complexFieldT;
53 typedef Eigen::Array< floatT, Eigen::Dynamic, Eigen::Dynamic> wfsImageT;
55 typedef _detectorT detectorT;
87 mx::fraunhoferImager<complexFieldT> fi;
90 std::vector<complexFieldT> tilts;
98 std::vector<wavefrontT> _wavefronts;
113 wfsImageT detectorImage;
143 void detSize(
int nrows,
int ncols);
155 void lambda(floatT l);
173 void simStep(floatT st);
175 template<
typename AOSysT>
176 void linkSystem(AOSysT & AOSys);
183 bool senseWavefront(wavefrontT & pupilPlane);
188 bool senseWavefrontCal(wavefrontT & pupilPlane);
206 void wfPS(floatT ps);
231 void modSteps(
int mSt);
243 void modRadius(floatT mR);
270 void doSenseWavefront();
271 void doSenseWavefrontNoMod(wavefrontT &);
277 template<
typename _
floatT,
typename _detectorT>
278 pyramidSensor<_floatT, _detectorT>::pyramidSensor()
303 ds9_interface_init(&ds9i);
304 ds9_interface_set_title(&ds9i,
"PyWFS");
307 template<
typename _
floatT,
typename _detectorT>
308 int pyramidSensor<_floatT, _detectorT>::wfSz()
313 template<
typename _
floatT,
typename _detectorT>
314 void pyramidSensor<_floatT, _detectorT>::wfSz(
int sz)
316 if( _wfSz == sz)
return;
320 fi.setWavefrontSizePixels(_wfSz);
325 template<
typename _
floatT,
typename _detectorT>
326 int pyramidSensor<_floatT, _detectorT>::detRows()
332 template<
typename _
floatT,
typename _detectorT>
333 int pyramidSensor<_floatT, _detectorT>::detCols()
338 template<
typename _
floatT,
typename _detectorT>
339 void pyramidSensor<_floatT, _detectorT>::detSize(
int nrows,
int ncols)
341 if( _detRows == nrows && _detCols == ncols)
return;
346 detector.setSize(_detRows, _detCols);
347 detectorImage.resize(_detRows, _detCols);
352 template<
typename _
floatT,
typename _detectorT>
353 _floatT pyramidSensor<_floatT, _detectorT>::lambda()
358 template<
typename _
floatT,
typename _detectorT>
359 void pyramidSensor<_floatT, _detectorT>::lambda(_floatT l)
365 template<
typename _
floatT,
typename _detectorT>
366 template<
typename AOSysT>
367 void pyramidSensor<_floatT, _detectorT>::linkSystem(AOSysT & AOSys)
369 AOSys.wfs.wfPS(AOSys._wfPS);
370 AOSys.wfs.D(AOSys._D);
374 template<
typename _
floatT,
typename _detectorT>
375 int pyramidSensor<_floatT, _detectorT>::wfPS()
380 template<
typename _
floatT,
typename _detectorT>
381 void pyramidSensor<_floatT, _detectorT>::wfPS(_floatT ps)
386 template<
typename _
floatT,
typename _detectorT>
387 _floatT pyramidSensor<_floatT, _detectorT>::D()
392 template<
typename _
floatT,
typename _detectorT>
393 void pyramidSensor<_floatT, _detectorT>::D(_floatT d)
400 template<
typename _
floatT,
typename _detectorT>
401 int pyramidSensor<_floatT, _detectorT>::modSteps()
406 template<
typename _
floatT,
typename _detectorT>
407 void pyramidSensor<_floatT, _detectorT>::modSteps(
int mSt)
414 template<
typename _
floatT,
typename _detectorT>
415 _floatT pyramidSensor<_floatT, _detectorT>::modRadius()
420 template<
typename _
floatT,
typename _detectorT>
421 void pyramidSensor<_floatT, _detectorT>::modRadius(_floatT mR)
428 template<
typename _
floatT,
typename _detectorT>
429 int pyramidSensor<_floatT, _detectorT>::quadSz()
434 template<
typename _
floatT,
typename _detectorT>
435 void pyramidSensor<_floatT, _detectorT>::quadSz(
int sz)
437 if( _quadSz == sz)
return;
441 wfsImage.resize(2*_quadSz, 2*_quadSz);
445 template<
typename _
floatT,
typename _detectorT>
446 void pyramidSensor<_floatT, _detectorT>::makeTilts()
448 constexpr _floatT
pi = math::pi<_floatT>();
450 _floatT dang = 2*
pi/_modSteps;
453 tilts.resize(_modSteps);
455 std::cout <<
"WF Size: " << _wfSz <<
"\n";
456 std::cout <<
"WF PS: " << _wfPS <<
"\n";
457 std::cout <<
"Lambda: " << _lambda <<
"\n";
459 std::cout <<
"Pyr. PS: " << mx::fftPlateScale<floatT>(_wfSz, _wfPS, _lambda)*206265. <<
" (mas/pix)\n";
460 std::cout <<
"Mod rad: " << _modRadius * (_lambda/_D)/mx::fftPlateScale<floatT>(_wfSz, _wfPS, _lambda) <<
" (pixels)\n";
462 for(
int i=0; i < _modSteps; ++i)
464 dx = _modRadius * (_lambda/_D) / mx::fftPlateScale<floatT>(_wfSz, _wfPS, _lambda) * cos(0.5*dang+dang * i);
465 dy = _modRadius * (_lambda/_D) / mx::fftPlateScale<floatT>(_wfSz, _wfPS, _lambda) * sin(0.5*dang+dang * i);
467 tilts[i].resize(_wfSz, _wfSz);
468 tilts[i].set(std::complex<_floatT>(0,1));
476 template<
typename _
floatT,
typename _detectorT>
477 int pyramidSensor<_floatT, _detectorT>::iTime()
482 template<
typename _
floatT,
typename _detectorT>
483 void pyramidSensor<_floatT, _detectorT>::iTime(
int it)
487 std::cerr <<
"iTime must be >= 1. Correcting\n";
493 _wavefronts.resize(_iTime+2);
496 detector.expTime(_simStep*_iTime);
500 template<
typename _
floatT,
typename _detectorT>
501 int pyramidSensor<_floatT, _detectorT>::roTime()
506 template<
typename _
floatT,
typename _detectorT>
507 void pyramidSensor<_floatT, _detectorT>::roTime(
int rt)
511 std::cerr <<
"roTime must be >= 1. Correcting\n";
520 template<
typename _
floatT,
typename _detectorT>
521 _floatT pyramidSensor<_floatT, _detectorT>::simStep()
526 template<
typename _
floatT,
typename _detectorT>
527 void pyramidSensor<_floatT, _detectorT>::simStep(_floatT st)
532 detector.expTime(_simStep*_iTime);
538 template<
typename _
floatT,
typename _detectorT>
539 bool pyramidSensor<_floatT, _detectorT>::senseWavefront(wavefrontT & pupilPlane)
543 if(_lastWavefront >= _wavefronts.size()) _lastWavefront = 0;
544 _wavefronts[_lastWavefront].amplitude = pupilPlane.amplitude;
545 _wavefronts[_lastWavefront].phase = pupilPlane.phase;
564 if(_roTime_counter >= _roTime)
566 std::cerr <<
"PyWFS: reading\n";
567 detector.exposeImage(detectorImage, wfsImage);
568 ds9_interface_display_raw( &ds9i, 1, detectorImage.data(), detectorImage.rows(), detectorImage.cols(),1, mx::getFitsBITPIX<floatT>());
576 if( _iTime_counter >= _iTime)
578 std::cerr <<
"PyWFS: sensing\n";
592 template<
typename _
floatT,
typename _detectorT>
593 bool pyramidSensor<_floatT, _detectorT>::senseWavefrontCal(wavefrontT & pupilPlane)
598 _wavefronts[0].amplitude = pupilPlane.amplitude;
599 _wavefronts[0].phase = pupilPlane.phase;
601 _wavefronts[1].amplitude = pupilPlane.amplitude;
602 _wavefronts[1].phase = pupilPlane.phase;
606 detector.exposeImage(detectorImage, wfsImage);
614 template<
typename _
floatT,
typename _detectorT>
615 void pyramidSensor<_floatT, _detectorT>::doSenseWavefront()
617 constexpr _floatT
pi = math::pi<_floatT>();
619 if(tiltsMade ==
false) makeTilts();
625 wavefrontT pupilPlane;
628 int _firstWavefront = _lastWavefront - _iTime;
629 if(_firstWavefront < 0) _firstWavefront += _wavefronts.size();
631 pupilPlane.amplitude = _wavefronts[_firstWavefront].amplitude;
632 pupilPlane.phase = _wavefronts[_firstWavefront].phase;
637 for(
int i=0; i<_iTime; ++i)
640 if(_firstWavefront >= _wavefronts.size()) _firstWavefront = 0;
642 pupilPlane.amplitude += _wavefronts[_firstWavefront].amplitude;
643 pupilPlane.phase += _wavefronts[_firstWavefront].phase;
646 pupilPlane.amplitude /= (_iTime+1);
647 pupilPlane.phase /= (_iTime+1);
652 if(_modRadius == 0)
return doSenseWavefrontNoMod(pupilPlane);
657 wfsImage.resize(2*_quadSz, 2*_quadSz);
660 complexFieldT pupilPlaneCF;
661 pupilPlane.getWavefront(pupilPlaneCF, _wfSz);
663 complexFieldT focalPlaneCF;
664 focalPlaneCF.resize(_wfSz, _wfSz);
668 complexFieldT tiltedPlane;
669 complexFieldT focalPlane;
670 complexFieldT sensorPlane;
671 complexFieldT temp_ul;
672 complexFieldT temp_ur;
673 complexFieldT temp_ll;
674 complexFieldT temp_lr;
676 wfsImageT sensorImage;
678 tiltedPlane.resize(_wfSz, _wfSz);
679 focalPlane.resize(_wfSz, _wfSz);
680 sensorPlane.resize(_wfSz, _wfSz);
682 temp_ul.resize(_wfSz, _wfSz);
683 temp_ul.set((complexT)0);
685 temp_ur.resize(_wfSz, _wfSz);
686 temp_ur.set((complexT)0);
688 temp_ll.resize(_wfSz, _wfSz);
689 temp_ll.set((complexT)0);
691 temp_lr.resize(_wfSz, _wfSz);
692 temp_lr.set((complexT)0);
696 sensorImage.resize(_quadSz*2, _quadSz*2);
697 sensorImage.setZero();
699 int dSz = (0.5*_wfSz-0.5*_quadSz + 2*_quadSz) - _wfSz;
704 for(
int i=0; i < _modSteps; ++i)
706 int nelem = _wfSz*_wfSz;
708 complexT * tp_data = tiltedPlane.data();
709 complexT * pp_data = pupilPlaneCF.data();
710 complexT * ti_data = tilts[i].data();
712 for(
int ii=0; ii< nelem; ++ii)
714 tp_data[ii] = pp_data[ii]*ti_data[ii];
717 fi.propagatePupilToFocal(focalPlane, tiltedPlane);
718 temp_ul.set(complexT(0,0));
719 extractBlock(temp_ul, 0,0.5*_wfSz, 0, 0.5*_wfSz, focalPlane, 0, 0);
721 fi.propagateFocalToPupil(sensorPlane, temp_ul);
722 extractIntensityImageAccum(sensorImage, 0,2*_quadSz-dSz, 0,2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-0.5*_quadSz, 0.5*_wfSz-0.5*_quadSz);
724 temp_ur.set( complexT(0,0));
725 extractBlock(temp_ur, 0.5*_wfSz,0.5*_wfSz, 0, 0.5*_wfSz, focalPlane, 0.5*_wfSz, 0);
726 fi.propagateFocalToPupil(sensorPlane, temp_ur);
727 extractIntensityImageAccum(sensorImage, dSz,2*_quadSz-dSz, 0, 2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-1.5*_quadSz+dSz, 0.5*_wfSz-0.5*_quadSz);
729 temp_ll.set( complexT(0,0));
730 extractBlock(temp_ll, 0, 0.5*_wfSz, 0.5*_wfSz, 0.5*_wfSz, focalPlane, 0, 0.5*_wfSz);
731 fi.propagateFocalToPupil(sensorPlane, temp_ll);
732 extractIntensityImageAccum(sensorImage, 0,2*_quadSz-dSz, dSz, 2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-0.5*_quadSz, 0.5*_wfSz-1.5*_quadSz+dSz);
734 temp_lr.set( complexT(0,0));
735 extractBlock(temp_lr, 0.5*_wfSz,0.5*_wfSz, 0.5*_wfSz, 0.5*_wfSz, focalPlane, 0.5*_wfSz, 0.5*_wfSz);
736 fi.propagateFocalToPupil(sensorPlane, temp_lr);
737 extractIntensityImageAccum(sensorImage, dSz,2*_quadSz-dSz, dSz, 2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-1.5*_quadSz+dSz, 0.5*_wfSz-1.5*_quadSz+dSz);
750 wfsImage += sensorImage;
758 wfsImage /= _modSteps;
762 template<
typename _
floatT,
typename _detectorT>
763 void pyramidSensor<_floatT, _detectorT>::doSenseWavefrontNoMod(wavefrontT & pupilPlane)
765 constexpr _floatT
pi = math::pi<_floatT>();
770 wfsImage.resize(2*_quadSz, 2*_quadSz);
773 complexFieldT pupilPlaneCF;
774 pupilPlane.getWavefront(pupilPlaneCF, _wfSz);
776 complexFieldT focalPlaneCF;
777 focalPlaneCF.resize(_wfSz, _wfSz);
779 complexFieldT tiltedPlane;
780 complexFieldT focalPlane;
781 complexFieldT sensorPlane;
782 complexFieldT temp_ul;
783 complexFieldT temp_ur;
784 complexFieldT temp_ll;
785 complexFieldT temp_lr;
787 wfsImageT sensorImage;
789 tiltedPlane.resize(_wfSz, _wfSz);
790 focalPlane.resize(_wfSz, _wfSz);
791 sensorPlane.resize(_wfSz, _wfSz);
793 temp_ul.resize(_wfSz, _wfSz);
794 temp_ul.set((complexT)0);
796 temp_ur.resize(_wfSz, _wfSz);
797 temp_ur.set((complexT)0);
799 temp_ll.resize(_wfSz, _wfSz);
800 temp_ll.set((complexT)0);
802 temp_lr.resize(_wfSz, _wfSz);
803 temp_lr.set((complexT)0);
805 sensorImage.resize(_quadSz*2, _quadSz*2);
806 sensorImage.setZero();
808 int dSz = (0.5*_wfSz-0.5*_quadSz + 2*_quadSz) - _wfSz;
810 int nelem = _wfSz*_wfSz;
812 complexT * tp_data = tiltedPlane.data();
813 complexT * pp_data = pupilPlaneCF.data();
816 for(
int ii=0; ii< nelem; ++ii)
818 tp_data[ii] = pp_data[ii];
823 fi.propagatePupilToFocal(focalPlane, tiltedPlane);
824 temp_ul.set(complexT(0,0));
825 extractBlock(temp_ul, 0,0.5*_wfSz, 0, 0.5*_wfSz, focalPlane, 0, 0);
827 fi.propagateFocalToPupil(sensorPlane, temp_ul);
828 extractIntensityImageAccum(sensorImage, 0,2*_quadSz-dSz, 0,2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-0.5*_quadSz, 0.5*_wfSz-0.5*_quadSz);
830 temp_ur.set( complexT(0,0));
831 extractBlock(temp_ur, 0.5*_wfSz,0.5*_wfSz, 0, 0.5*_wfSz, focalPlane, 0.5*_wfSz, 0);
832 fi.propagateFocalToPupil(sensorPlane, temp_ur);
833 extractIntensityImageAccum(sensorImage, dSz,2*_quadSz-dSz, 0, 2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-1.5*_quadSz+dSz, 0.5*_wfSz-0.5*_quadSz);
835 temp_ll.set( complexT(0,0));
836 extractBlock(temp_ll, 0, 0.5*_wfSz, 0.5*_wfSz, 0.5*_wfSz, focalPlane, 0, 0.5*_wfSz);
837 fi.propagateFocalToPupil(sensorPlane, temp_ll);
838 extractIntensityImageAccum(sensorImage, 0,2*_quadSz-dSz, dSz, 2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-0.5*_quadSz, 0.5*_wfSz-1.5*_quadSz+dSz);
840 temp_lr.set( complexT(0,0));
841 extractBlock(temp_lr, 0.5*_wfSz,0.5*_wfSz, 0.5*_wfSz, 0.5*_wfSz, focalPlane, 0.5*_wfSz, 0.5*_wfSz);
842 fi.propagateFocalToPupil(sensorPlane, temp_lr);
843 extractIntensityImageAccum(sensorImage, dSz,2*_quadSz-dSz, dSz, 2*_quadSz-dSz, sensorPlane, 0.5*_wfSz-1.5*_quadSz+dSz, 0.5*_wfSz-1.5*_quadSz+dSz);
850 wfsImage += sensorImage;
constexpr T pi()
Get the value of pi.
void tiltWavefront(wavefrontT &complexWavefront, typename wavefrontT::Scalar::value_type xTilt, typename wavefrontT::Scalar::value_type yTilt)
Apply a tilt to a wavefront.