Commit 00269f87230ad10b1603bd6fed52bb2ce6d39226
1 parent
6857ea15
Implement vectorised response computation for COMPTEL (#3501)
Showing
7 changed files
with
138 additions
and
100 deletions
ChangeLog
| 1 | -2021-01-14 | |
| 1 | +2021-01-15 | |
| 2 | 2 | |
| 3 | 3 | * Version 2.0.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | + Implement vectorised response computation for COMPTEL (#3501) | |
| 6 | 7 | Fix response cache removal for vector cache (#3499) |
| 7 | 8 | Add GModelAssociation and GModelAssociations classes (#3469) |
| 8 | 9 | Add GSkyMap::correlate() method (#3461) | ... | ... |
NEWS
| 1 | 1 | New Features and Important Changes in GammaLib 2.0.0 |
| 2 | 2 | |
| 3 | -14 January 2021 | |
| 3 | +15 January 2021 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | 1. Introduction |
| ... | ... | @@ -232,7 +232,7 @@ spatial model gradients (#3203). |
| 232 | 232 | |
| 233 | 233 | 21. COMPTEL interface |
| 234 | 234 | --------------------- |
| 235 | -None | |
| 235 | +Implement vectorised response computation in GCOMResponse::irf_ptsrc() method (#3501). | |
| 236 | 236 | |
| 237 | 237 | |
| 238 | 238 | 22. INTEGRAL/SPI interface | ... | ... |
README.md
| 1 | 1 | GammaLib information |
| 2 | 2 | ==================== |
| 3 | -* Version: 2.0.0.dev (14 January 2021) | |
| 3 | +* Version: 2.0.0.dev (15 January 2021) | |
| 4 | 4 | |
| 5 | 5 | [](https://cta-jenkins.irap.omp.eu/job/gammalib-integrate-os/) |
| 6 | 6 | ... | ... |
doc/source/admin/release_history/2.0.rst
| 1 | 1 | .. _2.0: |
| 2 | 2 | |
| 3 | -GammaLib 2.0 release (14 January 2021) | |
| 3 | +GammaLib 2.0 release (15 January 2021) | |
| 4 | 4 | ====================================== |
| 5 | 5 | |
| 6 | 6 | Overview |
| ... | ... | @@ -27,6 +27,8 @@ Bug fixes |
| 27 | 27 | Improvements |
| 28 | 28 | ------------ |
| 29 | 29 | |
| 30 | +* [`3501 <https://cta-redmine.irap.omp.eu/issues/3501>`_] - | |
| 31 | + Implement vectorised response computation for COMPTEL | |
| 30 | 32 | * [`3333 <https://cta-redmine.irap.omp.eu/issues/3333>`_] - |
| 31 | 33 | Integrate analytical gradients for energy dispersion computation |
| 32 | 34 | * [`3324 <https://cta-redmine.irap.omp.eu/issues/3324>`_] - | ... | ... |
inst/com/include/GCOMResponse.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * GCOMResponse.hpp - COMPTEL Response class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2012-2020 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2012-2021 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -101,8 +101,6 @@ private: |
| 101 | 101 | void init_members(void); |
| 102 | 102 | void copy_members(const GCOMResponse& rsp); |
| 103 | 103 | void free_members(void); |
| 104 | - GVector irf_drm(const GModelSky& model, | |
| 105 | - const GObservation& obs) const; | |
| 106 | 104 | |
| 107 | 105 | // Overloaded virtual base class methods |
| 108 | 106 | virtual GVector irf_ptsrc(const GModelSky& model, | ... | ... |
inst/com/src/GCOMResponse.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * GCOMResponse.cpp - COMPTEL Response class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2012-2020 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2012-2021 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -47,6 +47,7 @@ |
| 47 | 47 | #include "GModelSpectralConst.hpp" |
| 48 | 48 | #include "GCOMResponse.hpp" |
| 49 | 49 | #include "GCOMObservation.hpp" |
| 50 | +#include "GCOMEventCube.hpp" | |
| 50 | 51 | #include "GCOMEventBin.hpp" |
| 51 | 52 | #include "GCOMInstDir.hpp" |
| 52 | 53 | |
| ... | ... | @@ -57,7 +58,8 @@ |
| 57 | 58 | #define G_NROI "GCOMResponse::nroi(GModelSky&, GEnergy&, GTime&, "\ |
| 58 | 59 | "GObservation&)" |
| 59 | 60 | #define G_EBOUNDS "GCOMResponse::ebounds(GEnergy&)" |
| 60 | -#define G_IRF_DRM "GCOMResponse::irf_drm(GModelSky&, GObservation&)" | |
| 61 | +#define G_IRF_PTSRC "GCOMResponse::irf_ptsrc(GModelSky&, GObservation&, "\ | |
| 62 | + "GMatrix*)" | |
| 61 | 63 | #define G_IRF_RADIAL "GCOMResponse::irf_radial(GModelSky&, GObservation&, "\ |
| 62 | 64 | "GMatrix*)" |
| 63 | 65 | #define G_IRF_ELLIPTICAL "GCOMResponse::irf_elliptical(GModelSky&, "\ |
| ... | ... | @@ -841,122 +843,155 @@ void GCOMResponse::free_members(void) |
| 841 | 843 | |
| 842 | 844 | |
| 843 | 845 | /***********************************************************************//** |
| 844 | - * @brief Return instrument response vector | |
| 846 | + * @brief Return instrument response to point source | |
| 845 | 847 | * |
| 846 | 848 | * @param[in] model Sky model. |
| 847 | 849 | * @param[in] obs Observation. |
| 848 | - * @return Instrument response vector. | |
| 850 | + * @param[out] gradients Gradients matrix. | |
| 851 | + * @return Instrument response to point source for all events in | |
| 852 | + * observation. | |
| 849 | 853 | * |
| 850 | - * @exception GException::invalid_argument | |
| 851 | - * Invalid observation or event type specified. | |
| 852 | - * @exception GException::feature_not_implemented | |
| 853 | - * Computation for specified spatial model not implemented. | |
| 854 | + * Returns the instrument response to a point source for all events in the | |
| 855 | + * observations. | |
| 854 | 856 | * |
| 855 | - * Returns the instrument response to a sky model for all events in a given | |
| 856 | - * observation. The computation of the response is handled by the | |
| 857 | - * GCOMObservation::drm() method that also will update the cube in case that | |
| 858 | - * any of the parameters changes. | |
| 857 | + * @p gradients is an optional matrix where the number of rows corresponds | |
| 858 | + * to the number of events in the observation and the number of columns | |
| 859 | + * corresponds to the number of spatial model parameters. ince for point | |
| 860 | + * sources no gradients are computed, the method does not alter the | |
| 861 | + * content of @p gradients. | |
| 859 | 862 | ***************************************************************************/ |
| 860 | -GVector GCOMResponse::irf_drm(const GModelSky& model, | |
| 861 | - const GObservation& obs) const | |
| 863 | +GVector GCOMResponse::irf_ptsrc(const GModelSky& model, | |
| 864 | + const GObservation& obs, | |
| 865 | + GMatrix* gradients) const | |
| 862 | 866 | { |
| 863 | - // Get number of events | |
| 864 | - int nevents = obs.events()->size(); | |
| 867 | + // Extract COMPTEL observation | |
| 868 | + const GCOMObservation* obs_ptr = dynamic_cast<const GCOMObservation*>(&obs); | |
| 869 | + if (obs_ptr == NULL) { | |
| 870 | + std::string cls = std::string(typeid(&obs).name()); | |
| 871 | + std::string msg = "Observation of type \""+cls+"\" is not a COMPTEL " | |
| 872 | + "observations. Please specify a COMPTEL observation " | |
| 873 | + "as argument."; | |
| 874 | + throw GException::invalid_argument(G_IRF_PTSRC, msg); | |
| 875 | + } | |
| 876 | + | |
| 877 | + // Extract COMPTEL event cube | |
| 878 | + const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(obs_ptr->events()); | |
| 879 | + if (cube == NULL) { | |
| 880 | + std::string msg = "Observation \""+obs.name()+"\" ("+obs.id()+") does " | |
| 881 | + "not contain a COMPTEL event cube. Please specify " | |
| 882 | + "a COMPTEL observation containing and event cube."; | |
| 883 | + throw GException::invalid_argument(G_IRF_PTSRC, msg); | |
| 884 | + } | |
| 885 | + | |
| 886 | + // Get number of Chi/Psi pixels, Phibar layers and event bins | |
| 887 | + int npix = cube->naxis(0) * cube->naxis(1); | |
| 888 | + int nphibar = cube->naxis(2); | |
| 889 | + int nevents = cube->size(); | |
| 865 | 890 | |
| 866 | 891 | // Initialise result |
| 867 | 892 | GVector irfs(nevents); |
| 868 | 893 | |
| 869 | - // Get pointer to COMPTEL observation | |
| 870 | - const GCOMObservation* comobs = dynamic_cast<const GCOMObservation*>(&obs); | |
| 871 | - if (comobs == NULL) { | |
| 872 | - std::string cls = std::string(typeid(&obs).name()); | |
| 873 | - std::string msg = "Observation of type \""+cls+"\" is not a " | |
| 874 | - "COMPTEL observation. Please specify a COMPTEL " | |
| 875 | - "observation as argument."; | |
| 876 | - throw GException::invalid_argument(G_IRF_DRM, msg); | |
| 877 | - } | |
| 894 | + // Get point source direction | |
| 895 | + GSkyDir srcDir = | |
| 896 | + static_cast<const GModelSpatialPointSource*>(model.spatial())->dir(); | |
| 878 | 897 | |
| 879 | - // Get reference to DRM | |
| 880 | - const GCOMDri& drm = comobs->drm(model); | |
| 898 | + // Get IAQ normalisation (cm2): DRX (cm2 s) * DEADC / ONTIME (s) | |
| 899 | + double iaq_norm = obs_ptr->drx()(srcDir) * obs_ptr->deadc() / | |
| 900 | + obs_ptr->ontime(); | |
| 881 | 901 | |
| 882 | - // Extract model values from DRM cache | |
| 883 | - for (int k = 0; k < nevents; ++k) { | |
| 884 | - irfs[k] = drm[k]; | |
| 885 | - } | |
| 902 | + // Get pointer to DRG pixels | |
| 903 | + const double* drg = obs_ptr->drg().pixels(); | |
| 886 | 904 | |
| 887 | - // Return | |
| 888 | - return irfs; | |
| 889 | -} | |
| 905 | + // Loop over Chi and Psi | |
| 906 | + for (int ipix = 0; ipix < npix; ++ipix) { | |
| 890 | 907 | |
| 908 | + // Get pointer to event bin | |
| 909 | + const GCOMEventBin* bin = (*cube)[ipix]; | |
| 891 | 910 | |
| 892 | -/***********************************************************************//** | |
| 893 | - * @brief Return instrument response to point source sky model | |
| 894 | - * | |
| 895 | - * @param[in] model Sky model. | |
| 896 | - * @param[in] obs Observation. | |
| 897 | - * @param[in] gradients Gradients matrix. | |
| 898 | - * @return Instrument response to point source sky model. | |
| 899 | - * | |
| 900 | - * Returns the instrument response to a point source sky model for all | |
| 901 | - * events. | |
| 902 | - ***************************************************************************/ | |
| 903 | -GVector GCOMResponse::irf_ptsrc(const GModelSky& model, | |
| 904 | - const GObservation& obs, | |
| 905 | - GMatrix* gradients) const | |
| 906 | -{ | |
| 907 | - // Get number of events | |
| 908 | - int nevents = obs.events()->size(); | |
| 911 | + // Get reference to instrument direction | |
| 912 | + const GCOMInstDir& obsDir = bin->dir(); | |
| 909 | 913 | |
| 910 | - // Initialise result | |
| 911 | - GVector irfs(nevents); | |
| 914 | + // Get reference to Phigeo sky direction | |
| 915 | + const GSkyDir& phigeoDir = obsDir.dir(); | |
| 912 | 916 | |
| 913 | - // Check if spatial model has free parameters | |
| 914 | - bool has_free_pars = model.spatial()->has_free_pars(); | |
| 917 | + // Compute angle between true photon arrival direction and scatter | |
| 918 | + // direction (Chi,Psi) | |
| 919 | + double phigeo = srcDir.dist_deg(phigeoDir); | |
| 915 | 920 | |
| 916 | - // If model has free parameters then compute IRF value for all events | |
| 917 | - if (has_free_pars) { | |
| 918 | - | |
| 919 | - // Get point source direction | |
| 920 | - GSkyDir srcDir = | |
| 921 | - static_cast<const GModelSpatialPointSource*>(model.spatial())->dir(); | |
| 922 | - | |
| 923 | - // Loop over events | |
| 924 | - for (int k = 0; k < nevents; ++k) { | |
| 921 | + // Compute interpolation factors | |
| 922 | + double phirat = phigeo / m_phigeo_bin_size; // 0.5 at bin centre | |
| 923 | + int iphigeo = int(phirat); // index into which Phigeo falls | |
| 924 | + double eps = phirat - iphigeo - 0.5; // 0.0 at bin centre [-0.5, 0.5[ | |
| 925 | 925 | |
| 926 | - // Get reference to event | |
| 927 | - const GEvent& event = *((*obs.events())[k]); | |
| 926 | + // If Phigeo is in range then compute the IRF value for all | |
| 927 | + // Phibar layers | |
| 928 | + if (iphigeo < m_phigeo_bins) { | |
| 928 | 929 | |
| 929 | - // Get source energy and time (no dispersion) | |
| 930 | - GEnergy srcEng = event.energy(); | |
| 931 | - GTime srcTime = event.time(); | |
| 930 | + // Loop over Phibar | |
| 931 | + for (int iphibar = 0; iphibar < nphibar; ++iphibar) { | |
| 932 | 932 | |
| 933 | - // Setup photon | |
| 934 | - GPhoton photon(srcDir, srcEng, srcTime); | |
| 933 | + // Get IAQ index | |
| 934 | + int i = iphibar * m_phigeo_bins + iphigeo; | |
| 935 | 935 | |
| 936 | - // Get IRF value | |
| 937 | - irfs[k] = this->irf(event, photon, obs); | |
| 936 | + // Initialise IAQ | |
| 937 | + double iaq = 0.0; | |
| 938 | 938 | |
| 939 | - } // endfor: looped over events | |
| 939 | + // Compute IAQ | |
| 940 | + if (eps < 0.0) { // interpolate towards left | |
| 941 | + if (iphigeo > 0) { | |
| 942 | + iaq = (1.0 + eps) * m_iaq[i] - eps * m_iaq[i-1]; | |
| 943 | + } | |
| 944 | + else { | |
| 945 | + iaq = (1.0 - eps) * m_iaq[i] + eps * m_iaq[i+1]; | |
| 946 | + } | |
| 947 | + } | |
| 948 | + else { // interpolate towards right | |
| 949 | + if (iphigeo < m_phigeo_bins-1) { | |
| 950 | + iaq = (1.0 - eps) * m_iaq[i] + eps * m_iaq[i+1]; | |
| 951 | + } | |
| 952 | + else { | |
| 953 | + iaq = (1.0 + eps) * m_iaq[i] - eps * m_iaq[i-1]; | |
| 954 | + } | |
| 955 | + } | |
| 940 | 956 | |
| 941 | - } // endif: model had free parameters | |
| 957 | + // Continue only if IAQ is positive | |
| 958 | + if (iaq > 0.0) { | |
| 942 | 959 | |
| 943 | - // ... otherwise extract model from DRM cache | |
| 944 | - else { | |
| 945 | - irfs = irf_drm(model, obs); | |
| 946 | - } | |
| 960 | + // Get DRI index | |
| 961 | + int idri = ipix + iphibar * npix; | |
| 947 | 962 | |
| 948 | - // Return IRF value | |
| 963 | + // Compute IRF value | |
| 964 | + double irf = iaq * drg[idri] * iaq_norm; | |
| 965 | + | |
| 966 | + // Make sure that IRF is positive | |
| 967 | + if (irf < 0.0) { | |
| 968 | + irf = 0.0; | |
| 969 | + } | |
| 970 | + | |
| 971 | + // Store IRF value | |
| 972 | + irfs[idri] = irf; | |
| 973 | + | |
| 974 | + } // endif: IAQ was positive | |
| 975 | + | |
| 976 | + } // endfor: looped over Phibar | |
| 977 | + | |
| 978 | + } // endif: Phigeo was in valid range | |
| 979 | + | |
| 980 | + } // endfor: looped over Chi and Psi | |
| 981 | + | |
| 982 | + // Return IRF vector | |
| 949 | 983 | return irfs; |
| 950 | 984 | } |
| 951 | 985 | |
| 952 | 986 | |
| 953 | 987 | /***********************************************************************//** |
| 954 | - * @brief Return instrument response to radial source sky model | |
| 988 | + * @brief Return instrument response to radial source | |
| 955 | 989 | * |
| 956 | 990 | * @param[in] model Sky model. |
| 957 | 991 | * @param[in] obs Observation. |
| 958 | - * @param[in] gradients Gradients matrix. | |
| 959 | - * @return Instrument response to radial source sky model. | |
| 992 | + * @param[out] gradients Gradients matrix. | |
| 993 | + * @return Instrument response to radial source for all events in | |
| 994 | + * observation. | |
| 960 | 995 | * |
| 961 | 996 | * @todo Implement method. |
| 962 | 997 | ***************************************************************************/ |
| ... | ... | @@ -982,12 +1017,13 @@ GVector GCOMResponse::irf_radial(const GModelSky& model, |
| 982 | 1017 | |
| 983 | 1018 | |
| 984 | 1019 | /***********************************************************************//** |
| 985 | - * @brief Return instrument response to elliptical source sky model | |
| 1020 | + * @brief Return instrument response to elliptical source | |
| 986 | 1021 | * |
| 987 | 1022 | * @param[in] model Sky model. |
| 988 | 1023 | * @param[in] obs Observation. |
| 989 | - * @param[in] gradients Gradients matrix. | |
| 990 | - * @return Instrument response to elliptical source sky model. | |
| 1024 | + * @param[out] gradients Gradients matrix. | |
| 1025 | + * @return Instrument response to elliptical source for all events in | |
| 1026 | + * observation. | |
| 991 | 1027 | * |
| 992 | 1028 | * @todo Implement method. |
| 993 | 1029 | ***************************************************************************/ |
| ... | ... | @@ -1013,12 +1049,13 @@ GVector GCOMResponse::irf_elliptical(const GModelSky& model, |
| 1013 | 1049 | |
| 1014 | 1050 | |
| 1015 | 1051 | /***********************************************************************//** |
| 1016 | - * @brief Return instrument response to diffuse source sky model | |
| 1052 | + * @brief Return instrument response to diffuse source | |
| 1017 | 1053 | * |
| 1018 | 1054 | * @param[in] model Sky model. |
| 1019 | 1055 | * @param[in] obs Observation. |
| 1020 | - * @param[in] gradients Gradients matrix. | |
| 1021 | - * @return Instrument response to diffuse source sky model. | |
| 1056 | + * @param[out] gradients Gradients matrix. | |
| 1057 | + * @return Instrument response to diffuse source for all events in | |
| 1058 | + * observation. | |
| 1022 | 1059 | * |
| 1023 | 1060 | * @todo Implement method. |
| 1024 | 1061 | ***************************************************************************/ | ... | ... |
inst/cta/src/GCTAResponseCube.cpp
| ... | ... | @@ -1618,9 +1618,9 @@ double GCTAResponseCube::irf_diffuse(const GEvent& event, |
| 1618 | 1618 | * |
| 1619 | 1619 | * Returns the instrument response to a specified radial source. |
| 1620 | 1620 | * |
| 1621 | - * @p gradients is an optional sparse matrix where the number of rows | |
| 1622 | - * corresponds to the number of events in the observation and the number | |
| 1623 | - * of columns corresponds to the number of spatial model parameters. | |
| 1621 | + * @p gradients is an optional matrix where the number of rows corresponds | |
| 1622 | + * to the number of events in the observation and the number of columns | |
| 1623 | + * corresponds to the number of spatial model parameters. | |
| 1624 | 1624 | ***************************************************************************/ |
| 1625 | 1625 | GVector GCTAResponseCube::irf_radial(const GModelSky& model, |
| 1626 | 1626 | const GObservation& obs, | ... | ... |