diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 075a4f433..5e9aad5bc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -46,6 +46,21 @@ Internal changes CI changes ^^^^^^^^^^ * The `pip` cache, `tox` environments, and the `xclim-testdata` cache are now saved between workflow runs (using `actions/cache`) to reduce the time spent installing dependencies and downloading testing data. (:pull:`1906`). +v0.52.2 (2024-09-16) +-------------------- +Contributors to this version: Pascal Bourgault (:user:`aulemahal`). + +Bug fixes +^^^^^^^^^ +* Fixed ``decimal_year`` import, fixed functions ``rate2amount``, ``amount2rate``, ``time_bnds`` and ``stack_periods`` for `xarray` version 2024.09.0. Removed ``datetime_to_decimal_year`` as the mirrored `xarray` function was replaced by ``ds.time.dt.decimal_year``. (:pull:`1920`). + +v0.52.1 (2024-09-11) +-------------------- +Contributors to this version: Trevor James Smith (:user:`Zeitsperre`). + +Bug fixes +^^^^^^^^^ +* Adjusted the required base version of `pyarrow` to be `v10.0.1` to address an environment resolution error on conda-forge. (:pull:`1918`). v0.52.0 (2024-08-08) -------------------- diff --git a/environment.yml b/environment.yml index 9a7c4ea35..b6573e620 100644 --- a/environment.yml +++ b/environment.yml @@ -52,6 +52,7 @@ dependencies: - nbsphinx - nbval >=0.11.0 - nc-time-axis >=1.4.1 + - netcdf4 # Required for some Jupyter notebooks - notebook - pandas-stubs >=2.2 - pooch >=1.8.0 diff --git a/pyproject.toml b/pyproject.toml index 71bfbd6e3..b3bbc4f6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ dependencies = [ "packaging >=24.0", "pandas >=2.2", "pint >=0.18", - "pyarrow >=15.0.0", # Strongly encouraged for pandas v2.2.0+ + "pyarrow >=10.0.1", # Strongly encouraged for pandas v2.2.0+ "pyyaml >=6.0.1", "scikit-learn >=0.21.3", "scipy >=1.9.0", @@ -136,7 +136,7 @@ target-version = [ ] [tool.bumpversion] -current_version = "0.52.1-dev.5" +current_version = "0.52.3-dev.0" commit = true commit_args = "--no-verify" tag = false diff --git a/tests/test_testing_utils.py b/tests/test_testing_utils.py index 03b871986..6fb5d2dd1 100644 --- a/tests/test_testing_utils.py +++ b/tests/test_testing_utils.py @@ -37,9 +37,6 @@ def file_md5_checksum(f_name): hash_md5.update(f.read()) return hash_md5.hexdigest() - @pytest.mark.skip( - "This test has been significantly modified. Will adjust when #1889 is merged." - ) @pytest.mark.requires_internet def test_open_testdata( self, diff --git a/xclim/__init__.py b/xclim/__init__.py index 79a8237fb..543f308f7 100644 --- a/xclim/__init__.py +++ b/xclim/__init__.py @@ -13,7 +13,7 @@ __author__ = """Travis Logan""" __email__ = "logan.travis@ouranos.ca" -__version__ = "0.52.1-dev.5" +__version__ = "0.52.3-dev.0" with _resources.as_file(_resources.files("xclim.data")) as _module_data: diff --git a/xclim/core/calendar.py b/xclim/core/calendar.py index e75c3026b..78c8a0460 100644 --- a/xclim/core/calendar.py +++ b/xclim/core/calendar.py @@ -773,7 +773,7 @@ def time_bnds( # noqa: C901 time = time.indexes[time.name] elif isinstance(time, (DataArrayResample, DatasetResample)): for grouper in time.groupers: - if "time" in grouper.dims: + if isinstance(grouper.grouper, xr.groupers.TimeResampler): datetime = grouper.unique_coord.data freq = freq or grouper.grouper.freq if datetime.dtype == "O": @@ -1354,13 +1354,13 @@ def stack_periods( for _, strd_slc in da.resample(time=strd_frq).groups.items(): win_resamp = time2.isel(time=slice(strd_slc.start, None)).resample(time=win_frq) # Get slice for first group - win_slc = win_resamp._group_indices[0] + win_slc = list(win_resamp.groups.values())[0] if min_length < window: # If we ask for a min_length period instead is it complete ? min_resamp = time2.isel(time=slice(strd_slc.start, None)).resample( time=minl_frq ) - min_slc = min_resamp._group_indices[0] + min_slc = list(min_resamp.groups.values())[0] open_ended = min_slc.stop is None else: # The end of the group slice is None if no outside-group value was found after the last element @@ -1545,7 +1545,7 @@ def _reconstruct_time(_time_as_delta, _start): periods = [] for i, (start, length) in enumerate(zip(starts.values, lengths.values)): real_time = _reconstruct_time(time_as_delta, start) - slices = real_time.resample(time=strd_frq)._group_indices + slices = list(real_time.resample(time=strd_frq).groups.values()) if i == 0: slc = slice(slices[0].start, min(slices[mid].stop, length)) elif i == da.period.size - 1: diff --git a/xclim/core/units.py b/xclim/core/units.py index 51b479c27..bf494763c 100644 --- a/xclim/core/units.py +++ b/xclim/core/units.py @@ -17,6 +17,7 @@ import cf_xarray.units import numpy as np +import pandas as pd import pint import xarray as xr from boltons.funcutils import wraps @@ -650,7 +651,10 @@ def _rate_and_amount_converter( start = time.indexes[dim][0] if not start_anchor: # Anchor is on the end of the period, subtract 1 period. - start = start - xr.coding.cftime_offsets.to_offset(freq) + if isinstance(start, pd.Timestamp): + start = start - pd.tseries.frequencies.to_offset(freq) + else: + start = start - xr.coding.cftime_offsets.to_offset(freq) # In the diff below, assign to upper label! label = "upper" # We generate "time" with an extra element, so we do not need to repeat the last element below. diff --git a/xclim/indices/helpers.py b/xclim/indices/helpers.py index 4af47b962..2a172212c 100644 --- a/xclim/indices/helpers.py +++ b/xclim/indices/helpers.py @@ -16,9 +16,15 @@ import numba as nb import numpy as np import xarray as xr -from xarray.coding.calendar_ops import ( - _datetime_to_decimal_year as datetime_to_decimal_year, -) + +try: + from xarray.coding.calendar_ops import ( + _datetime_to_decimal_year as datetime_to_decimal_year, + ) +except ImportError: + XR2409 = True +else: + XR2409 = False from xclim.core import Quantified from xclim.core.calendar import ensure_cftime_array, get_calendar @@ -70,7 +76,10 @@ def day_angle(time: xr.DataArray): the beginning of the year up to that timestep. Also called the "julian day fraction". See :py:func:`~xclim.core.calendar.datetime_to_decimal_year`. """ - decimal_year = datetime_to_decimal_year(times=time, calendar=time.dt.calendar) + if XR2409: + decimal_year = time.dt.decimal_year + else: + decimal_year = datetime_to_decimal_year(times=time, calendar=time.dt.calendar) return ((decimal_year % 1) * 2 * np.pi).assign_attrs(units="rad")