Commit 5a80b6d4c8ff4c4e940a78d47f14306ac128ebc3

Authored by Jürgen Knödlseder
1 parent b4150689

Fix precision issue with GCTABackground3D Monte-Carlo simulations (#2708)

ChangeLog
1   -2018-10-31
  1 +2018-11-01
2 2  
3 3 * Version 1.6.0 released
4 4 ========================
5 5  
  6 + Fix precision issue with GCTABackground3D Monte-Carlo simulations (#2708)
6 7 Revise GCTAEdisp class interface (#2704)
7 8 GCTAEdisp returns now energy dispersion values per MeV (#2704)
8 9 Protect GCTAInstDir from access to invalid information (#2694)
... ...
1 1 New Features and Important Changes in GammaLib 1.6.0
2 2  
3   -31 October 2018
  3 +1 November 2018
4 4  
5 5  
6 6 1. Introduction
... ... @@ -306,6 +306,12 @@ None
306 306  
307 307 20. CTA interface
308 308 -----------------
  309 +GCTABackground3D::init_mc_cache now pre-computes the Monte Carlo cache at energy
  310 +nodes of the background cube, and in addition, inserts 8 logarithmically spaced
  311 +nodes between each pair of nodes. This assures that the energy variations of the
  312 +background rate are precisely captured and reproduced in the Monte Carlo
  313 +simulations (#2708).
  314 +
309 315 The GCTAEdisp::operator() now returns energy dispersion values per MeV. The
310 316 units are now consistent with the expectation in GResponse, and this changes
311 317 assurance the coherence between the various classes. In particular, no re-
... ...
doc/source/admin/release_history/1.6.rst
... ... @@ -19,6 +19,8 @@ In particular, this release provides:
19 19 Bug fixes
20 20 ---------
21 21  
  22 +* [`2708 <https://cta-redmine.irap.omp.eu/issues/2708>`_] -
  23 + Fix precision issue with ``GCTABackground3D`` Monte-Carlo simulations
22 24 * [`2683 <https://cta-redmine.irap.omp.eu/issues/2683>`_] -
23 25 Correct handling of stacked On/Off observations without background IRF.
24 26 Fix bug that potentially wrote the wrong exposure time in a PHA file.
... ...
inst/cta/src/GCTABackground3D.cpp
... ... @@ -912,6 +912,9 @@ int GCTABackground3D::index(const int&amp; idetx,
912 912 ***************************************************************************/
913 913 void GCTABackground3D::init_mc_cache(void) const
914 914 {
  915 + // Set number of subbins per energy bin of response cube
  916 + const int nsubbins = 10;
  917 +
915 918 // Initialise cache
916 919 m_mc_max.clear();
917 920 m_mc_spectrum.clear();
... ... @@ -936,23 +939,50 @@ void GCTABackground3D::init_mc_cache(void) const
936 939 }
937 940 m_mc_one_minus_costheta = 1.0 - std::cos(theta);
938 941  
939   - // Set number of energy bins. Make sure that we compute at least 100 energy
940   - // bins
941   - int nbins = m_num_energy * 10;
942   - if (nbins < 100) {
943   - nbins = 100;
944   - }
945   -
946   - // Compute DETX and DETY binsize in radians and energy binsize in log10(TeV)
  942 + // Compute DETX and DETY binsize in radians
947 943 double detx_bin = (m_detx_max - m_detx_min) / m_num_detx;
948 944 double dety_bin = (m_dety_max - m_dety_min) / m_num_dety;
949   - double logE_bin = (m_logE_max - m_logE_min) / (nbins-1);
  945 +
  946 + // Set energy bins for Monte Carlo cache spectrum. Make sure that the
  947 + // actual energy nodes are part of the energy bins to avoid that sharp
  948 + // structures in the background rate variations are missed.
  949 + GEnergies energies;
  950 + for (int i = 0; i < m_num_energy; ++i) {
  951 +
  952 + // If this is the first node then add energies below the first node
  953 + // down to the lower energy limit of the background response
  954 + if (i == 0) {
  955 + GEnergy emin(m_background.axis_lo(m_inx_energy, i),
  956 + m_background.axis_lo_unit(m_inx_energy));
  957 + GEnergies enodes(nsubbins/2, emin, m_energy[i]);
  958 + enodes.remove(enodes.size()-1); // avoids duplication of energy
  959 + energies.extend(enodes);
  960 + }
  961 +
  962 + // If this is not the last node then append nodes between current
  963 + // node and next node
  964 + if (i < m_num_energy-1) {
  965 + GEnergies enodes(nsubbins, m_energy[i], m_energy[i+1]);
  966 + enodes.remove(enodes.size()-1); // avoids duplication of energy
  967 + energies.extend(enodes);
  968 + }
  969 +
  970 + // ... otherwise this is the last node. Add energies above the last
  971 + // node up to the upper energy limit of the background response
  972 + else {
  973 + GEnergy emax(m_background.axis_hi(m_inx_energy, i),
  974 + m_background.axis_hi_unit(m_inx_energy));
  975 + GEnergies enodes(nsubbins/2, m_energy[i], emax);
  976 + energies.extend(enodes);
  977 + }
  978 +
  979 + } // endfor: looped over energy bins of background response
950 980  
951 981 // Loop over all energy bins
952   - for (int i = 0; i < nbins; ++i) {
  982 + for (int i = 0; i < energies.size(); ++i) {
953 983  
954 984 // Get logE of energy bin
955   - double logE = m_logE_min + i * logE_bin;
  985 + double logE = energies[i].log10TeV();
956 986  
957 987 // Initialise cache with cumulative pixel fluxes and compute total flux
958 988 // in response table for normalization. Negative pixels are excluded
... ... @@ -1007,18 +1037,14 @@ void GCTABackground3D::init_mc_cache(void) const
1007 1037  
1008 1038 } // endfor: loop over DETX
1009 1039  
1010   - // Set energy value (unit independent)
1011   - GEnergy energy;
1012   - energy.log10(logE, m_background.axis_lo_unit(m_inx_energy));
1013   -
1014   - // Only append node if flux is positive
  1040 + // Append node if flux is positive
1015 1041 if (total_flux > 0.0) {
1016   - m_mc_spectrum.append(energy, total_flux);
  1042 + m_mc_spectrum.append(energies[i], total_flux);
1017 1043 }
1018 1044  
1019 1045 // Dump spectrum for debugging
1020 1046 #if defined(G_DEBUG_MC_INIT)
1021   - std::cout << "Energy=" << energy;
  1047 + std::cout << "Energy=" << energies[i];
1022 1048 std::cout << " Rate_total=" << total_flux;
1023 1049 std::cout << " events/s/MeV" << std::endl;
1024 1050 #endif
... ...