Commit eb131e63aa1cdc9f2b451e5f2da95f4af7adfc49
Merge branch '1039-allow-energy-thresholds-via-IRF-and-XML' into integration
Showing
9 changed files
with
216 additions
and
42 deletions
ChangeLog
| 1 | -2014-10-31 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 1 | +2014-11-07 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 2 | 2 | |
| 3 | 3 | * Version 0.9.0 released |
| 4 | 4 | ======================== |
| ... | ... | @@ -34,6 +34,7 @@ |
| 34 | 34 | Introduce class codes to avoid dynamic type casting |
| 35 | 35 | Remove error computation from optimization |
| 36 | 36 | Add GOptimize::errors() method for error computation |
| 37 | + Add support for user and save CTA energy thresholds | |
| 37 | 38 | Several bug corrections |
| 38 | 39 | |
| 39 | 40 | ... | ... |
NEWS
| ... | ... | @@ -2,7 +2,7 @@ New Features and Important Changes in GammaLib 00-09-00 |
| 2 | 2 | |
| 3 | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | |
| 5 | -31 October 2014 | |
| 5 | +7 November 2014 | |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | 1. Introduction |
| ... | ... | @@ -307,6 +307,11 @@ Events are now only loaded when needed into GCTAObservation. This reduces memory |
| 307 | 307 | the usage. The method dispose_events() has been added to explicitely allow the |
| 308 | 308 | disposal of the events. |
| 309 | 309 | |
| 310 | +Support for user provided energy thresholds and save energy thresholds has been | |
| 311 | +implemented. Save energy thresholds will be extracted from the LO_THRES and | |
| 312 | +HI_THRES keywords if they are present in the effective area response FITS | |
| 313 | +file. The user may supply energy thresholds in the XML file. | |
| 314 | + | |
| 310 | 315 | |
| 311 | 316 | 21. COMPTEL interface |
| 312 | 317 | --------------------- | ... | ... |
inst/cta/include/GCTAObservation.hpp
| ... | ... | @@ -120,6 +120,8 @@ public: |
| 120 | 120 | void eventfile(const std::string& filename); |
| 121 | 121 | const std::string& eventfile(void) const; |
| 122 | 122 | void dispose_events(void); |
| 123 | + const double& lo_user_thres(void) const; | |
| 124 | + const double& hi_user_thres(void) const; | |
| 123 | 125 | |
| 124 | 126 | protected: |
| 125 | 127 | // Protected methods |
| ... | ... | @@ -131,17 +133,19 @@ protected: |
| 131 | 133 | void set_event_type(void); |
| 132 | 134 | |
| 133 | 135 | // Protected members |
| 134 | - std::string m_instrument; //!< Instrument name | |
| 135 | - std::string m_eventfile; //!< Event filename | |
| 136 | - std::string m_eventtype; //!< Event type (for XML file) | |
| 137 | - GCTAResponse* m_response; //!< Pointer to instrument response functions | |
| 138 | - GCTAPointing m_pointing; //!< Pointing direction | |
| 139 | - int m_obs_id; //!< Observation ID | |
| 140 | - double m_ontime; //!< Ontime (seconds) | |
| 141 | - double m_livetime; //!< Livetime (seconds) | |
| 142 | - double m_deadc; //!< Deadtime correction (livetime/ontime) | |
| 143 | - double m_ra_obj; //!< Right Ascension of object (degrees) | |
| 144 | - double m_dec_obj; //!< Declination of object (degrees) | |
| 136 | + std::string m_instrument; //!< Instrument name | |
| 137 | + std::string m_eventfile; //!< Event filename | |
| 138 | + std::string m_eventtype; //!< Event type (for XML file) | |
| 139 | + GCTAResponse* m_response; //!< Pointer to instrument response functions | |
| 140 | + GCTAPointing m_pointing; //!< Pointing direction | |
| 141 | + int m_obs_id; //!< Observation ID | |
| 142 | + double m_ontime; //!< Ontime (seconds) | |
| 143 | + double m_livetime; //!< Livetime (seconds) | |
| 144 | + double m_deadc; //!< Deadtime correction (livetime/ontime) | |
| 145 | + double m_ra_obj; //!< Right Ascension of object (degrees) | |
| 146 | + double m_dec_obj; //!< Declination of object (degrees) | |
| 147 | + double m_lo_user_thres; //!< User defined lower energy threshold | |
| 148 | + double m_hi_user_thres; //!< User defined upper energy boundary | |
| 145 | 149 | |
| 146 | 150 | // Special protected member for GCTAModelCubeBackground friend |
| 147 | 151 | std::string m_bgdfile; //!< Background filename |
| ... | ... | @@ -387,4 +391,30 @@ const std::string& GCTAObservation::eventfile(void) const |
| 387 | 391 | return m_eventfile; |
| 388 | 392 | } |
| 389 | 393 | |
| 394 | + | |
| 395 | +/***********************************************************************//** | |
| 396 | + * @brief Return user low energy threshold | |
| 397 | + * | |
| 398 | + * @return User low energy threshold. | |
| 399 | + ***************************************************************************/ | |
| 400 | +inline | |
| 401 | +const double& GCTAObservation::lo_user_thres(void) const | |
| 402 | +{ | |
| 403 | + return m_lo_user_thres; | |
| 404 | +} | |
| 405 | + | |
| 406 | +/***********************************************************************//** | |
| 407 | + * @brief Return user high energy threshold | |
| 408 | + * | |
| 409 | + * @return User high energy threshold. | |
| 410 | + ***************************************************************************/ | |
| 411 | +inline | |
| 412 | +const double& GCTAObservation::hi_user_thres(void) const | |
| 413 | +{ | |
| 414 | + return m_hi_user_thres; | |
| 415 | +} | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 390 | 420 | #endif /* GCTAOBSERVATION_HPP */ | ... | ... |
inst/cta/include/GCTAResponse.hpp
inst/cta/include/GCTAResponseIrf.hpp
| ... | ... | @@ -127,6 +127,8 @@ public: |
| 127 | 127 | void edisp(GCTAEdisp* edisp); |
| 128 | 128 | const GCTABackground* background(void) const; |
| 129 | 129 | void background(GCTABackground* background); |
| 130 | + const double& lo_save_thres(void) const; | |
| 131 | + const double& hi_save_thres(void) const; | |
| 130 | 132 | |
| 131 | 133 | // Low-level response methods |
| 132 | 134 | double aeff(const double& theta, |
| ... | ... | @@ -177,6 +179,8 @@ private: |
| 177 | 179 | GCTAEdisp* m_edisp; //!< Energy dispersion |
| 178 | 180 | GCTABackground* m_background; //!< Energy dispersion |
| 179 | 181 | mutable bool m_apply_edisp; //!< Apply energy dispersion |
| 182 | + double m_lo_save_thres; //!< Save low energy threshold | |
| 183 | + double m_hi_save_thres; //!< Save high energy threshold | |
| 180 | 184 | |
| 181 | 185 | // XML response filename |
| 182 | 186 | std::string m_xml_caldb; //!< Calibration database string in XML file |
| ... | ... | @@ -398,4 +402,26 @@ void GCTAResponseIrf::background(GCTABackground* background) |
| 398 | 402 | return; |
| 399 | 403 | } |
| 400 | 404 | |
| 405 | +/***********************************************************************//** | |
| 406 | + * @brief Return low energy threshold from IRF | |
| 407 | + * | |
| 408 | + * @return Low energy threshold from IRF. | |
| 409 | + ***************************************************************************/ | |
| 410 | +inline | |
| 411 | +const double& GCTAResponseIrf::lo_save_thres(void) const | |
| 412 | +{ | |
| 413 | + return m_lo_save_thres; | |
| 414 | +} | |
| 415 | + | |
| 416 | +/***********************************************************************//** | |
| 417 | + * @brief Return high energy threshold from IRF | |
| 418 | + * | |
| 419 | + * @return High energy threshold from IRF. | |
| 420 | + ***************************************************************************/ | |
| 421 | +inline | |
| 422 | +const double& GCTAResponseIrf::hi_save_thres(void) const | |
| 423 | +{ | |
| 424 | + return m_hi_save_thres; | |
| 425 | +} | |
| 426 | + | |
| 401 | 427 | #endif /* GCTARESPONSEIRF_HPP */ | ... | ... |
inst/cta/pyext/GCTAObservation.i
inst/cta/src/GCTAObservation.cpp
| ... | ... | @@ -638,7 +638,10 @@ GEbounds GCTAObservation::ebounds(void) const |
| 638 | 638 | * ... |
| 639 | 639 | * </observation> |
| 640 | 640 | * |
| 641 | - * for a binned observation. | |
| 641 | + * for a binned observation. Optional user energy thresholds can be | |
| 642 | + * specified by adding the emin and emax attributes: | |
| 643 | + * | |
| 644 | + * <observation name="..." id="..." instrument="..." emin="..." emax="..."> | |
| 642 | 645 | * |
| 643 | 646 | * The method does no load the events into memory but stores the file name |
| 644 | 647 | * of the event file. The events are only loaded when required. This reduces |
| ... | ... | @@ -653,6 +656,14 @@ void GCTAObservation::read(const GXmlElement& xml) |
| 653 | 656 | // Extract instrument name |
| 654 | 657 | m_instrument = xml.attribute("instrument"); |
| 655 | 658 | |
| 659 | + // Read in user defined energy boundaries of this observation | |
| 660 | + if (xml.attribute("emin") != "") { | |
| 661 | + m_lo_user_thres = gammalib::todouble(xml.attribute("emin")); | |
| 662 | + } | |
| 663 | + if (xml.attribute("emax") != "") { | |
| 664 | + m_hi_user_thres = gammalib::todouble(xml.attribute("emax")); | |
| 665 | + } | |
| 666 | + | |
| 656 | 667 | // Determine number of parameter nodes in XML element |
| 657 | 668 | int npars = xml.elements("parameter"); |
| 658 | 669 | |
| ... | ... | @@ -793,7 +804,12 @@ void GCTAObservation::read(const GXmlElement& xml) |
| 793 | 804 | * ... |
| 794 | 805 | * </observation> |
| 795 | 806 | * |
| 796 | - * for a binned observation. | |
| 807 | + * for a binned observation. If user energy threshold are defined (i.e. | |
| 808 | + * threshold values are >0) the additional emin and emax attributes will | |
| 809 | + * be written to the file: | |
| 810 | + * | |
| 811 | + * <observation name="..." id="..." instrument="..." emin="..." emax="..."> | |
| 812 | + * | |
| 797 | 813 | ***************************************************************************/ |
| 798 | 814 | void GCTAObservation::write(GXmlElement& xml) const |
| 799 | 815 | { |
| ... | ... | @@ -813,6 +829,14 @@ void GCTAObservation::write(GXmlElement& xml) const |
| 813 | 829 | throw GException::invalid_value(G_WRITE, msg); |
| 814 | 830 | } |
| 815 | 831 | |
| 832 | + // Add user energy threshold attributes (if set) | |
| 833 | + if (m_lo_user_thres > 0.0) { | |
| 834 | + xml.attribute("emin", gammalib::str(m_lo_user_thres)); | |
| 835 | + } | |
| 836 | + if (m_hi_user_thres > 0.0) { | |
| 837 | + xml.attribute("emax", gammalib::str(m_hi_user_thres)); | |
| 838 | + } | |
| 839 | + | |
| 816 | 840 | // If XML element has 0 nodes then add the required parameter nodes |
| 817 | 841 | if (xml.elements() == 0) { |
| 818 | 842 | std::string text = "parameter name=\""+m_eventtype+"\""; |
| ... | ... | @@ -1033,6 +1057,7 @@ void GCTAObservation::load(const std::string& cntcube, |
| 1033 | 1057 | ***************************************************************************/ |
| 1034 | 1058 | void GCTAObservation::save(const std::string& filename, const bool& clobber) const |
| 1035 | 1059 | { |
| 1060 | + | |
| 1036 | 1061 | // Create FITS file |
| 1037 | 1062 | GFits fits; |
| 1038 | 1063 | |
| ... | ... | @@ -1173,6 +1198,28 @@ std::string GCTAObservation::print(const GChatter& chatter) const |
| 1173 | 1198 | result.append("\n"+gammalib::parformat("Deadtime correction")); |
| 1174 | 1199 | result.append(gammalib::str(m_deadc)); |
| 1175 | 1200 | |
| 1201 | + // Append user energy threshold information | |
| 1202 | + result.append("\n"+gammalib::parformat("User energy range")); | |
| 1203 | + if (m_lo_user_thres > 0.0 && m_hi_user_thres) { | |
| 1204 | + result.append(gammalib::str(m_lo_user_thres)); | |
| 1205 | + result.append(" - "); | |
| 1206 | + result.append(gammalib::str(m_hi_user_thres)); | |
| 1207 | + result.append(" TeV"); | |
| 1208 | + } | |
| 1209 | + else if (m_lo_user_thres > 0.0) { | |
| 1210 | + result.append("> "); | |
| 1211 | + result.append(gammalib::str(m_lo_user_thres)); | |
| 1212 | + result.append(" TeV"); | |
| 1213 | + } | |
| 1214 | + else if (m_hi_user_thres > 0.0) { | |
| 1215 | + result.append("< "); | |
| 1216 | + result.append(gammalib::str(m_hi_user_thres)); | |
| 1217 | + result.append(" TeV"); | |
| 1218 | + } | |
| 1219 | + else { | |
| 1220 | + result.append("undefined"); | |
| 1221 | + } | |
| 1222 | + | |
| 1176 | 1223 | // Append detailed information |
| 1177 | 1224 | GChatter reduced_chatter = gammalib::reduce(chatter); |
| 1178 | 1225 | if (reduced_chatter > SILENT) { |
| ... | ... | @@ -1221,12 +1268,14 @@ void GCTAObservation::init_members(void) |
| 1221 | 1268 | m_bgdfile.clear(); |
| 1222 | 1269 | m_response = NULL; |
| 1223 | 1270 | m_pointing.clear(); |
| 1224 | - m_obs_id = 0; | |
| 1225 | - m_ontime = 0.0; | |
| 1226 | - m_livetime = 0.0; | |
| 1227 | - m_deadc = 0.0; | |
| 1228 | - m_ra_obj = 0.0; | |
| 1229 | - m_dec_obj = 0.0; | |
| 1271 | + m_obs_id = 0; | |
| 1272 | + m_ontime = 0.0; | |
| 1273 | + m_livetime = 0.0; | |
| 1274 | + m_deadc = 0.0; | |
| 1275 | + m_ra_obj = 0.0; | |
| 1276 | + m_dec_obj = 0.0; | |
| 1277 | + m_lo_user_thres = 0.0; | |
| 1278 | + m_hi_user_thres = 0.0; | |
| 1230 | 1279 | |
| 1231 | 1280 | // Return |
| 1232 | 1281 | return; |
| ... | ... | @@ -1241,17 +1290,19 @@ void GCTAObservation::init_members(void) |
| 1241 | 1290 | void GCTAObservation::copy_members(const GCTAObservation& obs) |
| 1242 | 1291 | { |
| 1243 | 1292 | // Copy members |
| 1244 | - m_instrument = obs.m_instrument; | |
| 1245 | - m_eventfile = obs.m_eventfile; | |
| 1246 | - m_eventtype = obs.m_eventtype; | |
| 1247 | - m_bgdfile = obs.m_bgdfile; | |
| 1248 | - m_pointing = obs.m_pointing; | |
| 1249 | - m_obs_id = obs.m_obs_id; | |
| 1250 | - m_ontime = obs.m_ontime; | |
| 1251 | - m_livetime = obs.m_livetime; | |
| 1252 | - m_deadc = obs.m_deadc; | |
| 1253 | - m_ra_obj = obs.m_ra_obj; | |
| 1254 | - m_dec_obj = obs.m_dec_obj; | |
| 1293 | + m_instrument = obs.m_instrument; | |
| 1294 | + m_eventfile = obs.m_eventfile; | |
| 1295 | + m_eventtype = obs.m_eventtype; | |
| 1296 | + m_bgdfile = obs.m_bgdfile; | |
| 1297 | + m_pointing = obs.m_pointing; | |
| 1298 | + m_obs_id = obs.m_obs_id; | |
| 1299 | + m_ontime = obs.m_ontime; | |
| 1300 | + m_livetime = obs.m_livetime; | |
| 1301 | + m_deadc = obs.m_deadc; | |
| 1302 | + m_ra_obj = obs.m_ra_obj; | |
| 1303 | + m_dec_obj = obs.m_dec_obj; | |
| 1304 | + m_lo_user_thres = obs.m_lo_user_thres; | |
| 1305 | + m_hi_user_thres = obs.m_hi_user_thres; | |
| 1255 | 1306 | |
| 1256 | 1307 | // Clone members |
| 1257 | 1308 | m_response = (obs.m_response != NULL) ? obs.m_response->clone() : NULL; | ... | ... |
inst/cta/src/GCTAResponseIrf.cpp
| ... | ... | @@ -948,15 +948,47 @@ void GCTAResponseIrf::load_aeff(const std::string& filename) |
| 948 | 948 | // If file contains an "EFFECTIVE AREA" extension then load it |
| 949 | 949 | // as CTA response table |
| 950 | 950 | if (file.contains("EFFECTIVE AREA")) { |
| 951 | + | |
| 952 | + // Get HDU | |
| 953 | + const GFitsHDU* hdu = file.at("EFFECTIVE AREA"); | |
| 954 | + | |
| 955 | + // Read save energy thresholds if available | |
| 956 | + if (hdu->has_card("LO_THRES")) { | |
| 957 | + m_lo_save_thres = hdu->real("LO_THRES"); | |
| 958 | + } | |
| 959 | + if (hdu->has_card("HI_THRES")) { | |
| 960 | + m_hi_save_thres = hdu->real("HI_THRES"); | |
| 961 | + } | |
| 962 | + | |
| 963 | + // Close file | |
| 951 | 964 | file.close(); |
| 965 | + | |
| 966 | + // Allocate Aeff from file | |
| 952 | 967 | m_aeff = new GCTAAeff2D(filename); |
| 968 | + | |
| 953 | 969 | } |
| 954 | 970 | |
| 955 | 971 | // ... else if file contains a "SPECRESP" extension then load it |
| 956 | 972 | // as ARF |
| 957 | 973 | else if (file.contains("SPECRESP")) { |
| 974 | + | |
| 975 | + // Get HDU | |
| 976 | + const GFitsHDU* hdu = file.at("SPECRESP"); | |
| 977 | + | |
| 978 | + // Read save energy thresholds if available | |
| 979 | + if (hdu->has_card("LO_THRES")) { | |
| 980 | + m_lo_save_thres = hdu->real("LO_THRES"); | |
| 981 | + } | |
| 982 | + if (hdu->has_card("LO_THRES")) { | |
| 983 | + m_hi_save_thres = hdu->real("HI_THRES"); | |
| 984 | + } | |
| 985 | + | |
| 986 | + // Close file | |
| 958 | 987 | file.close(); |
| 988 | + | |
| 989 | + // Allocate Aeff from file | |
| 959 | 990 | m_aeff = new GCTAAeffArf(filename); |
| 991 | + | |
| 960 | 992 | } |
| 961 | 993 | |
| 962 | 994 | } |
| ... | ... | @@ -1221,6 +1253,28 @@ std::string GCTAResponseIrf::print(const GChatter& chatter) const |
| 1221 | 1253 | } |
| 1222 | 1254 | } |
| 1223 | 1255 | |
| 1256 | + // Append save energy threshold information | |
| 1257 | + result.append("\n"+gammalib::parformat("Save energy range")); | |
| 1258 | + if (m_lo_save_thres > 0.0 && m_hi_save_thres) { | |
| 1259 | + result.append(gammalib::str(m_lo_save_thres)); | |
| 1260 | + result.append(" - "); | |
| 1261 | + result.append(gammalib::str(m_hi_save_thres)); | |
| 1262 | + result.append(" TeV"); | |
| 1263 | + } | |
| 1264 | + else if (m_lo_save_thres > 0.0) { | |
| 1265 | + result.append("> "); | |
| 1266 | + result.append(gammalib::str(m_lo_save_thres)); | |
| 1267 | + result.append(" TeV"); | |
| 1268 | + } | |
| 1269 | + else if (m_hi_save_thres > 0.0) { | |
| 1270 | + result.append("< "); | |
| 1271 | + result.append(gammalib::str(m_hi_save_thres)); | |
| 1272 | + result.append(" TeV"); | |
| 1273 | + } | |
| 1274 | + else { | |
| 1275 | + result.append("undefined"); | |
| 1276 | + } | |
| 1277 | + | |
| 1224 | 1278 | // Append calibration database |
| 1225 | 1279 | result.append("\n"+m_caldb.print(chatter)); |
| 1226 | 1280 | |
| ... | ... | @@ -2905,11 +2959,13 @@ void GCTAResponseIrf::init_members(void) |
| 2905 | 2959 | // Initialise members |
| 2906 | 2960 | m_caldb.clear(); |
| 2907 | 2961 | m_rspname.clear(); |
| 2908 | - m_aeff = NULL; | |
| 2909 | - m_psf = NULL; | |
| 2910 | - m_edisp = NULL; | |
| 2911 | - m_background = NULL; | |
| 2912 | - m_apply_edisp = false; //!< Switched off by default | |
| 2962 | + m_aeff = NULL; | |
| 2963 | + m_psf = NULL; | |
| 2964 | + m_edisp = NULL; | |
| 2965 | + m_background = NULL; | |
| 2966 | + m_apply_edisp = false; //!< Switched off by default | |
| 2967 | + m_lo_save_thres = 0.0; | |
| 2968 | + m_hi_save_thres = 0.0; | |
| 2913 | 2969 | |
| 2914 | 2970 | // XML response filenames |
| 2915 | 2971 | m_xml_caldb.clear(); |
| ... | ... | @@ -2938,9 +2994,11 @@ void GCTAResponseIrf::init_members(void) |
| 2938 | 2994 | void GCTAResponseIrf::copy_members(const GCTAResponseIrf& rsp) |
| 2939 | 2995 | { |
| 2940 | 2996 | // Copy members |
| 2941 | - m_caldb = rsp.m_caldb; | |
| 2942 | - m_rspname = rsp.m_rspname; | |
| 2943 | - m_apply_edisp = rsp.m_apply_edisp; | |
| 2997 | + m_caldb = rsp.m_caldb; | |
| 2998 | + m_rspname = rsp.m_rspname; | |
| 2999 | + m_apply_edisp = rsp.m_apply_edisp; | |
| 3000 | + m_lo_save_thres = rsp.m_lo_save_thres; | |
| 3001 | + m_hi_save_thres = rsp.m_hi_save_thres; | |
| 2944 | 3002 | |
| 2945 | 3003 | // Copy response filenames |
| 2946 | 3004 | m_xml_caldb = rsp.m_xml_caldb; | ... | ... |
src/obs/GObservations.cpp
| ... | ... | @@ -646,7 +646,7 @@ void GObservations::write(GXml& xml) const |
| 646 | 646 | |
| 647 | 647 | // Write all observations into library |
| 648 | 648 | for (int i = 0; i < size(); ++i) { |
| 649 | - | |
| 649 | + | |
| 650 | 650 | // Initialise pointer on observation |
| 651 | 651 | GXmlElement* obs = NULL; |
| 652 | 652 | |
| ... | ... | @@ -670,7 +670,7 @@ void GObservations::write(GXml& xml) const |
| 670 | 670 | obs->attribute("id", m_obs[i]->id()); |
| 671 | 671 | obs->attribute("instrument", m_obs[i]->instrument()); |
| 672 | 672 | } |
| 673 | - | |
| 673 | + | |
| 674 | 674 | // Write now observation |
| 675 | 675 | m_obs[i]->write(*obs); |
| 676 | 676 | ... | ... |