mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
array2FitGaussian2D.hpp
Go to the documentation of this file.
1 /** \file array2FitGaussian2D.hpp
2  * \author Jared R. Males
3  * \brief Wrapper for a native array to pass to \ref levmarInterface, with 2D Gaussian details.
4  * \ingroup fitting_files
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2020 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef math_fit_array2FitGaussian2D_hpp
28 #define math_fit_array2FitGaussian2D_hpp
29 
30 #include "../../mxError.hpp"
31 
32 namespace mx
33 {
34 namespace math
35 {
36 namespace fit
37 {
38 
39 
40 /// Wrapper for a native array to pass to \ref levmarInterface, with 2D Gaussian details.
41 /** Supports fixing G0, G, x0, and y0 independently. The shape and orientation can be fixed, but
42  * for the general form, sigma_x, sigma_y, and theta can only be fixed together.
43  * \ingroup gaussian_peak_fit
44  */
45 template<typename realT>
47 {
48  realT * data {nullptr}; ///< Pointer to the array
49  size_t nx {0}; ///< X dimension of the array
50  size_t ny {0}; ///< Y dimension of the array
51 
52  realT * mask {nullptr}; ///< Pointer to the (optional) mask array. Any 0 pixels are excluded from the fit.
53 
54  realT m_G0 {0};
55  realT m_G {0};
56  realT m_x0 {0};
57  realT m_y0 {0};
58  realT m_sigma_x {0};
59  realT m_sigma_y {0};
60  realT m_theta {0};
61 
62  realT m_a {0};
63  realT m_b {0};
64  realT m_c {0};
65 
66  realT m_sigma {0};
67 
68  int m_G0_idx {0};
69  int m_G_idx {1};
70  int m_x0_idx {2};
71  int m_y0_idx {3};
72  int m_sigma_x_idx {4}; ///< Index of sigma_x in the parameters. Re-used for a.
73  int m_sigma_y_idx {5}; ///< Index of sigma_y in the parameters. Re-used for b.
74  int m_theta_idx {6}; ///< Index of theta in the parameters. Re-used for c.
75 
76  int m_sigma_idx {4}; ///< Index of sigma in the symmetric case
77 
78  int m_nparams {7};
79  int m_maxNparams {7};
80 
81  void setSymmetric();
82 
83  void setGeneral();
84 
85  /// Set whether each parameter is fixed.
86  /** Sets the parameter indices appropriately.
87  */
88  void setFixed( bool G0,
89  bool G,
90  bool x0,
91  bool y0,
92  bool sigma_x,
93  bool sigma_y,
94  bool theta
95  );
96 
97  realT G0( realT * p );
98 
99  void G0( realT * p,
100  realT nG0
101  );
102 
103  realT G( realT * p );
104 
105  void G( realT * p,
106  realT nG
107  );
108 
109  realT x0( realT * p );
110 
111  void x0( realT * p,
112  realT nx0
113  );
114 
115  realT y0( realT * p );
116 
117  void y0( realT * p,
118  realT ny0
119  );
120 
121  realT sigma_x( realT * p );
122 
123  void sigma_x( realT * p,
124  realT nsigma_x
125  );
126 
127  realT sigma_y( realT * p );
128 
129  void sigma_y( realT * p,
130  realT nsigma_y
131  );
132 
133  realT theta( realT * p );
134 
135  void theta( realT * p,
136  realT ntheta
137  );
138 
139  realT sigma( realT * p );
140 
141  void sigma( realT * p,
142  realT nsigma
143  );
144 
145  realT a( realT * p );
146 
147  void a( realT * p,
148  realT na
149  );
150 
151  realT b( realT * p );
152 
153  void b( realT * p,
154  realT nb
155  );
156 
157  realT c( realT * p );
158 
159  void c( realT * p,
160  realT nc
161  );
162 
163  int nparams();
164 
165 };
166 
167 template<typename realT>
168 void array2FitGaussian2D<realT>::setSymmetric()
169 {
170  m_maxNparams = 5;
171 }
172 
173 template<typename realT>
174 void array2FitGaussian2D<realT>::setGeneral()
175 {
176  m_maxNparams = 7;
177 }
178 
179 template<typename realT>
181  bool G,
182  bool x0,
183  bool y0,
184  bool sigma_x,
185  bool sigma_y,
186  bool theta
187  )
188 {
189  int idx = 0;
190 
191  if(G0) m_G0_idx = -1;
192  else m_G0_idx = idx++;
193 
194  if(G) m_G_idx = -1;
195  else m_G_idx = idx++;
196 
197  if(x0) m_x0_idx = -1;
198  else m_x0_idx = idx++;
199 
200  if(y0) m_y0_idx = -1;
201  else m_y0_idx = idx++;
202 
203  if(m_maxNparams == 5)
204  {
205  if(sigma_x) m_sigma_idx = -1;
206  else m_sigma_idx = idx++;
207  }
208  else if(sigma_x && sigma_y && theta)
209  {
210  m_sigma_x_idx = -1;
211  m_sigma_y_idx = -1;
212  m_theta_idx = -1;
213  }
214  else
215  {
216  if(sigma_x || sigma_y || theta)
217  {
218  mxError("array2FitGaussian2D::setFixed", MXE_NOTIMPL, "cannot fix sigma_x, sigma_y, and theta separately");
219  }
220 
221  m_sigma_x_idx = idx++;
222  m_sigma_y_idx = idx++;
223  m_theta_idx = idx++;
224  }
225 
226  m_nparams = idx;
227 }
228 
229 template<typename realT>
230 realT array2FitGaussian2D<realT>::G0( realT * p )
231 {
232  if( m_G0_idx < 0 )
233  {
234  return m_G0;
235  }
236  else
237  {
238  return p[m_G0_idx];
239  }
240 }
241 
242 template<typename realT>
243 void array2FitGaussian2D<realT>::G0( realT * p,
244  realT nG0
245  )
246 {
247  if( m_G0_idx < 0 )
248  {
249  m_G0 = nG0;
250  }
251  else
252  {
253  p[m_G0_idx]=nG0;
254  }
255 }
256 
257 template<typename realT>
258 realT array2FitGaussian2D<realT>::G( realT * p )
259 {
260  if( m_G_idx < 0 )
261  {
262  return m_G;
263  }
264  else
265  {
266  return p[m_G_idx];
267  }
268 }
269 
270 template<typename realT>
271 void array2FitGaussian2D<realT>::G( realT * p,
272  realT nG
273  )
274 {
275  if( m_G_idx < 0 )
276  {
277  m_G = nG;
278  }
279  else
280  {
281  p[m_G_idx] = nG;
282  }
283 }
284 
285 template<typename realT>
286 realT array2FitGaussian2D<realT>::x0( realT * p )
287 {
288  if( m_x0_idx < 0 )
289  {
290  return m_x0;
291  }
292  else
293  {
294  return p[m_x0_idx];
295  }
296 }
297 
298 template<typename realT>
299 void array2FitGaussian2D<realT>::x0( realT * p,
300  realT nx0
301  )
302 {
303  if( m_x0_idx < 0 )
304  {
305  m_x0 = nx0;
306  }
307  else
308  {
309  p[m_x0_idx] = nx0;
310  }
311 }
312 
313 template<typename realT>
314 realT array2FitGaussian2D<realT>::y0( realT * p )
315 {
316  if( m_y0_idx < 0 )
317  {
318  return m_y0;
319  }
320  else
321  {
322  return p[m_y0_idx];
323  }
324 }
325 
326 template<typename realT>
327 void array2FitGaussian2D<realT>::y0( realT * p,
328  realT ny0
329  )
330 {
331  if( m_y0_idx < 0 )
332  {
333  m_y0 = ny0;
334  }
335  else
336  {
337  p[m_y0_idx] = ny0;
338  }
339 }
340 
341 template<typename realT>
342 realT array2FitGaussian2D<realT>::sigma_x( realT * p )
343 {
344  if( m_sigma_x_idx < 0 )
345  {
346  return m_sigma_x;
347  }
348  else
349  {
350  return p[m_sigma_x_idx];
351  }
352 }
353 
354 template<typename realT>
355 void array2FitGaussian2D<realT>::sigma_x( realT * p,
356  realT nsigma_x
357  )
358 {
359  if( m_sigma_x_idx < 0 )
360  {
361  m_sigma_x = nsigma_x;
362  }
363  else
364  {
365  p[m_sigma_x_idx] = nsigma_x;
366  }
367 }
368 
369 template<typename realT>
370 realT array2FitGaussian2D<realT>::sigma_y( realT * p )
371 {
372  if( m_sigma_y_idx < 0 )
373  {
374  return m_sigma_y;
375  }
376  else
377  {
378  return p[m_sigma_y_idx];
379  }
380 }
381 
382 template<typename realT>
383 void array2FitGaussian2D<realT>::sigma_y( realT * p,
384  realT nsigma_y
385  )
386 {
387  if( m_sigma_y_idx < 0 )
388  {
389  m_sigma_y = nsigma_y;
390  }
391  else
392  {
393  p[m_sigma_y_idx] = nsigma_y;
394  }
395 }
396 
397 template<typename realT>
398 realT array2FitGaussian2D<realT>::theta( realT * p )
399 {
400  if( m_theta_idx < 0 )
401  {
402  return m_theta;
403  }
404  else
405  {
406  return p[m_theta_idx];
407  }
408 }
409 
410 template<typename realT>
411 void array2FitGaussian2D<realT>::theta( realT * p,
412  realT ntheta
413  )
414 {
415  if( m_theta_idx < 0 )
416  {
417  m_theta = ntheta;
418  }
419  else
420  {
421  p[m_theta_idx] = ntheta;
422  }
423 }
424 
425 template<typename realT>
426 realT array2FitGaussian2D<realT>::sigma( realT * p )
427 {
428  if( m_sigma_idx < 0 )
429  {
430  return m_sigma;
431  }
432  else
433  {
434  return p[m_sigma_idx];
435  }
436 }
437 
438 template<typename realT>
439 void array2FitGaussian2D<realT>::sigma( realT * p,
440  realT nsigma
441  )
442 {
443  if( m_sigma_idx < 0 )
444  {
445  m_sigma = nsigma;
446  }
447  else
448  {
449  p[m_sigma_idx] = nsigma;
450  }
451 }
452 
453 template<typename realT>
454 realT array2FitGaussian2D<realT>::a( realT * p )
455 {
456  //This aliases sigma_x after param normalization
457  if( m_sigma_x_idx < 0 )
458  {
459  return m_a;
460  }
461  else
462  {
463  return p[m_sigma_x_idx];
464  }
465 }
466 
467 template<typename realT>
468 void array2FitGaussian2D<realT>::a( realT * p,
469  realT na
470  )
471 {
472  //This aliases sigma_x after param normalization
473  if( m_sigma_x_idx < 0 )
474  {
475  m_a = na;
476  }
477  else
478  {
479  p[m_sigma_x_idx] = na;
480  }
481 }
482 
483 template<typename realT>
484 realT array2FitGaussian2D<realT>::b( realT * p )
485 {
486  //This aliases sigma_y after param normalization
487  if( m_sigma_y_idx < 0 )
488  {
489  return m_b;
490  }
491  else
492  {
493  return p[m_sigma_y_idx];
494  }
495 }
496 
497 template<typename realT>
498 void array2FitGaussian2D<realT>::b( realT * p,
499  realT nb
500  )
501 {
502  //This aliases sigma_y after param normalization
503  if( m_sigma_y_idx < 0 )
504  {
505  m_b = nb;
506  }
507  else
508  {
509  p[m_sigma_y_idx] = nb;
510  }
511 }
512 
513 template<typename realT>
514 realT array2FitGaussian2D<realT>::c( realT * p )
515 {
516  //This aliases theta after param normalization
517  if( m_theta_idx < 0 )
518  {
519  return m_c;
520  }
521  else
522  {
523  return p[m_theta_idx];
524  }
525 }
526 
527 template<typename realT>
528 void array2FitGaussian2D<realT>::c( realT * p,
529  realT nc
530  )
531 {
532  //This aliases theta after param normalization
533  if( m_theta_idx < 0 )
534  {
535  m_c = nc;
536  }
537  else
538  {
539  p[m_theta_idx] = nc;
540  }
541 }
542 
543 template<typename realT>
544 int array2FitGaussian2D<realT>::nparams()
545 {
546  return m_nparams;
547 }
548 
549 } //namespace fit
550 } //namespace math
551 
552 } //namespace mx
553 
554 #endif //math_fit_array2FitGaussian2D_hpp
555 
constexpr units::realT G()
Newton's Gravitational Constant.
Definition: constants.hpp:51
The mxlib c++ namespace.
Definition: mxError.hpp:107
Wrapper for a native array to pass to levmarInterface, with 2D Gaussian details.
int m_sigma_x_idx
Index of sigma_x in the parameters. Re-used for a.
size_t ny
Y dimension of the array.
int m_sigma_idx
Index of sigma in the symmetric case.
int m_sigma_y_idx
Index of sigma_y in the parameters. Re-used for b.
void setFixed(bool G0, bool G, bool x0, bool y0, bool sigma_x, bool sigma_y, bool theta)
Set whether each parameter is fixed.
size_t nx
X dimension of the array.
realT * data
Pointer to the array.
int m_theta_idx
Index of theta in the parameters. Re-used for c.
realT * mask
Pointer to the (optional) mask array. Any 0 pixels are excluded from the fit.