Skip to content

Commit

Permalink
Rolled back the current scale of my ambitions for supporting older CF…
Browse files Browse the repository at this point in the history
…ITSIO versions. Now the earliers version for which all tests pass is 3.09. 3.08 passes except for one test which fails due to a bug in CFITSIO itself. But now versions earlier than 3.28 which do not support the GZIP_COMPRESSED_DATA column will work. This required a few small bug fixes: Most importantly was a fix to updateCompressedData to ensure that the memory allocated for compressed data is a multiple of 2880 bytes.
  • Loading branch information
embray committed Nov 23, 2012
1 parent 5d7fb31 commit d8d4b8f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 49 deletions.
6 changes: 4 additions & 2 deletions README.txt
Expand Up @@ -22,5 +22,7 @@ compression support. A minimal copy of CFITSIO is included in the PyFITS
source under cextern/cfitsio. Packagers wishing to link with an existing
system CFITSIO remove this directory and modify the setup.cfg as instructed
by the comments in that file. CFITSIO support has been tested for versions
3.28 through 3.30. Earlier versions *may* work by YMMV. Please send in any
results of experimentation with other CFITSIO versions.
3.08 through 3.30. The earliers known fully working version is 3.09. Version
3.08 mostly works except for a bug in CFITSIO itself when decompressing some
images with BITPIX=-64. Earlier versions *may* work but YMMV. Please send in
any results of experimentation with other CFITSIO versions.
69 changes: 31 additions & 38 deletions lib/pyfits/hdu/compressed.py
Expand Up @@ -34,7 +34,6 @@
# CFITSIO version-specific features
if COMPRESSION_SUPPORTED:
CFITSIO_SUPPORTS_GZIPDATA = compression.CFITSIO_VERSION >= 3.28
CFITSIO_SUPPORTS_BYTEPIX = compression.CFITSIO_VERSION >= 3.08


