Skip to content

Commit

Permalink
Merge branch 'master' into faster_first_last_run
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeitsperre authored Nov 30, 2023
2 parents 6cde4a8 + a7165ab commit e305e34
Show file tree
Hide file tree
Showing 27 changed files with 307 additions and 280 deletions.
13 changes: 7 additions & 6 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,26 @@ Contributors to this version: Juliette Lavoie (:user:`juliettelavoie`), Pascal B

Announcements
^^^^^^^^^^^^^
* To circumvent issues stemming from changes to the frequency code convention in `pandas` v2.2, we have pinned `xarray` (<2023.11.0) and `pandas` (< 2.2) for this release. This change will be reverted in `xclim` v0.48.0 to support the newer versions (`xarray>= 2023.11.0` and `pandas>= 2.2`).
* To circumvent issues stemming from changes to the frequency code convention in `pandas` v2.2, we have pinned `xarray` (<2023.11.0) and `pandas` (< 2.2) for this release. This change will be reverted in `xclim` v0.48.0 to support the newer versions (`xarray >= 2023.11.0` and `pandas >= 2.2`).
* `xclim` v0.47.0 will be the last release supporting Python3.8.

New features and enhancements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* New functions ``xclim.ensembles.robustness_fractions`` and ``xclim.ensembles.robustness_categories``. The former will replace ``xclim.ensembles.change_significance`` which is now deprecated and will be removed in xclim 0.49 (:pull:`1514`).
* Add indicator ID to searched terms in the indicator search documentation page (:issue:`1525`, :pull:`1528`).
* New functions ``xclim.ensembles.robustness_fractions`` and ``xclim.ensembles.robustness_categories``. The former will replace ``xclim.ensembles.change_significance`` which is now deprecated and will be removed in xclim 0.49. (:pull:`1514`).
* Add indicator ID to searched terms in the indicator search documentation page. (:issue:`1525`, :pull:`1528`).

Bug fixes
^^^^^^^^^
* Fixed a bug with ``n_escore=-1`` in ``xclim.sdba.adjustment.NpdfTransform`` (:issue:`1515`, :pull:`1515`).
* In the documentaion, fix the tooltips in the indicator search results (:issue:`1524`, :pull:`1527`).
* If chunked inputs are passed to indicators ``mean_radiant_temperature`` and ``potential_evapotranspiration``, subcalculations of the solar angle will also use the same chunks, instead of a single one of the same size as the data (:issue:`1536`, :pull:`1542`).
* Fixed a bug with ``n_escore=-1`` in ``xclim.sdba.adjustment.NpdfTransform``. (:issue:`1515`, :pull:`1515`).
* In the documentation, fix the tooltips in the indicator search results. (:issue:`1524`, :pull:`1527`).
* If chunked inputs are passed to indicators ``mean_radiant_temperature`` and ``potential_evapotranspiration``, sub-calculations of the solar angle will also use the same chunks, instead of a single one of the same size as the data. (:issue:`1536`, :pull:`1542`).

Internal changes
^^^^^^^^^^^^^^^^
* Pinned `cf-xarray` below v0.8.5 in Python3.8 installation to further extend legacy support. (:pull:`1519`).
* `pip check` in conda builds in GitHub workflows have been temporarily set to always pass. (:pull:`1531`).
* Configure RtD search rankings to emphasize notebooks and indicators over indices and raw source code. (:pull:`1526`).
* Addressed around 100 very basic `mypy` typing errors and call signature errors. (:pull:`1532`).
* Use the intermediate step ``_cumsum_reset_on_zero`` instead of ``rle`` which is sufficient in ``_boundary_run``. (:issue:`1405`, :pull:`1530`).

v0.46.0 (2023-10-24)
Expand Down
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,16 @@ module = [
"clisops.core.subset.*",
"dask.*",
"lmoments3.*",
"matplotlib.*",
"numba.*",
"numpy.*",
"pandas.*",
"pint.*",
"SBCK.*",
"scipy.*",
"sklearn.cluster.*",
"xarray.*"
"xarray.*",
"yaml.*"
]
ignore_missing_imports = true

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.46.8-beta
current_version = 0.46.9-beta
commit = True
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+).(?P<patch>\d+)(\-(?P<release>[a-z]+))?
Expand Down
2 changes: 1 addition & 1 deletion xclim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

