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 3 * Version 1.1.0 released
4 4 =========================
5 5  
  6 + Optimise GModelSpatialDiffuseCube::set_mc_cone() method (#1673)
6 7 Use default GTime in GObservation::deadc() method (#1670)
7 8 The GApplicationPar::filename() methods now take and return GFilename (#1671)
8 9 Add GFilename methods and remove equivalents from GTools (#1666)
... ...
... ... @@ -111,7 +111,10 @@ None
111 111  
112 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 120 9. Numerics module
... ...
include/GModelSpatialDiffuseCube.hpp
... ... @@ -130,6 +130,8 @@ protected:
130 130 GEbounds m_ebounds; //!< Energy bounds of the maps
131 131  
132 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 135 mutable std::vector<double> m_mc_cache; //!< Monte Carlo cache
134 136 mutable std::vector<double> m_mc_max; //!< Maximum values for MC
135 137 mutable GModelSpectralNodes m_mc_spectrum; //!< Map cube spectrum
... ...
src/model/GModelSpatialDiffuseCube.cpp
... ... @@ -782,186 +782,198 @@ GEnergies GModelSpatialDiffuseCube::energies(void)
782 782 void GModelSpatialDiffuseCube::set_mc_cone(const GSkyDir& centre,
783 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 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 978 // Return
967 979 return;
... ... @@ -1155,6 +1167,8 @@ void GModelSpatialDiffuseCube::init_members(void)
1155 1167 m_loaded = false;
1156 1168  
1157 1169 // Initialise MC cache
  1170 + m_mc_centre.clear();
  1171 + m_mc_radius = -1.0; //!< Signal that initialisation is needed
1158 1172 m_mc_cache.clear();
1159 1173 m_mc_max.clear();
1160 1174 m_mc_spectrum.clear();
... ... @@ -1180,6 +1194,8 @@ void GModelSpatialDiffuseCube::copy_members(const GModelSpatialDiffuseCube&amp; mode
1180 1194 m_loaded = model.m_loaded;
1181 1195  
1182 1196 // Copy MC cache
  1197 + m_mc_centre = model.m_mc_centre;
  1198 + m_mc_radius = model.m_mc_radius;
1183 1199 m_mc_cache = model.m_mc_cache;
1184 1200 m_mc_max = model.m_mc_max;
1185 1201 m_mc_spectrum = model.m_mc_spectrum;
... ...