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