Commit 868ff9dfb74e1ff2a12dfed3b28c2e808039b903

Authored by Jürgen Knödlseder
1 parent e5c33747

Energy dispersion integration is now done in log10 MeV (#2704)

include/GResponse.hpp
1 1 /***************************************************************************
2 2 * GResponse.hpp - Abstract response base class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2008-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2008-2018 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -127,7 +127,7 @@ protected:
127 127 m_event(event),
128 128 m_srcTime(srcTime),
129 129 m_grad(grad) { }
130   - double eval(const double& x);
  130 + double eval(const double& logEsrc);
131 131 protected:
132 132 const GResponse* m_parent; //!< Response
133 133 const GObservation* m_obs; //!< Observation
... ...
src/obs/GResponse.cpp
1 1 /***************************************************************************
2 2 * GResponse.cpp - Abstract response base class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2008-2016 by Juergen Knoedlseder *
  4 + * copyright (C) 2008-2018 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -57,6 +57,7 @@
57 57 /* __ Coding definitions _________________________________________________ */
58 58  
59 59 /* __ Debug definitions __________________________________________________ */
  60 +#define G_DEBUG_CONVOLVE_EDISP //!< Debug convolve for energy dispersion
60 61  
61 62  
62 63 /*==========================================================================
... ... @@ -194,12 +195,12 @@ double GResponse::convolve(const GModelSky&amp; model,
194 195 // Loop over all boundaries
195 196 for (int i = 0; i < ebounds.size(); ++i) {
196 197  
197   - // Get boundaries in MeV
198   - double emin = ebounds.emin(i).MeV();
199   - double emax = ebounds.emax(i).MeV();
  198 + // Get true energy boundaries in log10 MeV
  199 + double log10_etrue_min = ebounds.emin(i).log10MeV();
  200 + double log10_etrue_max = ebounds.emax(i).log10MeV();
200 201  
201 202 // Continue only if valid
202   - if (emax > emin) {
  203 + if (log10_etrue_max > log10_etrue_min) {
203 204  
204 205 // Setup integration function
205 206 edisp_kern integrand(this, &obs, &model, &event, srcTime, grad);
... ... @@ -209,10 +210,8 @@ double GResponse::convolve(const GModelSky&amp; model,
209 210 integral.fixed_iter(iter);
210 211  
211 212 // Do Romberg integration
212   - emin = std::log(emin);
213   - emax = std::log(emax);
214   - prob += integral.romberg(emin, emax);
215   -
  213 + prob += integral.romberg(log10_etrue_min, log10_etrue_max);
  214 +
216 215 } // endif: interval was valid
217 216  
218 217 } // endfor: looped over intervals
... ... @@ -221,7 +220,7 @@ double GResponse::convolve(const GModelSky&amp; model,
221 220  
222 221 // Case B: No integration (assume no energy dispersion)
223 222 else {
224   -
  223 +
225 224 // Get source energy (no dispersion)
226 225 GEnergy srcEng = event.energy();
227 226  
... ... @@ -410,39 +409,34 @@ double GResponse::eval_prob(const GModelSky&amp; model,
410 409  
411 410  
412 411 /***********************************************************************//**
413   - * @brief Integration kernel for edisp_kern() method
  412 + * @brief Integration kernel for GResponse::edisp_kern() class
414 413 *
415   - * @param[in] x Function value.
  414 + * @param[in] logEsrc Base 10 logarithm of true photon energy in MeV.
416 415 *
417   - * This method implements the integration kernel needed for the edisp_kern()
418   - * method.
  416 + * This method implements the integration kernel needed for the
  417 + * GResponse::edisp_kern() class.
419 418 ***************************************************************************/
420   -double GResponse::edisp_kern::eval(const double& x)
  419 +double GResponse::edisp_kern::eval(const double& logEsrc)
421 420 {
422   - // Set energy
423   - GEnergy eng;
424   - double expx = std::exp(x);
425   - eng.MeV(expx);
  421 + // Set true energy
  422 + GEnergy srcEng;
  423 + srcEng.log10MeV(logEsrc);
426 424  
427 425 // Get function value
428   - double value = m_parent->eval_prob(*m_model, *m_event, eng, m_srcTime, *m_obs, m_grad);
429   -
430   - // Save value if needed
431   - #if defined(G_NAN_CHECK)
432   - double value_out = value;
433   - #endif
  426 + double value = m_parent->eval_prob(*m_model, *m_event,
  427 + srcEng, m_srcTime, *m_obs, m_grad);
434 428  
435   - // Correct for variable substitution
436   - value *= expx;
  429 + // Account for the fact that integration is done in log10 MeV and
  430 + // not in MeV
  431 + value *= gammalib::ln10 * m_event->energy().MeV();
437 432  
438 433 // Compile option: Check for NaN
439 434 #if defined(G_NAN_CHECK)
440 435 if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
441 436 std::cout << "*** ERROR: GResponse::edisp_kern::eval";
442   - std::cout << "(x=" << x << "): ";
  437 + std::cout << "(logEsrc=" << logEsrc << "): ";
443 438 std::cout << " NaN/Inf encountered";
444   - std::cout << " (value=" << value_out;
445   - std::cout << " exp(x)=" << expx;
  439 + std::cout << " (value=" << value;
446 440 std::cout << ")" << std::endl;
447 441 }
448 442 #endif
... ...