Commit e059bed749781f3849a5ff3e0a283f00f8e4e359
1 parent
fe605e26
implement effective area access
Showing
4 changed files
with
125 additions
and
12 deletions
include/GLATResponse.hpp
| @@ -58,6 +58,9 @@ public: | @@ -58,6 +58,9 @@ public: | ||
| 58 | const GSkyDir& srcDir, const double& srcEng, | 58 | const GSkyDir& srcDir, const double& srcEng, |
| 59 | const GSkyDir& instPntDir, const double& instPosAng, | 59 | const GSkyDir& instPntDir, const double& instPosAng, |
| 60 | const double& time); | 60 | const double& time); |
| 61 | + double aeff(const double& logE, const double& ctheta); | ||
| 62 | + void aeff_ctheta_min(const double& ctheta); | ||
| 63 | + double aeff_ctheta_min(void) const; | ||
| 61 | 64 | ||
| 62 | // PSF Methods | 65 | // PSF Methods |
| 63 | double psf(const GSkyDir& obsDir, const double& obsEng, | 66 | double psf(const GSkyDir& obsDir, const double& obsEng, |
| @@ -112,7 +115,9 @@ private: | @@ -112,7 +115,9 @@ private: | ||
| 112 | GVector get_fits_vector(const GFitsHDU* hdu, const std::string& colname, int row = 0); | 115 | GVector get_fits_vector(const GFitsHDU* hdu, const std::string& colname, int row = 0); |
| 113 | 116 | ||
| 114 | // Private Aeff data | 117 | // Private Aeff data |
| 115 | - GLATResponseTable m_aeff_bins; //!< Aeff energy and cos theta binning | 118 | + GLATResponseTable m_aeff_bins; //!< Aeff energy and cos theta binning |
| 119 | + double* m_aeff; //!< Aeff array | ||
| 120 | + double m_aeff_ctheta_min; //!< Minimum valid cos(theta) | ||
| 116 | 121 | ||
| 117 | // Private PSF data | 122 | // Private PSF data |
| 118 | GLATResponseTable m_psf_bins; //!< PSF energy and cos theta binning | 123 | GLATResponseTable m_psf_bins; //!< PSF energy and cos theta binning |
include/GLATResponseTable.hpp
| @@ -56,6 +56,10 @@ public: | @@ -56,6 +56,10 @@ public: | ||
| 56 | double energy(const int& ie) const; | 56 | double energy(const int& ie) const; |
| 57 | int num_energy(void) const { return m_energy_num; } | 57 | int num_energy(void) const { return m_energy_num; } |
| 58 | int num_ctheta(void) const { return m_ctheta_num; } | 58 | int num_ctheta(void) const { return m_ctheta_num; } |
| 59 | + double energy_lo(const int& inx) const { return m_energy_lo[inx]; } | ||
| 60 | + double energy_hi(const int& inx) const { return m_energy_hi[inx]; } | ||
| 61 | + double ctheta_lo(const int& inx) const { return m_ctheta_lo[inx]; } | ||
| 62 | + double ctheta_hi(const int& inx) const { return m_ctheta_hi[inx]; } | ||
| 59 | 63 | ||
| 60 | private: | 64 | private: |
| 61 | // Methods | 65 | // Methods |
pyext/GLATResponse.i
| @@ -34,26 +34,36 @@ public: | @@ -34,26 +34,36 @@ public: | ||
| 34 | GLATResponse(const GLATResponse& rsp); | 34 | GLATResponse(const GLATResponse& rsp); |
| 35 | ~GLATResponse(); | 35 | ~GLATResponse(); |
| 36 | 36 | ||
| 37 | - // Methods | 37 | + // IRF Methods |
| 38 | double irf(const GSkyDir& obsDir, const double& obsEng, | 38 | double irf(const GSkyDir& obsDir, const double& obsEng, |
| 39 | const GSkyDir& srcDir, const double& srcEng, | 39 | const GSkyDir& srcDir, const double& srcEng, |
| 40 | const GSkyDir& instPntDir, const double& instPosAng, | 40 | const GSkyDir& instPntDir, const double& instPosAng, |
| 41 | const double& time); | 41 | const double& time); |
| 42 | - double psf(const GSkyDir& obsDir, const double& obsEng, | 42 | + // Aeff Methods |
| 43 | + double aeff(const GSkyDir& obsDir, const double& obsEng, | ||
| 43 | const GSkyDir& srcDir, const double& srcEng, | 44 | const GSkyDir& srcDir, const double& srcEng, |
| 44 | const GSkyDir& instPntDir, const double& instPosAng, | 45 | const GSkyDir& instPntDir, const double& instPosAng, |
| 45 | const double& time); | 46 | const double& time); |
| 46 | - double psf(const double& delta, const double& logE, const double& ctheta); | ||
| 47 | - GVector psf(const GVector& delta, const double& logE, const double& ctheta); | ||
| 48 | - double aeff(const GSkyDir& obsDir, const double& obsEng, | 47 | + double aeff(const double& logE, const double& ctheta); |
| 48 | + void aeff_ctheta_min(const double& ctheta); | ||
| 49 | + double aeff_ctheta_min(void) const; | ||
| 50 | + | ||
| 51 | + // PSF Methods | ||
| 52 | + double psf(const GSkyDir& obsDir, const double& obsEng, | ||
| 49 | const GSkyDir& srcDir, const double& srcEng, | 53 | const GSkyDir& srcDir, const double& srcEng, |
| 50 | const GSkyDir& instPntDir, const double& instPosAng, | 54 | const GSkyDir& instPntDir, const double& instPosAng, |
| 51 | const double& time); | 55 | const double& time); |
| 56 | + double psf(const double& delta, const double& logE, const double& ctheta); | ||
| 57 | + GVector psf(const GVector& delta, const double& logE, const double& ctheta); | ||
| 58 | + | ||
| 59 | + // Edisp Methods | ||
| 52 | double edisp(const GSkyDir& obsDir, const double& obsEng, | 60 | double edisp(const GSkyDir& obsDir, const double& obsEng, |
| 53 | const GSkyDir& srcDir, const double& srcEng, | 61 | const GSkyDir& srcDir, const double& srcEng, |
| 54 | const GSkyDir& instPntDir, const double& instPosAng, | 62 | const GSkyDir& instPntDir, const double& instPosAng, |
| 55 | const double& time); | 63 | const double& time); |
| 56 | - void set_caldb(const std::string& caldb); | ||
| 57 | - void load(const std::string& rspname, const std::string& rsptype); | ||
| 58 | - void save(const std::string& rspname) const; | 64 | + |
| 65 | + // Other Methods | ||
| 66 | + void set_caldb(const std::string& caldb); | ||
| 67 | + void load(const std::string& rspname, const std::string& rsptype); | ||
| 68 | + void save(const std::string& rspname) const; | ||
| 59 | }; | 69 | }; |
src/rsp/GLATAeff.cpp
| @@ -66,6 +66,50 @@ double GLATResponse::aeff(const GSkyDir& obsDir, const double& obsEng, | @@ -66,6 +66,50 @@ double GLATResponse::aeff(const GSkyDir& obsDir, const double& obsEng, | ||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | 68 | ||
| 69 | +/***********************************************************************//** | ||
| 70 | + * @brief Return effective area in units of cm2 | ||
| 71 | + * | ||
| 72 | + * @param[in] logE Logarithm of the true photon energy (MeV). | ||
| 73 | + * @param[in] ctheta Cosine of the zenith angle with respect to the pointing | ||
| 74 | + * axis. | ||
| 75 | + ***************************************************************************/ | ||
| 76 | +double GLATResponse::aeff(const double& logE, const double& ctheta) | ||
| 77 | +{ | ||
| 78 | + // Get effective area value | ||
| 79 | + double aeff = (ctheta >= m_aeff_ctheta_min) | ||
| 80 | + ? m_aeff_bins.interpolate(logE, ctheta, m_aeff) : 0.0; | ||
| 81 | + | ||
| 82 | + // Return effective area value | ||
| 83 | + return aeff; | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | + | ||
| 87 | +/***********************************************************************//** | ||
| 88 | + * @brief Set minimum cos(theta) angle for effective area access | ||
| 89 | + * | ||
| 90 | + * @param[in] ctheta Cosine of the maximum zenith angle for which effective | ||
| 91 | + * areas will be returned (0 is returned for larger values) | ||
| 92 | + ***************************************************************************/ | ||
| 93 | +void GLATResponse::aeff_ctheta_min(const double& ctheta) | ||
| 94 | +{ | ||
| 95 | + // Set minimum cos(theta) value | ||
| 96 | + m_aeff_ctheta_min = ctheta; | ||
| 97 | + | ||
| 98 | + // Return | ||
| 99 | + return; | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | + | ||
| 103 | +/***********************************************************************//** | ||
| 104 | + * @brief Get minimum cos(theta) angle for effective area access | ||
| 105 | + ***************************************************************************/ | ||
| 106 | +double GLATResponse::aeff_ctheta_min(void) const | ||
| 107 | +{ | ||
| 108 | + // Return minimum cos(theta) value | ||
| 109 | + return m_aeff_ctheta_min; | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | + | ||
| 69 | /*========================================================================== | 113 | /*========================================================================== |
| 70 | = = | 114 | = = |
| 71 | = Private methods = | 115 | = Private methods = |
| @@ -74,6 +118,8 @@ double GLATResponse::aeff(const GSkyDir& obsDir, const double& obsEng, | @@ -74,6 +118,8 @@ double GLATResponse::aeff(const GSkyDir& obsDir, const double& obsEng, | ||
| 74 | 118 | ||
| 75 | /***********************************************************************//** | 119 | /***********************************************************************//** |
| 76 | * @brief Initialise effective area | 120 | * @brief Initialise effective area |
| 121 | + * | ||
| 122 | + * The effective area is converted into units of cm2. | ||
| 77 | ***************************************************************************/ | 123 | ***************************************************************************/ |
| 78 | void GLATResponse::aeff_init(void) | 124 | void GLATResponse::aeff_init(void) |
| 79 | { | 125 | { |
| @@ -92,8 +138,23 @@ void GLATResponse::aeff_init(void) | @@ -92,8 +138,23 @@ void GLATResponse::aeff_init(void) | ||
| 92 | // Get the energy and cos(theta) bins | 138 | // Get the energy and cos(theta) bins |
| 93 | m_aeff_bins.load(hdu); | 139 | m_aeff_bins.load(hdu); |
| 94 | 140 | ||
| 95 | - // Get the data | ||
| 96 | - GVector effarea = get_fits_vector(hdu, "EFFAREA"); | 141 | + // Allocate memory for effective area |
| 142 | + int size = m_aeff_bins.num_energy() * m_aeff_bins.num_ctheta(); | ||
| 143 | + if (size > 0) | ||
| 144 | + m_aeff = new double[size]; | ||
| 145 | + | ||
| 146 | + // Get pointer to effective area column | ||
| 147 | + GFitsTableCol* ptr = hdu->column("EFFAREA"); | ||
| 148 | + if (ptr == NULL) | ||
| 149 | + throw GException::fits_column_not_found(G_INIT_AEFF, "EFFAREA"); | ||
| 150 | + | ||
| 151 | + // Copy data and convert from m2 into cm2 | ||
| 152 | + int num = ptr->number(); | ||
| 153 | + for (int i = 0; i < num; ++i) | ||
| 154 | + m_aeff[i] = ptr->real(0,i) * 1.0e4; | ||
| 155 | + | ||
| 156 | + // Set minimum cos(theta) | ||
| 157 | + m_aeff_ctheta_min = m_aeff_bins.ctheta_lo(0); | ||
| 97 | 158 | ||
| 98 | // Return | 159 | // Return |
| 99 | return; | 160 | return; |
| @@ -116,8 +177,20 @@ void GLATResponse::aeff_append(GFits& file) const | @@ -116,8 +177,20 @@ void GLATResponse::aeff_append(GFits& file) const | ||
| 116 | m_aeff_bins.save(&hdu_bounds); | 177 | m_aeff_bins.save(&hdu_bounds); |
| 117 | hdu_bounds.extname("ABOUNDS"); | 178 | hdu_bounds.extname("ABOUNDS"); |
| 118 | 179 | ||
| 180 | + // Build effective area image | ||
| 181 | + int naxes[] = {m_aeff_bins.num_energy(), m_aeff_bins.num_ctheta()}; | ||
| 182 | + GFitsDblImage image_aeff(2, naxes, m_aeff); | ||
| 183 | + | ||
| 184 | + // Construct effective area HDU | ||
| 185 | + GFitsHDU hdu_aeff(image_aeff); | ||
| 186 | + hdu_aeff.extname("AEFF"); | ||
| 187 | + hdu_aeff.header()->update(GFitsHeaderCard("CTYPE1", "Energy", "Energy binning")); | ||
| 188 | + hdu_aeff.header()->update(GFitsHeaderCard("CTYPE2", "cos(theta)", "cos(theta) binning")); | ||
| 189 | + hdu_aeff.header()->update(GFitsHeaderCard("BUNIT", "cm2", "Pixel unit")); | ||
| 190 | + | ||
| 119 | // Append HDUs to FITS file | 191 | // Append HDUs to FITS file |
| 120 | file.append_hdu(hdu_bounds); | 192 | file.append_hdu(hdu_bounds); |
| 193 | + file.append_hdu(hdu_aeff); | ||
| 121 | 194 | ||
| 122 | // Return | 195 | // Return |
| 123 | return; | 196 | return; |
| @@ -130,7 +203,9 @@ void GLATResponse::aeff_append(GFits& file) const | @@ -130,7 +203,9 @@ void GLATResponse::aeff_append(GFits& file) const | ||
| 130 | void GLATResponse::aeff_init_members(void) | 203 | void GLATResponse::aeff_init_members(void) |
| 131 | { | 204 | { |
| 132 | // Initialise Aeff members | 205 | // Initialise Aeff members |
| 133 | - | 206 | + m_aeff_ctheta_min = 0.0; |
| 207 | + m_aeff = NULL; | ||
| 208 | + | ||
| 134 | // Return | 209 | // Return |
| 135 | return; | 210 | return; |
| 136 | } | 211 | } |
| @@ -141,6 +216,19 @@ void GLATResponse::aeff_init_members(void) | @@ -141,6 +216,19 @@ void GLATResponse::aeff_init_members(void) | ||
| 141 | ***************************************************************************/ | 216 | ***************************************************************************/ |
| 142 | void GLATResponse::aeff_copy_members(const GLATResponse& rsp) | 217 | void GLATResponse::aeff_copy_members(const GLATResponse& rsp) |
| 143 | { | 218 | { |
| 219 | + // Copy attributes | ||
| 220 | + m_aeff_bins = rsp.m_aeff_bins; | ||
| 221 | + m_aeff_ctheta_min = rsp.m_aeff_ctheta_min; | ||
| 222 | + | ||
| 223 | + // Copy effective area array | ||
| 224 | + if (rsp.m_aeff != NULL) { | ||
| 225 | + int size = m_aeff_bins.num_energy() * m_aeff_bins.num_ctheta(); | ||
| 226 | + if (size > 0) { | ||
| 227 | + m_aeff = new double[size]; | ||
| 228 | + memcpy(m_aeff, rsp.m_aeff, size*sizeof(double)); | ||
| 229 | + } | ||
| 230 | + } | ||
| 231 | + | ||
| 144 | // Return | 232 | // Return |
| 145 | return; | 233 | return; |
| 146 | } | 234 | } |
| @@ -151,6 +239,12 @@ void GLATResponse::aeff_copy_members(const GLATResponse& rsp) | @@ -151,6 +239,12 @@ void GLATResponse::aeff_copy_members(const GLATResponse& rsp) | ||
| 151 | ***************************************************************************/ | 239 | ***************************************************************************/ |
| 152 | void GLATResponse::aeff_free_members(void) | 240 | void GLATResponse::aeff_free_members(void) |
| 153 | { | 241 | { |
| 242 | + // Free effective area memory | ||
| 243 | + if (m_aeff != NULL) delete [] m_aeff; | ||
| 244 | + | ||
| 245 | + // Signal that effective area memory is free | ||
| 246 | + m_aeff = NULL; | ||
| 247 | + | ||
| 154 | // Return | 248 | // Return |
| 155 | return; | 249 | return; |
| 156 | } | 250 | } |