Commit e059bed749781f3849a5ff3e0a283f00f8e4e359

Authored by knodlseder
1 parent fe605e26

implement effective area access

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&amp; obsDir, const double&amp; obsEng, @@ -66,6 +66,50 @@ double GLATResponse::aeff(const GSkyDir&amp; obsDir, const double&amp; 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&amp; obsDir, const double&amp; obsEng, @@ -74,6 +118,8 @@ double GLATResponse::aeff(const GSkyDir&amp; obsDir, const double&amp; 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&amp; file) const @@ -116,8 +177,20 @@ void GLATResponse::aeff_append(GFits&amp; 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&amp; file) const @@ -130,7 +203,9 @@ void GLATResponse::aeff_append(GFits&amp; 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&amp; rsp) @@ -151,6 +239,12 @@ void GLATResponse::aeff_copy_members(const GLATResponse&amp; 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 }