Chandra X-Ray Observatory (CXC)
Skip to the navigation links
Last modified: December 2012

URL: http://cxc.harvard.edu/ciao/crates.html
AHELP for CIAO 4.5

crates

Context: crates

Synopsis

CRATES - A high-level I/O interface for Python

Description

CRATES is a software package developed by the Chandra X-Ray Center (CXC) to provide a high level I/O interface for use by Python. The CIAO applications ChIPS and Sherpa use CRATES to read input data for use in plotting and fitting and to write output data files. It supports reading and writing both FITS and ASCII files.

The classes and methods allow a user to easily access and manipulate general data files. There are specialized classes for specific data products (e.g. PHA Type I and II and RMF). CRATES also provides convenient access to metadata information, such as keywords and WCS transforms, which may be associated with a table column or image.

It can be used from Python by saying

from pycrates import *

The Sherpa and ChIPS environments automatically load CRATES at startup. There are help files for each of the CRATES commands; a full list can be seen with the following command

unix% ahelp -c crates

Example 1

chips> cr = read_file("evt2.fits")
chips> print(get_keyval(cr, "OBJECT"))
ELAIS-S1 A
chips> print(get_keyval(cr, "EXPOSURE") / 1000)
31.7432921583

Here we get the values of the OBJECT and EXPOSURE keywords from the header of evt2.fits. The return value from get_keyval() uses the appropriate Python type, so OBJECT is a string and the exposure time is a number.

Example 2

>>> from pycrates import *
>>> cr = read_file("evt2.fits[ccd_id=7,energy=300:7000]")
>>> e = copy_colvals(cr, "energy")
>>> emin = e.min() / 1000
>>> emax = e.max() / 1000
>>> emean = e.mean() / 1000
>>> print("Mean E = {0} min= {1} max= {2}".format(emean, emin, emax))
Mean E = 3.10554851929 min= 0.300000335693 max= 6.99996289063

Here we read in the energy column from an event file and calculate the minimum, maximum and mean energy in keV.

Example 3

>>> import numpy as np
>>> import pycrates as *
>>> import pychips.all as pychips
>>> cr = read_file("0.5-7.0_bin2.img")
>>> img = copy_piximgvals(cr)
>>> pychips.add_image(np.log10(img))
Warning: divide by zero encountered in log10
>>> pychips.add_image("2.3_bin2.expmap", ["wcs", "logical", "alpha",
[0.2,0.2]])

Here we display the logarithm of the pixel values using the ChIPS add_image() command and then overlay the exposure map for the observation, using transparency to ensure that the image can still be seen.

To display the data using the EQPOS (or SKY) coordinate system, you could copy the transformed pixel values back into the crate and use that; for example

>>> pychips.clear()
>>> pychips.add_window(8, 8, "inches")
>>> set_piximgvals(cr, np.log10(img))
Warning: divide by zero encountered in log10
>>> pychips.add_image(cr)
>>> pychips.add_image("2.3_bin2.expmap", ["alpha", [0.2,0.2]])

The divide-by-zero warning

The warning about divide by zero comes from NumPy and can be turned off using the seterr routine; for example

>>> olderr = np.seterr(divide='ignore')

Example 4

chips> x = np.arange(1, 10)
chips> y = np.sin(x) * np.cos(x)
chips> z = x**2 + y**2
chips> xcol = CrateData()
chips> xcol.name = "x"
chips> xcol.values = x
chips> ycol = CrateData()
chips> ycol.name = "y"
chips> ycol.values = y
chips> zcol = CrateData()
chips> zcol.name = "zz"
chips> zcol.values = z
chips> cr = TABLECrate()
chips> add_col(cr, xcol)
chips> add_col(cr, ycol)
chips> add_col(cr, zcol)
chips> write_file(cr, "out.fits")
chips> write_file(cr, "out.dat[opt kernel=text/simple]")
chips> !cat out.dat
#TEXT/SIMPLE
# x y zz
1 4.5464871341284e-01 1.206705452608
2 -3.7840124765396e-01 4.143187504226
3 -1.3970774909946e-01 9.019518255158
4 4.9467912331169e-01 16.24470743504
5 -2.7201055544468e-01 25.07398974227
6 -2.6828645900022e-01 36.07197762408
7 4.9530367784744e-01 49.24532573329
8 -1.4395165833253e-01 64.02072207994
9 -3.7549362338584e-01 81.14099546120

Here we create two files containing the contents of the x, y, and z arrays in columns called "x", "y", and "zz" respectively. The file out.fits is a FITS binary table whereas out.dat is an ASCII file (see ahelp dmascii for more information on ASCII support in the CIAO Data model).

Example 5

chips> ivals = np.arange(12).reshape(3, 4)
chips> cd = CrateData()
chips> cd.values = ivals
chips> cr = IMAGECrate()
chips> add_piximg(cr, cd)
chips> cr.name = "SIMPLE"
chips> write_file(cr, "img.fits")

