A python library to read from and write to FITS files.
Description
This is a python extension written in c and python. Data are read into
numerical python arrays.
A version of cfitsio is bundled with this package, there is no need to install
your own, nor will this conflict with a version you have installed.
Some Features
- Read from and write to image, binary, and ascii table extensions.
- Read arbitrary subsets of table columns and rows without loading all the data
to memory.
- Read image subsets without reading the whole image. Write subsets to existing images.
- Write and read variable length table columns.
- Read images and tables using slice notation similar to numpy arrays. This is like a more
powerful memmap, since it is column-aware for tables.
- Append rows to an existing table. Delete row sets and row ranges. Resize tables,
or insert rows.
- Query the columns and rows in a table.
- Read and write header keywords.
- Read and write images in tile-compressed format (RICE,GZIP,PLIO,HCOMPRESS).
- Read/write gzip files directly. Read unix compress (.Z,.zip) and bzip2 (.bz2) files.
- TDIM information is used to return array columns in the correct shape.
- Write and read string table columns, including array columns of arbitrary
shape.
- Read and write complex, bool (logical), unsigned integer, signed bytes types.
- Write checksums into the header and verify them.
- Insert new columns into tables in-place.
- Iterate over rows in a table. Data are buffered for efficiency.
- python 3 support, including python 3 strings
Examples
import fitsio
from fitsio import FITS,FITSHDR
filename='data.fits'
data = fitsio.read(filename)
data = fitsio.read(filename, rows=[35,1001], columns=['x','y'], ext=2)
h = fitsio.read_header(filename)
data,h = fitsio.read(filename, header=True)
data = np.zeros(10, dtype=[('id','i8'),('ra','f8'),('dec','f8')])
fitsio.write(filename, data)
fitsio.write(filename, image)
fits=fitsio.FITS('data.fits')
print(fits)
file: data.fits
mode: READONLY
extnum hdutype hduname
0 IMAGE_HDU
1 BINARY_TBL mytable
>>> fits
file: data.fits
... etc
>>> fits[0]
file: data.fits
extension: 0
type: IMAGE_HDU
image info:
data type: f8
dims: [4096,2048]
>>> fits['mytable']
file: data.fits
extension: 1
type: BINARY_TBL
extname: mytable
rows: 4328342
column info:
i1scalar u1
f f4
fvec f4 array[2]
darr f8 array[3,2]
dvarr f8 varray[10]
s S5
svec S6 array[3]
svar S0 vstring[8]
sarr S2 array[4,3]
>>> fits[-1]
...
img = fits[0].read()
img = fits[0][:,:]
img = fits[0][25:35, 45:55]
data = fits[1].read()
data = fits['mytable'].read()
data = fits[1][:]
data = fits[1].read(rows=[1,5], columns=['index','x','y'])
data = fits[1][10:20]
data = fits[1][10:20:2]
data = fits[1][[1,5,18]]
data = fits['SCI',2][10:20]
data = fits[1][40:25]
data = fits[1][40:25:-5]
data = fits[1]['x'][:]
data = fits[1]['x','y'][:]
columns=['index','x','y']
rows = [1, 5]
data = fits[1][columns][rows]
rows = [2, 2, 5]
data = fits[1][columns][rows]
fits=fitsio.FITS(filename,iter_row_buffer=1000)
for row in fits[1]:
print(row)
for hdu in fits:
data=hdu.read()
fits = fitsio.FITS(filename,vstorage='object')
data = fits[1].read(vstorage='object')
print(data['dvarr'].dtype)
dtype('object')
hdu1 = fits[1]
data = hdu1['x','y'][35:50]
w=fits[1].where("x > 0.25 && y < 35.0")
data = fits[1][w]
h = fits[0].read_header()
print(h['BITPIX'])
-64
fits.close()
fits = FITS('test.fits','rw')
nrows=35
data = np.zeros(nrows, dtype=[('index','i4'),('vstr','O'),('x','f8'),
('arr','f4',(3,4))])
data['index'] = np.arange(nrows,dtype='i4')
data['x'] = np.random.random(nrows)
data['vstr'] = [str(i) for i in xrange(nrows)]
data['arr'] = np.arange(nrows*3*4,dtype='f4').reshape(nrows,3,4)
fits.write(data)
array_list=[xarray,yarray,namearray]
names=['x','y','name']
fits.write(array_list, names=names)
fits.write(dict_of_arrays)
fits.write(dict_of_arrays, names=names)
fits[-1].append(data2)
fits[-1].insert_column('newcol', data)
fits[-1].insert_column('newcol', data, colnum=2)
fits[-1].write(data)
fits[-1].write(data, firstrow=350)
img=np.arange(2*3,dtype='i4').reshape(2,3)
fits.write(img)
fits.write(img, compress='rice')
fimg=np.random.normal(size=2*3).reshape(2, 3)
fits.write(img, compress='rice', qlevel=16, qmethod='SUBTRACTIVE_DITHER_2')
fits.write(img, compress='gzip', qlevel=None)
fits.write(fimg, compress='gzip', qlevel=None)
fits[ext].write(img2)
fits[ext].write(img3, start=[300,400])
fits[ext].reshape([250,100])
fits[-1].write_checksum()
fits[-1].verify_checksum()
hdict = {'somekey': 35, 'location': 'kitt peak'}
fits.write(data, header=hdict)
hlist = [{'name':'observer', 'value':'ES', 'comment':'who'},
{'name':'location','value':'CTIO'},
{'name':'photometric','value':True}]
fits.write(data, header=hlist)
hdr=FITSHDR(hlist)
fits.write(data, header=hdr)
fits[1].write_key(name, value, comment="my comment")
fits[1].write_keys(records)
fits[1].write_comment("observer JS")
fits[1].write_comment("we had good weather")
fits[1].write_history("processed with software X")
fits[1].write_history("re-processed with software Y")
fits.close()
with FITS('path/to/file') as fits:
data = fits[ext].read()
if 'blah' in fits:
data=fits['blah'].read()
if 2 in f:
data=fits[2].read()
f[1].get_info()
f[1].has_data()
f[1].get_extname()
f[1].get_extver()
f[1].get_extnum()
f[1].get_exttype()
f[1].get_offsets()
f[1].is_compressed()
f[1].get_colnames()
f[1].get_colname(colnum)
f[1].get_nrows()
f[1].get_rec_dtype()
f[1].get_rec_column_descr()
f[1].get_vstorage()
f[1].lower
f[1].upper
f[1].case_sensitive
Installation
The easiest way is using pip or conda. To get the latest release
pip install fitsio
# update fitsio (and everything else)
pip install fitsio --upgrade
# if pip refuses to update to a newer version
pip install fitsio --upgrade --ignore-installed
# if you only want to upgrade fitsio
pip install fitsio --no-deps --upgrade --ignore-installed
# for conda, use conda-forge
conda install -c conda-forge fitsio
You can also get the latest source tarball release from
https://pypi.python.org/pypi/fitsio
or the bleeding edge source from github or use git. To check out
the code for the first time
git clone https://github.com/esheldon/fitsio.git
Or at a later time to update to the latest
cd fitsio
git update
Use tar xvfz to untar the file, enter the fitsio directory and type
python setup.py install
optionally with a prefix
python setup.py install --prefix=/some/path
Requirements
- python 2 or python 3
- a C compiler and build tools like
make
, patch
, etc. - numpy (See the note below. Generally, numpy 1.11 or later is better.)
Do not use numpy 1.10.0 or 1.10.1
There is a serious performance regression in numpy 1.10 that results
in fitsio running tens to hundreds of times slower. A fix may be
forthcoming in a later release. Please comment here if this
has already impacted your work https://github.com/numpy/numpy/issues/6467
Tests
The unit tests should all pass for full support.
pytest fitsio
Some tests may fail if certain libraries are not available, such
as bzip2. This failure only implies that bzipped files cannot
be read, without affecting other functionality.
Notes on Usage and Features
cfitsio bundling
We bundle cfitsio partly because many deployed versions of cfitsio in the
wild do not have support for interesting features like tiled image compression.
Bundling a version that meets our needs is a safe alternative.
array ordering
Since numpy uses C order, FITS uses fortran order, we have to write the TDIM
and image dimensions in reverse order, but write the data as is. Then we need
to also reverse the dims as read from the header when creating the numpy dtype,
but read as is.
distutils
vs setuptools
As of version 1.0.0
, fitsio
has been transitioned to setuptools
for packaging
and installation. There are many reasons to do this (and to not do this). However,
at a practical level, what this means for you is that you may have trouble uninstalling
older versions with pip
via pip uninstall fitsio
. If you do, the best thing to do is
to manually remove the files manually. See this stackoverflow question
for example.
python 3 strings
As of version 1.0.0
, fitsio now supports Python 3 strings natively. This support
means that for Python 3, native strings are read from and written correctly to
FITS files. All byte string columns are treated as ASCII-encoded unicode strings
as well. For FITS files written with a previous version of fitsio, the data
in Python 3 will now come back as a string and not a byte string. Note that this
support is not the same as full unicode support. Internally, fitsio only supports
the ASCII character set.
TODO
- HDU groups: does anyone use these? If so open an issue!