Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Ouranosinc/xclim into spi…
Browse files Browse the repository at this point in the history
…_loc
  • Loading branch information
coxipi committed Feb 22, 2024
2 parents 7c89f33 + 334add7 commit c2f020d
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: 'Dependency Review'
uses: actions/dependency-review-action@fd07d42ce87ab09f10c61a2d1a5e59e6c655620a
uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce
6 changes: 1 addition & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ jobs:
repo.anaconda.com:443
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Conda (Micromamba) with Python${{ matrix.python-version }}
uses: mamba-org/setup-micromamba@8767fb704bd78032e9392f0386bf46950bdd1194 # v1.8.0
uses: mamba-org/setup-micromamba@422500192359a097648154e8db4e39bdb6c6eed7 # v1.8.1
with:
cache-downloads: true
cache-environment: true
Expand Down Expand Up @@ -276,10 +276,6 @@ jobs:
runs-on: ubuntu-latest
container: python:3-slim
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
egress-policy: audit
- name: Coveralls Finished
run: |
python -m pip install --upgrade coveralls
Expand Down
13 changes: 8 additions & 5 deletions .github/workflows/publish-mastodon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ jobs:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
egress-policy: audit
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
github.com:443
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
Expand Down Expand Up @@ -77,9 +81,8 @@ jobs:
if: ${{ github.event.inputs.dry-run != 'true' }} || ${{ github.event_name == 'release' }}
uses: cbrgm/mastodon-github-action@eb0fa2c755679b459015a898dada174b5ddbff7c # v2.0.2
with:
language: "en"
url: ${{ secrets.MASTODON_URL }}
access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }}
message: "${{ steps.render_template.outputs.result }}${{ env.contributors }}"
language: "en"
visibility: "public"
env:
MASTODON_URL: ${{ secrets.MASTODON_URL }}
MASTODON_ACCESS_TOKEN: ${{ secrets.MASTODON_ACCESS_TOKEN }}
8 changes: 7 additions & 1 deletion .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ jobs:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
egress-policy: audit
disable-sudo: true
egress-policy: block
allowed-endpoints: >
files.pythonhosted.org:443
github.com:443
pypi.org:443
upload.pypi.org:443
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Python3
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/tag-testpypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ jobs:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
egress-policy: audit
disable-sudo: true
egress-policy: block
allowed-endpoints: >
files.pythonhosted.org:443
github.com:443
pypi.org:443
test.pypi.org:443
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Python3
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/upstream.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
with:
fetch-depth: 0 # Fetch all history for all branches and tags.
- name: Setup Conda (Micromamba) with Python${{ matrix.python-version }}
uses: mamba-org/setup-micromamba@8767fb704bd78032e9392f0386bf46950bdd1194 # v1.8.0
uses: mamba-org/setup-micromamba@422500192359a097648154e8db4e39bdb6c6eed7 # v1.8.1
with:
cache-downloads: true
cache-environment: true
Expand Down
40 changes: 26 additions & 14 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@
Changelog
=========

v0.48 (unreleased)
------------------
Contributors to this version: Juliette Lavoie (:user:`juliettelavoie`), Pascal Bourgault (:user:`aulemahal`), Trevor James Smith (:user:`Zeitsperre`), David Huard (:user:`huard`), Éric Dupuis (:user:`coxipi`), Dante Castro (:user:`profesorpaiche`).
v0.48.1 (2024-02-20)
--------------------
Contributors to this version: Trevor James Smith (:user:`Zeitsperre`).

Bug fixes
^^^^^^^^^
* Fixed an issue with missing `conda` dependencies in the `xclim` documentation. (:pull:`1657`).
* Adjusted the Mastodon publishing workflow. (:pull:`1657`).
* Pinned `nbconvert` to address regressions when building the documentation. (:pull:`1658`).

