Commit c5d45282c745d5ba5901a0a04aae3c68b2fb43b4

Authored by Jürgen Knödlseder
2 parents eaa252c2 fe0597f6

Merge branch '2189-ctmodel_trim_models' into integration

# Conflicts:
#	ChangeLog
#	NEWS
#	doc/source/admin/release_history/1.5.rst
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
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