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 | 3 | * Version 1.5.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | - Use t-type parameters for all "tmin" and "tmax" parameters (#1864) | |
| 7 | 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 | 11 | 2017-07-28 | ... | ... |
NEWS
| 1 | 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 | 6 | Introduction |
| ... | ... | @@ -63,6 +63,11 @@ ctmodel - CTA counts cube modelling |
| 63 | 63 | Use t-type parameters for "tmin" and "tmax" to all specifying times in various |
| 64 | 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 | 72 | ctexpcube - CTA exposure cube generation |
| 68 | 73 | ---------------------------------------- | ... | ... |
doc/source/admin/release_history/1.5.rst
| ... | ... | @@ -24,6 +24,8 @@ Improvements |
| 24 | 24 | |
| 25 | 25 | * [`2194 <https://cta-redmine.irap.omp.eu/issues/2194>`_] - |
| 26 | 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 | 31 | New features | ... | ... |
src/ctmodel/ctmodel.cpp
| ... | ... | @@ -235,48 +235,55 @@ void ctmodel::run(void) |
| 235 | 235 | log_header1(TERSE, "Generate model cube"); |
| 236 | 236 | |
| 237 | 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 | 287 | // Write model cube into header |
| 281 | 288 | log_header1(NORMAL, "Model cube"); |
| 282 | 289 | log_string(NORMAL, m_cube.print()); |
| ... | ... | @@ -789,7 +796,7 @@ void ctmodel::extract_cube_properties(void) |
| 789 | 796 | * GTI of the model cube so that cube GTI is a list of the GTIs of all |
| 790 | 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 | 801 | // Get number of spatial and spectral bins in counts cube |
| 795 | 802 | int npix = m_cube.npix(); |
| ... | ... | @@ -819,8 +826,8 @@ void ctmodel::fill_cube(const GCTAObservation* obs) |
| 819 | 826 | int num_outside_roi = 0; |
| 820 | 827 | |
| 821 | 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 | 831 | // Get pointer to event cube pixels |
| 825 | 832 | double* pixels = const_cast<double*>(m_cube.counts().pixels()); |
| 826 | 833 | |
| ... | ... | @@ -877,6 +884,9 @@ void ctmodel::fill_cube(const GCTAObservation* obs) |
| 877 | 884 | |
| 878 | 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 | 890 | // Update GTIs |
| 881 | 891 | #pragma omp critical(ctmodel_fill_cube) |
| 882 | 892 | { |
| ... | ... | @@ -905,3 +915,66 @@ void ctmodel::fill_cube(const GCTAObservation* obs) |
| 905 | 915 | // Return |
| 906 | 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 | 74 | |
| 75 | 75 | protected: |
| 76 | 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 | 87 | // User parameters |
| 87 | 88 | GFilename m_outcube; //!< Output model cube | ... | ... |