Here we create an image, with dimensions of 4 (x) by 3 (y), add it to an IMAGECrate using add_piximg (note that add_image is a ChIPS call that displays an image), and write it out to the file img.fits. After these commands we have:

chips> print(cr)
   Crate Type:        <IMAGECrate>
   Crate Name:        SIMPLE
   Crate Number:      0

chips> !dmlist img.fits blocks
 
--------------------------------------------------------------------------------
Dataset: img.fits
--------------------------------------------------------------------------------
 
     Block Name                          Type         Dimensions
--------------------------------------------------------------------------------
Block    1: SIMPLE                         Image      Int4(4x3)
chips> !dmstat img.fits centroid-
SIMPLE
    min:	0 	      @:	( 1 1 )
    max:	11 	      @:	( 4 3 )
   mean:	5.5 
  sigma:	3.4520525295 
    sum:	66 
   good:	12 
   null:	0 

Example 6

unix% cat qconv.py
#!/usr/bin/env python
import sys
import pycrates as pyc
cr = pyc.read_file(sys.argv[1])
sky = cr.get_transform("SKY")
x = float(sys.argv[2])
y = float(sys.argv[3])
lcoord = [[x, y]]
scoord = sky.apply_transform(lcoord)
print("Logical {0} -> SKY {1}".format(lcoord[0], scoord[0]))

This simple Python script (which has no sanity checks such as ensuring the number of command-line arguments is correct) will convert the logical coordinates given on the command line to SKY coordinates using the transform taken from the first argument. An example run (which assumes the executable bit is set) is given below:

unix% ./qconv.py img.fits 1 1
Logical [1.0, 1.0] -> SKY [ 2009.5 3149.5]

Changes in CIAO 4.5

Memory-management improvements

Memory is now correctly freed up when a variable containing a Crate goes out of scope. This means that the work-around

cr.get_dataset().snip()

is no longer needed (but can be retained, since the snip() routine does nothing in CIAO 4.5).

The Crates object

The get_filename attribute of a Crate now includes any Data-Model filter:

chips> cr = read_file("evt2.fits[energy=500:1000][bin sky=8]")
chips> cr.get_filename()
       'evt2.fits[energy=500:1000][bin sky=8]'

where the return would have just been 'evt2.fits' in CIAO 4.4.

New routine

The set_key() routine has been added, which simplifies adding a keyword to a Crate.

Improved transform support

The transform library (ahelp transform) has been updated to support 1D linear transformations.

Bugs

Writing a crate with a string column into a file increases the string length by one.  (08 Oct 2012)

Writing a crate with a string column into a file increases the string length by one. Repeatedly reading and writing a file will cause the string length to grow with each iteration.

chips> crate = read_file('tmp.fits')
chips> crate.write('tmp1.fits')
chips> exit()

unix%  dmlist tmp.fits cols |grep MLE
   54 MLEBAND  String[4] mleband
unix%  dmlist tmp1.fits cols | grep MLE
   54 MLEBAND  String[5] mleband 

In the above example the string column has grown by one. Repeating the chips commands with tmp1.fits as input will cause the column to grow again.

Using numpy views of arrays can lead to data corruption.  (08 Oct 2012)

numpy uses a special indexing scheme to access arrays that have been sliced (ie truncated at either end) or when for example transposing 2D arrays. The origianal data are preserved and the user only sees a view of the array.

The crates python to datamodel C interface does not handle views correctly. It may result in data being truncated or simply producing nonsensical results.

Users should make sure that any arrays sent to pycrates are in C_CONTIGUOUS order and ALGINED

chips-1> foo = np.arange(10).reshape(5,2)
chips-2> foo2 = bob.T
chips-3> foo.flags

   C_CONTIGUOUS : True
   F_CONTIGUOUS : False
   OWNDATA : False
   WRITEABLE : True
   ALIGNED : True
   UPDATEIFCOPY : False
chips-4> foo2.flags

   C_CONTIGUOUS : False
   F_CONTIGUOUS : True
   OWNDATA : False
   WRITEABLE : True
   ALIGNED : True
   UPDATEIFCOPY : False 
ASCII files with non-alphanumeric column names can leads to inaccessible crates.  (08 Oct 2012)

If an ASCII file is loaded into a crate that has non-alphanumeric characters, then the crate data may become inaccessible.

Column names should only contain letters A-Z (case insensitive), numbers 0-9, and underscores. Column names that contain square braces, paranthese, or any other character may cause problems.

Files with 1D linear transforms  (07 Sep 2012)

pycrates does not support 1D, linear transforms. It tries to create a 2D transform which causes memory corruption and may lead to either a crash (Segmentation Violation) or could lead to incorrect results.

Users can check if their file contains a 1D transform by using dmlist to list the columns and look for any coordinates transforms that look like

unix% dmlist myfile.fits cols
...
World Coord Transforms for Columns in Table Block EVENTS
--------------------------------------------------------------------------------
 
