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

Make imports work with current and future pyuvdata, fix compatibility with numpy 2.0 #253

Merged
merged 5 commits into from
Jul 1, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

## [Unreleased]

### Changed
- pyuvdata utils imports to ensure compatibility with version 3.0.
- `numpy.string_` calls to `numpy.bytes_`, `np.in1d` to `np.isin` and a few other
changes for numpy 2.0 compatibility.

### Fixed
- An error when Skymodel.concat was called serially.


## [1.0.0] - 2024-05-09

### Changed
Expand Down
12 changes: 7 additions & 5 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,7 @@ d) Other time and position related attributes and methods
... Latitude,
... Galactic)
>>> from astropy.time import Time
>>> from astropy.units import Quantity

>>> # Create a couple sources near zenith
>>> array_location = EarthLocation(lat="-30d43m17.5s", lon="21d25m41.9s", height=1073.0)
Expand All @@ -1191,14 +1192,15 @@ d) Other time and position related attributes and methods
>>> sm.update_positions(time, array_location)
>>> print(sm.time)
2015-03-01 00:00:00.000
>>> print(sm.telescope_location)
(5109342.76037543, 2005241.90402741, -3239939.46926403) m
>>> with np.printoptions(precision=3):
... print(Quantity(sm.telescope_location.geocentric).to_value("m"))
[ 5109342.76 2005241.904 -3239939.469]

>>> # Limit the precision for testing on different platforms
>>> with np.printoptions(precision=3):
>>> with np.printoptions(precision=2):
... print(sm.alt_az)
[[1.571 1.396]
[1.73 0.175]]
[[1.57 1.4 ]
[1.73 0.17]]

