Skip to content

Commit

Permalink
Merge 5105df7 into 32a808d
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeitsperre committed Feb 21, 2024
2 parents 32a808d + 5105df7 commit 77fbf14
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 50 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- python-version: "3.9"
- python-version: "3.10"
- python-version: "3.11"
# - python-version: "3.12"
- python-version: "3.12"
defaults:
run:
shell: bash -l {0}
Expand All @@ -71,10 +71,11 @@ jobs:
create-args: >-
mamba
python=${{ matrix.python-version }}
- name: Downgrade intake-esm (for xscen)
- name: Downgrade intake-esm (for xscen) and xclim
if: matrix.python-version == '3.9'
run: |
micromamba install -y intake-esm=2023.11.10
micromamba install -y xclim=0.47.0
- name: Conda and Mamba versions
run: |
mamba --version
Expand Down
4 changes: 3 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Changelog
=========


v0.4.0 (unreleased)
-------------------
Contributors to this version: Trevor James Smith (:user:`Zeitsperre`), Thomas-Charles Fortier Filion (:user:`TC-FF`).
Expand All @@ -14,6 +13,8 @@ New features and enhancements
* `xhydro` is now configured to use `pooch` to download and cache testing datasets from `hydrologie/xhydro-testdata`. (:pull:`62`).
* `xhydro` is now `Semantic Versioning v2.0.0 <https://semver.org/spec/v2.0.0.html>`_ compliant. (:pull:`70`).
* Added new functions to `xhydro.frequency_analysis.local` to calculate plotting positions and to prepare plots. (:pull:`87`).
* `xscen` now supports Python3.12. (:pull:`99`).
* `xscen` now supports `pandas` >= 2.2.0, `xarray` >= 2023.11.0, and `xclim` >= 0.47.0. (:pull:`99`).

Breaking changes
^^^^^^^^^^^^^^^^
Expand All @@ -32,6 +33,7 @@ Internal changes
* Updated pre-commit hook versions to the latest available.
* Formatting tools are now pinned to their pre-commit equivalents.
* `actions-version-updater.yml` has been replaced by `dependabot <https://docs.github.com/en/code-security/dependabot/working-with-dependabot>`_.
* Added a few functions missing from the API to their respective modules via ``__all__``. (:pull:`99`).

v0.3.0 (2023-12-01)
-------------------
Expand Down
13 changes: 9 additions & 4 deletions environment-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: xhydro-dev
channels:
- conda-forge
dependencies:
- python >=3.9,<3.12
- python >=3.9,<3.13
# Don't forget to sync changes between environment.yml, environment-dev.yml, and pyproject.toml!
# Main packages
- numpy
Expand All @@ -11,7 +11,7 @@ dependencies:
- spotpy
- statsmodels
- xarray
- xclim >=0.47.0 # FIXME: Remove pin once our dependencies (xclim, xscen) support pandas 2.2.0
- xclim >=0.47.0
- xscen >=0.7.1
- pip
- pip:
Expand All @@ -20,7 +20,7 @@ dependencies:
- black ==24.1.1
- blackdoc ==0.3.9
- bump-my-version >=0.17.1
- coveralls >=3.3.1
# - coveralls >=3.3.1
- flake8 >=7.0.0
- furo
- ipykernel
Expand All @@ -33,7 +33,7 @@ dependencies:
- pooch
- pre-commit >=3.3.2
- pytest >=7.3.1
- pytest-cov >=4.0.0
# - pytest-cov >=4.0.0
- sphinx
- sphinx-autoapi
- sphinx-codeautolink
Expand All @@ -46,3 +46,8 @@ dependencies:
- flit
# Notebooks
- hvplot
- pip
- pip:
- coverage # Not available in conda-forge for Python3.12
- coveralls
- pytest-cov >=4.0.0
4 changes: 2 additions & 2 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: xhydro
channels:
- conda-forge
dependencies:
- python >=3.9,<3.12
- python >=3.9,<3.13
# Don't forget to sync changes between environment.yml, environment-dev.yml, and pyproject.toml!
# Main packages
- numpy
Expand All @@ -11,7 +11,7 @@ dependencies:
- spotpy
- statsmodels
- xarray
- xclim >=0.47.0 # FIXME: Remove pin once our dependencies (xclim, xscen) support pandas 2.2.0
- xclim >=0.47.0
- xscen >=0.7.1
- pip
- pip:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
# "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Scientific/Engineering :: GIS",
"Topic :: Scientific/Engineering :: Hydrology"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pytest

