diff --git a/CHANGES.md b/CHANGES.md index 879a5944..f4285665 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,10 @@ Changes errors in a FITS file. Currently this only raises when extensions are not properly marked with XTENSION but we can expand this over time +Bug Fixes + + - Bug not writing compression qlevel when it is set to None/0.0 + This was preventing lossless gzip compression version 1.2.0 -------------- diff --git a/fitsio/__init__.py b/fitsio/__init__.py index 6b34a503..e8acf9cc 100644 --- a/fitsio/__init__.py +++ b/fitsio/__init__.py @@ -5,7 +5,7 @@ usage. """ -__version__ = '1.2.0' +__version__ = '1.2.1' from . import fitslib diff --git a/fitsio/fitsio_pywrap.c b/fitsio/fitsio_pywrap.c index 09732e30..a71d42f5 100644 --- a/fitsio/fitsio_pywrap.c +++ b/fitsio/fitsio_pywrap.c @@ -1485,10 +1485,8 @@ PyFITSObject_create_image_hdu(struct PyFITSObject* self, PyObject* args, PyObjec goto create_image_hdu_cleanup; } - if (qlevel > 0) { - if (fits_set_quantize_level(self->fits, qlevel, &status)) { - goto create_image_hdu_cleanup; - } + if (fits_set_quantize_level(self->fits, qlevel, &status)) { + goto create_image_hdu_cleanup; } if (fits_set_quantize_method(self->fits, qmethod, &status)) { diff --git a/fitsio/tests/test_image_compression.py b/fitsio/tests/test_image_compression.py index 51de922c..c2c0c0be 100644 --- a/fitsio/tests/test_image_compression.py +++ b/fitsio/tests/test_image_compression.py @@ -11,6 +11,7 @@ from ..fitslib import ( FITS, read, + write, ) @@ -32,6 +33,80 @@ def test_compressed_write_read(compress): """ nrows = 5 ncols = 20 + if compress in ['rice', 'hcompress'] or 'gzip' in compress: + dtypes = ['u1', 'i1', 'u2', 'i2', 'u4', 'i4', 'f4', 'f8'] + elif compress == 'plio': + dtypes = ['i1', 'i2', 'i4', 'f4', 'f8'] + else: + raise ValueError('unexpected compress %s' % compress) + + if 'lossless' in compress: + qlevel = None + else: + qlevel = 16 + + seed = 1919 + rng = np.random.RandomState(seed) + + with tempfile.TemporaryDirectory() as tmpdir: + fname = os.path.join(tmpdir, 'test.fits') + + for ext, dtype in enumerate(dtypes): + if dtype[0] == 'f': + data = rng.normal(size=(nrows, ncols)) + if compress == 'plio': + data = data.clip(min=0) + data = data.astype(dtype) + else: + data = np.arange( + nrows * ncols, dtype=dtype, + ).reshape(nrows, ncols) + + csend = compress.replace('_lossless', '') + write(fname, data, compress=csend, qlevel=qlevel) + rdata = read(fname, ext=ext+1) + + if 'lossless' in compress or dtype[0] in ['i', 'u']: + compare_array( + data, rdata, + "%s compressed images ('%s')" % (compress, dtype) + ) + else: + # lossy floating point + compare_array_abstol( + data, + rdata, + 0.2, + "%s compressed images ('%s')" % (compress, dtype), + ) + + with FITS(fname) as fits: + for ii in range(len(dtypes)): + i = ii + 1 + assert fits[i].is_compressed(), "is compressed" + + +@pytest.mark.parametrize( + 'compress', + [ + 'rice', + 'hcompress', + 'plio', + 'gzip', + 'gzip_2', + 'gzip_lossless', + 'gzip_2_lossless', + ] +) +def _test_compressed_write_read_fitsobj(compress): + """ + Test writing and reading a rice compressed image + + This one fails because the compressed data do not seem to be + finalized + """ + nrows = 5 + ncols = 20 if compress in ['rice', 'hcompress'] or 'gzip' in compress: dtypes = ['u1', 'i1', 'u2', 'i2', 'u4', 'i4', 'f4', 'f8'] # dtypes = ['u2'] @@ -69,14 +144,7 @@ def test_compressed_write_read(compress): fits.write_image(data, compress=csend, qlevel=qlevel) rdata = fits[-1].read() - if dtype[0] == 'f': - compare_array_abstol( - data, - rdata, - 0.2, - "%s compressed images ('%s')" % (compress, dtype), - ) - else: + if 'lossless' in compress or dtype[0] in ['i', 'u']: # for integers we have chosen a wide range of values, so # there will be no quantization and we expect no # information loss @@ -84,6 +152,22 @@ def test_compressed_write_read(compress): data, rdata, "%s compressed images ('%s')" % (compress, dtype) ) + else: + # lossy floating point + compare_array_abstol( + data, + rdata, + 0.2, + "%s compressed images ('%s')" % (compress, dtype), + ) + # else: + # # for integers we have chosen a wide range of values, so + # # there will be no quantization and we expect no + # # information loss + # compare_array( + # data, rdata, + # "%s compressed images ('%s')" % (compress, dtype) + # ) with FITS(fname) as fits: for ii in range(len(dtypes)): diff --git a/setup.py b/setup.py index 4fc5fae3..63d85f39 100644 --- a/setup.py +++ b/setup.py @@ -318,7 +318,7 @@ def check_system_cfitsio_objects(self, obj_name): setup( name="fitsio", - version="1.2.0", + version="1.2.1", description=description, long_description=long_description, long_description_content_type='text/markdown; charset=UTF-8; variant=GFM',