mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
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 "../../mxlib.hpp"
31
32namespace mx
33{
34namespace math
35{
36namespace fit
37{
38
39/// Wrapper for a native array to pass to \ref levmarInterface, with 2D Gaussian details.
40/** Supports fixing G0, G, x0, and y0 independently. The shape and orientation can be fixed, but
41 * for the general form, sigma_x, sigma_y, and theta can only be fixed together.
42 * \ingroup gaussian_peak_fit
43 */
44template <typename realT>
46{
47 realT *data{ nullptr }; ///< Pointer to the array
48 size_t nx{ 0 }; ///< X dimension of the array
49 size_t ny{ 0 }; ///< Y dimension of the array
50
51 realT *weights{ nullptr }; /**< Pointer to the (optional) weight array. Normally this should be the
52 square root of the variance.*/
53
54 realT *mask{ nullptr }; ///< Pointer to the (optional) mask array. Any 0 pixels are excluded from the fit.
55
56 realT m_G0{ 0 };
57 realT m_G{ 0 };
58 realT m_x0{ 0 };
59 realT m_y0{ 0 };
60 realT m_sigma_x{ 0 };
61 realT m_sigma_y{ 0 };
62 realT m_theta{ 0 };
63
64 realT m_a{ 0 };
65 realT m_b{ 0 };
66 realT m_c{ 0 };
67
68 realT m_sigma{ 0 };
69
70 int m_G0_idx{ 0 };
71 int m_G_idx{ 1 };
72 int m_x0_idx{ 2 };
73 int m_y0_idx{ 3 };
74 int m_sigma_x_idx{ 4 }; ///< Index of sigma_x in the parameters. Re-used for a.
75 int m_sigma_y_idx{ 5 }; ///< Index of sigma_y in the parameters. Re-used for b.
76 int m_theta_idx{ 6 }; ///< Index of theta in the parameters. Re-used for c.
77
78 int m_sigma_idx{ 4 }; ///< Index of sigma in the symmetric case
79
80 int m_nparams{ 7 };
81 int m_maxNparams{ 7 };
82
83 void setSymmetric();
84
85 void setGeneral();
86
87 /// Set whether each parameter is fixed.
88 /** Sets the parameter indices appropriately.
89 */
90 void setFixed( bool G0, bool G, bool x0, bool y0, bool sigma_x, bool sigma_y, bool theta );
91
92 realT G0( realT *p );
93
94 void G0( realT *p, realT nG0 );
95
96 realT G( realT *p );
97
98 void G( realT *p, realT nG );
99
100 realT x0( realT *p );
101
102 void x0( realT *p, realT nx0 );
103
104 realT y0( realT *p );
105
106 void y0( realT *p, realT ny0 );
107
108 realT sigma_x( realT *p );
109
110 void sigma_x( realT *p, realT nsigma_x );
111
112 realT sigma_y( realT *p );
113
114 void sigma_y( realT *p, realT nsigma_y );
115
116 realT theta( realT *p );
117
118 void theta( realT *p, realT ntheta );
119
120 realT sigma( realT *p );
121
122 void sigma( realT *p, realT nsigma );
123
124 realT a( realT *p );
125
126 void a( realT *p, realT na );
127
128 realT b( realT *p );
129
130 void b( realT *p, realT nb );
131
132 realT c( realT *p );
133
134 void c( realT *p, realT nc );
135
136 int nparams();
137};
138
139template <typename realT>
140void array2FitGaussian2D<realT>::setSymmetric()
141{
142 m_maxNparams = 5;
143}
144
145template <typename realT>
146void array2FitGaussian2D<realT>::setGeneral()
147{
148 m_maxNparams = 7;
149}
150
151template <typename realT>
152void array2FitGaussian2D<realT>::setFixed( bool G0, bool G, bool x0, bool y0, bool sigma_x, bool sigma_y, bool theta )
153{
154 int idx = 0;
155
156 if( G0 )
157 m_G0_idx = -1;
158 else
159 m_G0_idx = idx++;
160
161 if( G )
162 m_G_idx = -1;
163 else
164 m_G_idx = idx++;
165
166 if( x0 )
167 m_x0_idx = -1;
168 else
169 m_x0_idx = idx++;
170
171 if( y0 )
172 m_y0_idx = -1;
173 else
174 m_y0_idx = idx++;
175
176 if( m_maxNparams == 5 )
177 {
178 if( sigma_x )
179 m_sigma_idx = -1;
180 else
181 m_sigma_idx = idx++;
182 }
183 else if( sigma_x && sigma_y && theta )
184 {
185 m_sigma_x_idx = -1;
186 m_sigma_y_idx = -1;
187 m_theta_idx = -1;
188 }
189 else
190 {
191 if( sigma_x || sigma_y || theta )
192 {
193 internal::mxlib_error_report(error_t::notimpl, "cannot fix sigma_x, sigma_y, and theta separately" );
194 }
195
196 m_sigma_x_idx = idx++;
197 m_sigma_y_idx = idx++;
198 m_theta_idx = idx++;
199 }
200
201 m_nparams = idx;
202}
203
204template <typename realT>
205realT array2FitGaussian2D<realT>::G0( realT *p )
206{
207 if( m_G0_idx < 0 )
208 {
209 return m_G0;
210 }
211 else
212 {
213 return p[m_G0_idx];
214 }
215}
216
217template <typename realT>
218void array2FitGaussian2D<realT>::G0( realT *p, realT nG0 )
219{
220 if( m_G0_idx < 0 )
221 {
222 m_G0 = nG0;
223 }
224 else
225 {
226 p[m_G0_idx] = nG0;
227 }
228}
229
230template <typename realT>
231realT array2FitGaussian2D<realT>::G( realT *p )
232{
233 if( m_G_idx < 0 )
234 {
235 return m_G;
236 }
237 else
238 {
239 return p[m_G_idx];
240 }
241}
242
243template <typename realT>
244void array2FitGaussian2D<realT>::G( realT *p, realT nG )
245{
246 if( m_G_idx < 0 )
247 {
248 m_G = nG;
249 }
250 else
251 {
252 p[m_G_idx] = nG;
253 }
254}
255
256template <typename realT>
257realT array2FitGaussian2D<realT>::x0( realT *p )
258{
259 if( m_x0_idx < 0 )
260 {
261 return m_x0;
262 }
263 else
264 {
265 return p[m_x0_idx];
266 }
267}
268
269template <typename realT>
270void array2FitGaussian2D<realT>::x0( realT *p, realT nx0 )
271{
272 if( m_x0_idx < 0 )
273 {
274 m_x0 = nx0;
275 }
276 else
277 {
278 p[m_x0_idx] = nx0;
279 }
280}
281
282template <typename realT>
283realT array2FitGaussian2D<realT>::y0( realT *p )
284{
285 if( m_y0_idx < 0 )
286 {
287 return m_y0;
288 }
289 else
290 {
291 return p[m_y0_idx];
292 }
293}
294
295template <typename realT>
296void array2FitGaussian2D<realT>::y0( realT *p, realT ny0 )
297{
298 if( m_y0_idx < 0 )
299 {
300 m_y0 = ny0;
301 }
302 else
303 {
304 p[m_y0_idx] = ny0;
305 }
306}
307
308template <typename realT>
309realT array2FitGaussian2D<realT>::sigma_x( realT *p )
310{
311 if( m_sigma_x_idx < 0 )
312 {
313 return m_sigma_x;
314 }
315 else
316 {
317 return p[m_sigma_x_idx];
318 }
319}
320
321template <typename realT>
322void array2FitGaussian2D<realT>::sigma_x( realT *p, realT nsigma_x )
323{
324 if( m_sigma_x_idx < 0 )
325 {
326 m_sigma_x = nsigma_x;
327 }
328 else
329 {
330 p[m_sigma_x_idx] = nsigma_x;
331 }
332}
333
334template <typename realT>
335realT array2FitGaussian2D<realT>::sigma_y( realT *p )
336{
337 if( m_sigma_y_idx < 0 )
338 {
339 return m_sigma_y;
340 }
341 else
342 {
343 return p[m_sigma_y_idx];
344 }
345}
346
347template <typename realT>
348void array2FitGaussian2D<realT>::sigma_y( realT *p, realT nsigma_y )
349{
350 if( m_sigma_y_idx < 0 )
351 {
352 m_sigma_y = nsigma_y;
353 }
354 else
355 {
356 p[m_sigma_y_idx] = nsigma_y;
357 }
358}
359
360template <typename realT>
361realT array2FitGaussian2D<realT>::theta( realT *p )
362{
363 if( m_theta_idx < 0 )
364 {
365 return m_theta;
366 }
367 else
368 {
369 return p[m_theta_idx];
370 }
371}
372
373template <typename realT>
374void array2FitGaussian2D<realT>::theta( realT *p, realT ntheta )
375{
376 if( m_theta_idx < 0 )
377 {
378 m_theta = ntheta;
379 }
380 else
381 {
382 p[m_theta_idx] = ntheta;
383 }
384}
385
386template <typename realT>
387realT array2FitGaussian2D<realT>::sigma( realT *p )
388{
389 if( m_sigma_idx < 0 )
390 {
391 return m_sigma;
392 }
393 else
394 {
395 return p[m_sigma_idx];
396 }
397}
398
399template <typename realT>
400void array2FitGaussian2D<realT>::sigma( realT *p, realT nsigma )
401{
402 if( m_sigma_idx < 0 )
403 {
404 m_sigma = nsigma;
405 }
406 else
407 {
408 p[m_sigma_idx] = nsigma;
409 }
410}
411
412template <typename realT>
413realT array2FitGaussian2D<realT>::a( realT *p )
414{
415 // This aliases sigma_x after param normalization
416 if( m_sigma_x_idx < 0 )
417 {
418 return m_a;
419 }
420 else
421 {
422 return p[m_sigma_x_idx];
423 }
424}
425
426template <typename realT>
427void array2FitGaussian2D<realT>::a( realT *p, realT na )
428{
429 // This aliases sigma_x after param normalization
430 if( m_sigma_x_idx < 0 )
431 {
432 m_a = na;
433 }
434 else
435 {
436 p[m_sigma_x_idx] = na;
437 }
438}
439
440template <typename realT>
441realT array2FitGaussian2D<realT>::b( realT *p )
442{
443 // This aliases sigma_y after param normalization
444 if( m_sigma_y_idx < 0 )
445 {
446 return m_b;
447 }
448 else
449 {
450 return p[m_sigma_y_idx];
451 }
452}
453
454template <typename realT>
455void array2FitGaussian2D<realT>::b( realT *p, realT nb )
456{
457 // This aliases sigma_y after param normalization
458 if( m_sigma_y_idx < 0 )
459 {
460 m_b = nb;
461 }
462 else
463 {
464 p[m_sigma_y_idx] = nb;
465 }
466}
467
468template <typename realT>
469realT array2FitGaussian2D<realT>::c( realT *p )
470{
471 // This aliases theta after param normalization
472 if( m_theta_idx < 0 )
473 {
474 return m_c;
475 }
476 else
477 {
478 return p[m_theta_idx];
479 }
480}
481
482template <typename realT>
483void array2FitGaussian2D<realT>::c( realT *p, realT nc )
484{
485 // This aliases theta after param normalization
486 if( m_theta_idx < 0 )
487 {
488 m_c = nc;
489 }
490 else
491 {
492 p[m_theta_idx] = nc;
493 }
494}
495
496template <typename realT>
497int array2FitGaussian2D<realT>::nparams()
498{
499 return m_nparams;
500}
501
502} // namespace fit
503} // namespace math
504
505} // namespace mx
506
507#endif // math_fit_array2FitGaussian2D_hpp
@ notimpl
A component or technique is not implemented.
error_t mxlib_error_report(const error_t &code, const std::string &expl, const std::source_location &loc=std::source_location::current())
Print a report to stderr given an mxlib error_t code and explanation and return the code.
Definition error.hpp:331
constexpr floatT six_fifths()
Return 6/5 in the specified precision.
The mxlib c++ namespace.
Definition mxlib.hpp:37
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.