Commit 44d3f497eb672a29adbe814218ff208dd1035bf0
1 parent
f4cec345
Use CTA response cache in GCTAResponse and GCTAResponseIRF and remove former dif…
…fuse model cache (#2715)
Showing
5 changed files
with
297 additions
and
325 deletions
NEWS
| @@ -312,7 +312,12 @@ None | @@ -312,7 +312,12 @@ None | ||
| 312 | 20. CTA interface | 312 | 20. CTA interface |
| 313 | ----------------- | 313 | ----------------- |
| 314 | The GCTAResponseCache class was added to implement a general response cache for | 314 | The GCTAResponseCache class was added to implement a general response cache for |
| 315 | -CTA (#2715). | 315 | +CTA. The response cache is now used in GCTAResponse::irf(GEvent&, GSource&, |
| 316 | +GObservation&) and in GCTAResponseIrf::nroi(GModelSky&, GEnergy&, GTime&, | ||
| 317 | +GEnergy&, GTime&, GObservation&) in case that the spatial model has no free | ||
| 318 | +parameters. This means that now all other spatial models with frozen parameters | ||
| 319 | +will be cached. The use of the cache can be toggled by internal data members | ||
| 320 | +(#2715). | ||
| 316 | 321 | ||
| 317 | GCTABackground3D::init_mc_cache now pre-computes the Monte Carlo cache at energy | 322 | GCTABackground3D::init_mc_cache now pre-computes the Monte Carlo cache at energy |
| 318 | nodes of the background cube, and in addition, inserts 8 logarithmically spaced | 323 | nodes of the background cube, and in addition, inserts 8 logarithmically spaced |
inst/cta/include/GCTAResponse.hpp
| @@ -30,6 +30,7 @@ | @@ -30,6 +30,7 @@ | ||
| 30 | /* __ Includes ___________________________________________________________ */ | 30 | /* __ Includes ___________________________________________________________ */ |
| 31 | #include <string> | 31 | #include <string> |
| 32 | #include "GResponse.hpp" | 32 | #include "GResponse.hpp" |
| 33 | +#include "GCTAResponseCache.hpp" | ||
| 33 | 34 | ||
| 34 | /* __ Type definitions ___________________________________________________ */ | 35 | /* __ Type definitions ___________________________________________________ */ |
| 35 | 36 | ||
| @@ -113,6 +114,12 @@ protected: | @@ -113,6 +114,12 @@ protected: | ||
| 113 | virtual double irf_composite(const GEvent& event, | 114 | virtual double irf_composite(const GEvent& event, |
| 114 | const GSource& source, | 115 | const GSource& source, |
| 115 | const GObservation& obs) const; | 116 | const GObservation& obs) const; |
| 117 | + | ||
| 118 | + // Protected members | ||
| 119 | + bool m_use_irf_cache; //!< Control usage of IRF cache | ||
| 120 | + | ||
| 121 | + // Cache for irf(GEvent&, GSource&, GObservation&) computation | ||
| 122 | + mutable GCTAResponseCache m_irf_cache; | ||
| 116 | }; | 123 | }; |
| 117 | 124 | ||
| 118 | #endif /* GCTARESPONSE_HPP */ | 125 | #endif /* GCTARESPONSE_HPP */ |
inst/cta/include/GCTAResponseIrf.hpp
| @@ -34,6 +34,7 @@ | @@ -34,6 +34,7 @@ | ||
| 34 | #include "GTime.hpp" | 34 | #include "GTime.hpp" |
| 35 | #include "GCaldb.hpp" | 35 | #include "GCaldb.hpp" |
| 36 | #include "GCTAResponse.hpp" | 36 | #include "GCTAResponse.hpp" |
| 37 | +#include "GCTAResponseCache.hpp" | ||
| 37 | #include "GCTAAeff.hpp" | 38 | #include "GCTAAeff.hpp" |
| 38 | #include "GCTAPsf.hpp" | 39 | #include "GCTAPsf.hpp" |
| 39 | #include "GCTAEdisp.hpp" | 40 | #include "GCTAEdisp.hpp" |
| @@ -218,16 +219,15 @@ private: | @@ -218,16 +219,15 @@ private: | ||
| 218 | mutable bool m_apply_edisp; //!< Apply energy dispersion | 219 | mutable bool m_apply_edisp; //!< Apply energy dispersion |
| 219 | double m_lo_save_thres; //!< Save low energy threshold | 220 | double m_lo_save_thres; //!< Save low energy threshold |
| 220 | double m_hi_save_thres; //!< Save high energy threshold | 221 | double m_hi_save_thres; //!< Save high energy threshold |
| 222 | + bool m_use_nroi_cache; //!< Control usage of nroi cache | ||
| 221 | 223 | ||
| 222 | // XML response filename | 224 | // XML response filename |
| 223 | std::string m_xml_caldb; //!< Calibration database string in XML file | 225 | std::string m_xml_caldb; //!< Calibration database string in XML file |
| 224 | std::string m_xml_rspname; //!< Response name in XML file | 226 | std::string m_xml_rspname; //!< Response name in XML file |
| 225 | 227 | ||
| 226 | - // Npred cache | ||
| 227 | - mutable std::vector<std::string> m_npred_names; //!< Model names | ||
| 228 | - mutable std::vector<GEnergy> m_npred_energies; //!< Model energy | ||
| 229 | - mutable std::vector<GTime> m_npred_times; //!< Model time | ||
| 230 | - mutable std::vector<double> m_npred_values; //!< Model values | 228 | + // Cache for nroi(GModelSky&, GEnergy&, GTime&, GEnergy&, GTime&, GObservation&) |
| 229 | + // computation | ||
| 230 | + mutable GCTAResponseCache m_nroi_cache; | ||
| 231 | }; | 231 | }; |
| 232 | 232 | ||
| 233 | 233 |
inst/cta/src/GCTAResponse.cpp
| @@ -34,6 +34,7 @@ | @@ -34,6 +34,7 @@ | ||
| 34 | #include "GModelSpatial.hpp" | 34 | #include "GModelSpatial.hpp" |
| 35 | #include "GModelSpatialComposite.hpp" | 35 | #include "GModelSpatialComposite.hpp" |
| 36 | #include "GCTAResponse.hpp" | 36 | #include "GCTAResponse.hpp" |
| 37 | +#include "GCTAResponse.hpp" | ||
| 37 | 38 | ||
| 38 | /* __ Method name definitions ____________________________________________ */ | 39 | /* __ Method name definitions ____________________________________________ */ |
| 39 | 40 | ||
| @@ -166,25 +167,48 @@ double GCTAResponse::irf(const GEvent& event, | @@ -166,25 +167,48 @@ double GCTAResponse::irf(const GEvent& event, | ||
| 166 | // Initialise IRF value | 167 | // Initialise IRF value |
| 167 | double irf = 0.0; | 168 | double irf = 0.0; |
| 168 | 169 | ||
| 169 | - // Select IRF depending on the spatial model type | ||
| 170 | - switch (source.model()->code()) { | ||
| 171 | - case GMODEL_SPATIAL_POINT_SOURCE: | ||
| 172 | - irf = irf_ptsrc(event, source, obs); | ||
| 173 | - break; | ||
| 174 | - case GMODEL_SPATIAL_RADIAL: | ||
| 175 | - irf = irf_radial(event, source, obs); | ||
| 176 | - break; | ||
| 177 | - case GMODEL_SPATIAL_ELLIPTICAL: | ||
| 178 | - irf = irf_elliptical(event, source, obs); | ||
| 179 | - break; | ||
| 180 | - case GMODEL_SPATIAL_DIFFUSE: | ||
| 181 | - irf = irf_diffuse(event, source, obs); | ||
| 182 | - break; | ||
| 183 | - case GMODEL_SPATIAL_COMPOSITE: | ||
| 184 | - irf = irf_composite(event, source, obs); | ||
| 185 | - break; | ||
| 186 | - default: | ||
| 187 | - break; | 170 | + // Set IRF value attributes |
| 171 | + std::string name = obs.id() + "::" + source.name(); | ||
| 172 | + const GEnergy& ereco = event.energy(); | ||
| 173 | + const GEnergy& etrue = source.energy(); | ||
| 174 | + | ||
| 175 | + // Signal if spatial model has free parameters | ||
| 176 | + bool has_free_pars = source.model()->has_free_pars(); | ||
| 177 | + | ||
| 178 | + // If the spatial model component has free parameters, or the response | ||
| 179 | + // cache should not be used, or the cache does not contain the requested | ||
| 180 | + // IRF value then compute the IRF value for the spatial model. | ||
| 181 | + if (has_free_pars || | ||
| 182 | + !m_use_irf_cache || | ||
| 183 | + !m_irf_cache.contains(name, ereco, etrue, &irf)) { | ||
| 184 | + | ||
| 185 | + // Compute IRF for spatial model | ||
| 186 | + switch (source.model()->code()) { | ||
| 187 | + case GMODEL_SPATIAL_POINT_SOURCE: | ||
| 188 | + irf = irf_ptsrc(event, source, obs); | ||
| 189 | + break; | ||
| 190 | + case GMODEL_SPATIAL_RADIAL: | ||
| 191 | + irf = irf_radial(event, source, obs); | ||
| 192 | + break; | ||
| 193 | + case GMODEL_SPATIAL_ELLIPTICAL: | ||
| 194 | + irf = irf_elliptical(event, source, obs); | ||
| 195 | + break; | ||
| 196 | + case GMODEL_SPATIAL_DIFFUSE: | ||
| 197 | + irf = irf_diffuse(event, source, obs); | ||
| 198 | + break; | ||
| 199 | + case GMODEL_SPATIAL_COMPOSITE: | ||
| 200 | + irf = irf_composite(event, source, obs); | ||
| 201 | + break; | ||
| 202 | + default: | ||
| 203 | + break; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + } // endif: computed spatial model | ||
| 207 | + | ||
| 208 | + // If the spatial model has no free parameters and the response cache | ||
| 209 | + // should be used then put the IRF value in the response cache. | ||
| 210 | + if (!has_free_pars && m_use_irf_cache) { | ||
| 211 | + m_irf_cache.set(name, ereco, etrue, irf); | ||
| 188 | } | 212 | } |
| 189 | 213 | ||
| 190 | // Return IRF value | 214 | // Return IRF value |
| @@ -203,6 +227,10 @@ double GCTAResponse::irf(const GEvent& event, | @@ -203,6 +227,10 @@ double GCTAResponse::irf(const GEvent& event, | ||
| 203 | ***************************************************************************/ | 227 | ***************************************************************************/ |
| 204 | void GCTAResponse::init_members(void) | 228 | void GCTAResponse::init_members(void) |
| 205 | { | 229 | { |
| 230 | + // Initialize members | ||
| 231 | + m_use_irf_cache = true; | ||
| 232 | + m_irf_cache.clear(); | ||
| 233 | + | ||
| 206 | // Return | 234 | // Return |
| 207 | return; | 235 | return; |
| 208 | } | 236 | } |
| @@ -215,6 +243,10 @@ void GCTAResponse::init_members(void) | @@ -215,6 +243,10 @@ void GCTAResponse::init_members(void) | ||
| 215 | ***************************************************************************/ | 243 | ***************************************************************************/ |
| 216 | void GCTAResponse::copy_members(const GCTAResponse& rsp) | 244 | void GCTAResponse::copy_members(const GCTAResponse& rsp) |
| 217 | { | 245 | { |
| 246 | + // Copy members | ||
| 247 | + m_use_irf_cache = rsp.m_use_irf_cache; | ||
| 248 | + m_irf_cache = rsp.m_irf_cache; | ||
| 249 | + | ||
| 218 | // Return | 250 | // Return |
| 219 | return; | 251 | return; |
| 220 | } | 252 | } |
inst/cta/src/GCTAResponseIrf.cpp
| @@ -107,8 +107,6 @@ | @@ -107,8 +107,6 @@ | ||
| 107 | /* __ Macros _____________________________________________________________ */ | 107 | /* __ Macros _____________________________________________________________ */ |
| 108 | 108 | ||
| 109 | /* __ Coding definitions _________________________________________________ */ | 109 | /* __ Coding definitions _________________________________________________ */ |
| 110 | -#define G_USE_IRF_CACHE //!< Use IRF cache in irf_diffuse method | ||
| 111 | -#define G_USE_NPRED_CACHE //!< Use Npred cache in npred_diffuse method | ||
| 112 | //#define G_USE_PSF_SYSTEM //!< Do radial Irf integrations in Psf system | 110 | //#define G_USE_PSF_SYSTEM //!< Do radial Irf integrations in Psf system |
| 113 | 111 | ||
| 114 | /* __ Debug definitions __________________________________________________ */ | 112 | /* __ Debug definitions __________________________________________________ */ |
| @@ -1604,8 +1602,8 @@ std::string GCTAResponseIrf::print(const GChatter& chatter) const | @@ -1604,8 +1602,8 @@ std::string GCTAResponseIrf::print(const GChatter& chatter) const | ||
| 1604 | } | 1602 | } |
| 1605 | } | 1603 | } |
| 1606 | 1604 | ||
| 1607 | - // Append save energy threshold information | ||
| 1608 | - result.append("\n"+gammalib::parformat("Save energy range")); | 1605 | + // Append safe energy threshold information |
| 1606 | + result.append("\n"+gammalib::parformat("Safe energy range")); | ||
| 1609 | if (m_lo_save_thres > 0.0 && m_hi_save_thres) { | 1607 | if (m_lo_save_thres > 0.0 && m_hi_save_thres) { |
| 1610 | result.append(gammalib::str(m_lo_save_thres)); | 1608 | result.append(gammalib::str(m_lo_save_thres)); |
| 1611 | result.append(" - "); | 1609 | result.append(" - "); |
| @@ -1626,9 +1624,11 @@ std::string GCTAResponseIrf::print(const GChatter& chatter) const | @@ -1626,9 +1624,11 @@ std::string GCTAResponseIrf::print(const GChatter& chatter) const | ||
| 1626 | result.append("undefined"); | 1624 | result.append("undefined"); |
| 1627 | } | 1625 | } |
| 1628 | 1626 | ||
| 1629 | - // Append detailed information | 1627 | + // Get reduced chatter level |
| 1630 | GChatter reduced_chatter = gammalib::reduce(chatter); | 1628 | GChatter reduced_chatter = gammalib::reduce(chatter); |
| 1631 | - if (reduced_chatter > SILENT) { | 1629 | + |
| 1630 | + // Append detailed information | ||
| 1631 | + if (chatter >= NORMAL) { | ||
| 1632 | 1632 | ||
| 1633 | // Append calibration database | 1633 | // Append calibration database |
| 1634 | result.append("\n"+m_caldb.print(reduced_chatter)); | 1634 | result.append("\n"+m_caldb.print(reduced_chatter)); |
| @@ -1655,19 +1655,11 @@ std::string GCTAResponseIrf::print(const GChatter& chatter) const | @@ -1655,19 +1655,11 @@ std::string GCTAResponseIrf::print(const GChatter& chatter) const | ||
| 1655 | 1655 | ||
| 1656 | } | 1656 | } |
| 1657 | 1657 | ||
| 1658 | - // EXPLICIT: Append Npred cache information | 1658 | + // Append cache information |
| 1659 | if (chatter >= EXPLICIT) { | 1659 | if (chatter >= EXPLICIT) { |
| 1660 | - if (!m_npred_names.empty()) { | ||
| 1661 | - for (int i = 0; i < m_npred_names.size(); ++i) { | ||
| 1662 | - result.append("\n"+gammalib::parformat("Npred cache " + | ||
| 1663 | - gammalib::str(i))); | ||
| 1664 | - result.append(m_npred_names[i]+", "); | ||
| 1665 | - result.append(m_npred_energies[i].print()+", "); | ||
| 1666 | - result.append(m_npred_times[i].print()+" = "); | ||
| 1667 | - result.append(gammalib::str(m_npred_values[i])); | ||
| 1668 | - } | ||
| 1669 | - } | ||
| 1670 | - } // endif: chatter was explicit | 1660 | + result.append("\n"+m_irf_cache.print(reduced_chatter)); |
| 1661 | + result.append("\n"+m_nroi_cache.print(reduced_chatter)); | ||
| 1662 | + } | ||
| 1671 | 1663 | ||
| 1672 | } // endif: chatter was not silent | 1664 | } // endif: chatter was not silent |
| 1673 | 1665 | ||
| @@ -1864,25 +1856,46 @@ double GCTAResponseIrf::nroi(const GModelSky& model, | @@ -1864,25 +1856,46 @@ double GCTAResponseIrf::nroi(const GModelSky& model, | ||
| 1864 | // Initialise response value | 1856 | // Initialise response value |
| 1865 | double nroi = 0.0; | 1857 | double nroi = 0.0; |
| 1866 | 1858 | ||
| 1867 | - // Select method depending on the spatial model type | ||
| 1868 | - switch (model.spatial()->code()) { | ||
| 1869 | - case GMODEL_SPATIAL_POINT_SOURCE: | ||
| 1870 | - nroi = nroi_ptsrc(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1871 | - break; | ||
| 1872 | - case GMODEL_SPATIAL_RADIAL: | ||
| 1873 | - nroi = nroi_radial(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1874 | - break; | ||
| 1875 | - case GMODEL_SPATIAL_ELLIPTICAL: | ||
| 1876 | - nroi = nroi_elliptical(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1877 | - break; | ||
| 1878 | - case GMODEL_SPATIAL_DIFFUSE: | ||
| 1879 | - nroi = nroi_diffuse(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1880 | - break; | ||
| 1881 | - case GMODEL_SPATIAL_COMPOSITE: | ||
| 1882 | - nroi = nroi_composite(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1883 | - break; | ||
| 1884 | - default: | ||
| 1885 | - break; | 1859 | + // Set response value attributes |
| 1860 | + std::string name = obs.id() + "::" + model.name(); | ||
| 1861 | + | ||
| 1862 | + // Signal if spatial model has free parameters | ||
| 1863 | + bool has_free_pars = model.spatial()->has_free_pars(); | ||
| 1864 | + | ||
| 1865 | + // If the spatial model component has free parameters, or the response | ||
| 1866 | + // cache should not be used, or the cache does not contain the requested | ||
| 1867 | + // IRF value then compute the IRF value for the spatial model. | ||
| 1868 | + if (has_free_pars || | ||
| 1869 | + !m_use_nroi_cache || | ||
| 1870 | + !m_nroi_cache.contains(name, obsEng, srcEng, &nroi)) { | ||
| 1871 | + | ||
| 1872 | + // Select method depending on the spatial model type | ||
| 1873 | + switch (model.spatial()->code()) { | ||
| 1874 | + case GMODEL_SPATIAL_POINT_SOURCE: | ||
| 1875 | + nroi = nroi_ptsrc(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1876 | + break; | ||
| 1877 | + case GMODEL_SPATIAL_RADIAL: | ||
| 1878 | + nroi = nroi_radial(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1879 | + break; | ||
| 1880 | + case GMODEL_SPATIAL_ELLIPTICAL: | ||
| 1881 | + nroi = nroi_elliptical(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1882 | + break; | ||
| 1883 | + case GMODEL_SPATIAL_DIFFUSE: | ||
| 1884 | + nroi = nroi_diffuse(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1885 | + break; | ||
| 1886 | + case GMODEL_SPATIAL_COMPOSITE: | ||
| 1887 | + nroi = nroi_composite(model, srcEng, srcTime, obsEng, obsTime, obs); | ||
| 1888 | + break; | ||
| 1889 | + default: | ||
| 1890 | + break; | ||
| 1891 | + } | ||
| 1892 | + | ||
| 1893 | + } // endif: computed spatial model | ||
| 1894 | + | ||
| 1895 | + // If the spatial model has no free parameters and the response cache | ||
| 1896 | + // should be used then put the IRF value in the response cache. | ||
| 1897 | + if (!has_free_pars && m_use_nroi_cache) { | ||
| 1898 | + m_nroi_cache.set(name, obsEng, srcEng, nroi); | ||
| 1886 | } | 1899 | } |
| 1887 | 1900 | ||
| 1888 | // Return response value | 1901 | // Return response value |
| @@ -2105,23 +2118,21 @@ void GCTAResponseIrf::init_members(void) | @@ -2105,23 +2118,21 @@ void GCTAResponseIrf::init_members(void) | ||
| 2105 | // Initialise members | 2118 | // Initialise members |
| 2106 | m_caldb.clear(); | 2119 | m_caldb.clear(); |
| 2107 | m_rspname.clear(); | 2120 | m_rspname.clear(); |
| 2108 | - m_aeff = NULL; | ||
| 2109 | - m_psf = NULL; | ||
| 2110 | - m_edisp = NULL; | ||
| 2111 | - m_background = NULL; | ||
| 2112 | - m_apply_edisp = false; //!< Switched off by default | ||
| 2113 | - m_lo_save_thres = 0.0; | ||
| 2114 | - m_hi_save_thres = 0.0; | 2121 | + m_aeff = NULL; |
| 2122 | + m_psf = NULL; | ||
| 2123 | + m_edisp = NULL; | ||
| 2124 | + m_background = NULL; | ||
| 2125 | + m_apply_edisp = false; //!< Switched off by default | ||
| 2126 | + m_lo_save_thres = 0.0; | ||
| 2127 | + m_hi_save_thres = 0.0; | ||
| 2128 | + m_use_nroi_cache = true; //!< Switched on by default | ||
| 2115 | 2129 | ||
| 2116 | // XML response filenames | 2130 | // XML response filenames |
| 2117 | m_xml_caldb.clear(); | 2131 | m_xml_caldb.clear(); |
| 2118 | m_xml_rspname.clear(); | 2132 | m_xml_rspname.clear(); |
| 2119 | 2133 | ||
| 2120 | - // Initialise Npred cache | ||
| 2121 | - m_npred_names.clear(); | ||
| 2122 | - m_npred_energies.clear(); | ||
| 2123 | - m_npred_times.clear(); | ||
| 2124 | - m_npred_values.clear(); | 2134 | + // Initialise nroi cache |
| 2135 | + m_nroi_cache.clear(); | ||
| 2125 | 2136 | ||
| 2126 | // Return | 2137 | // Return |
| 2127 | return; | 2138 | return; |
| @@ -2136,21 +2147,19 @@ void GCTAResponseIrf::init_members(void) | @@ -2136,21 +2147,19 @@ void GCTAResponseIrf::init_members(void) | ||
| 2136 | void GCTAResponseIrf::copy_members(const GCTAResponseIrf& rsp) | 2147 | void GCTAResponseIrf::copy_members(const GCTAResponseIrf& rsp) |
| 2137 | { | 2148 | { |
| 2138 | // Copy members | 2149 | // Copy members |
| 2139 | - m_caldb = rsp.m_caldb; | ||
| 2140 | - m_rspname = rsp.m_rspname; | ||
| 2141 | - m_apply_edisp = rsp.m_apply_edisp; | ||
| 2142 | - m_lo_save_thres = rsp.m_lo_save_thres; | ||
| 2143 | - m_hi_save_thres = rsp.m_hi_save_thres; | 2150 | + m_caldb = rsp.m_caldb; |
| 2151 | + m_rspname = rsp.m_rspname; | ||
| 2152 | + m_apply_edisp = rsp.m_apply_edisp; | ||
| 2153 | + m_lo_save_thres = rsp.m_lo_save_thres; | ||
| 2154 | + m_hi_save_thres = rsp.m_hi_save_thres; | ||
| 2155 | + m_use_nroi_cache = rsp.m_use_nroi_cache; | ||
| 2144 | 2156 | ||
| 2145 | // Copy response filenames | 2157 | // Copy response filenames |
| 2146 | m_xml_caldb = rsp.m_xml_caldb; | 2158 | m_xml_caldb = rsp.m_xml_caldb; |
| 2147 | m_xml_rspname = rsp.m_xml_rspname; | 2159 | m_xml_rspname = rsp.m_xml_rspname; |
| 2148 | 2160 | ||
| 2149 | - // Copy cache | ||
| 2150 | - m_npred_names = rsp.m_npred_names; | ||
| 2151 | - m_npred_energies = rsp.m_npred_energies; | ||
| 2152 | - m_npred_times = rsp.m_npred_times; | ||
| 2153 | - m_npred_values = rsp.m_npred_values; | 2161 | + // Copy nroi cache |
| 2162 | + m_nroi_cache = rsp.m_nroi_cache; | ||
| 2154 | 2163 | ||
| 2155 | // Clone members | 2164 | // Clone members |
| 2156 | m_aeff = (rsp.m_aeff != NULL) ? rsp.m_aeff->clone() : NULL; | 2165 | m_aeff = (rsp.m_aeff != NULL) ? rsp.m_aeff->clone() : NULL; |
| @@ -2715,152 +2724,117 @@ double GCTAResponseIrf::irf_diffuse(const GEvent& event, | @@ -2715,152 +2724,117 @@ double GCTAResponseIrf::irf_diffuse(const GEvent& event, | ||
| 2715 | static const int max_iter_phi = 8; | 2724 | static const int max_iter_phi = 8; |
| 2716 | 2725 | ||
| 2717 | // Initialise IRF value | 2726 | // Initialise IRF value |
| 2718 | - bool has_irf = false; | ||
| 2719 | - double irf = 0.0; | 2727 | + double irf = 0.0; |
| 2720 | 2728 | ||
| 2721 | // Retrieve CTA pointing | 2729 | // Retrieve CTA pointing |
| 2722 | const GCTAPointing& pnt = gammalib::cta_pnt(G_IRF_DIFFUSE, obs); | 2730 | const GCTAPointing& pnt = gammalib::cta_pnt(G_IRF_DIFFUSE, obs); |
| 2723 | 2731 | ||
| 2724 | - // Try getting the IRF value from cache. Do not do this for energy | ||
| 2725 | - // dispersion since the the spectral model will change the IRF values | ||
| 2726 | - #if defined(G_USE_IRF_CACHE) | ||
| 2727 | - const GCTAEventList* list = dynamic_cast<const GCTAEventList*>(obs.events()); | ||
| 2728 | - const GCTAEventAtom* atom = dynamic_cast<const GCTAEventAtom*>(&event); | ||
| 2729 | - if (list != NULL && atom != NULL && !use_edisp()) { | ||
| 2730 | - irf = list->irf_cache(source.name(), atom->index()); | ||
| 2731 | - if (irf >= 0.0) { | ||
| 2732 | - has_irf = true; | ||
| 2733 | - #if defined(G_DEBUG_IRF_DIFFUSE) | ||
| 2734 | - std::cout << "GCTAResponseIrf::irf_diffuse:"; | ||
| 2735 | - std::cout << " cached irf=" << irf << std::endl; | ||
| 2736 | - #endif | ||
| 2737 | - } | ||
| 2738 | - else { | ||
| 2739 | - irf = 0.0; | ||
| 2740 | - } | ||
| 2741 | - } | ||
| 2742 | - #endif | ||
| 2743 | - | ||
| 2744 | - // Continue only if we have no IRF value | ||
| 2745 | - if (!has_irf) { | 2732 | + // Get CTA instrument direction |
| 2733 | + const GCTAInstDir& dir = gammalib::cta_dir(G_IRF_ELLIPTICAL, event); | ||
| 2746 | 2734 | ||
| 2747 | - // Get CTA instrument direction | ||
| 2748 | - const GCTAInstDir& dir = gammalib::cta_dir(G_IRF_ELLIPTICAL, event); | ||
| 2749 | - | ||
| 2750 | - // Get pointer on spatial model | ||
| 2751 | - const GModelSpatial* model = | ||
| 2752 | - dynamic_cast<const GModelSpatial*>(source.model()); | ||
| 2753 | - if (model == NULL) { | ||
| 2754 | - throw GCTAException::bad_model_type(G_IRF_DIFFUSE); | ||
| 2755 | - } | ||
| 2756 | - | ||
| 2757 | - // Get resolution of spatial model | ||
| 2758 | - double resolution = gammalib::resolution(model); | ||
| 2759 | - | ||
| 2760 | - // Get event attributes | ||
| 2761 | - const GEnergy& obsEng = event.energy(); | 2735 | + // Get pointer on spatial model |
| 2736 | + const GModelSpatial* model = | ||
| 2737 | + dynamic_cast<const GModelSpatial*>(source.model()); | ||
| 2738 | + if (model == NULL) { | ||
| 2739 | + throw GCTAException::bad_model_type(G_IRF_DIFFUSE); | ||
| 2740 | + } | ||
| 2762 | 2741 | ||
| 2763 | - // Get source attributes | ||
| 2764 | - const GEnergy& srcEng = source.energy(); | ||
| 2765 | - const GTime& srcTime = source.time(); | 2742 | + // Get resolution of spatial model |
| 2743 | + double resolution = gammalib::resolution(model); | ||
| 2766 | 2744 | ||
| 2767 | - // Get pointing direction zenith angle and azimuth [radians] | ||
| 2768 | - double zenith = pnt.zenith(); | ||
| 2769 | - double azimuth = pnt.azimuth(); | 2745 | + // Get event attributes |
| 2746 | + const GEnergy& obsEng = event.energy(); | ||
| 2770 | 2747 | ||
| 2771 | - // Determine angular distance between measured photon direction and | ||
| 2772 | - // pointing direction [radians] | ||
| 2773 | - double eta = pnt.dir().dist(dir.dir()); | 2748 | + // Get source attributes |
| 2749 | + const GEnergy& srcEng = source.energy(); | ||
| 2750 | + const GTime& srcTime = source.time(); | ||
| 2774 | 2751 | ||
| 2775 | - // Get log10(E/TeV) of true photon energy | ||
| 2776 | - double srcLogEng = srcEng.log10TeV(); | 2752 | + // Get pointing direction zenith angle and azimuth [radians] |
| 2753 | + double zenith = pnt.zenith(); | ||
| 2754 | + double azimuth = pnt.azimuth(); | ||
| 2777 | 2755 | ||
| 2778 | - // Assign the observed theta angle (eta) as the true theta angle | ||
| 2779 | - // between the source and the pointing directions. This is a (not | ||
| 2780 | - // too bad) approximation which helps to speed up computations. | ||
| 2781 | - // If we want to do this correctly, however, we would need to move | ||
| 2782 | - // the psf_dummy_sigma down to the integration kernel, and we would | ||
| 2783 | - // need to make sure that psf_delta_max really gives the absolute | ||
| 2784 | - // maximum (this is certainly less critical) | ||
| 2785 | - double theta = eta; | ||
| 2786 | - double phi = 0.0; //TODO: Implement Phi dependence | 2756 | + // Determine angular distance between measured photon direction and |
| 2757 | + // pointing direction [radians] | ||
| 2758 | + double eta = pnt.dir().dist(dir.dir()); | ||
| 2787 | 2759 | ||
| 2788 | - // Get maximum PSF radius in radians | ||
| 2789 | - double delta_max = psf_delta_max(theta, phi, zenith, azimuth, srcLogEng); | 2760 | + // Get log10(E/TeV) of true photon energy |
| 2761 | + double srcLogEng = srcEng.log10TeV(); | ||
| 2790 | 2762 | ||
| 2791 | - // Perform zenith angle integration if interval is valid | ||
| 2792 | - if (delta_max > 0.0) { | 2763 | + // Assign the observed theta angle (eta) as the true theta angle |
| 2764 | + // between the source and the pointing directions. This is a (not | ||
| 2765 | + // too bad) approximation which helps to speed up computations. | ||
| 2766 | + // If we want to do this correctly, however, we would need to move | ||
| 2767 | + // the psf_dummy_sigma down to the integration kernel, and we would | ||
| 2768 | + // need to make sure that psf_delta_max really gives the absolute | ||
| 2769 | + // maximum (this is certainly less critical) | ||
| 2770 | + double theta = eta; | ||
| 2771 | + double phi = 0.0; //TODO: Implement Phi dependence | ||
| 2793 | 2772 | ||
| 2794 | - // Compute rotation matrix to convert from coordinates (theta,phi) | ||
| 2795 | - // in the reference frame of the observed arrival direction into | ||
| 2796 | - // celestial coordinates | ||
| 2797 | - GMatrix ry; | ||
| 2798 | - GMatrix rz; | ||
| 2799 | - ry.eulery(dir.dir().dec_deg() - 90.0); | ||
| 2800 | - rz.eulerz(-dir.dir().ra_deg()); | ||
| 2801 | - GMatrix rot = (ry * rz).transpose(); | 2773 | + // Get maximum PSF radius in radians |
| 2774 | + double delta_max = psf_delta_max(theta, phi, zenith, azimuth, srcLogEng); | ||
| 2802 | 2775 | ||
| 2803 | - // Setup integration kernel | ||
| 2804 | - cta_irf_diffuse_kern_theta integrand(this, | ||
| 2805 | - model, | ||
| 2806 | - &rot, | ||
| 2807 | - theta, | ||
| 2808 | - phi, | ||
| 2809 | - zenith, | ||
| 2810 | - azimuth, | ||
| 2811 | - srcEng, | ||
| 2812 | - srcTime, | ||
| 2813 | - srcLogEng, | ||
| 2814 | - obsEng, | ||
| 2815 | - eta, | ||
| 2816 | - min_iter_phi, | ||
| 2817 | - max_iter_phi, | ||
| 2818 | - resolution); | ||
| 2819 | - | ||
| 2820 | - // Set number of radial integration iterations | ||
| 2821 | - int iter = gammalib::iter_rho(delta_max, resolution, | ||
| 2822 | - min_iter_rho, max_iter_rho); | ||
| 2823 | - | ||
| 2824 | - // Integrate over Psf delta angle | ||
| 2825 | - GIntegral integral(&integrand); | ||
| 2826 | - integral.fixed_iter(iter); | ||
| 2827 | - irf = integral.romberg(0.0, delta_max); | 2776 | + // Perform zenith angle integration if interval is valid |
| 2777 | + if (delta_max > 0.0) { | ||
| 2828 | 2778 | ||
| 2829 | - // Compile option: Check for NaN/Inf | ||
| 2830 | - #if defined(G_NAN_CHECK) | ||
| 2831 | - if (gammalib::is_notanumber(irf) || gammalib::is_infinite(irf)) { | ||
| 2832 | - std::cout << "*** ERROR: GCTAResponseIrf::irf_diffuse:"; | ||
| 2833 | - std::cout << " NaN/Inf encountered"; | ||
| 2834 | - std::cout << " (irf=" << irf; | ||
| 2835 | - std::cout << ", delta_max=" << delta_max << ")"; | ||
| 2836 | - std::cout << std::endl; | ||
| 2837 | - } | ||
| 2838 | - #endif | ||
| 2839 | - } | 2779 | + // Compute rotation matrix to convert from coordinates (theta,phi) |
| 2780 | + // in the reference frame of the observed arrival direction into | ||
| 2781 | + // celestial coordinates | ||
| 2782 | + GMatrix ry; | ||
| 2783 | + GMatrix rz; | ||
| 2784 | + ry.eulery(dir.dir().dec_deg() - 90.0); | ||
| 2785 | + rz.eulerz(-dir.dir().ra_deg()); | ||
| 2786 | + GMatrix rot = (ry * rz).transpose(); | ||
| 2840 | 2787 | ||
| 2841 | - // Apply deadtime correction | ||
| 2842 | - irf *= obs.deadc(srcTime); | 2788 | + // Setup integration kernel |
| 2789 | + cta_irf_diffuse_kern_theta integrand(this, | ||
| 2790 | + model, | ||
| 2791 | + &rot, | ||
| 2792 | + theta, | ||
| 2793 | + phi, | ||
| 2794 | + zenith, | ||
| 2795 | + azimuth, | ||
| 2796 | + srcEng, | ||
| 2797 | + srcTime, | ||
| 2798 | + srcLogEng, | ||
| 2799 | + obsEng, | ||
| 2800 | + eta, | ||
| 2801 | + min_iter_phi, | ||
| 2802 | + max_iter_phi, | ||
| 2803 | + resolution); | ||
| 2804 | + | ||
| 2805 | + // Set number of radial integration iterations | ||
| 2806 | + int iter = gammalib::iter_rho(delta_max, resolution, | ||
| 2807 | + min_iter_rho, max_iter_rho); | ||
| 2808 | + | ||
| 2809 | + // Integrate over Psf delta angle | ||
| 2810 | + GIntegral integral(&integrand); | ||
| 2811 | + integral.fixed_iter(iter); | ||
| 2812 | + irf = integral.romberg(0.0, delta_max); | ||
| 2843 | 2813 | ||
| 2844 | - // Put IRF value in cache. Only do this in no energy dispersion is | ||
| 2845 | - // requested, since for energy dispersion the IRF values will | ||
| 2846 | - // depend on the spectrum | ||
| 2847 | - #if defined(G_USE_IRF_CACHE) | ||
| 2848 | - if (list != NULL && atom != NULL && !use_edisp()) { | ||
| 2849 | - list->irf_cache(source.name(), atom->index(), irf); | 2814 | + // Compile option: Check for NaN/Inf |
| 2815 | + #if defined(G_NAN_CHECK) | ||
| 2816 | + if (gammalib::is_notanumber(irf) || gammalib::is_infinite(irf)) { | ||
| 2817 | + std::cout << "*** ERROR: GCTAResponseIrf::irf_diffuse:"; | ||
| 2818 | + std::cout << " NaN/Inf encountered"; | ||
| 2819 | + std::cout << " (irf=" << irf; | ||
| 2820 | + std::cout << ", delta_max=" << delta_max << ")"; | ||
| 2821 | + std::cout << std::endl; | ||
| 2850 | } | 2822 | } |
| 2851 | #endif | 2823 | #endif |
| 2824 | + } | ||
| 2852 | 2825 | ||
| 2853 | - // Compile option: Show integration results | ||
| 2854 | - #if defined(G_DEBUG_IRF_DIFFUSE) | ||
| 2855 | - std::cout << "GCTAResponseIrf::irf_diffuse:"; | ||
| 2856 | - std::cout << " srcLogEng=" << srcLogEng; | ||
| 2857 | - std::cout << " obsLogEng=" << obsLogEng; | ||
| 2858 | - std::cout << " eta=" << eta; | ||
| 2859 | - std::cout << " delta_max=" << delta_max; | ||
| 2860 | - std::cout << " irf=" << irf << std::endl; | ||
| 2861 | - #endif | 2826 | + // Apply deadtime correction |
| 2827 | + irf *= obs.deadc(srcTime); | ||
| 2862 | 2828 | ||
| 2863 | - } // endif: has no IRF | 2829 | + // Compile option: Show integration results |
| 2830 | + #if defined(G_DEBUG_IRF_DIFFUSE) | ||
| 2831 | + std::cout << "GCTAResponseIrf::irf_diffuse:"; | ||
| 2832 | + std::cout << " srcLogEng=" << srcLogEng; | ||
| 2833 | + std::cout << " obsLogEng=" << obsLogEng; | ||
| 2834 | + std::cout << " eta=" << eta; | ||
| 2835 | + std::cout << " delta_max=" << delta_max; | ||
| 2836 | + std::cout << " irf=" << irf << std::endl; | ||
| 2837 | + #endif | ||
| 2864 | 2838 | ||
| 2865 | // Return IRF value | 2839 | // Return IRF value |
| 2866 | return irf; | 2840 | return irf; |
| @@ -3326,137 +3300,91 @@ double GCTAResponseIrf::nroi_diffuse(const GModelSky& model, | @@ -3326,137 +3300,91 @@ double GCTAResponseIrf::nroi_diffuse(const GModelSky& model, | ||
| 3326 | static const int iter_phi = 9; | 3300 | static const int iter_phi = 9; |
| 3327 | 3301 | ||
| 3328 | // Initialise Nroi value | 3302 | // Initialise Nroi value |
| 3329 | - double nroi = 0.0; | ||
| 3330 | - bool has_nroi = false; | ||
| 3331 | - | ||
| 3332 | - // Build unique identifier | ||
| 3333 | - std::string id = model.name() + "::" + obs.id(); | ||
| 3334 | - | ||
| 3335 | - // Check if Nroi value is already in cache. Do not use the Npred cache | ||
| 3336 | - // for energy dispersion since the actual value will depend on the | ||
| 3337 | - // spectral model | ||
| 3338 | - #if defined(G_USE_NPRED_CACHE) | ||
| 3339 | - if (!m_npred_names.empty() && !use_edisp()) { | ||
| 3340 | - | ||
| 3341 | - // Search for unique identifier, and if found, recover Npred value | ||
| 3342 | - // and break | ||
| 3343 | - for (int i = 0; i < m_npred_names.size(); ++i) { | ||
| 3344 | - if (m_npred_names[i] == id && | ||
| 3345 | - m_npred_energies[i] == srcEng && | ||
| 3346 | - m_npred_times[i] == srcTime) { | ||
| 3347 | - nroi = m_npred_values[i]; | ||
| 3348 | - has_nroi = true; | ||
| 3349 | - #if defined(G_DEBUG_NROI_DIFFUSE) | ||
| 3350 | - std::cout << "GCTAResponseIrf::nroi_diffuse:"; | ||
| 3351 | - std::cout << " cache=" << i; | ||
| 3352 | - std::cout << " nroi=" << nroi << std::endl; | ||
| 3353 | - #endif | ||
| 3354 | - break; | ||
| 3355 | - } | ||
| 3356 | - } | ||
| 3357 | - | ||
| 3358 | - } // endif: there were values in the Npred cache | ||
| 3359 | - #endif | ||
| 3360 | - | ||
| 3361 | - // Continue only if no Npred cache value was found | ||
| 3362 | - if (!has_nroi) { | 3303 | + double nroi = 0.0; |
| 3363 | 3304 | ||
| 3364 | - // Retrieve CTA observation, ROI and pointing | ||
| 3365 | - const GCTAObservation& cta = gammalib::cta_obs(G_NROI_DIFFUSE, obs); | ||
| 3366 | - const GCTARoi& roi = gammalib::cta_event_list(G_NROI_DIFFUSE, obs).roi(); | ||
| 3367 | - const GCTAPointing& pnt = cta.pointing(); | 3305 | + // Retrieve CTA observation, ROI and pointing |
| 3306 | + const GCTAObservation& cta = gammalib::cta_obs(G_NROI_DIFFUSE, obs); | ||
| 3307 | + const GCTARoi& roi = gammalib::cta_event_list(G_NROI_DIFFUSE, obs).roi(); | ||
| 3308 | + const GCTAPointing& pnt = cta.pointing(); | ||
| 3368 | 3309 | ||
| 3369 | - // Get pointer on spatial model | ||
| 3370 | - const GModelSpatial* spatial = | ||
| 3371 | - dynamic_cast<const GModelSpatial*>(model.spatial()); | ||
| 3372 | - if (spatial == NULL) { | ||
| 3373 | - throw GCTAException::bad_model_type(G_NROI_DIFFUSE); | ||
| 3374 | - } | 3310 | + // Get pointer on spatial model |
| 3311 | + const GModelSpatial* spatial = | ||
| 3312 | + dynamic_cast<const GModelSpatial*>(model.spatial()); | ||
| 3313 | + if (spatial == NULL) { | ||
| 3314 | + throw GCTAException::bad_model_type(G_NROI_DIFFUSE); | ||
| 3315 | + } | ||
| 3375 | 3316 | ||
| 3376 | - // Get pointing direction zenith angle and azimuth [radians] | ||
| 3377 | - double zenith = pnt.zenith(); | ||
| 3378 | - double azimuth = pnt.azimuth(); | 3317 | + // Get pointing direction zenith angle and azimuth [radians] |
| 3318 | + double zenith = pnt.zenith(); | ||
| 3319 | + double azimuth = pnt.azimuth(); | ||
| 3379 | 3320 | ||
| 3380 | - // Get log10(E/TeV) of true photon energy | ||
| 3381 | - double srcLogEng = srcEng.log10TeV(); | 3321 | + // Get log10(E/TeV) of true photon energy |
| 3322 | + double srcLogEng = srcEng.log10TeV(); | ||
| 3382 | 3323 | ||
| 3383 | - // Get maximum PSF radius (radians). We do this for the onaxis PSF only, | ||
| 3384 | - // as this allows us doing this computation in the outer loop. This | ||
| 3385 | - // should be sufficient here, unless the offaxis PSF becomes much worse | ||
| 3386 | - // than the onaxis PSF. In this case, we may add a safety factor here | ||
| 3387 | - // to make sure we encompass the entire PSF. | ||
| 3388 | - double psf_max_radius = psf_delta_max(0.0, 0.0, zenith, azimuth, srcLogEng); | 3324 | + // Get maximum PSF radius (radians). We do this for the onaxis PSF only, |
| 3325 | + // as this allows us doing this computation in the outer loop. This | ||
| 3326 | + // should be sufficient here, unless the offaxis PSF becomes much worse | ||
| 3327 | + // than the onaxis PSF. In this case, we may add a safety factor here | ||
| 3328 | + // to make sure we encompass the entire PSF. | ||
| 3329 | + double psf_max_radius = psf_delta_max(0.0, 0.0, zenith, azimuth, srcLogEng); | ||
| 3389 | 3330 | ||
| 3390 | - // Extract ROI radius (radians) | ||
| 3391 | - double roi_radius = roi.radius() * gammalib::deg2rad; | 3331 | + // Extract ROI radius (radians) |
| 3332 | + double roi_radius = roi.radius() * gammalib::deg2rad; | ||
| 3392 | 3333 | ||
| 3393 | - // Compute the ROI radius plus maximum PSF radius (radians). Any photon | ||
| 3394 | - // coming from beyond this radius will not make it in the dataspace and | ||
| 3395 | - // thus can be neglected. | ||
| 3396 | - double roi_psf_radius = roi_radius + psf_max_radius; | 3334 | + // Compute the ROI radius plus maximum PSF radius (radians). Any photon |
| 3335 | + // coming from beyond this radius will not make it in the dataspace and | ||
| 3336 | + // thus can be neglected. | ||
| 3337 | + double roi_psf_radius = roi_radius + psf_max_radius; | ||
| 3397 | 3338 | ||
| 3398 | - // Perform offset angle integration only if interval is valid | ||
| 3399 | - if (roi_psf_radius > 0.0) { | 3339 | + // Perform offset angle integration only if interval is valid |
| 3340 | + if (roi_psf_radius > 0.0) { | ||
| 3400 | 3341 | ||
| 3401 | - // Compute rotation matrix to convert from native ROI coordinates, | ||
| 3402 | - // given by (theta,phi), into celestial coordinates. | ||
| 3403 | - GMatrix ry; | ||
| 3404 | - GMatrix rz; | ||
| 3405 | - ry.eulery(roi.centre().dir().dec_deg() - 90.0); | ||
| 3406 | - rz.eulerz(-roi.centre().dir().ra_deg()); | ||
| 3407 | - GMatrix rot = (ry * rz).transpose(); | 3342 | + // Compute rotation matrix to convert from native ROI coordinates, |
| 3343 | + // given by (theta,phi), into celestial coordinates. | ||
| 3344 | + GMatrix ry; | ||
| 3345 | + GMatrix rz; | ||
| 3346 | + ry.eulery(roi.centre().dir().dec_deg() - 90.0); | ||
| 3347 | + rz.eulerz(-roi.centre().dir().ra_deg()); | ||
| 3348 | + GMatrix rot = (ry * rz).transpose(); | ||
| 3408 | 3349 | ||
| 3409 | - // Setup integration kernel | ||
| 3410 | - cta_nroi_diffuse_kern_theta integrand(this, | ||
| 3411 | - &cta, | ||
| 3412 | - spatial, | ||
| 3413 | - &rot, | ||
| 3414 | - srcEng, | ||
| 3415 | - srcTime, | ||
| 3416 | - obsEng, | ||
| 3417 | - obsTime, | ||
| 3418 | - iter_phi); | ||
| 3419 | - | ||
| 3420 | - // Integrate over model's zenith angle | ||
| 3421 | - GIntegral integral(&integrand); | ||
| 3422 | - integral.fixed_iter(iter_rho); | ||
| 3423 | - nroi = integral.romberg(0.0, roi_psf_radius); | ||
| 3424 | - | ||
| 3425 | - // Compile option: Show integration results | ||
| 3426 | - #if defined(G_DEBUG_NROI_DIFFUSE) | ||
| 3427 | - std::cout << "GCTAResponseIrf::nroi_diffuse:"; | ||
| 3428 | - std::cout << " roi_psf_radius=" << roi_psf_radius; | ||
| 3429 | - std::cout << " nroi=" << nroi; | ||
| 3430 | - std::cout << " Etrue=" << srcEng; | ||
| 3431 | - std::cout << " Ereco=" << obsEng; | ||
| 3432 | - std::cout << " id=" << id << std::endl; | ||
| 3433 | - #endif | 3350 | + // Setup integration kernel |
| 3351 | + cta_nroi_diffuse_kern_theta integrand(this, | ||
| 3352 | + &cta, | ||
| 3353 | + spatial, | ||
| 3354 | + &rot, | ||
| 3355 | + srcEng, | ||
| 3356 | + srcTime, | ||
| 3357 | + obsEng, | ||
| 3358 | + obsTime, | ||
| 3359 | + iter_phi); | ||
| 3434 | 3360 | ||
| 3435 | - } // endif: offset angle range was valid | 3361 | + // Integrate over model's zenith angle |
| 3362 | + GIntegral integral(&integrand); | ||
| 3363 | + integral.fixed_iter(iter_rho); | ||
| 3364 | + nroi = integral.romberg(0.0, roi_psf_radius); | ||
| 3436 | 3365 | ||
| 3437 | - // Store result in Npred cache in case that no energy dispersion | ||
| 3438 | - // is requested | ||
| 3439 | - #if defined(G_USE_NPRED_CACHE) | ||
| 3440 | - if (!use_edisp()) { | ||
| 3441 | - m_npred_names.push_back(id); | ||
| 3442 | - m_npred_energies.push_back(srcEng); | ||
| 3443 | - m_npred_times.push_back(srcTime); | ||
| 3444 | - m_npred_values.push_back(nroi); | ||
| 3445 | - } | 3366 | + // Compile option: Show integration results |
| 3367 | + #if defined(G_DEBUG_NROI_DIFFUSE) | ||
| 3368 | + std::cout << "GCTAResponseIrf::nroi_diffuse:"; | ||
| 3369 | + std::cout << " roi_psf_radius=" << roi_psf_radius; | ||
| 3370 | + std::cout << " nroi=" << nroi; | ||
| 3371 | + std::cout << " Etrue=" << srcEng; | ||
| 3372 | + std::cout << " Ereco=" << obsEng; | ||
| 3373 | + std::cout << " id=" << id << std::endl; | ||
| 3446 | #endif | 3374 | #endif |
| 3447 | 3375 | ||
| 3448 | - // Debug: Check for NaN | ||
| 3449 | - #if defined(G_NAN_CHECK) | ||
| 3450 | - if (gammalib::is_notanumber(nroi) || gammalib::is_infinite(nroi)) { | ||
| 3451 | - std::cout << "*** ERROR: GCTAResponseIrf::nroi_diffuse:"; | ||
| 3452 | - std::cout << " NaN/Inf encountered"; | ||
| 3453 | - std::cout << " (nroi=" << nroi; | ||
| 3454 | - std::cout << ", roi_psf_radius=" << roi_psf_radius; | ||
| 3455 | - std::cout << ")" << std::endl; | ||
| 3456 | - } | ||
| 3457 | - #endif | 3376 | + } // endif: offset angle range was valid |
| 3458 | 3377 | ||
| 3459 | - } // endif: Nroi computation required | 3378 | + // Debug: Check for NaN |
| 3379 | + #if defined(G_NAN_CHECK) | ||
| 3380 | + if (gammalib::is_notanumber(nroi) || gammalib::is_infinite(nroi)) { | ||
| 3381 | + std::cout << "*** ERROR: GCTAResponseIrf::nroi_diffuse:"; | ||
| 3382 | + std::cout << " NaN/Inf encountered"; | ||
| 3383 | + std::cout << " (nroi=" << nroi; | ||
| 3384 | + std::cout << ", roi_psf_radius=" << roi_psf_radius; | ||
| 3385 | + std::cout << ")" << std::endl; | ||
| 3386 | + } | ||
| 3387 | + #endif | ||
| 3460 | 3388 | ||
| 3461 | // Return Nroi | 3389 | // Return Nroi |
| 3462 | return nroi; | 3390 | return nroi; |