Commit 63ac93b6bbc5ba74a838d9b9fca9f7e13545051a

Authored by Jürgen Knödlseder
1 parent e93ed906

Correctly take RoI and livetime variations in background computation into account.

The background models are now livetime weighted before addition, and only event bins are filled that fall within the RoI of the corresponding event list.
src/ctbkgcube/ctbkgcube.cpp
... ... @@ -37,6 +37,7 @@
37 37 #define G_GET_OBS "ctbkgcube::get_obs()"
38 38 #define G_GET_EBOUNDS "ctbkgcube::get_ebounds()"
39 39 #define G_SET_FROM_CNTMAP "ctbkgcube::set_from_cntmap(std::string&)"
  40 +#define G_FILL_CUBE "ctbkgcube::fill_cube(GCTAObservation*)"
40 41  
41 42 /* __ Debug definitions __________________________________________________ */
42 43  
... ... @@ -239,6 +240,9 @@ void ctbkgcube::run(void)
239 240 log.cout(true);
240 241 }
241 242  
  243 + // Initialise run parameters
  244 + m_livetime = 0.0;
  245 +
242 246 // Get task parameters
243 247 get_parameters();
244 248  
... ... @@ -353,6 +357,19 @@ void ctbkgcube::run(void)
353 357  
354 358 } // endfor: looped over observations
355 359  
  360 + // Re-normalize cube to get units of counts/MeV/s/sr
  361 + if (m_livetime > 0.0) {
  362 +
  363 + // Loop over all bins in background cube and divide the content
  364 + // by the total livetime.
  365 + for (int i = 0; i < m_bkgcube.size(); ++i) {
  366 + GCTAEventBin* bin = m_bkgcube[i];
  367 + double rate = bin->counts() / m_livetime;
  368 + bin->counts(rate);
  369 + }
  370 +
  371 + } // endif: livetime was positive
  372 +
