Commit 735726c7829fc612eb17088d964673de00cdf031

Authored by Jürgen Knödlseder
1 parent 2c2465cd

Renormalize H.E.S.S. energy dispersion from linear to dlog10(E_reco)

inst/cta/include/GCTAEdisp2D.hpp
... ... @@ -136,6 +136,7 @@ private:
136 136 void set_boundaries(void);
137 137 void set_max_edisp(void) const;
138 138 void normalize_table(void);
  139 + void hess_renormalization(void);
139 140 int table_index(const int& ietrue,
140 141 const int& imigra,
141 142 const int& itheta) const;
... ...
inst/cta/src/GCTAEdisp2D.cpp
... ... @@ -57,6 +57,7 @@
57 57 //#define G_SMOOTH_EDISP_SAVE_TEST //!< Save test matrix
58 58  
59 59 /* __ Debug definitions __________________________________________________ */
  60 +//#define G_DEBUG_HESS_RENORMALIZATION
60 61  
61 62 /* __ Constants __________________________________________________________ */
62 63  
... ... @@ -1366,6 +1367,11 @@ void GCTAEdisp2D::set_table(void)
1366 1367 // Set table boundaries
1367 1368 set_boundaries();
1368 1369  
  1370 + // Renormalize energy dispersion table for H.E.S.S.
  1371 + if (gammalib::strip_whitespace(m_edisp.telescope()) == "HESS") {
  1372 + hess_renormalization();
  1373 + }
  1374 +
1369 1375 // Smooth energy dispersion table (kludge only for CTA)
1370 1376 #if defined(G_SMOOTH_EDISP_KLUDGE)
1371 1377 if (gammalib::strip_whitespace(m_edisp.telescope()) == "CTA") {
... ... @@ -1373,8 +1379,11 @@ void GCTAEdisp2D::set_table(void)
1373 1379 }
1374 1380 #endif
1375 1381  
1376   - // Normalize energy dispersion table
1377   - normalize_table();
  1382 + // Normalize energy dispersion table (not for H.E.S.S. normalization
  1383 + // since we renormalized the H.E.S.S. data before)
  1384 + if (gammalib::strip_whitespace(m_edisp.telescope()) != "HESS") {
  1385 + normalize_table();
  1386 + }
