mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
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 
32 
33 namespace mx
34 {
35 namespace math
36 {
37 namespace func
38 {
39 
40 ///Constant to convert between the Gaussian width parameter and FWHM
41 /** Used for
42  *
43  * \f$ FWHM = 2\sqrt{2\log2}\sigma \f$
44  *
45  * This was calculated in long double precision.
46  *
47  * \ingroup gen_math_gaussians
48  */
49 template<typename floatT>
50 constexpr floatT twosqrt2log2()
51 {
52  return static_cast<floatT>(2.3548200450309493820231386529193992754947713787716);
53 }
54 
55 ///Convert from FWHM to the Gaussian width parameter
56 /** Performs the conversion:
57  *
58  * \f$ \sigma = 2\sqrt{2\log2}FWHM \f$
59  *
60  * \returns the converted value of the Gaussian width parameter
61  *
62  * \ingroup gen_math_gaussians
63  */
64 template<typename floatT>
65 floatT fwhm2sigma(floatT fw /**< [in] the full-width at half maximum */)
66 {
67  return fw / twosqrt2log2<floatT>();
68 }
69 
70 ///Convert from Gaussian width parameter to FWHM
71 /** Performs the conversion:
72  *
73  * \f$ FWHM = 2\sqrt{2\log2}\sigma \f$
74  *
75  * \returns the converted value of the full-width at half maximum
76  *
77  * \ingroup gen_math_gaussians
78  */
79 template<typename floatT>
80 floatT sigma2fwhm(floatT sig /**< [in] the Gaussian width parameter */)
81 {
82  return sig*twosqrt2log2<floatT>();
83 }
84 
85 ///Find value at position (x) of the 1D arbitrarily-centered symmetric Gaussian
86 /**
87  * Computes:
88  * \f$ G(x) = G_0 + G\exp[-(0.5/\sigma^2)((x-x_0)^2)]\f$
89  *
90  *
91  * \returns the value of the 1D arbitrarily-centered symmetric Gaussian at (x)
92  *
93  * \tparam realT is the type to use for arithmetic
94  *
95  * \ingroup gen_math_gaussians
96  *
97  *
98  */
99 template<typename realT>
100 realT gaussian( const realT x, ///< [in] is the x-position at which to evaluate the Gaussian
101  const realT G0, ///< [in] is the constant to add to the Gaussian
102  const realT G, ///< [in] is the scaling factor (peak height = G-G0)
103  const realT x0, ///< [in] is the x-coordinate of the center
104  const realT sigma ///< [in] is the width of the Gaussian.
105  )
106 {
107  return G0 + G * exp( -( static_cast<realT>(0.5)/(sigma*sigma) * ( ( (x-x0)*(x-x0))) ));
108 }
109 
110 ///Find value at position (x,y) of the 2D arbitrarily-centered symmetric Gaussian
111 /**
112  * Computes:
113  * \f[
114  f(x,y) = G_0 + G \exp[-(0.5/\sigma^2)((x-x_0)^2+(y-y_0)^2)]
115  * \f]
116  *
117  * \returns the value of the 2D arbitrarily-centered symmetric Gaussian at (x,y)
118  *
119  * \tparam realT is the type to use for arithmetic
120  *
121  * \ingroup gen_math_gaussians
122  *
123  * \test Scenario: Verify direction and accuracy of various image shifts \ref tests_improc_imageTransforms_imageShift "[test doc]"
124  *
125  */
126 template<typename realT>
127 realT gaussian2D( const realT x, ///< [in] the x-position at which to evaluate the Gaussian
128  const realT y, ///< [in] the y-positoin at which to evaluate the Gaussian
129  const realT G0, ///< [in] the constant to add to the Gaussian
130  const realT G, ///< [in] the scaling factor (peak height is G-G0)
131  const realT x0, ///< [in] the x-coordinate of the center
132  const realT y0, ///< [in] the y-coordinate of the center
133  const realT sigma ///< [in] the width of the Gaussian.
134  )
135 {
136  return G0 + 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  */
149 template<typename realT>
150 void 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 href="http://mathworld.wolfram.com/PositiveDefiniteMatrix.html">positive-definite</a>
190  * otherwise infinities can result from the argument of the exponent being positive.
191  *
192  * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
193  * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back. The function gaussian2D_ang() is a
194  * wrapper for this function, which instead accepts (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) as inputs.
195  *
196  * \returns the value of the 2D elliptical Gaussian at (x,y)
197  *
198  * \tparam realT is the type to use for arithmetic
199  *
200  * \ingroup gen_math_gaussians
201  */
202 template<typename realT>
203 realT gaussian2D( const realT x, ///< [in] the x-position at which to evaluate the Gaussian
204  const realT y, ///< [in] the y-positoin at which to evaluate the Gaussian
205  const realT G0, ///< [in] the constant to add to the Gaussian
206  const realT G, ///< [in] the scaling factor (peak = G-G0)
207  const realT x0, ///< [in] the x-coordinate of the center
208  const realT y0, ///< [in] the y-coordinate of the center
209  const realT a, ///< [in] the first rotation and scaling factor
210  const realT b, ///< [in] the second rotation and scaling factor
211  const realT c ///< [in] the third rotation and scaling factor
212  )
213 {
214  realT dx = x-x0;
215  realT dy = y-y0;
216 
217  return G0 + G*std::exp( -0.5* ( a*dx*dx + 2.*b*dx*dy + c*dy*dy));
218 
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  */
244 template<typename realT>
245 void 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 
306 ///Convert from (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) to (a,b,c) for the elliptical Gaussian.
307 /** The general 2D elliptical Gaussian
308  *
309  * \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$
310  *
311  * can be expressed in terms of widths and a rotation angle using:
312  *
313  * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
314  *
315  * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
316  *
317  * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
318  *
319  * where \f$ \theta \f$ specifies a counter-clockwise rotation.
320  *
321  * This function calculates (a,b,c) from inputs (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$).
322  *
323  * \tparam realT is the type to use for arithmetic
324  *
325  * \ingroup gen_math_gaussians
326  */
327 template<typename realT>
328 void gaussian2D_rot2gen( realT & a, ///< [out] the first rotation and scaling parameter
329  realT & b, ///< [out] the second rotation and scaling parameter
330  realT & c, ///< [out] the the third rotation and scaling parameter
331  const realT sigma_x, ///< [in] the width parameter in the rotated x-direction
332  const realT sigma_y, ///< [in] the width parameter in the rotated y-direction
333  const realT theta ///< [in] the c.c.w rotation
334  )
335 {
336  realT sn,cs, sx2, sy2;
337 
338  sn = sin(theta);
339  cs = cos(theta);
340  sx2 = sigma_x * sigma_x;
341  sy2 = sigma_y * sigma_y;
342 
343  a = cs*cs/sx2 + sn*sn/sy2;
344  b = sn*cs*(1./sx2-1./sy2);
345  c = sn*sn/sx2 + cs*cs/sy2;
346 }
347 
348 ///Find value at position (x,y) of the 2D rotated elliptical Gaussian
349 /**
350  * Computes:
351  * \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$
352  *
353  * where, for a counter-clockwise rotation \f$ \theta \f$, we have
354  *
355  * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
356  *
357  * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
358  *
359  * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
360  *
361  * This is a convenience wrapper for the general elliptical Gaussian function gaussian2D(), where here
362  * (a,b,c) are first calculated from (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$). This will in general be
363  * slower due to the trig function calls, so the (a,b,c) version should be used most of the time.
364  *
365  * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
366  * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back. The function gaussian2D_rot() is a
367  * wrapper for this function, which instead accepts (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) as inputs.
368  *
369  * \returns the value of the 2D elliptical Gaussian at (x,y)
370  *
371  * \tparam realT is the type to use for arithmetic
372  *
373  * \ingroup gen_math_gaussians
374  */
375 template<typename realT>
376 realT gaussian2D_ang( const realT x, ///< [in] the x-position at which to evaluate the Gaussian
377  const realT y, ///< [in] the y-positoin at which to evaluate the Gaussian
378  const realT G0, ///< [in] the constant to add to the Gaussian
379  const realT G, ///< [in] the scaling factor (peak height = G-G0)
380  const realT x0, ///< [in] the x-coordinate of the center
381  const realT y0, ///< [in] the y-coordinate of the center
382  const realT sigma_x, ///< [in] the width in the rotated x direction
383  const realT sigma_y, ///< [in] the width in the rotated y direction
384  const realT theta ///< [in] the counter-clockwise rotation angle
385  )
386 {
387  realT a, b, c;
388 
389  gaussian2D_rot2gen(a,b,c, sigma_x, sigma_y, theta);
390 
391  return gaussian2D(x,y,G0, G,x0,y0, a,b,c);
392 }
393 
394 /// Fill in an array with the 2D general elliptical Gaussian
395 /**
396  * At each pixel (x,y) of the array this computes:
397  *
398  * \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$
399  *
400  * where, for a counter-clockwise rotation \f$ \theta \f$, we have
401  *
402  * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
403  *
404  * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
405  *
406  * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
407  *
408  * In this version the parameters are specified directly as (a,b,c), in particular avoiding the trig function calls.
409  * This should be much more efficient, and so this version should be used inside fitting routines, etc.
410  *
411  * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
412  * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back. The function gaussian2D_ang() is a
413  * wrapper for this function, which instead accepts (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) as inputs.
414  *
415  * \tparam realT is the type to use for arithmetic
416  *
417  * \ingroup gen_math_gaussians
418  */
419 template<typename realT>
420 void gaussian2D( realT * arr, ///< [out] the native array to populate with the Gaussian function
421  size_t nx, ///< [in] the x-size of the array, in pixels
422  size_t ny, ///< [in] the y-size of the array, in pixels
423  const realT G0, ///< [in] the constant to add to the Gaussian
424  const realT G, ///< [in] the scaling factor (peak = G)
425  const realT x0, ///< [in] the x-coordinate of the center, in pixels
426  const realT y0, ///< [in] the y-coordinate of the center, in pixels
427  const realT a, ///< [in] is the first rotation and scaling factor
428  const realT b, ///< [in] is the second rotation and scaling factor
429  const realT c ///< [in] is the third rotation and scaling factor
430  )
431 {
432  size_t idx;
433 
434  for(size_t j=0;j<ny; ++j)
435  {
436  for(size_t i=0;i<nx; ++i)
437  {
438  idx = i + j*nx;
439 
440  arr[idx] = gaussian2D((realT) i, (realT) j,G0,G, x0, y0, a, b, c);
441  }
442  }
443 }
444 
445 
446 ///Fill in an array with the 2D general elliptical Gaussian
447 /**
448  * At each pixel (x,y) of the array this computes:
449  *
450  * \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$
451  *
452  * where, for a counter-clockwise rotation \f$ \theta \f$, we have
453  *
454  * \f$ a = \frac{\cos^2 \theta}{\sigma_x^2} + \frac{\sin^2\theta}{\sigma_y^2}\f$
455  *
456  * \f$ b = \frac{\sin 2\theta}{2} \left(\frac{1}{\sigma_x^2} - \frac{1}{\sigma_y^2} \right)\f$
457  *
458  * \f$ c = \frac{\sin^2 \theta}{\sigma_x^2} + \frac{\cos^2\theta}{\sigma_y^2}\f$
459  *
460  * This is a convenience wrapper for the general elliptical Gaussian function
461  * gaussian2D( realT *, size_t, size_t, const realT, const realT, const realT, const realT, const realT, const realT, const realT) ,
462  * where here (a,b,c) are first calculated from (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$).
463  *
464  * The functions gaussian2D_gen2rot() and gaussian2D_rot2gen() provide conversions from
465  * (a,b,c) to (\f$\sigma_x\f$,\f$\sigma_y\f$,\f$\theta\f$) and back.
466  *
467  *
468  * \tparam realT is the type to use for arithmetic
469  *
470  * \ingroup gen_math_gaussians
471  */
472 template<typename realT>
473 void gaussian2D_ang( realT * arr, ///< [out] the native array to populate with the Gaussian function
474  size_t nx, ///< [in] the x-size of the array, in pixels
475  size_t ny, ///< [in] the y-size of the array, in pixels
476  const realT G0, ///< [in] the constant to add to the Gaussian
477  const realT G, ///< [in] the scaling factor (peak = G)
478  const realT x0, ///< [in] the x-coordinate of the center, in pixels
479  const realT y0, ///< [in] the y-coordinate of the center, in pixels
480  const realT sigma_x, ///< [in] the width in the rotated x direction, in pixels
481  const realT sigma_y, ///< [in] the width in the rotated y direction, in pixels
482  const realT theta ///< [in] the counter-clockwise rotation angle, in radians
483  )
484 {
485  realT a, b, c;
486  size_t idx;
487 
488  //Get the (a,b,c) parameters so the trig only happens once
489  gaussian2D_rot2gen(a,b,c,sigma_x, sigma_y, theta);
490 
491  gaussian2D(arr, nx, ny, G0, G, x0, y0, a,b,c);
492 }
493 
494 
495 ///Calculate the Jacobian at position (x,y) for the 2D general elliptical Gaussian
496 /** \note this has not been verified and may be incorrect.
497  *
498  * Given:
499  *
500  * \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$
501  *
502  * we calculate
503  *
504  * \f$ \frac{\partial G}{\partial G_0} = 1 \f$
505  *
506  * \f$ \frac{\partial G}{\partial G} = (G - G_0)/A \f$
507  *
508  * \f$ \frac{\partial G}{\partial x_0} = 0.5(G-G_0)( 2a(x-x_0) + b(y-y_0)) \f$
509  *
510  * \f$ \frac{\partial G}{\partial y_0} = 0.5(G-G_0) ( b(x-x_0) + 2c(y-y_0)) \f$
511  *
512  * \f$ \frac{\partial G}{\partial a} = -0.5(G-G_0) ( (x-x_0)^2 ) \f$
513  *
514  * \f$ \frac{\partial G}{\partial b} = -0.5(G-G_0) ( (x-x_0)(y-y_0) ) \f$
515  *
516  * \f$ \frac{\partial G}{\partial c} = -0.5(G-G_0) ( (y-y_0)^2 )\f$
517  *
518  * \param j is a 7 element vector which is populated with the derivatives
519  * \param x is the x-position at which to evaluate the Gaussian
520  * \param y is the y-positoin at which to evaluate the Gaussian
521  * \param G0 is the constant to add to the Gaussian
522  * \param G is the scaling factor (peak = A)
523  * \param x0 is the x-coordinate of the center
524  * \param y0 is the y-coordinate of the center
525  * \param a is the first rotation and scaling factor
526  * \param b is the second rotation and scaling factor
527  * \param c is the third rotation and scaling factor
528  *
529  *
530  * \tparam realT is the type to use for arithmetic
531  *
532  * \ingroup gen_math_gaussians
533  */
534 template<typename realT>
535 void gaussian2D_jacobian( realT *j,
536  const realT x,
537  const realT y,
538  const realT G0,
539  const realT G,
540  const realT x0,
541  const realT y0,
542  const realT a,
543  const realT b,
544  const realT c )
545 {
546  realT G_G0 = gaussian2D<realT>(x, y, 0, G, x0, y0, a, b ,c);
547 
548  j[0] = (realT) 1;
549 
550  j[1] = (G_G0)/G;
551 
552  j[2] = 0.5*G_G0 * ( 2*a*(x-x0) + b*(y-y0));
553 
554  j[3] = 0.5*G_G0 * ( b*(x-x0) + 2*c*(y-y0));
555 
556  j[4] = -0.5*G_G0 * ( (x-x0)*(x-x0) );
557 
558  j[5] = -0.5*G_G0 * ( (x-x0)*(y-y0) );
559 
560  j[6] = -0.5*G_G0 * ( (y-y0)*(y-y0) );
561 
562 }
563 
564 } //namespace func
565 } //namespace math
566 } //namespace mx
567 
568 #endif //gaussian_hpp
569 
570 
571 
constexpr units::realT G()
Newton's Gravitational Constant.
Definition: constants.hpp:51
constexpr units::realT c()
The speed of light.
Definition: constants.hpp:60
constexpr units::realT sigma()
Stefan-Boltzmann Constant.
Definition: constants.hpp:82
floatT sigma2fwhm(floatT sig)
Convert from Gaussian width parameter to FWHM.
Definition: gaussian.hpp:80
floatT fwhm2sigma(floatT fw)
Convert from FWHM to the Gaussian width parameter.
Definition: gaussian.hpp:65
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:100
void gaussian2D(realT *arr, size_t nx, size_t ny, const realT G0, const realT G, const realT x0, const realT y0, const realT a, const realT b, const realT c)
Fill in an array with the 2D general elliptical Gaussian.
Definition: gaussian.hpp:420
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:535
constexpr floatT twosqrt2log2()
Constant to convert between the Gaussian width parameter and FWHM.
Definition: gaussian.hpp:50
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:328
void gaussian2D_ang(realT *arr, size_t nx, size_t ny, const realT G0, const realT G, const realT x0, const realT y0, const realT sigma_x, const realT sigma_y, const realT theta)
Fill in an array with the 2D general elliptical Gaussian.
Definition: gaussian.hpp:473
The mxlib c++ namespace.
Definition: mxError.hpp:107