Commit 42c737c13279f5fa71d51575b2a6ab58a8e98bb9

Authored by Jürgen Knödlseder
1 parent a3805817

Reduce memory requirements for ctobssim.

The memory needs for ctobssim have been reduced by first working on a local copy of the CTA observation (this de-allocates properly and memory cache associated to the response functions), and by saving and disposing the event lists immediately if called using the execute() method (this is the method called when the tool is run from the command line).
ChangeLog
1   -2014-10-17 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
  1 +2014-10-24 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
2 2  
3 3 * Version 0.8.0 released
4 4 ========================
... ... @@ -17,6 +17,7 @@
17 17 Support energy dispersion in ctobssim, ctlike and ctmodel
18 18 Correct ctobssim for thread safety
19 19 Correctly apply time references in ctselect
  20 + Reduce memory usage
20 21 Move obsutils to ctools namespace
21 22 Add several functions to obsutils
22 23 Enhance documentation
... ...
... ... @@ -2,7 +2,7 @@ New Features and Important Changes in ctools 00-08-00
2 2  
3 3 Author(s) : Juergen Knoedlseder
4 4  
5   -17 October 2014
  5 +24 October 2014
6 6  
7 7  
8 8 1. Introduction
... ... @@ -48,6 +48,12 @@ avoiding concurrent memory access (#1258).
48 48 ctobssim now also supports the handling of energy dispersion. Energy
49 49 dispersion can be switched on or off using the hidden edisp parameter.
50 50  
  51 +The memory needs for ctobssim have been reduced by first working on a
  52 +local copy of the CTA observation (this de-allocates properly and memory
  53 +cache associated to the response functions), and by saving and disposing
  54 +the event lists immediately if called using the execute() method (this
  55 +is the method called when the tool is run from the command line).
  56 +
51 57  
52 58 6. ctselect - CTA event selection
53 59 ---------------------------------
... ...
src/ctobssim/ctobssim.cpp
... ... @@ -92,7 +92,7 @@ ctobssim::ctobssim(const GObservations&amp; obs) :
92 92 *
93 93 * Constructs application using command line arguments for parameter setting.
94 94 ***************************************************************************/
95   -ctobssim::ctobssim(int argc, char *argv[]) :
  95 +ctobssim::ctobssim(int argc, char *argv[]) :
96 96 ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION, argc, argv)
97 97 {
98 98 // Initialise members
... ... @@ -218,18 +218,16 @@ void ctobssim::run(void)
218 218 log << std::endl;
219 219 }
220 220  
221   - // Write seed values into logger
222   - if (logTerse()) {
223   - log << std::endl;
224   - log.header1("Seed values");
225   - for (int i = 0; i < m_rans.size(); ++i) {
226   - log << gammalib::parformat("Seed "+gammalib::str(i));
227   - log << gammalib::str(m_rans[i].seed()) << std::endl;
228   - }
  221 + // Special mode: if read ahead is specified we know that we called
  222 + // the execute() method, hence files are saved immediately and event
  223 + // lists are disposed afterwards.
  224 + if (read_ahead()) {
  225 + m_save_and_dispose = true;
229 226 }
230 227  
231   - // Set energy dispersion flag for all CTA observations and save old
232   - // values in save_edisp vector
  228 + // Determine the number of valid CTA observations, set energy dispersion flag
  229 + // for all CTA observations and save old values in save_edisp vector
  230 + int n_observations = 0;
233 231 std::vector<bool> save_edisp;
234 232 save_edisp.assign(m_obs.size(), false);
235 233 for (int i = 0; i < m_obs.size(); ++i) {
... ... @@ -237,6 +235,43 @@ void ctobssim::run(void)
237 235 if (obs != NULL) {
238 236 save_edisp[i] = obs->response()->apply_edisp();
239 237 obs->response()->apply_edisp(m_apply_edisp);
  238 + n_observations++;
  239 + }
  240 + }
  241 +
  242 + // If more than a single observation has been handled then make sure that
  243 + // an XML file will be used for storage
  244 + if (n_observations > 1) {
  245 + m_use_xml = true;
  246 + }
  247 +
  248 + // Write execution mode into logger
  249 + if (logTerse()) {
  250 + log << std::endl;
  251 + log.header1("Execution mode");
  252 + log << gammalib::parformat("Event list management");
  253 + if (m_save_and_dispose) {
  254 + log << "Save and dispose (reduces memory needs)" << std::endl;
  255 + }
  256 + else {
  257 + log << "Keep events in memory" << std::endl;
  258 + }
  259 + log << gammalib::parformat("Output format");
  260 + if (m_use_xml) {
  261 + log << "Write Observation Definition XML file" << std::endl;
  262 + }
  263 + else {
  264 + log << "Write single event list FITS file" << std::endl;
  265 + }
  266 + }
  267 +
  268 + // Write seed values into logger
  269 + if (logTerse()) {
  270 + log << std::endl;
  271 + log.header1("Seed values");
  272 + for (int i = 0; i < m_rans.size(); ++i) {
  273 + log << gammalib::parformat("Seed "+gammalib::str(i));
  274 + log << gammalib::str(m_rans[i].seed()) << std::endl;
240 275 }
241 276 }
242 277  
... ... @@ -263,9 +298,6 @@ void ctobssim::run(void)
263 298 }
264 299 }
265 300  
266   - // Initialise counters
267   - int n_observations = 0;
268   -
269 301 // From here on the code can be parallelized if OpenMP support
270 302 // is enabled. The code in the following block corresponds to the
271 303 // code that will be executed in each thread
... ... @@ -288,11 +320,11 @@ void ctobssim::run(void)
288 320 wrklog.max_size(10000000);
289 321  
290 322 // Loop over all observation in the container. If OpenMP support
291   - // is enabled, this looped will be parallelized.
  323 + // is enabled, this loop will be parallelized.
