Commit 2ff018b5b4ac82860be8e40408f781a96dc83d03
1 parent
45c4368b
Correct containment radius computation in GCTAPsf2D::containment_radius (#1876)
Showing
3 changed files
with
40 additions
and
29 deletions
ChangeLog
| 1 | -2016-10-17 | 1 | +2016-11-10 |
| 2 | 2 | ||
| 3 | * Version 1.2.0 released | 3 | * Version 1.2.0 released |
| 4 | ========================= | 4 | ========================= |
| 5 | 5 | ||
| 6 | + Correct containment radius computation in GCTAPsf2D::containment_radius (#1876) | ||
| 6 | Add composite spatial and spectral models (#1706) | 7 | Add composite spatial and spectral models (#1706) |
| 7 | Add GObservations::save_covmat() method (#1863) | 8 | Add GObservations::save_covmat() method (#1863) |
| 8 | Add GFft and GFftWavetable classes (#1731) | 9 | Add GFft and GFftWavetable classes (#1731) |
NEWS
| 1 | New Features and Important Changes in GammaLib 1.2.0 | 1 | New Features and Important Changes in GammaLib 1.2.0 |
| 2 | 2 | ||
| 3 | -17 October 2016 | 3 | +10 November 2016 |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | 1. Introduction | 6 | 1. Introduction |
| @@ -256,6 +256,9 @@ None | @@ -256,6 +256,9 @@ None | ||
| 256 | The dimension of response tables is now checked for being consistent with the | 256 | The dimension of response tables is now checked for being consistent with the |
| 257 | axis dimension (#1848). | 257 | axis dimension (#1848). |
| 258 | 258 | ||
| 259 | +The formula for the containment radius computation in GCTAPsf2D::containment_radius | ||
| 260 | +was wrong and has been corrected (#1876). | ||
| 261 | + | ||
| 259 | 262 | ||
| 260 | 21. COMPTEL interface | 263 | 21. COMPTEL interface |
| 261 | --------------------- | 264 | --------------------- |
inst/cta/src/GCTAPsf2D.cpp
| @@ -540,7 +540,7 @@ double GCTAPsf2D::delta_max(const double& logE, | @@ -540,7 +540,7 @@ double GCTAPsf2D::delta_max(const double& logE, | ||
| 540 | /***********************************************************************//** | 540 | /***********************************************************************//** |
| 541 | * @brief Return the radius that contains a fraction of the events (radians) | 541 | * @brief Return the radius that contains a fraction of the events (radians) |
| 542 | * | 542 | * |
| 543 | - * @param[in] fraction of events (0.0<fraction<1.0) | 543 | + * @param[in] fraction of events (0.0 < fraction < 1.0) |
| 544 | * @param[in] logE Log10 of the true photon energy (TeV). | 544 | * @param[in] logE Log10 of the true photon energy (TeV). |
| 545 | * @param[in] theta Offset angle in camera system (rad). Not used. | 545 | * @param[in] theta Offset angle in camera system (rad). Not used. |
| 546 | * @param[in] phi Azimuth angle in camera system (rad). Not used. | 546 | * @param[in] phi Azimuth angle in camera system (rad). Not used. |
| @@ -556,16 +556,18 @@ double GCTAPsf2D::delta_max(const double& logE, | @@ -556,16 +556,18 @@ double GCTAPsf2D::delta_max(const double& logE, | ||
| 556 | * | 556 | * |
| 557 | * \f[ | 557 | * \f[ |
| 558 | * | 558 | * |
| 559 | - * fraction = \pi * m\_norm * \left( | ||
| 560 | - * \frac{ 1 }{m\_width1} e^{m\_width1 * a^2} + | ||
| 561 | - * \frac{m\_norm2}{m\_width2} e^{m\_width2 * a^2} + | ||
| 562 | - * \frac{m\_norm3}{m\_width3} e^{m\_width3 * a^2} \right) | 559 | + * fraction = m\_norm * \left( e^{m\_width1 * a^2} + |
| 560 | + * m\_norm2 * e^{m\_width2 * a^2} + | ||
| 561 | + * m\_norm3 * e^{m\_width3 * a^2} \right) | ||
| 563 | * | 562 | * |
| 564 | * \f] | 563 | * \f] |
| 565 | * | 564 | * |
| 566 | - * Calculate the radius from the center that contains 'fraction' percent | ||
| 567 | - * of the events. fraction * 100. = Containment % . Fraction must be | ||
| 568 | - * 0.0 < fraction < 1.0 . | 565 | + * Calculate the radius from the center that contains @p fraction of the |
| 566 | + * events (@p fraction * 100. = Containment % ). Fraction must be | ||
| 567 | + * | ||
| 568 | + * \f[ | ||
| 569 | + * 0.0 < fraction < 1.0 | ||
| 570 | + * \f] | ||
| 569 | ***************************************************************************/ | 571 | ***************************************************************************/ |
| 570 | double GCTAPsf2D::containment_radius(const double& fraction, | 572 | double GCTAPsf2D::containment_radius(const double& fraction, |
| 571 | const double& logE, | 573 | const double& logE, |
| @@ -592,38 +594,43 @@ double GCTAPsf2D::containment_radius(const double& fraction, | @@ -592,38 +594,43 @@ double GCTAPsf2D::containment_radius(const double& fraction, | ||
| 592 | // Initial radius to start Newton's method with guess fraction * delta_max | 594 | // Initial radius to start Newton's method with guess fraction * delta_max |
| 593 | double a = fraction * delta_max(logE, theta, phi, zenith, azimuth, etrue); | 595 | double a = fraction * delta_max(logE, theta, phi, zenith, azimuth, etrue); |
| 594 | 596 | ||
| 595 | - // Maximum number of newton-raphson loops before giving up | 597 | + // Maximum number of Newton-Raphson loops before giving up |
| 596 | const int iterlimit = 10000; | 598 | const int iterlimit = 10000; |
| 597 | 599 | ||
| 598 | - // Do the newton-raphson loops | ||
| 599 | - int iter(0); | 600 | + // Do the Newton-Raphson loops |
| 601 | + int iter = 0; | ||
| 600 | for (; iter < iterlimit; ++iter) { | 602 | for (; iter < iterlimit; ++iter) { |
| 601 | 603 | ||
| 602 | - // ... | 604 | + // Compute square of test radius |
| 603 | double a2 = a*a; | 605 | double a2 = a*a; |
| 604 | 606 | ||
| 605 | // Calculate f(a) | 607 | // Calculate f(a) |
| 606 | - double fa(0.0); | ||
| 607 | - fa += m_norm * (std::exp( m_width1 * a2) - 1.0) / m_width1; | ||
| 608 | - fa += m_norm2 * (std::exp( m_width2 * a2) - 1.0) / m_width2; | ||
| 609 | - fa += m_norm3 * (std::exp( m_width3 * a2) - 1.0) / m_width3; | ||
| 610 | - fa *= gammalib::pi; | ||
| 611 | - fa -= fraction; | ||
| 612 | - | ||
| 613 | - // Check if we've met the desired accuracy | 608 | + double fa = 0.0; |
| 609 | + fa += 1.0 - std::exp(m_width1 * a2); | ||
| 610 | + fa += m_norm2 * (1.0 - std::exp(m_width2 * a2)); | ||
| 611 | + fa += m_norm3 * (1.0 - std::exp(m_width3 * a2)); | ||
| 612 | + fa *= m_norm; | ||
| 613 | + fa -= fraction; | ||
| 614 | + | ||
| 615 | + // If we've met the desired accuracy then exit the loop | ||
| 614 | if (std::abs(fa) < convergence) { | 616 | if (std::abs(fa) < convergence) { |
| 615 | break; | 617 | break; |
| 616 | } | 618 | } |
| 617 | - | 619 | + |
| 618 | // Calculate f'(a) | 620 | // Calculate f'(a) |
| 619 | - double fp(0.0); | ||
| 620 | - fp += m_norm * std::exp(m_width1 * a2); | ||
| 621 | - fp += m_norm2 * std::exp(m_width2 * a2); | ||
| 622 | - fp += m_norm3 * std::exp(m_width3 * a2); | ||
| 623 | - fp *= gammalib::twopi * a; | 621 | + double fp = 0.0; |
| 622 | + fp += std::exp(m_width1 * a2); | ||
| 623 | + fp += m_norm2 * std::exp(m_width2 * a2); | ||
| 624 | + fp += m_norm3 * std::exp(m_width3 * a2); | ||
| 625 | + fp *= -2.0 * a * m_norm; | ||
| 624 | 626 | ||
| 625 | // Calculate next point via x+1 = x - f(a) / f'(a) | 627 | // Calculate next point via x+1 = x - f(a) / f'(a) |
| 626 | - a = a - fa / fp; | 628 | + if (fp != 0.0) { |
| 629 | + a -= fa / fp; | ||
| 630 | + } | ||
| 631 | + else { | ||
| 632 | + break; | ||
| 633 | + } | ||
| 627 | 634 | ||
| 628 | } // endfor: Newton-Raphson loops | 635 | } // endfor: Newton-Raphson loops |
| 629 | 636 |