8 #ifndef __pyramidSensor_hpp__
9 #define __pyramidSensor_hpp__
12 #include "../../wfp/imagingUtils.hpp"
13 #include "../../wfp/fraunhoferPropagator.hpp"
14 #include "../../sys/timeUtils.hpp"
15 #include "../../ioutils/fits/fitsFile.hpp"
16 #include "../../improc/imageTransforms.hpp"
17 #include "../../math/constants.hpp"
19 #include "wavefront.hpp"
23 #define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
36 template<
typename _realT>
44 typedef Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
51 template<
typename _realT,
typename _detectorT>
58 typedef std::complex<realT> complexT;
61 typedef wavefront<realT> wavefrontT;
64 typedef wfp::imagingArray<std::complex<realT>, wfp::fftwAllocator<std::complex<realT> >, 0> complexFieldT;
69 typedef _detectorT detectorT;
86 std::vector<realT> m_wavelengths;
87 std::vector<realT> _wavelengthWeights;
115 realT m_modRadius {3.0};
117 realT m_effRad, m_rmsRad, m_bestRad, m_bestAng;
119 std::vector<realT> m_modShift_x;
120 std::vector<realT> m_modShift_y;
134 void perStep(realT prStp );
152 void modRadius(realT mR );
159 wfp::fraunhoferPropagator<complexFieldT> m_frProp;
161 bool m_opdMaskMade {
false};
162 complexFieldT m_opdMask;
164 bool m_tiltsMade {
false};
165 std::vector<complexFieldT> m_tilts;
167 bool m_preAllocated {
false};
168 complexFieldT m_pupilPlaneCF;
172 std::vector<complexFieldT> m_th_tiltedPlane;
174 std::vector<complexFieldT> m_th_focalPlane;
176 std::vector<typename wfsImageT<realT>::imageT> m_th_focalImage;
178 std::vector<complexFieldT> m_th_sensorPlane;
180 std::vector<typename wfsImageT<realT>::imageT> m_th_sensorImage;
189 std::vector<wavefrontT> _wavefronts;
202 wfsImageT<realT> detectorImage;
232 void detSize(
int nrows,
246 void lambda(realT l );
258 void roTime(
int rt );
264 void simStep(realT st );
266 template<
typename AOSysT>
267 void linkSystem(AOSysT & AOSys );
274 bool senseWavefront(wavefrontT & pupilPlane );
279 bool senseWavefrontCal(wavefrontT & pupilPlane );
294 void wfPS(realT ps );
325 void quadSz(
int sz );
328 template<
typename pupilT>
329 void makeRefTipImage( pupilT & pupil);
336 wfsImageT<realT> m_wfsImage;
338 wfsImageT<realT> wfsTipImage;
340 wfsImageT<realT> refTipImage;
346 void allocThreadMem();
351 void doSenseWavefront();
352 void doSenseWavefront(wavefrontT & );
353 void doSenseWavefrontNoMod(wavefrontT & );
359 template<
typename realT,
typename detectorT>
360 pyramidSensor<realT, detectorT>::pyramidSensor()
381 m_opdMaskMade =
false;
387 m_frProp.wholePixel(0);
391 template<
typename realT,
typename detectorT>
392 int pyramidSensor<realT, detectorT>::wfSz()
397 template<
typename realT,
typename detectorT>
398 void pyramidSensor<realT, detectorT>::wfSz(
int sz)
400 if( m_wfSz == sz)
return;
404 m_frProp.setWavefrontSizePixels(m_wfSz);
407 m_opdMaskMade =
false;
408 m_preAllocated =
false;
411 template<
typename realT,
typename detectorT>
412 int pyramidSensor<realT, detectorT>::detRows()
418 template<
typename realT,
typename detectorT>
419 int pyramidSensor<realT, detectorT>::detCols()
424 template<
typename realT,
typename detectorT>
425 void pyramidSensor<realT, detectorT>::detSize(
int nrows,
int ncols)
427 if( _detRows == nrows && _detCols == ncols)
return;
432 detector.setSize(_detRows, _detCols);
433 detectorImage.image.resize(_detRows, _detCols);
438 template<
typename realT,
typename detectorT>
439 realT pyramidSensor<realT, detectorT>::lambda()
444 template<
typename realT,
typename detectorT>
445 void pyramidSensor<realT, detectorT>::lambda(realT l)
452 if( m_wavelengths.size() == 0 )
454 m_wavelengths.resize(1, m_lambda);
455 _wavelengthWeights.resize(1, 1.0);
460 template<
typename realT,
typename detectorT>
461 template<
typename AOSysT>
462 void pyramidSensor<realT, detectorT>::linkSystem(AOSysT & AOSys)
464 AOSys.wfs.wfPS(AOSys.m_wfPS);
465 AOSys.wfs.D(AOSys._D);
469 template<
typename realT,
typename detectorT>
470 int pyramidSensor<realT, detectorT>::wfPS()
475 template<
typename realT,
typename detectorT>
476 void pyramidSensor<realT, detectorT>::wfPS(realT ps)
482 template<
typename realT,
typename detectorT>
483 realT pyramidSensor<realT, detectorT>::D()
488 template<
typename realT,
typename detectorT>
489 void pyramidSensor<realT, detectorT>::D(realT d)
494 template<
typename realT,
typename detectorT>
495 realT pyramidSensor<realT, detectorT>::perStep()
500 template<
typename realT,
typename detectorT>
501 void pyramidSensor<realT, detectorT>::perStep(realT prStp)
511 realT radPerStep = m_perStep/m_modRadius;
515 while( math::half_pi<realT>()/m_modSteps > radPerStep ) ++m_modSteps;
521 template<
typename realT,
typename detectorT>
522 int pyramidSensor<realT, detectorT>::modSteps()
527 template<
typename realT,
typename detectorT>
528 realT pyramidSensor<realT, detectorT>::modRadius()
533 template<
typename realT,
typename detectorT>
534 void pyramidSensor<realT, detectorT>::modRadius(realT mR)
543 template<
typename realT,
typename detectorT>
544 int pyramidSensor<realT, detectorT>::quadSz()
549 template<
typename realT,
typename detectorT>
550 void pyramidSensor<realT, detectorT>::quadSz(
int sz)
552 if( m_quadSz == sz)
return;
556 m_wfsImage.image.resize(2*m_quadSz, 2*m_quadSz);
558 m_opdMaskMade =
false;
559 m_preAllocated =
false;
562 template<
typename realT,
typename detectorT>
563 template<
typename pupilT>
564 void pyramidSensor<realT, detectorT>::makeRefTipImage(pupilT & pupil)
567 currWF.setAmplitude( pupil );
568 currWF.setPhase( pupil*0 );
570 refTipImage.image.resize(0,0);
572 senseWavefrontCal(currWF);
574 refTipImage = wfsTipImage;
578 template<
typename realT,
typename detectorT>
579 void pyramidSensor<realT, detectorT>::makeOpdMask()
581 complexFieldT opdMaskQ;
583 m_opdMask.resize(m_wfSz, m_wfSz);
584 opdMaskQ.resize( m_wfSz, m_wfSz);
587 realT shift = 0.5*(m_quadSz);
589 opdMaskQ.set(std::complex<realT>(0,1));
591 wfp::extractBlock(m_opdMask, 0, 0.5*m_wfSz, 0, 0.5*m_wfSz, opdMaskQ, 0 , 0);
593 opdMaskQ.set(std::complex<realT>(0,1));
595 wfp::extractBlock(m_opdMask, 0.5*m_wfSz, 0.5*m_wfSz, 0.5*m_wfSz, 0.5*m_wfSz-1, opdMaskQ, 0.5*m_wfSz, 0.5*m_wfSz);
597 opdMaskQ.set(std::complex<realT>(0,1));
599 wfp::extractBlock(m_opdMask, 0, 0.5*m_wfSz, 0.5*m_wfSz, 0.5*m_wfSz, opdMaskQ, 0 , 0.5*m_wfSz);
601 opdMaskQ.set(std::complex<realT>(0,1));
603 wfp::extractBlock(m_opdMask, 0.5*m_wfSz, 0.5*m_wfSz, 0, 0.5*m_wfSz, opdMaskQ, 0.5*m_wfSz, 0);
611 m_opdMaskMade =
true;
616 template <
typename realT,
typename detectorT>
617 void pyramidSensor<realT, detectorT>::makeTilts()
619 constexpr realT
pi = math::pi<realT>();
621 realT dang = 2 *
pi / (m_modSteps);
624 m_tilts.resize(m_modSteps);
626 std::cout <<
"WF Size: " << m_wfSz <<
"\n";
627 std::cout <<
"WF PS: " << m_wfPS <<
"\n";
628 std::cout <<
"Lambda: " << m_lambda <<
"\n";
629 std::cout <<
"Pyr. PS: " << wfp::fftPlateScale<realT>(m_wfSz, m_wfPS, m_lambda) * 206265. <<
" (mas/pix)\n";
630 std::cout <<
"Mod. steps: " << m_modSteps <<
"\n";
631 std::cout <<
"Mod rad: " << m_modRadius * (m_lambda / _D) / wfp::fftPlateScale<realT>(m_wfSz, m_wfPS, m_lambda) <<
" (pixels)\n";
633 for (
int i = 0; i < m_modSteps; ++i)
635 dx = m_modRadius * (m_lambda / _D) / wfp::fftPlateScale<realT>(m_wfSz, m_wfPS, m_lambda) * cos(0.0 * dang + dang * i);
636 dy = m_modRadius * (m_lambda / _D) / wfp::fftPlateScale<realT>(m_wfSz, m_wfPS, m_lambda) * sin(0.0 * dang + dang * i);
638 m_tilts[i].resize(m_wfSz, m_wfSz);
639 m_tilts[i].set(std::complex<realT>(0, 1));
647 template<
typename realT,
typename detectorT>
648 void pyramidSensor<realT, detectorT>::allocThreadMem()
650 m_pupilPlaneCF.resize(m_wfSz, m_wfSz);
652 int maxTh = omp_get_max_threads();
653 m_th_tiltedPlane.resize(maxTh);
655 m_th_focalPlane.resize(maxTh);
657 m_th_focalImage.resize(maxTh);
659 m_th_sensorPlane.resize(maxTh);
661 m_th_sensorImage.resize(maxTh);
663 for(
int nTh=0;nTh<maxTh; ++nTh)
665 m_th_tiltedPlane[nTh].resize(m_wfSz, m_wfSz);
667 m_th_focalPlane[nTh].resize(m_wfSz, m_wfSz);
669 m_th_focalImage[nTh].resize(m_wfSz, m_wfSz);
671 m_th_sensorPlane[nTh].resize(m_wfSz, m_wfSz);
673 m_th_sensorImage[nTh].resize(m_quadSz*2, m_quadSz*2);
676 m_preAllocated =
true;
679 template<
typename realT,
typename detectorT>
680 void pyramidSensor<realT, detectorT>::preAllocate()
687 template<
typename realT,
typename detectorT>
688 int pyramidSensor<realT, detectorT>::iTime()
693 template<
typename realT,
typename detectorT>
694 void pyramidSensor<realT, detectorT>::iTime(
int it)
698 std::cerr <<
"iTime must be >= 1. Correcting\n";
704 _wavefronts.resize(_iTime+2);
707 detector.expTime(_simStep*_iTime);
711 template<
typename realT,
typename detectorT>
712 int pyramidSensor<realT, detectorT>::roTime()
717 template<
typename realT,
typename detectorT>
718 void pyramidSensor<realT, detectorT>::roTime(
int rt)
722 std::cerr <<
"roTime must be >= 1. Correcting\n";
731 template<
typename realT,
typename detectorT>
732 realT pyramidSensor<realT, detectorT>::simStep()
737 template<
typename realT,
typename detectorT>
738 void pyramidSensor<realT, detectorT>::simStep(realT st)
743 detector.expTime(_simStep*_iTime);
749 template<
typename realT,
typename detectorT>
750 bool pyramidSensor<realT, detectorT>::senseWavefront(wavefrontT & pupilPlane)
754 if(_lastWavefront >= _wavefronts.size()) _lastWavefront = 0;
755 _wavefronts[_lastWavefront].amplitude = pupilPlane.amplitude;
756 _wavefronts[_lastWavefront].phase = pupilPlane.phase;
757 _wavefronts[_lastWavefront].iterNo = pupilPlane.iterNo;
775 if(_roTime_counter >= _roTime)
777 detector.exposeImage(detectorImage.image, m_wfsImage.image);
779 detectorImage.tipImage = wfsTipImage.image;
780 detectorImage.iterNo = m_wfsImage.iterNo;
788 if( _iTime_counter >= _iTime)
803 template<
typename realT,
typename detectorT>
804 bool pyramidSensor<realT, detectorT>::senseWavefrontCal(wavefrontT & pupilPlane)
809 _wavefronts[0].amplitude = pupilPlane.amplitude;
810 _wavefronts[0].phase = pupilPlane.phase;
812 _wavefronts[1].amplitude = pupilPlane.amplitude;
813 _wavefronts[1].phase = pupilPlane.phase;
822 detector.exposeImage(detectorImage.image, m_wfsImage.image);
825 detectorImage.tipImage = wfsTipImage.image;
832 template<
typename realT,
typename detectorT>
833 void pyramidSensor<realT, detectorT>::doSenseWavefront()
837 wavefrontT pupilPlane;
840 int _firstWavefront = _lastWavefront - _iTime;
841 if(_firstWavefront < 0) _firstWavefront += _wavefronts.size();
843 pupilPlane.amplitude = _wavefronts[_firstWavefront].amplitude;
844 pupilPlane.phase = _wavefronts[_firstWavefront].phase;
846 realT avgIt = _wavefronts[_firstWavefront].iterNo;
850 for(
int i=0; i<_iTime; ++i)
853 if( (
size_t) _firstWavefront >= _wavefronts.size()) _firstWavefront = 0;
855 pupilPlane.amplitude += _wavefronts[_firstWavefront].amplitude;
856 pupilPlane.phase += _wavefronts[_firstWavefront].phase;
857 avgIt += _wavefronts[_firstWavefront].iterNo;
862 pupilPlane.amplitude /= (_iTime+1);
863 pupilPlane.phase /= (_iTime+1);
865 avgIt /= (_iTime + 1.0);
868 doSenseWavefront(pupilPlane);
870 m_wfsImage.iterNo = avgIt;
873 template<
typename realT,
typename detectorT>
874 void pyramidSensor<realT, detectorT>::doSenseWavefront(wavefrontT & pupilPlane)
876 if(m_modRadius == 0)
return doSenseWavefrontNoMod(pupilPlane);
878 if(!m_preAllocated) preAllocate();
882 m_wfsImage.image.resize(2*m_quadSz, 2*m_quadSz);
883 m_wfsImage.image.setZero();
885 wfsTipImage.image.resize(m_wfSz, m_wfSz);
886 wfsTipImage.image.setZero();
888 for(
size_t l = 0; l<m_wavelengths.size(); ++l)
890 pupilPlane.lambda = m_lambda;
891 pupilPlane.getWavefront(m_pupilPlaneCF, m_wavelengths[l], m_wfSz);
895 int nTh = omp_get_thread_num();
897 m_th_sensorImage[nTh].setZero();
898 m_th_focalImage[nTh].setZero();
906 pp_data = m_pupilPlaneCF.data();
907 tp_data = m_th_tiltedPlane[nTh].data();
908 fp_data = m_th_focalPlane[nTh].data();
909 opd_data = m_opdMask.data();
911 int nelem = m_wfSz*m_wfSz;
914 for(
int i=0; i < m_modSteps; ++i)
917 ti_data = m_tilts[i].data();
922 for(
int ii=0; ii< nelem; ++ii)
924 tp_data[ii] = pp_data[ii]*ti_data[ii];
931 m_frProp.propagatePupilToFocal(m_th_focalPlane[nTh], m_th_tiltedPlane[nTh],
true);
936 wfp::extractIntensityImageAccum(m_th_focalImage[nTh], 0, m_wfSz, 0, m_wfSz, m_th_focalPlane[nTh], 0, 0);
940 for(
int ii=0; ii< nelem; ++ii)
942 fp_data[ii] = fp_data[ii]*opd_data[ii];
948 m_frProp.propagateFocalToPupil(m_th_sensorPlane[nTh], m_th_focalPlane[nTh],
true);
953 wfp::extractIntensityImageAccum(m_th_sensorImage[nTh], 0, 2*m_quadSz, 0, 2*m_quadSz, m_th_sensorPlane[nTh],
954 0.5*m_wfSz-m_quadSz, 0.5*m_wfSz-m_quadSz);
962 m_wfsImage.image += m_th_sensorImage[nTh] * _wavelengthWeights[l];
963 wfsTipImage.image += m_th_focalImage[nTh] * _wavelengthWeights[l];
972 m_wfsImage.image /= m_modSteps;
973 wfsTipImage.image /= m_modSteps;
978 template<
typename realT,
typename detectorT>
979 void pyramidSensor<realT, detectorT>::doSenseWavefrontNoMod(wavefrontT & pupilPlane)
983 m_wfsImage.image.resize(2*m_quadSz, 2*m_quadSz);
984 m_wfsImage.image.setZero();
986 complexFieldT m_pupilPlaneCF;
988 pupilPlane.getWavefront(m_pupilPlaneCF, m_wfSz);
990 if(!m_opdMaskMade) makeOpdMask();
992 complexFieldT tiltedPlane;
993 complexFieldT focalPlane;
994 complexFieldT sensorPlane;
996 tiltedPlane.resize(m_wfSz, m_wfSz);
997 focalPlane.resize(m_wfSz, m_wfSz);
998 sensorPlane.resize(m_wfSz, m_wfSz);
1000 int nelem = m_wfSz*m_wfSz;
1002 complexT * tp_data = tiltedPlane.data();
1003 complexT * pp_data = m_pupilPlaneCF.data();
1004 complexT * opd_data = m_opdMask.data();
1005 complexT * fp_data = focalPlane.data();
1012 for(
int ii=0; ii< nelem; ++ii)
1014 tp_data[ii] = pp_data[ii];
1022 m_frProp.propagatePupilToFocal(focalPlane, tiltedPlane,
true);
1030 for(
int ii=0; ii< nelem; ++ii)
1032 fp_data[ii] = fp_data[ii]*opd_data[ii];
1041 m_frProp.propagateFocalToPupil(sensorPlane, focalPlane,
true);
1048 wfp::extractIntensityImageAccum(m_wfsImage.image, 0, 2*m_quadSz, 0, 2*m_quadSz, sensorPlane, 0.5*m_wfSz-m_quadSz, 0.5*m_wfSz-m_quadSz);
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.