292 324 #pragma omp for
293 325 for (int i = 0; i < m_obs.size(); ++i) {
294 326  
295   - // Get CTA observation
  327 + // Get pointer on CTA observation
296 328 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
297 329  
298 330 // Continue only if observation is a CTA observation
... ... @@ -308,26 +340,55 @@ void ctobssim::run(void)
308 340 }
309 341 }
310 342  
311   - // Increment counter
312   - n_observations++;
  343 + // Work on a clone of the CTA observation. This makes sure that
  344 + // any memory allocated for computing (for example a response
  345 + // cache) is properly de-allocated on exit of this run
  346 + GCTAObservation obs_clone = *obs;
313 347  
314 348 // Save number of events before entering simulation
315   - int events_before = obs->events()->size();
  349 + int events_before = obs_clone.events()->size();
316 350  
317 351 // Simulate source events
318   - simulate_source(obs, models, m_rans[i], &wrklog);
  352 + simulate_source(&obs_clone, models, m_rans[i], &wrklog);
319 353  
320 354 // Simulate source events
321   - simulate_background(obs, models, m_rans[i], &wrklog);
  355 + simulate_background(&obs_clone, models, m_rans[i], &wrklog);
322 356  
323 357 // Dump simulation results
324 358 if (logNormal()) {
325 359 wrklog << gammalib::parformat("MC events");
326   - wrklog << obs->events()->size() - events_before;
  360 + wrklog << obs_clone.events()->size() - events_before;
327 361 wrklog << " (all models)";
328 362 wrklog << std::endl;
329 363 }
330 364  
  365 + // If requested, event lists are saved immediately
  366 + if (m_save_and_dispose) {
  367 +
  368 + // Set event output file name. If multiple observations are
  369 + // handled, build the filename from prefix and observation
  370 + // index. Otherwise use the outfile parameter.
  371 + std::string outfile;
  372 + if (m_use_xml) {
  373 + m_prefix = (*this)["prefix"].string();
  374 + outfile = m_prefix + gammalib::str(i) + ".fits";
  375 + }
  376 + else {
  377 + outfile = (*this)["outfile"].filename();
  378 + }
  379 +
  380 + // Store output file name in original observation
  381 + obs->eventfile(outfile);
  382 +
  383 + // Save observation into FITS file
  384 + obs_clone.save(outfile, clobber());
  385 +
  386 + }
  387 +
  388 + // ... otherwise append the event list to the original observation
  389 + else {
  390 + obs->events(*(obs_clone.events()));
  391 + }