from xhydro.modelling.calibration import perform_calibration
from xhydro.modelling.hydrological_modelling import _dummy_model
from xhydro.modelling.hydrological_modelling import _dummy_model # noqa
from xhydro.modelling.obj_funcs import get_objective_function, transform_flows


Expand Down
20 changes: 16 additions & 4 deletions tests/test_indicators.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import numpy as np
import pytest
from packaging.version import parse
from xclim import __version__ as __xclim_version__
from xclim.testing.helpers import test_timeseries as timeseries

import xhydro as xh
Expand All @@ -25,10 +27,14 @@ def test_compute_volume(self, freq):
mult = 86400 if freq == "D" else 86400 * 365
np.testing.assert_array_equal(out, da * mult)
assert out.attrs["long_name"] == "Foo"
assert out.attrs["units"] == "m^3"
assert out.attrs["cell_methods"] == "time: sum"
assert out.attrs["description"] == "Volume of water"

if parse(__xclim_version__) < parse("0.48.0"):
assert out.attrs["units"] == "m^3"
else:
assert out.attrs["units"] == "m3"

def test_units(self):
da = timeseries(
np.tile(np.arange(1, 366), 3),
Expand All @@ -38,9 +44,15 @@ def test_units(self):
)

out_m3 = xh.indicators.compute_volume(da)
assert out_m3.attrs["units"] == "m^3"
out_hm3 = xh.indicators.compute_volume(da, out_units="hm3")
assert out_hm3.attrs["units"] == "hm^3"

if parse(__xclim_version__) < parse("0.48.0"):
assert out_m3.attrs["units"] == "m^3"
assert out_hm3.attrs["units"] == "hm^3"
else:
assert out_m3.attrs["units"] == "m3"
assert out_hm3.attrs["units"] == "hm3"

np.testing.assert_array_equal(out_m3 * 1e-6, out_hm3)


Expand Down Expand Up @@ -227,7 +239,7 @@ def test_errors(self):
op="max",
timeargs={"annual": {"season": ["DJF"], "doy_bounds": [200, 300]}},
)
with pytest.warns(UserWarning, match="The frequency is not AS-DEC"):
with pytest.warns(UserWarning, match="The frequency is not YS-DEC"):
xh.indicators.get_yearly_op(
self.ds, op="max", timeargs={"annual": {"season": ["DJF"]}}
)
Expand Down
63 changes: 38 additions & 25 deletions tests/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
from xclim.testing.helpers import test_timeseries as timeseries

import xhydro.frequency_analysis as xhfa
from xhydro.frequency_analysis.local import _get_plotting_positions, _prepare_plots
from xhydro.frequency_analysis.local import ( # noqa
_get_plotting_positions,
_prepare_plots,
)


class TestFit:
Expand All @@ -29,10 +32,12 @@ def test_fit(self):

np.testing.assert_array_almost_equal(
params.streamflow,
[
[9.95357815e00, np.nan, -3.07846650e01, 1.56498193e01],
[np.nan, -2.25674044e-05, 1.25012261e02, 4.74238877e01],
],
np.array(
[
[9.95357815e00, np.nan, -3.07846650e01, 1.56498193e01],
[np.nan, -2.25674044e-05, 1.25012261e02, 4.74238877e01],
]
),
)

def test_default(self):
Expand Down Expand Up @@ -73,9 +78,11 @@ def test_min_years(self, miny):
np.testing.assert_array_almost_equal(
params.streamflow,
(
[[9.95357815e00, -3.07846650e01, 1.56498193e01]]
if miny == 10
else [[np.nan, np.nan, np.nan]]
np.array(
[[9.95357815e00, -3.07846650e01, 1.56498193e01]]
if miny == 10
else [[np.nan, np.nan, np.nan]]
)
),
)

