Commit e9f7fb0a06651f39aa8a93501e6990b896c07971

Authored by Josh Cardenzana
1 parent 1c4c3571

Updated model trimming and parallelization in ctmodel (#2189)

Updated the model trimming so that the models that are outside an observation are offloaded to another model container and then re-appended after the evaluation.
Parallelization scheduling set to "static" with a chunk size of 1. This will slightly help with the issue in which multiple observations in a row do not contribute to the model cube and thus dividing the observations into "n-observations/n-cores" is not ideal.
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) {
  245 +
  246 + // Get CTA observation
  247 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
271 248  
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();
  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,7 +826,7 @@ 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 = trim_models(m_obs.models(), roi);
  829 + GModels ex_models = trim_models(models, roi);
823 830  
824 831 // Get pointer to event cube pixels
825 832 double* pixels = const_cast<double*>(m_cube.counts().pixels());
... ... @@ -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 {
... ... @@ -918,27 +928,24 @@ void ctmodel::fill_cube(const GCTAObservation* obs)
918 928 * point sources (which have radius=0) are appropriately included if they
919 929 * fall near the edge of the observation.
920 930 ***************************************************************************/
921   -GModels ctmodel::trim_models(const GModels& all_models, const GCTARoi& roi)
  931 +GModels ctmodel::trim_models(GModels& all_models, const GCTARoi& roi)
922 932 {
  933 + // Create the model object to be returned
  934 + GModels excluded_models;
  935 +
923 936 // Do nothing if roi is not valid. This will be the case for binned data
924 937 // sets as they have the default roi radius of 0. In this case we would
925 938 // remove ALL models, which is obviously incorrect. So we keep all models
926 939 // when filling based on a counts cube.
927 940 if (!roi.is_valid()) {
928   - return all_models;
  941 + return excluded_models;
929 942 }
930 943  
931 944 // Remove all models that dont overlap with the region of interest. Note
932 945 // that an extra factor is used since point sources have regions of
933 946 // radius 0, which is a problem when they fall just barely outside the
934 947 // ROI. This ensures point sources are appropriately included.
935   - GSkyRegionCircle obsreg(
936   - roi.centre().dir().ra_deg(),
937   - roi.centre().dir().dec_deg(),
938   - roi.radius()+0.5); // Note the buffer
939   -
940   - // Create the model object to be returned
941   - GModels contained_models;
  948 + GSkyRegionCircle obsreg(roi.centre().dir(), roi.radius()+0.5);
942 949  
943 950 // Loop over the models in the passed container
944 951 for (int mod=0; mod<all_models.size(); mod++) {
... ... @@ -947,18 +954,21 @@ GModels ctmodel::trim_models(const GModels&amp; all_models, const GCTARoi&amp; roi)
947 954  
948 955 if (model == NULL) {
949 956 // Model is most likely a background model and should be kept
950   - contained_models.append(*all_models.at(mod)->clone());
951   -
952   - } else if (model->spatial()->region()->overlaps(obsreg)) {
953   - // Model represents a source, that overlaps the observation
954   - // and should be kept.
955   - contained_models.append(*model);
956   -
957   - // Delete model since it isnt needed anymore
958   - delete model;
  957 + continue;
  958 + }
  959 + // Otherwise, exclude the model if it isn't a diffuse cube and it
  960 + // doesn't overlap with the observation.
  961 + else if (!(model->spatial()->code() == GMODEL_SPATIAL_DIFFUSE) &&
  962 + (!model->spatial()->region()->overlaps(obsreg))) {
  963 + // Model represents a source, that doesn't overlap the observation
  964 + // and should be removed for now.
  965 + excluded_models.append(*model);
  966 + all_models.remove(mod);
  967 + mod--; // decrement to prevent skipping models
959 968 }
960 969  
  970 + delete model;
961 971 }
962 972  
963   - return contained_models;
  973 + return excluded_models;
964 974 }
... ...
src/ctmodel/ctmodel.hpp
... ... @@ -80,9 +80,9 @@ protected:
80 80 void get_parameters(void);
81 81 void get_obs(void);
82 82 void extract_cube_properties(void);
83   - void fill_cube(const GCTAObservation* obs);
  83 + void fill_cube(const GCTAObservation* obs, GModels& models);
84 84 bool has_cube(void) const;
85   - GModels trim_models(const GModels& all_models, const GCTARoi& roi);
  85 + GModels trim_models(GModels& all_models, const GCTARoi& roi);
86 86  
87 87 // User parameters
88 88 GFilename m_outcube; //!< Output model cube
... ...