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

Using Masked inside Time #15231

Merged
merged 22 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
320c4e7
Allow Time to use masked numerical values internally.
mhvk Dec 12, 2020
3d07bba
Move mask and cache from the format to Time.
mhvk Dec 26, 2020
bb67cba
Test all formats and fix bug for ymdhms
mhvk Aug 26, 2023
9e58a26
Ensure the mask from the mask attribute is always read-only.
mhvk Sep 28, 2023
55cb8f7
Allow unmasked by assigning np.ma.nomask
mhvk Sep 28, 2023
81887a3
Allow the output masked class to be configurable.
mhvk Sep 28, 2023
d7f96aa
Changelog and whatsnew entries, updates to the docs
mhvk Sep 29, 2023
609df0c
Fix case where format already masks some entries
mhvk Sep 29, 2023
a9b2e42
Let Time.masked reflect whether _time.jd1 is Masked
mhvk Oct 7, 2023
d6326cd
Add unmasked property and filled method
mhvk Oct 7, 2023
0708d7a
Fix TimeDeltaQuantityString for Masked
taldcroft Oct 20, 2023
025c7f3
Add a fill_value class method to TimeFormat
taldcroft Oct 20, 2023
3cf845d
New strategy for Time masking / filling
taldcroft Oct 20, 2023
d154975
Add class method to fill masked values
taldcroft Oct 20, 2023
bb08f68
Use in_subfmt for determining fill_value
taldcroft Oct 20, 2023
728d59b
Update narrative docs
taldcroft Oct 20, 2023
25bd233
Change default fill value to J2000.0 (jd=2451545.0)
taldcroft Oct 21, 2023
4e898c5
Ensure we give each format the original values
mhvk Oct 21, 2023
e3574c1
Ensure that unmasked works also with an array-valued location
mhvk Oct 22, 2023
5f21301
Make cache depend on masked_array_type
mhvk Oct 22, 2023
afe9a30
Give explicit link to astropy.utils.masked package in whatsnew
mhvk Oct 22, 2023
de5736b
Move fill value discussion to warning and clarify scale
mhvk Oct 26, 2023
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
8 changes: 5 additions & 3 deletions astropy/io/fits/fitstime.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,9 +595,11 @@ def time_to_fits(table):

# The following is necessary to deal with multi-dimensional ``Time`` objects
# (i.e. where Time.shape is non-trivial).
jd12 = np.stack([col.jd1, col.jd2], axis=-1)
# Roll the 0th (innermost) axis backwards, until it lies in the last position
# (jd12.ndim)
# Note: easier would be np.stack([col.jd1, col.jd2], axis=-1), but that
# fails for np.ma.MaskedArray, as it returns just the data, ignoring the mask.
jd12 = np.empty_like(col.jd1, shape=col.jd1.shape + (2,))
jd12[..., 0] = col.jd1
jd12[..., 1] = col.jd2
newtable.replace_column(col.info.name, col_cls(jd12, unit="d"))

# Time column-specific override keywords
Expand Down
8 changes: 5 additions & 3 deletions astropy/io/fits/tests/test_fitstime.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from astropy.time.core import BARYCENTRIC_SCALES
from astropy.time.formats import FITS_DEPRECATED_SCALES
from astropy.utils.exceptions import AstropyUserWarning
from astropy.utils.masked import Masked

from .conftest import FitsTestCase

Expand Down Expand Up @@ -159,15 +160,16 @@ def test_time_to_fits_loc(self, table_types):

assert tm["a"].location == t["a"].location

@pytest.mark.parametrize("masked_cls", (np.ma.MaskedArray, Masked))
@pytest.mark.parametrize("mask", (False, [True, False]))
@pytest.mark.parametrize("serialize_method", ("jd1_jd2", "formatted_value"))
def test_time_to_fits_serialize_method(self, serialize_method, mask):
def test_time_to_fits_serialize_method(self, serialize_method, mask, masked_cls):
"""
Test the data returned by ``time_to_fits`` for masked values.
"""
a = Time(np.ma.MaskedArray(self.time, mask=mask))
a = Time(masked_cls(self.time, mask=mask))
b = Time(
np.ma.MaskedArray([[1, 2], [3, 4]], mask=np.broadcast_to(mask, (2, 2))),
masked_cls([[1, 2], [3, 4]], mask=np.broadcast_to(mask, (2, 2))),
format="cxcsec",
)
assert b.masked is a.masked is (mask is not False)
Expand Down
26 changes: 25 additions & 1 deletion astropy/time/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class Conf(_config.ConfigNamespace):
"""
Configuration parameters for `astropy.table`.
Configuration parameters for `astropy.time`.
"""

use_fast_parser = _config.ConfigItem(
Expand All @@ -16,6 +16,30 @@ class Conf(_config.ConfigNamespace):
"options are all strings.",
)

masked_array_type = _config.ConfigItem(
["astropy", "numpy"],
'The type of masked array used for masked output data. Can be "astropy" '
'for `astropy.utils.masked.Masked` or "numpy" to use `numpy.ma.MaskedArray`. '
"Note that if `astropy.units.Quantity` is produced, the output always "
"uses `astropy.utils.masked.Masked`, since `numpy.ma.MaskedArray` does not "
"work with quantities.",
)
# Create a dict of available masked classes for speed.
# Use local imports so we do not pollute the module namespace.
from numpy.ma import MaskedArray

from astropy.utils.masked import Masked

_MASKED_CLASSES = {"astropy": Masked, "numpy": MaskedArray}

@property
def _masked_cls(self):
"""The masked class set by ``masked_array_type``.

This is |Masked| for "astropy", `numpy.ma.MaskedArray` for "numpy".
"""
return self._MASKED_CLASSES[self.masked_array_type]


conf = Conf()

Expand Down