Commit 9dc8a8dd5a2df5ff6033c4fb799611d258f20095

Authored by Jürgen Knödlseder
1 parent 964b56a9

Multiply map values with solid angle in GResponse::irf_diffuse()

Showing 1 changed file with 96 additions and 28 deletions
src/obs/GResponse.cpp
... ... @@ -693,12 +693,13 @@ double GResponse::irf_elliptical(const GEvent& event,
693 693 * source and observation. The method computes
694 694 *
695 695 * \f[
696   - * {\tt irf}(p', E', t') = \sum_p M_{\rm S}(p | E, t) \,
  696 + * {\tt irf}(p', E', t') = \sum_p M_{\rm S}(p | E, t) \, \Delta(p)
697 697 * R(p', E', t' | p, E, t)
698 698 * \f]
699 699 *
700 700 * where
701 701 * * \f$M_{\rm S}(p | E, t)\f$ is the diffuse model component,
  702 + * * \f$\Delta(p)\f$ is the solid angle of the map pixel
702 703 * * \f$R(p', E', t' | p, E, t)\f$ is the Instrument Response Function (IRF),
703 704 * * \f$p'\f$ is the measured instrument direction,
704 705 * * \f$E'\f$ is the measured or reconstructed energy,
... ... @@ -720,56 +721,123 @@ double GResponse::irf_diffuse(const GEvent& event,
720 721 // Initialise IRF
721 722 double irf = 0.0;
722 723  
  724 + // Get source attributes
  725 + const GEnergy& srcEng = source.energy();
  726 + const GTime& srcTime = source.time();
  727 +
723 728 // Initialise map
724   - GSkyMap skymap;
  729 + //GSkyMap skymap;
725 730  
726 731 // If model is a diffuse map model then extract sky map
727 732 const GModelSpatialDiffuseMap* map =
728 733 dynamic_cast<const GModelSpatialDiffuseMap*>(source.model());
729 734 if (map != NULL) {
730   - skymap = map->map();
731   - }
  735 +
  736 + // Get reference to sky map
  737 + const GSkyMap& skymap = map->map();
  738 +
  739 + // Loop over all sky map pixels
  740 + for (int i = 0; i < skymap.npix(); ++i) {
  741 +
  742 + // Get map value
  743 + double value = skymap(i);
  744 +
  745 + // Go to next pixel if map value is not positive
  746 + if (value <= 0.0) {
  747 + continue;
  748 + }
  749 +
  750 + // Get sky direction
  751 + GSkyDir srcDir = skymap.inx2dir(i);
  752 +
  753 + // Setup photon
  754 + GPhoton photon(srcDir, srcEng, srcTime);
  755 +
  756 + // Add IRF multiplied by flux in map pixel. Since the map value
  757 + // is per steradian we have to multiply with the solid angle of
  758 + // the map pixel
  759 + irf += this->irf(event, photon, obs) * value * skymap.solidangle(i);
  760 +
  761 + } // endfor: looped over all sky map pixels
  762 +
  763 + } // endif: model was diffuse map
732 764  
733 765 // ... otherwise if model is a cube map model then extract sky map
734 766 else {
735 767 const GModelSpatialDiffuseCube* cube =
736 768 dynamic_cast<const GModelSpatialDiffuseCube*>(source.model());
737 769 if (cube != NULL) {
738   - skymap = cube->cube();
739   - }
  770 +
  771 + // Get reference to sky cube
  772 + const GSkyMap& skymap = cube->cube();
  773 +
  774 + // Loop over all sky map pixels
  775 + for (int i = 0; i < skymap.npix(); ++i) {
  776 +
  777 + // Get sky direction
  778 + GSkyDir srcDir = skymap.inx2dir(i);
  779 +
  780 + // Setup photon
  781 + GPhoton photon(srcDir, srcEng, srcTime);
  782 +
  783 + // Get map value
  784 + double value = cube->eval(photon);
  785 +
  786 + // Go to next pixel if map value is not positive
  787 + if (value <= 0.0) {
  788 + continue;
  789 + }
  790 +
  791 + // Add IRF multiplied by flux in map pixel. Since the map
  792 + // value is per steradian we have to multiply with the solid
  793 + // angle of the map pixel
  794 + irf += this->irf(event, photon, obs) * value * skymap.solidangle(i);
  795 +
  796 + } // endfor: looped over all sky map pixels
  797 +
  798 + } // endelse: model was diffuse cube
740 799  
741 800 // ... otherwise allocate all sky map with specified resolution
742 801 else {
743   - int nx = int(360.0/m_irf_diffuse_resolution + 0.5);
744   - int ny = int(180.0/m_irf_diffuse_resolution + 0.5);
745   - double dx = 360.0 / double(nx);
746   - double dy = 180.0 / double(ny);
747   - skymap = GSkyMap("CAR", "CEL", 0.0, 0.0, -dx, dy, nx, ny);
748   - }
749 802  
750   - } // endelse: model was not a diffuse map
  803 + // Allocate sky map
  804 + int nx = int(360.0/m_irf_diffuse_resolution + 0.5);
  805 + int ny = int(180.0/m_irf_diffuse_resolution + 0.5);
  806 + double dx = 360.0 / double(nx);
  807 + double dy = 180.0 / double(ny);
  808 + GSkyMap skymap = GSkyMap("CAR", "CEL", 0.0, 0.0, -dx, dy, nx, ny);
751 809  
752   - // Get pointer to diffuse model
753   - const GModelSpatialDiffuse* model =
754   - static_cast<const GModelSpatialDiffuse*>(source.model());
  810 + // Get pointer to diffuse model
  811 + const GModelSpatialDiffuse* model =
  812 + static_cast<const GModelSpatialDiffuse*>(source.model());
755 813  
756   - // Get source attributes
757   - const GEnergy& srcEng = source.energy();
758   - const GTime& srcTime = source.time();
  814 + // Loop over all sky map pixels
  815 + for (int i = 0; i < skymap.npix(); ++i) {
759 816  
760   - // Loop over all sky map pixels
761   - for (int i = 0; i < skymap.npix(); ++i) {
  817 + // Get sky direction
  818 + GSkyDir srcDir = skymap.inx2dir(i);
762 819  
763   - // Get sky direction
764   - GSkyDir srcDir = skymap.inx2dir(i);
  820 + // Setup photon
  821 + GPhoton photon(srcDir, srcEng, srcTime);
765 822  
766   - // Setup photon
767   - GPhoton photon(srcDir, srcEng, srcTime);
  823 + // Get model value
  824 + double value = model->eval(photon);
768 825  
769   - // Add IRF for photon
770   - irf += this->irf(event, photon, obs) * model->eval(photon);
  826 + // Go to next pixel if map value is not positive
  827 + if (value <= 0.0) {
  828 + continue;
  829 + }
771 830  
772   - }
  831 + // Add IRF multiplied by flux in map pixel. Since the map
  832 + // value is per steradian we have to multiply with the solid
  833 + // angle of the map pixel
  834 + irf += this->irf(event, photon, obs) * value * skymap.solidangle(i);
  835 +
  836 + } // endfor: looped over sky map pixels
  837 +
  838 + } // endelse: model was not a cube
  839 +
  840 + } // endelse: model was not a map
773 841  
774 842 // Return IRF value
775 843 return irf;
... ...