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

Dimensionless units as "1" - adapt to numpy 2 #1814

Merged
merged 40 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
583917f
Fix NaN and Inf
aulemahal Jun 27, 2024
06d18ca
Fix tests for numpy 2
aulemahal Jun 28, 2024
7e9107e
remove pint pin
aulemahal Jun 28, 2024
e3b9851
upd changes
aulemahal Jun 28, 2024
7a36c35
Merge branch 'main' into fix-for-np2
aulemahal Jun 28, 2024
deaa702
Merge branch 'main' into fix-for-np2
Zeitsperre Jul 2, 2024
7330221
upd pin for cf-xarray
aulemahal Jul 8, 2024
b446e60
Merge branch 'main' into fix-for-np2
aulemahal Jul 8, 2024
c14d0b9
Pin cf_xarray, pint and numpy - adapt to "1" change
aulemahal Jul 8, 2024
da22473
Add ensure_absolute_tempetature to __all__ and refactor to put both s…
aulemahal Jul 8, 2024
14c1f59
new spi test values (due to np2's float32)
coxipi Jul 10, 2024
7be1d57
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 10, 2024
cc4fe55
Merge branch 'main' into fix-for-np2
aulemahal Jul 11, 2024
c21b8ed
Merge branch 'main' into fix-for-np2
Zeitsperre Jul 26, 2024
d956c3f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2024
97d653b
fix changelog
Zeitsperre Jul 26, 2024
60a186c
revert pins
Zeitsperre Jul 26, 2024
0f289e8
WIP - conditional tests
Zeitsperre Jul 26, 2024
9943914
add an older numpy build
Zeitsperre Jul 26, 2024
8967596
fix imports
Zeitsperre Jul 26, 2024
82c6f20
unpin netcdf4
Zeitsperre Jul 26, 2024
3577bbb
woops
Zeitsperre Jul 26, 2024
107d44c
use h5netcdf
Zeitsperre Jul 26, 2024
fd952b2
promote h5netcdf to dependency, address errors
Zeitsperre Jul 26, 2024
0f6f756
add h5netcdf to deptry
Zeitsperre Jul 26, 2024
4aeeb89
add xarray engine to cli
Zeitsperre Jul 26, 2024
a2b0b42
adjust more IO calls to use h5netcdf
Zeitsperre Jul 26, 2024
cf286d2
fix cannon test
Zeitsperre Jul 26, 2024
d557f4d
use h5netcdf
Zeitsperre Jul 26, 2024
4d95e63
Remove netCDF4 as a dep - put h5netcdf back to dev deps - fix cli tests
aulemahal Jul 26, 2024
3312405
replace open_dataset
Zeitsperre Jul 31, 2024
39f1e65
Merge branch 'main' into fix-for-np2
Zeitsperre Jul 31, 2024
f472a9c
Merge branch 'main' into fix-for-np2
Zeitsperre Jul 31, 2024
3f3ae71
Better Version checks
aulemahal Jul 31, 2024
967ddbb
oups wrong version
aulemahal Jul 31, 2024
14a62d5
Update CHANGELOG.rst
aulemahal Jul 31, 2024
0524386
fix doctests
aulemahal Jul 31, 2024
3d4beab
Remove opendap test as the CI doesnt have opendap support anymore
aulemahal Jul 31, 2024
1bc53fd
Fix notebooks for netCDF4 absence
aulemahal Jul 31, 2024
3ded3ed
Fix xarray 2024.7.0 regression (?) issue 9300
aulemahal Jul 31, 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 .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:
markers: -m 'not slow'
os: windows-latest
# macOS builds
- tox-env: py310-coverage-extras-lmoments
- tox-env: py310-coverage-extras-lmoments-numpy
python-version: "3.10"
markers: -m 'not slow'
os: macos-latest
Expand All @@ -135,7 +135,7 @@ jobs:
- tox-env: py310-coverage-lmoments # No markers -- includes slow tests
python-version: "3.10"
os: ubuntu-latest
- tox-env: py311-coverage-extras-sbck
- tox-env: py311-coverage-extras-sbck-numpy
python-version: "3.11"
markers: -m 'not slow'
os: ubuntu-latest
Expand Down
7 changes: 6 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ Changelog

v0.52.0 (unreleased)
--------------------
Contributors to this version: David Huard (:user:`huard`), Trevor James Smith (:user:`Zeitsperre`), Hui-Min Wang (:user:`Hem-W`), Éric Dupuis (:user:`coxipi`), Sarah Gammon (:user:`SarahG-579462`).
Contributors to this version: David Huard (:user:`huard`), Trevor James Smith (:user:`Zeitsperre`), Hui-Min Wang (:user:`Hem-W`), Éric Dupuis (:user:`coxipi`), Sarah Gammon (:user:`SarahG-579462`), Pascal Bourgault (:user:`aulemahal`).

New features and enhancements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* ``xclim.sdba.nbutils.quantile`` and its child functions are now faster. If the module `fastnanquantile` is installed, it is used as the backend for the computation of quantiles and yields even faster results. This dependency is now listed in the `xclim[extras]` recipe. (:issue:`1255`, :pull:`1513`).
* New multivariate bias adjustment class `MBCn`, giving a faster and more accurate implementation of the 'MBCn' algorithm (:issue:`1551`, :pull:`1580`).
* `xclim` is now compatible with `pytest` versions `>=8.0.0`. (:pull:`1632`).

Breaking changes
^^^^^^^^^^^^^^^^
* As updated in ``cf_xarray>=0.9.3``, dimensionless quantities now use the "1" units attribute as specified by the CF conventions, previously an empty string was returned. (:pull:`1814`).

Bug fixes
^^^^^^^^^
* Fixed the indexer bug in the ``xclim.indices.standardized_index_fit_params`` when multiple or non-array indexers are specified and fitted parameters are reloaded from netCDF. (:issue:`1842`, :pull:`1843`).
* Addressed a bug found in ``wet_spell_*`` indicators that was contributing to erroneous results. A new generic spell length statistic function ``xclim.indices.generic.spell_length_statistics`` is now used in wet and dry spells indicators. (:issue:`1834`, :pull:`1838`).
* Syntax for ``nan`` and ``inf`` was adapted to support ``numpy>=2.0.0``. (:pull:`1814`, :issue:`1785`).

Internal changes
^^^^^^^^^^^^^^^^
Expand Down
8 changes: 5 additions & 3 deletions docs/notebooks/sdba-advanced.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,9 @@
"metadata": {},
"outputs": [],
"source": [
"QDM.ds.to_netcdf(\"QDM_training.nc\")\n",
"# The engine keyword is only needed if netCDF4 is not available\n",
"# The training dataset contains some attributes with types not supported by scipy/netCDF3\n",
"QDM.ds.to_netcdf(\"QDM_training.nc\", engine=\"h5netcdf\")\n",
"ds = xr.open_dataset(\"QDM_training.nc\")\n",
"QDM2 = QuantileDeltaMapping.from_dataset(ds)\n",
"QDM2"
Expand All @@ -292,7 +294,7 @@
"metadata": {},
"outputs": [],
"source": [
"QDM.ds.to_netcdf(\"QDM_training2.nc\")\n",
"QDM.ds.to_netcdf(\"QDM_training2.nc\", engine=\"h5netcdf\")\n",
"ds = xr.open_dataset(\"QDM_training2.nc\")\n",
"ds.attrs[\"title\"] = \"This is the dataset, but read from disk.\"\n",
"QDM.set_dataset(ds)\n",
Expand Down Expand Up @@ -878,7 +880,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.12.4"
},
"toc": {
"base_numbering": 1,
Expand Down
4 changes: 2 additions & 2 deletions docs/notebooks/sdba.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@
"outputs": [],
"source": [
"# We are using xarray's \"air_temperature\" dataset\n",
"ds = xr.tutorial.open_dataset(\"air_temperature\")"
"ds = xr.tutorial.load_dataset(\"air_temperature\")"
]
},
{
Expand Down Expand Up @@ -598,7 +598,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
"version": "3.12.4"
},
"toc": {
"base_numbering": 1,
Expand Down
6 changes: 2 additions & 4 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
name: xclim
channels:
- numba # Added to gain access to Python3.12-compatible numba release candidates.
- conda-forge
- defaults
dependencies:
Expand All @@ -13,9 +12,9 @@ dependencies:
- dask >=2.6.0
- jsonpickle
- numba
- numpy >=1.20.0,<2.0.0
- numpy >=1.20.0
- pandas >=2.2.0
- pint >=0.10,<0.24
- pint >=0.18.0
- poppler >=0.67
- pyarrow # Strongly encouraged for Pandas v2.2.0+
- pyyaml
Expand Down Expand Up @@ -53,7 +52,6 @@ dependencies:
- nbsphinx
- nbval >=0.11.0
- nc-time-axis
- netCDF4 >=1.4,<1.7
- notebook
- pandas-stubs
- platformdirs
Expand Down
7 changes: 3 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ dependencies = [
"filelock",
"jsonpickle",
"numba",
"numpy>=1.20.0,<2.0.0",
"numpy>=1.20.0",
"packaging",
"pandas>=2.2",
"pint>=0.10,<0.24",
"pint>=0.18",
"platformdirs >=3.2",
"pyarrow", # Strongly encouraged for pandas v2.2.0+
"pyyaml",
Expand Down Expand Up @@ -74,7 +74,6 @@ dev = [
"nbconvert <7.14", # Pinned due to directive errors in sphinx. See: https://github.com/jupyter/nbconvert/issues/2092
"nbqa >=1.8.2",
"nbval >=0.11.0",
"netCDF4 >=1.4,<1.7",
"pandas-stubs >=2.2",
"platformdirs >=3.2",
"pooch",
Expand Down Expand Up @@ -181,7 +180,7 @@ pep621_dev_dependency_groups = ["all", "dev", "docs"]

[tool.deptry.per_rule_ignores]
DEP001 = ["SBCK"]
DEP002 = ["bottleneck", "pyarrow"]
DEP002 = ["bottleneck", "h5netcdf", "pyarrow"]
DEP004 = ["matplotlib", "pytest", "pytest_socket"]

[tool.flit.sdist]
Expand Down
8 changes: 7 additions & 1 deletion tests/test_atmos.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import numpy as np
import xarray as xr
from cf_xarray import __version__ as __cfxr_version__
from packaging.version import Version

from xclim import atmos, set_options

Expand Down Expand Up @@ -260,7 +262,11 @@ def test_wind_profile(atmosds):

def test_wind_power_potential(atmosds):
out = atmos.wind_power_potential(wind_speed=atmosds.sfcWind)
assert out.attrs["units"] == ""

if Version(__cfxr_version__) < Version("0.9.3"):
assert out.attrs["units"] == ""
else:
assert out.attrs["units"] == "1"
assert (out >= 0).all()
assert (out <= 1).all()

Expand Down
6 changes: 3 additions & 3 deletions tests/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def test_convert_calendar_and_doy():
out = convert_doy(doy, target_cal="360_day", align_on="date").convert_calendar(
"360_day", align_on="date"
)
np.testing.assert_array_equal(out, [np.NaN, 31, 332, 360.23, np.NaN])
np.testing.assert_array_equal(out, [np.nan, 31, 332, 360.23, np.nan])
assert out.time.dt.calendar == "360_day"


Expand Down Expand Up @@ -456,7 +456,7 @@ def test_convert_doy():
)

out = convert_doy(doy, "360_day", align_on="date")
np.testing.assert_array_equal(out, [np.NaN, 31, 332, 360.23, np.NaN])
np.testing.assert_array_equal(out, [np.nan, 31, 332, 360.23, np.nan])
assert out.time.dt.calendar == "noleap"
out = convert_doy(doy, "360_day", align_on="year")
np.testing.assert_allclose(
Expand All @@ -475,7 +475,7 @@ def test_convert_doy():
).expand_dims(lat=[10, 20, 30])

out = convert_doy(doy, "noleap", align_on="date")
np.testing.assert_array_equal(out.isel(lat=0), [31, 200.48, 190, np.NaN, 299.54])
np.testing.assert_array_equal(out.isel(lat=0), [31, 200.48, 190, np.nan, 299.54])
out = convert_doy(doy, "noleap", align_on="year")
np.testing.assert_allclose(
out.isel(lat=0), [31.0, 200.48, 190.0, 59.83607, 299.71885]
Expand Down
12 changes: 6 additions & 6 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def test_normal_computation(
input_file = tmp_path / "in.nc"
output_file = tmp_path / "out.nc"

ds.to_netcdf(input_file)
ds.to_netcdf(input_file, engine="h5netcdf")

args = ["-i", str(input_file), "-o", str(output_file), "-v", indicator]
runner = CliRunner()
Expand Down Expand Up @@ -136,7 +136,7 @@ def test_multi_output(tmp_path, open_dataset):
ds = open_dataset("ERA5/daily_surface_cancities_1990-1993.nc")
input_file = tmp_path / "ws_in.nc"
output_file = tmp_path / "out.nc"
ds.to_netcdf(input_file)
ds.to_netcdf(input_file, engine="h5netcdf")

runner = CliRunner()
results = runner.invoke(
Expand Down Expand Up @@ -216,7 +216,7 @@ def test_missing_variable(tas_series, tmp_path):
input_file = tmp_path / "tas.nc"
output_file = tmp_path / "out.nc"

tas.to_netcdf(input_file)
tas.to_netcdf(input_file, engine="h5netcdf")

runner = CliRunner()
results = runner.invoke(
Expand All @@ -243,7 +243,7 @@ def test_global_options(tas_series, tmp_path, options, output):
input_file = tmp_path / "tas.nc"
output_file = tmp_path / "out.nc"

tas.to_netcdf(input_file)
tas.to_netcdf(input_file, engine="h5netcdf")

runner = CliRunner()
results = runner.invoke(
Expand Down Expand Up @@ -283,7 +283,7 @@ def test_dataflags_output(tmp_path, tas_series, tasmax_series, tasmin_series):
arr = series(vals, start="1971-01-01")
ds = xr.merge([ds, arr])
input_file = tmp_path / "ws_in.nc"
ds.to_netcdf(input_file)
ds.to_netcdf(input_file, engine="h5netcdf")

runner = CliRunner()
results = runner.invoke(
Expand All @@ -303,7 +303,7 @@ def test_bad_usage(tas_series, tmp_path):
input_file = tmp_path / "tas.nc"
output_file = tmp_path / "out.nc"

tas.to_netcdf(input_file)
tas.to_netcdf(input_file, engine="h5netcdf")

runner = CliRunner()

Expand Down
12 changes: 9 additions & 3 deletions tests/test_ensembles.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def test_no_time(self, tmp_path, ensemble_dataset_objects, open_dataset):
ds["time"] = xr.decode_cf(ds).time
ds_all.append(ds.groupby(ds.time.dt.month).mean("time", keep_attrs=True))
ds.groupby(ds.time.dt.month).mean("time", keep_attrs=True).to_netcdf(
f1.joinpath(Path(n).name)
f1.joinpath(Path(n).name), engine="h5netcdf"
)
ens = ensembles.create_ensemble(ds_all)

Expand Down Expand Up @@ -288,8 +288,14 @@ def test_calc_mean_std_min_max(self, ensemble_dataset_objects, open_dataset):
)
out2 = ensembles.ensemble_mean_std_max_min(ens, weights=weights)
values = ens["tg_mean"][:, 0, 5, 5]
# Explicit float64 so numpy does the expected datatype promotion (change in numpy 2)
np.testing.assert_array_equal(
(values[0] * 1 + values[1] * 0.1 + values[2] * 3.5 + values[3] * 5)
(
values[0] * np.float64(1)
+ values[1] * np.float64(0.1)
+ values[2] * np.float64(3.5)
+ values[3] * np.float64(5)
)
/ np.sum(weights),
out2.tg_mean_mean[0, 5, 5],
)
Expand All @@ -311,7 +317,7 @@ def test_stats_min_members(self, ensemble_dataset_objects, open_dataset, aggfunc
ds_all = [open_dataset(n) for n in ensemble_dataset_objects["nc_files_simple"]]
ens = ensembles.create_ensemble(ds_all).isel(lat=0, lon=0)
ens = ens.where(ens.realization > 0)
ens = xr.where((ens.realization == 1) & (ens.time.dt.year == 1950), np.NaN, ens)
ens = xr.where((ens.realization == 1) & (ens.time.dt.year == 1950), np.nan, ens)

def first(ds):
return ds[list(ds.data_vars.keys())[0]]
Expand Down
16 changes: 11 additions & 5 deletions tests/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import numpy as np
import pytest
import xarray as xr
from cf_xarray import __version__ as __cfxr_version__
from packaging.version import Version

from xclim.core.calendar import doy_to_days_since, select_time
from xclim.indices import generic
Expand Down Expand Up @@ -101,7 +103,11 @@ def test_doyminmax(self, q_series):
for da in [dmx, dmn]:
for attr in ["units", "is_dayofyear", "calendar"]:
assert attr in da.attrs.keys()
assert da.attrs["units"] == ""

if Version(__cfxr_version__) < Version("0.9.3"):
assert da.attrs["units"] == ""
else:
assert da.attrs["units"] == "1"
assert da.attrs["is_dayofyear"] == 1


Expand Down Expand Up @@ -393,13 +399,13 @@ def test_generic_forbidden_op(self, pr_series):

class TestGetDailyEvents:
def test_simple(self, tas_series):
arr = xr.DataArray(np.array([-10, 15, 20, np.NaN, 10]), name="Stuff")
arr = xr.DataArray(np.array([-10, 15, 20, np.nan, 10]), name="Stuff")

out = generic.get_daily_events(arr, threshold=10, op=">=")

assert out.name == "events"
assert out.sum() == 3
np.testing.assert_array_equal(out, [0, 1, 1, np.NaN, 1])
np.testing.assert_array_equal(out, [0, 1, 1, np.nan, 1])


class TestGenericCountingIndices:
Expand Down Expand Up @@ -470,7 +476,7 @@ def test_count_occurrences(self, tas_series, op, constrain, expected, should_fai
@pytest.mark.parametrize(
"op, constrain, expected, should_fail",
[
("<", None, np.NaN, False),
("<", None, np.nan, False),
("<=", None, 3, False),
("!=", ("!=",), 1, False),
("==", ("==", "!="), 3, False),
Expand All @@ -497,7 +503,7 @@ def test_first_occurrence(self, tas_series, op, constrain, expected, should_fail
@pytest.mark.parametrize(
"op, constrain, expected, should_fail",
[
("<", None, np.NaN, False),
("<", None, np.nan, False),
("<=", None, 8, False),
("!=", ("!=",), 9, False),
("==", ("==", "!="), 8, False),
Expand Down
8 changes: 7 additions & 1 deletion tests/test_hydrology.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import annotations

import numpy as np
from cf_xarray import __version__ as __cfxr_version__
from packaging.version import Version

from xclim import indices as xci

Expand Down Expand Up @@ -40,7 +42,11 @@ def test_simple(self, snw_series):
snw = snw_series(a, start="1999-01-01")
out = xci.snw_max_doy(snw, freq="YS")
np.testing.assert_array_equal(out, [11, np.nan])
assert out.units == ""

if Version(__cfxr_version__) < Version("0.9.3"):
assert out.attrs["units"] == ""
else:
assert out.attrs["units"] == "1"


class TestSnowMeltWEMax:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_indicators.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ def test_resampling_indicator_with_indexing(tas_series):
out = xclim.atmos.tx_days_above(
tas, thresh="0 degC", freq="YS-JUL", doy_bounds=(1, 50)
)
np.testing.assert_allclose(out, [50, 50, np.NaN])
np.testing.assert_allclose(out, [50, 50, np.nan])

out = xclim.atmos.tx_days_above(
tas, thresh="0 degC", freq="YS", date_bounds=("02-29", "04-01")
Expand Down
Loading