Line data Source code
1 : /** \file aoWFS.hpp
2 : * \author Jared R. Males (jaredmales@gmail.com)
3 : * \brief Definitions of various analytic wavefront sensors
4 : * \ingroup mxAO_files
5 : *
6 : */
7 :
8 : #ifndef aoWFS_hpp
9 : #define aoWFS_hpp
10 :
11 : #include "../../math/constants.hpp"
12 : #include "../../mxlib.hpp"
13 : #include "../../improc/eigenImage.hpp"
14 : #include "../../ioutils/fits/fitsFile.hpp"
15 :
16 : namespace mx
17 : {
18 : namespace AO
19 : {
20 : namespace analysis
21 : {
22 :
23 : /// The ideal wavefront sensor sensitivity function.
24 : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
25 : * for the ideal WFS.
26 : *
27 : * This is the base class for all WFS.
28 : *
29 : * \tparam realT is the floating point type used for calculations
30 : * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
31 : *
32 : * \ingroup mxAOAnalytic
33 : */
34 : template <typename realT, typename iosT = std::ostream>
35 : struct wfs
36 : {
37 : std::string _id;
38 :
39 : /// Constructor
40 : /** Only sets the value of _id.
41 : */
42 52 : wfs()
43 52 : {
44 52 : _id = "Ideal WFS";
45 52 : }
46 :
47 : /// Destructor
48 : /** Declared virtual so more complicated derived types can be created.
49 : */
50 101 : virtual ~wfs()
51 : {
52 104 : return;
53 101 : }
54 :
55 : /// Get the photon noise sensitivity at a spatial frequency.
56 : /** The sensitivity of the ideal WFS is 1 at all k \cite guyon_2005.
57 : *
58 : * \returns the sensitivity to photon noise parameter
59 : */
60 0 : virtual realT beta_p( int m, ///< [in] the spatial frequency index for u (not used by this WFS)
61 : int n, ///< [in] the spatial frequency index for v (not used by this WFS)
62 : realT D, ///< [in] the telescope diameter (not used by this WFS)
63 : realT d, ///< [in] the sub-ap spacing (not used by this WFS)
64 : realT r0 ///< [in] Fried's parameter (not used by this WFS)
65 : )
66 : {
67 : // Stuff a sock in the compiler's mouth:
68 : static_cast<void>( m );
69 : static_cast<void>( n );
70 : static_cast<void>( D );
71 : static_cast<void>( d );
72 : static_cast<void>( r0 );
73 :
74 0 : return static_cast<realT>( 1 );
75 : }
76 :
77 : /// Get the read noise sensitivity at a spatial frequency.
78 : /** Here we assume beta_r is the same as beta_p.
79 : *
80 : * \returns the sensitivity to read noise parameter
81 : */
82 0 : virtual realT beta_r( int m, ///< [in] the spatial frequency index for u (not used by this WFS)
83 : int n, ///< [in] the spatial frequency index for v (not used by this WFS)
84 : realT D, ///< [in] the telescope diameter (not used by this WFS)
85 : realT d, ///< [in] the sub-ap spacing (not used by this WFS)
86 : realT r0 ///< [in] Fried's parameter (not used by this WFS)
87 : )
88 : {
89 0 : return beta_p( m, n, D, d, r0 );
90 : }
91 :
92 : /// Dump the details of the WFS to an io stream.
93 : /** Is virtual so that derived types can add parameters.
94 : */
95 1 : virtual iosT &dumpWFS( iosT &ios )
96 : {
97 1 : ios << "# WFS Parameters:\n";
98 1 : ios << "# ID = " << _id << '\n';
99 :
100 1 : return ios;
101 : }
102 : };
103 :
104 : /// The unmodulated pyramid wavefront sensor sensitivity function.
105 : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
106 : * for the unmodulated PyWFS.
107 : *
108 : * \tparam realT is the floating point type used for calculations
109 : * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
110 : *
111 : * \ingroup mxAOAnalytic
112 : */
113 : template <typename realT, typename iosT = std::ostream>
114 : struct pywfsUnmod : public wfs<realT, iosT>
115 : {
116 1 : pywfsUnmod()
117 1 : {
118 1 : this->_id = "Unmodulated Pyramid";
119 1 : }
120 :
121 : /// Get the photon noise sensitivity at a spatial frequency.
122 : /** The sensitivity of the unmodulated PyWFS is \f$ \sqrt{2} \f$ at all k.
123 : *
124 : * \returns the sensitivity to photon noise parameter
125 : */
126 0 : virtual realT beta_p( int m, ///< [in] the spatial frequency index for u (not used by this WFS)
127 : int n, ///< [in] the spatial frequency index for v (not used by this WFS)
128 : realT D, ///< [in] the telescope diameter (not used by this WFS)
129 : realT d, ///< [in] the sub-ap spacing (not used by this WFS)
130 : realT r0 ///< [in] Fried's parameter (not used by this WFS)
131 : )
132 : {
133 : // Stuff a sock in the compiler's mouth:
134 : static_cast<void>( m );
135 : static_cast<void>( n );
136 : static_cast<void>( D );
137 : static_cast<void>( d );
138 : static_cast<void>( r0 );
139 :
140 0 : return math::root_two<realT>();
141 : }
142 :
143 : /// Get the read noise sensitivity at a spatial frequency.
144 : /** Here we assume that beta_r is the same as beta_p.
145 : *
146 : * \returns the sensitivity to read noise parameter
147 : */
148 0 : virtual realT beta_r( int m, ///< [in] the spatial frequency index for u (not used by this WFS)
149 : int n, ///< [in] the spatial frequency index for v (not used by this WFS)
150 : realT D, ///< [in] the telescope diameter (not used by this WFS)
151 : realT d, ///< [in] the sub-ap spacing (not used by this WFS)
152 : realT r0 ///< [in] Fried's parameter (not used by this WFS)
153 : )
154 : {
155 0 : return beta_p( m, n, D, d, r0 );
156 : }
157 : };
158 :
159 : /// The asymptotic modulated pyramid wavefront sensor sensitivity function.
160 : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
161 : * for the modulated PyWFS in the asymptotic limit.
162 : *
163 : * \tparam realT is the floating point type used for calculations
164 : * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
165 : *
166 : * \ingroup mxAOAnalytic
167 : */
168 : template <typename realT, typename iosT = std::ostream>
169 : struct pywfsModAsymptotic : public wfs<realT, iosT>
170 : {
171 1 : pywfsModAsymptotic()
172 1 : {
173 1 : this->_id = "Asymptotic Modulated Pyramid";
174 1 : }
175 :
176 : /// Get the photon sensitivity at a spatial frequency.
177 : /** The photon noise sensitivity of the asymptotic modulated PyWFS is \f$ 2 \sqrt{2} \f$ at all k.
178 : *
179 : * \returns the sensitivity to photon noise parameter
180 : */
181 0 : virtual realT beta_p( int m, ///< [in] the spatial frequency index for u (not used by this WFS)
182 : int n, ///< [in] the spatial frequency index for v (not used by this WFS)
183 : realT D, ///< [in] the telescope diameter (not used by this WFS)
184 : realT d, ///< [in] the sub-ap spacing (not used by this WFS)
185 : realT r0 ///< [in] Fried's parameter (not used by this WFS)
186 : )
187 : {
188 : // Stuff a sock in the compiler's mouth:
189 : static_cast<void>( m );
190 : static_cast<void>( n );
191 : static_cast<void>( D );
192 : static_cast<void>( d );
193 : static_cast<void>( r0 );
194 :
195 0 : return static_cast<realT>( 2 ) * math::root_two<realT>();
196 : }
197 :
198 : /// Get the read noise sensitivity at a spatial frequency.
199 : /** Here we assume beta_r is the same as beta_p
200 : *
201 : * \returns the sensitivity to read noise parameter
202 : */
203 0 : virtual realT beta_r( int m, ///< [in] the spatial frequency index for u (not used by this WFS)
204 : int n, ///< [in] the spatial frequency index for v (not used by this WFS)
205 : realT D, ///< [in] the telescope diameter (not used by this WFS)
206 : realT d, ///< [in] the sub-ap spacing (not used by this WFS)
207 : realT r0 ///< [in] Fried's parameter (not used by this WFS)
208 : )
209 : {
210 0 : return beta_p( m, m, D, d, r0 );
211 : }
212 : };
213 :
214 : /// The shack hartmann wavefront sensor sensitivity function.
215 : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
216 : * for the shack hartmann WFS.
217 : *
218 : * \tparam realT is the floating point type used for calculations
219 : * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
220 : *
221 : * \ingroup mxAOAnalytic
222 : */
223 : template <typename realT, typename iosT = std::ostream>
224 : struct shwfs : public wfs<realT, iosT>
225 : {
226 1 : shwfs()
227 1 : {
228 1 : this->_id = "Shack Hartmann";
229 1 : }
230 :
231 : /// Get the photon noise sensitivity at a spatial frequency.
232 : /** The photon noise sensitivity of the shack hartmann WFS
233 : *
234 : * \returns the sensitivity to photon noise parameter
235 : */
236 0 : virtual realT beta_p( int m, ///< [in] the spatial frequency index for u
237 : int n, ///< [in] the spatial frequency index for v
238 : realT D, ///< [in] the telescope diameter
239 : realT d, ///< [in] the sub-ap spacing
240 : realT r0 ///< [in] Fried's parameter
241 : )
242 : {
243 0 : realT k = sqrt( m * m + n * n ) / D;
244 :
245 0 : return 1.48 / ( k * d ) * sqrt( 1 + pow( d / r0, 2 ) );
246 : }
247 :
248 : /// Get the read noise sensitivity at a spatial frequency.
249 : /** Here we assume beta_r = beta_p
250 : *
251 : * \returns the sensitivity to read noise parameter
252 : */
253 0 : virtual realT beta_r( int m, ///< [in] the spatial frequency index for u
254 : int n, ///< [in] the spatial frequency index for v
255 : realT D, ///< [in] the telescope diameter
256 : realT d, ///< [in] the sub-ap spacing
257 : realT r0 ///< [in] Fried's parameter
258 : )
259 : {
260 0 : return beta_p( m, n, D, d, r0 );
261 : }
262 : };
263 :
264 : /// The calculated WFS uses sensitivities provided by FITS files
265 : /** Provides the \f$ \beta_p \f$ and \f$ \beta_r \f$ parameters
266 : * from FITS files.
267 : *
268 : * \tparam realT is the floating point type used for calculations
269 : * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
270 : *
271 : * \ingroup mxAOAnalytic
272 : */
273 : template <typename realT, typename iosT = std::ostream>
274 : struct calculatedWFS : public wfs<realT, iosT>
275 : {
276 : typedef verbose::d verboseT;
277 :
278 : std::string m_beta_p_file;
279 : std::string m_beta_r_file;
280 : bool m_sensitivity{ false };
281 :
282 : improc::eigenImage<realT> m_beta_p;
283 : improc::eigenImage<realT> m_beta_r;
284 :
285 0 : calculatedWFS()
286 0 : {
287 0 : this->_id = "Calculated WFS";
288 0 : }
289 :
290 : /// Get the photon noise sensitivity at a spatial frequency.
291 : /** The photon noise sensitivity from the FITS file is returned.
292 : *
293 : * \returns the sensitivity to photon noise parameter
294 : */
295 0 : virtual realT beta_p( int m, ///< [in] the spatial frequency index for u
296 : int n, ///< [in] the spatial frequency index for v
297 : realT D, ///< [in] the telescope diameter
298 : realT d, ///< [in] the sub-ap spacing
299 : realT r0 ///< [in] Fried's parameter
300 : )
301 : {
302 :
303 0 : if( m_beta_p.rows() == 0 )
304 : {
305 0 : #pragma omp critical // Make sure we don't race in m/t
306 : {
307 0 : if( m_beta_p.rows() == 0 ) // Check again after critical locks
308 : {
309 0 : fits::fitsFile<realT> ff;
310 0 : ff.read( m_beta_p, m_beta_p_file );
311 :
312 0 : if( m_sensitivity )
313 : {
314 0 : m_beta_p = 1.0 / m_beta_p;
315 : }
316 0 : }
317 : }
318 : }
319 :
320 0 : int midx = 0.5 * ( m_beta_p.rows() - 1.0 ) + m;
321 0 : int nidx = 0.5 * ( m_beta_p.cols() - 1.0 ) + n;
322 :
323 0 : if( midx > m_beta_p.rows() - 1 || midx < 0 )
324 : {
325 0 : #pragma omp critical
326 : {
327 0 : std::cerr << "calculatedWFS::beta_p: m index out of range. Got m = " << m
328 0 : << " / beta_p.rows = " << m_beta_p.rows() << "\n";
329 : }
330 : // Just return a huge number to make this spatial frequency unsenseable
331 0 : return std::numeric_limits<realT>::max();
332 : }
333 :
334 0 : if( nidx > m_beta_p.cols() - 1 || nidx < 0 )
335 : {
336 0 : #pragma omp critical
337 : {
338 0 : std::cerr << "calculatedWFS::beta_p: n index out of range. Got n = " << n
339 0 : << " / beta_p.cols = " << m_beta_p.cols() << "\n";
340 : }
341 : // Just return a huge number to make this spatial frequency unsenseable
342 0 : return std::numeric_limits<realT>::max();
343 : }
344 :
345 0 : return m_beta_p( midx, nidx );
346 : }
347 :
348 : /// Get the read noise sensitivity at a spatial frequency.
349 : /** The read noise sensitivity from the FITS file is returned.
350 : *
351 : * \returns the sensitivity to read noise parameter
352 : */
353 0 : virtual realT beta_r( int m, ///< [in] the spatial frequency index for u
354 : int n, ///< [in] the spatial frequency index for v
355 : realT D, ///< [in] the telescope diameter
356 : realT d, ///< [in] the sub-ap spacing
357 : realT r0 ///< [in] Fried's parameter
358 : )
359 : {
360 0 : if( m_beta_r.rows() == 0 )
361 : {
362 0 : fits::fitsFile<realT> ff;
363 0 : ff.read( m_beta_r, m_beta_r_file );
364 :
365 0 : if( m_sensitivity )
366 0 : m_beta_r = 1.0 / m_beta_r;
367 0 : }
368 :
369 0 : int midx = 0.5 * ( m_beta_r.rows() - 1.0 ) + m;
370 0 : int nidx = 0.5 * ( m_beta_r.cols() - 1.0 ) + n;
371 :
372 0 : if( midx > m_beta_r.rows() - 1 || midx < 0 )
373 : {
374 0 : throw(mx::exception<verboseT>(error_t::sizeerr, "m index out of range" ));
375 : }
376 :
377 0 : if( nidx > m_beta_r.cols() - 1 || nidx < 0 )
378 : {
379 0 : throw(mx::exception<verboseT>(error_t::sizeerr, "n index out of range" ));
380 : }
381 :
382 0 : return m_beta_r( midx, nidx );
383 : }
384 :
385 : /// Dump the details of the WFS to an io stream.
386 : /** Is virtual so that derived types can add parameters.
387 : */
388 0 : virtual iosT &dumpWFS( iosT &ios )
389 : {
390 0 : wfs<realT, iosT>::dumpWFS( ios );
391 :
392 0 : ios << "# beta_p = " << m_beta_p_file << '\n';
393 0 : ios << "# beta_r = " << m_beta_r_file << '\n';
394 0 : ios << "# sensitivity = " << std::boolalpha << m_sensitivity << "\n";
395 :
396 0 : return ios;
397 : }
398 : };
399 :
400 : } // namespace analysis
401 : } // namespace AO
402 : } // namespace mx
403 :
404 : #endif // aoWFS_hpp
|