1378 1387  
1379 1388 // Set maximum energy dispersion value
1380 1389 set_max_edisp();
... ... @@ -1557,6 +1566,106 @@ void GCTAEdisp2D::normalize_table(void)
1557 1566  
1558 1567  
1559 1568 /***********************************************************************//**
  1569 + * @brief Renormalize H.E.S.S. energy dispersion table
  1570 + *
  1571 + * The H.E.S.S. energy dispersion table is normalized so that
  1572 + *
  1573 + * \f[
  1574 + * \int_{{\rm migra}_{\rm min}}^{{\rm migra}_{\rm max}}
  1575 + * E_{\rm disp}({\rm migra}) \, d{\rm migra} = 1
  1576 + * \f]
  1577 + *
  1578 + * while the class needs values that are normalize according to
  1579 + *
  1580 + * \f[
  1581 + * \int_{\log_{10} E_{\rm reco}^{\rm min}}^{\log_{10} E_{\rm reco}^{\rm max}}
  1582 + * E_{\rm disp}(\log_{10} E_{\rm reco}) \, d(\log_{10} E_{\rm reco}) = 1
  1583 + * \f]
  1584 + *
  1585 + * The method thus multiplies each matrix element with
  1586 + *
  1587 + * \f[
  1588 + * \frac{{\rm migra}_{\rm max} - {\rm migra}_{\rm min}}
  1589 + * {\log_{10} E_{\rm reco}^{\rm max} - \log_{10} E_{\rm reco}^{\rm min}}
  1590 + * \f]
  1591 + *
  1592 + * where
  1593 + * \f${\rm migra}_{\rm min}\f$ and \f${\rm migra}_{\rm max}\f$ are the
  1594 + * minimum and maximum migration values of a given bin and
  1595 + * \f$E_{\rm reco}^{\rm min}\f$ and \f$E_{\rm reco}^{\rm max}\f$ are the
  1596 + * minimum and maximum reconstructed energy values for the same bin.
  1597 + ***************************************************************************/
  1598 +void GCTAEdisp2D::hess_renormalization(void)
  1599 +{
  1600 + // Optional dump header
  1601 + #if defined(G_DEBUG_HESS_RENORMALIZATION)
  1602 + std::cout << "GCTAEdisp2D::hess_renormalization:" << std::endl;
  1603 + #endif
  1604 +
  1605 + // Get axes dimensions
  1606 + int etrue_size = m_edisp.axis_bins(m_inx_etrue);
  1607 + int migra_size = m_edisp.axis_bins(m_inx_migra);
  1608 + int theta_size = m_edisp.axis_bins(m_inx_theta);
  1609 +
  1610 + // Perform renormalization
  1611 + for (int i_etrue = 0; i_etrue < etrue_size; ++i_etrue) {
  1612 +
  1613 + // Get true energy in TeV
  1614 + double etrue = std::sqrt(m_edisp.axis_lo(m_inx_etrue, i_etrue) *
  1615 + m_edisp.axis_hi(m_inx_etrue, i_etrue));
  1616 +
  1617 + // Get offset angle
  1618 + for (int i_theta = 0; i_theta < theta_size; ++i_theta) {
  1619 +
  1620 + // Intialize control sum
  1621 + #if defined(G_DEBUG_HESS_RENORMALIZATION)
  1622 + double sum = 0.0;
  1623 + #endif
  1624 +
  1625 + // Loop over all migration bins
  1626 + int offset = table_index(i_etrue, 0, i_theta);
  1627 + int stride = table_stride(m_inx_migra);
  1628 + for (int i_migra = 0, i = offset; i_migra < migra_size; ++i_migra, i += stride) {
  1629 +
  1630 + // Get migration bin size
  1631 + double migra_bin = m_edisp.axis_hi(m_inx_migra, i_migra) -
  1632 + m_edisp.axis_lo(m_inx_migra, i_migra);
  1633 +
  1634 + // Get dlog10(E_reco) bin size
  1635 + double ereco_min = m_edisp.axis_lo(m_inx_migra, i_migra) * etrue;
  1636 + double ereco_max = m_edisp.axis_hi(m_inx_migra, i_migra) * etrue;
  1637 + double dlogE_bin = std::log10(ereco_max) - std::log10(ereco_min);
  1638 +
  1639 + // Compute normalization factor
  1640 + double norm = migra_bin / dlogE_bin;
  1641 +
  1642 + // Multiply matrix element
  1643 + m_edisp(m_inx_matrix, i) *= norm;
  1644 +
  1645 + // Update test sum
  1646 + #if defined(G_DEBUG_HESS_RENORMALIZATION)
  1647 + sum += m_edisp(m_inx_matrix, i) * dlogE_bin;
  1648 + #endif
  1649 +
  1650 + } // endfor: looped over migration bins
  1651 +
  1652 + // Optional test dump
  1653 + #if defined(G_DEBUG_HESS_RENORMALIZATION)
  1654 + std::cout << "etrue=" << etrue << " TeV ";
  1655 + std::cout << "i_theta=" << i_theta << ": ";
  1656 + std::cout << sum << std::endl;
  1657 + #endif
  1658 +
  1659 + } // endfor: looped over offset angle
  1660 +
  1661 + } // endfor: looped over true energies
  1662 +
  1663 + // Return
  1664 + return;
  1665 +}
  1666 +
  1667 +
  1668 +/***********************************************************************//**
1560 1669 * @brief Return index of response table element
1561 1670 *
1562 1671 * @param[in] ietrue True energy index.
... ...
src/obs/GResponse.cpp
... ... @@ -187,10 +187,10 @@ double GResponse::convolve(const GModelSky&amp; model,
187 187  
188 188 // Case A: Integration
189 189 if (use_edisp()) {
190   -
  190 +
191 191 // Retrieve true energy boundaries
192 192 GEbounds ebounds = this->ebounds(event.energy());
193   -
  193 +
194 194 // Loop over all boundaries
195 195 for (int i = 0; i < ebounds.size(); ++i) {
196 196  
... ...