Commit d47bd257a83c088d35b94d226ae05ae99d9ead0b
1 parent
8321269e
Replace trapezoid rule for energy integration of background template by numerica…
…l integration in ctskymap (#1975)
Showing
4 changed files
with
69 additions
and
32 deletions
ChangeLog
| 1 | -2017-03-18 | 1 | +2017-03-21 |
| 2 | 2 | ||
| 3 | * Version 1.3.0 released | 3 | * Version 1.3.0 released |
| 4 | ======================== | 4 | ======================== |
| 5 | 5 | ||
| 6 | - Take into account RoI in ctskymap (#1975) | 6 | + Take into account RoI in ctskymap and use numerical integration for IRF (#1975) |
| 7 | Set local language to english (#1370) | 7 | Set local language to english (#1370) |
| 8 | Enhance logfile output of csroot2caldb script | 8 | Enhance logfile output of csroot2caldb script |
| 9 | Set default deadc value to 0.98 (CTA has <2% deadtime) | 9 | Set default deadc value to 0.98 (CTA has <2% deadtime) |
NEWS
| 1 | New Features and Important Changes in ctools 1.3.0.dev1 | 1 | New Features and Important Changes in ctools 1.3.0.dev1 |
| 2 | 2 | ||
| 3 | -18 March 2017 | 3 | +21 March 2017 |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | Introduction | 6 | Introduction |
| @@ -53,7 +53,10 @@ None | @@ -53,7 +53,10 @@ None | ||
| 53 | ctskymap - CTA sky mapping | 53 | ctskymap - CTA sky mapping |
| 54 | -------------------------- | 54 | -------------------------- |
| 55 | Any RoI is now taken into account in ctskymap so that if IRF background | 55 | Any RoI is now taken into account in ctskymap so that if IRF background |
| 56 | -subtraction is requested the counts and background maps are coherent | 56 | +subtraction is requested the counts and background maps are coherent. In |
| 57 | +addition, the energy integration over the background template is now done | ||
| 58 | +numerically so that strong variations in the background rate, such as | ||
| 59 | +those occuring close to the threshold, are correctly taken into account | ||
| 57 | (#1975). | 60 | (#1975). |
| 58 | 61 | ||
| 59 | 62 |
src/ctskymap/ctskymap.cpp
| @@ -30,7 +30,6 @@ | @@ -30,7 +30,6 @@ | ||
| 30 | #endif | 30 | #endif |
| 31 | #include <cstdio> | 31 | #include <cstdio> |
| 32 | #include "ctskymap.hpp" | 32 | #include "ctskymap.hpp" |
| 33 | -#include "GTools.hpp" | ||
| 34 | 33 | ||
| 35 | /* __ Method name definitions ____________________________________________ */ | 34 | /* __ Method name definitions ____________________________________________ */ |
| 36 | #define G_INIT_MAP "ctskymap::init_map(GCTAObservation* obs)" | 35 | #define G_INIT_MAP "ctskymap::init_map(GCTAObservation* obs)" |
| @@ -584,7 +583,8 @@ void ctskymap::map_background(GCTAObservation* obs) | @@ -584,7 +583,8 @@ void ctskymap::map_background(GCTAObservation* obs) | ||
| 584 | * No background template available in instrument response function. | 583 | * No background template available in instrument response function. |
| 585 | * | 584 | * |
| 586 | * Estimates the background in the sky map using the IRF template for a given | 585 | * Estimates the background in the sky map using the IRF template for a given |
| 587 | - * observation and adds this estimate to the background sky map. | 586 | + * observation and adds this estimate to the background sky map. The IRF |
| 587 | + * template is integrated numerically in energy. | ||
| 588 | ***************************************************************************/ | 588 | ***************************************************************************/ |
| 589 | void ctskymap::map_background_irf(GCTAObservation* obs) | 589 | void ctskymap::map_background_irf(GCTAObservation* obs) |
| 590 | { | 590 | { |
| @@ -612,24 +612,16 @@ void ctskymap::map_background_irf(GCTAObservation* obs) | @@ -612,24 +612,16 @@ void ctskymap::map_background_irf(GCTAObservation* obs) | ||
| 612 | throw GException::invalid_value(G_BKG_SUBTRACT_IRF, msg); | 612 | throw GException::invalid_value(G_BKG_SUBTRACT_IRF, msg); |
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | - // Setup energy range covered by data | ||
| 616 | - GEnergy emin; | ||
| 617 | - GEnergy emax; | ||
| 618 | - GEbounds ebds; | ||
| 619 | - emin.TeV(m_emin); | ||
| 620 | - emax.TeV(m_emax); | ||
| 621 | - | ||
| 622 | - // Determine number of energy nodes, 20 per decade, at least 10 bins | ||
| 623 | - int nebin = int((emax.log10TeV() - emin.log10TeV()) * 20.0); | ||
| 624 | - if (nebin < 10) { | ||
| 625 | - nebin = 10; | ||
| 626 | - } | 615 | + // Compute natural logarithm of energy range in MeV |
| 616 | + double lnEmin = std::log(m_emin * 1.0e6); | ||
| 617 | + double lnEmax = std::log(m_emax * 1.0e6); | ||
| 627 | 618 | ||
| 628 | // Extract region of interest from observation | 619 | // Extract region of interest from observation |
| 629 | GCTARoi roi = obs->roi(); | 620 | GCTARoi roi = obs->roi(); |
| 630 | 621 | ||
| 631 | - // Setup energy nodes for computation | ||
| 632 | - GEnergies energies(nebin, emin, emax); // More complicated nbins later | 622 | + // Initialise statistics |
| 623 | + int calls = 0; | ||
| 624 | + double total = 0.0; | ||
| 633 | 625 | ||
| 634 | // Loop over all background map pixels | 626 | // Loop over all background map pixels |
| 635 | for (int i = 0; i < m_bkgmap.npix(); ++i) { | 627 | for (int i = 0; i < m_bkgmap.npix(); ++i) { |
| @@ -646,28 +638,57 @@ void ctskymap::map_background_irf(GCTAObservation* obs) | @@ -646,28 +638,57 @@ void ctskymap::map_background_irf(GCTAObservation* obs) | ||
| 646 | continue; | 638 | continue; |
| 647 | } | 639 | } |
| 648 | 640 | ||
| 649 | - // Compute background value for each energy node | ||
| 650 | - std::vector<double> values(energies.size(), 0.0); | ||
| 651 | - for (int k = 0; k < energies.size(); ++k) { | ||
| 652 | - values[k] = (*bkg)(energies[k].log10TeV(), instdir.detx(), | ||
| 653 | - instdir.dety()); | ||
| 654 | - } | 641 | + // Setup integration function |
| 642 | + ctskymap::irf_kern integrand(bkg, &instdir); | ||
| 643 | + GIntegral integral(&integrand); | ||
| 655 | 644 | ||
| 656 | - // Integrate background values according to Trapezoid rule | ||
| 657 | - double value = 0; | ||
| 658 | - for (int k = 1; k < energies.size(); ++k) { | ||
| 659 | - value += 0.5 * (values[k] + values[k-1]) * | ||
| 660 | - (energies[k].MeV() - energies[k-1].MeV()); | ||
| 661 | - } | 645 | + // Set precision (has been carefully adjusted using a test simulation |
| 646 | + // over the energy range 20 GeV - 120 TeV) | ||
| 647 | + integral.eps(1.0e-7); | ||
| 662 | 648 | ||
| 649 | + // Do Romberg integration | ||
| 650 | + double value = integral.romberg(lnEmin, lnEmax); | ||
| 651 | + | ||
| 652 | + // Update number of background function calls | ||
| 653 | + calls += integral.calls(); | ||
| 654 | + | ||
| 663 | // Multiply background rate with livetime and solid angle | 655 | // Multiply background rate with livetime and solid angle |
| 664 | value *= obs->livetime() * m_bkgmap.solidangle(i); | 656 | value *= obs->livetime() * m_bkgmap.solidangle(i); |
| 665 | 657 | ||
| 666 | // Add number of background events to background map | 658 | // Add number of background events to background map |
| 667 | m_bkgmap(i,0) += value; | 659 | m_bkgmap(i,0) += value; |
| 668 | 660 | ||
| 661 | + // Update total number of background events | ||
| 662 | + total += value; | ||
| 663 | + | ||
| 669 | } // endfor: looped over background map pixels | 664 | } // endfor: looped over background map pixels |
| 665 | + | ||
| 666 | + // Log background subtraction results | ||
| 667 | + log_value(NORMAL, "Events in background", int(total+0.5)); | ||
| 668 | + log_value(NORMAL, "Background evaluations", calls); | ||
| 670 | 669 | ||
| 671 | // Return | 670 | // Return |
| 672 | return; | 671 | return; |
| 673 | } | 672 | } |
| 673 | + | ||
| 674 | + | ||
| 675 | +/***********************************************************************//** | ||
| 676 | + * @brief Estimates the background in sky map based on IRF template | ||
| 677 | + * | ||
| 678 | + * @param[in] lnE Natural logarithm of energy in MeV. | ||
| 679 | + ***************************************************************************/ | ||
| 680 | +double ctskymap::irf_kern::eval(const double& lnE) | ||
| 681 | +{ | ||
| 682 | + // Get log10 of energy in TeV | ||
| 683 | + double logE = lnE * gammalib::inv_ln10 - 6; | ||
| 684 | + | ||
| 685 | + // Get function value | ||
| 686 | + double value = (*m_bgd)(logE, m_dir->detx(), m_dir->dety()); | ||
| 687 | + | ||
| 688 | + // Correct for variable substitution | ||
| 689 | + value *= std::exp(lnE); | ||
| 690 | + | ||
| 691 | + // Return value | ||
| 692 | + return value; | ||
| 693 | +} | ||
| 694 | + |
src/ctskymap/ctskymap.hpp
| @@ -73,6 +73,19 @@ protected: | @@ -73,6 +73,19 @@ protected: | ||
| 73 | void map_background(GCTAObservation* obs); | 73 | void map_background(GCTAObservation* obs); |
| 74 | void map_background_irf(GCTAObservation* obs); | 74 | void map_background_irf(GCTAObservation* obs); |
| 75 | 75 | ||
| 76 | + // Background integration kernel | ||
| 77 | + class irf_kern : public GFunction { | ||
| 78 | + public: | ||
| 79 | + irf_kern(const GCTABackground* bgd, | ||
| 80 | + const GCTAInstDir* dir) : | ||
| 81 | + m_bgd(bgd), | ||
| 82 | + m_dir(dir) { } | ||
| 83 | + double eval(const double& lnE); | ||
| 84 | + protected: | ||
| 85 | + const GCTABackground* m_bgd; //!< Pointer to background | ||
| 86 | + const GCTAInstDir* m_dir; //!< Pointer to instrument direction | ||
| 87 | + }; | ||
| 88 | + | ||
| 76 | // User parameters | 89 | // User parameters |
| 77 | GFilename m_outmap; //!< Output file name | 90 | GFilename m_outmap; //!< Output file name |
| 78 | double m_emin; //!< Minimum energy (TeV) | 91 | double m_emin; //!< Minimum energy (TeV) |