Skip to content

Changes for Python 3.13 support #569

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
test:
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.10', '3.11', '3.12', '3.13']

runs-on: ubuntu-latest

Expand Down
89 changes: 79 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ exclude = '''

[tool.poetry]
name = 'climate_indices'
version = '2.0.1'
version = '2.0.2'
description = 'Reference implementations of various climate indices typically used for drought monitoring'
authors = ['James Adams <[email protected]>']
readme = 'README.md'
Expand All @@ -33,27 +33,27 @@ classifiers = [
'Intended Audience :: Education',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Scientific/Engineering :: Atmospheric Science',
'Topic :: Scientific/Engineering :: Physics'
'Topic :: Scientific/Engineering :: Climate Science',
]
packages = [{include = 'climate_indices', from = 'src'}]

[tool.poetry.dependencies]
# only Python and scipy are required for the base library code
python = '>=3.8,<3.12'
scipy = '1.10.1'
python = '>=3.10,<3.14'
scipy = '>=1.14.1'
# remaining dependencies are required for the CLI (console) scripts
cftime = '>=1.6.4'
dask = '>=2023.5.0'
h5netcdf = '>=1.1.0'
xarray = '>=2023.1.0'
dask = '>=2024.12.0'
h5netcdf = '>=1.4.0'
xarray = '>=2024.11.0'

[tool.poetry.dev-dependencies]
coverage = '^7.6.9'
pytest = '8.3.3'
toml = '>=0.10.2'

Expand All @@ -68,3 +68,72 @@ spi = 'climate_indices.__spi__:main'
filterwarnings = [
'ignore::FutureWarning',
]

## ========================== below for conversion to uv instead of poetry ==========================
#[project]
# authors = [
# {name = "James Adams", email = "[email protected]"},
# ]
# requires-python = ">=3.10,<3.14"
# dependencies = [
# "scipy>=1.14.1",
# "cftime",
# "dask",
# "h5py",
# "xarray",
# ]
# name = "climate_indices"
# version = "2.0.2"
# description = "Reference implementations of various climate indices typically used for drought monitoring"
# readme = "README.md"
# classifiers = [
# "Development Status :: 5 - Production/Stable",
# "Intended Audience :: Developers",
# "Intended Audience :: Education",
# "Intended Audience :: Science/Research",
# "License :: OSI Approved :: BSD License",
# "Programming Language :: Python :: 3.10",
# "Programming Language :: Python :: 3.11",
# "Programming Language :: Python :: 3.12",
# "Programming Language :: Python :: 3.13",
# "Topic :: Software Development :: Libraries :: Python Modules",
# "Topic :: Scientific/Engineering :: Climate Science",
# ]
#
#[dependency-groups]
# dev = [
# "sphinx-autodoc-typehints==2.0.1",
# "pytest==8.3.3",
# "toml>=0.10.2",
# ]
#
#[project.urls]
# 'Homepage' = 'https://github.com/monocongo/climate_indices'
# 'Bug Tracker' = 'https://github.com/monocongo/climate_indices/issues'
#
#[project.scripts]
# process_climate_indices = "climate_indices.__main__:main"
# spi = "climate_indices.__spi__:main"
#
#[tool.black]
#line-length = 120
#target-version = ['py39', 'py310', 'py311', 'py312', 'py313']
#include = '\.pyi?$'
#exclude = '''
#/(
# \.git
# | \.mypy_cache
# | \.tox
# | \.venv
# | build
# | dist
#)/
#'''
#
#[tool.pytest.ini_options]
#filterwarnings = [
# 'ignore::FutureWarning',
#]
#
#[tool.pdm.build]
#includes = ["src/climate_indices"]
33 changes: 5 additions & 28 deletions src/climate_indices/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Common classes and functions used to compute the various climate indices.
"""
from enum import Enum
from distutils.version import LooseVersion
import logging
from typing import Tuple

Expand All @@ -21,9 +20,6 @@
"transform_fitted_pearson",
]

# depending on the version of scipy we may need to use a workaround due to a bug in some versions of scipy
_do_pearson3_workaround = LooseVersion(scipy.version.version) < "1.6.0"

# Retrieve logger and set desired logging level
_logger = utils.get_logger(__name__, logging.WARN)

Expand Down Expand Up @@ -501,30 +497,11 @@ def _pearson_fit(
values[zero_mask] = 0.0
values[trace_mask] = 0.0005

if _do_pearson3_workaround:
# Before scipy 1.6.0, there were a few bugs in pearson3.
# Looks like https://github.com/scipy/scipy/pull/12640 fixed them.

# compute the minimum value possible, and if any values are below
# that threshold then we set the corresponding CDF to a floor value.
# This was not properly done in older scipy releases.
# TODO ask Richard Heim why the use of this floor value, matching
# that used for the trace amount?
nans_mask = np.isnan(values)
values[np.logical_and(minimums_mask, nans_mask)] = 0.0005
# This will get turned into 0.9995 when the negative
# skew bug is worked around a few lines from here.
values[np.logical_and(maximums_mask, nans_mask)] = 0.0005

# account for negative skew
skew_mask = skew < 0.0
values[:, skew_mask] = 1 - values[:, skew_mask]
else:
# The original values were found to be outside the
# range of the fitted distribution, so we will set
# the probabilities to something just within the range.
values[minimums_mask] = 0.0005
values[maximums_mask] = 0.9995
# The original values were found to be outside the
# range of the fitted distribution, so we will set
# the probabilities to something just within the range.
values[minimums_mask] = 0.0005
values[maximums_mask] = 0.9995

if not np.all(np.isnan(values)):
# calculate the probability value, clipped between 0 and 1
Expand Down
Loading