v0.48.0 (2024-02-19)
--------------------
Contributors to this version: Juliette Lavoie (:user:`juliettelavoie`), Pascal Bourgault (:user:`aulemahal`), Trevor James Smith (:user:`Zeitsperre`), David Huard (:user:`huard`), Éric Dupuis (:user:`coxipi`), Dante Castro (:user:`profesorpaiche`), Gabriel Rondeau-Genesse (:user:`RondeauG`).

Announcements
^^^^^^^^^^^^^
Expand All @@ -21,40 +31,41 @@ New features and enhancements
* Support ``indexer`` keyword in YAML indicator description. (:issue:`1522`, :pull:`1561`).
* New ``xclim.core.calendar.stack_periods`` and ``unstack_periods`` for performing ``rolling(time=...).construct(..., stride=...)`` but with non-uniform temporal periods like years or months. They replace ``xclim.sdba.processing.construct_moving_yearly_window`` and ``unpack_moving_yearly_window`` which are deprecated and will be removed in a future release.
* New ``as_dataset`` options for ``xclim.set_options``. When True, indicators will output Datasets instead of DataArrays. (:issue:`1257`, :pull:`1625`).
* Added new option for UTCI calculation to cap low wind velocities to a minimum of 0.5 m/s following Bröde (2012) guidelines. (:issue:`1634`, :pull:`1635`).
* Distribution with negative values are directly fitted without need for an offset for distributions such as `gamma, fisk` in ``xclim.indices.standardized_precipitation_evapotranspiration_index``. (:issue:`1477` :pull:`1653`).

* Added new option for ``universal_thermal_climate_index`` calculation (``wind_cap_min: bool``) to cap low wind velocities to a minimum of 0.5 m/s following Bröde (2012) guidelines. (:issue:`1634`, :pull:`1635`).
* Added option ``never_reached`` to ``degree_days_exceedance_date`` to assign a custom value when the sum threshold is never reached. (:issue:`1459`, :pull:`1647`).
* Added option ``min_members`` to ensemble statistics to mask elements when the number of valid members is under a threshold. (:issue:`1459`, :pull:`1647`).
* Distribution instances can now be passed to the ``dist`` argument of most statistical indices. (:pull:`1644`).
* Added a new ``xclim.indices.generic.select_rolling_resample_op`` function to allow for computing rolling statistics. (:issue:`1480`, :pull:`1643`).
* Add the possibility to use a group with a window in ``xc.sdba.processing.reordering``. (:pull:`1566`).
* Distribution with negative values are directly fitted without need for an offset for distributions such as `gamma, fisk` in ``xclim.indices.standardized_precipitation_evapotranspiration_index``. (:issue:`1477` :pull:`1653`).

