Commit 2ff018b5b4ac82860be8e40408f781a96dc83d03

Authored by Jürgen Knödlseder
1 parent 45c4368b

Correct containment radius computation in GCTAPsf2D::containment_radius (#1876)

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)
... ...
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&amp; 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&amp; 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  
... ...