Expand Down Expand Up @@ -110,7 +117,7 @@ def test_quantiles(mode):
assert rp.streamflow.attrs["cell_methods"] == "dparams: ppf"
assert rp.streamflow.attrs["mode"] == mode

ans = (
ans = np.array(
[[190.66041057, 214.08102761], [185.78830382, 203.01731036]]
if mode == "max"
else [[66.00067153, 53.58658639], [64.23598869, 47.00660287]]
Expand Down Expand Up @@ -150,10 +157,12 @@ def test_criteria():

np.testing.assert_array_almost_equal(
crit.streamflow,
[
[118.19066549, 118.58856076, 118.63510993],
[118.12140939, 118.51930466, 118.56585383],
],
np.array(
[
[118.19066549, 118.58856076, 118.63510993],
[118.12140939, 118.51930466, 118.56585383],
]
),
)


Expand All @@ -166,7 +175,7 @@ def test_default(self):
freq="YS",
as_dataset=True,
)
expected = [1.16666667, 1.61538462, 2.625, 7.0]
expected = np.array([1.16666667, 1.61538462, 2.625, 7.0])
result = _get_plotting_positions(data)
np.testing.assert_array_almost_equal(result.streamflow_pp, expected)
np.testing.assert_array_almost_equal(result.streamflow, data.streamflow)
Expand All @@ -184,7 +193,7 @@ def test_nan(self):
freq="YS",
as_dataset=True,
)
expected = [1.23076923, np.nan, 2.0, 5.33333333]
expected = np.array([1.23076923, np.nan, 2.0, 5.33333333])
result = _get_plotting_positions(data)
np.testing.assert_array_almost_equal(result.streamflow_pp, expected)
np.testing.assert_array_almost_equal(result.streamflow, data.streamflow)
Expand All @@ -202,7 +211,7 @@ def test_return_period(self):
freq="YS",
as_dataset=True,
)
expected = [0.14285714, 0.38095238, 0.61904762, 0.85714286]
expected = np.array([0.14285714, 0.38095238, 0.61904762, 0.85714286])
result = _get_plotting_positions(data, return_period=False)
np.testing.assert_array_almost_equal(result.streamflow_pp, expected)
np.testing.assert_array_almost_equal(result.streamflow, data.streamflow)
Expand All @@ -220,7 +229,7 @@ def test_alpha_beta(self):
freq="YS",
as_dataset=True,
)
expected = [1.25, 1.66666667, 2.5, 5.0]
expected = np.array([1.25, 1.66666667, 2.5, 5.0])
result = _get_plotting_positions(data, alpha=0, beta=0)
np.testing.assert_array_almost_equal(result.streamflow_pp, expected)
np.testing.assert_array_almost_equal(result.streamflow, data.streamflow)
Expand All @@ -246,19 +255,23 @@ def test_prepare_plots_default(self):
assert result.streamflow.shape == (2, 100)
assert result.return_period.min() == 1
assert result.return_period.max() == 10000
expected = [
[-30.78466504, 63.64266447, 78.19229358, 88.62699148, 97.15369501],
[-np.inf, 61.08708903, 79.72126025, 92.05411647, 101.59650405],
]
expected = np.array(
[
[-30.78466504, 63.64266447, 78.19229358, 88.62699148, 97.15369501],
[-np.inf, 61.08708903, 79.72126025, 92.05411647, 101.59650405],
]
)
np.testing.assert_array_almost_equal(result.streamflow.head(), expected)

def test_prepare_plots_linear(self):
result = _prepare_plots(self.params, log=False)

expected = [
[-30.78466504, 262.72577254, 281.56238078, 292.27851004, 299.75980757],
[-np.inf, 235.6878466, 247.41104463, 253.8825982, 258.32114457],
]
expected = np.array(
[
[-30.78466504, 262.72577254, 281.56238078, 292.27851004, 299.75980757],
[-np.inf, 235.6878466, 247.41104463, 253.8825982, 258.32114457],
]
)
np.testing.assert_array_almost_equal(result.streamflow.head(), expected)