Breaking changes
^^^^^^^^^^^^^^^^
* `xclim` base Python version has been raised to `python>=3.9`. Python3.9+ coding conventions are now supported. (:issue:`1268`, :pull:`1565`).
* `xclim` base Python version has been raised to Python3.9. Python3.9+ coding conventions are now supported. (:issue:`1268`, :pull:`1565`).
* `xclim` base dependencies have been raised to `pandas>=2.2.0` and `xarray>=2023.11.0` to reflect changes to time frequency codes introduced in `pandas==2.2.0`. (:issue:`1534`, :pull:`1565`; see also: `pydata/xarray GH/8394 <https://github.com/pydata/xarray/issues/8394>`_ and ). Many default frequency string outputs have been modified (:
* 'Y' (year) -> 'YE' (year end). (see: `pandas PR/55792 <https://github.com/pandas-dev/pandas/pull/55792>`_).
* 'M' (month) -> 'ME' (month end). (see: `pandas PR/52064 <https://github.com/pandas-dev/pandas/pull/52064>`_).
* 'Q' (quarter) -> 'QE' (quarter end). (see: `pandas PR/55553 <https://github.com/pandas-dev/pandas/pull/55553>`_)
* 'A' and 'AS' have been removed (use 'YE' and 'YS' instead). (see: `pandas PR/55252 <https://github.com/pandas-dev/pandas/pull/55252>`_). ('YE' is only supported for cftime data in `xarray >= 2024.1.1`).
* 'T' (minute), 'L' (millisecond), 'U' (microsecond), and 'N' (nanosecond) -> 'min', 'ms', 'us', and 'ns'. (see: `pandas PR/54061 <https://github.com/pandas-dev/pandas/pull/54061>`_).
* `bump2version` has been replaced with `bump-my-version` to bump the version number using configurations set in the ``pyproject.toml`` file. (:issue:`1557`, :pull:`1569`).
* `xclim`'s units registry and units formatting are now extended from `cf-xarray`. The exponent sign "^" is now never added in the ``units`` attribute. For example, square meters are given as "m2" instead of "m^2" by xclim, both are still accepted as input. (:issue:`1010`, :pull:`1590`).
* `xclim`'s units registry and units formatting are now extended from `cf-xarray`. The exponent sign "^" is now never added in the ``units`` attribute. For example, square meters are given as "m2" instead of "m^2" by `xclim`. Both signs are still accepted as inputs. (:issue:`1010`, :pull:`1590`).
* `yamale` is now listed as a core dependency (was previously listed in the `dev` installation recipe). (:issue:`1595`, :pull:`1596`).
* Due to a licensing limitation, the calculation of empirical orthogonal function based on `eofs` (``xclim.sdba.properties.first_eof``) has been removed from `xclim`. (:issue:`1620`, :pull:`1621`).
* `black` formatting style has been updated to the 2024 stable conventions. `isort` has been added to the `dev` installation recipe. (:pull:`1626`).
* The indice and indicator for ``winter_storm`` has been removed (deprecated since `xclim` v0.46.0 in favour of ``snd_storm_days``). (:pull:`1565`).
* `xclim` has dropped support for `scipy` version below v1.9.0 and `numpy` versions below v1.20.0. (:pull:`1565`).
* The indice and indicator for ``winter_storm`` has been removed (deprecated since `xclim>=0.46.0` in favour of ``snd_storm_days``). (:pull:`1565`).
* `xclim` has dropped support for `scipy` versions below v1.9.0 and `numpy` versions below v1.20.0. (:pull:`1565`).
* For generic function ``select_resample_op`` and ``core.units.to_agg_units``, operation "sum" will now return the same units as the input, and not implicitly be translated to an "integral". (:issue:`1645`, :pull:`1649`).
* `lmoments3` was removed as a dependency of `xclim` due to incompatible licensing (GPLv3 vs `xclim`'s Apache 2.0). Depending on the outcome of efforts to modify the licensing of `lmoments3`, this change may eventually be reverted. See `Ouranosinc/lmoments3#12 <https://github.com/Ouranosinc/lmoments3/issues/12>`_. See also the "frequency analysis" notebook for an example on how to continue using the probability weighted moments method for fitting distributions. (:issue:`1620`, :pull:`1644`).
* Argument `offset` is removed from ``xclim.indices.standardized_precipitation_evapotranspiration_index``. This will slightly change results when using SPEI with default values (:issue:`1477` :pull:`1653`).

Bug fixes
^^^^^^^^^
* Fixed passing ``missing=0`` to ``xclim.core.calendar.convert_calendar``. (:issue:`1562`, :pull:`1563`).
* Fix wrong `window` attributes in ``xclim.indices.standardized_precipitation_index``, ``xclim.indices.standardized_precipitation_evapotranspiration_index``. (:issue:`1552` :pull:`1554`).
* Fix the daily case `freq='D'` of ``xclim.stats.preprocess_standardized_index`` (:issue:`1602` :pull:`1607`).
* Fixed wrong `window` attributes in ``xclim.indices.standardized_precipitation_index``, ``xclim.indices.standardized_precipitation_evapotranspiration_index``. (:issue:`1552` :pull:`1554`).
* Fixed the daily case ``freq='D'`` for ``xclim.stats.preprocess_standardized_index`` (:issue:`1602` :pull:`1607`).
* Several spelling mistakes have been corrected within the documentation and codebase. (:pull:`1576`).
* Added missing ``xclim.ensembles.robustness_fractions`` and ``xclim.ensembles.robustness_categories`` in api doc section. (:pull:`1630`).
* Added missing ``xclim.ensembles.robustness_fractions`` and ``xclim.ensembles.robustness_categories`` in API doc section. (:pull:`1630`).
* Fixed an issue that can occur when fetching the testing data and running tests on Windows systems. Adapted a few existing tests for Windows support. (:pull:`1648`).

Internal changes
Expand All @@ -74,7 +85,8 @@ Internal changes
* `dev` formatting tools (`black`, `blackdoc`, `isort`) are now pinned to their `pre-commit` hook version equivalents in both ``pyproject.toml`` and ``tox.ini``. (:pull:`1626`).
* `black`, `isort`, and `pyupgrade` code formatters no longer target Python3.8 coding style conventions. (:pull:`1565`).
* The GitHub Workflows now include builds to run tests against both Windows and MacOS. (:pull:`1648`).
* `prefetch` is now available as a `tox` environment modifier in order to download the testing data before launching `pytest` (e.g. `py3x-prefetch`). This is . (:pull:`1648`).
* `prefetch` is now available as a `tox` environment modifier in order to download the testing data before launching `pytest` (e.g. `py3x-prefetch`). This is required for running tests the first time on Windows if the testing data has not already been installed. (:pull:`1648`).
* Removed `step-security/harden-runner` from the `finish` job as it does not work on container images lacking `sudo` access. (:pull:`1655`).

v0.47.0 (2023-12-01)
--------------------
Expand Down
2 changes: 2 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies:
- yamale
# Extras
- flox
- lmoments3 # Required for some Jupyter notebooks
# Testing and development dependencies
- black ==24.1.1
- blackdoc ==0.3.9
Expand All @@ -45,6 +46,7 @@ dependencies:
- isort ==5.13.2
- matplotlib
- mypy
- nbconvert <7.14 # Pinned due to directive errors in sphinx. See: https://github.com/jupyter/nbconvert/issues/2092
- nbqa
- nbsphinx
- nbval
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ dev = [
"ipython",
"isort ==5.13.2",
"mypy",
"nbconvert",
"nbconvert <7.14", # Pinned due to directive errors in sphinx. See: https://github.com/jupyter/nbconvert/issues/2092
"nbqa",
"nbval",
"netCDF4 >=1.4",
Expand Down Expand Up @@ -123,7 +123,7 @@ target-version = [
]

[tool.bumpversion]
current_version = "0.47.5-dev.20"
current_version = "0.48.1"
commit = true
commit_args = "--no-verify"
tag = false
Expand Down
41 changes: 41 additions & 0 deletions tests/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,47 @@ def test_season(self, q_series):
assert o[0] == 31 + 29


class TestSelectRollingResampleOp:
def test_rollingmax(self, q_series):
q = q_series(np.arange(1, 366 + 365 + 365 + 1)) # 1st year is leap
o = generic.select_rolling_resample_op(
q, "max", window=14, window_center=False, window_op="mean"
)
np.testing.assert_array_equal(
[
np.mean(np.arange(353, 366 + 1)),
np.mean(np.arange(353 + 365, 366 + 365 + 1)),
np.mean(np.arange(353 + 365 * 2, 366 + 365 * 2 + 1)),
],
o.values,
)
assert o.attrs["units"] == "m3 s-1"

def test_rollingmaxindexer(self, q_series):
q = q_series(np.arange(1, 366 + 365 + 365 + 1)) # 1st year is leap
o = generic.select_rolling_resample_op(
q, "min", window=14, window_center=False, window_op="max", season="DJF"
)
np.testing.assert_array_equal(
[14, 367, 367 + 365], o.values
) # 14th day for 1st year, then Jan 1st for the next two
assert o.attrs["units"] == "m3 s-1"

def test_freq(self, q_series):
q = q_series(np.arange(1, 366 + 365 + 365 + 1)) # 1st year is leap
o = generic.select_rolling_resample_op(
q, "max", window=3, window_center=True, window_op="integral", freq="MS"
)
np.testing.assert_array_equal(
[
np.sum([30, 31, 32]) * 86400,
np.sum([30 + 29, 31 + 29, 32 + 29]) * 86400,
], # m3 s-1 being summed by the frequency of the data
o.isel(time=slice(0, 2)).values,
)
assert o.attrs["units"] == "m3"


class TestThresholdCount:
def test_simple(self, tas_series):
ts = tas_series(np.arange(365))
Expand Down
26 changes: 26 additions & 0 deletions tests/test_sdba/test_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest
import xarray as xr

from xclim.core.calendar import date_range
from xclim.core.units import units
from xclim.sdba.adjustment import EmpiricalQuantileMapping
from xclim.sdba.base import Grouper
Expand Down Expand Up @@ -185,6 +186,31 @@ def test_reordering():
assert out.attrs == y.attrs


def test_reordering_with_window():
time = list(
date_range("2000-01-01", "2000-01-04", freq="D", calendar="noleap")
) + list(date_range("2001-01-01", "2001-01-04", freq="D", calendar="noleap"))

x = xr.DataArray(
np.arange(1, 9, 1),
dims=("time"),
coords={"time": time},
)

y = xr.DataArray(
np.arange(8, 0, -1),
dims=("time"),
coords={"time": time},
)

group = Grouper(group="time.dayofyear", window=3)
out = reordering(x, y, group=group)

np.testing.assert_array_equal(out, [3.0, 3.0, 2.0, 2.0, 7.0, 7.0, 6.0, 6.0])
out.attrs.pop("history")
assert out.attrs == y.attrs


def test_to_additive(pr_series, hurs_series):
# log
pr = pr_series(np.array([0, 1e-5, 1, np.e**10]))
Expand Down
2 changes: 1 addition & 1 deletion xclim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

__author__ = """Travis Logan"""
__email__ = "[email protected]"
__version__ = "0.47.5-dev.20"
__version__ = "0.48.1"


_module_data = _files("xclim.data")
Expand Down
46 changes: 46 additions & 0 deletions xclim/indices/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,52 @@ def select_resample_op(
return to_agg_units(out, da, op)


def select_rolling_resample_op(
da: xr.DataArray,
op: str,
window: int,
window_center: bool = True,
window_op: str = "mean",
freq: str = "YS",
out_units=None,
**indexer,
) -> xr.DataArray:
"""Apply operation over each period that is part of the index selection, using a rolling window before the operation.
Parameters
----------
da : xr.DataArray
Input data.
op : str {'min', 'max', 'mean', 'std', 'var', 'count', 'sum', 'integral', 'argmax', 'argmin'} or func
Reduce operation. Can either be a DataArray method or a function that can be applied to a DataArray.
window : int
Size of the rolling window (centered).
window_center : bool
If True, the window is centered on the date. If False, the window is right-aligned.
window_op : str {'min', 'max', 'mean', 'std', 'var', 'count', 'sum', 'integral'}
Operation to apply to the rolling window. Default: 'mean'.
freq : str
Resampling frequency defining the periods as defined in :ref:`timeseries.resampling`. Applied after the rolling window.
out_units : str, optional
Output units to assign. Only necessary if `op` is function not supported by :py:func:`xclim.core.units.to_agg_units`.
indexer : {dim: indexer, }, optional
Time attribute and values over which to subset the array. For example, use season='DJF' to select winter values,
month=1 to select January, or month=[6,7,8] to select summer months. If not indexer is given, all values are
considered.
Returns
-------
xr.DataArray
The array for which the operation has been applied over each period.
"""
rolled = getattr(
da.rolling(time=window, center=window_center),
window_op.replace("integral", "sum"),
)()
rolled = to_agg_units(rolled, da, window_op)
return select_resample_op(rolled, op=op, freq=freq, out_units=out_units, **indexer)


def doymax(da: xr.DataArray) -> xr.DataArray:
"""Return the day of year of the maximum value."""
i = da.argmax(dim="time")
Expand Down
Loading

0 comments on commit c2f020d

Please sign in to comment.