From b237652f492a54dbe3f70b4f2b20d908c951d013 Mon Sep 17 00:00:00 2001 From: Ed Slavich Date: Fri, 12 Nov 2021 08:19:32 -0900 Subject: [PATCH] Support casting of FITS_rec with unsigned integer column --- CHANGES.rst | 2 ++ src/stdatamodels/util.py | 7 +++++-- tests/test_util.py | 10 ++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index edd0ecc5..64a2f324 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,8 @@ - Add schema feature to forward deprecated model attributes to a new location. [#86] +- Support casting of FITS_rec tables with unsigned integer columns. [#87] + 0.3.0 (2021-09-03) ================== diff --git a/src/stdatamodels/util.py b/src/stdatamodels/util.py index 0ada48d2..cd58ca76 100644 --- a/src/stdatamodels/util.py +++ b/src/stdatamodels/util.py @@ -91,10 +91,13 @@ def gentle_asarray(a, dtype): def _safe_asanyarray(a, dtype): if isinstance(a, fits.fitsrec.FITS_rec): if any(c.bzero is not None for c in a.columns): - # Due to an issue in astropy, it's not safe to convert + # Due to an issue in astropy, it's not safe to directly cast # a FITS_rec with a pseudo-unsigned column. # See https://github.com/astropy/astropy/issues/12112 - raise ValueError("Cannot convert FITS_rec dtype") + result = np.zeros(a.shape, dtype=dtype) + for old_col, new_col in zip(a.dtype.names, result.dtype.names): + result[new_col] = a[old_col] + return result return np.asanyarray(a, dtype=dtype) diff --git a/tests/test_util.py b/tests/test_util.py index b8d74071..2fe3b990 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -87,8 +87,8 @@ def test_gentle_asarray_fits_rec_pseudo_unsigned(tmp_path): assert result["col1"][3] == 4 # This tests the case where a table with a pseudo unsigned integer column - # is opened from a FITS file and needs to be cast. Due to a bug in astropy - # this isn't safe so we expect an exception. + # is opened from a FITS file and needs to be cast. This requires special + # handling on our end to dodge the bug. file_path = tmp_path / "test.fits" data = np.array([(0,)], dtype=[("col1", np.uint16)]) @@ -98,8 +98,10 @@ def test_gentle_asarray_fits_rec_pseudo_unsigned(tmp_path): hdul.writeto(file_path) with fits.open(file_path) as hdul: - with pytest.raises(ValueError, match="Cannot convert FITS_rec dtype"): - util.gentle_asarray(hdul[-1].data, dtype=[("col1", np.uint32)]) + result = util.gentle_asarray(hdul[-1].data, dtype=[("col1", np.uint32)]) + # Without the fix, the value in the array would be 128 due to bzero + # shift being applied twice. + assert result[0][0] == 0 def test_gentle_asarray_nested_array():