52#define G_IRF "GSPIResponse::irf(GEvent&, GSource&, GObservation&)"
53#define G_NROI "GSPIResponse::nroi(GModelSky&, GEnergy&, GTime&, "\
55#define G_EBOUNDS "GSPIResponse::ebounds(GEnergy&)"
56#define G_SET "GSPIResponse::set(const GSPIObservation& obs)"
57#define G_LOAD_IRF "GSPIResponse::load_irf(GFilename&)"
58#define G_LOAD_IRFS "GSPIResponse::load_irfs(int&)"
254 if (spi_obs == NULL) {
255 std::string cls = std::string(
typeid(&obs).name());
256 std::string msg =
"Observation of type \""+cls+
"\" is not an "
257 "INTEGRAL/SPI observation. Please specify an "
258 "INTEGRAL/SPI observation as argument.";
265 std::string msg =
"INTEGRAL/SPI observation does not contain a valid "
266 "event cube. Please specify an observation with an "
267 "event cube as argument.";
274 std::string cls = std::string(
typeid(&event).name());
275 std::string msg =
"Event of type \""+cls+
"\" is not an INTEGRAL/SPI "
276 "event. Please specify an INTEGRAL/SPI event as "
293 #if defined(G_NAN_CHECK)
295 std::cout <<
"*** ERROR: GSPIResponse::irf:";
296 std::cout <<
" NaN/Inf encountered";
297 std::cout <<
" (irf=" <<
irf;
299 std::cout << std::endl;
327 const int& ireg)
const
355 int ieng = bin.
iebin();
358 int map = idet + (ireg + ieng * nreg) * ndet;
361 int ix_left = int(xpix);
362 int ix_right = ix_left + 1;
363 int iy_top = int(ypix);
364 int iy_bottom = iy_top + 1;
367 double wgt_right = xpix - double(ix_left);
368 double wgt_left = 1.0 - wgt_right;
369 double wgt_bottom = ypix - double(iy_top);
370 double wgt_top = 1.0 - wgt_bottom;
373 int inx_1 = ix_left + iy_top * nx;
374 int inx_2 = ix_right + iy_top * nx;
375 int inx_3 = ix_left + iy_bottom * nx;
376 int inx_4 = ix_right + iy_bottom * nx;
379 double wgt_1 = wgt_left * wgt_top;
380 double wgt_2 = wgt_right * wgt_top;
381 double wgt_3 = wgt_left * wgt_bottom;
382 double wgt_4 = wgt_right * wgt_bottom;
418 const GTime& obsTime,
422 std::string msg =
"Spatial integration of sky model over the data space "
423 "is not implemented.";
448 std::string msg =
"Energy dispersion not implemented.";
493 int neng = cube->
naxis(2);
497 irfs.
nmaps(ndet * nreg * neng);
498 irfs.
shape(ndet, nreg, neng);
502 for (
int ieng = 0; ieng < neng; ++ieng) {
505 double emin = cube->
ebounds().emin(ieng).keV();
506 double emax = cube->
ebounds().emax(ieng).keV();
523 for (
int idet = 0; idet < ndet; ++idet) {
524 for (
int ireg = 0; ireg < nreg; ++ireg) {
525 int map_irf = idet + ireg * ndet;
526 int map_irfs = idet + (ireg + ieng * nreg) * ndet;
527 for (
int i = 0; i < npix; ++i) {
528 irfs(i, map_irfs) =
irf(i, map_irf);
613 GFits fits(filename);
643 fits.
saveto(filename, clobber);
675 result.append(
"=== GSPIResponse ===");
685 result.append(
"] deg");
689 result.append(
"] deg");
819 int num = table.
nrows();
825 for (
int i = 0; i < num; ++i) {
874 int num = table.
nrows();
880 std::string unit =
"keV";
882 unit = table.
string(
"TUNIT1");
886 for (
int i = 0; i < num; ++i) {
920 for (
int i = 0; i < num; ++i) {
958 table.
card(
"ENERGY",
m_energy_keV,
"[keV] IRF line energy (0 for continuum IRF)");
959 table.
card(
"DLOGE",
m_dlogE,
"Logarithmic step size for continuum IRF");
960 table.
card(
"GAMMA",
m_gamma,
"Power-law index for continuum IRF");
974 for (
int i = 0; i < num; ++i) {
977 col_energy.
unit(
"keV");
1006 GFits fits(irfname);
1012 int naxis1 = image->
integer(
"NAXIS1");
1013 int naxis2 = image->
integer(
"NAXIS2");
1014 int naxis3 = image->
integer(
"NAXIS3");
1015 int naxis4 = image->
integer(
"NAXIS4");
1016 double crval2 = image->
real(
"CRVAL2");
1017 double crval3 = image->
real(
"CRVAL3");
1018 double crpix2 = image->
real(
"CRPIX2");
1019 double crpix3 = image->
real(
"CRPIX3");
1020 double cdelt2 = image->
real(
"CDELT2");
1021 double cdelt3 = image->
real(
"CDELT3");
1030 double wcs_xmax = wcs_xmin + double(naxis2-1) * wcs_xbin;
1031 double wcs_ymax = wcs_ymin + double(naxis3-1) * wcs_ybin;
1032 double wcs_xpix_max = double(naxis2-1);
1033 double wcs_ypix_max = double(naxis3-1);
1052 if ((std::abs(wcs_xmin -
m_wcs_xmin) > 1.0e-6) ||
1053 (std::abs(wcs_ymin -
m_wcs_ymin) > 1.0e-6) ||
1054 (std::abs(wcs_xbin -
m_wcs_xbin) > 1.0e-6) ||
1055 (std::abs(wcs_ybin -
m_wcs_ybin) > 1.0e-6) ||
1056 (std::abs(wcs_xmax -
m_wcs_xmax) > 1.0e-6) ||
1057 (std::abs(wcs_ymax -
m_wcs_ymax) > 1.0e-6) ||
1060 std::string msg =
"Inconsistent IRFs encountered in file \""+
1061 irfname.
url()+
"\". Please specify a response "
1062 "group where all IRFs have the same definition.";
1072 int nmap = naxis1 * naxis4;
1076 GSkyMap irf(
"ARC",
"CEL", crval2, crval3, cdelt2, cdelt3, naxis2, naxis3, nmap);
1079 for (
int ix = 0; ix < naxis2; ++ix) {
1080 for (
int iy = 0; iy < naxis3; ++iy) {
1081 for (
int idet = 0; idet < naxis1; ++idet) {
1082 for (
int ireg = 0; ireg < naxis4; ++ireg) {
1083 int index = ix + iy * naxis2;
1084 int map = idet + ireg * naxis1;
1085 irf(index,map) = image->
pixel(idet, ix, iy, ireg);
1092 irf.shape(naxis1, naxis4);
1127 std::string msg =
"No response grouping table found in file \""+
1129 "response grouping file.";
1137 for (
int i_irf = 0; i_irf < num_irfs; ++i_irf) {
1142 for (
int i_irf = 0; i_irf < num_irfs; ++i_irf) {
1146 (*grp)[
"MEMBER_LOCATION"]->string(i_irf);
1152 int num_regions = (region == -1) ?
irf.shape()[1] : 1;
1172 int ndet =
irf.shape()[0];
1175 for (
int i_region = 0; i_region < num_regions; ++i_region) {
1178 for (
int i_det = 0; i_det < num_det; ++i_det) {
1181 int map_irf =
m_detids[i_det] + i_region * ndet;
1182 int map_irfs = i_det + (i_region + i_irf * num_regions) * num_det;
1185 for (
int i = 0, iy = 0; iy < ny; ++iy) {
1186 for (
int ix = 0; ix < nx; ++ix, ++i) {
1224 #if defined(G_DEBUG_COMPUTE_IRF)
1225 std::cout <<
"GSPIResponse::compute_irf:" << std::endl;
1226 std::cout <<
"- emin = " << emin <<
" keV" << std::endl;
1227 std::cout <<
"- emax = " << emax <<
" keV" << std::endl;
1228 std::cout <<
"- npix = " << npix << std::endl;
1229 std::cout <<
"- ndet = " << ndet << std::endl;
1230 std::cout <<
"- nreg = " << nreg << std::endl;
1235 irf.nmaps(ndet * nreg);
1236 irf.shape(ndet, nreg);
1243 double log_emin = std::log10(emin);
1244 double log_emax = std::log10(emax);
1245 double log_ewidth = log_emax - log_emin;
1249 double wgt0 = 1.0 /
irf_weight(beta, log_emin, log_emax);
1253 int num_int = (
m_dlogE > DBL_MIN) ?
int(log_ewidth /
m_dlogE + 0.5) : 1;
1257 double log_estep = log_ewidth / num_int;
1260 #if defined(G_DEBUG_COMPUTE_IRF)
1261 std::cout <<
"- log_emin = " << log_emin << std::endl;
1262 std::cout <<
"- log_emax = " << log_emax << std::endl;
1263 std::cout <<
"- log_ewidth = " << log_ewidth << std::endl;
1264 std::cout <<
"- beta = " << beta << std::endl;
1265 std::cout <<
"- wgt0 = " << wgt0 << std::endl;
1266 std::cout <<
"- num_int = " << num_int << std::endl;
1267 std::cout <<
"- log_estep = " << log_estep << std::endl;
1268 double wgt_check = 0.0;
1272 for (
int i_int = 0; i_int < num_int; ++i_int) {
1275 double log_emin_bin = log_emin + i_int * log_estep;
1276 double log_emax_bin = log_emin_bin + log_estep;
1278 (log_emin_bin + log_emax_bin));
1281 double wgt =
irf_weight(beta, log_emin_bin, log_emax_bin) * wgt0;
1291 #if defined(G_DEBUG_COMPUTE_IRF)
1292 wgt_check += wgt_low + wgt_up;
1296 for (
int idet = 0; idet < ndet; ++idet) {
1297 for (
int ireg = 0; ireg < nreg; ++ireg) {
1298 int map = idet + ireg * ndet;
1299 int map_low = map + irf_low * ndet * nreg;
1300 int map_up = map + irf_up * ndet * nreg;
1301 for (
int i = 0; i < npix; ++i) {
1302 irf(i, map) += wgt_low *
m_irfs(i, map_low) +
1303 wgt_up *
m_irfs(i, map_up);
1311 #if defined(G_DEBUG_COMPUTE_IRF)
1312 std::cout <<
"- wgt_check = " << wgt_check <<
" (should be 1)" << std::endl;
1328 for (
int idet = 0; idet < ndet; ++idet) {
1329 for (
int ireg = 0; ireg < nreg; ++ireg) {
1330 int map = idet + ireg * ndet;
1331 int map_low = map + irf_low * ndet * nreg;
1332 int map_up = map + irf_up * ndet * nreg;
1333 for (
int i = 0; i < npix; ++i) {
1334 irf(i, map) = wgt_low *
m_irfs(i, map_low) +
1335 wgt_up *
m_irfs(i, map_up);
1341 #if defined(G_DEBUG_COMPUTE_IRF)
1342 std::cout <<
"- wgt_low = " << wgt_low << std::endl;
1343 std::cout <<
"- wgt_up = " << wgt_up << std::endl;
1344 std::cout <<
"- wgt_low+wgt_up = " << wgt_low+wgt_up;
1345 std::cout <<
" (should be 1)" << std::endl;
1365 int naxis1 = image->
integer(
"NAXIS1");
1366 int naxis2 = image->
integer(
"NAXIS2");
1367 double crval1 = image->
real(
"CRVAL1");
1368 double crval2 = image->
real(
"CRVAL2");
1369 double crpix1 = image->
real(
"CRPIX1");
1370 double crpix2 = image->
real(
"CRPIX2");
1371 double cdelt1 = image->
real(
"CDELT1");
1372 double cdelt2 = image->
real(
"CDELT2");
1414 int npt = cube->
naxis(0);
1415 int ndet = cube->
naxis(1);
1418 for (
int ipt = 0; ipt < npt; ++ipt) {
1419 for (
int idet = 0; idet < ndet; ++idet) {
1425 std::vector<int>::iterator it = find(
m_detids.begin(),
m_detids.end(), detid);
1451 int npt = cube->
naxis(0);
1460 for (
int ipt = 0; ipt < npt; ++ipt) {
1515 const double& emax)
const
1521 if (std::abs(beta) < DBL_MIN) {
1522 weight = (emax - emin);
Energy boundaries class interface definition.
Energy container class definition.
Exception handler interface definition.
FITS binary table class definition.
FITS table double column class interface definition.
FITS table short integer column class interface definition.
FITS file class interface definition.
Point source spatial model class interface definition.
Node array class interface definition.
INTEGRAL/SPI event bin class definition.
INTEGRAL/SPI event bin container class definition.
INTEGRAL/SPI observation class definition.
INTEGRAL/SPI instrument response function class definition.
Energy boundaries container class.
void read(const GFitsTable &table)
Read energy boundaries from FITS table.
void append(const GEnergy &emin, const GEnergy &emax)
Append energy interval.
void clear(void)
Clear energy boundaries.
bool is_empty(void) const
Signal if there are no energy boundaries.
void write(GFits &file, const std::string &extname=gammalib::extname_ebounds, const std::string &unit="keV") const
Write energy boundaries into FITS object.
Class that handles energies in a unit independent way.
double keV(void) const
Return energy in keV.
Abstract interface for the event classes.
void ebounds(const GEbounds &ebounds)
Set energy boundaries.
std::string path(void) const
Return access path.
std::string url(void) const
Return Uniform Resource Locator (URL)
void clear(void)
Clear file name.
bool has_card(const int &cardno) const
Check existence of header card.
const std::string & extname(void) const
Return extension name.
double real(const std::string &keyname) const
Return card value as double precision.
std::string string(const std::string &keyname) const
Return card value as string.
GFitsHeaderCard & card(const int &cardno)
Return header card.
int integer(const std::string &keyname) const
Return card value as integer.
Abstract FITS image base class.
virtual double pixel(const int &ix) const =0
Abstract interface for FITS table column.
virtual int integer(const int &row, const int &inx=0) const =0
virtual double real(const int &row, const int &inx=0) const =0
void unit(const std::string &unit)
Set column unit.
FITS table double column.
FITS table short integer column.
Abstract interface for FITS table.
GFitsTableCol * append(const GFitsTableCol &column)
Append column to the table.
const int & nrows(void) const
Return number of rows in table.
void saveto(const GFilename &filename, const bool &clobber=false)
Saves to specified FITS file.
bool contains(const int &extno) const
Check if HDU exists in FITS file.
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
GFitsImage * image(const int &extno)
Get pointer to image HDU.
void close(void)
Close FITS file.
GFitsTable * table(const int &extno)
Get pointer to table HDU.
void set_value(const double &value) const
Set indices and weighting factors for interpolation.
const int & inx_right(void) const
Returns right node index.
const int & inx_left(void) const
Returns left node index.
void reserve(const int &num)
Reserves space for nodes in node array.
const double & wgt_right(void) const
Returns right node weight.
const double & wgt_left(void) const
Returns left node weight.
void clear(void)
Clear node array.
int size(void) const
Return number of nodes in node array.
void append(const double &node)
Append one node to array.
Abstract observation base class.
virtual GEvents * events(void)
Return events.
Class that handles photons.
const GSkyDir & dir(void) const
Return photon sky direction.
const GEnergy & energy(void) const
Return photon energy.
Abstract instrument response base class.
void init_members(void)
Initialise class members.
void free_members(void)
Delete class members.
virtual GResponse & operator=(const GResponse &rsp)
Assignment operator.
INTEGRAL/SPI event bin class.
const int & ipt(void) const
Return event bin pointing index.
const int & iebin(void) const
Return event bin energy index.
virtual const GSPIInstDir & dir(void) const
Return instrument direction.
const double & livetime(void) const
Return livetime of event bin.
INTEGRAL/SPI event bin container class.
const GSPIInstDir & dir(const int &ipt, const int &idet) const
Return instrument direction.
const GSkyDir & spi_z(const int &ipt) const
Return SPI Z direction.
virtual int naxis(const int &axis) const
Return number of bins in axis.
const GSkyDir & spi_x(const int &ipt) const
Return SPI X direction (pointing direction)
void detid(const int &detid)
Set detector identifier.
INTEGRAL/SPI observation class.
INTEGRAL/SPI instrument response function class.
double m_wcs_xpix_max
Maximum X pixel index.
void set_detids(const GSPIEventCube *cube)
Set vector of detector identifiers used by the observation.
virtual GSPIResponse & operator=(const GSPIResponse &rsp)
Assignment operator.
void write(GFits &fits) const
Write SPI response into FITS object.
double m_wcs_xbin
X value bin size (radians)
void save(const GFilename &filename, const bool &clobber=false) const
Save SPI response into file.
GSkyMap m_irfs
IRFs stored as sky map.
GNodeArray m_energies
Node array of IRF energies.
virtual double nroi(const GModelSky &model, const GEnergy &obsEng, const GTime &obsTime, const GObservation &obs) const
Return integral of event probability for a given sky model over ROI.
double irf_weight(const double &beta, const double &emin, const double &emax) const
Compute weight of logarithmic energy bin.
double m_wcs_ymin
Minimum Y value (radians)
virtual std::string print(const GChatter &chatter=NORMAL) const
Print INTEGRAL/SPI response information.
double m_wcs_ybin
Y value bin size (radians)
void set_wcs(const GFitsImage *image)
Set IRF image limits.
double irf_value(const GSkyDir &srcDir, const GSPIEventBin &bin, const int &ireg) const
Return value of INTEGRAL/SPI instrument response for sky direction and event bin.
void read(const GFits &fits)
Read SPI response from FITS object.
GSkyMap compute_irf(const double &emin, const double &emax) const
Compute as sky map.
virtual double irf(const GEvent &event, const GPhoton &photon, const GObservation &obs) const
Return value of INTEGRAL/SPI instrument response for a photon.
GSkyMap load_irf(const GFilename &rspname) const
Load IRF as sky map.
std::vector< GSkyDir > m_spix
SPI pointing direction.
double m_dlogE
Logarithmic energy step for IRF band.
void write_detids(GFits &fits) const
Write detector identifiers into FITS object.
void init_members(void)
Initialise class members.
virtual ~GSPIResponse(void)
Destructor.
double azimuth(const int &ipt, const GSkyDir &dir) const
Return azimuth angle of sky direction for pointing in radians.
void copy_members(const GSPIResponse &rsp)
Copy class members.
std::vector< int > m_detids
Vector of detector IDs.
void free_members(void)
Delete class members.
GFilename m_rspname
File name of response group.
void write_energies(GFits &fits) const
Write energies into FITS object.
void load(const GFilename &filename)
Load SPI response from file.
double m_wcs_ypix_max
Maximum Y pixel index.
double m_gamma
Power-law spectral index for IRF band.
void read_detids(const GFits &fits)
Read detector identifiers from FITS object.
void set_cache(const GSPIEventCube *cube)
Set computation cache.
int irf_detid(const int &detid) const
Convert detector identifier into IRF detector identifier.
double zenith(const int &ipt, const GSkyDir &dir) const
Return zenith angle of sky direction for pointing in radians.
double m_wcs_xmax
Maximum X value (radians)
double m_wcs_ymax
Maximum Y value (radians)
virtual GSPIResponse * clone(void) const
Clone instance.
double m_wcs_xmin
Minimum X value (radians)
double m_energy_keV
IRF line energy (optional)
GEbounds m_ebounds
Energy bounaries of IRF.
double m_max_zenith
Maximum zenith angle (radians)
void read_energies(const GFits &fits)
Read energies from FITS object.
GSPIResponse(void)
Void constructor.
virtual void clear(void)
Clear instance.
const GFilename & rspname(void) const
Get response group file name.
bool m_has_wcs
Has WCS information.
virtual GEbounds ebounds(const GEnergy &obsEnergy) const
Return true energy boundaries for a specific observed energy.
void set(const GSPIObservation &obs, const GEnergy &energy=GEnergy())
Set response for a specific observation.
std::vector< double > m_posang
Position angle of Y axis (CEL, radians)
void load_irfs(const int ®ion)
Load Instrument Response Functions.
double posang(const GSkyDir &dir, const std::string &coordsys="CEL") const
Compute position angle between sky directions in radians.
const int & nmaps(void) const
Returns number of maps.
void clear(void)
Clear instance.
const int & nx(void) const
Returns number of pixels in x coordinate.
void read(const GFitsHDU &hdu)
Read skymap from FITS HDU.
const int & npix(void) const
Returns number of pixels.
const int & ny(void) const
Returns number of pixels in y coordinate.
GFitsHDU * write(GFits &file, const std::string &extname="") const
Write sky map into FITS file.
const std::vector< int > & shape(void) const
Returns shape of maps.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
bool is_infinite(const double &x)
Signal if argument is infinite.
bool is_notanumber(const double &x)
Signal if argument is not a number.
const std::string extname_ebounds
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
int spi_num_hdus(const GFits &fits, const std::string &extname)
Return number of HDU versions.
const GFitsTable * spi_hdu(const GFits &fits, const std::string &extname, const int &extver=1)
Return FITS table.
const std::string extname_energies