Commit 2a49e2107fb4874801a6da9fccef47f628c4e2d7
1 parent
ffa7e42d
Limit the sky directions drawn in GModelSpatialEllipticalGauss::mc to an effecti…
…ve radius that is consistent with the Gaussian normalization (#1561).
Showing
1 changed file
with
31 additions
and
13 deletions
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& theta, | @@ -367,7 +373,10 @@ double GModelSpatialEllipticalGauss::eval_gradients(const double& 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& energy, | @@ -382,8 +391,16 @@ GSkyDir GModelSpatialEllipticalGauss::mc(const GEnergy& 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& dir, | @@ -431,10 +448,10 @@ bool GModelSpatialEllipticalGauss::contains(const GSkyDir& 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 |