Commit de55878739b8fadd68a729e63820d2b9f58c40d4

Authored by Josh Cardenzana
1 parent d44e87a4

Updated ctskymap with RING bkg subtraction (#2207)

Removed 'runavgalpha' option, since computing the run-by-run significance is a non trivial thing and the difference in the residual counts map is negligible.
Added special handling in the significance computation when Non=0 to avoid NaN's.
doc/source/users/reference_manual/ctskymap.rst
... ... @@ -82,7 +82,7 @@ Background subtraction configuration parameters
82 82 Background subtraction method.
83 83  
84 84 ``roiradius [real]``
85   - Region of interest radius for RING subtraction (in degrees).
  85 + Source region radius for estimating on-counts (in degrees).
86 86  
87 87 ``inradius [real]``
88 88 Inner ring radius for RING subtraction (in degrees).
... ... @@ -93,11 +93,6 @@ Background subtraction configuration parameters
93 93 ``(regfile = NONE) [file]``
94 94 Exclusion region file as either a FITS map or DS9 region file.
95 95  
96   -``(runavgalpha = yes) [boolean]``
97   - Specifies whether or not to compute the run averaged alpha for RING
98   - subtraction. Setting to 'no' will result in computing the alpha parameter
99   - for each individual run (which can take a very long time).
100   -
101 96  
102 97 Standard parameters
103 98 -------------------
... ...
src/ctskymap/ctskymap.cpp
... ... @@ -475,7 +475,6 @@ void ctskymap::get_parameters(void)
475 475 m_roiradius = (*this)["roiradius"].real();
476 476 m_inradius = (*this)["inradius"].real();
477 477 m_outradius = (*this)["outradius"].real();
478   - m_runavgalpha = (*this)["runavgalpha"].boolean();
479 478  
480 479 // Make sure that (roiradius < inradius < outradius)
481 480 if (m_roiradius > m_inradius) {
... ... @@ -498,10 +497,10 @@ void ctskymap::get_parameters(void)
498 497 map_exclusions((*this)["regfile"].filename());
499 498  
500 499 // Cache the pixel areas
501   - m_solidangle = std::vector<double>(m_bkgmap.npix(), 0.0);
  500 + m_solidangle.reserve(m_bkgmap.npix());
502 501 m_dirs.reserve(m_bkgmap.npix());
503 502 for (int i=0; i<m_bkgmap.npix(); i++) {
504   - m_solidangle[i] = m_bkgmap.solidangle(i);
  503 + m_solidangle.push_back(m_bkgmap.solidangle(i));
505 504 m_dirs.push_back(m_bkgmap.inx2dir(i));
506 505 }
507 506  
... ... @@ -789,11 +788,6 @@ void ctskymap::map_background_ring(GCTAObservation* obs)
789 788 double total = 0.0;
790 789 double exposure = obs->livetime() ;
791 790  
792   - // Create map for caching background IRF sensitivities
793   - GSkyMap sens = create_map(m_obs);
794   -
795   - std::vector<int> bin_indx(0);
796   -
797 791 // Loop over all map pixels
798 792 for (int i = 0; i < m_bkgmap.npix(); ++i) {
799 793  
... ... @@ -809,9 +803,6 @@ void ctskymap::map_background_ring(GCTAObservation* obs)
809 803 continue;
810 804 }
811 805  
812   - // Add this bin to the list of bins overlapping the skymap
813   - bin_indx.push_back( i );
814   -
815 806 // Setup integration function
816 807 ctskymap::irf_kern integrand(bkg, &instdir);
817 808 GIntegral integral(&integrand);
... ... @@ -822,53 +813,17 @@ void ctskymap::map_background_ring(GCTAObservation* obs)
822 813  
823 814 // Do Romberg integration to get the sensitivity (note: this assumes the
824 815 // background IRF is a good approximation for the radial sensitivity)
825   - sens(i,0) = integral.romberg(lnEmin, lnEmax) *
826   - m_solidangle[i] * obs->livetime();
  816 + m_alphamap(i,0) += integral.romberg(lnEmin, lnEmax) *
  817 + m_solidangle[i] * obs->livetime();
827 818  
  819 + // Store the counts in this bin
  820 + m_onmap(i,0) += m_skymap(i,0);
  821 +
828 822 // Update number of background function calls
829 823 calls += integral.calls();
830 824  
831 825 } // endfor: Loop for caching bkg IRF sensitivity
832 826  
833   - // Loop over all map pixels that fall in this observation
834   - for (int i = 0; i < bin_indx.size(); ++i) {
835   -
836   - // Get this bin
837   - int ibin = bin_indx[i];
838   -
839   - // If averaging parameters over all positions, then update intermediate
840   - // values to be used in the full computation later
841   - if (m_runavgalpha) {
842   -
843   - // Store the sensitivity for this bin
844   - m_alphamap(ibin,0) += sens(ibin,0);
845   -
846   - // Store the counts in this bin
847   - m_onmap(ibin,0) += m_skymap(ibin,0);
848   - }
849   -
850   - // Otherwise we need to re-loop on each observation to compute the
851   - // alpha weighted value of Noff for this run
852   - else {
853   -
854   - // Compute the on, off and alpha parameters
855   - double n_on(0.0), n_off(0.0), alpha(0.0);
856   - compute_ring_values(m_skymap, sens, m_dirs[ibin],
857   - n_on, n_off, alpha);
858   -
859   - // Update intermediate computation of significance
860   - m_sigmap( ibin, 0 ) +=
861   - n_on * std::log((1.0+alpha) * n_on / alpha / (n_on+n_off)) +
862   - n_off * std::log((1.0+alpha) * n_off / (n_on+n_off));
863   -
864   - // Update the predicted background counts and alpha parameters
865   - m_alphamap( ibin, 0 ) += alpha;
866   - m_bkgmap( ibin,0 ) += alpha * n_off;
867   - m_onmap( ibin, 0 ) += n_on;
868   - }
869   -
870   - } // endfor: looped over background map pixels
871   -
872 827 // Zero out the counts map to prepare it for the next observation
873 828 m_skymap = 0.0;
874 829  
... ... @@ -876,6 +831,7 @@ void ctskymap::map_background_ring(GCTAObservation* obs)
876 831 return;
877 832 }
878 833  
  834 +
