mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
pyramidSensorSepQuad.hpp
Go to the documentation of this file.
1/** \file
2 * \author Jared R. Males (jaredmales@gmail.com)
3 * \brief
4 * \ingroup mxAO_sim_files
5 *
6 */
7
8#ifndef __pyramidSensor_hpp__
9#define __pyramidSensor_hpp__
10
11#include "mx/imagingUtils.hpp"
12#include "mx/fraunhoferImager.hpp"
13#include "mx/timeUtils.hpp"
14#include "mx/fitsFile.hpp"
15// #include "mx/ds9_interface.h"
16#include "../../math/constants.hpp"
17
18#include "wavefront.hpp"
19
20#include "mx/imageTransforms.hpp"
21
22#ifdef DEBUG
23#define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
24#else
25#define BREAD_CRUMB
26#endif
27
28namespace mx
29{
30namespace AO
31{
32namespace sim
33{
34
35template <typename _floatT, typename _detectorT>
36class pyramidSensor
37{
38 public:
39 typedef _floatT floatT;
40
41 typedef std::complex<floatT> complexT;
42
43 /// The wavefront data type
44 typedef wavefront<floatT> wavefrontT;
45
46 /// The wavefront complex field type
47 typedef mx::imagingArray<std::complex<floatT>, fftwAllocator<std::complex<floatT>>, 0> complexFieldT;
48
49 /// The wavefront sensor detector image type
50 typedef Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> wfsImageT;
51
52 typedef _detectorT detectorT;
53
54 protected:
55 /* Standard WFS Interface: */
56 int _wfSz; ///< Size of the wavefront in pixels
57
58 int _detRows; ///< The number of rows of the WFS detector. After forming the image the WFS detector plane is
59 ///< re-binned to this.
60 int _detCols; ///< The number of columns of the WFS detector. After forming the image the WFS detector plane is
61 ///< re-binned to this.
62
63 floatT _lambda; ///< Central wavelength, in meters
64
65 int _iTime; ///< Integration time in loop steps
66
67 int _roTime; ///< Readout time in loop steps
68
69 floatT _simStep; ///< The simulation stepsize in seconds.
70
71 /* PyWFS Specific: */
72
73 floatT _wfPS; ///< Wavefront pixel scale, in meters/pixel
74
75 floatT _D; ///< Telescope diameter, in meters
76
77 int _modSteps; ///< Number of steps in the modulation simulation
78
79 floatT _modRadius; ///< Radius of the modulation in pixels
80
81 int _quadSz; ///< The size of the PyWFS quadrant
82
83 mx::fraunhoferImager<complexFieldT> fi;
84
85 bool tiltsMade;
86 std::vector<complexFieldT> tilts;
87
88 int _iTime_counter;
89
90 int _reading;
91
92 int _roTime_counter;
93
94 std::vector<wavefrontT> _wavefronts;
95
96 int _lastWavefront;
97
98 ds9_interface ds9i;
99
100 public:
101 /// Default c'tor
102 pyramidSensor();
103
104 /* The standard WFS interface: */
105
106 detectorT detector;
107
108 /// The image on the detector, resized from wfsImage
109 wfsImageT detectorImage;
110
111 /// Get the wavefront size in pixels
112 /**
113 * \returns the wavefront size in pixels
114 */
115 int wfSz();
116
117 /// Set the wavefront size in pixels.
118 /**
119 * \param sz is the new size
120 */
121 void wfSz( int sz );
122
123 /// Get the detector rows in pixels
124 /**
125 * \returns _detRows
126 */
127 int detRows();
128
129 /// Get the detector columns in pixels
130 /**
131 * \returns _detCols
132 */
133 int detCols();
134
135 /// Set the detector columns in pixels.
136 /**
137 * \param sz is the new size
138 */
139 void detSize( int nrows, int ncols );
140
141 /// Get the PyWFS central wavelength
142 /**
143 * \returns the central wavelength in meters
144 */
145 floatT lambda();
146
147 /// Set the PyWFS central wavelength
148 /**
149 * \param d is the new central wavelength in meters
150 */
151 void lambda( floatT l );
152
153 /// Get the PyWFS integration time, in time steps
154 int iTime();
155
156 /// Set the PyWFS integration time, in time steps
157 void iTime( int it );
158
159 /// Get the PyWFS detector readout time, in time steps
160 int roTime();
161
162 /// Set the PyWFS detector readout time, in time steps
163 void roTime( int rt );
164
165 /// Get the simulation step-size, in seconds.
166 floatT simStep();
167
168 /// Set the simulation step-size, in seconds.
169 void simStep( floatT st );
170
171 template <typename AOSysT>
172 void linkSystem( AOSysT &AOSys );
173
174 /// Sense the wavefront aberrations
175 /** Returns true if a new wavefront measurement is ready.
176 * Retruns false if still integrating.
177 */
178 bool senseWavefront( wavefrontT &pupilPlane );
179
180 /// Sense the wavefront aberrations in a calibration mode
181 /** Allows for faster calibrations.
182 */
183 bool senseWavefrontCal( wavefrontT &pupilPlane );
184
185 /* The PyWFS Specific Interface */
186
187 /// Get the wavefront pixel scale in meters per pixel
188 /**
189 * \returns the wavefront pixel scale in meters/pixel
190 */
191 int wfPS();
192
193 /// Set the wavefront pixel scale in meters per pixel
194 /**
195 * \param ps is the pixel scale
196 */
197 void wfPS( floatT ps );
198
199 /// Get the telescope diameter
200 /**
201 * \returns the telescope diameter in meters
202 */
203 floatT D();
204
205 /// Set the telescope diameter
206 /**
207 * \param d is the new size in meters
208 */
209 void D( floatT d );
210
211 /// Get the number of modulation steps
212 /**
213 * \returns _modSteps;
214 */
215 int modSteps();
216
217 /// Set the number of modulation steps
218 /**
219 * \param mSt is the new number of modulation steps
220 */
221 void modSteps( int mSt );
222
223 /// Get the radius of modulation
224 /**
225 * \returns _modRadius;
226 */
227 floatT modRadius();
228
229 /// Set the modulation radius
230 /**
231 * \param mR is the new modulation radius in lambda/D
232 */
233 void modRadius( floatT mR );
234
235 /// Get the quadrant size in pixels
236 /** This is the size of the quadrant in un-binned wavefront space
237 *
238 *
239 * \returns _quadSz
240 */
241 int quadSz();
242
243 /// Set the quadrant size in pixels.
244 /** This is the size of the quadrant in un-binned wavefront space
245 * It should be at least the size of the Pupil. Make larger than the pupil
246 * to have smaller pupil images on the PyWFS detector.
247 *
248 * \param sz is the new size
249 */
250 void quadSz( int sz );
251
252 protected:
253 /// The image formed by the WFS
254 wfsImageT wfsImage;
255
256 void makeTilts();
257
258 void doSenseWavefront();
259 void doSenseWavefrontNoMod( wavefrontT & );
260
261 bool firstRun;
262};
263
264template <typename _floatT, typename _detectorT>
265pyramidSensor<_floatT, _detectorT>::pyramidSensor()
266{
267 _wfSz = 0;
268 _detRows = 0;
269 _detCols = 0;
270 _lambda = 0;
271
272 _modSteps = 16;
273 _modRadius = 16;
274
275 iTime( 1 );
276 _iTime_counter = 0;
277
278 _reading = 0;
279 _roTime = 1;
280 _roTime_counter = 0;
281
282 _simStep = 0.001;
283
284 tiltsMade = false;
285
286 firstRun = true;
287
288 ds9_interface_init( &ds9i );
289 ds9_interface_set_title( &ds9i, "PyWFS" );
290}
291
292template <typename _floatT, typename _detectorT>
293int pyramidSensor<_floatT, _detectorT>::wfSz()
294{
295 return _wfSz;
296}
297
298template <typename _floatT, typename _detectorT>
299void pyramidSensor<_floatT, _detectorT>::wfSz( int sz )
300{
301 if( _wfSz == sz )
302 return;
303
304 _wfSz = sz;
305
306 fi.setWavefrontSizePixels( _wfSz );
307
308 tiltsMade = false;
309}
310
311template <typename _floatT, typename _detectorT>
312int pyramidSensor<_floatT, _detectorT>::detRows()
313{
314 return _detRows;
315}
316
317template <typename _floatT, typename _detectorT>
318int pyramidSensor<_floatT, _detectorT>::detCols()
319{
320 return _detCols;
321}
322
323template <typename _floatT, typename _detectorT>
324void pyramidSensor<_floatT, _detectorT>::detSize( int nrows, int ncols )
325{
326 if( _detRows == nrows && _detCols == ncols )
327 return;
328
329 _detRows = nrows;
330 _detCols = ncols;
331
332 detector.setSize( _detRows, _detCols );
333 detectorImage.resize( _detRows, _detCols );
334}
335
336template <typename _floatT, typename _detectorT>
337_floatT pyramidSensor<_floatT, _detectorT>::lambda()
338{
339 return _lambda;
340}
341
342template <typename _floatT, typename _detectorT>
343void pyramidSensor<_floatT, _detectorT>::lambda( _floatT l )
344{
345 _lambda = l;
346}
347
348template <typename _floatT, typename _detectorT>
349template <typename AOSysT>
350void pyramidSensor<_floatT, _detectorT>::linkSystem( AOSysT &AOSys )
351{
352 AOSys.wfs.wfPS( AOSys._wfPS );
353 AOSys.wfs.D( AOSys._D );
354}
355
356template <typename _floatT, typename _detectorT>
357int pyramidSensor<_floatT, _detectorT>::wfPS()
358{
359 return _wfPS;
360}
361
362template <typename _floatT, typename _detectorT>
363void pyramidSensor<_floatT, _detectorT>::wfPS( _floatT ps )
364{
365 _wfPS = ps;
366}
367
368template <typename _floatT, typename _detectorT>
369_floatT pyramidSensor<_floatT, _detectorT>::D()
370{
371 return _D;
372}
373
374template <typename _floatT, typename _detectorT>
375void pyramidSensor<_floatT, _detectorT>::D( _floatT d )
376{
377 _D = d;
378}
379
380template <typename _floatT, typename _detectorT>
381int pyramidSensor<_floatT, _detectorT>::modSteps()
382{
383 return _modSteps;
384}
385
386template <typename _floatT, typename _detectorT>
387void pyramidSensor<_floatT, _detectorT>::modSteps( int mSt )
388{
389 _modSteps = mSt;
390
391 tiltsMade = false;
392}
393
394template <typename _floatT, typename _detectorT>
395_floatT pyramidSensor<_floatT, _detectorT>::modRadius()
396{
397 return _modRadius; // * mx::fftPlateScale(_wfSz, _wfPS, _lambda)/(_lambda/D);
398}
399
400template <typename _floatT, typename _detectorT>
401void pyramidSensor<_floatT, _detectorT>::modRadius( _floatT mR )
402{
403 _modRadius = mR; // (_lambda/D)/mx::fftPlateScale(_wfSz, _wfPS, _lambda);
404
405 tiltsMade = false;
406}
407
408template <typename _floatT, typename _detectorT>
409int pyramidSensor<_floatT, _detectorT>::quadSz()
410{
411 return _quadSz;
412}
413
414template <typename _floatT, typename _detectorT>
415void pyramidSensor<_floatT, _detectorT>::quadSz( int sz )
416{
417 if( _quadSz == sz )
418 return;
419
420 _quadSz = sz;
421
422 wfsImage.resize( 2 * _quadSz, 2 * _quadSz );
423}
424
425template <typename _floatT, typename _detectorT>
426void pyramidSensor<_floatT, _detectorT>::makeTilts()
427{
428 constexpr _floatT pi = math::pi<_floatT>();
429
430 _floatT dang = 2 * pi / _modSteps;
431 _floatT dx, dy;
432
433 tilts.resize( _modSteps );
434
435 std::cout << "WF Size: " << _wfSz << "\n";
436 std::cout << "WF PS: " << _wfPS << "\n";
437 std::cout << "Lambda: " << _lambda << "\n";
438
439 std::cout << "Pyr. PS: " << mx::fftPlateScale<floatT>( _wfSz, _wfPS, _lambda ) * 206265. << " (mas/pix)\n";
440 std::cout << "Mod rad: " << _modRadius * ( _lambda / _D ) / mx::fftPlateScale<floatT>( _wfSz, _wfPS, _lambda )
441 << " (pixels)\n";
442
443 for( int i = 0; i < _modSteps; ++i )
444 {
445 dx = _modRadius * ( _lambda / _D ) / mx::fftPlateScale<floatT>( _wfSz, _wfPS, _lambda ) *
446 cos( 0.5 * dang + dang * i );
447 dy = _modRadius * ( _lambda / _D ) / mx::fftPlateScale<floatT>( _wfSz, _wfPS, _lambda ) *
448 sin( 0.5 * dang + dang * i );
449
450 tilts[i].resize( _wfSz, _wfSz );
451 tilts[i].set( std::complex<_floatT>( 0, 1 ) );
452
453 tiltWavefront( tilts[i], dx, dy );
454 }
455
456 tiltsMade = true;
457}
458
459template <typename _floatT, typename _detectorT>
460int pyramidSensor<_floatT, _detectorT>::iTime()
461{
462 return _iTime;
463}
464
465template <typename _floatT, typename _detectorT>
466void pyramidSensor<_floatT, _detectorT>::iTime( int it )
467{
468 if( it < 1 )
469 {
470 std::cerr << "iTime must be >= 1. Correcting\n";
471 it = 1;
472 }
473
474 _iTime = it;
475
476 _wavefronts.resize( _iTime + 2 );
477 _lastWavefront = -1;
478
479 detector.expTime( _simStep * _iTime );
480}
481
482template <typename _floatT, typename _detectorT>
483int pyramidSensor<_floatT, _detectorT>::roTime()
484{
485 return roTime;
486}
487
488template <typename _floatT, typename _detectorT>
489void pyramidSensor<_floatT, _detectorT>::roTime( int rt )
490{
491 if( rt < 1 )
492 {
493 std::cerr << "roTime must be >= 1. Correcting\n";
494 rt = 1;
495 }
496
497 _roTime = rt;
498}
499
500template <typename _floatT, typename _detectorT>
501_floatT pyramidSensor<_floatT, _detectorT>::simStep()
502{
503 return simStep;
504}
505
506template <typename _floatT, typename _detectorT>
507void pyramidSensor<_floatT, _detectorT>::simStep( _floatT st )
508{
509
510 _simStep = st;
511
512 detector.expTime( _simStep * _iTime );
513}
514
515template <typename _floatT, typename _detectorT>
516bool pyramidSensor<_floatT, _detectorT>::senseWavefront( wavefrontT &pupilPlane )
517{
518
519 ++_lastWavefront;
520 if( _lastWavefront >= _wavefronts.size() )
521 _lastWavefront = 0;
522 _wavefronts[_lastWavefront].amplitude = pupilPlane.amplitude;
523 _wavefronts[_lastWavefront].phase = pupilPlane.phase;
524
525 // Always skip the first one for averaging to center of iTime.
526 if( firstRun )
527 {
528 firstRun = false;
529 return false;
530 }
531
532 ++_iTime_counter;
533
534 bool rv = false;
535
536 if( _reading )
537 {
538 ++_roTime_counter;
539
540 if( _roTime_counter >= _roTime )
541 {
542 std::cerr << "PyWFS: reading\n";
543 detector.exposeImage( detectorImage, wfsImage );
544 ds9_interface_display_raw( &ds9i,
545 1,
546 detectorImage.data(),
547 detectorImage.rows(),
548 detectorImage.cols(),
549 1,
550 mx::getFitsBITPIX<floatT>() );
551
552 _roTime_counter = 0;
553 _reading = 0;
554 rv = true;
555 }
556 }
557
558 if( _iTime_counter >= _iTime )
559 {
560 std::cerr << "PyWFS: sensing\n";
561 doSenseWavefront();
562 _iTime_counter = 0;
563
564 _reading = 1;
565 _roTime_counter = 0;
566 }
567
568 return rv;
569}
570
571template <typename _floatT, typename _detectorT>
572bool pyramidSensor<_floatT, _detectorT>::senseWavefrontCal( wavefrontT &pupilPlane )
573{
574
575 _lastWavefront = 1;
576
577 _wavefronts[0].amplitude = pupilPlane.amplitude;
578 _wavefronts[0].phase = pupilPlane.phase;
579
580 _wavefronts[1].amplitude = pupilPlane.amplitude;
581 _wavefronts[1].phase = pupilPlane.phase;
582
583 doSenseWavefront();
584
585 detector.exposeImage( detectorImage, wfsImage );
586
587 // ds9_interface_display_raw( &ds9i, 1, detectorImage.data(), detectorImage.rows(), detectorImage.cols(),1,
588 // mx::getFitsBITPIX<floatT>());
589
590 return true;
591}
592
593template <typename _floatT, typename _detectorT>
594void pyramidSensor<_floatT, _detectorT>::doSenseWavefront()
595{
596 constexpr _floatT pi = math::pi<_floatT>();
597
598 if( tiltsMade == false )
599 makeTilts();
600
601 // std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
602 BREAD_CRUMB;
603
604 wavefrontT pupilPlane;
605
606 /* Here make average wavefront for now */
607 int _firstWavefront = _lastWavefront - _iTime;
608 if( _firstWavefront < 0 )
609 _firstWavefront += _wavefronts.size();
610
611 pupilPlane.amplitude = _wavefronts[_firstWavefront].amplitude;
612 pupilPlane.phase = _wavefronts[_firstWavefront].phase;
613
614 // std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
615 BREAD_CRUMB;
616
617 for( int i = 0; i < _iTime; ++i )
618 {
619 ++_firstWavefront;
620 if( _firstWavefront >= _wavefronts.size() )
621 _firstWavefront = 0;
622
623 pupilPlane.amplitude += _wavefronts[_firstWavefront].amplitude;
624 pupilPlane.phase += _wavefronts[_firstWavefront].phase;
625 }
626
627 pupilPlane.amplitude /= ( _iTime + 1 );
628 pupilPlane.phase /= ( _iTime + 1 );
629
630 /*=====================================*/
631
632 if( _modRadius == 0 )
633 return doSenseWavefrontNoMod( pupilPlane );
634
635 // std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
636 BREAD_CRUMB;
637
638 wfsImage.resize( 2 * _quadSz, 2 * _quadSz );
639 wfsImage.setZero();
640
641 complexFieldT pupilPlaneCF;
642 pupilPlane.getWavefront( pupilPlaneCF, _wfSz );
643
644 complexFieldT focalPlaneCF;
645 focalPlaneCF.resize( _wfSz, _wfSz );
646
647#pragma omp parallel
648 {
649 complexFieldT tiltedPlane;
650 complexFieldT focalPlane;
651 complexFieldT sensorPlane;
652 complexFieldT temp_ul;
653 complexFieldT temp_ur;
654 complexFieldT temp_ll;
655 complexFieldT temp_lr;
656
657 wfsImageT sensorImage;
658
659 tiltedPlane.resize( _wfSz, _wfSz );
660 focalPlane.resize( _wfSz, _wfSz );
661 sensorPlane.resize( _wfSz, _wfSz );
662
663 temp_ul.resize( _wfSz, _wfSz );
664 temp_ul.set( (complexT)0 );
665
666 temp_ur.resize( _wfSz, _wfSz );
667 temp_ur.set( (complexT)0 );
668
669 temp_ll.resize( _wfSz, _wfSz );
670 temp_ll.set( (complexT)0 );
671
672 temp_lr.resize( _wfSz, _wfSz );
673 temp_lr.set( (complexT)0 );
674
675 // sensorImage.resize(_wfSz, _wfSz);
676 sensorImage.resize( _quadSz * 2, _quadSz * 2 );
677 sensorImage.setZero();
678
679 int dSz = ( 0.5 * _wfSz - 0.5 * _quadSz + 2 * _quadSz ) - _wfSz;
680 if( dSz < 0 )
681 dSz = 0;
682
683#pragma omp for
684 for( int i = 0; i < _modSteps; ++i )
685 {
686 int nelem = _wfSz * _wfSz;
687
688 complexT *tp_data = tiltedPlane.data();
689 complexT *pp_data = pupilPlaneCF.data();
690 complexT *ti_data = tilts[i].data();
691
692 for( int ii = 0; ii < nelem; ++ii )
693 {
694 tp_data[ii] = pp_data[ii] * ti_data[ii];
695 }
696
697 fi.propagatePupilToFocal( focalPlane, tiltedPlane );
698 temp_ul.set( complexT( 0, 0 ) );
699 extractBlock( temp_ul, 0, 0.5 * _wfSz, 0, 0.5 * _wfSz, focalPlane, 0, 0 );
700
701 fi.propagateFocalToPupil( sensorPlane, temp_ul );
702 extractIntensityImageAccum( sensorImage,
703 0,
704 2 * _quadSz - dSz,
705 0,
706 2 * _quadSz - dSz,
707 sensorPlane,
708 0.5 * _wfSz - 0.5 * _quadSz,
709 0.5 * _wfSz - 0.5 * _quadSz );
710
711 temp_ur.set( complexT( 0, 0 ) );
712 extractBlock( temp_ur, 0.5 * _wfSz, 0.5 * _wfSz, 0, 0.5 * _wfSz, focalPlane, 0.5 * _wfSz, 0 );
713 fi.propagateFocalToPupil( sensorPlane, temp_ur );
714 extractIntensityImageAccum( sensorImage,
715 dSz,
716 2 * _quadSz - dSz,
717 0,
718 2 * _quadSz - dSz,
719 sensorPlane,
720 0.5 * _wfSz - 1.5 * _quadSz + dSz,
721 0.5 * _wfSz - 0.5 * _quadSz );
722
723 temp_ll.set( complexT( 0, 0 ) );
724 extractBlock( temp_ll, 0, 0.5 * _wfSz, 0.5 * _wfSz, 0.5 * _wfSz, focalPlane, 0, 0.5 * _wfSz );
725 fi.propagateFocalToPupil( sensorPlane, temp_ll );
726 extractIntensityImageAccum( sensorImage,
727 0,
728 2 * _quadSz - dSz,
729 dSz,
730 2 * _quadSz - dSz,
731 sensorPlane,
732 0.5 * _wfSz - 0.5 * _quadSz,
733 0.5 * _wfSz - 1.5 * _quadSz + dSz );
734
735 temp_lr.set( complexT( 0, 0 ) );
737 temp_lr, 0.5 * _wfSz, 0.5 * _wfSz, 0.5 * _wfSz, 0.5 * _wfSz, focalPlane, 0.5 * _wfSz, 0.5 * _wfSz );
738 fi.propagateFocalToPupil( sensorPlane, temp_lr );
739 extractIntensityImageAccum( sensorImage,
740 dSz,
741 2 * _quadSz - dSz,
742 dSz,
743 2 * _quadSz - dSz,
744 sensorPlane,
745 0.5 * _wfSz - 1.5 * _quadSz + dSz,
746 0.5 * _wfSz - 1.5 * _quadSz + dSz );
747
748 } // for
749
750 BREAD_CRUMB;
751
752 // std::cerr << wfsImage.rows() << " " << wfsImage.cols() << "\n";
753 // std::cerr << sensorImage.rows() << " " << sensorImage.cols() << "\n";
754
755#pragma omp critical
756 {
757 wfsImage += sensorImage;
758 }
759
760 } // #pragma omp parallel
761
762 BREAD_CRUMB;
763
764 wfsImage /= _modSteps;
765}
766
767template <typename _floatT, typename _detectorT>
768void pyramidSensor<_floatT, _detectorT>::doSenseWavefrontNoMod( wavefrontT &pupilPlane )
769{
770 constexpr _floatT pi = math::pi<_floatT>();
771
772 BREAD_CRUMB;
773
774 wfsImage.resize( 2 * _quadSz, 2 * _quadSz );
775 wfsImage.setZero();
776
777 complexFieldT pupilPlaneCF;
778 pupilPlane.getWavefront( pupilPlaneCF, _wfSz );
779
780 complexFieldT focalPlaneCF;
781 focalPlaneCF.resize( _wfSz, _wfSz );
782
783 complexFieldT tiltedPlane;
784 complexFieldT focalPlane;
785 complexFieldT sensorPlane;
786 complexFieldT temp_ul;
787 complexFieldT temp_ur;
788 complexFieldT temp_ll;
789 complexFieldT temp_lr;
790
791 wfsImageT sensorImage;
792
793 tiltedPlane.resize( _wfSz, _wfSz );
794 focalPlane.resize( _wfSz, _wfSz );
795 sensorPlane.resize( _wfSz, _wfSz );
796
797 temp_ul.resize( _wfSz, _wfSz );
798 temp_ul.set( (complexT)0 );
799
800 temp_ur.resize( _wfSz, _wfSz );
801 temp_ur.set( (complexT)0 );
802
803 temp_ll.resize( _wfSz, _wfSz );
804 temp_ll.set( (complexT)0 );
805
806 temp_lr.resize( _wfSz, _wfSz );
807 temp_lr.set( (complexT)0 );
808
809 sensorImage.resize( _quadSz * 2, _quadSz * 2 );
810 sensorImage.setZero();
811
812 int dSz = ( 0.5 * _wfSz - 0.5 * _quadSz + 2 * _quadSz ) - _wfSz;
813 if( dSz < 0 )
814 dSz = 0;
815 int nelem = _wfSz * _wfSz;
816
817 complexT *tp_data = tiltedPlane.data();
818 complexT *pp_data = pupilPlaneCF.data();
819
820 BREAD_CRUMB;
821 for( int ii = 0; ii < nelem; ++ii )
822 {
823 tp_data[ii] = pp_data[ii]; //*ti_data[ii];
824 }
825
826 BREAD_CRUMB;
827
828 fi.propagatePupilToFocal( focalPlane, tiltedPlane );
829 temp_ul.set( complexT( 0, 0 ) );
830 extractBlock( temp_ul, 0, 0.5 * _wfSz, 0, 0.5 * _wfSz, focalPlane, 0, 0 );
831
832 fi.propagateFocalToPupil( sensorPlane, temp_ul );
833 extractIntensityImageAccum( sensorImage,
834 0,
835 2 * _quadSz - dSz,
836 0,
837 2 * _quadSz - dSz,
838 sensorPlane,
839 0.5 * _wfSz - 0.5 * _quadSz,
840 0.5 * _wfSz - 0.5 * _quadSz );
841
842 temp_ur.set( complexT( 0, 0 ) );
843 extractBlock( temp_ur, 0.5 * _wfSz, 0.5 * _wfSz, 0, 0.5 * _wfSz, focalPlane, 0.5 * _wfSz, 0 );
844 fi.propagateFocalToPupil( sensorPlane, temp_ur );
845 extractIntensityImageAccum( sensorImage,
846 dSz,
847 2 * _quadSz - dSz,
848 0,
849 2 * _quadSz - dSz,
850 sensorPlane,
851 0.5 * _wfSz - 1.5 * _quadSz + dSz,
852 0.5 * _wfSz - 0.5 * _quadSz );
853
854 temp_ll.set( complexT( 0, 0 ) );
855 extractBlock( temp_ll, 0, 0.5 * _wfSz, 0.5 * _wfSz, 0.5 * _wfSz, focalPlane, 0, 0.5 * _wfSz );
856 fi.propagateFocalToPupil( sensorPlane, temp_ll );
857 extractIntensityImageAccum( sensorImage,
858 0,
859 2 * _quadSz - dSz,
860 dSz,
861 2 * _quadSz - dSz,
862 sensorPlane,
863 0.5 * _wfSz - 0.5 * _quadSz,
864 0.5 * _wfSz - 1.5 * _quadSz + dSz );
865
866 temp_lr.set( complexT( 0, 0 ) );
867 extractBlock( temp_lr, 0.5 * _wfSz, 0.5 * _wfSz, 0.5 * _wfSz, 0.5 * _wfSz, focalPlane, 0.5 * _wfSz, 0.5 * _wfSz );
868 fi.propagateFocalToPupil( sensorPlane, temp_lr );
869 extractIntensityImageAccum( sensorImage,
870 dSz,
871 2 * _quadSz - dSz,
872 dSz,
873 2 * _quadSz - dSz,
874 sensorPlane,
875 0.5 * _wfSz - 1.5 * _quadSz + dSz,
876 0.5 * _wfSz - 1.5 * _quadSz + dSz );
877
878 BREAD_CRUMB;
879
880 wfsImage += sensorImage;
881
882 BREAD_CRUMB;
883}
884
885} // namespace sim
886} // namespace AO
887} // namespace mx
888
889#endif //__pyramidSensor_hpp__
constexpr T pi()
Get the value of pi.
Definition constants.hpp:55
constexpr floatT six_fifths()
Return 6/5 in the specified precision.
void tiltWavefront(wavefrontT &complexWavefront, typename wavefrontT::Scalar::value_type xTilt, typename wavefrontT::Scalar::value_type yTilt)
Apply a tilt to a wavefront.
void extractBlock(imageT1 &dest, int imX0, int imXsz, int imY0, int imYsz, imageT2 &src, int wfX0, int wfY0)
Extract a block from one image and insert it into a second.
The mxlib c++ namespace.
Definition mxError.hpp:106