__author__ = """Travis Logan"""
__email__ = "logan.travis@ouranos.ca"
__version__ = "0.46.8-beta"
__version__ = "0.46.9-beta"


_module_data = _files("xclim.data")
Expand Down
14 changes: 7 additions & 7 deletions xclim/analog.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Code adapted from flyingpigeon.dissimilarity, Nov 2020.
from __future__ import annotations

from typing import Sequence
from typing import Any, Sequence

import numpy as np
import pandas as pd
Expand All @@ -16,7 +16,7 @@
from scipy import spatial
from scipy.spatial import cKDTree as KDTree

metrics = {}
metrics: dict[str, Any] = {}


def spatial_analogs(
Expand Down Expand Up @@ -61,7 +61,7 @@ def spatial_analogs(
raise RuntimeError(f"Spatial analogue method ({method}) requires scipy>=1.6.0.")

# Create the target DataArray:
target = target.to_array("_indices", "target")
target_array = target.to_array("_indices", "target")

# Create the target DataArray
# drop any (sub-)index along "dist_dim" that could conflict with target, and rename it.
Expand All @@ -86,13 +86,13 @@ def spatial_analogs(

if candidates.chunks is not None:
candidates = candidates.chunk({"_indices": -1})
if target.chunks is not None:
target = target.chunk({"_indices": -1})
if target_array.chunks is not None:
target_array = target_array.chunk({"_indices": -1})

# Compute dissimilarity
diss = xr.apply_ufunc(
metric_func,
target,
target_array,
candidates,
input_core_dims=[(dist_dim, "_indices"), ("_dist_dim", "_indices")],
output_core_dims=[()],
Expand All @@ -104,7 +104,7 @@ def spatial_analogs(
diss.name = "dissimilarity"
diss.attrs.update(
long_name=f"Dissimilarity between target and candidates, using metric {method}.",
indices=",".join(target._indices.values), # noqa
indices=",".join(target_array._indices.values), # noqa
metric=method,
)

Expand Down
150 changes: 73 additions & 77 deletions xclim/core/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1135,14 +1135,14 @@ def climatological_mean_doy(
Parameters
----------
arr : xarray.DataArray
Input array.
Input array.
window : int
Window size in days.
Window size in days.
Returns
-------
xarray.DataArray, xarray.DataArray
Mean and standard deviation.
Mean and standard deviation.
"""
rr = arr.rolling(min_periods=1, center=True, time=window).construct("window")

Expand All @@ -1163,11 +1163,11 @@ def within_bnds_doy(
Parameters
----------
arr : xarray.DataArray
Input array.
Input array.
low : xarray.DataArray
Low bound with dayofyear coordinate.
Low bound with dayofyear coordinate.
high : xarray.DataArray
High bound with dayofyear coordinate.
High bound with dayofyear coordinate.
Returns
-------
Expand All @@ -1185,20 +1185,20 @@ def _doy_days_since_doys(
Parameters
----------
base: xr.DataArray
1D time coordinate.
start: DayOfYearStr, optional
A date to compute the offset relative to. If note given, start_doy is the same as base_doy.
base : xr.DataArray
1D time coordinate.
start : DayOfYearStr, optional
A date to compute the offset relative to. If note given, start_doy is the same as base_doy.
Returns
-------
base_doy : xr.DataArray
Day of year for each element in base.
Day of year for each element in base.
start_doy : xr.DataArray
Day of year of the "start" date.
The year used is the one the start date would take as a doy for the corresponding base element.
Day of year of the "start" date.
The year used is the one the start date would take as a doy for the corresponding base element.
doy_max : xr.DataArray
Number of days (maximum doy) for the year of each value in base.
Number of days (maximum doy) for the year of each value in base.
"""
calendar = get_calendar(base)

Expand Down Expand Up @@ -1234,24 +1234,23 @@ def doy_to_days_since(
Parameters
----------
da: xr.DataArray
Array of "day-of-year", usually int dtype, must have a `time` dimension.
Sampling frequency should be finer or similar to yearly and coarser then daily.
start: date of year str, optional
A date in "MM-DD" format, the base day of the new array.
If None (default), the `time` axis is used.
Passing `start` only makes sense if `da` has a yearly sampling frequency.
calendar: str, optional
The calendar to use when computing the new interval.
If None (default), the calendar attribute of the data or of its `time` axis is used.
All time coordinates of `da` must exist in this calendar.
No check is done to ensure doy values exist in this calendar.
da : xr.DataArray
Array of "day-of-year", usually int dtype, must have a `time` dimension.
Sampling frequency should be finer or similar to yearly and coarser than daily.
start : date of year str, optional
A date in "MM-DD" format, the base day of the new array. If None (default), the `time` axis is used.
Passing `start` only makes sense if `da` has a yearly sampling frequency.
calendar : str, optional
The calendar to use when computing the new interval.
If None (default), the calendar attribute of the data or of its `time` axis is used.
All time coordinates of `da` must exist in this calendar.
No check is done to ensure doy values exist in this calendar.
Returns
-------
xr.DataArray
Same shape as `da`, int dtype, day-of-year data translated to a number of days since a given date.
If start is not None, there might be negative values.
Same shape as `da`, int dtype, day-of-year data translated to a number of days since a given date.
If start is not None, there might be negative values.
Notes
-----
Expand Down Expand Up @@ -1306,14 +1305,14 @@ def days_since_to_doy(
Parameters
----------
da: xr.DataArray
The result of :py:func:`doy_to_days_since`.
start: DateOfYearStr, optional
`da` is considered as days since that start date (in the year of the time index).
If None (default), it is read from the attributes.
calendar: str, optional
Calendar the "days since" were computed in.
If None (default), it is read from the attributes.
da : xr.DataArray
The result of :py:func:`doy_to_days_since`.
start : DateOfYearStr, optional
`da` is considered as days since that start date (in the year of the time index).
If None (default), it is read from the attributes.
calendar : str, optional
Calendar the "days since" were computed in.
If None (default), it is read from the attributes.
Returns
-------
Expand Down Expand Up @@ -1364,23 +1363,23 @@ def date_range_like(source: xr.DataArray, calendar: str) -> xr.DataArray:
Parameters
----------
source : xr.DataArray
1D datetime coordinate DataArray
1D datetime coordinate DataArray
calendar : str
New calendar name.
New calendar name.
Raises
------
ValueError
If the source's frequency was not found.
If the source's frequency was not found.
Returns
-------
xr.DataArray
1D datetime coordinate with the same start, end and frequency as the source, but in the new calendar.
The start date is assumed to exist in the target calendar.
If the end date doesn't exist, the code tries 1 and 2 calendar days before.
Exception when the source is in 360_day and the end of the range is the 30th of a 31-days month,
then the 31st is appended to the range.
1D datetime coordinate with the same start, end and frequency as the source, but in the new calendar.
The start date is assumed to exist in the target calendar.
If the end date doesn't exist, the code tries 1 and 2 calendar days before.
Exception when the source is in 360_day and the end of the range is the 30th of a 31-days month,
then the 31st is appended to the range.
"""
freq = xr.infer_freq(source)
if freq is None:
Expand Down Expand Up @@ -1428,20 +1427,20 @@ def _convert_datetime(
Parameters
----------
datetime: Union[datetime.datetime, cftime.datetime]
A datetime object to convert.
new_doy: Optional[Union[float, int]]
Allows for redefining the day of year (thus ignoring month and day information from the source datetime).
-1 is understood as a nan.
calendar: str
The target calendar
datetime: datetime.datetime or cftime.datetime
A datetime object to convert.
new_doy : float or int, optional
Allows for redefining the day of year (thus ignoring month and day information from the source datetime).
-1 is understood as a nan.
calendar : str
The target calendar
Returns
-------
Union[cftime.datetime, datetime.datetime, np.nan]
A datetime object of the target calendar with the same year, month, day and time
as the source (month and day according to `new_doy` if given).
If the month and day doesn't exist in the target calendar, returns np.nan. (Ex. 02-29 in "noleap")
A datetime object of the target calendar with the same year, month, day and time as the source
(month and day according to `new_doy` if given).
If the month and day doesn't exist in the target calendar, returns np.nan. (Ex. 02-29 in "noleap")
"""
if new_doy in [np.nan, -1]:
return np.nan
Expand Down Expand Up @@ -1470,10 +1469,10 @@ def _convert_datetime(
def select_time(
da: xr.DataArray | xr.Dataset,
drop: bool = False,
season: str | Sequence[str] = None,
month: int | Sequence[int] = None,
doy_bounds: tuple[int, int] = None,
date_bounds: tuple[str, str] = None,
season: str | Sequence[str] | None = None,
month: int | Sequence[int] | None = None,
doy_bounds: tuple[int, int] | None = None,
date_bounds: tuple[str, str] | None = None,
include_bounds: bool | tuple[bool, bool] = True,
) -> xr.DataArray | xr.Dataset:
"""Select entries according to a time period.
Expand All @@ -1486,25 +1485,22 @@ def select_time(
Parameters
----------
da : xr.DataArray or xr.Dataset
Input data.
drop: boolean
Whether to drop elements outside the period of interest or
to simply mask them (default).
season: string or sequence of strings
One or more of 'DJF', 'MAM', 'JJA' and 'SON'.
month: integer or sequence of integers
Sequence of month numbers (January = 1 ... December = 12)
doy_bounds: 2-tuple of integers
The bounds as (start, end) of the period of interest expressed in day-of-year,
integers going from 1 (January 1st) to 365 or 366 (December 31st). If calendar
awareness is needed, consider using ``date_bounds`` instead.
date_bounds: 2-tuple of strings
The bounds as (start, end) of the period of interest expressed as dates in the
month-day (%m-%d) format.
include_bounds: bool or 2-tuple of booleans
Whether the bounds of `doy_bounds` or `date_bounds` should be inclusive or not.
Either one value for both or a tuple.
Default is True, meaning bounds are inclusive.
Input data.
drop : bool
Whether to drop elements outside the period of interest or to simply mask them (default).
season : string or sequence of strings, optional
One or more of 'DJF', 'MAM', 'JJA' and 'SON'.
month : integer or sequence of integers, optional
Sequence of month numbers (January = 1 ... December = 12)
doy_bounds : 2-tuple of integers, optional
The bounds as (start, end) of the period of interest expressed in day-of-year, integers going from
1 (January 1st) to 365 or 366 (December 31st).
If calendar awareness is needed, consider using ``date_bounds`` instead.
date_bounds : 2-tuple of strings, optional
The bounds as (start, end) of the period of interest expressed as dates in the month-day (%m-%d) format.
include_bounds : bool or 2-tuple of booleans
Whether the bounds of `doy_bounds` or `date_bounds` should be inclusive or not.
Either one value for both or a tuple. Default is True, meaning bounds are inclusive.
Returns
-------
Expand Down
2 changes: 1 addition & 1 deletion xclim/core/cfchecks.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def check_valid(var, key: str, expected: str | Sequence[str]):
)


def cfcheck_from_name(varname, vardata, attrs: list[str] = None):
def cfcheck_from_name(varname, vardata, attrs: list[str] | None = None):
"""Perform cfchecks on a DataArray using specifications from xclim's default variables."""
if attrs is None:
attrs = ["cell_methods", "standard_name"]
Expand Down
4 changes: 2 additions & 2 deletions xclim/core/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,14 @@ def unprefix_attrs(source: dict, keys: Sequence, prefix: str):
}


def _gen_parameters_section(parameters: dict, allowed_periods: list[str] = None):
def _gen_parameters_section(parameters: dict, allowed_periods: list[str] | None = None):
"""Generate the "parameters" section of the indicator docstring.
Parameters
----------
parameters : dict
Parameters dictionary (`Ind.parameters`).
allowed_periods : List[str], optional
allowed_periods : list of str, optional
Restrict parameters to specific periods. Default: None.
"""
section = "Parameters\n----------\n"
Expand Down
Loading

0 comments on commit e305e34

Please sign in to comment.