Skip to content

Commit

Permalink
Merge branch 'dev' into R_benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
martinvonk committed Mar 7, 2024
2 parents 950b4c5 + 0d32a15 commit 7c40a33
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 42 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
Expand Down
13 changes: 4 additions & 9 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ jobs:
fail-fast: false
matrix:
include:
- name: Test suite with py38-ubuntu
python: "3.8"
os: ubuntu-latest
toxenv: py38
experimental: false
- name: Test suite with py39-ubuntu
python: "3.9"
os: ubuntu-latest
Expand All @@ -33,10 +28,10 @@ jobs:
toxenv: py311
experimental: false
- name: Test suite with py312-ubuntu
python: "3.12-dev"
python: "3.12"
os: ubuntu-latest
toxenv: py312
experimental: true
experimental: false
- name: Type check with mypy
python: "3.9"
os: ubuntu-latest
Expand Down Expand Up @@ -72,10 +67,10 @@ jobs:
# Pytest
PYTEST_ADDOPTS: "--color=yes"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
check-latest: true
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ To get the development version download or clone the GitHub repository to your l

## Literature

1. B. Lloyd-Hughes and M.A. Saunders (2002) - A Drought Climatology for Europe. DOI: 10.1002/joc.846
2. S.M. Vicente-Serrano, S. Beguería and J.I. López-Moreno (2010) - A Multi-scalar drought index sensitive to global warming: The Standardized Precipitation Evapotranspiration Index. DOI: 10.1175/2009JCLI2909.1
3. J.P.Bloomfield and B.P. Marchant, B. P. (2013) - Analysis of groundwater drought building on the standardised precipitation index approach. DOI: 10.5194/hess-17-4769-2013
4. A. Babre, A. Kalvāns, Z. Avotniece, I. Retiķe, J. Bikše, K.P.M. Jemeljanova, A. Zelenkevičs and A. Dēliņa (2022) - The use of predefined drought indices for the assessment of groundwater drought episodes in the Baltic States over the period 1989–2018. DOI: 10.1016/j.ejrh.2022.101049
5. E. Tijdeman, K. Stahl and L.M. Tallaksen (2020) - Drought characteristics derived based on the Standardized Streamflow Index: A large sample comparison for parametric and nonparametric methods. DOI: 10.1029/2019WR026315
1. B. Lloyd-Hughes and M.A. Saunders (2002) - A Drought Climatology for Europe. DOI: 10.1002/joc.846
2. S.M. Vicente-Serrano, S. Beguería and J.I. López-Moreno (2010) - A Multi-scalar drought index sensitive to global warming: The Standardized Precipitation Evapotranspiration Index. DOI: 10.1175/2009JCLI2909.1
3. J.P. Bloomfield and B.P. Marchant, B. P. (2013) - Analysis of groundwater drought building on the standardised precipitation index approach. DOI: 10.5194/hess-17-4769-2013
4. A. Babre, A. Kalvāns, Z. Avotniece, I. Retiķe, J. Bikše, K.P.M. Jemeljanova, A. Zelenkevičs and A. Dēliņa (2022) - The use of predefined drought indices for the assessment of groundwater drought episodes in the Baltic States over the period 1989–2018. DOI: 10.1016/j.ejrh.2022.101049
5. E. Tijdeman, K. Stahl and L.M. Tallaksen (2020) - Drought characteristics derived based on the Standardized Streamflow Index: A large sample comparison for parametric and nonparametric methods. DOI: 10.1029/2019WR026315

Note that the method for calculating the drought indices does not come from these articles and SciPy is used for deriving the distribution. However the literature is helpful as a reference to understand the context and application of drought indices.

Expand Down
Binary file removed doc/_static/logo.png
Binary file not shown.
Binary file removed doc/_static/logo.pptx
Binary file not shown.
10 changes: 0 additions & 10 deletions doc/_static/make_logo.py

This file was deleted.

