Commit d47bd257a83c088d35b94d226ae05ae99d9ead0b

Authored by Jürgen Knödlseder
1 parent 8321269e

Replace trapezoid rule for energy integration of background template by numerica…

…l integration in ctskymap (#1975)
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)
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)