879 835 /***********************************************************************//**
880 836 * @brief Write keywords in FITS HDU
881 837 *
... ... @@ -914,63 +870,69 @@ void ctskymap::map_significance(void)
914 870 // Compute significance from "RING" method (Li & Ma eq. 17)
915 871 if (m_bkgsubtract == "RING") {
916 872  
917   - // Check if we're averaging the alpha parameter over all runs
918   - if (m_runavgalpha) {
  873 + // Log message about what is being done
  874 + log_header1(NORMAL, "Computing RBM map");
  875 + log_value(NORMAL, "Total pixels to process", m_onmap.npix());
919 876  
920   - // Log message about what is being done
921   - log_header1(NORMAL, "Computing run averaged RBM map");
922   - log_value(NORMAL, "Total pixels to process", m_onmap.npix());
  877 + // Store the number of bins with an inappropriate alpha parameter
  878 + int num_bad_alpha(0);
  879 + // Loop through each bin in the on-counts map
  880 + for (int i = 0; i < m_onmap.npix(); ++i) {
923 881  
924   - // Loop through each bin in the on-counts map
925   - for (int i = 0; i < m_onmap.npix(); ++i) {
  882 + // Reset the on/off counts and alpha for this bin
  883 + double n_on(0), n_off(0), alpha(0.0);
926 884  
927   - // Since this can take a long time, keep the user updated on
928   - // the progress when another 10% of pixels is processed
929   - if (i%(m_onmap.npix()/10)==0) {
930   - log_value(NORMAL, "Pixels remaining", m_onmap.npix()-i);
931   - }
  885 + // Since this can take a long time, keep the user updated on
  886 + // the progress when another 10% of pixels is processed
  887 + if (i%(m_onmap.npix()/10)==0) {
  888 + log_value(NORMAL, "Pixels remaining", m_onmap.npix()-i);
  889 + }
932 890  
933   - // Get bin coordinate
934   - GSkyDir& skydir = m_dirs[i];
935   -
936   - // Compute the alpha and lambda for this bin
937   - double n_on(0), n_off(0), alpha(0.0);
938   - compute_ring_values(m_onmap, m_alphamap, skydir,
939   - n_on, n_off, alpha);
940   -
941   - // If alpha is reasonable, then store the results
942   - if (alpha > 0.0) {
943   - // Save the on-counts
944   - m_skymap(i,0) = n_on;
945   -
946   - // Save the significance and off-counts
947   - m_bkgmap(i,0) = alpha * n_off;
948   - m_sigmap(i,0) =
949   - n_on * std::log((1.0+alpha) * n_on / alpha / (n_on+n_off)) +
950   - n_off * std::log((1.0+alpha) * n_off / (n_on+n_off));
951   - }
952   - } // endfor: Loop over all pixels
953   - }
  891 + // Get bin coordinates
  892 + GSkyDir& skydir = m_dirs[i];
954 893  
955   - // Otherwise most of the intensive calculations were done at the
956   - // observation level.
957   - else {
958   - // m_onmap is the integral on-counts map, so update m_skymap
959   - m_skymap = m_onmap;
  894 + // Compute the alpha and counts for this bin
  895 + compute_ring_values(m_onmap, m_alphamap, skydir,
  896 + n_on, n_off, alpha);
960 897  
961   - } // endif: m_runavgalpha
  898 + // If alpha is reasonable, then store the results
  899 + if (alpha == 0.0) {
  900 + // Increment the bad alpha counter
  901 + num_bad_alpha++;
  902 + }
  903 +
  904 + else {
  905 + // Save the on-counts and alpha-weighted off-counts
  906 + m_skymap(i,0) = n_on;
  907 + m_bkgmap(i,0) = alpha * n_off;
  908 +
  909 + // Compute significance
  910 + if (n_on == 0.0) {
  911 +
  912 + // The significance computation reduces to the following form
  913 + m_sigmap(i,0) = -2.0 * n_off * std::log(1.0+alpha);
  914 +
  915 + } else {
  916 + // Save the significance
  917 + m_sigmap(i,0) = (n_on < (alpha*n_off) ? -2.0:2.0 ) *
  918 + (n_on * std::log((1.0+alpha) * n_on / (alpha * (n_on+n_off))) +
  919 + n_off * std::log((1.0+alpha) * n_off / (n_on+n_off)));
  920 + }
  921 + }
  922 + } // endfor: Loop over all pixels
962 923  
963   - // Multiply the significance map by '2', as per Li & Ma (1983) Eq. 17
964   - m_sigmap *= 2.0;
  924 + // Log the number of bad-alpha bins
  925 + log_value(NORMAL, "Bins with bad alpha", num_bad_alpha);
965 926  
966 927 // Now take the square root. Since some bins can be negative, first take
967 928 // the absolute value of the map, square root that, then multiply each
968 929 // bin by its sign to preserve the +/- significance.
969   - m_sigmap = sign(m_skymap - m_bkgmap) * sqrt( abs(m_sigmap) );
  930 + m_sigmap = sign(m_sigmap) * sqrt( abs(m_sigmap) );
970 931 }
971 932  
972   - // ... using Poisson statistics in the Gaussian limit
  933 + // Compute significance using Poisson statistics in the Gaussian limit
973 934 else {
  935 +
974 936 // Compute significance map
975 937 m_sigmap = (m_skymap - m_bkgmap) / sqrt(m_skymap);
976 938  
... ... @@ -1018,6 +980,7 @@ void ctskymap::compute_ring_values(const GSkyMap&amp; counts,
1018 980 if ((m_exclmap(j,0) == 1.0) &&
1019 981 outer_reg.contains(skydir) &&
1020 982 !inner_reg.contains(skydir)) {
  983 +
1021 984 // Update n_off
1022 985 noff += counts(j,0);
1023 986  
... ... @@ -1027,6 +990,7 @@ void ctskymap::compute_ring_values(const GSkyMap&amp; counts,
1027 990  
1028 991 // Check if pixel is inside source region
1029 992 else if (roi_reg.contains(skydir)) {
  993 +
1030 994 // Update n_on for significance computation
1031 995 non += counts(j,0);
1032 996  
... ... @@ -1038,8 +1002,13 @@ void ctskymap::compute_ring_values(const GSkyMap&amp; counts,
1038 1002 } // endfor: sub-loop over pixels
1039 1003  
1040 1004 // Compute alpha
1041   - if (alpha_off == 0) {
  1005 + if (alpha_off == 0.0) {
  1006 + // The off region does not have any sensitivity or there are no events
  1007 + // in either the on region or the off region
1042 1008 alpha = 0.0;
  1009 + non = 0.0;
  1010 + noff = 0.0;
  1011 +
1043 1012 } else {
1044 1013 alpha = alpha_on / alpha_off;
1045 1014 }
... ... @@ -1092,6 +1061,7 @@ void ctskymap::map_exclusions_fits(const GFilename&amp; filename)
1092 1061  
1093 1062 // Check this sky position in the fits map
1094 1063 if (inmap.contains(dir) && (inmap(inmap.dir2inx(dir)) == 0.0)) {
  1064 +
1095 1065 // Set the pixel to 0
1096 1066 m_exclmap(i) = 0.0;
1097 1067  
... ... @@ -1111,10 +1081,10 @@ void ctskymap::map_exclusions_reg(const GFilename&amp; filename)
1111 1081 GSkyRegions regions(filename);
1112 1082  
1113 1083 // Loop through the individual pixels in the exclusion map
1114   - GSkyDir dir;
1115 1084 for (int i=0; i<m_exclmap.npix(); i++) {
  1085 +
1116 1086 // Get the pixel position
1117   - dir = m_exclmap.pix2dir(i);
  1087 + GSkyDir dir = m_exclmap.pix2dir(i);
1118 1088  
1119 1089 // Check if GSkyDir overlaps with the regions
1120 1090 if (regions.contains(dir)) {
... ...
src/ctskymap/ctskymap.hpp
... ... @@ -74,8 +74,8 @@ protected:
74 74 void map_background_ring(GCTAObservation* obs);
75 75 void map_significance(void);
76 76 void map_exclusions(const GFilename& filename);
77   - void map_exclusions_reg(const GFilename& filename);
78 77 void map_exclusions_fits(const GFilename& filename);
  78 + void map_exclusions_reg(const GFilename& filename);
79 79 void compute_ring_values(const GSkyMap& counts,
80 80 const GSkyMap& sensitivity,
81 81 const GSkyDir& position,
... ... @@ -107,7 +107,6 @@ protected:
107 107 double m_roiradius; //!< Region of interest radius
108 108 double m_inradius; //!< Inner ring radius
109 109 double m_outradius; //!< Outer ring radius
110   - bool m_runavgalpha; //!< Determines how alpha is computed
111 110  
112 111 // Protected members
113 112 GSkyMap m_skymap; //!< Sky map
... ...
src/ctskymap/ctskymap.par
... ... @@ -43,11 +43,10 @@ yref, r, a, 22.01,-90,90, &quot;Second coordinate of image center in degrees (DEC
43 43 # Background subtraction parameters
44 44 #==================================
45 45 bkgsubtract, s, a, NONE, NONE|IRF|RING,, "Background subtraction method"
46   -roiradius, r, a, 0.0,,, "Region of interest radius (degrees)"
  46 +roiradius, r, a, 0.0,,, "Source region radius for estimating on-counts (degrees)"
47 47 inradius, r, a, 0.6,,, "Inner ring radius (degrees)"
48 48 outradius, r, a, 0.8,,, "Outer ring radius (degrees)"
49 49 regfile, f, h, NONE,,, "Exclusion regions definition file"
50   -runavgalpha, b, h, yes,,, "Compute alpha as average over runs"
51 50  
52 51 #
53 52 # Standard parameters
... ...
test/test_ctskymap.py
... ... @@ -261,8 +261,7 @@ class Test(test):
261 261 skymap['roiradius'] = 0.1
262 262 skymap['inradius'] = 0.6
263 263 skymap['outradius'] = 0.8
264   - skymap['regfile'] = 'NONE'
265   - skymap['runavgalpha'] = True
  264 + skymap['regfile'] = 'NONE'
266 265  
267 266 # Execute tool
268 267 skymap.logFileOpen() # Needed to get a new log file
... ...