Last modified: 23 Dec 2014


Determine if location is inside Field of View

CIAO 4.12 Science Threads



It may be necessary to determine if a celestial location (RA, Dec), is located within a Chandra observation. There are several ways to get an approximate answer by doing a radius search around the observation's nominal pointing RA_PNT,DEC_PNT. However, especially for ACIS observations, this can lead to many incorrect results since the number and configuration of CCDs varies between observations. There are also things such as subarrays and windows to consider which can further limit the field of view.

One of the standard Chandra data products is a Field of View (FOV) file -- a FITS region file that provides a polygon around each CCD.


Remember that due to dither, the square CCDs are "blurred" on the sky so the observed field of view must be described by a polygon.

This thread will show how to use the FOV files to determine if a celestial location, rather than a physical location, is located in a particular Chandra observation.


To determine if a position is within the field of view of a Chandra observation.

Related Links:

Last Update: 23 Dec 2014 - Reviewed for CIAO 4.7; no changes.


Getting Started

Download the sample data: 5794 (SDSS J1004+4112)

unix% download_chandra_obsid 5794 fov


Check if celestial location is inside FOV

As with all Chandra FITS region files, the coordinates in the FOV file are stored in sky pixels, on the same tangent plane used by the event file for the observation. However, the POS (position) column also has a World Coordinate System (WCS) to convert the X,Y values to RA,Dec. This can be seen when the file is dmlist'd with the cols options:

unix% dmlist acis_fov.fits cols
Columns for Table Block FOV
ColNo  Name                 Unit        Type             Range
   1   POS(X,Y)[13]         pixel        Real8(13)      -Inf:+Inf            Position
   2   SHAPE                             String[16]                          Region shape type
   3   R[2]                 pixel        Real8(2)       -Inf:+Inf            Radius
   4   ROTANG[2]            pixel        Real8(2)       -Inf:+Inf            Angle
   5   COMPONENT                         Int2           -                    Component number
   6   CCD_ID                            Int2           -                    CCD ID
World Coord Transforms for Columns in Table Block FOV
ColNo    Name
1:    EQPOS(RA ) = (+151.1396)[degree] +TAN[(-0.000136667)* (POS(X)-(+4096.50))]
           (DEC)   (+41.2327 )              (+0.000136667)  (   (Y) (+4096.50)) 

By default when CIAO tools and applications try to use the FOV files they will use the POS position values, which are simply sky X and Y values. For example using the CIAO Python region module

unix% chips -n
chips> from region import *
chips> myreg = regParse("region(acis_fov.fits)")
chips> regPrintRegion(myreg)
1	POLYGON     (Pos: pixel, Size: pixel)	(3444.117776,3350.854062)	
(3444.267914,3350.723266)	(4448.914811,3189.872261)	
(4486.690055,3189.901456)	(4486.873430,3189.978306)	
(4647.906504,4196.681895)	(4647.905087,4233.937865)	
(4647.880421,4234.048007)	(3643.098937,4394.839952)	
(3605.418653,4394.877205)	(3605.360752,4394.779719)	
(3444.119379,3388.110141)	(3444.117776,3350.854062)	 

This shows the POLYGON shape and the typical ACIS sky position values (in the 3000-5000 range). However, this is not directly useful when a celestial location, RA,Dec in decimal degrees, needs to be checked.

Using the CXC Datamodel virtual file syntax, it is possible to change the above example to use the WCS values in the virtual EQPOS column. By using a [cols ] filter, the virtual EQPOS column will be used instead of the sky positions as shown below

chips> mycelreg = regParse("region(acis_fov.fits[cols eqpos,shape,component]")
chips> regPrintRegion(mycelreg)
1	POLYGON     (Pos: pixel, Size: pixel)	(151.257958,41.130691)	
(151.257931,41.130673)	(151.075664,41.108733)	
(151.068812,41.108733)	(151.068779,41.108744)	
(151.039359,41.246305)	(151.039352,41.251396)	
(151.039356,41.251411)	(151.222033,41.273400)	
(151.228885,41.273400)	(151.228896,41.273387)	
(151.257967,41.135783)	(151.257958,41.130691)	 

The additional columns, shape and component are needed to complete the FITS region definition. The polygon points are now the sky X,Y values converted to RA,Dec.

The regInsideRegion routine can then be used to check whether a celestial location is within the field-of-view. Below the nominal pointing is checked along with a location several degrees away.

chips> !dmlist acis_fov.fits header,clean | grep PNT   
RA_PNT                     151.1395864022 [deg]     Pointing RA
DEC_PNT                     41.2326566497 [deg]     Pointing Dec
ROLL_PNT                    99.0636885982 [deg]     Pointing Roll
chips> regInsideRegion(mycelreg, 151.1395864022, 41.2326566497 )
chips> regInsideRegion(mycelreg, 145.2, 45.0 )

Checking several FOV files

This technique has been scripted into the FOVFiles Python class. After users have downloaded a set of FOV files, they can use this routine to determine which observations, from those they have downloaded, contains data for the requested location. This is essentially a local footprint service. An example is shown here:

unix% find_chandra_obsid "SDSS J1004+4112"
# obsid  sepn   inst grat   time    obsdate   piname            target
5794      0.2 ACIS-S NONE   81.1 2005-01-01    Inada "SDSS J1004+4112"
11546     0.1 ACIS-S NONE    6.0 2010-03-08 Kochanek     SDSS1004+4112
11547     0.1 ACIS-S NONE    6.0 2010-06-19 Kochanek     SDSS1004+4112
11548     0.1 ACIS-S NONE    6.0 2010-09-23 Kochanek     SDSS1004+4112
11549     0.1 ACIS-S NONE    6.0 2011-01-30 Kochanek     SDSS1004+4112
14495     0.1 ACIS-S NONE   24.7 2013-01-27 Kochanek     SDSS1004+4112
14496     0.1 ACIS-S NONE   24.7 2013-03-01 Kochanek     SDSS1004+4112

unix% mkdir SDSS1004+4112
unix% cd SDSS1004+4112
unix% download_chandra_obsid 5794,11546,11547,11548,11549,14495,14496 fov
unix% mv */primary/*fov1.fits.gz .
unix% python

>>> from ciao_contrib.region.check_fov import FOVFiles
>>> regions = FOVFiles("*fov1.fits.gz")
>>> print(regions)
List of FOV files

>>> regions.inside( 151.25426, 41.090654)

In this example all the observations that include SDSS J1004+4112 are located using the find_chandra_obsid script and the FOV files are retrieved. Since the FOV files are small (only a few kBytes per file), they can be retrieved and used quickly before deciding which full datasets need to be downloaded. The FOVFiles object is then used to load all the files that were retrieved and to check the coverage of a location. In this example only 3 out of the 8 observations imaged the location.


This thread has shown how to use DM virtual file syntax to access the World Coordinate System attached to the sky position column in a Field of View file. This allows the user to easily check if arbitrary celestial coordinate are included in an observation.


The Chandra FOV files are not the tightest possible bounding polygon around the data. It may be slightly bigger (never smaller) than the actual footprint of the date due to dither, bad detector pixels, and based on the roll angle of the spacecraft. The gap is no more than half the dither pattern (based on roll).

This technique is used by the CXC Footprint service. The Level 1 FOV files are converted to celestial coordinates and stored in a database which is queried to determine which observations observed the input position.


31 Mar 2014 Initial version.
16 Jul 2014 Added section showing how to use new FOVFiles routines to automate for multiple FOV files.
23 Dec 2014 Reviewed for CIAO 4.7; no changes.