Skip to content

Commit

Permalink
Backport PR astropy#15001: Fixed a bug that caused compressed images …
Browse files Browse the repository at this point in the history
…with TFORM missing the optional '1' prefix to not be readable
  • Loading branch information
saimn authored and astrofrog committed Jul 3, 2023
1 parent caa4d7c commit 7762840
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 8 deletions.
19 changes: 11 additions & 8 deletions astropy/io/fits/_tiled_compression/tiled_compression.py
Expand Up @@ -203,12 +203,13 @@ def _check_compressed_header(header):
if not np.isreal(header[kw]) or not float(header[kw]).is_integer():
raise TypeError(f"{kw} should be an integer")

if "TFORM1" in header:
for valid in ["1PB", "1PI", "1PJ", "1QB", "1QI", "1QJ"]:
if header["TFORM1"].startswith(valid):
break
else:
raise RuntimeError(f"Invalid TFORM1: {header['TFORM1']}")
for suffix in range(1, header["TFIELDS"] + 1):
if header.get(f"TTYPE{suffix}", "").endswith("COMPRESSED_DATA"):
for valid in ["PB", "PI", "PJ", "QB", "QI", "QJ"]:
if header[f"TFORM{suffix}"].startswith((valid, f"1{valid}")):
break
else:
raise RuntimeError(f"Invalid TFORM{suffix}: {header[f'TFORM{suffix}']}")

# Check values

Expand Down Expand Up @@ -253,11 +254,13 @@ def _get_compression_setting(header, name, default):

def _column_dtype(hdu, column_name):
tform = hdu.columns[column_name].format
if tform.startswith("1"):
tform = tform[1:]
if tform[2] == "B":
dtype = np.uint8
elif tform[2] == "I":
elif tform[1] == "I":
dtype = ">i2"
elif tform[2] == "J":
elif tform[1] == "J":
dtype = ">i4"
return np.dtype(dtype)

Expand Down
26 changes: 26 additions & 0 deletions astropy/io/fits/tests/test_image.py
Expand Up @@ -2009,6 +2009,32 @@ def test_comp_image_properties_set(self):
assert chdu.tile_shape == (2, 3, 4)
assert chdu.compression_type == "PLIO_1"

def test_compressed_optional_prefix_tform(self, tmp_path):
# Regression test for a bug that caused an error if a
# compressed file had TFORM missing the optional 1 prefix

data = np.zeros((3, 4, 5))

hdu1 = fits.CompImageHDU(data=data)
hdu1.writeto(tmp_path / "compressed.fits")

with fits.open(
tmp_path / "compressed.fits", disable_image_compression=True, mode="update"
) as hdul:
assert hdul[1].header["TFORM1"] == "1PB(0)"
assert hdul[1].header["TFORM2"] == "1PB(24)"
hdul[1].header["TFORM1"] = "PB(0)"
hdul[1].header["TFORM2"] = "PB(24)"

with fits.open(
tmp_path / "compressed.fits", disable_image_compression=True
) as hdul:
assert hdul[1].header["TFORM1"] == "PB(0)"
assert hdul[1].header["TFORM2"] == "PB(24)"

with fits.open(tmp_path / "compressed.fits") as hdul:
assert_equal(hdul[1].data, data)


class TestCompHDUSections:
@pytest.fixture(autouse=True)
Expand Down
1 change: 1 addition & 0 deletions docs/changes/io.fits/15001.bugfix.rst
@@ -0,0 +1 @@
Fixed a bug that caused compressed images with TFORM missing the optional '1' prefix to not be readable.

0 comments on commit 7762840

Please sign in to comment.