331 392  
332 393 } // endif: CTA observation found
333 394  
... ... @@ -341,12 +402,6 @@ void ctobssim::run(void)
341 402 }
342 403  
343 404 } // end pragma omp parallel
344   -
345   - // If more than a single observation has been handled then make sure that
346   - // an XML file will be used for storage
347   - if (n_observations > 1) {
348   - m_use_xml = true;
349   - }
350 405  
351 406 // Restore energy dispersion flag for all CTA observations
352 407 for (int i = 0; i < m_obs.size(); ++i) {
... ... @@ -409,6 +464,142 @@ void ctobssim::save(void)
409 464  
410 465  
411 466 /***********************************************************************//**
  467 + * @brief Return observation container
  468 + *
  469 + * @return Reference to observation container
  470 + ***************************************************************************/
  471 +const GObservations& ctobssim::obs(void) const
  472 +{
  473 + // If event lists have been disposed, load them now into the observation
  474 + // container
  475 + if (m_save_and_dispose) {
  476 +
  477 + // Loop over all observation in the container
  478 + for (int i = 0; i < m_obs.size(); ++i) {
  479 +
  480 + // Get CTA observation
  481 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  482 +
  483 + // Handle only CTA observations
  484 + if (obs != NULL) {
  485 +
  486 + // Load observation from FITS file
  487 + obs->load(obs->eventfile());
  488 +
  489 + } // endif: observation was a CTA observations
  490 +
  491 + } // endfor: looped over CTA observations
  492 +
  493 + // Now we have the event lists hence we can reset the disposal flag
  494 + m_save_and_dispose = false;
  495 +
  496 + } // endif: event lists have been disposed
  497 +
  498 + // Return observation container
  499 + return m_obs;
  500 +}
  501 +
  502 +
  503 +/*==========================================================================
  504 + = =
  505 + = Private methods =
  506 + = =
  507 + ==========================================================================*/
  508 +
  509 +/***********************************************************************//**
  510 + * @brief Initialise class members
  511 + *
  512 + * The thrown area is fixed to pi*(2500^2) m2, which is the same value that
  513 + * is used in the Monte Carlo simulations (information from Konrad Bernloehr)
  514 + ***************************************************************************/
  515 +void ctobssim::init_members(void)
  516 +{
  517 + // Initialise user parameters
  518 + m_infile.clear();
  519 + m_outfile.clear();
  520 + m_prefix.clear();
  521 + m_seed = 1;
  522 + m_ra = 0.0;
  523 + m_dec = 0.0;
  524 + m_rad = 0.0;
  525 + m_tmin = 0.0;
  526 + m_tmax = 0.0;
  527 + m_emin = 0.0;
  528 + m_emax = 0.0;
  529 + m_apply_edisp = false;
  530 + m_deadc = 1.0;
  531 +
  532 + // Initialise protected members
  533 + m_rans.clear();
  534 + m_obs.clear();
  535 + m_use_xml = false;
  536 + m_save_and_dispose = false;
  537 +
  538 + // Set fixed parameters
  539 + m_area = 19634954.0 * 1.0e4; //!< pi*(2500^2) m^2
  540 + m_max_photons = 1000000; //!< Maximum number of photons / time slice
  541 +
  542 + // Set CTA time reference. G_CTA_MJDREF is the CTA reference MJD,
  543 + // which is defined in GCTALib.hpp. This is somehow a kluge. We need
  544 + // a better mechanism to implement the CTA reference MJD.
  545 + m_cta_ref.set(G_CTA_MJDREF, "s", "TT", "LOCAL");
  546 +
  547 + // Initialise first event identifier
  548 + m_event_id = 1;
  549 +
  550 + // Return
  551 + return;
  552 +}
  553 +
  554 +
  555 +/***********************************************************************//**
  556 + * @brief Copy class members
  557 + *
  558 + * @param[in] app Application.
  559 + ***************************************************************************/
  560 +void ctobssim::copy_members(const ctobssim& app)
  561 +{
  562 + // Copy user parameters
  563 + m_infile = app.m_infile;
  564 + m_outfile = app.m_outfile;
  565 + m_prefix = app.m_prefix;
  566 + m_seed = app.m_seed;
  567 + m_ra = app.m_ra;
  568 + m_dec = app.m_dec;
  569 + m_rad = app.m_rad;
  570 + m_tmin = app.m_tmin;
  571 + m_tmax = app.m_tmax;
  572 + m_emin = app.m_emin;
  573 + m_emax = app.m_emax;
  574 + m_apply_edisp = app.m_apply_edisp;
  575 + m_deadc = app.m_deadc;
  576 +
  577 + // Copy protected members
  578 + m_area = app.m_area;
  579 + m_max_photons = app.m_max_photons;
  580 + m_rans = app.m_rans;
  581 + m_obs = app.m_obs;
  582 + m_use_xml = app.m_use_xml;
  583 + m_save_and_dispose = app.m_save_and_dispose;
  584 + m_cta_ref = app.m_cta_ref;
  585 + m_event_id = app.m_event_id;
  586 +
  587 + // Return
  588 + return;
  589 +}
  590 +
  591 +
  592 +/***********************************************************************//**
  593 + * @brief Delete class members
  594 + ***************************************************************************/
  595 +void ctobssim::free_members(void)
  596 +{
  597 + // Return
  598 + return;
  599 +}
  600 +
  601 +
  602 +/***********************************************************************//**
412 603 * @brief Get application parameters
413 604 *
414 605 * Get all task parameters from parameter file or (if required) by querying
... ... @@ -473,6 +664,16 @@ void ctobssim::get_parameters(void)
473 664 m_prefix = (*this)["prefix"].string();
474 665 }
475 666  
  667 + // Make sure that all observations hold a CTA event list
  668 + for (int i = 0; i < m_obs.size(); ++i) {
  669 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  670 + if (obs != NULL) {
  671 + if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) {
  672 + set_list(obs);
  673 + }
  674 + }
  675 + }
  676 +
476 677 // Initialise random number generators. We initialise here one random
477 678 // number generator per observation so that each observation will
478 679 // get it's own random number generator. This will lead to identical
... ... @@ -624,21 +825,17 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models,
624 825 }
625 826  
626 827 // Get CTA response
627   - const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(obs->response());
  828 + const GCTAResponseIrf* rsp =
  829 + dynamic_cast<const GCTAResponseIrf*>(obs->response());
628 830 if (rsp == NULL) {
629 831 std::string msg = "Response is not an IRF response.\n" +
630 832 obs->response()->print();
631 833 throw GException::invalid_value(G_SIMULATE_SOURCE, msg);
632 834 }
633 835  
634   - // Make sure that the observation holds a CTA event list. If this
635   - // is not the case then allocate and attach a CTA event list now.
636   - if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) {
637   - set_list(obs);
638   - }
639   -
640 836 // Get pointer on event list (circumvent const correctness)
641   - GCTAEventList* events = static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events()));
  837 + GCTAEventList* events =
  838 + static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events()));
642 839  
643 840 // Extract simulation region.
644 841 GSkyDir dir = events->roi().centre().dir();
... ... @@ -898,7 +1095,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models,
898 1095 ***************************************************************************/
899 1096 void ctobssim::simulate_background(GCTAObservation* obs,
900 1097 const GModels& models,
901   - GRan& ran,
  1098 + GRan& ran,
902 1099 GLog* wrklog)
903 1100 {
904 1101 // Continue only if observation pointer is valid
... ... @@ -909,12 +1106,6 @@ void ctobssim::simulate_background(GCTAObservation* obs,
909 1106 wrklog = &log;
910 1107 }
911 1108  
912   - // Make sure that the observation holds a CTA event list. If this
913   - // is not the case then allocate and attach a CTA event list now.
914   - if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) {
915   - set_list(obs);
916   - }
917   -
918 1109 // Get pointer on event list (circumvent const correctness)
919 1110 GCTAEventList* events =
920 1111 static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events()));
... ... @@ -934,7 +1125,7 @@ void ctobssim::simulate_background(GCTAObservation* obs,
934 1125 // Get simulated CTA event list. Note that this method
935 1126 // includes the deadtime correction.
936 1127 GCTAEventList* list =
937   - dynamic_cast<GCTAEventList*>(model->mc(*obs, ran));
  1128 + dynamic_cast<GCTAEventList*>(model->mc(*obs, ran));
938 1129  
939 1130 // Continue only if we got a CTA event list
940 1131 if (list != NULL) {
... ... @@ -984,103 +1175,6 @@ void ctobssim::simulate_background(GCTAObservation* obs,
984 1175 }
985 1176  
986 1177  
987   -/*==========================================================================
988   - = =
989   - = Private methods =
990   - = =
991   - ==========================================================================*/
992   -
993   -/***********************************************************************//**
994   - * @brief Initialise class members
995   - *
996   - * The thrown area is fixed to pi*(2500^2) m2, which is the same value that
997   - * is used in the Monte Carlo simulations (information from Konrad Bernloehr)
998   - ***************************************************************************/
999   -void ctobssim::init_members(void)
1000   -{
1001   - // Initialise user parameters
1002   - m_infile.clear();
1003   - m_outfile.clear();
1004   - m_prefix.clear();
1005   - m_seed = 1;
1006   - m_ra = 0.0;
1007   - m_dec = 0.0;
1008   - m_rad = 0.0;
1009   - m_tmin = 0.0;
1010   - m_tmax = 0.0;
1011   - m_emin = 0.0;
1012   - m_emax = 0.0;
1013   - m_apply_edisp = false;
1014   - m_deadc = 1.0;
1015   -
1016   - // Initialise protected members
1017   - m_rans.clear();
1018   - m_obs.clear();
1019   - m_use_xml = false;
1020   -
1021   - // Set fixed parameters
1022   - m_area = 19634954.0 * 1.0e4; //!< pi*(2500^2) m^2
1023   - m_max_photons = 1000000; //!< Maximum number of photons / time slice
1024   -
1025   - // Set CTA time reference. G_CTA_MJDREF is the CTA reference MJD,
1026   - // which is defined in GCTALib.hpp. This is somehow a kluge. We need
1027   - // a better mechanism to implement the CTA reference MJD.
1028   - m_cta_ref.set(G_CTA_MJDREF, "s", "TT", "LOCAL");
1029   -
1030   - // Initialise first event identifier
1031   - m_event_id = 1;
1032   -
1033   - // Return
1034   - return;
1035   -}
1036   -
1037   -
1038   -/***********************************************************************//**
1039   - * @brief Copy class members
1040   - *
1041   - * @param[in] app Application.
1042   - ***************************************************************************/
1043   -void ctobssim::copy_members(const ctobssim& app)
1044   -{
1045   - // Copy user parameters
1046   - m_infile = app.m_infile;
1047   - m_outfile = app.m_outfile;
1048   - m_prefix = app.m_prefix;
1049   - m_seed = app.m_seed;
1050   - m_ra = app.m_ra;
1051   - m_dec = app.m_dec;
1052   - m_rad = app.m_rad;
1053   - m_tmin = app.m_tmin;
1054   - m_tmax = app.m_tmax;
1055   - m_emin = app.m_emin;
1056   - m_emax = app.m_emax;
1057   - m_apply_edisp = app.m_apply_edisp;
1058   - m_deadc = app.m_deadc;
1059   -
1060   - // Copy protected members
1061   - m_area = app.m_area;
1062   - m_max_photons = app.m_max_photons;
1063   - m_rans = app.m_rans;
1064   - m_obs = app.m_obs;
1065   - m_use_xml = app.m_use_xml;
1066   - m_cta_ref = app.m_cta_ref;
1067   - m_event_id = app.m_event_id;
1068   -
1069   - // Return
1070   - return;
1071   -}
1072   -
1073   -
1074   -/***********************************************************************//**
1075   - * @brief Delete class members
1076   - ***************************************************************************/
1077   -void ctobssim::free_members(void)
1078   -{
1079   - // Return
1080   - return;
1081   -}
1082   -
1083   -
1084 1178 /***********************************************************************//**
1085 1179 * @brief Save event list in FITS format.
1086 1180 *
... ... @@ -1089,14 +1183,19 @@ void ctobssim::free_members(void)
1089 1183 ***************************************************************************/
1090 1184 void ctobssim::save_fits(void)
1091 1185 {
1092   - // Get output filename
1093   - m_outfile = (*this)["outfile"].filename();
  1186 + // Save only if event list has not yet been saved and disposed
  1187 + if (!m_save_and_dispose) {
  1188 +
  1189 + // Get output filename
  1190 + m_outfile = (*this)["outfile"].filename();
1094 1191  
1095   - // Get CTA observation from observation container
1096   - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]);
  1192 + // Get CTA observation from observation container
  1193 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]);
