Commit 2a49e2107fb4874801a6da9fccef47f628c4e2d7

Authored by Jürgen Knödlseder
1 parent ffa7e42d

Limit the sky directions drawn in GModelSpatialEllipticalGauss::mc to an effecti…

…ve radius that is consistent with the Gaussian normalization (#1561).
src/model/GModelSpatialEllipticalGauss.cpp
@@ -36,6 +36,11 @@ @@ -36,6 +36,11 @@
36 #include "GModelSpatialRegistry.hpp" 36 #include "GModelSpatialRegistry.hpp"
37 37
38 /* __ Constants __________________________________________________________ */ 38 /* __ Constants __________________________________________________________ */
  39 +namespace {
  40 + const double c_theta_max = 2.0; //!< semiaxis multiplied for theta_max()
  41 + const double c_max_exponent = 0.5 * c_theta_max * c_theta_max;
  42 + const double c_fraction = 1.0 - std::exp(-c_max_exponent);
  43 +}
39 44
40 /* __ Globals ____________________________________________________________ */ 45 /* __ Globals ____________________________________________________________ */
41 const GModelSpatialEllipticalGauss g_elliptical_gauss_seed; 46 const GModelSpatialEllipticalGauss g_elliptical_gauss_seed;
@@ -242,12 +247,13 @@ GModelSpatialEllipticalGauss* GModelSpatialEllipticalGauss::clone(void) const @@ -242,12 +247,13 @@ GModelSpatialEllipticalGauss* GModelSpatialEllipticalGauss::clone(void) const
242 * @param[in] time Photon arrival time. 247 * @param[in] time Photon arrival time.
243 * @return Model value. 248 * @return Model value.
244 * 249 *
245 - * Evaluates the spatial component for an elliptical gauss source model. The  
246 - * source model is an elliptical gaussian function 250 + * Evaluates the spatial component for an elliptical Gaussian source model.
  251 + *
  252 + * The source model is an elliptical Gaussian function
247 * \f$S_{\rm p}(\theta, \phi | E, t)\f$, where 253 * \f$S_{\rm p}(\theta, \phi | E, t)\f$, where
248 - * \f$\theta\f$ is the angular separation between elliptical gauss centre and  
249 - * the actual location and \f$\phi\f$ the position angle with respect to the  
250 - * model centre, counted counterclockwise from North. 254 + * \f$\theta\f$ is the angular separation between elliptical Gaussian centre
  255 + * and the actual location and \f$\phi\f$ the position angle with respect to
  256 + * the model centre, counted counterclockwise from North.
251 * 257 *
252 * The function \f$f(\theta, \phi)\f$ is given by 258 * The function \f$f(\theta, \phi)\f$ is given by
253 * 259 *
@@ -367,7 +373,10 @@ double GModelSpatialEllipticalGauss::eval_gradients(const double&amp; theta, @@ -367,7 +373,10 @@ double GModelSpatialEllipticalGauss::eval_gradients(const double&amp; theta,
367 * @param[in,out] ran Random number generator. 373 * @param[in,out] ran Random number generator.
368 * @return Sky direction. 374 * @return Sky direction.
369 * 375 *
370 - * Draws an arbitrary sky position from the 2D gauss distribution. 376 + * Draws an arbitrary sky direction from the 2D ellipital Gaussian model.
  377 + * The drawn sky direction will be truncated to \f$2 \sigma\f$ offsets from
  378 + * the ellipse centre, where \f$\sigma\f$ is the effective Gaussian size
  379 + * in the direction of a specific position angle.
371 ***************************************************************************/ 380 ***************************************************************************/
372 GSkyDir GModelSpatialEllipticalGauss::mc(const GEnergy& energy, 381 GSkyDir GModelSpatialEllipticalGauss::mc(const GEnergy& energy,
373 const GTime& time, 382 const GTime& time,
@@ -382,8 +391,16 @@ GSkyDir GModelSpatialEllipticalGauss::mc(const GEnergy&amp; energy, @@ -382,8 +391,16 @@ GSkyDir GModelSpatialEllipticalGauss::mc(const GEnergy&amp; energy,
382 photon.time(time); 391 photon.time(time);
383 392
384 // Draw gaussian offset from each axis 393 // Draw gaussian offset from each axis
385 - double theta1 = semimajor() * ran.normal();  
386 - double theta2 = semiminor() * ran.normal(); 394 + double ran_major;
  395 + double ran_minor;
  396 + do {
  397 + ran_major = ran.normal();
  398 + } while (ran_major > c_theta_max);
  399 + do {
  400 + ran_minor = ran.normal();
  401 + } while (ran_minor > c_theta_max);
  402 + double theta1 = semimajor() * ran_major;
  403 + double theta2 = semiminor() * ran_minor;
387 404
388 // Compute total offset from model centre 405 // Compute total offset from model centre
389 double theta = std::sqrt(theta1 * theta1 + theta2 * theta2); 406 double theta = std::sqrt(theta1 * theta1 + theta2 * theta2);
@@ -431,10 +448,10 @@ bool GModelSpatialEllipticalGauss::contains(const GSkyDir&amp; dir, @@ -431,10 +448,10 @@ bool GModelSpatialEllipticalGauss::contains(const GSkyDir&amp; dir,
431 * 448 *
432 * @return Returns maximum model radius. 449 * @return Returns maximum model radius.
433 * 450 *
434 - * Returns the maximum of \f$2.5\f$ semimajor() and \f$2.5\f$ semiminor() as 451 + * Returns the maximum of \f$2\f$ semimajor() and \f$2\f$ semiminor() as
435 * approximate edge of the Gaussian. This limit is of course arbitrary, but 452 * approximate edge of the Gaussian. This limit is of course arbitrary, but
436 * allows to limit the integration region for response computation. The value 453 * allows to limit the integration region for response computation. The value
437 - * of 2.5 has been determined by experiment. Ideally, a large value should 454 + * of 2 has been determined by experiment. Ideally, a large value should
438 * be used to properly take into account the tails of the distribution, but 455 * be used to properly take into account the tails of the distribution, but
439 * this apparently leads to fit convergence problems (#1561). 456 * this apparently leads to fit convergence problems (#1561).
440 ***************************************************************************/ 457 ***************************************************************************/
@@ -442,8 +459,8 @@ double GModelSpatialEllipticalGauss::theta_max(void) const @@ -442,8 +459,8 @@ double GModelSpatialEllipticalGauss::theta_max(void) const
442 { 459 {
443 // Set maximum model radius 460 // Set maximum model radius
444 double theta_max = (semimajor() > semiminor()) 461 double theta_max = (semimajor() > semiminor())
445 - ? semimajor() * gammalib::deg2rad * 2.5  
446 - : semiminor() * gammalib::deg2rad * 2.5; 462 + ? semimajor() * gammalib::deg2rad * c_theta_max
  463 + : semiminor() * gammalib::deg2rad * c_theta_max;
447 464
448 // Return value 465 // Return value
449 return theta_max; 466 return theta_max;
@@ -768,7 +785,8 @@ void GModelSpatialEllipticalGauss::update() const @@ -768,7 +785,8 @@ void GModelSpatialEllipticalGauss::update() const
768 // approximation. 785 // approximation.
769 m_minor2 = m_minor_rad * m_minor_rad; 786 m_minor2 = m_minor_rad * m_minor_rad;
770 m_major2 = m_major_rad * m_major_rad; 787 m_major2 = m_major_rad * m_major_rad;
771 - double denom = gammalib::twopi * m_minor_rad * m_major_rad; 788 + double denom = gammalib::twopi * m_minor_rad * m_major_rad *
  789 + c_fraction;
772 m_norm = (denom > 0.0) ? 1.0 / denom : 0.0; 790 m_norm = (denom > 0.0) ? 1.0 / denom : 0.0;
773 791
774 } // endif: update required 792 } // endif: update required