ColNo    Name
3:    CPC(CPCX) = (+0)[mm] +(+0.0240)* (chip(chipx)-(+0.50))
         (CPCY)   (+0)      (+0.0240)  (    (chipy) (+0.50))
4:    MSC(PHI  ) = (+0)[deg] +TAN-P[(+0.000136667)* (det(detx)-(+4096.50))]
         (THETA)   (+0)             (+0.000136667)  (   (dety) (+4096.50)) 
5:    EQPOS(RA ) = (+270.1153)[deg] +TAN[(-0.000136667)* (sky(x)-(+4096.50))]
           (DEC)   (-24.0418 )           (+0.000136667)  (   (y) (+4096.50)) 
6:    pha_COORD            = pha 

Here, the pha column has a 1D linear transform attached to it and would cause problems with pycrates.

Another example would be

unix% dmlist dmextract29b.out cols
 ...
--------------------------------------------------------------------------------
World Coord Transforms for Columns in Table Block HISTOGRAM
--------------------------------------------------------------------------------
 
ColNo    Name
4:    CEL_R                = +0 [arcsec] +0.4920 * (R  -0)
9:    CEL_AREA             = +0 [arcsec**2] +0.2421 * (AREA  -0)
17:   CEL_BRI              = +0 [count/arcsec**2] +4.1311 * (SUR_BRI  -0)
18:   CEL_BRI_ERR          = +0 [count/arcsec**2] +4.1311 * (SUR_BRI_ERR  -0)

All these columns are 1D linear transforms that would cause pycrates a problem.

Some example of files with linear transforms include

  • Radial profiles output from dmextract
  • ACIS Blank Sky background files with '2005' date
  • Event files
  • Aspect histogram files created by asphist

Currently there is no generic work around. If you do not need to use the column with the linear transform, you can just exclude it using a [cols -column_name] filter. If you need to use the column that has a transform attached, contact Helpdesk and we will try to help with a custom solution.

Adding a column without a name creates a column called () in the output file  (03 Jan 2012)
chips> cr = TABLECrate() 
chips> cd = CrateData() 
chips> cd.values = np.arange(20,31) 
chips> add_col(cr, cd) 
chips> cr.get_colnames() 
          ['']
chips> cr.write("/tmp/temp.fits") 
chips> !dmlist /tmp/temp.fits cols
 
--------------------------------------------------------------------------------
Columns for Table Block HDU2
--------------------------------------------------------------------------------
 
ColNo  Name                 Unit        Type             Range
   1   ()                                Int4           -                    
Numerical subspace ranges are not propagated correctly  (06 Jan 2012)
(Mac OS X)

This file was read with CRATES and then written out again. The numerical subspace ranges have been replaced by "DEFAULT":

dmlist pha_copy.fits"[REGION]" subspace 
 
--------------------------------------------------------------------------------
Data subspace for block REGION: Components: 1 Descriptors: 11 
--------------------------------------------------------------------------------
 
 --- Component 1 --- 
   1 SPEC_NUM             Int2                1:16384 
   2 ROWID                String              
   3 SHAPE                String              
   4 TG_R                 Real8               DEFAULT
   5 TG_D                 Real8               DEFAULT
   6 R                    Real8               DEFAULT
   7 ROTANG               Real8               DEFAULT
   8 COMPONENT            Int2                DEFAULT
   9 INCLUDE              Int2                DEFAULT
  10 TG_SRCID             Int2                DEFAULT
  11 TG_M                 Int2                DEFAULT 

Caveats

Cannot add rows to a column that is part of a virtual column.  (08 Oct 2012)

Users can not add rows a column which is a component of a vector using Crates (the new values are set to 0). User can extend scalar and array columns. To work around this, users must add rows the vector column itself rather than the components.

See Also

contrib
add_colvals, add_keyval, make_image_crate, make_table_crate, scale_image_crate, smooth_image_crate, write_arrays, write_columns
crates
add_col, add_key, add_piximg, col_exists, copy_colvals, copy_piximgvals, cratedata, cratekey, delete_col, delete_key, delete_piximg, get_axis_transform, get_col, get_col_names, get_colvals, get_crate_item_type, get_crate_type, get_key, get_key_names, get_keyval, get_number_cols, get_number_rows, get_piximg, get_piximg_shape, get_piximgvals, get_transform, get_transform_matrix, is_pha, is_rmf, is_virtual, key_exists, print_crate_names, read_file, read_pha, read_rmf, set_colvals, set_key, set_keyval, set_piximgvals, write_file, write_pha, write_rmf

Last modified: December 2012
CXC logo

The Chandra X-Ray Center (CXC) is operated for NASA by the Smithsonian Astrophysical Observatory. 60 Garden Street, Cambridge, MA 02138 USA.   Email: cxcweb@head.cfa.harvard.edu Smithsonian Institution, Copyright © 1998-2012. All rights reserved.