1097 1194  
1098   - // Save observation into FITS file
1099   - obs->save(m_outfile, clobber());
  1195 + // Save observation into FITS file
  1196 + obs->save(m_outfile, clobber());
  1197 +
  1198 + } // endif: event list has not yet been saved and disposed
1100 1199  
1101 1200 // Return
1102 1201 return;
... ... @@ -1131,34 +1230,37 @@ void ctobssim::save_xml(void)
1131 1230 " definition files." << std::endl;
1132 1231 }
1133 1232  
1134   - // Initialise file number
1135   - int file_num = 0;
  1233 + // Save only if event lists have not yet been saved and disposed
  1234 + if (!m_save_and_dispose) {
1136 1235  
1137   - // Loop over all observation in the container
1138   - for (int i = 0; i < m_obs.size(); ++i) {
  1236 + // Loop over all observation in the container
  1237 + for (int i = 0; i < m_obs.size(); ++i) {
1139 1238  
1140   - // Get CTA observation
1141   - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  1239 + // Get CTA observation
  1240 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
1142 1241  
1143   - // Handle only CTA observations
1144   - if (obs != NULL) {
  1242 + // Handle only CTA observations
  1243 + if (obs != NULL) {
1145 1244  
1146   - // Set event output file name
1147   - std::string outfile = m_prefix + gammalib::str(file_num) + ".fits";
  1245 + // Continue only if there is an event list (it may have been disposed)
  1246 + if (obs->events()->size() != 0) {
1148 1247  
1149   - // Store output file name in observation
1150   - obs->eventfile(outfile);
  1248 + // Set event output file name
  1249 + std::string outfile = m_prefix + gammalib::str(i) + ".fits";
1151 1250  
1152   - // Save observation into FITS file
1153   - obs->save(outfile, clobber());
  1251 + // Store output file name in observation
  1252 + obs->eventfile(outfile);
1154 1253  
1155   - // Increment file number
1156   - file_num++;
  1254 + // Save observation into FITS file
  1255 + obs->save(outfile, clobber());
1157 1256  
  1257 + }
1158 1258  
1159   - } // endif: observation was a CTA observations
  1259 + } // endif: observation was a CTA observations
1160 1260  
1161   - } // endfor: looped over observations
  1261 + } // endfor: looped over observations
  1262 +
  1263 + } // endif: event list has not yet been saved and disposed
