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 | 3 | * Version 1.2.0 released |
| 4 | 4 | ========================= |
| 5 | 5 | |
| 6 | + Correct containment radius computation in GCTAPsf2D::containment_radius (#1876) | |
| 6 | 7 | Add composite spatial and spectral models (#1706) |
| 7 | 8 | Add GObservations::save_covmat() method (#1863) |
| 8 | 9 | Add GFft and GFftWavetable classes (#1731) | ... | ... |
NEWS
| 1 | 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 | 6 | 1. Introduction |
| ... | ... | @@ -256,6 +256,9 @@ None |
| 256 | 256 | The dimension of response tables is now checked for being consistent with the |
| 257 | 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 | 263 | 21. COMPTEL interface |
| 261 | 264 | --------------------- | ... | ... |
inst/cta/src/GCTAPsf2D.cpp
| ... | ... | @@ -540,7 +540,7 @@ double GCTAPsf2D::delta_max(const double& logE, |
| 540 | 540 | /***********************************************************************//** |
| 541 | 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 | 544 | * @param[in] logE Log10 of the true photon energy (TeV). |
| 545 | 545 | * @param[in] theta Offset angle in camera system (rad). Not used. |
| 546 | 546 | * @param[in] phi Azimuth angle in camera system (rad). Not used. |
| ... | ... | @@ -556,16 +556,18 @@ double GCTAPsf2D::delta_max(const double& logE, |
| 556 | 556 | * |
| 557 | 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 | 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 | 572 | double GCTAPsf2D::containment_radius(const double& fraction, |
| 571 | 573 | const double& logE, |
| ... | ... | @@ -592,38 +594,43 @@ double GCTAPsf2D::containment_radius(const double& fraction, |
| 592 | 594 | // Initial radius to start Newton's method with guess fraction * delta_max |
| 593 | 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 | 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 | 602 | for (; iter < iterlimit; ++iter) { |
| 601 | 603 | |
| 602 | - // ... | |
| 604 | + // Compute square of test radius | |
| 603 | 605 | double a2 = a*a; |
| 604 | 606 | |
| 605 | 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 | 616 | if (std::abs(fa) < convergence) { |
| 615 | 617 | break; |
| 616 | 618 | } |
| 617 | - | |
| 619 | + | |
| 618 | 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 | 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 | 635 | } // endfor: Newton-Raphson loops |
| 629 | 636 | ... | ... |