class CompImageHeader(Header):
Expand Down Expand Up @@ -759,29 +758,21 @@ def updateHeaderData(self, image_header,
self._header.set('ZVAL1', DEFAULT_BLOCK_SIZE, 'pixels per block',
after='ZNAME1')

if CFITSIO_SUPPORTS_BYTEPIX:
# CFITSIO version prior to 3.08 do not support the BYTEPIX
# compression parameter, and ZVAL2 for Rice compression should
# be the NOISEBIT parameter
self._header.set('ZNAME2', 'BYTEPIX',
'bytes per pixel (1, 2, 4, or 8)',
after='ZVAL1')

if self._header['ZBITPIX'] == 8:
bytepix = 1
elif self._header['ZBITPIX'] == 16:
bytepix = 2
else:
bytepix = DEFAULT_BYTE_PIX
self._header.set('ZNAME2', 'BYTEPIX',
'bytes per pixel (1, 2, 4, or 8)', after='ZVAL1')

self._header.set('ZVAL2', bytepix,
'bytes per pixel (1, 2, 4, or 8)',
after='ZNAME2')
afterCard = 'ZVAL2'
idx = 3
if self._header['ZBITPIX'] == 8:
bytepix = 1
elif self._header['ZBITPIX'] == 16:
bytepix = 2
else:
afterCard = 'ZVAL1'
idx = 2
bytepix = DEFAULT_BYTE_PIX

self._header.set('ZVAL2', bytepix,
'bytes per pixel (1, 2, 4, or 8)',
after='ZNAME2')
afterCard = 'ZVAL2'
idx = 3
elif compressionType == 'HCOMPRESS_1':
self._header.set('ZNAME1', 'SCALE', 'HCOMPRESS scale factor',
after=afterCard)
Expand Down Expand Up @@ -951,6 +942,7 @@ def compData(self):
# data) from the file, if there is any.
compData = super(BinTableHDU, self).data
if isinstance(compData, np.rec.recarray):
del self.data
return compData
else:
# This will actually set self.compData with the pre-allocated space
Expand Down Expand Up @@ -1264,6 +1256,11 @@ def updateCompressedData(self):
if dataspan < BLOCK_SIZE:
# We must a full FITS block at a minimum
dataspan = BLOCK_SIZE
else:
# Still make sure to pad out to a multiple of 2880 byte blocks
# otherwise CFITSIO can get read errors when it tries to read
# a partial block that goes past the end of the file
dataspan += _pad_length(dataspan)
self.compData = np.empty((dataspan,), dtype=np.byte)
self.compData[:tbsize] = 0

Expand Down Expand Up @@ -1351,23 +1348,19 @@ def updateHeader(self):
self._header.set('ZVAL1', DEFAULT_BLOCK_SIZE, 'pixels per block',
after='ZNAME1')

if CFITSIO_SUPPORTS_BYTEPIX:
# CFITSIO < 3.08 does not support the BYTEPIX parameter for
# Rice compression
self._header.set('ZNAME2', 'BYTEPIX',
'bytes per pixel (1, 2, 4, or 8)',
after='ZVAL1')

if self._header['ZBITPIX'] == 8:
bytepix = 1
elif self._header['ZBITPIX'] == 16:
bytepix = 2
else:
bytepix = DEFAULT_BYTE_PIX
self._header.set('ZNAME2', 'BYTEPIX',
'bytes per pixel (1, 2, 4, or 8)', after='ZVAL1')

self._header.set('ZVAL2', bytepix,
'bytes per pixel (1, 2, 4, or 8)',
after='ZNAME2')
if self._header['ZBITPIX'] == 8:
bytepix = 1
elif self._header['ZBITPIX'] == 16:
bytepix = 2
else:
bytepix = DEFAULT_BYTE_PIX

self._header.set('ZVAL2', bytepix,
'bytes per pixel (1, 2, 4, or 8)',
after='ZNAME2')

def scale(self, type=None, option='old', bscale=1, bzero=0):
"""
Expand Down
15 changes: 6 additions & 9 deletions src/compressionmodule.c
Expand Up @@ -584,14 +584,8 @@ void configure_compression(fitsfile* fileptr, PyObject* header) {

// Set some more default compression options
Fptr->rice_blocksize = DEFAULT_BLOCK_SIZE;
#ifdef CFITSIO_SUPPORTS_BYTEPIX
Fptr->rice_bytepix = DEFAULT_BYTE_PIX;
#endif
#ifdef CFITSIO_SUPPORTS_QUANTIZE_LEVEL
Fptr->quantize_level = DEFAULT_QUANTIZE_LEVEL;
#else
Fptr->rice_nbits = DEFAULT_QUANTIZE_LEVEL;
#endif
Fptr->hcomp_smooth = DEFAULT_HCOMP_SMOOTH;
Fptr->hcomp_scale = DEFAULT_HCOMP_SCALE;

Expand All @@ -610,11 +604,9 @@ void configure_compression(fitsfile* fileptr, PyObject* header) {
if (0 == strcmp(zname, "BLOCKSIZE")) {
get_header_int(header, keyword, &(Fptr->rice_blocksize),
DEFAULT_BLOCK_SIZE);
#ifdef CFITSIO_SUPPORTS_BYTEPIX
} else if (0 == strcmp(zname, "BYTEPIX")) {
get_header_int(header, keyword, &(Fptr->rice_bytepix),
DEFAULT_BYTE_PIX);
#endif
}
} else if (Fptr->compress_type == HCOMPRESS_1) {
if (0 == strcmp(zname, "SMOOTH")) {
Expand Down Expand Up @@ -792,7 +784,6 @@ PyObject* compression_compress_hdu(PyObject* self, PyObject* args)

indata = (PyArrayObject*) PyObject_GetAttrString(hdu, "data");

// Test values
fits_write_img(fileptr, datatype, 1, PyArray_SIZE(indata), indata->data,
&status);
if (status != 0) {
Expand Down Expand Up @@ -840,6 +831,9 @@ PyObject* compression_compress_hdu(PyObject* self, PyObject* args)
}
Py_XDECREF(indata);

// Clear any messages remaining in CFITSIO's error stack
fits_clear_errmsg();

return retval;
}

Expand Down Expand Up @@ -914,6 +908,9 @@ PyObject* compression_decompress_hdu(PyObject* self, PyObject* args)
}
PyMem_Free(znaxis);

// Clear any messages remaining in CFITSIO's error stack
fits_clear_errmsg();

return (PyObject*) outdata;
}

Expand Down

0 comments on commit d8d4b8f

Please sign in to comment.