Commit c5d45282c745d5ba5901a0a04aae3c68b2fb43b4
Merge branch '2189-ctmodel_trim_models' into integration
# Conflicts: # ChangeLog # NEWS # doc/source/admin/release_history/1.5.rst
Showing
5 changed files
with
134 additions
and
52 deletions
ChangeLog
| 1 | -2017-10-10 | 1 | +2017-10-11 |
| 2 | 2 | ||
| 3 | * Version 1.5.0 released | 3 | * Version 1.5.0 released |
| 4 | ======================== | 4 | ======================== |
| 5 | 5 | ||
| 6 | - Use t-type parameters for all "tmin" and "tmax" parameters (#1864) | ||
| 7 | Add keywords to sky maps produced by ctskymap (#2194) | 6 | Add keywords to sky maps produced by ctskymap (#2194) |
| 7 | + Enhance efficiency of computations in ctmodel (#2189) | ||
| 8 | + Use t-type parameters for all "tmin" and "tmax" parameters (#1864) | ||
| 8 | 9 | ||
| 9 | 10 | ||
| 10 | 2017-07-28 | 11 | 2017-07-28 |
NEWS
| 1 | New Features and Important Changes in ctools 1.5.0 | 1 | New Features and Important Changes in ctools 1.5.0 |
| 2 | 2 | ||
| 3 | -10 October 2017 | 3 | +11 October 2017 |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | Introduction | 6 | Introduction |
| @@ -63,6 +63,11 @@ ctmodel - CTA counts cube modelling | @@ -63,6 +63,11 @@ ctmodel - CTA counts cube modelling | ||
| 63 | Use t-type parameters for "tmin" and "tmax" to all specifying times in various | 63 | Use t-type parameters for "tmin" and "tmax" to all specifying times in various |
| 64 | formats (#1864). | 64 | formats (#1864). |
| 65 | 65 | ||
| 66 | +The tool now also checks which models actually overlap with the RoI of a given | ||
| 67 | +observation and then only use these models to compute the model cube. The | ||
| 68 | +parallelization of the tool has also been optimised so that diffuse models are | ||
| 69 | +not loaded over and over again (#2189). | ||
| 70 | + | ||
| 66 | 71 | ||
| 67 | ctexpcube - CTA exposure cube generation | 72 | ctexpcube - CTA exposure cube generation |
| 68 | ---------------------------------------- | 73 | ---------------------------------------- |
doc/source/admin/release_history/1.5.rst
| @@ -24,6 +24,8 @@ Improvements | @@ -24,6 +24,8 @@ Improvements | ||
| 24 | 24 | ||
| 25 | * [`2194 <https://cta-redmine.irap.omp.eu/issues/2194>`_] - | 25 | * [`2194 <https://cta-redmine.irap.omp.eu/issues/2194>`_] - |
| 26 | Add keywords to sky maps produced by :ref:`ctskymap` | 26 | Add keywords to sky maps produced by :ref:`ctskymap` |
| 27 | +* [`2189 <https://cta-redmine.irap.omp.eu/issues/2189>`_] - | ||
| 28 | + Enhance efficiency of computations in :ref:`ctmodel` | ||
| 27 | 29 | ||
| 28 | 30 | ||
| 29 | New features | 31 | New features |
src/ctmodel/ctmodel.cpp
| @@ -235,48 +235,55 @@ void ctmodel::run(void) | @@ -235,48 +235,55 @@ void ctmodel::run(void) | ||
| 235 | log_header1(TERSE, "Generate model cube"); | 235 | log_header1(TERSE, "Generate model cube"); |
| 236 | 236 | ||
| 237 | // Loop over all observations in the container | 237 | // Loop over all observations in the container |
| 238 | - #pragma omp parallel for | ||
| 239 | - for (int i = 0; i < m_obs.size(); ++i) { | 238 | + #pragma omp parallel |
| 239 | + { | ||
| 240 | + // Create a models object for this core | ||
| 241 | + GModels models(m_obs.models()); | ||
| 240 | 242 | ||
| 241 | - // Get CTA observation | ||
| 242 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | ||
| 243 | - | ||
| 244 | - // Skip observation if it's not CTA | ||
| 245 | - if (obs == NULL) { | ||
| 246 | - log_header3(TERSE, get_obs_header(m_obs[i])); | ||
| 247 | - std::string msg = " Skipping "+m_obs[i]->instrument()+ | ||
| 248 | - " observation"; | ||
| 249 | - log_string(NORMAL, msg); | ||
| 250 | - } | ||
| 251 | - | ||
| 252 | - // Fill cube and leave loop if we are binned mode (meaning we | ||
| 253 | - // only have one binned observation) | ||
| 254 | - else if (m_binned) { | ||
| 255 | - fill_cube(obs); | ||
| 256 | - i = m_obs.size(); | ||
| 257 | - } | ||
| 258 | - | ||
| 259 | - // Skip observation if we have a binned observation | ||
| 260 | - else if (obs->eventtype() == "CountsCube") { | ||
| 261 | - log_header3(TERSE, get_obs_header(m_obs[i])); | ||
| 262 | - std::string msg = " Skipping binned "+m_obs[i]->instrument()+ | ||
| 263 | - " observation"; | ||
| 264 | - log_string(NORMAL, msg); | ||
| 265 | - } | ||
| 266 | - | ||
| 267 | - // Otherwise, everything seems to be fine, so fill the cube from obs | ||
| 268 | - else { | ||
| 269 | - // Fill the cube | ||
| 270 | - fill_cube(obs); | 243 | + #pragma omp for schedule(static,1) |
| 244 | + for (int i = 0; i < m_obs.size(); ++i) { | ||
| 271 | 245 | ||
| 272 | - // Dispose events to free memory if event file exists on disk | ||
| 273 | - if (obs->eventfile().length() > 0 && obs->eventfile().exists()) { | ||
| 274 | - obs->dispose_events(); | 246 | + // Get CTA observation |
| 247 | + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | ||
| 248 | + | ||
| 249 | + // Skip observation if it's not CTA | ||
| 250 | + if (obs == NULL) { | ||
| 251 | + log_header3(TERSE, get_obs_header(m_obs[i])); | ||
| 252 | + std::string msg = " Skipping "+m_obs[i]->instrument()+ | ||
| 253 | + " observation"; | ||
| 254 | + log_string(NORMAL, msg); | ||
| 275 | } | 255 | } |
| 276 | - } | ||
| 277 | - | ||
| 278 | - } // endfor: looped over observations | 256 | + |
| 257 | + // Fill cube and leave loop if we are binned mode (meaning we | ||
| 258 | + // only have one binned observation) | ||
| 259 | + else if (m_binned) { | ||
| 260 | + fill_cube(obs, models); | ||
| 261 | + i = m_obs.size(); | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + // Skip observation if we have a binned observation | ||
| 265 | + else if (obs->eventtype() == "CountsCube") { | ||
| 266 | + log_header3(TERSE, get_obs_header(m_obs[i])); | ||
| 267 | + std::string msg = " Skipping binned "+m_obs[i]->instrument()+ | ||
| 268 | + " observation"; | ||
| 269 | + log_string(NORMAL, msg); | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + // Otherwise, everything seems to be fine, so fill the cube from obs | ||
| 273 | + else { | ||
| 274 | + // Fill the cube | ||
| 275 | + fill_cube(obs, models); | ||
| 276 | + | ||
| 277 | + // Dispose events to free memory if event file exists on disk | ||
| 278 | + if (obs->eventfile().length() > 0 && obs->eventfile().exists()) { | ||
| 279 | + obs->dispose_events(); | ||
| 280 | + } | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + } // endfor: looped over observations | ||
| 279 | 284 | ||
| 285 | + } // end openmp parallel section | ||
| 286 | + | ||
| 280 | // Write model cube into header | 287 | // Write model cube into header |
| 281 | log_header1(NORMAL, "Model cube"); | 288 | log_header1(NORMAL, "Model cube"); |
| 282 | log_string(NORMAL, m_cube.print()); | 289 | log_string(NORMAL, m_cube.print()); |
| @@ -789,7 +796,7 @@ void ctmodel::extract_cube_properties(void) | @@ -789,7 +796,7 @@ void ctmodel::extract_cube_properties(void) | ||
| 789 | * GTI of the model cube so that cube GTI is a list of the GTIs of all | 796 | * GTI of the model cube so that cube GTI is a list of the GTIs of all |
| 790 | * observations that were used to generate the model cube. | 797 | * observations that were used to generate the model cube. |
| 791 | ***************************************************************************/ | 798 | ***************************************************************************/ |
| 792 | -void ctmodel::fill_cube(const GCTAObservation* obs) | 799 | +void ctmodel::fill_cube(const GCTAObservation* obs, GModels& models) |
| 793 | { | 800 | { |
| 794 | // Get number of spatial and spectral bins in counts cube | 801 | // Get number of spatial and spectral bins in counts cube |
| 795 | int npix = m_cube.npix(); | 802 | int npix = m_cube.npix(); |
| @@ -819,8 +826,8 @@ void ctmodel::fill_cube(const GCTAObservation* obs) | @@ -819,8 +826,8 @@ void ctmodel::fill_cube(const GCTAObservation* obs) | ||
| 819 | int num_outside_roi = 0; | 826 | int num_outside_roi = 0; |
| 820 | 827 | ||
| 821 | // Extract copy of models from observation container | 828 | // Extract copy of models from observation container |
| 822 | - GModels models(m_obs.models()); | ||
| 823 | - | 829 | + GModels ex_models = trim_models(models, roi); |
| 830 | + | ||
| 824 | // Get pointer to event cube pixels | 831 | // Get pointer to event cube pixels |
| 825 | double* pixels = const_cast<double*>(m_cube.counts().pixels()); | 832 | double* pixels = const_cast<double*>(m_cube.counts().pixels()); |
| 826 | 833 | ||
| @@ -877,6 +884,9 @@ void ctmodel::fill_cube(const GCTAObservation* obs) | @@ -877,6 +884,9 @@ void ctmodel::fill_cube(const GCTAObservation* obs) | ||
| 877 | 884 | ||
| 878 | } // endfor: looped over all cube bins | 885 | } // endfor: looped over all cube bins |
| 879 | 886 | ||
| 887 | + // Re-append the models to the main model | ||
| 888 | + models.extend(ex_models); | ||
| 889 | + | ||
| 880 | // Update GTIs | 890 | // Update GTIs |
| 881 | #pragma omp critical(ctmodel_fill_cube) | 891 | #pragma omp critical(ctmodel_fill_cube) |
| 882 | { | 892 | { |
| @@ -905,3 +915,66 @@ void ctmodel::fill_cube(const GCTAObservation* obs) | @@ -905,3 +915,66 @@ void ctmodel::fill_cube(const GCTAObservation* obs) | ||
| 905 | // Return | 915 | // Return |
| 906 | return; | 916 | return; |
| 907 | } | 917 | } |
| 918 | + | ||
| 919 | + | ||
| 920 | +/***********************************************************************//** | ||
| 921 | + * @brief Find the models falling inside a defined region of interest. | ||
| 922 | + * | ||
| 923 | + * @param[in,out] all_models Model container to be trimmed. | ||
| 924 | + * @param[in] roi Observation region of interest. | ||
| 925 | + * @return New model container containing only models inside RoI. | ||
| 926 | + * | ||
| 927 | + * Note that a buffer is added to the observation region to ensure that | ||
| 928 | + * point sources (which have radius=0) are appropriately included if they | ||
| 929 | + * fall near the edge of the observation. | ||
| 930 | + ***************************************************************************/ | ||
| 931 | +GModels ctmodel::trim_models(GModels& all_models, const GCTARoi& roi) | ||
| 932 | +{ | ||
| 933 | + // Create the model container containing only models in RoI | ||
| 934 | + GModels excluded_models; | ||
| 935 | + | ||
| 936 | + // Do nothing if roi is not valid. This will be the case for binned data | ||
| 937 | + // sets as they have the default roi radius of 0. In this case we would | ||
| 938 | + // remove ALL models, which is obviously incorrect. So we keep all models | ||
| 939 | + // when filling based on a counts cube. | ||
| 940 | + if (!roi.is_valid()) { | ||
| 941 | + return excluded_models; | ||
| 942 | + } | ||
| 943 | + | ||
| 944 | + // Remove all models that dont overlap with the region of interest. Note | ||
| 945 | + // that an extra factor is used since point sources have regions of | ||
| 946 | + // radius 0, which is a problem when they fall just barely outside the | ||
| 947 | + // RoI. This ensures point sources are appropriately included. | ||
| 948 | + GSkyRegionCircle obsreg(roi.centre().dir(), roi.radius()+0.5); | ||
| 949 | + | ||
| 950 | + // Loop over the models in the passed container | ||
| 951 | + for (int i = 0; i < all_models.size(); ++i) { | ||
| 952 | + | ||
| 953 | + // Cast the model to a GModelSky object | ||
| 954 | + GModelSky* model = dynamic_cast<GModelSky*>(all_models[i]); | ||
| 955 | + | ||
| 956 | + // If model is not a GModelSky model than skip | ||
| 957 | + if (model == NULL) { | ||
| 958 | + continue; | ||
| 959 | + } | ||
| 960 | + | ||
| 961 | + // Otherwise, exclude the model if it isn't a diffuse cube and it | ||
| 962 | + // doesn't overlap with the observation. | ||
| 963 | + if (!(model->spatial()->code() == GMODEL_SPATIAL_DIFFUSE) && | ||
| 964 | + (!model->spatial()->region()->overlaps(obsreg))) { | ||
| 965 | + | ||
| 966 | + // Append model to the excluded models | ||
| 967 | + excluded_models.append(*model); | ||
| 968 | + | ||
| 969 | + // Remove model | ||
| 970 | + all_models.remove(i); | ||
| 971 | + | ||
| 972 | + // Decrement to prevent skipping models | ||
| 973 | + i--; | ||
| 974 | + } | ||
| 975 | + | ||
| 976 | + } // endfor: looped over all models | ||
| 977 | + | ||
| 978 | + // Return excluded models | ||
| 979 | + return excluded_models; | ||
| 980 | +} |
src/ctmodel/ctmodel.hpp
| @@ -74,14 +74,15 @@ public: | @@ -74,14 +74,15 @@ public: | ||
| 74 | 74 | ||
| 75 | protected: | 75 | protected: |
| 76 | // Protected methods | 76 | // Protected methods |
| 77 | - void init_members(void); | ||
| 78 | - void copy_members(const ctmodel& app); | ||
| 79 | - void free_members(void); | ||
| 80 | - void get_parameters(void); | ||
| 81 | - void get_obs(void); | ||
| 82 | - void extract_cube_properties(void); | ||
| 83 | - void fill_cube(const GCTAObservation* obs); | ||
| 84 | - bool has_cube(void) const; | 77 | + void init_members(void); |
| 78 | + void copy_members(const ctmodel& app); | ||
| 79 | + void free_members(void); | ||
| 80 | + void get_parameters(void); | ||
| 81 | + void get_obs(void); | ||
| 82 | + void extract_cube_properties(void); | ||
| 83 | + void fill_cube(const GCTAObservation* obs, GModels& models); | ||
| 84 | + bool has_cube(void) const; | ||
| 85 | + GModels trim_models(GModels& all_models, const GCTARoi& roi); | ||
| 85 | 86 | ||
| 86 | // User parameters | 87 | // User parameters |
| 87 | GFilename m_outcube; //!< Output model cube | 88 | GFilename m_outcube; //!< Output model cube |