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

[Numpy2] Support for numpy==2.0.0 (and pin iris >=3.11) #2395

Merged
merged 80 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
8930af0
add numpy 2 from conda-forge dev
valeriupredoi Apr 12, 2024
a3e0632
temp remove PyPI numpy - add numpy 2 from conda-forge dev
valeriupredoi Apr 12, 2024
233eb67
run a GA
valeriupredoi Apr 12, 2024
3687ea0
remove numpy from env
valeriupredoi Apr 12, 2024
bf8dff5
manually install numpy 2.0
valeriupredoi Apr 12, 2024
29284bc
correct conda forge channel
valeriupredoi Apr 15, 2024
23429bc
correct conda forge channel
valeriupredoi Apr 15, 2024
50910b4
do not install manually numpy, like a peasant
valeriupredoi Apr 15, 2024
4d5d1eb
revert to manual installation
valeriupredoi Apr 15, 2024
9fb584a
comment out numpy gubbins i environment yml
valeriupredoi Apr 15, 2024
91a87ed
Merge branch 'main' into numpy2-dev
valeriupredoi May 7, 2024
6eb3d00
Merge branch 'main' into numpy2-dev
valeriupredoi May 10, 2024
ade96ca
Merge branch 'main' into numpy2-dev
valeriupredoi May 13, 2024
ac75b84
Merge branch 'main' into numpy2-dev
valeriupredoi May 27, 2024
d36350a
deactivate direct download
valeriupredoi May 27, 2024
5dfa45a
use direct download again
valeriupredoi May 27, 2024
baedee8
use direct download again
valeriupredoi May 27, 2024
5f91615
Merge branch 'main' into numpy2-dev
valeriupredoi Jun 6, 2024
038099d
Merge branch 'main' into numpy2-dev
valeriupredoi Jun 17, 2024
ccb8f2f
use conda forge package
valeriupredoi Jun 17, 2024
882c1cd
dont install from conda package
valeriupredoi Jun 17, 2024
6d9cda5
restore numpy dep
valeriupredoi Jun 17, 2024
e3e2e25
completeley remove line that installed numpy2 from anaconda package
valeriupredoi Jun 17, 2024
30c99e5
unpin pandas
valeriupredoi Jun 19, 2024
98ee116
unpin pandas
valeriupredoi Jun 19, 2024
0e2799b
release numpy to choose its path
valeriupredoi Jun 19, 2024
03a46fa
replace np.NaN with np.nan
valeriupredoi Jun 19, 2024
af8944e
replace np.NaN with np.nan
valeriupredoi Jun 19, 2024
6a8fe23
fix for new output of np.ogrid
valeriupredoi Jun 19, 2024
e849a73
add printout to test
valeriupredoi Jun 19, 2024
3ec3fe5
explicitly cast Python int
valeriupredoi Jun 20, 2024
26a5228
use vstack instead of simple array
valeriupredoi Jun 20, 2024
ecf68f8
make list out of now tuple
valeriupredoi Jun 20, 2024
c10ce96
explicit cast to numpy strings ffs
valeriupredoi Jun 20, 2024
f822bb8
reqwite the distance stat with sqrt account for masks
valeriupredoi Jun 21, 2024
061a4fb
account for variations in rstol for numpy 2.0
valeriupredoi Jun 21, 2024
a4707ef
add note on sqrt bug
valeriupredoi Jun 21, 2024
266781a
temprary pin numpy<2
valeriupredoi Jun 21, 2024
73d455b
temprary pin numpy<2
valeriupredoi Jun 21, 2024
3007575
unpin and let numpy be two
valeriupredoi Jun 21, 2024
7386b7e
unpin and let numpy be two
valeriupredoi Jun 21, 2024
bf01de0
Merge branch 'main' into numpy2-dev
valeriupredoi Jun 24, 2024
043407a
use the force and xfail the icon test instead
valeriupredoi Jun 24, 2024
a3ccff6
remove commented out pandas pins
valeriupredoi Jun 24, 2024
aefb52c
remove commented out pandas pins
valeriupredoi Jun 24, 2024
1741727
unrun GA
valeriupredoi Jun 24, 2024
4afc351
Update esmvalcore/preprocessor/_compare_with_refs.py
valeriupredoi Jul 3, 2024
6464ecf
Merge branch 'main' into numpy2-dev
valeriupredoi Jul 3, 2024
85b2aa4
remove numpy2 related comment
valeriupredoi Jul 3, 2024
05dea66
remove numpy2 related comment
valeriupredoi Jul 3, 2024
64da79d
Merge branch 'main' into numpy2-dev
valeriupredoi Jul 8, 2024
ea3c702
Merge branch 'main' into numpy2-dev
valeriupredoi Jul 9, 2024
0b2e975
Merge branch 'main' into numpy2-dev
valeriupredoi Aug 5, 2024
b345843
Merge branch 'main' into numpy2-dev
valeriupredoi Sep 13, 2024
55edd79
Merge branch 'main' into numpy2-dev
valeriupredoi Sep 19, 2024
400ccc4
Merge branch 'main' into numpy2-dev
valeriupredoi Sep 27, 2024
e6073eb
run precommit twice
valeriupredoi Sep 27, 2024
803017d
run precommit twice
valeriupredoi Sep 27, 2024
0ee7dcd
Merge branch 'main' into numpy2-dev
valeriupredoi Oct 24, 2024
c4cb2f1
unpin numpy
valeriupredoi Oct 24, 2024
9c5eace
well I have just found one of those rare occasions when merge resulte…
valeriupredoi Oct 24, 2024
519769c
Merge branch 'main' into numpy2-dev
valeriupredoi Oct 30, 2024
fb6cdc3
Merge branch 'main' into numpy2-dev
valeriupredoi Nov 5, 2024
ef6c154
Merge branch 'main' into numpy2-dev
valeriupredoi Nov 11, 2024
dddc083
pin iris
valeriupredoi Nov 11, 2024
858ae11
pin iris
valeriupredoi Nov 11, 2024
e636c7b
rerun GA tests see all is fine
valeriupredoi Nov 11, 2024
acf7838
unrun GA
valeriupredoi Nov 11, 2024
801b7d0
change inline comment
valeriupredoi Nov 11, 2024
bab038d
change inline comment
valeriupredoi Nov 11, 2024
d59d606
cleanup
valeriupredoi Nov 11, 2024
b81db5f
cleanup
valeriupredoi Nov 11, 2024
3bd0468
Update esmvalcore/preprocessor/_regrid_esmpy.py
valeriupredoi Nov 11, 2024
19d7700
Update pyproject.toml
valeriupredoi Nov 11, 2024
8adcd1b
Update environment.yml
valeriupredoi Nov 11, 2024
f11ad18
Update tests/unit/preprocessor/_compare_with_refs/test_compare_with_r…
valeriupredoi Nov 11, 2024
e81c026
revert to old syntax to recheck
valeriupredoi Nov 11, 2024
c99f262
Don't use int8
schlunma Nov 11, 2024
280e692
Restore nice error string when invalid season(s) are given
schlunma Nov 11, 2024
24f2549
Cast 360 to original dtype
schlunma Nov 11, 2024
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
4 changes: 2 additions & 2 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies:
- fire
- geopy
- humanfriendly
- iris >=3.10.0
- iris >=3.11 # 3.11 first to support Numpy 2 and Python 3.13
- iris-esmf-regrid >=0.11.0
- iris-grib >=0.20.0 # github.com/ESMValGroup/ESMValCore/issues/2535
- isodate >=0.7.0 # incompatible with very old 0.6.1
Expand All @@ -27,7 +27,7 @@ dependencies:
- nc-time-axis
- nested-lookup
- netcdf4
- numpy !=1.24.3,<2.0.0 # avoid pulling 2.0.0rcX
- numpy !=1.24.3
- packaging
- pandas
- pillow
Expand Down
6 changes: 5 additions & 1 deletion esmvalcore/preprocessor/_compare_with_refs.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,11 @@ def _calculate_rmse(
weights = get_weights(cube, coords) if weighted else None
squared_error = (cube.core_data() - reference.core_data()) ** 2
npx = get_array_module(squared_error)
rmse = npx.sqrt(npx.ma.average(squared_error, axis=axis, weights=weights))
mse = npx.ma.average(squared_error, axis=axis, weights=weights)
if isinstance(mse, da.Array):
rmse = da.reductions.safe_sqrt(mse)
else:
rmse = np.ma.sqrt(mse)

# Metadata
metadata = CubeMetadata(
Expand Down
2 changes: 1 addition & 1 deletion esmvalcore/preprocessor/_derive/_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def _create_pressure_array(cube, ps_cube, top_limit):
ps_4d_array = iris.util.broadcast_to_shape(ps_cube.data, shape, [0, 2, 3])

# Set pressure levels below the surface pressure to NaN
pressure_4d = np.where((ps_4d_array - p_4d_array) < 0, np.NaN, p_4d_array)
pressure_4d = np.where((ps_4d_array - p_4d_array) < 0, np.nan, p_4d_array)

# Make top_limit last pressure level
top_limit_array = np.full(ps_cube.shape, top_limit, dtype=np.float32)
Expand Down
2 changes: 2 additions & 0 deletions esmvalcore/preprocessor/_derive/co2s.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def _get_first_unmasked_data(array, axis):
*[da.arange(array.shape[i]) for i in range(array.ndim) if i != axis],
indexing="ij",
)

indices = list(indices)
indices.insert(axis, indices_first_positive)
first_unmasked_data = np.array(array)[tuple(indices)]
return first_unmasked_data
Expand Down
2 changes: 1 addition & 1 deletion esmvalcore/preprocessor/_regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def _generate_cube_from_dimcoords(latdata, londata, circular: bool = False):

# Construct the resultant stock cube, with dummy data.
shape = (latdata.size, londata.size)
dummy = np.empty(shape, dtype=np.dtype("int8"))
dummy = np.empty(shape, dtype=np.int32)
coords_spec = [(lats, 0), (lons, 1)]
cube = Cube(dummy, dim_coords_and_dims=coords_spec)

Expand Down
3 changes: 2 additions & 1 deletion esmvalcore/preprocessor/_regrid_esmpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,9 @@ def get_grid(
num_peri_dims = 1
else:
num_peri_dims = 0

grid = esmpy.Grid(
np.array(esmpy_lat.shape),
np.vstack(esmpy_lat.shape),
num_peri_dims=num_peri_dims,
staggerloc=[esmpy.StaggerLoc.CENTER],
)
Expand Down
5 changes: 3 additions & 2 deletions esmvalcore/preprocessor/_regrid_unstructured.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ def _get_weights_and_idx(
src_points_with_convex_hull = self._add_convex_hull_twice(
src_points, hull.vertices
)
src_points_with_convex_hull[-2 * n_hull : -n_hull, 1] -= 360
src_points_with_convex_hull[-n_hull:, 1] += 360
lon_period = np.array(360, dtype=src_points_with_convex_hull.dtype)
src_points_with_convex_hull[-2 * n_hull : -n_hull, 1] -= lon_period
src_points_with_convex_hull[-n_hull:, 1] += lon_period

# Actual weights calculation
(weights, indices) = self._calculate_weights(
Expand Down
6 changes: 4 additions & 2 deletions esmvalcore/preprocessor/_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,9 @@ def seasonal_statistics(
cube, "time", name="clim_season", seasons=seasons
)
else:
old_seasons = sorted(set(cube.coord("clim_season").points))
old_seasons = sorted(
{str(s) for s in cube.coord("clim_season").points}
)
if not all(osea in seasons for osea in old_seasons):
raise ValueError(
f"Seasons {seasons} do not match prior season extraction "
Expand Down Expand Up @@ -1597,7 +1599,7 @@ def _transform_to_lst_eager(
"""
# Apart from the time index, all other dimensions will stay the same; this
# is ensured with np.ogrid
idx = np.ogrid[tuple(slice(0, d) for d in data.shape)]
idx = list(np.ogrid[tuple(slice(0, d) for d in data.shape)])
time_index = broadcast_to_shape(
time_index, data.shape, (time_dim, lon_dim)
)
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ dependencies = [
"nc-time-axis", # needed by iris.plot
"nested-lookup",
"netCDF4",
"numpy!=1.24.3,<2.0.0", # avoid pulling 2.0.0rc1
"numpy!=1.24.3",
"packaging",
"pandas",
"pillow",
Expand All @@ -61,7 +61,7 @@ dependencies = [
"pyyaml",
"requests",
"scipy>=1.6",
"scitools-iris>=3.10.0",
"scitools-iris>=3.11", # 3.11 first to support Numpy 2 and Python 3.13
"shapely>=2.0.0",
"stratify>=0.3",
"yamale",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
from tests import PreprocessorFile


def assert_allclose(array_1, array_2):
def assert_allclose(array_1, array_2, rtol=1e-7):
"""Assert that (masked) array 1 is close to (masked) array 2."""
if np.ma.is_masked(array_1) or np.ma.is_masked(array_2):
mask_1 = np.ma.getmaskarray(array_1)
mask_2 = np.ma.getmaskarray(array_2)
np.testing.assert_equal(mask_1, mask_2)
np.testing.assert_allclose(array_1[~mask_1], array_2[~mask_2])
np.testing.assert_allclose(array_1[~mask_1], array_2[~mask_2], rtol)
else:
np.testing.assert_allclose(array_1, array_2)
np.testing.assert_allclose(array_1, array_2, rtol)


def products_set_to_dict(products):
Expand Down Expand Up @@ -473,7 +473,10 @@ def test_distance_metric(
assert out_cube.shape == ()
assert out_cube.dtype == np.float32
assert not out_cube.has_lazy_data()
assert_allclose(out_cube.data, ref_data)
# an rtol=1e-6 is needed for numpy >=2.0
assert_allclose(
out_cube.data, np.array(ref_data, dtype=np.float32), rtol=1e-6
)
assert out_cube.var_name == var_name
assert out_cube.long_name == long_name
assert out_cube.standard_name is None
Expand Down Expand Up @@ -684,7 +687,8 @@ def test_distance_metric_masked_data(
expected_data = np.ma.masked_invalid(data)
else:
expected_data = np.array(data, dtype=np.float32)
assert_allclose(out_cube.data, expected_data)
# an rtol=1e-6 is needed for numpy >=2.0
assert_allclose(out_cube.data, expected_data, rtol=1e-6)
assert out_cube.var_name == var_name
assert out_cube.long_name == long_name
assert out_cube.standard_name is None
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/preprocessor/_derive/test_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def test_low_lev_below_surf_press():
"""Test for lowest level below surface pressure."""
plev = 970
top_limit = 5
col = np.array([np.NaN, 900, 800])
col = np.array([np.nan, 900, 800])
col = np.insert(col, 0, plev)
col = np.append(col, top_limit)
result = np.array([0, 120, 845])
Expand All @@ -197,7 +197,7 @@ def test_low_lev_below_surf_press():
np.atleast_3d(result),
)

col = np.array([np.NaN, np.NaN, 900, 800])
col = np.array([np.nan, np.nan, 900, 800])
col = np.insert(col, 0, plev)
col = np.append(col, top_limit)
result = np.array([0, 0, 120, 845])
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/preprocessor/_regrid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
def _make_vcoord(data, dtype=None):
"""Create a synthetic test vertical coordinate."""
if dtype is None:
dtype = np.dtype("int8")
dtype = np.int32

if isinstance(data, int):
data = np.arange(data, dtype=dtype)
Expand Down Expand Up @@ -45,7 +45,7 @@ def _make_cube(
):
"""Create a 3d synthetic test cube."""
if dtype is None:
dtype = np.dtype("int8")
dtype = np.int32

if not isinstance(data, np.ndarray):
data = np.empty(data, dtype=dtype)
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/preprocessor/_regrid/test__create_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
class Test(tests.Test):
def setUp(self):
shape = (3, 2, 1)
self.dtype = np.dtype("int8")
self.dtype = np.int32
self.cube = _make_cube(shape, dtype=self.dtype)

def test_invalid_shape__data_mismatch_with_levels(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/preprocessor/_regrid/test_extract_levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Test(tests.Test):
def setUp(self):
self.shape = (3, 2, 1)
self.z = self.shape[0]
self.dtype = np.dtype("int8")
self.dtype = np.int32
data = np.arange(np.prod(self.shape), dtype=self.dtype).reshape(
self.shape
)
Expand Down