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 * 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)
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&amp; logE, @@ -556,16 +556,18 @@ double GCTAPsf2D::delta_max(const double&amp; 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&amp; fraction, @@ -592,38 +594,43 @@ double GCTAPsf2D::containment_radius(const double&amp; 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