Commit cd21731005495d04311938244f29acbe07a08bca
1 parent
d33354d2
Implement deadtime correction.
The deadtime is controlled using the deadc parameter. An additional MC process decides whether a photon event or a background event falls within a dead period of the system or not.
Showing
2 changed files
with
122 additions
and
49 deletions
src/ctobssim/ctobssim.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctobssim - CTA observation simulator tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2011 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2011-2012 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -241,20 +241,24 @@ void ctobssim::run(void) |
| 241 | 241 | // Write observation(s) into logger |
| 242 | 242 | if (logTerse()) { |
| 243 | 243 | log << std::endl; |
| 244 | - if (m_obs.size() > 1) | |
| 244 | + if (m_obs.size() > 1) { | |
| 245 | 245 | log.header1("Observations"); |
| 246 | - else | |
| 246 | + } | |
| 247 | + else { | |
| 247 | 248 | log.header1("Observation"); |
| 249 | + } | |
| 248 | 250 | log << m_obs << std::endl; |
| 249 | 251 | } |
| 250 | 252 | |
| 251 | 253 | // Write header |
| 252 | 254 | if (logTerse()) { |
| 253 | 255 | log << std::endl; |
| 254 | - if (m_obs.size() > 1) | |
| 256 | + if (m_obs.size() > 1) { | |
| 255 | 257 | log.header1("Simulate observations"); |
| 256 | - else | |
| 258 | + } | |
| 259 | + else { | |
| 257 | 260 | log.header1("Simulate observation"); |
| 261 | + } | |
| 258 | 262 | } |
| 259 | 263 | |
| 260 | 264 | // Loop over all observation in the container |
| ... | ... | @@ -268,17 +272,15 @@ void ctobssim::run(void) |
| 268 | 272 | |
| 269 | 273 | // Write header for observation |
| 270 | 274 | if (logTerse()) { |
| 271 | - if (obs->name().length() > 1) | |
| 275 | + if (obs->name().length() > 1) { | |
| 272 | 276 | log.header3("Observation "+obs->name()); |
| 273 | - else | |
| 277 | + } | |
| 278 | + else { | |
| 274 | 279 | log.header3("Observation"); |
| 280 | + } | |
| 275 | 281 | } |
| 276 | 282 | |
| 277 | - // Simulate photons | |
| 278 | - //GPhotons photons = simulate_photons(obs, m_obs.models()); | |
| 279 | - | |
| 280 | 283 | // Simulate source events |
| 281 | - //simulate_source(obs, photons); | |
| 282 | 284 | simulate_source(obs, m_obs.models()); |
| 283 | 285 | |
| 284 | 286 | // Simulate source events |
| ... | ... | @@ -297,16 +299,21 @@ void ctobssim::run(void) |
| 297 | 299 | * @brief Save simulated observation |
| 298 | 300 | * |
| 299 | 301 | * This method saves the results. |
| 302 | + * | |
| 303 | + * @todo Implement XML file output in case that on observation list is | |
| 304 | + * provided on input. | |
| 300 | 305 | ***************************************************************************/ |
| 301 | 306 | void ctobssim::save(void) |
| 302 | 307 | { |
| 303 | 308 | // Write header |
| 304 | 309 | if (logTerse()) { |
| 305 | 310 | log << std::endl; |
| 306 | - if (m_obs.size() > 1) | |
| 311 | + if (m_obs.size() > 1) { | |
| 307 | 312 | log.header1("Save observations"); |
| 308 | - else | |
| 313 | + } | |
| 314 | + else { | |
| 309 | 315 | log.header1("Save observation"); |
| 316 | + } | |
| 310 | 317 | } |
| 311 | 318 | |
| 312 | 319 | // Get output filename |
| ... | ... | @@ -325,8 +332,9 @@ void ctobssim::save(void) |
| 325 | 332 | // Set filename. If more than one file will be created an |
| 326 | 333 | // index "_xxx" will be appended. |
| 327 | 334 | std::string filename = m_outfile; |
| 328 | - if (file_num > 0) | |
| 335 | + if (file_num > 0) { | |
| 329 | 336 | filename += "_"+str(file_num); |
| 337 | + } | |
| 330 | 338 | |
| 331 | 339 | // Save file |
| 332 | 340 | obs->save(filename, clobber()); |
| ... | ... | @@ -403,7 +411,13 @@ void ctobssim::get_parameters(void) |
| 403 | 411 | /***********************************************************************//** |
| 404 | 412 | * @brief Set empty CTA event list |
| 405 | 413 | * |
| 406 | - * @param[in] obs Attach empty event list to CTA observation | |
| 414 | + * @param[in] obs CTA observation. | |
| 415 | + * | |
| 416 | + * Attaches an empty event list to CTA observation. The method also sets the | |
| 417 | + * pointing direction using the m_ra and m_dec members, the ROI based on | |
| 418 | + * m_ra, m_dec and m_rad, a single GTI based on m_tmin and m_tmax, and a | |
| 419 | + * single energy boundary based on m_emin and m_emax. The method furthermore | |
| 420 | + * sets the ontime, livetime and deadtime correction factor. | |
| 407 | 421 | ***************************************************************************/ |
| 408 | 422 | void ctobssim::set_list(GCTAObservation* obs) |
| 409 | 423 | { |
| ... | ... | @@ -411,13 +425,14 @@ void ctobssim::set_list(GCTAObservation* obs) |
| 411 | 425 | if (obs != NULL) { |
| 412 | 426 | |
| 413 | 427 | // Get CTA observation parameters |
| 414 | - m_ra = (*this)["ra"].real(); | |
| 415 | - m_dec = (*this)["dec"].real(); | |
| 416 | - m_rad = (*this)["rad"].real(); | |
| 417 | - m_tmin = (*this)["tmin"].real(); | |
| 418 | - m_tmax = (*this)["tmax"].real(); | |
| 419 | - m_emin = (*this)["emin"].real(); | |
| 420 | - m_emax = (*this)["emax"].real(); | |
| 428 | + m_ra = (*this)["ra"].real(); | |
| 429 | + m_dec = (*this)["dec"].real(); | |
| 430 | + m_rad = (*this)["rad"].real(); | |
| 431 | + m_tmin = (*this)["tmin"].real(); | |
| 432 | + m_tmax = (*this)["tmax"].real(); | |
| 433 | + m_emin = (*this)["emin"].real(); | |
| 434 | + m_emax = (*this)["emax"].real(); | |
| 435 | + m_deadc = (*this)["deadc"].real(); | |
| 421 | 436 | |
| 422 | 437 | // Allocate CTA event list |
| 423 | 438 | GCTAEventList events; |
| ... | ... | @@ -458,6 +473,11 @@ void ctobssim::set_list(GCTAObservation* obs) |
| 458 | 473 | |
| 459 | 474 | // Attach event list to CTA observation |
| 460 | 475 | obs->events(&events); |
| 476 | + | |
| 477 | + // Set observation ontime, livetime and deadtime correction factor | |
| 478 | + obs->ontime(gti.ontime()); | |
| 479 | + obs->livetime(gti.ontime()*m_deadc); | |
| 480 | + obs->deadc(m_deadc); | |
| 461 | 481 | |
| 462 | 482 | } // endif: oberservation was valid |
| 463 | 483 | |
| ... | ... | @@ -511,8 +531,9 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models) |
| 511 | 531 | |
| 512 | 532 | // Make sure that the observation holds a CTA event list. If this |
| 513 | 533 | // is not the case then allocate and attach a CTA event list now. |
| 514 | - if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) | |
| 534 | + if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) { | |
| 515 | 535 | set_list(obs); |
| 536 | + } | |
| 516 | 537 | |
| 517 | 538 | // Get pointer on event list (circumvent const correctness) |
| 518 | 539 | GCTAEventList* events = (GCTAEventList*)(obs->events()); |
| ... | ... | @@ -584,15 +605,17 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models) |
| 584 | 605 | GTime tstart = tmin; |
| 585 | 606 | GTime tstop = tstart + m_time_max; |
| 586 | 607 | |
| 587 | - // Initialise cumulative photon counter | |
| 608 | + // Initialise cumulative photon counters | |
| 588 | 609 | int nphotons = 0; |
| 610 | + int ndeadc = 0; | |
| 589 | 611 | |
| 590 | 612 | // Loop over time slices |
| 591 | 613 | while (tstart < tmax) { |
| 592 | 614 | |
| 593 | 615 | // Make sure that tstop <= tmax |
| 594 | - if (tstop > tmax) | |
| 616 | + if (tstop > tmax) { | |
| 595 | 617 | tstop = tmax; |
| 618 | + } | |
| 596 | 619 | |
| 597 | 620 | // Dump time slice |
| 598 | 621 | if (logExplicit()) { |
| ... | ... | @@ -609,17 +632,28 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models) |
| 609 | 632 | emin, emax, |
| 610 | 633 | tstart, tstop, m_ran); |
| 611 | 634 | |
| 612 | - // Bookkeeping of simulated number of photons | |
| 613 | - nphotons += photons.size(); | |
| 614 | - | |
| 615 | 635 | // Simulate events from photons |
| 616 | 636 | for (int i = 0; i < photons.size(); ++i) { |
| 637 | + | |
| 638 | + // Apply deadtime correction | |
| 639 | + if (m_deadc < 1.0) { | |
| 640 | + if (m_ran.uniform() > m_deadc) { | |
| 641 | + ndeadc++; | |
| 642 | + continue; | |
| 643 | + } | |
| 644 | + } | |
| 645 | + | |
| 646 | + // Increment photon counter | |
| 647 | + nphotons++; | |
| 648 | + | |
| 649 | + // Simulate event | |
| 617 | 650 | GCTAEventAtom* event = rsp->mc(m_area, photons[i], *pnt, m_ran); |
| 618 | 651 | if (event != NULL) { |
| 619 | 652 | events->append(*event); |
| 620 | 653 | delete event; |
| 621 | 654 | } |
| 622 | - } | |
| 655 | + | |
| 656 | + } // endfor: looped over events | |
| 623 | 657 | |
| 624 | 658 | // Go to next time slice |
| 625 | 659 | tstart = tstop; |
| ... | ... | @@ -639,13 +673,21 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models) |
| 639 | 673 | if (logNormal()) { |
| 640 | 674 | log << parformat("MC source photons"); |
| 641 | 675 | log << str(nphotons); |
| 642 | - if (model->name().length() > 0) | |
| 676 | + if (model->name().length() > 0) { | |
| 643 | 677 | log << " [" << model->name() << "]"; |
| 678 | + } | |
| 679 | + log << std::endl; | |
| 680 | + log << parformat("MC photons during deadtime"); | |
| 681 | + log << str(ndeadc); | |
| 682 | + if (model->name().length() > 0) { | |
| 683 | + log << " [" << model->name() << "]"; | |
| 684 | + } | |
| 644 | 685 | log << std::endl; |
| 645 | 686 | log << parformat("MC source events"); |
| 646 | 687 | log << str(events->size()); |
| 647 | - if (model->name().length() > 0) | |
| 688 | + if (model->name().length() > 0) { | |
| 648 | 689 | log << " [" << model->name() << "]"; |
| 690 | + } | |
| 649 | 691 | log << std::endl; |
| 650 | 692 | } |
| 651 | 693 | |
| ... | ... | @@ -709,8 +751,9 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels& models) |
| 709 | 751 | |
| 710 | 752 | // Make sure that the observation holds a CTA event list. If this |
| 711 | 753 | // is not the case then allocate and attach a CTA event list now. |
| 712 | - if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) | |
| 754 | + if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) { | |
| 713 | 755 | set_list(obs); |
| 756 | + } | |
| 714 | 757 | |
| 715 | 758 | // Get pointer on event list (circumvent const correctness) |
| 716 | 759 | GCTAEventList* events = (GCTAEventList*)(obs->events()); |
| ... | ... | @@ -731,14 +774,35 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels& models) |
| 731 | 774 | // Reserves space for events |
| 732 | 775 | events->reserve(list->size()+events->size()); |
| 733 | 776 | |
| 777 | + // Initialise event counters | |
| 778 | + int nevents = 0; | |
| 779 | + int ndeadc = 0; | |
| 780 | + | |
| 734 | 781 | // Append events |
| 735 | - for (int k = 0; k < list->size(); k++) | |
| 782 | + for (int k = 0; k < list->size(); k++) { | |
| 783 | + | |
| 784 | + // Apply deadtime correction | |
| 785 | + if (m_deadc < 1.0) { | |
| 786 | + if (m_ran.uniform() > m_deadc) { | |
| 787 | + ndeadc++; | |
| 788 | + continue; | |
| 789 | + } | |
| 790 | + } | |
| 791 | + | |
| 792 | + // Increment background event counter | |
| 793 | + nevents++; | |
| 794 | + | |
| 795 | + // Append event | |
| 736 | 796 | events->append(*((*list)[k])); |
| 737 | 797 | |
| 798 | + } // endfor: looped over all events | |
| 799 | + | |
| 738 | 800 | // Dump simulation results |
| 739 | 801 | if (logNormal()) { |
| 740 | 802 | log << parformat("MC background events"); |
| 741 | - log << str(list->size()) << std::endl; | |
| 803 | + log << str(nevents) << std::endl; | |
| 804 | + log << parformat("MC events during deadtime"); | |
| 805 | + log << str(ndeadc) << std::endl; | |
| 742 | 806 | } |
| 743 | 807 | |
| 744 | 808 | // Free event list |
| ... | ... | @@ -769,23 +833,26 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels& models) |
| 769 | 833 | ***************************************************************************/ |
| 770 | 834 | void ctobssim::init_members(void) |
| 771 | 835 | { |
| 772 | - // Initialise members | |
| 836 | + // Initialise user parameters | |
| 773 | 837 | m_infile.clear(); |
| 774 | 838 | m_outfile.clear(); |
| 775 | 839 | m_caldb.clear(); |
| 776 | 840 | m_irf.clear(); |
| 841 | + m_seed = 1; | |
| 842 | + m_ra = 0.0; | |
| 843 | + m_dec = 0.0; | |
| 844 | + m_rad = 0.0; | |
| 845 | + m_tmin = 0.0; | |
| 846 | + m_tmax = 0.0; | |
| 847 | + m_emin = 0.0; | |
| 848 | + m_emax = 0.0; | |
| 849 | + m_deadc = 1.0; | |
| 850 | + | |
| 851 | + // Initialise protected members | |
| 777 | 852 | m_obs.clear(); |
| 778 | - m_seed = 1; | |
| 779 | - m_ra = 0.0; | |
| 780 | - m_dec = 0.0; | |
| 781 | - m_rad = 0.0; | |
| 782 | - m_tmin = 0.0; | |
| 783 | - m_tmax = 0.0; | |
| 784 | - m_emin = 0.0; | |
| 785 | - m_emax = 0.0; | |
| 786 | 853 | |
| 787 | 854 | // Set fixed parameters |
| 788 | - m_area = 19634954.0 * 1.0e4; //!< pi*(2500^2) m^2 | |
| 855 | + m_area = 19634954.0 * 1.0e4; //!< pi*(2500^2) m^2 | |
| 789 | 856 | m_time_max.met(1800.0); //!< Maximum length of time slice (s) |
| 790 | 857 | |
| 791 | 858 | // Set logger properties |
| ... | ... | @@ -803,12 +870,11 @@ void ctobssim::init_members(void) |
| 803 | 870 | ***************************************************************************/ |
| 804 | 871 | void ctobssim::copy_members(const ctobssim& app) |
| 805 | 872 | { |
| 806 | - // Copy attributes | |
| 873 | + // Copy user parameters | |
| 807 | 874 | m_infile = app.m_infile; |
| 808 | 875 | m_outfile = app.m_outfile; |
| 809 | 876 | m_caldb = app.m_caldb; |
| 810 | 877 | m_irf = app.m_irf; |
| 811 | - m_obs = app.m_obs; | |
| 812 | 878 | m_seed = app.m_seed; |
| 813 | 879 | m_ra = app.m_ra; |
| 814 | 880 | m_dec = app.m_dec; |
| ... | ... | @@ -817,8 +883,13 @@ void ctobssim::copy_members(const ctobssim& app) |
| 817 | 883 | m_tmax = app.m_tmax; |
| 818 | 884 | m_emin = app.m_emin; |
| 819 | 885 | m_emax = app.m_emax; |
| 886 | + m_deadc = app.m_deadc; | |
| 887 | + | |
| 888 | + // Copy protected members | |
| 820 | 889 | m_area = app.m_area; |
| 821 | 890 | m_time_max = app.m_time_max; |
| 891 | + m_ran = app.m_ran; | |
| 892 | + m_obs = app.m_obs; | |
| 822 | 893 | |
| 823 | 894 | // Return |
| 824 | 895 | return; |
| ... | ... | @@ -831,8 +902,9 @@ void ctobssim::copy_members(const ctobssim& app) |
| 831 | 902 | void ctobssim::free_members(void) |
| 832 | 903 | { |
| 833 | 904 | // Write separator into logger |
| 834 | - if (logTerse()) | |
| 905 | + if (logTerse()) { | |
| 835 | 906 | log << std::endl; |
| 907 | + } | |
| 836 | 908 | |
| 837 | 909 | // Return |
| 838 | 910 | return; | ... | ... |
src/ctobssim/ctobssim.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctobssim - CTA observation simulator tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2011 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2011-2012 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -33,7 +33,7 @@ |
| 33 | 33 | |
| 34 | 34 | /* __Definitions _________________________________________________________ */ |
| 35 | 35 | #define CTOBSSIM_NAME "ctobssim" |
| 36 | -#define CTOBSSIM_VERSION "00-03-01" | |
| 36 | +#define CTOBSSIM_VERSION "00-04-00" | |
| 37 | 37 | |
| 38 | 38 | |
| 39 | 39 | /***********************************************************************//** |
| ... | ... | @@ -89,6 +89,7 @@ protected: |
| 89 | 89 | double m_tmax; //!< Stop time (MET) |
| 90 | 90 | double m_emin; //!< Lower energy (TeV) |
| 91 | 91 | double m_emax; //!< Upper energy (TeV) |
| 92 | + double m_deadc; //!< Average deadtime correction | |
| 92 | 93 | |
| 93 | 94 | // Protected members |
| 94 | 95 | double m_area; //!< Surface area for simulation (cm2) | ... | ... |