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 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 7 Set local language to english (#1370)
8 8 Enhance logfile output of csroot2caldb script
9 9 Set default deadc value to 0.98 (CTA has <2% deadtime)
... ...
1 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 6 Introduction
... ... @@ -53,7 +53,10 @@ None
53 53 ctskymap - CTA sky mapping
54 54 --------------------------
55 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 60 (#1975).
58 61  
59 62  
... ...
src/ctskymap/ctskymap.cpp
... ... @@ -30,7 +30,6 @@
30 30 #endif
31 31 #include <cstdio>
32 32 #include "ctskymap.hpp"
33   -#include "GTools.hpp"
34 33  
35 34 /* __ Method name definitions ____________________________________________ */
36 35 #define G_INIT_MAP "ctskymap::init_map(GCTAObservation* obs)"
... ... @@ -584,7 +583,8 @@ void ctskymap::map_background(GCTAObservation* obs)
584 583 * No background template available in instrument response function.
585 584 *
586 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 589 void ctskymap::map_background_irf(GCTAObservation* obs)
590 590 {
... ... @@ -612,24 +612,16 @@ void ctskymap::map_background_irf(GCTAObservation* obs)
612 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 619 // Extract region of interest from observation
629 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 626 // Loop over all background map pixels
635 627 for (int i = 0; i < m_bkgmap.npix(); ++i) {
... ... @@ -646,28 +638,57 @@ void ctskymap::map_background_irf(GCTAObservation* obs)
646 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 655 // Multiply background rate with livetime and solid angle
664 656 value *= obs->livetime() * m_bkgmap.solidangle(i);
665 657  
666 658 // Add number of background events to background map
667 659 m_bkgmap(i,0) += value;
668 660  
  661 + // Update total number of background events
  662 + total += value;
  663 +
669 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 670 // Return
672 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 73 void map_background(GCTAObservation* obs);
74 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 89 // User parameters
77 90 GFilename m_outmap; //!< Output file name
78 91 double m_emin; //!< Minimum energy (TeV)
... ...