Commit 63ac93b6bbc5ba74a838d9b9fca9f7e13545051a
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.
Showing
3 changed files
with
176 additions
and
108 deletions
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& 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" | ... | ... |