Commit d4a4555fceffaa3d62a4ef90c3bac27e90403ff5
1 parent
f02bf3f3
Disable stacked response cutting in true energy (#2721)
Showing
7 changed files
with
73 additions
and
43 deletions
ChangeLog
| 1 | -2018-11-08 | |
| 1 | +2018-11-09 | |
| 2 | 2 | |
| 3 | 3 | * Version 1.6.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | - Revise GCTAEdispCube::operator() interface (#2721) | |
| 6 | + Revise GCTAEdispCube::operator() interface and disable stacked response | |
| 7 | + cutting in true energy (#2721) | |
| 7 | 8 | Rename GCTAResponseIrf::lo_save_thres() and GCTAResponseIrf::hi_save_thres() |
| 8 | 9 | to GCTAResponseIrf::lo_safe_thres() and GCTAResponseIrf::hi_safe_thres() |
| 9 | 10 | (#2716) | ... | ... |
NEWS
| 1 | 1 | New Features and Important Changes in GammaLib 1.6.0 |
| 2 | 2 | |
| 3 | -8 November 2018 | |
| 3 | +9 November 2018 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | 1. Introduction |
| ... | ... | @@ -316,7 +316,11 @@ None |
| 316 | 316 | ----------------- |
| 317 | 317 | The arguments of the GCTACubeEdisp::operator() were changed from, passing |
| 318 | 318 | now reconstructed and true energy objects, followed by a true sky direction. |
| 319 | -This is more consistent with the GCTAEdisp interface (#2721). | |
| 319 | +This is more consistent with the GCTAEdisp interface. The stacked response | |
| 320 | +is no longer cut in true energy. Before the information outside the | |
| 321 | +reconstructed energy bounds were reset to zero due to spill over effects, | |
| 322 | +but this lead a big bias in the H.E.S.S. analysis where energy dispersion is | |
| 323 | +important. The cutting was therefore disabled (#2721). | |
| 320 | 324 | |
| 321 | 325 | Rename GCTAResponseIrf::lo_save_thres() and GCTAResponseIrf::hi_save_thres() |
| 322 | 326 | to GCTAResponseIrf::lo_safe_thres() and GCTAResponseIrf::hi_safe_thres() | ... | ... |
doc/source/admin/release_history/1.6.rst
| ... | ... | @@ -48,7 +48,8 @@ Improvements |
| 48 | 48 | ------------ |
| 49 | 49 | |
| 50 | 50 | * [`2721 <https://cta-redmine.irap.omp.eu/issues/2721>`_] - |
| 51 | - Revise ``GCTAEdispCube::operator()`` interface | |
| 51 | + Revise ``GCTAEdispCube::operator()`` interface and disable stacked response | |
| 52 | + cutting in true energy | |
| 52 | 53 | * [`2715 <https://cta-redmine.irap.omp.eu/issues/2715>`_] - |
| 53 | 54 | Add generic CTA response cache |
| 54 | 55 | * [`2704 <https://cta-redmine.irap.omp.eu/issues/2704>`_] - | ... | ... |
inst/cta/include/GCTACubeEdisp.hpp
| ... | ... | @@ -118,6 +118,7 @@ protected: |
| 118 | 118 | GLog* log = NULL); |
| 119 | 119 | void update(const GEnergy& ereco, const GEnergy& etrue) const; |
| 120 | 120 | void set_eng_axis(void); |
| 121 | + void set_migras(const double& mmax, const int& nmbins); | |
| 121 | 122 | void compute_ebounds(void) const; |
| 122 | 123 | |
| 123 | 124 | // Members | ... | ... |
inst/cta/src/GCTACubeEdisp.cpp
| ... | ... | @@ -54,6 +54,7 @@ |
| 54 | 54 | /* __ Macros _____________________________________________________________ */ |
| 55 | 55 | |
| 56 | 56 | /* __ Coding definitions _________________________________________________ */ |
| 57 | +//#define G_CLIP_ETRUES //!< Clip true energies to reconstructed ones | |
| 57 | 58 | |
| 58 | 59 | /* __ Debug definitions __________________________________________________ */ |
| 59 | 60 | |
| ... | ... | @@ -128,7 +129,7 @@ GCTACubeEdisp::GCTACubeEdisp(const GFilename& filename) |
| 128 | 129 | * @brief Event cube constructor |
| 129 | 130 | * |
| 130 | 131 | * @param[in] cube Event cube. |
| 131 | - * @param[in] mmax Maximum energy migration (degrees, >0.0). | |
| 132 | + * @param[in] mmax Maximum energy migration. | |
| 132 | 133 | * @param[in] nmbins Number of migration bins (2 ...). |
| 133 | 134 | * |
| 134 | 135 | * @exception GException::invalid_argument |
| ... | ... | @@ -164,13 +165,8 @@ GCTACubeEdisp::GCTACubeEdisp(const GCTAEventCube& cube, const double& mmax, |
| 164 | 165 | // Set energy node array used for interpolation |
| 165 | 166 | set_eng_axis(); |
| 166 | 167 | |
| 167 | - // Set the migration nodes | |
| 168 | - m_migras.clear(); | |
| 169 | - double binsize = mmax / double(nmbins); | |
| 170 | - for (int i = 0; i < nmbins; ++i) { | |
| 171 | - double migra = binsize * (double(i) + 0.5); // avoid central singularity | |
| 172 | - m_migras.append(migra); | |
| 173 | - } | |
| 168 | + // Set migration axis used for interpolation | |
| 169 | + set_migras(mmax, nmbins); | |
| 174 | 170 | |
| 175 | 171 | // Compute number of sky maps |
| 176 | 172 | int nmaps = m_energies.size() * m_migras.size(); |
| ... | ... | @@ -205,7 +201,7 @@ GCTACubeEdisp::GCTACubeEdisp(const GCTAEventCube& cube, const double& mmax, |
| 205 | 201 | * @param[in] nx Number of pixels in x direction. |
| 206 | 202 | * @param[in] ny Number of pixels in y direction. |
| 207 | 203 | * @param[in] energies True energies. |
| 208 | - * @param[in] mmax Maximum energy migration (degrees, >0.0). | |
| 204 | + * @param[in] mmax Maximum energy migration. | |
| 209 | 205 | * @param[in] nmbins Number of migration bins (2 ...). |
| 210 | 206 | * |
| 211 | 207 | * @exception GException::invalid_argument |
| ... | ... | @@ -250,13 +246,8 @@ GCTACubeEdisp::GCTACubeEdisp(const std::string& wcs, |
| 250 | 246 | // Set energy node array used for interpolation |
| 251 | 247 | set_eng_axis(); |
| 252 | 248 | |
| 253 | - // Set migration node array | |
| 254 | - m_migras.clear(); | |
| 255 | - double binsize = mmax / double(nmbins); | |
| 256 | - for (int i = 0; i < nmbins; ++i) { | |
| 257 | - double migra = binsize * (double(i) + 0.5); // avoid central singularity | |
| 258 | - m_migras.append(migra); | |
| 259 | - } | |
| 249 | + // Set migration axis used for interpolation | |
| 250 | + set_migras(mmax, nmbins); | |
| 260 | 251 | |
| 261 | 252 | // Compute number of sky maps |
| 262 | 253 | int nmaps = m_energies.size() * m_migras.size(); |
| ... | ... | @@ -965,11 +956,13 @@ void GCTACubeEdisp::fill_cube(const GCTAObservation& obs, |
| 965 | 956 | // we can really do. |
| 966 | 957 | // We allow here for a small margin in case of rounding |
| 967 | 958 | // errors in the energy boundaries. |
| 959 | + #if defined(G_CLIP_ETRUES) | |
| 968 | 960 | if (!(obs_ebounds.contains(m_energies[iebin]) || |
| 969 | 961 | obs_ebounds.contains(m_energies[iebin]-margin) || |
| 970 | 962 | obs_ebounds.contains(m_energies[iebin]+margin))) { |
| 971 | 963 | continue; |
| 972 | 964 | } |
| 965 | + #endif | |
| 973 | 966 | |
| 974 | 967 | // Get log10 of true energy in TeV |
| 975 | 968 | double logEsrc = m_energies[iebin].log10TeV(); |
| ... | ... | @@ -985,7 +978,7 @@ void GCTACubeEdisp::fill_cube(const GCTAObservation& obs, |
| 985 | 978 | (*exposure)(pixel, iebin) += weight; |
| 986 | 979 | } |
| 987 | 980 | |
| 988 | - // Loop over delta values | |
| 981 | + // Loop over migration values | |
| 989 | 982 | for (int imigra = 0; imigra < m_migras.size(); ++imigra) { |
| 990 | 983 | |
| 991 | 984 | // Compute energy migration fraction |
| ... | ... | @@ -1080,23 +1073,45 @@ void GCTACubeEdisp::set_eng_axis(void) |
| 1080 | 1073 | |
| 1081 | 1074 | |
| 1082 | 1075 | /***********************************************************************//** |
| 1076 | + * @brief Set nodes for interpolation in migration | |
| 1077 | + * | |
| 1078 | + * @param[in] mmax Maximum energy migration (>0). | |
| 1079 | + * @param[in] nmbins Number of migration bins (2 ...). | |
| 1080 | + * | |
| 1081 | + * Sets the nodes for interpolation in migration. None of the nodes will | |
| 1082 | + * have a value of zero unless mmax is zero. | |
| 1083 | + ***************************************************************************/ | |
| 1084 | +void GCTACubeEdisp::set_migras(const double& mmax, const int& nmbins) | |
| 1085 | +{ | |
| 1086 | + // Clear migration axis | |
| 1087 | + m_migras.clear(); | |
| 1088 | + | |
| 1089 | + // Set the migration nodes | |
| 1090 | + double binsize = mmax / double(nmbins); | |
| 1091 | + for (int i = 0; i < nmbins; ++i) { | |
| 1092 | + double migra = binsize * double(i+1); // avoid central singularity | |
| 1093 | + m_migras.append(migra); | |
| 1094 | + } | |
| 1095 | + | |
| 1096 | + // Return | |
| 1097 | + return; | |
| 1098 | +} | |
| 1099 | + | |
| 1100 | + | |
| 1101 | +/***********************************************************************//** | |
| 1083 | 1102 | * @brief Compute true energy boundary vector |
| 1084 | 1103 | * |
| 1085 | 1104 | * Computes for all energies of the energy dispersion cube the boundaries in |
| 1086 | - * true energy that encompass non-negligible migration matrix elements. | |
| 1087 | - * Values >= 1.0e-12 are considered as non-negligible. In case that no matrix | |
| 1088 | - * elements are found for a given energy, the interval of true energies will | |
| 1089 | - * be set to [1 TeV, 1 TeV] (i.e. an empty interval). | |
| 1105 | + * true energy that encompass non-zero migration matrix elements. In case | |
| 1106 | + * that no matrix elements are found for a given energy, the interval of true | |
| 1107 | + * energies will be set to [0,0] (i.e. an empty interval). | |
| 1090 | 1108 | ***************************************************************************/ |
| 1091 | 1109 | void GCTACubeEdisp::compute_ebounds() const |
| 1092 | 1110 | { |
| 1093 | - // Set epsilon | |
| 1094 | - const double eps = 1.0e-12; | |
| 1095 | - | |
| 1096 | 1111 | // Clear energy boundary vector |
| 1097 | 1112 | m_ebounds.clear(); |
| 1098 | 1113 | |
| 1099 | - // Loop over all energies | |
| 1114 | + // Loop over all reconstructed energies | |
| 1100 | 1115 | for (int i = 0; i < m_energies.size(); i++) { |
| 1101 | 1116 | |
| 1102 | 1117 | // Initialise results |
| ... | ... | @@ -1121,8 +1136,8 @@ void GCTACubeEdisp::compute_ebounds() const |
| 1121 | 1136 | } |
| 1122 | 1137 | } |
| 1123 | 1138 | |
| 1124 | - // Find first non-negligible energy dispersion term | |
| 1125 | - if (edisp >= eps) { | |
| 1139 | + // Find first non-zero energy dispersion term | |
| 1140 | + if (edisp > 0.0) { | |
| 1126 | 1141 | minFound = true; |
| 1127 | 1142 | migra_min = m_migras[imap - mapmin]; |
| 1128 | 1143 | break; |
| ... | ... | @@ -1142,8 +1157,8 @@ void GCTACubeEdisp::compute_ebounds() const |
| 1142 | 1157 | } |
| 1143 | 1158 | } |
| 1144 | 1159 | |
| 1145 | - // Find first non-negligible energy dispersion term | |
| 1146 | - if (edisp >= eps) { | |
| 1160 | + // Find first non-zero energy dispersion term | |
| 1161 | + if (edisp > 0.0) { | |
| 1147 | 1162 | maxFound = true; |
| 1148 | 1163 | migra_max = m_migras[imap - mapmin]; |
| 1149 | 1164 | break; |
| ... | ... | @@ -1165,14 +1180,14 @@ void GCTACubeEdisp::compute_ebounds() const |
| 1165 | 1180 | |
| 1166 | 1181 | // ... otherwise we set the interval to a zero interval for safety |
| 1167 | 1182 | else { |
| 1168 | - emin.log10TeV(0.0); | |
| 1169 | - emax.log10TeV(0.0); | |
| 1183 | + emin.clear(); | |
| 1184 | + emax.clear(); | |
| 1170 | 1185 | } |
| 1171 | 1186 | |
| 1172 | 1187 | // Append energy boundaries |
| 1173 | 1188 | m_ebounds.push_back(GEbounds(emin, emax)); |
| 1174 | 1189 | |
| 1175 | - } // endfor: looped over all energies | |
| 1190 | + } // endfor: looped over all reconstruced energies | |
| 1176 | 1191 | |
| 1177 | 1192 | // Return |
| 1178 | 1193 | return; | ... | ... |
inst/cta/src/GCTACubeExposure.cpp
| ... | ... | @@ -41,6 +41,7 @@ |
| 41 | 41 | /* __ Macros _____________________________________________________________ */ |
| 42 | 42 | |
| 43 | 43 | /* __ Coding definitions _________________________________________________ */ |
| 44 | +//#define G_CLIP_ETRUES //!< Clip true energies to reconstructed ones | |
| 44 | 45 | |
| 45 | 46 | /* __ Debug definitions __________________________________________________ */ |
| 46 | 47 | |
| ... | ... | @@ -734,11 +735,13 @@ void GCTACubeExposure::fill_cube(const GCTAObservation& obs, GLog* log) |
| 734 | 735 | // approximation, but probably the only we can really do. |
| 735 | 736 | // We allow here for a small margin in case of rounding |
| 736 | 737 | // errors in the energy boundaries. |
| 738 | + #if defined(G_CLIP_ETRUES) | |
| 737 | 739 | if (!(obs_ebounds.contains(m_energies[iebin]) || |
| 738 | 740 | obs_ebounds.contains(m_energies[iebin]-margin) || |
| 739 | 741 | obs_ebounds.contains(m_energies[iebin]+margin))) { |
| 740 | 742 | continue; |
| 741 | 743 | } |
| 744 | + #endif | |
| 742 | 745 | |
| 743 | 746 | // Get logE/TeV |
| 744 | 747 | double logE = m_energies[iebin].log10TeV(); | ... | ... |
inst/cta/src/GCTACubePsf.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * GCTACubePsf.cpp - CTA cube analysis point spread function class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2014-2017 by Chia-Chun Lu * | |
| 4 | + * copyright (C) 2014-2018 by Chia-Chun Lu * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -48,6 +48,7 @@ |
| 48 | 48 | /* __ Macros _____________________________________________________________ */ |
| 49 | 49 | |
| 50 | 50 | /* __ Coding definitions _________________________________________________ */ |
| 51 | +//#define G_CLIP_ETRUES //!< Clip true energies to reconstructed ones | |
| 51 | 52 | #define G_SMOOTH_PSF //!< Guarantee no singularities |
| 52 | 53 | #define G_QUADRATIC_BINNING //!< Use quadratic delta spacing |
| 53 | 54 | |
| ... | ... | @@ -864,21 +865,25 @@ void GCTACubePsf::fill_cube(const GCTAObservation& obs, |
| 864 | 865 | // approximation, but probably the only we can really do. |
| 865 | 866 | // We allow here for a small margin in case of rounding |
| 866 | 867 | // errors in the energy boundaries. |
| 868 | + #if defined(G_CLIP_ETRUES) | |
| 867 | 869 | if (!(obs_ebounds.contains(m_energies[iebin]) || |
| 868 | 870 | obs_ebounds.contains(m_energies[iebin]-margin) || |
| 869 | 871 | obs_ebounds.contains(m_energies[iebin]+margin))) { |
| 870 | 872 | continue; |
| 871 | 873 | } |
| 874 | + #endif | |
| 872 | 875 | |
| 873 | 876 | // Get logE/TeV |
| 874 | 877 | double logE = m_energies[iebin].log10TeV(); |
| 875 | 878 | |
| 876 | - // Compute exposure weight | |
| 877 | - double weight = rsp->aeff(theta, 0.0, 0.0, 0.0, logE) * | |
| 878 | - obs.livetime(); | |
| 879 | - | |
| 880 | - // If available, accumulate weights | |
| 879 | + // Compute exposure weight. If no exposure map is | |
| 880 | + // specified, the weight is one. Otherwise, the weight | |
| 881 | + // is the effective area for this offset angle and | |
| 882 | + // source energy times the livetime of the observation. | |
| 883 | + double weight = 1.0; | |
| 881 | 884 | if (exposure != NULL) { |
| 885 | + weight = rsp->aeff(theta, 0.0, 0.0, 0.0, logE) * | |
| 886 | + obs.livetime(); | |
| 882 | 887 | (*exposure)(pixel, iebin) += weight; |
| 883 | 888 | } |
| 884 | 889 | ... | ... |