Commit a3ed1fd1cf08f614f11e276e5fab2369f7fb3cde
1 parent
7d605f42
Set maximum CTA King PSF radius to 2 degrees (#2112)
The maximum radius of the King PSF has been increased from 0.7 to 2 degrees to cope with some extreme cases. Now also the maximum PSF radius is computed for a given energy so that if the PSF is smaller than the maximum radius of 2 degrees a smaller region of interest will be used for the computation.
Showing
4 changed files
with
109 additions
and
87 deletions
ChangeLog
| 1 | -2017-05-14 | |
| 1 | +2017-06-06 | |
| 2 | 2 | |
| 3 | 3 | * Version 1.3.0 released |
| 4 | 4 | ========================= |
| 5 | 5 | |
| 6 | + Increase maximum CTA King PSF radius to 2 degrees (#2112) | |
| 6 | 7 | Correct set names of spatial GLON/GLAT model parameters (#2113) |
| 7 | 8 | Support "BKG" as name of CTA background template |
| 8 | 9 | Scale optimizer convergence criterion with step size (#2022) | ... | ... |
NEWS
| 1 | 1 | New Features and Important Changes in GammaLib 1.3.0.dev1 |
| 2 | 2 | |
| 3 | -14 May 2017 | |
| 3 | +6 June 2017 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | 1. Introduction |
| ... | ... | @@ -268,6 +268,11 @@ avoid FITS file pointer exceptions (#2021). |
| 268 | 268 | The CTA background template HDUCLAS2 was changed from "BGD" to "BKG". Both strings |
| 269 | 269 | are supported by GammaLib. |
| 270 | 270 | |
| 271 | +The maximum radius of the King PSF has been increased from 0.7 to 2 degrees to cope | |
| 272 | +with some extreme cases. Now also the maximum PSF radius is computed for a given | |
| 273 | +energy so that if the PSF is smaller than the maximum radius of 2 degrees a smaller | |
| 274 | +region of interest will be used for the computation (#2112). | |
| 275 | + | |
| 271 | 276 | |
| 272 | 277 | 21. COMPTEL interface |
| 273 | 278 | --------------------- | ... | ... |
inst/cta/include/GCTAPsfKing.hpp
| ... | ... | @@ -111,10 +111,11 @@ public: |
| 111 | 111 | |
| 112 | 112 | private: |
| 113 | 113 | // Methods |
| 114 | - void init_members(void); | |
| 115 | - void copy_members(const GCTAPsfKing& psf); | |
| 116 | - void free_members(void); | |
| 117 | - void update(const double& logE, const double& theta) const; | |
| 114 | + void init_members(void); | |
| 115 | + void copy_members(const GCTAPsfKing& psf); | |
| 116 | + void free_members(void); | |
| 117 | + void update(const double& logE, const double& theta) const; | |
| 118 | + double r_max(const double& logE, const double& theta) const; | |
| 118 | 119 | |
| 119 | 120 | // Members |
| 120 | 121 | GFilename m_filename; //!< Name of Aeff response file |
| ... | ... | @@ -131,6 +132,7 @@ private: |
| 131 | 132 | mutable double m_par_sigma; //!< King profile sigma (radians) |
| 132 | 133 | mutable double m_par_sigma2; //!< King profile sigma squared |
| 133 | 134 | mutable double m_par_gamma; //!< King profile gamma parameter |
| 135 | + mutable double m_par_rmax; //!< Maximum PSF radius | |
| 134 | 136 | }; |
| 135 | 137 | |
| 136 | 138 | ... | ... |
inst/cta/src/GCTAPsfKing.cpp
| ... | ... | @@ -49,14 +49,11 @@ |
| 49 | 49 | /* __ Macros _____________________________________________________________ */ |
| 50 | 50 | |
| 51 | 51 | /* __ Coding definitions _________________________________________________ */ |
| 52 | -#define G_FIX_DELTA_MAX | |
| 53 | 52 | #define G_SMOOTH_PSF |
| 54 | 53 | |
| 55 | 54 | /* __ Debug definitions __________________________________________________ */ |
| 56 | 55 | |
| 57 | 56 | /* __ Constants __________________________________________________________ */ |
| 58 | -const double r_max = 0.7 * gammalib::deg2rad; // Maximum delta for fixed | |
| 59 | - // delta_max computation | |
| 60 | 57 | |
| 61 | 58 | |
| 62 | 59 | /*========================================================================== |
| ... | ... | @@ -198,51 +195,42 @@ double GCTAPsfKing::operator()(const double& delta, |
| 198 | 195 | const double& azimuth, |
| 199 | 196 | const bool& etrue) const |
| 200 | 197 | { |
| 201 | - #if defined(G_FIX_DELTA_MAX) | |
| 202 | 198 | #if defined(G_SMOOTH_PSF) |
| 203 | 199 | // Set ramp down radius |
| 204 | - static const double ramp_down = 0.95 * r_max; | |
| 205 | - static const double norm_down = 1.0 / (r_max - ramp_down); | |
| 206 | - #endif | |
| 200 | + static const double ramp_down = 0.95 * m_par_rmax; | |
| 201 | + static const double norm_down = 1.0 / (m_par_rmax - ramp_down); | |
| 207 | 202 | #endif |
| 208 | 203 | |
| 209 | 204 | // Initialise PSF value |
| 210 | 205 | double psf = 0.0; |
| 211 | 206 | |
| 212 | - // Compile option: set PSF to zero outside delta_max | |
| 213 | - #if defined(G_FIX_DELTA_MAX) | |
| 214 | - if (delta <= r_max) { | |
| 215 | - #endif | |
| 216 | - | |
| 217 | 207 | // Update the parameter cache |
| 218 | 208 | update(logE, theta); |
| 219 | 209 | |
| 220 | - // Continue only if normalization is positive | |
| 221 | - if (m_par_norm > 0.0) { | |
| 222 | - | |
| 223 | - // Compute PSF value | |
| 224 | - double arg = delta / m_par_sigma; | |
| 225 | - double arg2 = arg * arg; | |
| 226 | - psf = m_par_norm * | |
| 227 | - std::pow((1.0 + 1.0 / (2.0 * m_par_gamma) * arg2), -m_par_gamma); | |
| 228 | - | |
| 229 | - // If we are at large offset angles, add a smooth ramp down to | |
| 230 | - // avoid steps in the log-likelihood computation | |
| 231 | - #if defined(G_FIX_DELTA_MAX) | |
| 232 | - #if defined(G_SMOOTH_PSF) | |
| 233 | - if (delta > ramp_down) { | |
| 234 | - double x = norm_down * (delta - ramp_down); | |
| 235 | - psf *= 1.0 - x * x; | |
| 236 | - } | |
| 237 | - #endif | |
| 238 | - #endif | |
| 210 | + // Continue only if delta is smaller than PSF radius | |
| 211 | + if (delta <= m_par_rmax) { | |
| 212 | + | |
| 213 | + // Continue only if normalization is positive | |
| 214 | + if (m_par_norm > 0.0) { | |
| 215 | + | |
| 216 | + // Compute PSF value | |
| 217 | + double arg = delta / m_par_sigma; | |
| 218 | + double arg2 = arg * arg; | |
| 219 | + psf = m_par_norm * | |
| 220 | + std::pow((1.0 + 1.0 / (2.0 * m_par_gamma) * arg2), -m_par_gamma); | |
| 221 | + | |
| 222 | + // If we are at large offset angles, add a smooth ramp down to | |
| 223 | + // avoid steps in the log-likelihood computation | |
| 224 | + #if defined(G_SMOOTH_PSF) | |
| 225 | + if (delta > ramp_down) { | |
| 226 | + double x = norm_down * (delta - ramp_down); | |
| 227 | + psf *= 1.0 - x * x; | |
| 228 | + } | |
| 229 | + #endif | |
| 239 | 230 | |
| 240 | - } // endif: normalization was positive | |
| 231 | + } // endif: normalization was positive | |
| 241 | 232 | |
| 242 | - // Compile option: set PSF to zero outside delta_max | |
| 243 | - #if defined(G_FIX_DELTA_MAX) | |
| 244 | - } | |
| 245 | - #endif | |
| 233 | + } // endif: PSF radius was smaller than PSF radius | |
| 246 | 234 | |
| 247 | 235 | // Return PSF |
| 248 | 236 | return psf; |
| ... | ... | @@ -488,22 +476,17 @@ double GCTAPsfKing::mc(GRan& ran, |
| 488 | 476 | // Compute exponent |
| 489 | 477 | double exponent = 1.0 / (1.0-m_par_gamma); |
| 490 | 478 | |
| 491 | - // Compile option: sample until delta <= r_max | |
| 492 | - #if defined(G_FIX_DELTA_MAX) | |
| 479 | + // Sample until delta <= m_par_rmax | |
| 493 | 480 | do { |
| 494 | - #endif | |
| 495 | 481 | |
| 496 | - // Get uniform random number | |
| 497 | - double u = ran.uniform(); | |
| 482 | + // Get uniform random number | |
| 483 | + double u = ran.uniform(); | |
| 498 | 484 | |
| 499 | - // Draw random offset using inversion sampling | |
| 500 | - double u_max = (std::pow((1.0 - u), exponent) - 1.0) * m_par_gamma; | |
| 501 | - delta = m_par_sigma * std::sqrt(2.0 * u_max); | |
| 485 | + // Draw random offset using inversion sampling | |
| 486 | + double u_max = (std::pow((1.0 - u), exponent) - 1.0) * m_par_gamma; | |
| 487 | + delta = m_par_sigma * std::sqrt(2.0 * u_max); | |
| 502 | 488 | |
| 503 | - // Compile option: sample until delta <= r_max | |
| 504 | - #if defined(G_FIX_DELTA_MAX) | |
| 505 | - } while (delta > r_max); | |
| 506 | - #endif | |
| 489 | + } while (delta > m_par_rmax); | |
| 507 | 490 | |
| 508 | 491 | } // endif: normalization was positive |
| 509 | 492 | |
| ... | ... | @@ -537,25 +520,13 @@ double GCTAPsfKing::delta_max(const double& logE, |
| 537 | 520 | // Initialise PSF radius |
| 538 | 521 | double radius = 0.0; |
| 539 | 522 | |
| 540 | - // Compile option: use fixed maximum delta | |
| 541 | - #if defined(G_FIX_DELTA_MAX) | |
| 542 | - radius = r_max; | |
| 543 | - #else | |
| 544 | - | |
| 545 | 523 | // Update the parameter cache |
| 546 | 524 | update(logE, theta); |
| 547 | 525 | |
| 548 | - // Continue only if normalization is positive | |
| 526 | + // Compute radius if normalization is positive | |
| 549 | 527 | if (m_par_norm > 0.0) { |
| 550 | - | |
| 551 | - // Compute maximum PSF radius (99.995% containment) | |
| 552 | - double F = 0.99995; | |
| 553 | - double u_max = (std::pow((1.0 - F), (1.0/(1.0-m_par_gamma))) - 1.0) * | |
| 554 | - m_par_gamma; | |
| 555 | - radius = m_par_sigma * std::sqrt(2.0 * u_max); | |
| 556 | - | |
| 557 | - } // endif: King profile parameters were valid | |
| 558 | - #endif | |
| 528 | + radius = r_max(logE, theta); | |
| 529 | + } | |
| 559 | 530 | |
| 560 | 531 | // Return maximum PSF radius |
| 561 | 532 | return radius; |
| ... | ... | @@ -687,6 +658,7 @@ void GCTAPsfKing::init_members(void) |
| 687 | 658 | m_par_gamma = 0.0; |
| 688 | 659 | m_par_sigma = 0.0; |
| 689 | 660 | m_par_sigma2 = 0.0; |
| 661 | + m_par_rmax = 0.0; | |
| 690 | 662 | |
| 691 | 663 | // Return |
| 692 | 664 | return; |
| ... | ... | @@ -713,6 +685,7 @@ void GCTAPsfKing::copy_members(const GCTAPsfKing& psf) |
| 713 | 685 | m_par_gamma = psf.m_par_gamma; |
| 714 | 686 | m_par_sigma = psf.m_par_sigma; |
| 715 | 687 | m_par_sigma2 = psf.m_par_sigma2; |
| 688 | + m_par_rmax = psf.m_par_rmax; | |
| 716 | 689 | |
| 717 | 690 | // Return |
| 718 | 691 | return; |
| ... | ... | @@ -738,10 +711,15 @@ void GCTAPsfKing::free_members(void) |
| 738 | 711 | * This method updates the PSF parameter cache. As the performance table PSF |
| 739 | 712 | * only depends on energy, the only parameter on which the cache values |
| 740 | 713 | * depend is the energy. If the PSF parameters are invalid the m_par_norm |
| 741 | - * member will be set to zero. | |
| 714 | + * member will be set to zero. Valid PSF parameters are \f$\gamma > 1\f$ and | |
| 715 | + * \f$\simga > 0\f$. | |
| 742 | 716 | ***************************************************************************/ |
| 743 | 717 | void GCTAPsfKing::update(const double& logE, const double& theta) const |
| 744 | 718 | { |
| 719 | + // Maximum PSF radius in radians. We set the maximum radius to 2 degrees | |
| 720 | + // since it's hard to imaging that a PSF will ever be larger. | |
| 721 | + const double r_max = 2.0 * gammalib::deg2rad; | |
| 722 | + | |
| 745 | 723 | // Only compute PSF parameters if arguments have changed |
| 746 | 724 | if (logE != m_par_logE || theta != m_par_theta) { |
| 747 | 725 | |
| ... | ... | @@ -758,31 +736,38 @@ void GCTAPsfKing::update(const double& logE, const double& theta) const |
| 758 | 736 | m_par_sigma = pars[m_inx_sigma]; |
| 759 | 737 | m_par_sigma2 = m_par_sigma * m_par_sigma; |
| 760 | 738 | |
| 761 | - // Check for parameter sanity | |
| 762 | - if (m_par_gamma <= 0.0 || m_par_sigma <= 0.0) { | |
| 739 | + // Check for parameter sanity. The King function is not defined for | |
| 740 | + // gamma values equal or smaller than one and non-positive sigma | |
| 741 | + // values. If this is the case we set the normalization and the | |
| 742 | + // maximum radius to zero ... | |
| 743 | + if (m_par_gamma <= 1.0 || m_par_sigma <= 0.0) { | |
| 763 | 744 | m_par_norm = 0.0; |
| 764 | - /* | |
| 765 | - std::string msg = "King function parameters gamma="+ | |
| 766 | - gammalib::str(m_par_gamma)+" or sigma="+ | |
| 767 | - gammalib::str(m_par_sigma)+" are not positive " | |
| 768 | - "for logE="+gammalib::str(logE)+" and theta="+ | |
| 769 | - gammalib::str(theta)+". Setting normalization " | |
| 770 | - "to zero."; | |
| 771 | - gammalib::warning(G_UPDATE, msg); | |
| 772 | - */ | |
| 745 | + m_par_rmax = 0.0; | |
| 773 | 746 | } |
| 747 | + | |
| 748 | + // ... otherwise we compute the normalization | |
| 774 | 749 | else { |
| 775 | 750 | |
| 776 | 751 | // Determine normalisation for given parameters |
| 777 | 752 | m_par_norm = 1.0 / gammalib::twopi * (1.0 - 1.0 / m_par_gamma) / |
| 778 | 753 | m_par_sigma2; |
| 779 | 754 | |
| 780 | - // Optionally correct for fixed delta_max | |
| 781 | - #if defined(G_FIX_DELTA_MAX) | |
| 782 | - double u_max = (r_max*r_max) / (2.0 * m_par_sigma2); | |
| 783 | - double norm = 1.0 - std::pow((1.0 + u_max/m_par_gamma), 1.0-m_par_gamma); | |
| 784 | - m_par_norm /= norm; | |
| 785 | - #endif | |
| 755 | + // Determine maximum PSF radius | |
| 756 | + m_par_rmax = this->r_max(logE, theta); | |
| 757 | + | |
| 758 | + // Make sure that radius is smaller than 2 degrees | |
| 759 | + if (m_par_rmax > r_max) { | |
| 760 | + | |
| 761 | + // Restrict PSF radius to 2 degrees | |
| 762 | + m_par_rmax = r_max; | |
| 763 | + | |
| 764 | + // Correct PSF normalization for restriction | |
| 765 | + double u_max = (m_par_rmax*m_par_rmax) / (2.0 * m_par_sigma2); | |
| 766 | + double norm = 1.0 - std::pow((1.0 + u_max/m_par_gamma), | |
| 767 | + (1.0-m_par_gamma)); | |
| 768 | + m_par_norm /= norm; | |
| 769 | + | |
| 770 | + } // endif: restricted PSF radius | |
| 786 | 771 | |
| 787 | 772 | } // endif: King profile parameters were valid |
| 788 | 773 | |
| ... | ... | @@ -791,3 +776,32 @@ void GCTAPsfKing::update(const double& logE, const double& theta) const |
| 791 | 776 | // Return |
| 792 | 777 | return; |
| 793 | 778 | } |
| 779 | + | |
| 780 | + | |
| 781 | +/***********************************************************************//** | |
| 782 | + * @brief Return maximum size of PSF (radians) | |
| 783 | + * | |
| 784 | + * @param[in] logE Log10 of the true photon energy (TeV). | |
| 785 | + * @param[in] theta Offset angle in camera system (rad). | |
| 786 | + * | |
| 787 | + * Determine the radius beyond which the PSF becomes negligible. This radius | |
| 788 | + * is set by this method to where the containment fraction become 99.995% | |
| 789 | + * which equals \f$5 \times \sigma\f$ of a Gaussian width. | |
| 790 | + * | |
| 791 | + * This method requires the m_par_gamma and m_par_sigma to be set to valid | |
| 792 | + * values. | |
| 793 | + ***************************************************************************/ | |
| 794 | +double GCTAPsfKing::r_max(const double& logE, | |
| 795 | + const double& theta) const | |
| 796 | +{ | |
| 797 | + // Set 99.995% containment fraction | |
| 798 | + const double F = 0.99995; | |
| 799 | + | |
| 800 | + // Compute maximum PSF radius for containment fraction | |
| 801 | + double u_max = (std::pow((1.0 - F), (1.0/(1.0-m_par_gamma))) - 1.0) * | |
| 802 | + m_par_gamma; | |
| 803 | + double radius = m_par_sigma * std::sqrt(2.0 * u_max); | |
| 804 | + | |
| 805 | + // Return maximum PSF radius | |
| 806 | + return radius; | |
| 807 | +} | ... | ... |