Last modified: October 2023

AHELP for CIAO 4.16


Context: psf


A Python module to calculate the size or enclosed-counts fraction of the Chandra PSF


The psf module is used to calculate an estimate of the size of the Chandra PSF at a given off-axis position and energy, or the enclosed fraction of energy at a given off-axis position and extraction radius.

What does 'size of the PSF' mean?

For this module, the size of the PSF refers to the radius of a circular region that encloses a given fraction of the counts from a point source. The values are calculated by interpolating the values from the REEF file found in the CALDB. It is therefore an approximation to the true PSF.

Loading the module

The module can be loaded by saying

import psf

Functions provided by the module

The following functions are provided by the module:

Function Description
psfClose Release the data read in by psfInit
psfFrac Calculate the enclosed-counts fraction for a given size
psfInit Read in the PSF data from a file
psfSize Calculate the size for a given enclosed-counts fraction

Using the module

The module must be initialized using the psfInit() routine, which returns a value that is then used by the psfFrac() or psfSize() routines. The psfClose() routine is then used to release the resources acquired bu the psfInit() routine.


The psfClose() routine releases the data read in by the psfInit() routine. It has no return value and is sent one argument, the object returned by psfInit().


This routine reads in the PSF data from the given filename (the CALDB REEF file) and returns an object which is used by the psfFrac() and psfSize() routiens. The psfClose() routine is used to release this information.

psfFrac(pdata, energy, theta, phi, size)

Returns the enclosed-count fraction for a PSF with the given energy (in keV), position (theta in arcminutes and phi in degrees), and size (in arcsec).

psfSize(pdata, energy, theta, phi, ecf)

Returns the radius, in arcsec, for a PSF with the given energy (in keV), position (theta in arcminutes and phi in degrees), and enclosed-count fraction (0 to 1).

Calculating the theta and phi values for a sourec

The dmcoords tool can be used to convert a position (e.g. celestial or in sky coordinates) to the required theta and phi coordinate system (the MSC coordinate system described in "ahelp coords"). Please note that


Example 1

>>> import psf
>>> import caldb4
>>> cdb = caldb4.Caldb(telescope="CHANDRA", product="REEF")
>>> reef =[0]
>>> reef = reef.split('[')[0]
>>> pdata = psf.psfInit(reef)
# ... do something interesting
>>> psf.psfClose(pdata)

Here we load in the PSF data into the pdata variable, do something with it, then release the data. The following examples can be considered as the "interesting" part of the code above.

Example 2

>>> f2 = psf.psfFrac(pdata, 2, 4, 225, 2)
>>> f3 = psf.psfFrac(pdata, 2, 4, 225, 3)
>>> f4 = psf.psfFrac(pdata, 2, 4, 225, 4)
>>> print(f"Fractions: {f2} {f3} {f4}")
Fractions: 0.778108093119 0.92679541645 0.952283503534

Here we calculate the enclosed-count fractions (ECF) for the radii 2, 3 and 4 arcseconds for a source located at an off-axis angle of 4 arcminutes with a PHI of 225 degrees. The calculation is made at an energy of 2 keV.

Example 3

>>> e5 = psf.psfSize(pdata, 2, 4, 225, 0.5)
>>> e7 = psf.psfSize(pdata, 2, 4, 225, 0.7)
>>> e9 = psf.psfSize(pdata, 2, 4, 225, 0.9)
>>> print(f"Radii (arcsec): {e5} {e7} {e9}")
Radii (arcsec): 1.26743534207 1.76177912951 2.63139134645

Here we calculate the radii where the enclosed-count-fractions of the source are 0.5, 0.7 and 0.9. As with the previous example the source is at 4 arcminutes off-axis angle at PHI of 225 degrees and has an energy of 2 keV.

Example 4

The psfSize() and psfFrac() routines only calcualte a single value, but they can easily be used to calculate a range of values. The following routine (esize) calculates the 90% enclosed-counts fraction for a source at the given theta and phi values for the energy range 0.3 to 9 keV:

def esize(pdata, theta, phi):
    "Calculate the 90% ECF for a range of energies"

    energies = np.arange(0.3, 9.1, 0.1)
    sizes = [psf.psfSize(pdata, e, theta, phi, 0.9) for e in energies]
    return (energies, np.array(sizes))

which could be used to plot up the curve using matplotlib:

>>> (e, s) = esize(pdata, 8, 345)
>>> import matplotlib.pylab as plt
>>> plt.plot(e, s, marker='')
>>> plt.xlabel("Energy (keV)")
>>> plt.ylabel("Radius (arcsec)")
>>> plt.title(r"$\theta=8' \phi=345\degree$")
>>> plt.text(0.1, 0.9, "90%")

Location of the REEF File

The psfInit() routine needs the location of the REEF file. Whilst this can be hard-coded, it is safest to query the CALDB for its location, in case it ever gets updated. This can be done from the command line or via Python, as shown below.

unix% punlearn calquiz
unix% calquiz telescope=CHANDRA product=REEF mode=h
unix% pget calquiz outfile

where the above output assumes that the environment variable CALDB is set to /soft/ciao/CALDB.

Using the caldb4 Python module

The following Python code, taking advantage of the caldb4 module provided by CIAO, can be used:

import psf
import caldb4
cdb = caldb4.Caldb(telescope="CHANDRA", product="REEF")
reef =[0]
extno = cdb.extno()
# Replace the trailing '[..]' block number specifier
reef = reef.split('[')[0] + f"[{extno+1}]"
pdata = psf.psfInit(reef)

Since the caldb module returns the file name using the FITSIO block-numbering convention (where the first block is 0), but psfInit requires the CXCDM Data Model convention (where the first block is 1), we have to convert the block number. With the REEF file included in the CALDB at the CIAO 4.5 release, we do not actually need to include the f"[{extno+1}]" part, since the file will load with no block number, but this is left in for completeness.

The REEF file

The latest information on the REEF file can be found in the Chandra CALDB website, in particular the HRMA calibration page.

The Radial Encircled Energy Function format is described in the OGIP Calibration Memo CAL/GEN/92-020.

See Also

asphist, dither_region
acis_bkgrnd_lookup, hrc_bkgrnd_lookup, readout_bkg
combine_grating_spectra, combine_spectra, specextract
acis_fef_lookup, acis_set_ardlib, addresp, dmarfadd, eff2evt, find_mono_energy, fullgarf, make_instmap_weights, mean_energy_map, mkacisrmf, mkarf, mkexpmap, mkgarf, mkgrmf, mkinstmap, mkpsfmap, mkrmf, mkwarf, psf_project_ray, rmfimg