def test_prepare_plots_range(self):
Expand Down
14 changes: 12 additions & 2 deletions tests/test_testing_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from pathlib import Path

import pytest

import xhydro as xh
Expand All @@ -7,7 +9,11 @@
@pytest.mark.requires_docs
def test_publish_release_notes(tmp_path):
temp_md_filename = tmp_path.joinpath("version_info.md")
xhu.publish_release_notes(style="md", file=temp_md_filename)
xhu.publish_release_notes(
style="md",
file=temp_md_filename,
changes=Path(__file__).parent.parent.joinpath("CHANGES.rst"),
)

with open(temp_md_filename) as f:
changelog = f.read()
Expand All @@ -28,7 +34,11 @@ def test_publish_release_notes(tmp_path):
assert ":pull:`" not in changelog

temp_rst_filename = tmp_path.joinpath("version_info.rst")
xhu.publish_release_notes(style="rst", file=temp_rst_filename)
xhu.publish_release_notes(
style="rst",
file=temp_rst_filename,
changes=Path(__file__).parent.parent.joinpath("CHANGES.rst"),
)
with open(temp_rst_filename) as f:
changelog_rst = f.read()
assert changelog_rst.startswith("=========\nChangelog\n=========")
12 changes: 6 additions & 6 deletions xhydro/indicators.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ def get_yearly_op(
Dictionary of time arguments for the operation.
Keys are the name of the period that will be added to the results (e.g. "winter", "summer", "annual").
Values are up to two dictionaries, with both being optional.
The first is {'freq': str}, where str is a frequency supported by xarray (e.g. "YS", "AS-JAN", "AS-DEC").
It needs to be a yearly frequency. Defaults to "AS-JAN".
The first is {'freq': str}, where str is a frequency supported by xarray (e.g. "YS", "YS-JAN", "YS-DEC").
It needs to be a yearly frequency. Defaults to "YS-JAN".
The second is an indexer as supported by :py:func:`xclim.core.calendar.select_time`.
Defaults to {}, which means the whole year.
See :py:func:`xclim.core.calendar.select_time` for more information.
Examples: {"winter": {"freq": "AS-DEC", "date_bounds": ["12-01", "02-28"]}}, {"jan": {"freq": "YS", "month": 1}}, {"annual": {}}.
Examples: {"winter": {"freq": "YS-DEC", "date_bounds": ["12-01", "02-28"]}}, {"jan": {"freq": "YS", "month": 1}}, {"annual": {}}.
missing : str
How to handle missing values. One of "skip", "any", "at_least_n", "pct", "wmo".
See :py:func:`xclim.core.missing` for more information.
Expand Down Expand Up @@ -172,10 +172,10 @@ def get_yearly_op(
if (
"season" in indexer.keys()
and "DJF" in indexer["season"]
and freq != "AS-DEC"
and freq != "YS-DEC"
):
warnings.warn(
"The frequency is not AS-DEC, but the season indexer includes DJF. "
"The frequency is not YS-DEC, but the season indexer includes DJF. "
"This will lead to misleading results."
)
elif (
Expand Down Expand Up @@ -207,7 +207,7 @@ def get_yearly_op(
if freq == "YS" or (month_start != month_labels.index(freq.split("-")[1])):
warnings.warn(
f"The frequency is {freq}, but the bounds are between months {month_start} and {month_end}. "
f"You should use 'AS-{month_labels[month_start - 1]}' as the frequency."
f"You should use 'YS-{month_labels[month_start - 1]}' as the frequency."
)

identifier = f"{input_var}{window if window > 1 else ''}_{op}_{i.lower()}"
Expand Down
2 changes: 1 addition & 1 deletion xhydro/modelling/hydrological_modelling.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import pandas as pd
import xarray as xr

__all__ = ["run_hydrological_model"]
__all__ = ["get_hydrological_model_inputs", "run_hydrological_model"]


def run_hydrological_model(model_config: dict):
Expand Down
Loading

0 comments on commit 77fbf14

Please sign in to comment.