Commit fc6ba477b38271ab9529a3dabdfc6a9f482136c7
1 parent
ae65ce02
Use bounding box for efficient ring background determination (#2309)
Showing
2 changed files
with
206 additions
and
63 deletions
src/ctskymap/ctskymap.cpp
| ... | ... | @@ -397,9 +397,10 @@ void ctskymap::publish(const std::string& name) |
| 397 | 397 | ***************************************************************************/ |
| 398 | 398 | void ctskymap::init_members(void) |
| 399 | 399 | { |
| 400 | - // Initialise members | |
| 400 | + // Initialise User parameters | |
| 401 | 401 | m_outmap.clear(); |
| 402 | 402 | m_inexclusion.clear(); |
| 403 | + m_binsz = 0.0; | |
| 403 | 404 | m_emin = 0.0; |
| 404 | 405 | m_emax = 0.0; |
| 405 | 406 | m_bkgsubtract = "NONE"; |
| ... | ... | @@ -409,7 +410,7 @@ void ctskymap::init_members(void) |
| 409 | 410 | m_publish = false; |
| 410 | 411 | m_chatter = static_cast<GChatter>(2); |
| 411 | 412 | |
| 412 | - // Initialise maps | |
| 413 | + // Initialise members | |
| 413 | 414 | m_skymap.clear(); |
| 414 | 415 | m_bkgmap.clear(); |
| 415 | 416 | m_sigmap.clear(); |
| ... | ... | @@ -418,6 +419,9 @@ void ctskymap::init_members(void) |
| 418 | 419 | // Initialise cache |
| 419 | 420 | m_solidangle.clear(); |
| 420 | 421 | m_dirs.clear(); |
| 422 | + m_cos_roiradius = 1.0; | |
| 423 | + m_cos_inradius = 1.0; | |
| 424 | + m_cos_outradius = 1.0; | |
| 421 | 425 | |
| 422 | 426 | // Return |
| 423 | 427 | return; |
| ... | ... | @@ -431,9 +435,10 @@ void ctskymap::init_members(void) |
| 431 | 435 | ***************************************************************************/ |
| 432 | 436 | void ctskymap::copy_members(const ctskymap& app) |
| 433 | 437 | { |
| 434 | - // Copy members | |
| 438 | + // Copy User parameters | |
| 435 | 439 | m_outmap = app.m_outmap; |
| 436 | 440 | m_inexclusion = app.m_inexclusion; |
| 441 | + m_binsz = app.m_binsz; | |
| 437 | 442 | m_emin = app.m_emin; |
| 438 | 443 | m_emax = app.m_emax; |
| 439 | 444 | m_bkgsubtract = app.m_bkgsubtract; |
| ... | ... | @@ -443,15 +448,18 @@ void ctskymap::copy_members(const ctskymap& app) |
| 443 | 448 | m_publish = app.m_publish; |
| 444 | 449 | m_chatter = app.m_chatter; |
| 445 | 450 | |
| 446 | - // Copy maps | |
| 447 | - m_skymap = app.m_skymap; | |
| 448 | - m_bkgmap = app.m_bkgmap; | |
| 449 | - m_sigmap = app.m_sigmap; | |
| 450 | - m_exclmap = app.m_exclmap; | |
| 451 | + // Copy members | |
| 452 | + m_skymap = app.m_skymap; | |
| 453 | + m_bkgmap = app.m_bkgmap; | |
| 454 | + m_sigmap = app.m_sigmap; | |
| 455 | + m_exclmap = app.m_exclmap; | |
| 451 | 456 | |
| 452 | 457 | // Copy cache |
| 453 | - m_solidangle = app.m_solidangle; | |
| 454 | - m_dirs = app.m_dirs; | |
| 458 | + m_solidangle = app.m_solidangle; | |
| 459 | + m_dirs = app.m_dirs; | |
| 460 | + m_cos_roiradius = app.m_cos_roiradius; | |
| 461 | + m_cos_inradius = app.m_cos_inradius; | |
| 462 | + m_cos_outradius = app.m_cos_outradius; | |
| 455 | 463 | |
| 456 | 464 | // Return |
| 457 | 465 | return; |
| ... | ... | @@ -487,6 +495,7 @@ void ctskymap::get_parameters(void) |
| 487 | 495 | m_skymap = create_map(m_obs); |
| 488 | 496 | |
| 489 | 497 | // Get further parameters |
| 498 | + m_binsz = (*this)["binsz"].real(); | |
| 490 | 499 | m_emin = (*this)["emin"].real(); |
| 491 | 500 | m_emax = (*this)["emax"].real(); |
| 492 | 501 | m_bkgsubtract = (*this)["bkgsubtract"].string(); |
| ... | ... | @@ -567,6 +576,13 @@ void ctskymap::setup_maps(void) |
| 567 | 576 | |
| 568 | 577 | } // endif: background subtraction selected |
| 569 | 578 | |
| 579 | + // Compute cosine of ring radii for RING background method | |
| 580 | + if (m_bkgsubtract == "RING") { | |
| 581 | + m_cos_roiradius = std::cos(m_roiradius * gammalib::deg2rad); | |
| 582 | + m_cos_inradius = std::cos(m_inradius * gammalib::deg2rad); | |
| 583 | + m_cos_outradius = std::cos(m_outradius * gammalib::deg2rad); | |
| 584 | + } | |
| 585 | + | |
| 570 | 586 | // Return |
| 571 | 587 | return; |
| 572 | 588 | } |
| ... | ... | @@ -964,11 +980,8 @@ void ctskymap::map_significance_ring(void) |
| 964 | 980 | log_value(NORMAL, "Pixels remaining", m_skymap.npix()-i); |
| 965 | 981 | } |
| 966 | 982 | |
| 967 | - // Get bin coordinates | |
| 968 | - GSkyDir& skydir = m_dirs[i]; | |
| 969 | - | |
| 970 | 983 | // Compute the alpha and counts for this bin |
| 971 | - compute_ring_values(m_skymap, m_bkgmap, skydir, n_on, n_off, alpha); | |
| 984 | + compute_ring_values(i, m_skymap, m_bkgmap, n_on, n_off, alpha); | |
| 972 | 985 | |
| 973 | 986 | // Store the On and alpha-weighted Off-counts |
| 974 | 987 | onmap(i) = n_on; |
| ... | ... | @@ -1020,74 +1033,107 @@ void ctskymap::map_significance_ring(void) |
| 1020 | 1033 | /***********************************************************************//** |
| 1021 | 1034 | * @brief Computes Non, Noff and alpha for a counts map and sensitivity map |
| 1022 | 1035 | * |
| 1023 | - * @param[in] counts Counts map | |
| 1024 | - * @param[in] background Background map | |
| 1025 | - * @param[in] position Position of the ring & roi centers | |
| 1026 | - * @param[out] non Returned estimate of ON counts | |
| 1027 | - * @param[out] noff Returned estimate of OFF counts | |
| 1028 | - * @param[out] alpha Returned estimate of alpha | |
| 1036 | + * @param[in] ipixel Sky map pixel to consider. | |
| 1037 | + * @param[in] counts Counts map. | |
| 1038 | + * @param[in] background Background map. | |
| 1039 | + * @param[out] non Returned estimate of On-counts. | |
| 1040 | + * @param[out] noff Returned estimate of Off-counts. | |
| 1041 | + * @param[out] alpha Returned estimate of alpha. | |
| 1029 | 1042 | * |
| 1030 | - * This method computes the Non counts Noff values at a given position. It | |
| 1031 | - * also computes the alpha parameter from the passed sensitivity map. | |
| 1043 | + * Computes the On- and Off-counts values at a given position from in counts | |
| 1044 | + * map and the alpha parameter from the background map. | |
| 1045 | + * | |
| 1046 | + * To speed-up the computations the method considers only the pixels within | |
| 1047 | + * a bounding box that comprises the outer background ring radius. The method | |
| 1048 | + * considers wrapping around of pixel indices in the Right Ascension / | |
| 1049 | + * Galactic longitude direction. | |
| 1050 | + * | |
| 1051 | + * If the alpha of the ring region is zero the values of @p non, @p noff, | |
| 1052 | + * and @p alpha will be set to zero. | |
| 1032 | 1053 | ***************************************************************************/ |
| 1033 | -void ctskymap::compute_ring_values(const GSkyMap& counts, | |
| 1054 | +void ctskymap::compute_ring_values(const int& ipixel, | |
| 1055 | + const GSkyMap& counts, | |
| 1034 | 1056 | const GSkyMap& background, |
| 1035 | - const GSkyDir& position, | |
| 1036 | 1057 | double& non, |
| 1037 | 1058 | double& noff, |
| 1038 | 1059 | double& alpha) |
| 1039 | 1060 | { |
| 1040 | - // Reset Non and Noff | |
| 1041 | - non = 0.0; | |
| 1042 | - noff = 0.0; | |
| 1061 | + // Initialise return values (non, noff and alpha) | |
| 1062 | + non = 0.0; | |
| 1063 | + noff = 0.0; | |
| 1064 | + alpha = 0.0; | |
| 1043 | 1065 | |
| 1044 | 1066 | // Initialise On and Off alpha |
| 1045 | 1067 | double alpha_on = 0.0; |
| 1046 | 1068 | double alpha_off = 0.0; |
| 1047 | 1069 | |
| 1048 | - // Compute cosine of radii. We use the cosine of the radius here to | |
| 1049 | - // mimimize as much as possible the trigonometric computations. Note that | |
| 1050 | - // the cosine of an angle is maximal for an angle of zero. This explains | |
| 1051 | - // later why we chose ">=" to test whether an angle is smaller than a | |
| 1052 | - // given radius. | |
| 1053 | - double cos_roiradius = std::cos(m_roiradius * gammalib::deg2rad); | |
| 1054 | - double cos_inradius = std::cos(m_inradius * gammalib::deg2rad); | |
| 1055 | - double cos_outradius = std::cos(m_outradius * gammalib::deg2rad); | |
| 1070 | + // Get sky direction of pixel | |
| 1071 | + GSkyDir& position = m_dirs[ipixel]; | |
| 1072 | + | |
| 1073 | + // Get pixel bounding box | |
| 1074 | + int ix_start; | |
| 1075 | + int ix_stop; | |
| 1076 | + int iy_start; | |
| 1077 | + int iy_stop; | |
| 1078 | + ring_bounding_box(ipixel, ix_start, ix_stop, iy_start, iy_stop); | |
| 1056 | 1079 | |
| 1057 | - // Loop over every pixel in the observation to compute Non, Noff | |
| 1058 | - for (int j = 0; j < counts.npix(); ++j) { | |
| 1080 | + // Get number of x pixels in sky map | |
| 1081 | + int nx = counts.nx(); | |
| 1059 | 1082 | |
| 1060 | - // Get the index and sky direction of this pixel | |
| 1061 | - GSkyDir& skydir = m_dirs[j]; | |
| 1083 | + // Loop over x pixels of bounding box | |
| 1084 | + for (int ix_nowrap = ix_start; ix_nowrap < ix_stop; ++ix_nowrap) { | |
| 1062 | 1085 | |
| 1063 | - // Only consider pixels within the outer radius of the background region | |
| 1064 | - if (position.cos_dist(skydir) >= cos_outradius) { | |
| 1086 | + // Compute x pixel index by wrapping the pixel index into the | |
| 1087 | + // interval [0,nx[ | |
| 1088 | + int ix = ix_nowrap; | |
| 1089 | + if (ix < 0) { | |
| 1090 | + ix += nx; | |
| 1091 | + } | |
| 1092 | + else if (ix >= nx) { | |
| 1093 | + ix -= nx; | |
| 1094 | + } | |
| 1065 | 1095 | |
| 1066 | - // Check if pixel is inside the background region | |
| 1067 | - if ((m_exclmap(j) == 0.0) && position.cos_dist(skydir) < cos_inradius) { | |
| 1096 | + // Initialise pixel index | |
| 1097 | + int i = ix + iy_start * nx; | |
| 1068 | 1098 | |
| 1069 | - // Update n_off | |
| 1070 | - noff += counts(j); | |
| 1099 | + // Loop over y pixels of bounding box | |
| 1100 | + for (int iy = iy_start; iy < iy_stop; ++iy, i += nx) { | |
| 1071 | 1101 | |
| 1072 | - // Update alpha_off | |
| 1073 | - alpha_off += background(j); | |
| 1102 | + // Get the index and sky direction of this pixel | |
| 1103 | + GSkyDir& skydir = m_dirs[i]; | |
| 1074 | 1104 | |
| 1075 | - } | |
| 1105 | + // Only consider pixels within the outer radius of the background | |
| 1106 | + // region | |
| 1107 | + if (position.cos_dist(skydir) >= m_cos_outradius) { | |
| 1108 | + | |
| 1109 | + // Check if pixel is inside the background region | |
| 1110 | + if ((m_exclmap(i) == 0.0) && | |
| 1111 | + (position.cos_dist(skydir) < m_cos_inradius)) { | |
| 1112 | + | |
| 1113 | + // Update n_off | |
| 1114 | + noff += counts(i); | |
| 1115 | + | |
| 1116 | + // Update alpha_off | |
| 1117 | + alpha_off += background(i); | |
| 1076 | 1118 | |
| 1077 | - // ... otherwise check if pixel is inside source region | |
| 1078 | - else if (position.cos_dist(skydir) >= cos_roiradius) { | |
| 1119 | + } | |
| 1079 | 1120 | |
| 1080 | - // Update n_on for significance computation | |
| 1081 | - non += counts(j); | |
| 1121 | + // ... otherwise check if pixel is inside source region | |
| 1122 | + else if (position.cos_dist(skydir) >= m_cos_roiradius) { | |
| 1082 | 1123 | |
| 1083 | - // Update alpha_on | |
| 1084 | - alpha_on += background(j); | |
| 1124 | + // Update n_on | |
| 1125 | + non += counts(i); | |
| 1085 | 1126 | |
| 1086 | - } // endif: source and background region check | |
| 1127 | + // Update alpha_on | |
| 1128 | + alpha_on += background(i); | |
| 1087 | 1129 | |
| 1088 | - } // endif: pixel is within outer radius of background region | |
| 1130 | + } // endif: source and background region check | |
| 1089 | 1131 | |
| 1090 | - } // endfor: looped over pixels | |
| 1132 | + } // endif: pixel is within outer radius of background region | |
| 1133 | + | |
| 1134 | + } // endfor: looped over y pixels | |
| 1135 | + | |
| 1136 | + } // endfor: looped over x pixels | |
| 1091 | 1137 | |
| 1092 | 1138 | // Compute alpha. If the off region does not have any sensitivity then |
| 1093 | 1139 | // set Non = Noff = 0 |
| ... | ... | @@ -1106,6 +1152,95 @@ void ctskymap::compute_ring_values(const GSkyMap& counts, |
| 1106 | 1152 | |
| 1107 | 1153 | |
| 1108 | 1154 | /***********************************************************************//** |
| 1155 | + * @brief Computes bounding box for RING background computation | |
| 1156 | + * | |
| 1157 | + * @param[in] ipixel Sky map pixel to consider. | |
| 1158 | + * @param[out] ix1 Index of first pixel in x. | |
| 1159 | + * @param[out] ix2 Index after last pixel in x. | |
| 1160 | + * @param[out] iy1 Index of first pixel in y. | |
| 1161 | + * @param[out] iy2 Index after last pixel in y. | |
| 1162 | + * | |
| 1163 | + * Computes the bounding box that contained the background ring for a | |
| 1164 | + * specific pixel for the RING background method. | |
| 1165 | + * | |
| 1166 | + * The method determines the local pixel scale for the requested pixel and | |
| 1167 | + * draws a bounding box with 1.5 times the outer background ring radius | |
| 1168 | + * around the pixel. In the x direction the pixel indices are unconstrained, | |
| 1169 | + * and the client has to assure that the pixel value is comprised within | |
| 1170 | + * the validity range (this is required to handle the longitude wrap around). | |
| 1171 | + * In the y direction the pixel indices are constrained to [0,ny], where | |
| 1172 | + * ny is the number of y pixels in the sky map. | |
| 1173 | + ***************************************************************************/ | |
| 1174 | +void ctskymap::ring_bounding_box(const int& ipixel, int& ix1, int& ix2, | |
| 1175 | + int& iy1, int& iy2) | |
| 1176 | +{ | |
| 1177 | + // Get number of pixels in x and y direction | |
| 1178 | + int nx = m_skymap.nx(); | |
| 1179 | + int ny = m_skymap.ny(); | |
| 1180 | + | |
| 1181 | + // Get x and y index of pixel to consider | |
| 1182 | + int ix0 = ipixel % nx; | |
| 1183 | + int iy0 = ipixel / nx; | |
| 1184 | + | |
| 1185 | + // Compute pixel increment in x-direction | |
| 1186 | + double dx = 0.0; | |
| 1187 | + int ix = (ix0 > 0) ? ix0 - 1 : ix0 + 1; | |
| 1188 | + if (ix < nx) { | |
| 1189 | + dx = m_dirs[ipixel].dist_deg(m_dirs[ix+iy0*nx]); | |
| 1190 | + } | |
| 1191 | + if (dx < m_binsz) { | |
| 1192 | + dx = m_binsz; | |
| 1193 | + } | |
| 1194 | + | |
| 1195 | + // Compute pixel increment in y-direction | |
| 1196 | + double dy = 0.0; | |
| 1197 | + int iy = (iy0 > 0) ? iy0 - 1 : iy0 + 1; | |
| 1198 | + if (iy < ny) { | |
| 1199 | + dx = m_dirs[ipixel].dist_deg(m_dirs[ix0+iy*nx]); | |
| 1200 | + } | |
| 1201 | + if (dy < m_binsz) { | |
| 1202 | + dy = m_binsz; | |
| 1203 | + } | |
| 1204 | + | |
| 1205 | + // Compute bounding box half size in x and y. The outer radius is | |
| 1206 | + // multiplied by 1.5 to have some margin in case of map distortions | |
| 1207 | + int nx_bbox = int(1.5 * m_outradius / dx); | |
| 1208 | + int ny_bbox = int(1.5 * m_outradius / dy); | |
| 1209 | + | |
| 1210 | + // Compute index range for x. We allow that indices are smaller than 0 | |
| 1211 | + // or equal or larger than nx to handle wrap around, which needs to be | |
| 1212 | + // done in the client method. | |
| 1213 | + if (2*nx_bbox < nx) { | |
| 1214 | + ix1 = ix0 - nx_bbox; | |
| 1215 | + ix2 = ix0 + nx_bbox; | |
| 1216 | + } | |
| 1217 | + else { | |
| 1218 | + ix1 = 0; | |
| 1219 | + ix2 = nx; | |
| 1220 | + } | |
| 1221 | + | |
| 1222 | + // Compute index range for y. The index range is restricted to [0,ny]. | |
| 1223 | + if (2*ny_bbox < ny) { | |
| 1224 | + iy1 = iy0 - ny_bbox; | |
| 1225 | + iy2 = iy0 + ny_bbox; | |
| 1226 | + if (iy1 < 0) { | |
| 1227 | + iy1 = 0; | |
| 1228 | + } | |
| 1229 | + if (iy2 > ny) { | |
| 1230 | + iy2 = ny; | |
| 1231 | + } | |
| 1232 | + } | |
| 1233 | + else { | |
| 1234 | + iy1 = 0; | |
| 1235 | + iy2 = ny; | |
| 1236 | + } | |
| 1237 | + | |
| 1238 | + // Return | |
| 1239 | + return; | |
| 1240 | +} | |
| 1241 | + | |
| 1242 | + | |
| 1243 | +/***********************************************************************//** | |
| 1109 | 1244 | * @brief Write keywords in FITS HDU |
| 1110 | 1245 | * |
| 1111 | 1246 | * @param[in,out] hdu Pointer to FITS HDU. | ... | ... |
src/ctskymap/ctskymap.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctskymap - Sky mapping tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2017 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2018 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -77,15 +77,20 @@ protected: |
| 77 | 77 | void map_background_irf(GCTAObservation* obs); |
| 78 | 78 | void map_significance(void); |
| 79 | 79 | void map_significance_ring(void); |
| 80 | - void compute_ring_values(const GSkyMap& counts, | |
| 80 | + void compute_ring_values(const int& ipixel, | |
| 81 | + const GSkyMap& counts, | |
| 81 | 82 | const GSkyMap& background, |
| 82 | - const GSkyDir& position, | |
| 83 | - double& non, double& noff, double& alpha); | |
| 83 | + double& non, | |
| 84 | + double& noff, | |
| 85 | + double& alpha); | |
| 86 | + void ring_bounding_box(const int& ipixel, int& ix1, int& ix2, | |
| 87 | + int& iy1, int& iy2); | |
| 84 | 88 | void write_hdu_keywords(GFitsHDU* hdu) const; |
| 85 | 89 | |
| 86 | 90 | // User parameters |
| 87 | 91 | GFilename m_outmap; //!< Output file name |
| 88 | 92 | GFilename m_inexclusion; //!< Exclusion map file name |
| 93 | + double m_binsz; //!< Sky map binsize | |
| 89 | 94 | double m_emin; //!< Minimum energy (TeV) |
| 90 | 95 | double m_emax; //!< Maximum energy (TeV) |
| 91 | 96 | std::string m_bkgsubtract; //!< Background subtraction method |
| ... | ... | @@ -102,8 +107,11 @@ protected: |
| 102 | 107 | GSkyMap m_exclmap; //!< Exclusion map for RING background |
| 103 | 108 | |
| 104 | 109 | // Caching variables to prevent multiple computations of the same thing |
| 105 | - std::vector<double> m_solidangle; //!< Cached pixel solid angles | |
| 106 | - std::vector<GSkyDir> m_dirs; //!< Cached pixel directions | |
| 110 | + std::vector<double> m_solidangle; //!< Cached pixel solid angles | |
| 111 | + std::vector<GSkyDir> m_dirs; //!< Cached pixel directions | |
| 112 | + double m_cos_roiradius; //!< Cosine of RoI radius | |
| 113 | + double m_cos_inradius; //!< Cosine of inner ring radius | |
| 114 | + double m_cos_outradius; //!< Cosine of outer ring radius | |
| 107 | 115 | }; |
| 108 | 116 | |
| 109 | 117 | ... | ... |