mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
gaussian.hpp
Go to the documentation of this file.
1/** \file gaussian.hpp
2 * \author Jared R. Males
3 * \brief Declarations for utilities related to the Gaussian function.
4 * \ingroup gen_math_files
5 *
6 */
7
8//***********************************************************************//
9// Copyright 2015, 2016, 2017, 2018, 2019, 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 gaussian_hpp
28#define gaussian_hpp
29
30#include <cmath>
31
32namespace mx
33{
34namespace math
35{
36namespace func
37{
38
39/// Constant to convert between the Gaussian width parameter and FWHM
40/** Used for
41 *
42 * \f$ FWHM = 2\sqrt{2\log2}\sigma \f$
43 *
44 * This was calculated in long double precision.
45 *
46 * \ingroup gen_math_gaussians
47 */
48template <typename floatT>
49constexpr floatT twosqrt2log2()
50{
51 return static_cast<floatT>( 2.3548200450309493820231386529193992754947713787716 );
52}
53
54/// Convert from FWHM to the Gaussian width parameter
55/** Performs the conversion:
56 *
57 * \f$ \sigma = 2\sqrt{2\log2}FWHM \f$
58 *
59 * \returns the converted value of the Gaussian width parameter
60 *
61 * \ingroup gen_math_gaussians
62 */
63template <typename floatT>
64floatT fwhm2sigma( floatT fw /**< [in] the full-width at half maximum */ )
65{
66 return fw / twosqrt2log2<floatT>();
67}
68
69/// Convert from Gaussian width parameter to FWHM
70/** Performs the conversion:
71 *
72 * \f$ FWHM = 2\sqrt{2\log2}\sigma \f$
73 *
74 * \returns the converted value of the full-width at half maximum
75 *
76 * \ingroup gen_math_gaussians
77 */
78template <typename floatT>
79floatT sigma2fwhm( floatT sig /**< [in] the Gaussian width parameter */ )
80{
81 return sig * twosqrt2log2<floatT>();
82}
83
84/// Find value at position (x) of the 1D arbitrarily-centered symmetric Gaussian
85/**
86 * Computes:
87 * \f$ G(x) = G_0 + G\exp[-(0.5/\sigma^2)((x-x_0)^2)]\f$
88 *
89 *
90 * \returns the value of the 1D arbitrarily-centered symmetric Gaussian at (x)
91 *
92 * \tparam realT is the type to use for arithmetic
93 *
94 * \ingroup gen_math_gaussians
95 *
96 *
97 */
98template <typename realT>
99realT gaussian( const realT x, ///< [in] is the x-position at which to evaluate the Gaussian
100 const realT G0, ///< [in] is the constant to add to the Gaussian
101 const realT G, ///< [in] is the scaling factor (peak height = G-G0)
102 const realT x0, ///< [in] is the x-coordinate of the center
103 const realT sigma ///< [in] is the width of the Gaussian.
104)
105{
106 return G0 + G * exp( -( static_cast<realT>( 0.5 ) / ( sigma * sigma ) * ( ( ( x - x0 ) * ( x - x0 ) ) ) ) );
107}
108
109/// Find value at position (x,y) of the 2D arbitrarily-centered symmetric Gaussian
110/**
111 * Computes:
112 * \f[
113 f(x,y) = G_0 + G \exp[-(0.5/\sigma^2)((x-x_0)^2+(y-y_0)^2)]
114 * \f]
115 *
116 * \returns the value of the 2D arbitrarily-centered symmetric Gaussian at (x,y)
117 *
118 * \tparam realT is the type to use for arithmetic
119 *
120 * \ingroup gen_math_gaussians
121 *
122 "[test doc]"
123 *
124 */
125template <typename realT>
126realT gaussian2D( const realT x, ///< [in] the x-position at which to evaluate the Gaussian
127 const realT y, ///< [in] the y-positoin at which to evaluate the Gaussian
128 const realT G0, ///< [in] the constant to add to the Gaussian
129 const realT G, ///< [in] the scaling factor (peak height is G-G0)
130 const realT x0, ///< [in] the x-coordinate of the center
131 const realT y0, ///< [in] the y-coordinate of the center
132 const realT sigma ///< [in] the width of the Gaussian.
133)
134{
135 return G0 +
136 G * std::exp( -( 0.5 / ( sigma * sigma ) * ( ( ( x - x0 ) * ( x - x0 ) ) + ( ( y - y0 ) * ( y - y0 ) ) ) ) );
137}
138
139/// Fill in an array with the 2D arbitrarily-centered symmetric Gaussian
140/**
141 * At each pixel (x,y) of the array this computes:
142 *
143 * \f$ f(x,y) = G_0 + G\exp[-(0.5/\sigma^2)((x-x_0)^2+(y-y_0)^2)] \f$
144 *
145 * \tparam realT is the type to use for arithmetic
146 *
147 * \ingroup gen_math_gaussians
148 */
149template <typename realT>
150void gaussian2D( realT *arr, ///< [out] is the allocated array to fill in
151 size_t nx, ///< [in] is the size of the x dimension of the array
152 size_t ny, ///< [in] is the size of the y dimension of the array
153 const realT G0, ///< [in] is the constant to add to the Gaussian
154 const realT G, ///< [in] is the scaling factor (peak height = G-G0)
155 const realT x0, ///< [in] is the x-coordinate of the center
156 const realT y0, ///< [in] is the y-coordinate of the center
157 const realT sigma ///< [in] is the third rotation and scaling factor
158)
159{
160 size_t idx;
161
162 for( size_t j = 0; j < ny; ++j )
163 {
164 for( size_t i = 0; i < nx; ++i )
165 {
166 idx = i + j * nx;
167
168 arr[idx] = gaussian2D( (realT)i, (realT)j, G0, G, x0, y0, sigma );
169 }
170 }
171}
172
173/// Find value at position (x,y) of the 2D general elliptical Gaussian
174/**
175 * Computes:
176 *
177 * \f$ f(x,y) = G_0 + G\exp [-0.5( a(x-x_0)^2 + b(x-x_0)(y-y_0) + c(y-y_0)^2 ]\f$
178 *
179 * where, for a counter-clockwise rotation \f$ \theta \f$, we have
180 *
181 * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
182 *
183 * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
184 *
185 * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
186 *
187 * In this version the parameters are specified directly as (a,b,c), in particular avoiding the trig function calls.
188 * This should be much more efficient, and so this version should be used inside fitting routines, etc. However
189 * note that the matrix {a b}{b c} must be <a
190 * href="http://mathworld.wolfram.com/PositiveDefiniteMatrix.html">positive-definite</a> otherwise infinities can result
191 * from the argument of the exponent being positive.
192 *
193 * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
194 * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back. The function gaussian2D_ang() is a
195 * wrapper for this function, which instead accepts (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) as inputs.
196 *
197 * \returns the value of the 2D elliptical Gaussian at (x,y)
198 *
199 * \tparam realT is the type to use for arithmetic
200 *
201 * \ingroup gen_math_gaussians
202 */
203template <typename realT>
204realT gaussian2D( const realT x, ///< [in] the x-position at which to evaluate the Gaussian
205 const realT y, ///< [in] the y-positoin at which to evaluate the Gaussian
206 const realT G0, ///< [in] the constant to add to the Gaussian
207 const realT G, ///< [in] the scaling factor (peak = G-G0)
208 const realT x0, ///< [in] the x-coordinate of the center
209 const realT y0, ///< [in] the y-coordinate of the center
210 const realT a, ///< [in] the first rotation and scaling factor
211 const realT b, ///< [in] the second rotation and scaling factor
212 const realT c ///< [in] the third rotation and scaling factor
213)
214{
215 realT dx = x - x0;
216 realT dy = y - y0;
217
218 return G0 + G * std::exp( -0.5 * ( a * dx * dx + 2. * b * dx * dy + c * dy * dy ) );
219}
220
221/// Convert from (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) for the elliptical Gaussian.
222/** The general 2D elliptical Gaussian
223 *
224 * \f$ f(x,y) = G_0 + G\exp [-0.5( a(x-x_0)^2 + b(x-x_0)(y-y_0) + c(y-y_0)^2 ]\f$
225 *
226 * can be expressed in terms of widths and a rotation angle using:
227 *
228 * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
229 *
230 * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
231 *
232 * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
233 *
234 * where \f$ \theta \f$ specifies a counter-clockwise rotation.
235 *
236 * This function calculates (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) from inputs (a,b,c). It adopts
237 * the convention that the long axis of the ellipse is \f$\sigma_x\f$, and \f$\theta\f$ is chosen
238 * appropriately. Note that \f$-\frac{\pi}{2} < \theta < \frac{\pi}{2}\f$.
239 *
240 * \tparam realT is the type to use for arithmetic
241 *
242 * \ingroup gen_math_gaussians
243 */
244template <typename realT>
245void gaussian2D_gen2rot( realT &sigma_x, ///< [out] the width parameter in the rotated x-direction
246 realT &sigma_y, ///< [out] the width parameter in the rotated y-direction
247 realT &theta, ///< [out] the c.c.w rotation
248 const realT a, ///< [in] the first rotation and scaling parameter
249 const realT b, ///< [in] the second rotation and scaling parameter
250 const realT c ///< [in] the the third rotation and scaling parameter
251)
252{
253 realT x1, x2, s, s2, theta0, theta1;
254
255 realT arg = a * a - 2 * a * c + 4 * b * b + c * c;
256 if( arg < 0 )
257 {
258 x2 = 0.5 * ( a + c );
259 x1 = x2;
260 }
261 else
262 {
263 // There are two roots, one is 1/sigma_x^2 and one is 1/sigma_y^2
264 x2 = 0.5 * ( a + c ) + 0.5 * sqrt( arg );
265 x1 = 0.5 * ( a + c ) - 0.5 * sqrt( arg );
266 }
267
268 // Our convention is that the larger width is sigma_x
269 sigma_x = sqrt( 1. / x1 );
270 sigma_y = sqrt( 1. / x2 );
271
272 //----------------------------------------------------------------------------//
273 // Choosing theta:
274 // There is an ambiguity in theta and which direction (x,y) is the long axis
275 // Here we choose theta so that it specifies the long direction, sigma_x
276 //----------------------------------------------------------------------------//
277
278 // s is (sin(theta))^2
279 // s2 = (a-x2)*(a-x2)/(b*b + (a-x2)*(a-x2));
280 s = ( a - x1 ) * ( a - x1 ) / ( b * b + ( a - x1 ) * ( a - x1 ) );
281
282 // First check if x1-x2 will be close to zero
283
284 if( fabs( x1 - x2 ) < 1e-12 )
285 {
286 theta = 0;
287 return;
288 }
289
290 theta0 = 0.5 * asin( 2 * b / ( x1 - x2 ) ); // This always gives the correct sign
291 theta1 = asin( sqrt( s ) ); // This always gives the correct magnitude, and seems to be more accurate
292
293 // Compare signs. If they match, then we use theta1
294 if( std::signbit( theta0 ) == std::signbit( theta1 ) )
295 {
296 theta = theta1;
297 }
298 else
299 {
300 // Otherwise, we switch quadrants
301 theta = asin( -sqrt( s ) );
302 }
303}
304
305/// Convert from (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) to (a,b,c) for the elliptical Gaussian.
306/** The general 2D elliptical Gaussian
307 *
308 * \f$ f(x,y) = G_0 + G\exp [-0.5( a(x-x_0)^2 + b(x-x_0)(y-y_0) + c(y-y_0)^2 ]\f$
309 *
310 * can be expressed in terms of widths and a rotation angle using:
311 *
312 * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
313 *
314 * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
315 *
316 * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
317 *
318 * where \f$ \theta \f$ specifies a counter-clockwise rotation.
319 *
320 * This function calculates (a,b,c) from inputs (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$).
321 *
322 * \tparam realT is the type to use for arithmetic
323 *
324 * \ingroup gen_math_gaussians
325 */
326template <typename realT>
327void gaussian2D_rot2gen( realT &a, ///< [out] the first rotation and scaling parameter
328 realT &b, ///< [out] the second rotation and scaling parameter
329 realT &c, ///< [out] the the third rotation and scaling parameter
330 const realT sigma_x, ///< [in] the width parameter in the rotated x-direction
331 const realT sigma_y, ///< [in] the width parameter in the rotated y-direction
332 const realT theta ///< [in] the c.c.w rotation
333)
334{
335 realT sn, cs, sx2, sy2;
336
337 sn = sin( theta );
338 cs = cos( theta );
339 sx2 = sigma_x * sigma_x;
340 sy2 = sigma_y * sigma_y;
341
342 a = cs * cs / sx2 + sn * sn / sy2;
343 b = sn * cs * ( 1. / sx2 - 1. / sy2 );
344 c = sn * sn / sx2 + cs * cs / sy2;
345}
346
347/// Find value at position (x,y) of the 2D rotated elliptical Gaussian
348/**
349 * Computes:
350 * \f$ f(x,y) = G_0 + G\exp [-0.5( a(x-x_0)^2 + b(x-x_0)(y-y_0) + c(y-y_0)^2 ]\f$
351 *
352 * where, for a counter-clockwise rotation \f$ \theta \f$, we have
353 *
354 * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
355 *
356 * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
357 *
358 * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
359 *
360 * This is a convenience wrapper for the general elliptical Gaussian function gaussian2D(), where here
361 * (a,b,c) are first calculated from (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$). This will in general be
362 * slower due to the trig function calls, so the (a,b,c) version should be used most of the time.
363 *
364 * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
365 * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back. The function gaussian2D_rot() is a
366 * wrapper for this function, which instead accepts (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) as inputs.
367 *
368 * \returns the value of the 2D elliptical Gaussian at (x,y)
369 *
370 * \tparam realT is the type to use for arithmetic
371 *
372 * \ingroup gen_math_gaussians
373 */
374template <typename realT>
375realT gaussian2D_ang( const realT x, ///< [in] the x-position at which to evaluate the Gaussian
376 const realT y, ///< [in] the y-positoin at which to evaluate the Gaussian
377 const realT G0, ///< [in] the constant to add to the Gaussian
378 const realT G, ///< [in] the scaling factor (peak height = G-G0)
379 const realT x0, ///< [in] the x-coordinate of the center
380 const realT y0, ///< [in] the y-coordinate of the center
381 const realT sigma_x, ///< [in] the width in the rotated x direction
382 const realT sigma_y, ///< [in] the width in the rotated y direction
383 const realT theta ///< [in] the counter-clockwise rotation angle
384)
385{
386 realT a, b, c;
387
388 gaussian2D_rot2gen( a, b, c, sigma_x, sigma_y, theta );
389
390 return gaussian2D( x, y, G0, G, x0, y0, a, b, c );
391}
392
393/// Fill in an array with the 2D general elliptical Gaussian
394/**
395 * At each pixel (x,y) of the array this computes:
396 *
397 * \f$ f(x,y) = G_0 + G\exp [-0.5( a(x-x_0)^2 + b(x-x_0)(y-y_0) + c(y-y_0)^2 ]\f$
398 *
399 * where, for a counter-clockwise rotation \f$ \theta \f$, we have
400 *
401 * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
402 *
403 * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
404 *
405 * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
406 *
407 * In this version the parameters are specified directly as (a,b,c), in particular avoiding the trig function calls.
408 * This should be much more efficient, and so this version should be used inside fitting routines, etc.
409 *
410 * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
411 * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back. The function gaussian2D_ang() is a
412 * wrapper for this function, which instead accepts (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) as inputs.
413 *
414 * \tparam realT is the type to use for arithmetic
415 *
416 * \ingroup gen_math_gaussians
417 */
418template <typename realT>
419void gaussian2D( realT *arr, ///< [out] the native array to populate with the Gaussian function
420 size_t nx, ///< [in] the x-size of the array, in pixels
421 size_t ny, ///< [in] the y-size of the array, in pixels
422 const realT G0, ///< [in] the constant to add to the Gaussian
423 const realT G, ///< [in] the scaling factor (peak = G)
424 const realT x0, ///< [in] the x-coordinate of the center, in pixels
425 const realT y0, ///< [in] the y-coordinate of the center, in pixels
426 const realT a, ///< [in] is the first rotation and scaling factor
427 const realT b, ///< [in] is the second rotation and scaling factor
428 const realT c ///< [in] is the third rotation and scaling factor
429)
430{
431 size_t idx;
432
433 for( size_t j = 0; j < ny; ++j )
434 {
435 for( size_t i = 0; i < nx; ++i )
436 {
437 idx = i + j * nx;
438
439 arr[idx] = gaussian2D( (realT)i, (realT)j, G0, G, x0, y0, a, b, c );
440 }
441 }
442}
443
444/// Fill in an array with the 2D general elliptical Gaussian
445/**
446 * At each pixel (x,y) of the array this computes:
447 *
448 * \f$ f(x,y) = G_0 + G\exp [-0.5( a(x-x_0)^2 + b(x-x_0)(y-y_0) + c(y-y_0)^2 ]\f$
449 *
450 * where, for a counter-clockwise rotation \f$ \theta \f$, we have
451 *
452 * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
453 *
454 * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
455 *
456 * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
457 *
458 * This is a convenience wrapper for the general elliptical Gaussian function
459 * gaussian2D( realT *, size_t, size_t, const realT, const realT, const realT, const realT, const realT, const realT,
460 * const realT) , where here (a,b,c) are first calculated from (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$).
461 *
462 * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
463 * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back.
464 *
465 *
466 * \tparam realT is the type to use for arithmetic
467 *
468 * \ingroup gen_math_gaussians
469 */
470template <typename realT>
471void gaussian2D_ang( realT *arr, ///< [out] the native array to populate with the Gaussian function
472 size_t nx, ///< [in] the x-size of the array, in pixels
473 size_t ny, ///< [in] the y-size of the array, in pixels
474 const realT G0, ///< [in] the constant to add to the Gaussian
475 const realT G, ///< [in] the scaling factor (peak = G)
476 const realT x0, ///< [in] the x-coordinate of the center, in pixels
477 const realT y0, ///< [in] the y-coordinate of the center, in pixels
478 const realT sigma_x, ///< [in] the width in the rotated x direction, in pixels
479 const realT sigma_y, ///< [in] the width in the rotated y direction, in pixels
480 const realT theta ///< [in] the counter-clockwise rotation angle, in radians
481)
482{
483 realT a, b, c;
484 size_t idx;
485
486 // Get the (a,b,c) parameters so the trig only happens once
487 gaussian2D_rot2gen( a, b, c, sigma_x, sigma_y, theta );
488
489 gaussian2D( arr, nx, ny, G0, G, x0, y0, a, b, c );
490}
491
492/// Calculate the Jacobian at position (x,y) for the 2D general elliptical Gaussian
493/** \note this has not been verified and may be incorrect.
494 *
495 * Given:
496 *
497 * \f$ f(x,y) = G_0 + G\exp [-0.5( a(x-x_0)^2 + b(x-x_0)(y-y_0) + c(y-y_0)^2 ]\f$
498 *
499 * we calculate
500 *
501 * \f$ \frac{\partial G}{\partial G_0} = 1 \f$
502 *
503 * \f$ \frac{\partial G}{\partial G} = (G - G_0)/A \f$
504 *
505 * \f$ \frac{\partial G}{\partial x_0} = 0.5(G-G_0)( 2a(x-x_0) + b(y-y_0)) \f$
506 *
507 * \f$ \frac{\partial G}{\partial y_0} = 0.5(G-G_0) ( b(x-x_0) + 2c(y-y_0)) \f$
508 *
509 * \f$ \frac{\partial G}{\partial a} = -0.5(G-G_0) ( (x-x_0)^2 ) \f$
510 *
511 * \f$ \frac{\partial G}{\partial b} = -0.5(G-G_0) ( (x-x_0)(y-y_0) ) \f$
512 *
513 * \f$ \frac{\partial G}{\partial c} = -0.5(G-G_0) ( (y-y_0)^2 )\f$
514 *
515 * \param j is a 7 element vector which is populated with the derivatives
516 * \param x is the x-position at which to evaluate the Gaussian
517 * \param y is the y-positoin at which to evaluate the Gaussian
518 * \param G0 is the constant to add to the Gaussian
519 * \param G is the scaling factor (peak = A)
520 * \param x0 is the x-coordinate of the center
521 * \param y0 is the y-coordinate of the center
522 * \param a is the first rotation and scaling factor
523 * \param b is the second rotation and scaling factor
524 * \param c is the third rotation and scaling factor
525 *
526 *
527 * \tparam realT is the type to use for arithmetic
528 *
529 * \ingroup gen_math_gaussians
530 */
531template <typename realT>
532void gaussian2D_jacobian( realT *j,
533 const realT x,
534 const realT y,
535 const realT G0,
536 const realT G,
537 const realT x0,
538 const realT y0,
539 const realT a,
540 const realT b,
541 const realT c )
542{
543 realT G_G0 = gaussian2D<realT>( x, y, 0, G, x0, y0, a, b, c );
544
545 j[0] = (realT)1;
546
547 j[1] = ( G_G0 ) / G;
548
549 j[2] = 0.5 * G_G0 * ( 2 * a * ( x - x0 ) + b * ( y - y0 ) );
550
551 j[3] = 0.5 * G_G0 * ( b * ( x - x0 ) + 2 * c * ( y - y0 ) );
552
553 j[4] = -0.5 * G_G0 * ( ( x - x0 ) * ( x - x0 ) );
554
555 j[5] = -0.5 * G_G0 * ( ( x - x0 ) * ( y - y0 ) );
556
557 j[6] = -0.5 * G_G0 * ( ( y - y0 ) * ( y - y0 ) );
558}
559
560} // namespace func
561} // namespace math
562} // namespace mx
563
564#endif // gaussian_hpp
realT gaussian2D(const realT x, const realT y, const realT G0, const realT G, const realT x0, const realT y0, const realT sigma)
Find value at position (x,y) of the 2D arbitrarily-centered symmetric Gaussian.
Definition gaussian.hpp:126
floatT sigma2fwhm(floatT sig)
Convert from Gaussian width parameter to FWHM.
Definition gaussian.hpp:79
floatT fwhm2sigma(floatT fw)
Convert from FWHM to the Gaussian width parameter.
Definition gaussian.hpp:64
realT gaussian2D_ang(const realT x, const realT y, const realT G0, const realT G, const realT x0, const realT y0, const realT sigma_x, const realT sigma_y, const realT theta)
Find value at position (x,y) of the 2D rotated elliptical Gaussian.
Definition gaussian.hpp:375
realT gaussian(const realT x, const realT G0, const realT G, const realT x0, const realT sigma)
Find value at position (x) of the 1D arbitrarily-centered symmetric Gaussian.
Definition gaussian.hpp:99
void gaussian2D_gen2rot(realT &sigma_x, realT &sigma_y, realT &theta, const realT a, const realT b, const realT c)
Convert from (a,b,c) to ( , , ) for the elliptical Gaussian.
Definition gaussian.hpp:245
void gaussian2D_jacobian(realT *j, const realT x, const realT y, const realT G0, const realT G, const realT x0, const realT y0, const realT a, const realT b, const realT c)
Calculate the Jacobian at position (x,y) for the 2D general elliptical Gaussian.
Definition gaussian.hpp:532
constexpr floatT twosqrt2log2()
Constant to convert between the Gaussian width parameter and FWHM.
Definition gaussian.hpp:49
void gaussian2D_rot2gen(realT &a, realT &b, realT &c, const realT sigma_x, const realT sigma_y, const realT theta)
Convert from ( , , ) to (a,b,c) for the elliptical Gaussian.
Definition gaussian.hpp:327
The mxlib c++ namespace.
Definition mxlib.hpp:37