Commit 647c4d1108d64cfa1dfa37723cbc0f61a1f2184a

Authored by Jürgen Knödlseder
1 parent a9ac5437

GModelSpatialDiffuseCube::set_mc_cone() recomputes MC cache only in case of cone changes.

ChangeLog
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 * Version 1.1.0 released 3 * Version 1.1.0 released
4 ========================= 4 =========================
5 5
  6 + Optimise GModelSpatialDiffuseCube::set_mc_cone() method (#1673)
6 Use default GTime in GObservation::deadc() method (#1670) 7 Use default GTime in GObservation::deadc() method (#1670)
7 The GApplicationPar::filename() methods now take and return GFilename (#1671) 8 The GApplicationPar::filename() methods now take and return GFilename (#1671)
8 Add GFilename methods and remove equivalents from GTools (#1666) 9 Add GFilename methods and remove equivalents from GTools (#1666)
@@ -111,7 +111,10 @@ None @@ -111,7 +111,10 @@ None
111 111
112 8. Model module 112 8. Model module
113 --------------- 113 ---------------
114 -None 114 +The GModelSpatialDiffuseCube::set_mc_cone() method now recomputes only
  115 +the Monte Carlo acceptance cone in case that the cone centre or radius
  116 +have changed since the last computation. This speeds up the computations
  117 +(#1673).
115 118
116 119
117 9. Numerics module 120 9. Numerics module
include/GModelSpatialDiffuseCube.hpp
@@ -130,6 +130,8 @@ protected: @@ -130,6 +130,8 @@ protected:
130 GEbounds m_ebounds; //!< Energy bounds of the maps 130 GEbounds m_ebounds; //!< Energy bounds of the maps
131 131
132 // Monte Carlo cache 132 // Monte Carlo cache
  133 + mutable GSkyDir m_mc_centre; //!< Centre of MC cone
  134 + mutable double m_mc_radius; //!< Radius of MC cone
133 mutable std::vector<double> m_mc_cache; //!< Monte Carlo cache 135 mutable std::vector<double> m_mc_cache; //!< Monte Carlo cache
134 mutable std::vector<double> m_mc_max; //!< Maximum values for MC 136 mutable std::vector<double> m_mc_max; //!< Maximum values for MC
135 mutable GModelSpectralNodes m_mc_spectrum; //!< Map cube spectrum 137 mutable GModelSpectralNodes m_mc_spectrum; //!< Map cube spectrum
src/model/GModelSpatialDiffuseCube.cpp
@@ -782,186 +782,198 @@ GEnergies GModelSpatialDiffuseCube::energies(void) @@ -782,186 +782,198 @@ GEnergies GModelSpatialDiffuseCube::energies(void)
782 void GModelSpatialDiffuseCube::set_mc_cone(const GSkyDir& centre, 782 void GModelSpatialDiffuseCube::set_mc_cone(const GSkyDir& centre,
783 const double& radius) const 783 const double& radius) const
784 { 784 {
785 - // Initialise cache  
786 - m_mc_cache.clear();  
787 - m_mc_max.clear();  
788 - m_mc_spectrum.clear(); 785 + // Continue only if the simulation cone has changed
  786 + if ((centre != m_mc_centre) || (radius != m_mc_radius)) {
789 787
790 - // Fetch cube  
791 - fetch_cube(); 788 + // Save simulation cone definition
  789 + m_mc_centre = centre;
  790 + m_mc_radius = radius;
792 791
793 - // Determine number of cube pixels and maps  
794 - int npix = pixels();  
795 - int nmaps = maps();  
796 -  
797 - // Continue only if there are pixels and maps  
798 - if (npix > 0 && nmaps > 0) {  
799 -  
800 - // Reserve space for all pixels in cache  
801 - m_mc_cache.reserve((npix+1)*nmaps);  
802 - m_mc_max.reserve((npix+1)*nmaps);  
803 - m_mc_spectrum.reserve(nmaps);  
804 -  
805 - // Loop over all maps  
806 - for (int i = 0; i < nmaps; ++i) {  
807 -  
808 - // Compute pixel offset  
809 - int offset = i * (npix+1);  
810 -  
811 - // Set first cache value to 0  
812 - m_mc_cache.push_back(0.0);  
813 -  
814 - // Initialise cache with cumulative pixel fluxes and compute  
815 - // total flux in skymap for normalization. Negative pixels are  
816 - // excluded from the cumulative map.  
817 - double sum = 0.0;  
818 - double sum_map = 0.0;  
819 - for (int k = 0; k < npix; ++k) {  
820 -  
821 - // Derive effective pixel radius from half opening angle  
822 - // that corresponds to the pixel's solid angle. For security,  
823 - // the radius is enhanced by 50%.  
824 - /*  
825 - double pixel_radius =  
826 - std::acos(1.0 - m_cube.solidangle(k)/gammalib::twopi) *  
827 - gammalib::rad2deg * 1.5;  
828 - */  
829 -  
830 - // Add up flux with simulation cone radius + effective pixel  
831 - // radius. The effective pixel radius is added to make sure  
832 - // that all pixels that overlap with the simulation cone are  
833 - // taken into account. There is no problem of having even  
834 - // pixels outside the simulation cone taken into account as  
835 - // long as the mc() method has an explicit test of whether a  
836 - // simulated event is contained in the simulation cone.  
837 - double flux = m_cube.flux(k,i);  
838 - if (flux > 0.0) {  
839 - //double distance = centre.dist_deg(m_cube.pix2dir(k));  
840 - //if (distance <= radius+pixel_radius) {  
841 - sum += flux;  
842 - //}  
843 - sum_map += flux; // sum up total flux in map  
844 - } 792 + // Initialise cache
  793 + m_mc_cache.clear();
  794 + m_mc_max.clear();
  795 + m_mc_spectrum.clear();
845 796
846 - // Push back flux  
847 - m_mc_cache.push_back(sum); // units: ph/cm2/s/MeV  
848 - } 797 + // Fetch cube
  798 + fetch_cube();
849 799
850 - // Normalize cumulative pixel fluxes so that the values in the  
851 - // cache run from 0 to 1  
852 - if (sum > 0.0) {  
853 - for (int k = 0; k < npix; ++k) {  
854 - m_mc_cache[k+offset] /= sum;  
855 - }  
856 - } 800 + // Determine number of cube pixels and maps
  801 + int npix = pixels();
  802 + int nmaps = maps();
  803 +
  804 + // Continue only if there are pixels and maps
  805 + if (npix > 0 && nmaps > 0) {
  806 +
  807 + // Reserve space for all pixels in cache
  808 + m_mc_cache.reserve((npix+1)*nmaps);
  809 + m_mc_max.reserve((npix+1)*nmaps);
  810 + m_mc_spectrum.reserve(nmaps);
  811 +
  812 + // Loop over all maps
  813 + for (int i = 0; i < nmaps; ++i) {
857 814
858 - // Make sure that last pixel in the cache is >1  
859 - m_mc_cache[npix+offset] = 1.0001; 815 + // Compute pixel offset
  816 + int offset = i * (npix+1);
860 817
861 - // Store flux as spectral node  
862 - if (m_logE.size() == nmaps) { 818 + // Set first cache value to 0
  819 + m_mc_cache.push_back(0.0);
863 820
864 - // Compute mean energy  
865 - GEnergy energy;  
866 - energy.log10MeV(m_logE[i]); 821 + // Initialise cache with cumulative pixel fluxes and compute
  822 + // total flux in skymap for normalization. Negative pixels
  823 + // are excluded from the cumulative map.
  824 + double sum = 0.0;
  825 + double sum_map = 0.0;
  826 + for (int k = 0; k < npix; ++k) {
  827 +
  828 + // Derive effective pixel radius from half opening angle
  829 + // that corresponds to the pixel's solid angle. For
  830 + // security, the radius is enhanced by 50%.
  831 + /*
  832 + double pixel_radius =
  833 + std::acos(1.0 - m_cube.solidangle(k)/gammalib::twopi) *
  834 + gammalib::rad2deg * 1.5;
  835 + */
  836 +
  837 + // Add up flux with simulation cone radius + effective
  838 + // pixel radius. The effective pixel radius is added to
  839 + // make sure that all pixels that overlap with the
  840 + // simulation cone are taken into account. There is no
  841 + // problem of having even pixels outside the simulation
  842 + // cone taken into account as long as the mc() method has
  843 + // an explicit test of whether a simulated event is
  844 + // contained in the simulation cone.
  845 + double flux = m_cube.flux(k,i);
  846 + if (flux > 0.0) {
  847 + //double distance = centre.dist_deg(m_cube.pix2dir(k));
  848 + //if (distance <= radius+pixel_radius) {
  849 + sum += flux;
  850 + //}
  851 + sum_map += flux; // sum up total flux in map
  852 + }
867 853
868 - // Only append node if flux > 0 854 + // Push back flux
  855 + m_mc_cache.push_back(sum); // units: ph/cm2/s/MeV
  856 + }
  857 +
  858 + // Normalize cumulative pixel fluxes so that the values in
  859 + // the cache run from 0 to 1
869 if (sum > 0.0) { 860 if (sum > 0.0) {
870 - m_mc_spectrum.append(energy, sum); 861 + for (int k = 0; k < npix; ++k) {
  862 + m_mc_cache[k+offset] /= sum;
  863 + }
871 } 864 }
872 865
873 - } 866 + // Make sure that last pixel in the cache is >1
  867 + m_mc_cache[npix+offset] = 1.0001;
874 868
875 - // Do we have a HealPix map?  
876 - if (m_cube.projection()->code() == "HPX") { 869 + // Store flux as spectral node
  870 + if (m_logE.size() == nmaps) {
877 871
878 - // Get pointer on HealPix projection  
879 - const GHealpix* healpix =  
880 - static_cast<const GHealpix*>(m_cube.projection()); 872 + // Compute mean energy
  873 + GEnergy energy;
  874 + energy.log10MeV(m_logE[i]);
881 875
882 - // Compute maximum value that may occur from bilinear  
883 - // interpolation within this pixel and push this value on the  
884 - // stack. We do this by checking values of all neighbours.  
885 - for (int k = 0; k < npix; ++k) { 876 + // Only append node if flux > 0
  877 + if (sum > 0.0) {
  878 + m_mc_spectrum.append(energy, sum);
  879 + }
886 880
887 - // Get neighbours  
888 - std::vector<int> neighbours = healpix->neighbours(k); 881 + }
889 882
890 - // Loop over neighbours  
891 - double max = m_cube(k,i);  
892 - for (int j = 0; j < neighbours.size(); ++j) {  
893 - if (neighbours[j] != -1) {  
894 - double value = m_cube(neighbours[j],i);  
895 - if (value > max) {  
896 - max = value; 883 + // Do we have a HealPix map?
  884 + if (m_cube.projection()->code() == "HPX") {
  885 +
  886 + // Get pointer on HealPix projection
  887 + const GHealpix* healpix =
  888 + static_cast<const GHealpix*>(m_cube.projection());
  889 +
  890 + // Compute maximum value that may occur from bilinear
  891 + // interpolation within this pixel and push this value
  892 + // on the stack. We do this by checking values of all
  893 + // neighbours.
  894 + for (int k = 0; k < npix; ++k) {
  895 +
  896 + // Get neighbours
  897 + std::vector<int> neighbours = healpix->neighbours(k);
  898 +
  899 + // Loop over neighbours
  900 + double max = m_cube(k,i);
  901 + for (int j = 0; j < neighbours.size(); ++j) {
  902 + if (neighbours[j] != -1) {
  903 + double value = m_cube(neighbours[j],i);
  904 + if (value > max) {
  905 + max = value;
  906 + }
897 } 907 }
898 } 908 }
899 - }  
900 909
901 - // Store maximum  
902 - m_mc_max[k+offset] = max; 910 + // Store maximum
  911 + m_mc_max[k+offset] = max;
903 912
904 - } // endfor: looped over pixels 913 + } // endfor: looped over pixels
905 914
906 - } // endif: Healpix projection 915 + } // endif: Healpix projection
907 916
908 - // ... no, then we have a WCS map  
909 - else { 917 + // ... no, then we have a WCS map
  918 + else {
910 919
911 - // Compute maximum value that may occur from bilinear  
912 - // interpolation within this pixel and push this value on the  
913 - // stack. We do this by checking the map values at the corners  
914 - // and the centre of each edge.  
915 - for (int k = 0; k < npix; ++k) {  
916 - GSkyPixel pixel = m_cube.inx2pix(k);  
917 - double max = m_cube(pixel,i);  
918 - for (int ix = -1; ix < 2; ++ix) {  
919 - for (int iy = -1; iy < 2; ++iy) {  
920 - if (ix != 0 && iy != 0) {  
921 - GSkyPixel edge(pixel.x()+ix*0.5, pixel.y()+iy*0.5);  
922 - if (m_cube.contains(edge)) {  
923 - GSkyDir dir = m_cube.pix2dir(edge);  
924 - double value = m_cube(dir,i);  
925 - if (value > max) {  
926 - max = value; 920 + // Compute maximum value that may occur from bilinear
  921 + // interpolation within this pixel and push this value
  922 + // on the stack. We do this by checking the map values
  923 + // at the corners and the centre of each edge.
  924 + for (int k = 0; k < npix; ++k) {
  925 + GSkyPixel pixel = m_cube.inx2pix(k);
  926 + double max = m_cube(pixel,i);
  927 + for (int ix = -1; ix < 2; ++ix) {
  928 + for (int iy = -1; iy < 2; ++iy) {
  929 + if (ix != 0 && iy != 0) {
  930 + GSkyPixel edge(pixel.x()+ix*0.5, pixel.y()+iy*0.5);
  931 + if (m_cube.contains(edge)) {
  932 + GSkyDir dir = m_cube.pix2dir(edge);
  933 + double value = m_cube(dir,i);
  934 + if (value > max) {
  935 + max = value;
  936 + }
927 } 937 }
928 } 938 }
929 } 939 }
930 } 940 }
  941 + m_mc_max[k+offset] = max;
931 } 942 }
932 - m_mc_max[k+offset] = max;  
933 - }  
934 943
935 - } // endelse: computed maximum pixel value 944 + } // endelse: computed maximum pixel value
936 945
937 - // Make sure that last pixel in the maximum cache has a well defined value  
938 - m_mc_max[npix+offset] = 0.0; 946 + // Make sure that last pixel in the maximum cache has a
  947 + // well defined value
  948 + m_mc_max[npix+offset] = 0.0;
939 949
940 - } // endfor: looped over all maps 950 + } // endfor: looped over all maps
941 951
942 - // Dump cache values for debugging  
943 - #if defined(G_DEBUG_CACHE)  
944 - std::cout << "GModelSpatialDiffuseCube::set_mc_cone: cache";  
945 - std::cout << std::endl;  
946 - for (int i = 0; i < m_mc_cache.size(); ++i) {  
947 - std::cout << "i=" << i;  
948 - std::cout << " cache=" << m_mc_cache[i];  
949 - std::cout << " max=" << m_mc_max[i] << std::endl;  
950 - }  
951 - #endif  
952 -  
953 - // Dump spectrum for debugging  
954 - #if defined(G_DEBUG_CACHE)  
955 - std::cout << "GModelSpatialDiffuseCube::set_mc_cone: spectrum";  
956 - std::cout << std::endl;  
957 - for (int i = 0; i < m_mc_spectrum.nodes(); ++i) {  
958 - std::cout << i;  
959 - std::cout << " " << m_mc_spectrum.energy(i);  
960 - std::cout << " " << m_mc_spectrum.intensity(i) << std::endl;  
961 - }  
962 - #endif 952 + // Dump cache values for debugging
  953 + #if defined(G_DEBUG_CACHE)
  954 + std::cout << "GModelSpatialDiffuseCube::set_mc_cone: cache";
  955 + std::cout << std::endl;
  956 + for (int i = 0; i < m_mc_cache.size(); ++i) {
  957 + std::cout << "i=" << i;
  958 + std::cout << " cache=" << m_mc_cache[i];
  959 + std::cout << " max=" << m_mc_max[i] << std::endl;
  960 + }
  961 + #endif
  962 +
  963 + // Dump spectrum for debugging
  964 + #if defined(G_DEBUG_CACHE)
  965 + std::cout << "GModelSpatialDiffuseCube::set_mc_cone: spectrum";
  966 + std::cout << std::endl;
  967 + for (int i = 0; i < m_mc_spectrum.nodes(); ++i) {
  968 + std::cout << i;
  969 + std::cout << " " << m_mc_spectrum.energy(i);
  970 + std::cout << " " << m_mc_spectrum.intensity(i) << std::endl;
  971 + }
  972 + #endif
  973 +
  974 + } // endif: there were cube pixels and maps
963 975
964 - } // endif: there were cube pixels and maps 976 + } // endif: simulation cone has changed
965 977
966 // Return 978 // Return
967 return; 979 return;
@@ -1155,6 +1167,8 @@ void GModelSpatialDiffuseCube::init_members(void) @@ -1155,6 +1167,8 @@ void GModelSpatialDiffuseCube::init_members(void)
1155 m_loaded = false; 1167 m_loaded = false;
1156 1168
1157 // Initialise MC cache 1169 // Initialise MC cache
  1170 + m_mc_centre.clear();
  1171 + m_mc_radius = -1.0; //!< Signal that initialisation is needed
1158 m_mc_cache.clear(); 1172 m_mc_cache.clear();
1159 m_mc_max.clear(); 1173 m_mc_max.clear();
1160 m_mc_spectrum.clear(); 1174 m_mc_spectrum.clear();
@@ -1180,6 +1194,8 @@ void GModelSpatialDiffuseCube::copy_members(const GModelSpatialDiffuseCube&amp; mode @@ -1180,6 +1194,8 @@ void GModelSpatialDiffuseCube::copy_members(const GModelSpatialDiffuseCube&amp; mode
1180 m_loaded = model.m_loaded; 1194 m_loaded = model.m_loaded;
1181 1195
1182 // Copy MC cache 1196 // Copy MC cache
  1197 + m_mc_centre = model.m_mc_centre;
  1198 + m_mc_radius = model.m_mc_radius;
1183 m_mc_cache = model.m_mc_cache; 1199 m_mc_cache = model.m_mc_cache;
1184 m_mc_max = model.m_mc_max; 1200 m_mc_max = model.m_mc_max;
1185 m_mc_spectrum = model.m_mc_spectrum; 1201 m_mc_spectrum = model.m_mc_spectrum;