Commit cd21731005495d04311938244f29acbe07a08bca

Authored by knodlseder
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.
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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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)
... ...