>>> # Can directly access direction cosines of the sources
>>> with np.printoptions(precision=1):
Expand Down
30 changes: 19 additions & 11 deletions src/pyradiosky/skymodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import astropy.units as units
import h5py
import numpy as np
import pyuvdata.utils as uvutils
import scipy.io
from astropy.coordinates import (
AltAz,
Expand All @@ -34,6 +33,15 @@
from . import spherical_coords_transforms as sct
from . import utils as skyutils

try: # pragma: no cover # This pragma can be removed once pyuvdata v3 is released.
import pyuvdata.utils.history as history_utils
import pyuvdata.utils.tools as uvutils
except ImportError:
# this can be removed once we require pyuvdata >= v3.0
import pyuvdata.utils as uvutils
import pyuvdata.utils as history_utils


__all__ = ["hasmoon", "SkyModel"]

try:
Expand Down Expand Up @@ -263,7 +271,7 @@
if isinstance(value, (list, np.ndarray)):
group[name] = np.asarray(value, dtype="bytes")
else:
group[name] = np.string_(value)
group[name] = np.bytes_(value)
else:
group[name] = value

Expand Down Expand Up @@ -1049,7 +1057,7 @@
self._filename.form = (len(filename_use),)

self.history = history
if not uvutils._check_history_version(
if not history_utils._check_history_version(
self.history, self.pyradiosky_version_str
):
self.history += self.pyradiosky_version_str
Expand Down Expand Up @@ -2157,7 +2165,7 @@
new_stokes[:, :, wh_non_nan] = finterp(at_freq_arr)

if nan_handling == "propagate":
new_stokes[:, :, wh_nan] = np.NaN
new_stokes[:, :, wh_nan] = np.nan
else:
wh_all_nan = []
wh_nan_high = []
Expand All @@ -2168,7 +2176,7 @@
np.all(~np.isnan(stokes_arr[:, :, comp]), axis=0)
)[0]
if freq_inds_use.size == 0:
new_stokes[:, :, comp] = np.NaN
new_stokes[:, :, comp] = np.nan
wh_all_nan.append(comp)
continue
at_freq_inds_use = np.arange(freqs.size)
Expand All @@ -2182,7 +2190,7 @@
)[0]
wh_nan_high.append(comp)
if nan_handling == "interp":
new_stokes[:, at_freqs_large, comp] = np.NaN
new_stokes[:, at_freqs_large, comp] = np.nan
else: # clip
large_inds_use = np.full(
(at_freqs_large.size), freq_inds_use[-1]
Expand All @@ -2203,7 +2211,7 @@
)[0]
wh_nan_low.append(comp)
if nan_handling == "interp":
new_stokes[:, at_freqs_small, comp] = np.NaN
new_stokes[:, at_freqs_small, comp] = np.nan
else: # clip
small_inds_use = np.full(
(at_freqs_small.size), freq_inds_use[0]
Expand Down Expand Up @@ -2603,7 +2611,7 @@

# This is a boolean array of length len(above_horizon)
# that identifies polarized sources above the horizon.
pol_over_hor = np.in1d(
pol_over_hor = np.isin(
np.arange(self.Ncomponents)[above_horizon], self._polarized
)

Expand Down Expand Up @@ -2897,14 +2905,14 @@
history_update_string = (
" Combined skymodels along the component axis using pyradiosky."
)
histories_match = uvutils._check_histories(this.history, other.history)
histories_match = history_utils._check_histories(this.history, other.history)

Check warning on line 2908 in src/pyradiosky/skymodel.py

View check run for this annotation

Codecov / codecov/patch

src/pyradiosky/skymodel.py#L2908

Added line #L2908 was not covered by tests

this.history += history_update_string
if not histories_match:
if verbose_history:
this.history += " Next object history follows. " + other.history
else:
extra_history = uvutils._combine_history_addition(
extra_history = history_utils._combine_history_addition(

Check warning on line 2915 in src/pyradiosky/skymodel.py

View check run for this annotation

Codecov / codecov/patch

src/pyradiosky/skymodel.py#L2915

Added line #L2915 was not covered by tests
this.history, other.history
)
if extra_history is not None:
Expand Down Expand Up @@ -4906,7 +4914,7 @@
if self.history is None:
self.history = self.pyradiosky_version_str
else:
if not uvutils._check_history_version(
if not history_utils._check_history_version(
self.history, self.pyradiosky_version_str
):
self.history += self.pyradiosky_version_str
Expand Down
37 changes: 19 additions & 18 deletions tests/test_skymodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
import pytest

try:
import pyuvdata.utils.history as history_utils
from pyuvdata.testing import check_warnings
except ImportError:
# this can be removed once we require pyuvdata >= v3.0
from pyuvdata.tests import check_warnings
import pyuvdata.utils as history_utils

import pyuvdata.utils as uvutils
import scipy.io
from astropy import units
from astropy.coordinates import (
Expand Down Expand Up @@ -1628,7 +1629,7 @@ def test_concat(comp_type, spec_type, healpix_disk_new):
+ " Combined skymodels along the component axis using pyradiosky."
+ " Combined skymodels along the component axis using pyradiosky."
)
assert uvutils._check_histories(skyobj_new.history, expected_history)
assert history_utils._check_histories(skyobj_new.history, expected_history)

skyobj_new.history = skyobj_full.history
assert skyobj_new == skyobj_full
Expand All @@ -1650,7 +1651,7 @@ def test_concat(comp_type, spec_type, healpix_disk_new):
skyobj_new = skyobj1.concat(skyobj2, inplace=False, run_check=False)
skyobj_new.concat(skyobj3)
assert skyobj_new.history != skyobj_full.history
assert uvutils._check_histories(skyobj_new.history, expected_history)
assert history_utils._check_histories(skyobj_new.history, expected_history)

skyobj_new = skyobj1.concat(skyobj2, inplace=False, verbose_history=True)
skyobj_new.concat(skyobj3, verbose_history=True)
Expand All @@ -1665,7 +1666,7 @@ def test_concat(comp_type, spec_type, healpix_disk_new):
+ "Next object history follows. "
+ skyobj3.history
)
assert uvutils._check_histories(skyobj_new.history, expected_history)
assert history_utils._check_histories(skyobj_new.history, expected_history)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -2135,12 +2136,12 @@ def test_flux_source_cuts():
expected_history2 = (
skyobj.history + " Downselected to specific components using pyradiosky."
)
assert uvutils._check_histories(skyobj2.history, expected_history2)
assert history_utils._check_histories(skyobj2.history, expected_history2)

expected_history3 = (
skyobj.history + " Downselected to specific components using pyradiosky."
)
assert uvutils._check_histories(skyobj3.history, expected_history3)
assert history_utils._check_histories(skyobj3.history, expected_history3)

skyobj2.history = skyobj3.history

Expand Down Expand Up @@ -3073,7 +3074,7 @@ def test_point_catalog_reader():
with open(catfile, "r") as fileobj:
header = fileobj.readline()
header = [h.strip() for h in header.split()]
dt = np.format_parser(
dt = np.rec.format_parser(
["U10", "f8", "f8", "f8", "f8"],
["source_id", "ra_j2000", "dec_j2000", "flux_density", "frequency"],
header,
Expand Down Expand Up @@ -3433,7 +3434,7 @@ def test_at_frequencies_interp_errors(mock_point_skies):
):
sky.at_frequencies(sky.freq_array - 10 * units.Hz)

sky.stokes[0, 0, 0] = np.NaN
sky.stokes[0, 0, 0] = np.nan
with pytest.raises(ValueError, match="nan_handling must be one of "):
sky.at_frequencies(sky.freq_array, nan_handling="foo")

Expand Down Expand Up @@ -3465,14 +3466,14 @@ def test_at_frequencies_nan_handling(nan_handling):

skyobj2 = skyobj.copy()
# add some NaNs. These exist in full GLEAM catalog but not in our small test file
skyobj2.stokes[0, 0:2, 0] = np.NaN # no low freq support
skyobj2.stokes[0, 10:11, 1] = np.NaN # missing freqs in middle
skyobj2.stokes[0, -2:, 2] = np.NaN # no high freq support
skyobj2.stokes[0, :, 3] = np.NaN # all NaNs
skyobj2.stokes[0, 1:-2, 4] = np.NaN # only 2 good freqs
skyobj2.stokes[0, 0, 5] = np.NaN # no low or high frequency support
skyobj2.stokes[0, -1, 5] = np.NaN # no low or high frequency support
skyobj2.stokes[0, 1:, 6] = np.NaN # only 1 good freqs
skyobj2.stokes[0, 0:2, 0] = np.nan # no low freq support
skyobj2.stokes[0, 10:11, 1] = np.nan # missing freqs in middle
skyobj2.stokes[0, -2:, 2] = np.nan # no high freq support
skyobj2.stokes[0, :, 3] = np.nan # all NaNs
skyobj2.stokes[0, 1:-2, 4] = np.nan # only 2 good freqs
skyobj2.stokes[0, 0, 5] = np.nan # no low or high frequency support
skyobj2.stokes[0, -1, 5] = np.nan # no low or high frequency support
skyobj2.stokes[0, 1:, 6] = np.nan # only 1 good freqs

message = ["Some stokes values are NaNs."]
if nan_handling == "propagate":
Expand Down Expand Up @@ -3624,7 +3625,7 @@ def test_at_frequencies_nan_handling_allsrc(nan_handling):

skyobj2 = skyobj.copy()
# add some NaNs to all sources
skyobj2.stokes[0, 10:11, :] = np.NaN
skyobj2.stokes[0, 10:11, :] = np.nan
message = ["Some stokes values are NaNs."]
if nan_handling == "propagate":
message[
Expand Down Expand Up @@ -3866,7 +3867,7 @@ def test_skyh5_backwards_compatibility_healpix(healpix_disk_new, tmpdir):

with h5py.File(testfile, "r+") as h5f:
del h5f["/Header/hpx_frame"]
h5f["/Header/hpx_frame"] = np.string_(sky.hpx_frame.name)
h5f["/Header/hpx_frame"] = np.bytes_(sky.hpx_frame.name)

sky2 = SkyModel.from_file(testfile)
assert sky == sky2
Expand Down
Loading