1162 1264  
1163 1265 // Save observations in XML file
1164 1266 m_obs.save(m_outfile);
... ...
src/ctobssim/ctobssim.hpp
... ... @@ -101,25 +101,14 @@ protected:
101 101 double m_deadc; //!< Average deadtime correction
102 102  
103 103 // Protected members
104   - double m_area; //!< Surface area for simulation (cm2)
105   - int m_max_photons; //!< Maximum number of photons/slice
106   - std::vector<GRan> m_rans; //!< Random number generators
107   - GObservations m_obs; //!< Observation container
108   - bool m_use_xml; //!< Use XML file instead of FITS file
109   - GTimeReference m_cta_ref; //!< CTA time reference
110   - int m_event_id; //!< Event identifier
  104 + mutable GObservations m_obs; //!< Observation container
  105 + mutable bool m_save_and_dispose; //!< Save and dispose immediately
  106 + double m_area; //!< Surface area for simulation (cm2)
  107 + int m_max_photons; //!< Maximum number of photons/slice
  108 + std::vector<GRan> m_rans; //!< Random number generators
  109 + bool m_use_xml; //!< Use XML file instead of FITS file
  110 + GTimeReference m_cta_ref; //!< CTA time reference
  111 + int m_event_id; //!< Event identifier
111 112 };
112 113  
113   -
114   -/***********************************************************************//**
115   - * @brief Return observation container
116   - *
117   - * @return Reference to observation container
118   - ***************************************************************************/
119   -inline
120   -const GObservations& ctobssim::obs(void) const
121   -{
122   - return m_obs;
123   -}
124   -
125 114 #endif /* CTOBSSIM_HPP */
... ...