356 373 // Log results
357 374 if (logTerse()) {
358 375 log << gammalib::parformat("Number of observations");
... ... @@ -365,58 +382,6 @@ void ctbkgcube::run(void)
365 382  
366 383  
367 384 /***********************************************************************//**
368   - * @brief Generate background cube
369   - *
370   - * @param[in] obs Pointer to CTA observation.
371   - *
372   - * Fills
373   - ***************************************************************************/
374   -void ctbkgcube::fill_cube(GCTAObservation* obs)
375   -{
376   - // Continue only if observation pointer is valid
377   - if (obs != NULL) {
378   -
379   - // Initialise statistics
380   - double sum = 0.0;
381   -
382   - // Set GTI of actual observations as the GTI of the event cube
383   - m_bkgcube.gti(obs->events()->gti());
384   -
385   - // Loop over all bins in background cube
386   - for (int i = 0; i < m_bkgcube.size(); ++i) {
387   -
388   - // Get event bin
389   - GCTAEventBin* bin = m_bkgcube[i];
390   -
391   - // Compute model value for event bin
392   - double model =
393   - m_bkgmdl.eval(*(const_cast<const GCTAEventBin*>(bin)), *obs) *
394   - bin->size();
395   -
396   - // Add existing number of counts
397   - model += bin->counts();
398   -
399   - // Store cumulated value
400   - bin->counts(model);
401   -
402   - // Sum all events
403   - sum += model;
404   - }
405   -
406   - // Log results
407   - if (logTerse()) {
408   - log << gammalib::parformat("Background events in cube");
409   - log << sum << std::endl;
410   - }
411   -
412   - } // endif: observation pointer was not valid
413   -
414   - // Return
415   - return;
416   -}
417   -
418   -
419   -/***********************************************************************//**
420 385 * @brief Save background cube
421 386 *
422 387 * Save the background cube into the file specified by the outfile parameter.
... ... @@ -455,6 +420,68 @@ void ctbkgcube::save(void)
455 420 }
456 421  
457 422  
  423 +/*==========================================================================
  424 + = =
  425 + = Private methods =
  426 + = =
  427 + ==========================================================================*/
  428 +
  429 +/***********************************************************************//**
  430 + * @brief Initialise class members
  431 + ***************************************************************************/
  432 +void ctbkgcube::init_members(void)
  433 +{
  434 + // Initialise members
  435 + m_read_ahead = false;
  436 + m_obs.clear();
  437 + m_bkgcube.clear();
  438 + m_bkgmdl.clear();
  439 + m_ebounds.clear();
  440 + m_livetime = 0.0;
  441 +
  442 + // Set logger properties
  443 + log.date(true);
  444 +
  445 + // Return
  446 + return;
  447 +}
  448 +
  449 +
  450 +/***********************************************************************//**
  451 + * @brief Copy class members
  452 + *
  453 + * @param[in] app Application.
  454 + ***************************************************************************/
  455 +void ctbkgcube::copy_members(const ctbkgcube& app)
  456 +{
  457 + // Copy members
  458 + m_read_ahead = app.m_read_ahead;
  459 + m_obs = app.m_obs;
  460 + m_bkgcube = app.m_bkgcube;
  461 + m_bkgmdl = app.m_bkgmdl;
  462 + m_ebounds = app.m_ebounds;
  463 + m_livetime = app.m_livetime;
  464 +
  465 + // Return
  466 + return;
  467 +}
  468 +
  469 +
  470 +/***********************************************************************//**
  471 + * @brief Delete class members
  472 + ***************************************************************************/
  473 +void ctbkgcube::free_members(void)
  474 +{
  475 + // Write separator into logger
  476 + if (logTerse()) {
  477 + log << std::endl;
  478 + }
  479 +
  480 + // Return
  481 + return;
  482 +}
  483 +
  484 +
458 485 /***********************************************************************//**
459 486 * @brief Get application parameters
460 487 *
... ... @@ -735,60 +762,100 @@ void ctbkgcube::set_from_cntmap(const std::string&amp; filename)
735 762 }
736 763  
737 764  
738   -/*==========================================================================
739   - = =
740   - = Private methods =
741   - = =
742   - ==========================================================================*/
743   -
744 765 /***********************************************************************//**
745   - * @brief Initialise class members
  766 + * @brief Generate background cube
  767 + *
  768 + * @param[in] obs Pointer to CTA observation.
  769 + *
  770 + * @exception GException::invalid_value
  771 + * No event list found in CTA observation.
  772 + *
  773 + * Fills the background cube with the model value for a CTA observation.
746 774 ***************************************************************************/
747   -void ctbkgcube::init_members(void)
  775 +void ctbkgcube::fill_cube(GCTAObservation* obs)
748 776 {
749   - // Initialise members
750   - m_read_ahead = false;
751   - m_obs.clear();
752   - m_bkgcube.clear();
753   - m_bkgmdl.clear();
754   - m_ebounds.clear();
  777 + // Continue only if observation pointer is valid
  778 + if (obs != NULL) {
755 779  
756   - // Set logger properties
757   - log.date(true);
  780 + // Initialise statistics
  781 + double sum = 0.0;
  782 + int n_bins_inside = 0;
  783 + int n_bins_outside = 0;
  784 +
  785 + // Extract region of interest from CTA observation
  786 + const GCTAEventList* list = dynamic_cast<const GCTAEventList*>(obs->events());
  787 + if (list == NULL) {
  788 + std::string msg = "CTA Observation does not contain an event "
  789 + "list. Event list information is needed to "
  790 + "retrieve the Region of Interest for each "
  791 + "CTA observation. Please profile an event list "
  792 + "or an observation definition file containing "
  793 + "event lists as \"infile\" parameter.";
  794 + throw GException::invalid_value(G_FILL_CUBE, msg);
  795 + }
  796 + const GCTARoi& roi = list->roi();
758 797  
759   - // Return
760   - return;
761   -}
  798 + // Set GTI of actual observations as the GTI of the event cube
  799 + m_bkgcube.gti(obs->events()->gti());
762 800  
  801 + // Get observation livetime
  802 + double livetime = obs->livetime();
763 803  
764   -/***********************************************************************//**
765   - * @brief Copy class members
766   - *
767   - * @param[in] app Application.
768   - ***************************************************************************/
769   -void ctbkgcube::copy_members(const ctbkgcube& app)
770   -{
771   - // Copy members
772   - m_read_ahead = app.m_read_ahead;
773   - m_obs = app.m_obs;
774   - m_bkgcube = app.m_bkgcube;
775   - m_bkgmdl = app.m_bkgmdl;
776   - m_ebounds = app.m_ebounds;
  804 + // Loop over all bins in background cube
  805 + for (int i = 0; i < m_bkgcube.size(); ++i) {
777 806  
778   - // Return
779   - return;
780   -}
  807 + // Get event bin
  808 + GCTAEventBin* bin = m_bkgcube[i];
781 809  
  810 + // Continue only if binned in contained in ROI
  811 + if (roi.contains(*bin)) {
  812 +
  813 + // Compute model value for event bin. The model value is
  814 + // given in counts/MeV/s/sr.
  815 + double model = m_bkgmdl.eval(*bin, *obs);
782 816  
783   -/***********************************************************************//**
784   - * @brief Delete class members
785   - ***************************************************************************/
786   -void ctbkgcube::free_members(void)
787   -{
788   - // Write separator into logger
789   - if (logTerse()) {
790   - log << std::endl;
791   - }
  817 + // Compute number events
  818 + sum += model * bin->size();
  819 +
  820 + // Multiply by livetime to get the correct weighting for
  821 + // each observation. We divide by the total livetime later
  822 + // to get the background model in units of counts/MeV/s/sr.
  823 + model *= livetime;
  824 +
  825 + // Add existing number of counts
  826 + model += bin->counts();
  827 +
  828 + // Store cumulated value (units: counts/MeV/sr)
  829 + bin->counts(model);
  830 +
  831 + // Increment contained bin counter
  832 + n_bins_inside++;
  833 +
  834 + } // endif: bin was contained in RoI
  835 +
  836 + // ... otherwise count bin as an outsider
  837 + else {
  838 + n_bins_outside++;
  839 + }
  840 +
  841 + } // endfor: looped over all bins
  842 +
  843 + // Accumulate livetime
  844 + m_livetime += livetime;
  845 +
  846 + // Log results
  847 + if (logTerse()) {
  848 + log << gammalib::parformat("Bins within RoI");
  849 + log << n_bins_inside << std::endl;
  850 + log << gammalib::parformat("Bins outside RoI");
  851 + log << n_bins_outside << std::endl;
  852 + log << gammalib::parformat("Background events in cube");
  853 + log << sum << std::endl;
  854 + log << gammalib::parformat("Cube livetime");
  855 + log << livetime << " sec" << std::endl;
  856 + }
  857 +
  858 + } // endif: observation pointer was not valid
792 859  
793 860 // Return
794 861 return;
... ...
src/ctbkgcube/ctbkgcube.hpp
... ... @@ -59,18 +59,18 @@ public:
59 59 void execute(void);
60 60 void run(void);
61 61 void save(void);
62   - const GObservations& obs(void) const;
63   - void get_parameters(void);
64   - void get_obs(void);
65   - void get_ebounds(void);
66   - void set_from_cntmap(const std::string& filename);
67   - void fill_cube(GCTAObservation* obs);
  62 + const GCTAEventCube& cube(void) const;
68 63  
69 64 protected:
70 65 // Protected methods
71 66 void init_members(void);
72 67 void copy_members(const ctbkgcube& app);
73 68 void free_members(void);
  69 + void get_parameters(void);
  70 + void get_obs(void);
  71 + void get_ebounds(void);
  72 + void set_from_cntmap(const std::string& filename);
  73 + void fill_cube(GCTAObservation* obs);
74 74  
75 75 // Protected members
76 76 bool m_read_ahead; //!< Read ahead parameters
... ... @@ -78,19 +78,20 @@ protected:
78 78 GCTAEventCube m_bkgcube; //!< Background cube
79 79 GModels m_bkgmdl; //!< CTA background models
80 80 GEbounds m_ebounds; //!< Energy boundaries
  81 + double m_livetime; //!< Total livetime for normalization
81 82 };
82 83  
83 84  
84 85 /***********************************************************************//**
85   - * @brief Return observation container
  86 + * @brief Return CTA event cube containing background rate
86 87 *
87   - * @return Observation container.
  88 + * @return CTA event cube.
88 89 ***************************************************************************/
89 90 inline
90   -const GObservations& ctbkgcube::obs(void) const
  91 +const GCTAEventCube& ctbkgcube::cube(void) const
91 92 {
92   - // Return observation container
93   - return m_obs;
  93 + // Return background cube
  94 + return (m_bkgcube);
94 95 }
95 96  
96 97 #endif /* CTBKGCUBE_HPP */
... ...
src/ctbkgcube/ctbkgcube.par
... ... @@ -17,7 +17,7 @@
17 17 #
18 18 # General parameters
19 19 #===================
20   -infile, f, a, "NONE",,, "Event list, counts cube or observation definition file"
  20 +infile, f, a, "NONE",,, "Event list or observation definition file"
21 21 bkgmdl, f, a, "NONE",,, "Background model XML file"
22 22 cntmap, f, a, "NONE",,, "Counts cube for background cube definition"
23 23 outfile, f, a, "bkgcube.fits",,, "Output background cube file"
... ...