Commit ad1eef9b740f43214c89821ede9761995eb9b7f8
1 parent
e00d5dd4
Add ctool::setup_observations() method to setup an observation container by comp…
…lementing missing information from user parameters.
Showing
3 changed files
with
207 additions
and
88 deletions
pyext/ctool.i
| ... | ... | @@ -87,6 +87,7 @@ public: |
| 87 | 87 | %rename(_read_ahead) read_ahead() const; |
| 88 | 88 | %rename(_time_reference) time_reference() const; |
| 89 | 89 | %rename(_get_observations) get_observations(const bool& get_response = true); |
| 90 | + %rename(_setup_observations) setup_observations(GObservations& obs); | |
| 90 | 91 | %rename(_create_ebounds) create_ebounds(); |
| 91 | 92 | %rename(_create_map) create_map(const GObservations& obs); |
| 92 | 93 | %rename(_create_cube) create_cube(const GObservations& obs); |
| ... | ... | @@ -105,6 +106,7 @@ public: |
| 105 | 106 | const bool& read_ahead(void) const; |
| 106 | 107 | const GTimeReference& time_reference(void) const; |
| 107 | 108 | GObservations get_observations(const bool& get_response = true); |
| 109 | + void setup_observations(GObservations& obs); | |
| 108 | 110 | |
| 109 | 111 | // Protected methods that create objects from user parameters |
| 110 | 112 | GEbounds create_ebounds(void); |
| ... | ... | @@ -170,14 +172,15 @@ public: |
| 170 | 172 | |
| 171 | 173 | # Initialise observation container from constructor arguments. In case that |
| 172 | 174 | # an observation container is provided as argument, this container will be |
| 173 | -# used to initialise the class. | |
| 175 | +# used to initialise the class. The function returns a tuple containing the | |
| 176 | +# observation container and the eventually reduced argument list. | |
| 174 | 177 | def _set_input_obs(self, argv): |
| 175 | 178 | if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations): |
| 176 | 179 | obs = argv[0] |
| 177 | 180 | argv = argv[1:] |
| 178 | 181 | else: |
| 179 | 182 | obs = gammalib.GObservations() |
| 180 | - return obs | |
| 183 | + return (obs, argv) | |
| 181 | 184 | cscript._set_input_obs = _set_input_obs |
| 182 | 185 | |
| 183 | 186 | # Initialise application by calling the appropriate class constructor. | ... | ... |
src/support/ctool.cpp
| ... | ... | @@ -49,6 +49,7 @@ |
| 49 | 49 | |
| 50 | 50 | |
| 51 | 51 | /* __ Method name definitions ____________________________________________ */ |
| 52 | +#define G_SETUP_OBSERVATION "ctool::setup_observations(GObservations&)" | |
| 52 | 53 | #define G_GET_MEAN_POINTING "ctool::get_mean_pointing(GObservations&)" |
| 53 | 54 | #define G_CREATE_EBOUNDS "ctool::create_ebounds()" |
| 54 | 55 | #define G_PROVIDE_HELP "ctool::provide_help()" |
| ... | ... | @@ -378,7 +379,98 @@ GObservations ctool::get_observations(const bool& get_response) |
| 378 | 379 | |
| 379 | 380 | // Return observation container |
| 380 | 381 | return obs; |
| 382 | +} | |
| 383 | + | |
| 384 | + | |
| 385 | +/***********************************************************************//** | |
| 386 | + * @brief Setup observation container | |
| 387 | + * | |
| 388 | + * @param[in] obs Observation container | |
| 389 | + * | |
| 390 | + * @exception GException::invalid_value | |
| 391 | + * Invalid "inobs" parameter encountered. | |
| 392 | + * | |
| 393 | + * Setup an observation container by appending all required information that | |
| 394 | + * is missing using user parameters. | |
| 395 | + * | |
| 396 | + * If the observation container @p obs is empty, the method will extract the | |
| 397 | + * filename from the "inobs" parameter, and if the filename is neither empty | |
| 398 | + * nor "NONE", will load the observation container from the specified file. | |
| 399 | + * If the file is a FITS file, and dependent on the information that is found | |
| 400 | + * in the FITS file, the method will append a single CTA observation to the | |
| 401 | + * observation container, containing either an event list or a counts cube. | |
| 402 | + * Otherwise, the method assumes that the file is an observation definition | |
| 403 | + * XML file and will load that file into the observation container. | |
| 404 | + * | |
| 405 | + * If the filename is empty or "NONE", the method will throw an exception. | |
| 406 | + * | |
| 407 | + * The method will then setup the response for all CTA observations in the | |
| 408 | + * container (see the set_response() method for more information). | |
| 409 | + * | |
| 410 | + * The method will furthermore setup the observation boundaries for all CTA | |
| 411 | + * observations in the container that contain event lists (see the | |
| 412 | + * set_obs_bounds() method for more information). | |
| 413 | + ***************************************************************************/ | |
| 414 | +void ctool::setup_observations(GObservations& obs) | |
| 415 | +{ | |
| 416 | + // Load observations if there are none in the container | |
| 417 | + if (obs.size() == 0) { | |
| 418 | + | |
| 419 | + // Get the filename from the "inobs" parameter | |
| 420 | + GFilename filename((*this)["inobs"].filename()); | |
| 421 | + | |
| 422 | + // Load observation container from file if the filename is neither | |
| 423 | + // "NONE" nor empty ... | |
| 424 | + if ((gammalib::toupper(filename.url()) != "NONE") && | |
| 425 | + !filename.is_empty()) { | |
| 426 | + | |
| 427 | + // If file does not exist then throw an exceptions | |
| 428 | + if (!filename.exists()) { | |
| 429 | + std::string msg = "The \"inobs\" parameter \""+filename+ | |
| 430 | + "\" specifies a file that does not " | |
| 431 | + "exist. Please specify a valid event " | |
| 432 | + "list, counts cube or observation " | |
| 433 | + "definition XML file."; | |
| 434 | + throw GException::invalid_value(G_SETUP_OBSERVATION, msg); | |
| 435 | + } | |
| 436 | + | |
| 437 | + // If the file is a FITS file then load it into a CTA | |
| 438 | + // observation and append that observation to the container ... | |
| 439 | + else if (filename.is_fits()) { | |
| 440 | + GCTAObservation cta(filename); | |
| 441 | + obs.append(cta); | |
| 442 | + } | |
| 443 | + | |
| 444 | + // ... otherwise it is assumed that the file is an observation | |
| 445 | + // definition XML file and the file is loaded into the | |
| 446 | + // observation container | |
| 447 | + else { | |
| 448 | + obs.load(filename); | |
| 449 | + } | |
| 450 | + | |
| 451 | + } | |
| 452 | + | |
| 453 | + // ... otherwise, if the filename is "NONE" or empty then throw | |
| 454 | + // an exception. | |
| 455 | + else { | |
| 456 | + std::string msg = "The \"inobs\" parameter \""+filename+ | |
| 457 | + "\" is not a valid filename. Please specify " | |
| 458 | + "a valid event list, counts cube or " | |
| 459 | + "observation definition XML file."; | |
| 460 | + throw GException::invalid_value(G_SETUP_OBSERVATION, msg); | |
| 461 | + } | |
| 462 | + | |
| 463 | + } // endif: there were no observations in the container | |
| 464 | + | |
| 465 | + // Setup the response for all CTA observations in the observation | |
| 466 | + // container | |
| 467 | + set_response(obs); | |
| 381 | 468 | |
| 469 | + // Setup boundaries for all CTA observations containing event lists | |
| 470 | + set_obs_bounds(obs); | |
| 471 | + | |
| 472 | + // Return | |
| 473 | + return; | |
| 382 | 474 | } |
| 383 | 475 | |
| 384 | 476 | |
| ... | ... | @@ -595,15 +687,16 @@ GCTAEventCube ctool::create_cube(const GObservations& obs) |
| 595 | 687 | * method furthermore sets the ontime, livetime and deadtime correction |
| 596 | 688 | * factor. |
| 597 | 689 | * |
| 598 | - * The following parameters are read: | |
| 599 | - * ra - Right Ascension of pointing and RoI centre (deg) | |
| 600 | - * dec - Declination of pointing and RoI centre (deg) | |
| 601 | - * rad - Radius of RoI (deg) | |
| 602 | - * deadc - Deadtime correction factor | |
| 603 | - * tmin - Start time | |
| 604 | - * tmax - Stop time | |
| 605 | - * emin - Minimum energy (TeV) | |
| 606 | - * emax - Maximum energy (TeV) | |
| 690 | + * The following parameters are read | |
| 691 | + * | |
| 692 | + * ra: Right Ascension of pointing and RoI centre (deg) | |
| 693 | + * dec: Declination of pointing and RoI centre (deg) | |
| 694 | + * rad: Radius of RoI (deg) | |
| 695 | + * deadc: Deadtime correction factor | |
| 696 | + * tmin: Start time | |
| 697 | + * tmax: Stop time | |
| 698 | + * emin: Minimum energy (TeV) | |
| 699 | + * emax: Maximum energy (TeV) | |
| 607 | 700 | ***************************************************************************/ |
| 608 | 701 | GCTAObservation ctool::create_cta_obs(void) |
| 609 | 702 | { |
| ... | ... | @@ -804,12 +897,9 @@ void ctool::require_inobs_nocube(const std::string& method) |
| 804 | 897 | * |
| 805 | 898 | * @param[in,out] obs Observation container |
| 806 | 899 | * |
| 807 | - * Set the response for a CTA observations in the container that so far have | |
| 808 | - * no response using the "caldb" and "irf" task parameters. | |
| 809 | - * | |
| 810 | - * The following parameters are read: | |
| 811 | - * caldb - Calibration database | |
| 812 | - * irf - Instrument response function | |
| 900 | + * Set the response for all CTA observations in the container that so far | |
| 901 | + * have no response information available. See the set_obs_response() | |
| 902 | + * method for more information about the user parameters that are read. | |
| 813 | 903 | ***************************************************************************/ |
| 814 | 904 | void ctool::set_response(GObservations& obs) |
| 815 | 905 | { |
| ... | ... | @@ -841,69 +931,83 @@ void ctool::set_response(GObservations& obs) |
| 841 | 931 | * |
| 842 | 932 | * @param[in,out] obs CTA observation |
| 843 | 933 | * |
| 844 | - * Set the response for a CTA observation. If the CTA observation contains | |
| 934 | + * Set the response for one CTA observation. If the CTA observation contains | |
| 845 | 935 | * a counts cube the method first attempts to set the response information |
| 846 | - * using the @a expcube and @a psfcube user parameters. If this is not | |
| 847 | - * successful (for example because the parameters do not exist or their | |
| 848 | - * value is NONE or blank), the method will set the response information | |
| 849 | - * from the @a caldb and @a irf user parameters. | |
| 936 | + * using the following user parameters | |
| 937 | + * | |
| 938 | + * expcube: Exposure cube file | |
| 939 | + * psfcube: Point spread function cube file | |
| 940 | + * edispcube: Energy dispersion cube file (optional) | |
| 941 | + * bkgcube: Background cube file | |
| 942 | + * | |
| 943 | + * If none of the @p expcube, @p psfcube and @p bkgcube parameters is | |
| 944 | + * "NONE" or empty, the method will allocate a stacked response for the | |
| 945 | + * observation. In case that an energy dispersion cube is provided using | |
| 946 | + * the @p edispcube parameter, this energy dispersion cube is also loaded | |
| 947 | + * and attached to the stacked response function. | |
| 948 | + * | |
| 949 | + * In case that any of the @p expcube, @p psfcube and @p bkgcube parameters | |
| 950 | + * is "NONE" or empty, the method will assume that a IRF response should | |
| 951 | + * be used, and will attempty to set the response information using the | |
| 952 | + * following user parameters | |
| 953 | + * | |
| 954 | + * caldb: Calibration database | |
| 955 | + * irf: Instrument response function | |
| 850 | 956 | * |
| 851 | - * The following parameters are read: | |
| 852 | - * expcube - Exposure cube file (optional) | |
| 853 | - * psfcube - PSF cube file (optional) | |
| 854 | - * caldb - Calibration database (optional) | |
| 855 | - * irf - Instrument response function (optional) | |
| 856 | 957 | ***************************************************************************/ |
| 857 | 958 | void ctool::set_obs_response(GCTAObservation* obs) |
| 858 | 959 | { |
| 859 | 960 | // Initialise response flag |
| 860 | 961 | bool has_response = false; |
| 861 | 962 | |
| 862 | - // If the observation contains a counts cube, then first check whether | |
| 863 | - // the expcube and psfcube parameters exist and are not NONE | |
| 963 | + // If the observation contains a counts cube, then check whether | |
| 964 | + // response information for a stacked analysis is provided, and if so, | |
| 965 | + // set that response information for the CTA observation | |
| 864 | 966 | if (dynamic_cast<const GCTAEventCube*>(obs->events()) != NULL) { |
| 865 | 967 | if (has_par("expcube") && has_par("psfcube") && |
| 866 | 968 | has_par("edispcube") && has_par("bkgcube")) { |
| 867 | 969 | |
| 868 | 970 | // Get filenames |
| 869 | - std::string expcube = (*this)["expcube"].filename(); | |
| 870 | - std::string psfcube = (*this)["psfcube"].filename(); | |
| 871 | - std::string edispcube = (*this)["edispcube"].filename(); | |
| 872 | - std::string bkgcube = (*this)["bkgcube"].filename(); | |
| 873 | - | |
| 874 | - // Extract response information if available | |
| 875 | - if ((expcube != "NONE") && (psfcube != "NONE") && | |
| 876 | - (bkgcube != "NONE") && | |
| 877 | - (gammalib::strip_whitespace(expcube) != "") && | |
| 878 | - (gammalib::strip_whitespace(psfcube) != "") && | |
| 879 | - (gammalib::strip_whitespace(bkgcube) != "")) { | |
| 971 | + GFilename expcube((*this)["expcube"].filename()); | |
| 972 | + GFilename psfcube((*this)["psfcube"].filename()); | |
| 973 | + GFilename edispcube((*this)["edispcube"].filename()); | |
| 974 | + GFilename bkgcube((*this)["bkgcube"].filename()); | |
| 975 | + | |
| 976 | + // Extract stacked response information if available | |
| 977 | + if ((gammalib::toupper(expcube.url()) != "NONE") && | |
| 978 | + (gammalib::toupper(psfcube.url()) != "NONE") && | |
| 979 | + (gammalib::toupper(bkgcube.url()) != "NONE") && | |
| 980 | + !expcube.is_empty() && | |
| 981 | + !psfcube.is_empty() && | |
| 982 | + !bkgcube.is_empty()) { | |
| 880 | 983 | |
| 881 | 984 | // Get exposure, PSF and background cubes |
| 882 | 985 | GCTACubeExposure exposure(expcube); |
| 883 | 986 | GCTACubePsf psf(psfcube); |
| 884 | 987 | GCTACubeBackground background(bkgcube); |
| 885 | 988 | |
| 886 | - // Optionally load energy dispersion cube | |
| 887 | - if ((edispcube != "NONE") && | |
| 888 | - (gammalib::strip_whitespace(edispcube) != "")) { | |
| 989 | + // If an energy dispersion cube is available, get also | |
| 990 | + // this cube, and set all information as stacked response | |
| 991 | + // for this CTA observation | |
| 992 | + if ((gammalib::toupper(edispcube.url()) != "NONE") && | |
| 993 | + !edispcube.is_empty()) { | |
| 889 | 994 | GCTACubeEdisp edisp(edispcube); |
| 890 | 995 | obs->response(exposure, psf, edisp, background); |
| 891 | 996 | } |
| 892 | 997 | else { |
| 893 | - // Set reponse | |
| 894 | 998 | obs->response(exposure, psf, background); |
| 895 | 999 | } |
| 896 | 1000 | |
| 897 | - // Signal response availability | |
| 1001 | + // Signal that response is available | |
| 898 | 1002 | has_response = true; |
| 899 | 1003 | |
| 900 | 1004 | } // endif: filenames were available |
| 901 | 1005 | |
| 902 | - } // endif: expcube and psfcube parameters exist | |
| 1006 | + } // endif: expcube, psfcube and bkdcube parameters valid | |
| 903 | 1007 | } // endif: observation contains a counts cube |
| 904 | 1008 | |
| 905 | - // If we have not yet response information then get it now | |
| 906 | - // from the caldb and irf parameters | |
| 1009 | + // If we have not yet response information then get it now from the | |
| 1010 | + // caldb and irf user parameters | |
| 907 | 1011 | if (!has_response) { |
| 908 | 1012 | |
| 909 | 1013 | // Load response information |
| ... | ... | @@ -938,59 +1042,70 @@ void ctool::set_obs_response(GCTAObservation* obs) |
| 938 | 1042 | |
| 939 | 1043 | |
| 940 | 1044 | /***********************************************************************//** |
| 941 | - * @brief Set observation boundaries | |
| 1045 | + * @brief Set observation boundaries for all CTA observations | |
| 942 | 1046 | * |
| 943 | 1047 | * @param[in,out] obs Observation container |
| 1048 | + * | |
| 1049 | + * Sets the observation boundaries for all CTA observations in the container | |
| 1050 | + * that contain event lists. If the energy boundaries of an event list are | |
| 1051 | + * empty, the method gets the | |
| 1052 | + * | |
| 1053 | + * emin: Minimum energy (TeV) | |
| 1054 | + * emax: Maximum energy (TeV) | |
| 1055 | + * | |
| 1056 | + * user parameters and sets a single energy boundary element @p [emin,emax]. | |
| 1057 | + * | |
| 1058 | + * If the RoI radius of the event list is invalid, the method gets the | |
| 1059 | + * | |
| 1060 | + * rad: Region of Interest radius (deg) | |
| 1061 | + * | |
| 1062 | + * user parameter to set the radius of the RoI, and uses the CTA pointing | |
| 1063 | + * direction to set the centre of the RoI. | |
| 944 | 1064 | ***************************************************************************/ |
| 945 | 1065 | void ctool::set_obs_bounds(GObservations& obs) |
| 946 | 1066 | { |
| 947 | - // Setup response for all observations | |
| 1067 | + // Loop over all observations in the container | |
| 948 | 1068 | for (int i = 0; i < obs.size(); ++i) { |
| 949 | 1069 | |
| 950 | - // Is this observation a CTA observation? | |
| 1070 | + // Get pointer to CTA observation | |
| 951 | 1071 | GCTAObservation* cta = dynamic_cast<GCTAObservation*>(obs[i]); |
| 952 | 1072 | |
| 953 | - // Continue only if observation is CTA and has events | |
| 954 | - if ((cta != NULL) && (cta->has_events())) { | |
| 955 | - | |
| 956 | - // Get pointer on event list | |
| 957 | - GCTAEventList* list = const_cast<GCTAEventList*>(dynamic_cast<const GCTAEventList*>(cta->events())); | |
| 958 | - | |
| 959 | - // Continue only if it's valid | |
| 960 | - if (list != NULL) { | |
| 961 | - | |
| 962 | - // If there are no energy boundaries then read the user | |
| 963 | - // parameters and add them | |
| 964 | - if (list->ebounds().is_empty()) { | |
| 965 | - | |
| 966 | - // If there are "emin" and "emax" parameters then use | |
| 967 | - // them | |
| 968 | - if (has_par("emin") && has_par("emax")) { | |
| 969 | - double emin = (*this)["emin"].real(); | |
| 970 | - double emax = (*this)["emax"].real(); | |
| 971 | - GEbounds ebounds(GEnergy(emin, "TeV"), | |
| 972 | - GEnergy(emax, "TeV")); | |
| 973 | - list->ebounds(ebounds); | |
| 974 | - } | |
| 975 | - | |
| 976 | - } | |
| 1073 | + // Fall through if observation is not a CTA observation or if it | |
| 1074 | + // does not contain events | |
| 1075 | + if ((cta == NULL) || (!cta->has_events())) { | |
| 1076 | + continue; | |
| 1077 | + } | |
| 977 | 1078 | |
| 978 | - // If there is no ROI then read the user parameters and add | |
| 979 | - // them | |
| 980 | - if (list->roi().radius() == 0) { | |
| 981 | - | |
| 982 | - // If there is a "rad" parameter then use it | |
| 983 | - if (has_par("rad")) { | |
| 984 | - double rad = (*this)["rad"].real(); | |
| 985 | - GCTARoi roi(GCTAInstDir(cta->pointing().dir()), rad); | |
| 986 | - list->roi(roi); | |
| 987 | - } | |
| 1079 | + // Get pointer on CTA event list | |
| 1080 | + GCTAEventList* list = const_cast<GCTAEventList*> | |
| 1081 | + (dynamic_cast<const GCTAEventList*>(cta->events())); | |
| 988 | 1082 | |
| 989 | - } | |
| 1083 | + // Fall through if CTA observation does not contain an event list | |
| 1084 | + if (list == NULL) { | |
| 1085 | + continue; | |
| 1086 | + } | |
| 990 | 1087 | |
| 991 | - } // endif: list was valid | |
| 1088 | + // If there are no energy boundaries then read the "emin" and "emax" | |
| 1089 | + // user parameters and add them | |
| 1090 | + if (list->ebounds().is_empty()) { | |
| 1091 | + if (has_par("emin") && has_par("emax")) { | |
| 1092 | + double emin((*this)["emin"].real()); | |
| 1093 | + double emax((*this)["emax"].real()); | |
| 1094 | + GEbounds ebounds(GEnergy(emin, "TeV"), | |
| 1095 | + GEnergy(emax, "TeV")); | |
| 1096 | + list->ebounds(ebounds); | |
| 1097 | + } | |
| 1098 | + } | |
| 992 | 1099 | |
| 993 | - } // endif: observation was CTA | |
| 1100 | + // If there is no RoI then read the "rad" user parameters and use | |
| 1101 | + // the pointing direction to set the RoI | |
| 1102 | + if (list->roi().radius() == 0) { | |
| 1103 | + if (has_par("rad")) { | |
| 1104 | + double rad = (*this)["rad"].real(); | |
| 1105 | + GCTARoi roi(GCTAInstDir(cta->pointing().dir()), rad); | |
| 1106 | + list->roi(roi); | |
| 1107 | + } | |
| 1108 | + } | |
| 994 | 1109 | |
| 995 | 1110 | } // endfor: looped over observations |
| 996 | 1111 | ... | ... |
src/support/ctool.hpp
| ... | ... | @@ -72,6 +72,7 @@ protected: |
| 72 | 72 | const bool& read_ahead(void) const; |
| 73 | 73 | const GTimeReference& time_reference(void) const; |
| 74 | 74 | GObservations get_observations(const bool& get_response = true); |
| 75 | + void setup_observations(GObservations& obs); | |
| 75 | 76 | |
| 76 | 77 | // Protected methods that create objects from user parameters |
| 77 | 78 | GEbounds create_ebounds(void); | ... | ... |