4 changes: 3 additions & 1 deletion doc/examples/example04_package_comparison.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@
"source": [
"# get rolling sum\n",
"prec_rsum = prec.rolling(\"30D\", min_periods=30).sum().dropna()\n",
"prec_rsum.plot(grid=True, linewidth=0.5, title=\"Precipitation, 30day rolling sum\", figsize=(6.5, 4));"
"prec_rsum.plot(\n",
" grid=True, linewidth=0.5, title=\"Precipitation, 30day rolling sum\", figsize=(6.5, 4)\n",
");"
]
},
{
Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ authors = [{ name = "Martin Vonk", email = "[email protected]" }]
description = "A simple Python package to calculate drought indices for time series such as the SPI, SPEI and SGI."
readme = "README.md"
license = { file = "LICENSE" }
requires-python = ">=3.8"
requires-python = ">=3.9"
dependencies = ["numpy", "scipy", "matplotlib", "pandas"]
classifiers = [
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
Expand Down Expand Up @@ -63,7 +62,7 @@ line-length = 88
legacy_tox_ini = """
[tox]
requires = tox>=4
env_list = format, type, lint, py38, py39, py310, py311, py312
env_list = format, type, lint, py39, py310, py311, py312
[testenv]
description = run unit tests
Expand Down
18 changes: 9 additions & 9 deletions src/spei/climdex.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def sdii(series: Series, threshold: float = 1.0, period: str = "30D") -> Series:
return series.loc[w].resample(period).sum() / w.sum()


def rnmm(series: Series, threshold: float, period: str = "1Y") -> Series:
def rnmm(series: Series, threshold: float, period: str = "1YE") -> Series:
"""Annual count of days when precipitation ≥ n mm. n is a user-defined threshold"""
series = validate_series(series)
_ = validate_index(series.index)
Expand All @@ -43,12 +43,12 @@ def rnmm(series: Series, threshold: float, period: str = "1Y") -> Series:
return w.resample(period).sum()


def r10mm(series: Series, threshold: float = 10.0, period: str = "1Y") -> Series:
def r10mm(series: Series, threshold: float = 10.0, period: str = "1YE") -> Series:
"""Annual count of days when precipitation ≥ 10 mm"""
return rnmm(series=series, threshold=threshold, period=period)


def r20mm(series: Series, threshold: float = 20.0, period: str = "1Y") -> Series:
def r20mm(series: Series, threshold: float = 20.0, period: str = "1YE") -> Series:
"""Annual count of days when precipitation ≥ 20 mm"""
return rnmm(series=series, threshold=threshold, period=period)

Expand All @@ -75,7 +75,7 @@ def cwd(series: Series, threshold: float = 1.0, period: str = "365D") -> Series:
return w.diff().rolling(period).sum().dropna().astype(int)


def prcptot(series: Series, period: str = "1Y") -> Series:
def prcptot(series: Series, period: str = "1YE") -> Series:
"""Total precipitation on wet days over a certain period"""
series = validate_series(series)
_ = validate_index(series.index)
Expand All @@ -84,7 +84,7 @@ def prcptot(series: Series, period: str = "1Y") -> Series:


def rnnp(
series: Series, quantile: float, threshold: float = 1.0, period: str = "1Y"
series: Series, quantile: float, threshold: float = 1.0, period: str = "1YE"
) -> Series:
"""Total amount of precipitation on wet days above certain quantile"""
series = validate_series(series)
Expand All @@ -97,21 +97,21 @@ def rnnp(


def r95p(
series: Series, quantile: float = 0.95, threshold: float = 1.0, period: str = "1Y"
series: Series, quantile: float = 0.95, threshold: float = 1.0, period: str = "1YE"
) -> Series:
"""Total amount of precipitation on very wet days"""
return rnnp(series=series, quantile=quantile, threshold=threshold, period=period)


def r99p(
series: Series, quantile: float = 0.99, threshold: float = 1.0, period: str = "1Y"
series: Series, quantile: float = 0.99, threshold: float = 1.0, period: str = "1YE"
) -> Series:
"""Total amount of precipitation on extremely wet days"""
return rnnp(series=series, quantile=quantile, threshold=threshold, period=period)


def r95ptot(
series: Series, quantile: float = 0.95, threshold: float = 1.0, period: str = "1Y"
series: Series, quantile: float = 0.95, threshold: float = 1.0, period: str = "1YE"
) -> Series:
"""Contribution to total precipitation from very wet days"""
r95 = r95p(series=series, quantile=quantile, threshold=threshold, period=period)
Expand All @@ -120,7 +120,7 @@ def r95ptot(


def r99ptot(
series: Series, quantile: float = 0.99, threshold: float = 1.0, period: str = "1Y"
series: Series, quantile: float = 0.99, threshold: float = 1.0, period: str = "1YE"
) -> Series:
"""Contribution to total precipitation from extremely wet days"""
r99 = r99p(series=series, quantile=quantile, threshold=threshold, period=period)
Expand Down
9 changes: 9 additions & 0 deletions src/spei/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ def validate_index(index: Index) -> DatetimeIndex:
)
index = DatetimeIndex(to_datetime(index))

if index.has_duplicates:
msg = (
"Duplicated indices found. Please remove them. For instance by"
" using `series = "
"series.loc[~series.index.duplicated(keep='first/last')]`"
)
logging.error(msg)
raise ValueError(msg)

return index


Expand Down
20 changes: 17 additions & 3 deletions tests/test_validate.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import logging

import pytest
from pandas import DataFrame, Series, to_datetime
from pandas import DataFrame, DatetimeIndex, Series, Timestamp, to_datetime

from spei.utils import validate_index, validate_series


def test_validate_index(caplog) -> None:
caplog.set_level(logging.INFO)
series = Series([1, 2, 3], index=["2018", "2019", "2020"])
series = Series([1.0, 2.0, 3.0], index=["2018", "2019", "2020"])
validate_index(series.index)
msg = (
f"Expected the index to be a DatetimeIndex. Automatically converted "
f"{type(series.index)} using pd.to_datetime(Index)\n"
)
print(f"{caplog.text=}")
assert msg in caplog.text


def test_validate_index_duplicated(caplog) -> None:
caplog.set_level(logging.ERROR)
series = Series(
[1.0, 1.0],
index=DatetimeIndex([Timestamp("2000-01-01"), Timestamp("2000-01-01")]),
)
with pytest.raises(ValueError):
validate_index(series.index)
msg = (
"Duplicated indices found. Please remove them. For instance by using"
"`series = series.loc[~series.index.duplicated(keep='first/last')]`"
)
assert msg in caplog.text


def test_validate_series() -> None:
with pytest.raises(TypeError):
validate_series([1, 2, 3])
Expand Down

0 comments on commit 7c40a33

Please sign in to comment.