Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure tables with masked and unmasked columns roundtrip properly #15473

Merged
merged 1 commit into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 6 additions & 5 deletions astropy/io/fits/convenience.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,12 +541,13 @@
# Binary FITS tables support TNULL *only* for integer data columns
# TODO: Determine a schema for handling non-integer masked columns
# with non-default fill values in FITS (if at all possible).
# Be careful that we do not set null for columns that were not masked!
int_formats = ("B", "I", "J", "K")
if not (col.format in int_formats or col.format.p_format in int_formats):
continue

fill_value = tarray[col.name].fill_value
col.null = fill_value.astype(int)
if (

Check warning on line 546 in astropy/io/fits/convenience.py

View check run for this annotation

Codecov / codecov/patch

astropy/io/fits/convenience.py#L546

Added line #L546 was not covered by tests
col.format in int_formats or col.format.p_format in int_formats
) and hasattr(table[col.name], "mask"):
fill_value = tarray[col.name].fill_value
col.null = fill_value.astype(int)

Check warning on line 550 in astropy/io/fits/convenience.py

View check run for this annotation

Codecov / codecov/patch

astropy/io/fits/convenience.py#L549-L550

Added lines #L549 - L550 were not covered by tests
else:
table_hdu = BinTableHDU.from_columns(
tarray, header=hdr, character_as_bytes=character_as_bytes
Expand Down
14 changes: 13 additions & 1 deletion astropy/io/fits/tests/test_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
python_to_tdisp,
)
from astropy.io.tests.mixin_columns import compare_attrs, mixin_cols, serialized_names
from astropy.table import Column, QTable, Table
from astropy.table import Column, MaskedColumn, QTable, Table
from astropy.table.table_helpers import simple_table
from astropy.time import Time
from astropy.units import allclose as quantity_allclose
Expand Down Expand Up @@ -1064,3 +1064,15 @@ def test_meta_not_modified(tmp_path):
def test_is_fits_gh_14305():
"""Regression test for https://github.com/astropy/astropy/issues/14305"""
assert not connect.is_fits("", "foo.bar", None)


def test_keep_masked_state_integer_columns(tmp_path):
"""Regression test for https://github.com/astropy/astropy/issues/15417"""
filename = tmp_path / "test_masked.fits"
t = Table([[1, 2], [1.5, 2.5]], names=["a", "b"])
t["c"] = MaskedColumn([1, 2], mask=[True, False])
t.write(filename)
tr = Table.read(filename)
assert not isinstance(tr["a"], MaskedColumn)
assert not isinstance(tr["b"], MaskedColumn)
assert isinstance(tr["c"], MaskedColumn)
3 changes: 3 additions & 0 deletions docs/changes/io.fits/15473.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Ensure that tables written to FITS with both masked and unmasked columns
roundtrip properly (previously, all integer columns would become masked
if any column was masked).