Commit d4a4555fceffaa3d62a4ef90c3bac27e90403ff5

Authored by Jürgen Knödlseder
1 parent f02bf3f3

Disable stacked response cutting in true energy (#2721)

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)
... ...
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&amp; 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&amp; cube, const double&amp; 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&amp; cube, const double&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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  
... ...