Commit 42c737c13279f5fa71d51575b2a6ab58a8e98bb9
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).
Showing
4 changed files
with
284 additions
and
186 deletions
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 | * Version 0.8.0 released | 3 | * Version 0.8.0 released |
| 4 | ======================== | 4 | ======================== |
| @@ -17,6 +17,7 @@ | @@ -17,6 +17,7 @@ | ||
| 17 | Support energy dispersion in ctobssim, ctlike and ctmodel | 17 | Support energy dispersion in ctobssim, ctlike and ctmodel |
| 18 | Correct ctobssim for thread safety | 18 | Correct ctobssim for thread safety |
| 19 | Correctly apply time references in ctselect | 19 | Correctly apply time references in ctselect |
| 20 | + Reduce memory usage | ||
| 20 | Move obsutils to ctools namespace | 21 | Move obsutils to ctools namespace |
| 21 | Add several functions to obsutils | 22 | Add several functions to obsutils |
| 22 | Enhance documentation | 23 | Enhance documentation |
NEWS
| @@ -2,7 +2,7 @@ New Features and Important Changes in ctools 00-08-00 | @@ -2,7 +2,7 @@ New Features and Important Changes in ctools 00-08-00 | ||
| 2 | 2 | ||
| 3 | Author(s) : Juergen Knoedlseder | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | ||
| 5 | -17 October 2014 | 5 | +24 October 2014 |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | 1. Introduction | 8 | 1. Introduction |
| @@ -48,6 +48,12 @@ avoiding concurrent memory access (#1258). | @@ -48,6 +48,12 @@ avoiding concurrent memory access (#1258). | ||
| 48 | ctobssim now also supports the handling of energy dispersion. Energy | 48 | ctobssim now also supports the handling of energy dispersion. Energy |
| 49 | dispersion can be switched on or off using the hidden edisp parameter. | 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 | 6. ctselect - CTA event selection | 58 | 6. ctselect - CTA event selection |
| 53 | --------------------------------- | 59 | --------------------------------- |
src/ctobssim/ctobssim.cpp
| @@ -92,7 +92,7 @@ ctobssim::ctobssim(const GObservations& obs) : | @@ -92,7 +92,7 @@ ctobssim::ctobssim(const GObservations& obs) : | ||
| 92 | * | 92 | * |
| 93 | * Constructs application using command line arguments for parameter setting. | 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 | ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION, argc, argv) | 96 | ctool(CTOBSSIM_NAME, CTOBSSIM_VERSION, argc, argv) |
| 97 | { | 97 | { |
| 98 | // Initialise members | 98 | // Initialise members |
| @@ -218,18 +218,16 @@ void ctobssim::run(void) | @@ -218,18 +218,16 @@ void ctobssim::run(void) | ||
| 218 | log << std::endl; | 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 | std::vector<bool> save_edisp; | 231 | std::vector<bool> save_edisp; |
| 234 | save_edisp.assign(m_obs.size(), false); | 232 | save_edisp.assign(m_obs.size(), false); |
| 235 | for (int i = 0; i < m_obs.size(); ++i) { | 233 | for (int i = 0; i < m_obs.size(); ++i) { |
| @@ -237,6 +235,43 @@ void ctobssim::run(void) | @@ -237,6 +235,43 @@ void ctobssim::run(void) | ||
| 237 | if (obs != NULL) { | 235 | if (obs != NULL) { |
| 238 | save_edisp[i] = obs->response()->apply_edisp(); | 236 | save_edisp[i] = obs->response()->apply_edisp(); |
| 239 | obs->response()->apply_edisp(m_apply_edisp); | 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,9 +298,6 @@ void ctobssim::run(void) | ||
| 263 | } | 298 | } |
| 264 | } | 299 | } |
| 265 | 300 | ||
| 266 | - // Initialise counters | ||
| 267 | - int n_observations = 0; | ||
| 268 | - | ||
| 269 | // From here on the code can be parallelized if OpenMP support | 301 | // From here on the code can be parallelized if OpenMP support |
| 270 | // is enabled. The code in the following block corresponds to the | 302 | // is enabled. The code in the following block corresponds to the |
| 271 | // code that will be executed in each thread | 303 | // code that will be executed in each thread |
| @@ -288,11 +320,11 @@ void ctobssim::run(void) | @@ -288,11 +320,11 @@ void ctobssim::run(void) | ||
| 288 | wrklog.max_size(10000000); | 320 | wrklog.max_size(10000000); |
| 289 | 321 | ||
| 290 | // Loop over all observation in the container. If OpenMP support | 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 | #pragma omp for | 324 | #pragma omp for |
| 293 | for (int i = 0; i < m_obs.size(); ++i) { | 325 | for (int i = 0; i < m_obs.size(); ++i) { |
| 294 | 326 | ||
| 295 | - // Get CTA observation | 327 | + // Get pointer on CTA observation |
| 296 | GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | 328 | GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); |
| 297 | 329 | ||
| 298 | // Continue only if observation is a CTA observation | 330 | // Continue only if observation is a CTA observation |
| @@ -308,26 +340,55 @@ void ctobssim::run(void) | @@ -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 | // Save number of events before entering simulation | 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 | // Simulate source events | 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 | // Simulate source events | 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 | // Dump simulation results | 357 | // Dump simulation results |
| 324 | if (logNormal()) { | 358 | if (logNormal()) { |
| 325 | wrklog << gammalib::parformat("MC events"); | 359 | wrklog << gammalib::parformat("MC events"); |
| 326 | - wrklog << obs->events()->size() - events_before; | 360 | + wrklog << obs_clone.events()->size() - events_before; |
| 327 | wrklog << " (all models)"; | 361 | wrklog << " (all models)"; |
| 328 | wrklog << std::endl; | 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 | } // endif: CTA observation found | 393 | } // endif: CTA observation found |
| 333 | 394 | ||
| @@ -341,12 +402,6 @@ void ctobssim::run(void) | @@ -341,12 +402,6 @@ void ctobssim::run(void) | ||
| 341 | } | 402 | } |
| 342 | 403 | ||
| 343 | } // end pragma omp parallel | 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 | // Restore energy dispersion flag for all CTA observations | 406 | // Restore energy dispersion flag for all CTA observations |
| 352 | for (int i = 0; i < m_obs.size(); ++i) { | 407 | for (int i = 0; i < m_obs.size(); ++i) { |
| @@ -409,6 +464,142 @@ void ctobssim::save(void) | @@ -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 | * @brief Get application parameters | 603 | * @brief Get application parameters |
| 413 | * | 604 | * |
| 414 | * Get all task parameters from parameter file or (if required) by querying | 605 | * Get all task parameters from parameter file or (if required) by querying |
| @@ -473,6 +664,16 @@ void ctobssim::get_parameters(void) | @@ -473,6 +664,16 @@ void ctobssim::get_parameters(void) | ||
| 473 | m_prefix = (*this)["prefix"].string(); | 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 | // Initialise random number generators. We initialise here one random | 677 | // Initialise random number generators. We initialise here one random |
| 477 | // number generator per observation so that each observation will | 678 | // number generator per observation so that each observation will |
| 478 | // get it's own random number generator. This will lead to identical | 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& models, | @@ -624,21 +825,17 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models, | ||
| 624 | } | 825 | } |
| 625 | 826 | ||
| 626 | // Get CTA response | 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 | if (rsp == NULL) { | 830 | if (rsp == NULL) { |
| 629 | std::string msg = "Response is not an IRF response.\n" + | 831 | std::string msg = "Response is not an IRF response.\n" + |
| 630 | obs->response()->print(); | 832 | obs->response()->print(); |
| 631 | throw GException::invalid_value(G_SIMULATE_SOURCE, msg); | 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 | // Get pointer on event list (circumvent const correctness) | 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 | // Extract simulation region. | 840 | // Extract simulation region. |
| 644 | GSkyDir dir = events->roi().centre().dir(); | 841 | GSkyDir dir = events->roi().centre().dir(); |
| @@ -898,7 +1095,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models, | @@ -898,7 +1095,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models, | ||
| 898 | ***************************************************************************/ | 1095 | ***************************************************************************/ |
| 899 | void ctobssim::simulate_background(GCTAObservation* obs, | 1096 | void ctobssim::simulate_background(GCTAObservation* obs, |
| 900 | const GModels& models, | 1097 | const GModels& models, |
| 901 | - GRan& ran, | 1098 | + GRan& ran, |
| 902 | GLog* wrklog) | 1099 | GLog* wrklog) |
| 903 | { | 1100 | { |
| 904 | // Continue only if observation pointer is valid | 1101 | // Continue only if observation pointer is valid |
| @@ -909,12 +1106,6 @@ void ctobssim::simulate_background(GCTAObservation* obs, | @@ -909,12 +1106,6 @@ void ctobssim::simulate_background(GCTAObservation* obs, | ||
| 909 | wrklog = &log; | 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 | // Get pointer on event list (circumvent const correctness) | 1109 | // Get pointer on event list (circumvent const correctness) |
| 919 | GCTAEventList* events = | 1110 | GCTAEventList* events = |
| 920 | static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); | 1111 | static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); |
| @@ -934,7 +1125,7 @@ void ctobssim::simulate_background(GCTAObservation* obs, | @@ -934,7 +1125,7 @@ void ctobssim::simulate_background(GCTAObservation* obs, | ||
| 934 | // Get simulated CTA event list. Note that this method | 1125 | // Get simulated CTA event list. Note that this method |
| 935 | // includes the deadtime correction. | 1126 | // includes the deadtime correction. |
| 936 | GCTAEventList* list = | 1127 | GCTAEventList* list = |
| 937 | - dynamic_cast<GCTAEventList*>(model->mc(*obs, ran)); | 1128 | + dynamic_cast<GCTAEventList*>(model->mc(*obs, ran)); |
| 938 | 1129 | ||
| 939 | // Continue only if we got a CTA event list | 1130 | // Continue only if we got a CTA event list |
| 940 | if (list != NULL) { | 1131 | if (list != NULL) { |
| @@ -984,103 +1175,6 @@ void ctobssim::simulate_background(GCTAObservation* obs, | @@ -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 | * @brief Save event list in FITS format. | 1179 | * @brief Save event list in FITS format. |
| 1086 | * | 1180 | * |
| @@ -1089,14 +1183,19 @@ void ctobssim::free_members(void) | @@ -1089,14 +1183,19 @@ void ctobssim::free_members(void) | ||
| 1089 | ***************************************************************************/ | 1183 | ***************************************************************************/ |
| 1090 | void ctobssim::save_fits(void) | 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 | // Return | 1200 | // Return |
| 1102 | return; | 1201 | return; |
| @@ -1131,34 +1230,37 @@ void ctobssim::save_xml(void) | @@ -1131,34 +1230,37 @@ void ctobssim::save_xml(void) | ||
| 1131 | " definition files." << std::endl; | 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 | // Save observations in XML file | 1265 | // Save observations in XML file |
| 1164 | m_obs.save(m_outfile); | 1266 | m_obs.save(m_outfile); |
src/ctobssim/ctobssim.hpp
| @@ -101,25 +101,14 @@ protected: | @@ -101,25 +101,14 @@ protected: | ||
| 101 | double m_deadc; //!< Average deadtime correction | 101 | double m_deadc; //!< Average deadtime correction |
| 102 | 102 | ||
| 103 | // Protected members | 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 | #endif /* CTOBSSIM_HPP */ | 114 | #endif /* CTOBSSIM_HPP */ |