Event File Tools

This section documents some helpful tools to take event files produced by the SOXS instrument simulator and make derivative products from them.

make_exposure_map

Exposure maps are maps of exposure for a given X-ray energy or range of energies, giving the effective exposure as a function of position on the sky. Uneven exposure may occur because of spacecraft dithering, chip gaps, or differences in effective area at different points on a chip (though the latter effect is currently not simulated in SOXS). For a more thorough explanation of exposure maps, see Introduction to Exposure Maps.

make_exposure_map() creates an exposure map for SOXS event files. This may be needed particularly if you have a simulation with dither and are concerned about effects near the edges of chips, but it will work for any event file produced by SOXS. This function determines the effective area for a given input energy or range of energies weighted by a spectrum, and then uses the aspect solution (the RA and Dec of the spacecraft pointing as a function of time) to create a histogram of aspect to determine how much time a given detector coordinate spent on a given sky location. These pieces of information are then used to produce a map of total exposure for the observation in sky coordinates. Exposure maps can be “reblocked” to a lower resolution, and this will typically speed up the computation of the exposure map.

To make an exposure map with the default parameters using an energy of 4.0 keV:

import soxs
soxs.make_exposure_map("my_evt.fits", "my_expmap.fits", 4.0, overwrite=True)

If you have an idea of what the spectrum of the object is, you can alternatively use an energy range and the spectrum itself as a set of “weights” to make a weighted exposure map. This example uses a Spectrum object spec:

import soxs

energy = spec.emid.value
weights = spec.flux.value

soxs.make_exposure_map("my_evt.fits", "my_expmap.fits", energy, weights=weights,
                       overwrite=True)

By default, exposure maps are computed in units of \(\rm{cm^2} \times \rm{s}\) and then divided by the exposure time to get a map in units of \(\rm{cm}^2\). To turn off this normalization and get a map in units of \(\rm{cm^2} \times \rm{s}\), set normalize=False:

import soxs
soxs.make_exposure_map("my_evt.fits", "my_expmap.fits", 4.0,
                       overwrite=True, normalize=False)

To write the aspect solution to a file, set the asol_file keyword to the file you want to use:

import soxs
soxs.make_exposure_map("my_evt.fits", "my_expmap.fits", 4.0,
                       overwrite=True, asol_file="my_asol.fits")

By default, the aspect is binned into a histogram of 16x16 bins covering the range of the aspect solution pattern. To change this binning, use the nhistx and nhisty keywords:

import soxs
soxs.make_exposure_map("my_evt.fits", "my_expmap.fits", 4.0,
                       overwrite=True, nhistx=32, nhisty=32)

To create an exposure map with pixels 4 times larger on a side, set the reblock parameter to 4:

import soxs
soxs.make_exposure_map("my_evt.fits", "my_expmap.fits", 4.0,
                       overwrite=True, reblock=4)

Examples of images and exposure maps for a simulation of a galaxy cluster for Chandra/ACIS-I and Athena/XIFU are shown in Figure 1.

../_images/exposure_maps.png

Figure 1: Images (left), exposure-corrected images (center) and exposure maps (right) for mock observations of a galaxy cluster for Chandra/ACIS-I (top) and Athena/XIFU (bottom), simulated using SOXS.

Warning

The make_exposure_map() tool only produces exposure maps for event files produced by SOXS, and this is the only tool that should be used for this purpose for event files produced by SOXS.

write_image

write_image() bins up events into an image according to the coordinate system inherent in the event file and writes the image to a FITS file. Images of sky, detector, or chip coordinates can be written. You can also restrict events within a particular energy range to be written to the file.

To write an image in sky coordinates:

from soxs import write_image
# Energy bounds are in keV
write_image("my_evt.fits", "my_sky_img.fits", emin=0.5, emax=7.0)

Or in detector coordinates:

write_image("my_evt.fits", "my_sky_img.fits", coord_type='det', emin=0.5, emax=7.0)

Or in chip coordinates:

write_image("my_evt.fits", "my_sky_img.fits", coord_type='sky', emin=0.5, emax=7.0)

To supply an exposure map produced by make_exposure_map() to make a flux image:

write_image("my_evt.fits", "my_sky_img.fits", coord_type='sky', emin=0.5, emax=7.0,
            expmap_file="my_expmap.fits")

To bin at a pixel size 4 times larger than the native pixel size, set reblock to 4:

write_image("my_evt.fits", "my_sky_img.fits", coord_type='sky', emin=0.5, emax=7.0,
            expmap_file="my_expmap.fits", reblock=4)

Note that if you set reblock and supply an exposure map, it must have been made with the same value of reblock.

This image can then be viewed in ds9 or APLpy.

write_radial_profile

write_radial_profile() bins up events into an radial profile defined by source center, a minimum radius, a maximum radius, and a number of bins. One can restrict the events that are binned by a specific energy band. An example execution:

from soxs import write_radial_profile
ctr = [30.0, 45.0] # by default the center is in celestial coordinates
rmin = 0.0 # arcseconds
rmax = 100.0 # arcseconds
nbins = 100 # number of bins
emin = 0.5 # keV
emax = 2.0 # keV
write_radial_profile("my_evt.fits", "my_radial_profile.fits", ctr, rmin,
                     rmax, nbins, emin=emin, emax=emax, overwrite=True)

If one wants to specify a center in physical pixel coordinates, you can use the same execution but set the ctr_type keyword to “physical” and use physical pixel coordinates as the ctr argument:

from soxs import write_radial_profile
ctr = [2048.5, 2048.5] # by default the center is in celestial coordinates
rmin = 0.0 # arcseconds
rmax = 100.0 # arcseconds
nbins = 100 # number of bins
emin = 0.5 # keV
emax = 2.0 # keV
write_radial_profile("my_evt.fits", "my_radial_profile.fits", ctr, rmin,
                     rmax, nbins, ctr_type="physical", emin=emin, emax=emax,
                     overwrite=True)

If one wants to compute flux-based quantities for the radial profile (such as surface flux), supply an exposure map produced by make_exposure_map():

write_radial_profile("my_evt.fits", "my_radial_profile.fits", ctr, rmin,
                     rmax, nbins, ctr_type="physical", emin=emin, emax=emax,
                     expmap_file="my_expmap.fits", overwrite=True)

A cookbook example showing how to extract a radial profile is shown in Radial Profile.

write_spectrum

write_spectrum() bins up events into a spectrum and writes the spectrum to a FITS file:

from soxs import write_spectrum
write_spectrum("my_evt.fits", "my_spec.pha", overwrite=True)

This spectrum file can be read and fit with standard X-ray analysis software such as XSPEC, ISIS, and Sherpa.

plot_spectrum

plot_spectrum() reads a spectrum stored in a FITS table file and makes a Matplotlib plot. There are a number of options for customizing the plot in the call to plot_spectrum(), but the method also returns a tuple of the Figure and the Axes objects to allow for further customization. This example opens up a spectrum file and plots it between 0.5 and 7.0 keV:

from soxs import plot_spectrum
plot_spectrum("evt.pha", xmin=0.5, xmax=7.0)
../_images/mucal_plot.png

If one wanted to plot the same spectrum in channel space instead of energy space, you would set plot_energy=False:

from soxs import plot_spectrum
plot_spectrum("evt.pha", plot_energy=False, xmin=300, xmax=7000)
../_images/mucal_plot_channel.png

where in that case the x-axis is now in channel space, so xmin and xmax had to be set accordingly. For other customizations, consult the plot_spectrum() API.