Skip to content
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

add numpy 2 support #340

Merged
merged 36 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ba5b0d9
Try out numpy 2 beta release
MuellerSeb Mar 14, 2024
3ad422a
Remove py38; use np 2 rc
MuellerSeb Apr 4, 2024
8c52b9a
try running with np 2; remove 32bit wheels
MuellerSeb Apr 4, 2024
7e51f1e
cap black version
MuellerSeb Apr 4, 2024
9618c1c
project: sphinx version fix; black min py version fix
MuellerSeb Apr 5, 2024
4de1557
estimator: use int instead of long
MuellerSeb Apr 5, 2024
7971261
np: use asarray where possible with atleast_Xd to mimic ndmin feature
MuellerSeb Apr 5, 2024
3b35caa
cython: always use 64-bit integers for counts
MuellerSeb Apr 5, 2024
bcf22c0
deps: emcee try patch version
MuellerSeb Apr 5, 2024
f354999
re-enable py38; np2 to build extensions for py>=3.9; check np2 in CI
MuellerSeb Apr 6, 2024
e52cc9b
CI: check several versions of numpy
MuellerSeb Apr 7, 2024
70a59fb
Doc: fix pyvista issue with renaming UniformGrid->ImageData
MuellerSeb Apr 7, 2024
7b8aab3
Doc: use rtd theme >v2
MuellerSeb Apr 7, 2024
b3b4fb5
Doc: fix ref issues
MuellerSeb Apr 7, 2024
a13968e
CI: try fix missing pip step
MuellerSeb Apr 7, 2024
74b130a
CI: try fix missing pip step by separate job step
MuellerSeb Apr 7, 2024
5f37aee
CI: try fix missing pip step by using env var for version
MuellerSeb Apr 7, 2024
ea00a48
CI: try fix missing pip step by using oldest-supported-numpy package
MuellerSeb Apr 7, 2024
ebe8ef6
CI: fix missing pip step by using quotes (>= is evil)
MuellerSeb Apr 7, 2024
9074056
CI: install numpy in test stage to ensure version
MuellerSeb Apr 7, 2024
dacc89a
deps: bump min np ver to 1.20 (meshio needs np.typing)
MuellerSeb Apr 7, 2024
4353f6e
build: use build dep caps from scipy
MuellerSeb Apr 7, 2024
d221248
CI: also fix scipy version
MuellerSeb Apr 7, 2024
ba5bfb1
Doc: fix pyvista deprecation warnings
MuellerSeb Apr 7, 2024
552cb58
CI: fix config
MuellerSeb Apr 7, 2024
728adee
fix typo
MuellerSeb Apr 7, 2024
227efb6
update changelog
MuellerSeb Apr 8, 2024
83f8594
finalize pyproject.toml
MuellerSeb Apr 8, 2024
1124580
CI: install scipy/numpy before test to really check compatibility
MuellerSeb Apr 8, 2024
3bff873
update docs with correct deps versions
MuellerSeb Apr 8, 2024
24fd5ca
update actions versions
MuellerSeb Apr 11, 2024
9a754fa
cython: use np.int64_t
MuellerSeb Apr 12, 2024
7b1fd1e
use black 24 and add black preview job to CI
MuellerSeb Apr 12, 2024
062caa8
apply black 24
MuellerSeb Apr 12, 2024
50e6672
fix black preview complain
MuellerSeb Apr 12, 2024
25e002e
CI: emcee 3.1.5 with numpy 2 support was released
MuellerSeb Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 24 additions & 11 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ jobs:
matrix:
cfg:
- { os: ubuntu-latest, arch: x86_64 }
- { os: ubuntu-latest, arch: i686 }
- { os: windows-latest, arch: AMD64 }
- { os: windows-latest, arch: x86 }
- { os: macos-latest, arch: x86_64 }
- { os: macos-latest, arch: arm64 }
- { os: macos-latest, arch: universal2 }
Expand All @@ -71,7 +69,7 @@ jobs:
fetch-depth: '0'

- name: Build wheels
uses: pypa/cibuildwheel@v2.16.2
uses: pypa/cibuildwheel@v2.17.0
env:
CIBW_ARCHS: ${{ matrix.cfg.arch }}
with:
Expand All @@ -82,36 +80,51 @@ jobs:
path: ./dist/*.whl

build_sdist:
name: sdist on ${{ matrix.os }} with py ${{ matrix.python-version }}
name: sdist on ${{ matrix.os }} with py ${{ matrix.ver.py }} numpy${{ matrix.ver.np }} scipy${{ matrix.ver.sp }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

# https://github.com/scipy/oldest-supported-numpy/blob/main/setup.cfg
ver:
- {py: '3.8', np: '==1.20.0', sp: '==1.5.4'}
- {py: '3.9', np: '==1.20.0', sp: '==1.5.4'}
- {py: '3.10', np: '==1.21.6', sp: '==1.7.2'}
- {py: '3.11', np: '==1.23.2', sp: '==1.9.2'}
- {py: '3.12', np: '==1.26.2', sp: '==1.11.2'}
- {py: '3.12', np: '>=2.0.0rc1', sp: '>=1.13.0'}
Comment on lines -85 to +98
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awful! But I guess there is no other way until py 3.11 is deprecated?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly is awful? I think it is pretty neat to test multiple numpy/scipy versions to fix stuff like #246 faster in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a lot of manual (and typo prone?) work. Just imagine we have to add another few packages to that version matrix.

And it also makes it more work to locally reproduce specific setups of users.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a new Python version is release we have to add it by hand either way. And then I would just add the first version of numpy and scipy that support that new python version. That is how I selected the numpy and scipy versions for the python version together with a bleeding edge job for the latest versions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to keep it like this for now. If we encounter version incompatibilities in the future, we can rethink this.

steps:
- uses: actions/checkout@v2
with:
fetch-depth: '0'

- name: Set up Python ${{ matrix.python-version }}
- name: Set up Python ${{ matrix.ver.py }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ matrix.ver.py }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build "coveralls>=3.0.0"

- name: bleeding edge
if: matrix.ver.np == '>=2.0.0rc1'
run: |
python -m pip install git+https://github.com/dfm/emcee.git

- name: Install GSTools
env:
GSTOOLS_BUILD_PARALLEL: 1
run: |
python -m pip install --upgrade pip
pip install build coveralls>=3.0.0
pip install -v --editable .[test]

- name: Run tests
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
pip install "numpy${{ matrix.ver.np }}" "scipy${{ matrix.ver.sp }}"
python -m pytest --cov gstools --cov-report term-missing -v tests/
python -m coveralls --service=github

Expand All @@ -121,7 +134,7 @@ jobs:
python -m build --sdist --outdir dist .

- uses: actions/upload-artifact@v2
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9'
if: matrix.os == 'ubuntu-latest' && matrix.ver.py == '3.9'
with:
path: dist/*.tar.gz

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ src/gstools/_version.py
# generated docs
docs/source/examples/
docs/source/api/
docs/source/sg_execution_times.rst

# other settings
.vscode/
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

All notable changes to **GSTools** will be documented in this file.

## [Unreleased] - ?

### Enhancements

- added global variable `config.NUM_THREADS` to select number of threads for parallel computation ([#336](https://github.com/GeoStat-Framework/GSTools/pull/336))
- prepare numpy 2 support ([#340](https://github.com/GeoStat-Framework/GSTools/pull/340))
- numpy 2.0.0rc1 for building extensions (for Python 3.9 and above)
- check multiple numpy and scipy versions in CI
- fixed minimal versions for numpy
- use `np.asarray` everywhere with `np.atleast_(n)d`
- fix long/longlong integer issue in cython on windows by always using 64bit integers

### Bugfixes
- build docs with latest sphinx version ([#340](https://github.com/GeoStat-Framework/GSTools/pull/340))

### Changes
- require pyvista 0.40 at least ([#340](https://github.com/GeoStat-Framework/GSTools/pull/340))


## [1.5.1] - Nifty Neon - 2023-11

### Enhancements
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ in memory for immediate 3D plotting in Python.

## Requirements:

- [NumPy >= 1.14.5](https://www.numpy.org)
- [NumPy >= 1.20.0](https://www.numpy.org)
- [SciPy >= 1.1.0](https://www.scipy.org/scipylib)
- [hankel >= 1.0.0](https://github.com/steven-murray/hankel)
- [emcee >= 3.0.0](https://github.com/dfm/emcee)
Expand All @@ -366,7 +366,7 @@ You can contact us via <info@geostat-framework.org>.

## License

[LGPLv3][license_link] © 2018-2021
[LGPLv3][license_link] © 2018-2024

[pip_link]: https://pypi.org/project/gstools
[conda_link]: https://docs.conda.io/en/latest/miniconda.html
Expand Down
7 changes: 3 additions & 4 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,9 @@ def setup(app):
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
"Python": ("https://docs.python.org/", None),
"NumPy": ("http://docs.scipy.org/doc/numpy/", None),
"SciPy": ("http://docs.scipy.org/doc/scipy/reference", None),
"matplotlib": ("http://matplotlib.org", None),
"Sphinx": ("http://www.sphinx-doc.org/en/stable/", None),
"NumPy": ("https://numpy.org/doc/stable/", None),
"SciPy": ("https://docs.scipy.org/doc/scipy/", None),
"matplotlib": ("https://matplotlib.org/stable/", None),
"hankel": ("https://hankel.readthedocs.io/en/latest/", None),
"emcee": ("https://emcee.readthedocs.io/en/latest/", None),
}
Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ in memory for immediate 3D plotting in Python.
Requirements
============

- `Numpy >= 1.14.5 <http://www.numpy.org>`_
- `NumPy >= 1.20.0 <http://www.numpy.org>`_
- `SciPy >= 1.1.0 <http://www.scipy.org>`_
- `hankel >= 1.0.0 <https://github.com/steven-murray/hankel>`_
- `emcee >= 3.0.0 <https://github.com/dfm/emcee>`_
Expand Down
4 changes: 2 additions & 2 deletions examples/01_random_field/06_pyvista_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
# We create a structured grid with PyVista containing 50 segments on all three
# axes each with a length of 2 (whatever unit).

dim, spacing = (50, 50, 50), (2, 2, 2)
grid = pv.UniformGrid(dim, spacing)
dims, spacing = (50, 50, 50), (2, 2, 2)
grid = pv.ImageData(dimensions=dims, spacing=spacing)

###############################################################################
# Now we set up the SRF class as always. We'll use an anisotropic model.
Expand Down
2 changes: 1 addition & 1 deletion examples/04_vector_field/01_3d_vector_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
###############################################################################
# create a uniform grid with PyVista
dims, spacing, origin = (40, 30, 10), (1, 1, 1), (-10, 0, 0)
mesh = pv.UniformGrid(dims=dims, spacing=spacing, origin=origin)
mesh = pv.ImageData(dimensions=dims, spacing=spacing, origin=origin)

###############################################################################
# create an incompressible random 3d velocity field on the given mesh
Expand Down
21 changes: 10 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
requires = [
"setuptools>=64",
"setuptools_scm>=7",
"oldest-supported-numpy",
"Cython>=3.0",
"numpy>=2.0.0rc1,<2.3; python_version >= '3.9'",
"oldest-supported-numpy; python_version < '3.9'",
"Cython>=3.0.10,<3.1.0",
"extension-helpers>=1",
]
build-backend = "setuptools.build_meta"
Expand Down Expand Up @@ -48,7 +49,7 @@ dependencies = [
"emcee>=3.0.0",
"hankel>=1.0.0",
"meshio>=5.1.0",
"numpy>=1.14.5",
"numpy>=1.20.0",
"pyevtk>=1.1.1",
"scipy>=1.1.0",
]
Expand All @@ -60,20 +61,20 @@ doc = [
"meshzoo>=0.7",
"numpydoc>=1.1",
"pykrige>=1.5,<2",
"pyvista>=0.29",
"sphinx>=4",
"pyvista>=0.40",
"sphinx>=7",
"sphinx-gallery>=0.8",
"sphinx-rtd-theme>=1,<1.1",
"sphinx-rtd-theme>=2",
"sphinxcontrib-youtube>=1.1",
]
plotting = [
"matplotlib>=3",
"pyvista>=0.29",
"pyvista>=0.40",
]
rust = ["gstools_core>=0.2.0,<1"]
test = ["pytest-cov>=3"]
lint = [
"black",
"black>=23,<24",
MuellerSeb marked this conversation as resolved.
Show resolved Hide resolved
"pylint",
"isort[colors]",
"cython-lint",
Expand Down Expand Up @@ -161,11 +162,9 @@ target-version = [
# Switch to using build
build-frontend = "build"
# Disable building PyPy wheels on all platforms, 32bit for py3.10/11/12, musllinux builds, py3.6/7
skip = ["cp36-*", "cp37-*", "pp*", "cp31*-win32", "cp31*-manylinux_i686", "*-musllinux_*"]
skip = ["cp36-*", "cp37-*", "pp*", "*-win32", "*-manylinux_i686", "*-musllinux_*"]
# Run the package tests using `pytest`
test-extras = "test"
test-command = "pytest -v {package}/tests"
# Skip trying to test arm64 builds on Intel Macs
test-skip = "*-macosx_arm64 *-macosx_universal2:arm64"
# no wheels for linux-32bit anymore for numpy>=1.22
environment = "PIP_PREFER_BINARY=1"
2 changes: 1 addition & 1 deletion src/gstools/field/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def transform(
----------
method : :class:`str`
Method to use.
See :any:`gstools.transform` for available transformations.
See :py:mod:`gstools.transform` for available transformations.
field : :class:`str`, optional
Name of field to be transformed. The default is "field".
store : :class:`str` or :class:`bool`, optional
Expand Down
4 changes: 1 addition & 3 deletions src/gstools/krige/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,9 +383,7 @@ def _pre_ext_drift(self, pnt_cnt, ext_drift=None, set_cond=False):
the drift values at the given positions
"""
if ext_drift is not None:
ext_drift = np.array(
ext_drift, dtype=np.double, ndmin=2, copy=False
)
ext_drift = np.atleast_2d(np.asarray(ext_drift, dtype=np.double))
if ext_drift.size == 0: # treat empty array as no ext_drift
return np.array([])
if set_cond:
Expand Down
6 changes: 3 additions & 3 deletions src/gstools/tools/geometric.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def generate_st_grid(pos, time, mesh_type="unstructured"):
if mesh_type != "unstructured":
pos = generate_grid(pos)
else:
pos = np.array(pos, dtype=np.double, ndmin=2, copy=False)
pos = np.atleast_2d(np.asarray(pos, dtype=np.double))
out = [np.repeat(p.reshape(-1), np.size(time)) for p in pos]
out.append(np.tile(time, np.size(pos[0])))
return np.asarray(out, dtype=np.double)
Expand Down Expand Up @@ -552,7 +552,7 @@ def format_unstruct_pos_shape(pos, shape, check_stacked_shape=False):
# now we try to be smart
pre_len = len(np.atleast_1d(pos))
# care about 1D: pos can be given as 1D array here -> convert to 2D array
pos = np.array(pos, dtype=np.double, ndmin=2, copy=False)
pos = np.atleast_2d(np.asarray(pos, dtype=np.double))
post_len = len(pos)
# first array dimension should be spatial dimension (1D is special case)
dim = post_len if pre_len == post_len else 1
Expand Down Expand Up @@ -606,7 +606,7 @@ def ang2dir(angles, dtype=np.double, dim=None):
the array of direction vectors
"""
pre_dim = np.asanyarray(angles).ndim
angles = np.array(angles, ndmin=2, dtype=dtype, copy=False)
angles = np.atleast_2d(np.asarray(angles, dtype=dtype))
if len(angles.shape) > 2:
raise ValueError(f"Can't interpret angles array {angles}")
dim = angles.shape[1] + 1 if dim is None else dim
Expand Down
2 changes: 1 addition & 1 deletion src/gstools/transform/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def apply(fld, method, field="field", store=True, process=False, **kwargs):
Field class containing a generated field.
method : :class:`str`
Method to use.
See :any:`gstools.transform` for available transformations.
See :py:mod:`gstools.transform` for available transformations.
field : :class:`str`, optional
Name of field to be transformed. The default is "field".
store : :class:`str` or :class:`bool`, optional
Expand Down
23 changes: 12 additions & 11 deletions src/gstools/variogram/estimator.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ IF OPENMP:

cimport numpy as np
from libc.math cimport M_PI, acos, atan2, cos, fabs, isnan, pow, sin, sqrt
from libc.stdint cimport int64_t


def set_num_threads(num_threads):
Expand Down Expand Up @@ -116,7 +117,7 @@ ctypedef double (*_estimator_func)(const double) nogil

cdef inline void normalization_matheron(
double[:] variogram,
long[:] counts,
int64_t[:] counts,
):
cdef int i
for i in range(variogram.shape[0]):
Expand All @@ -125,10 +126,10 @@ cdef inline void normalization_matheron(

cdef inline void normalization_cressie(
double[:] variogram,
long[:] counts,
int64_t[:] counts,
):
cdef int i
cdef long cnt
cdef int64_t cnt
for i in range(variogram.shape[0]):
# avoid division by zero
cnt = max(counts[i], 1)
Expand All @@ -139,28 +140,28 @@ cdef inline void normalization_cressie(

ctypedef void (*_normalization_func)(
double[:],
long[:],
int64_t[:],
)

cdef inline void normalization_matheron_vec(
double[:, :] variogram,
long[:, :] counts,
int64_t[:, :] counts,
):
cdef int d
for d in range(variogram.shape[0]):
normalization_matheron(variogram[d, :], counts[d, :])

cdef inline void normalization_cressie_vec(
double[:, :] variogram,
long[:, :] counts,
int64_t[:, :] counts,
):
cdef int d
for d in range(variogram.shape[0]):
normalization_cressie(variogram[d, :], counts[d, :])

ctypedef void (*_normalization_func_vec)(
double[:, :],
long[:, :],
int64_t[:, :],
)

cdef _estimator_func choose_estimator_func(str estimator_type):
Expand Down Expand Up @@ -221,7 +222,7 @@ def directional(
cdef int f_max = f.shape[0]

cdef double[:, :] variogram = np.zeros((d_max, len(bin_edges)-1))
cdef long[:, :] counts = np.zeros((d_max, len(bin_edges)-1), dtype=long)
cdef int64_t[:, :] counts = np.zeros((d_max, len(bin_edges)-1), dtype=np.int64)
cdef int i, j, k, m, d
cdef double dist

Expand Down Expand Up @@ -287,7 +288,7 @@ def unstructured(
cdef int f_max = f.shape[0]

cdef double[:] variogram = np.zeros(len(bin_edges)-1)
cdef long[:] counts = np.zeros(len(bin_edges)-1, dtype=long)
cdef int64_t[:] counts = np.zeros(len(bin_edges)-1, dtype=np.int64)
cdef int i, j, k, m
cdef double dist

Expand Down Expand Up @@ -324,7 +325,7 @@ def structured(
cdef int k_max = i_max + 1

cdef double[:] variogram = np.zeros(k_max)
cdef long[:] counts = np.zeros(k_max, dtype=long)
cdef int64_t[:] counts = np.zeros(k_max, dtype=np.int64)
cdef int i, j, k

cdef int num_threads_c = set_num_threads(num_threads)
Expand Down Expand Up @@ -356,7 +357,7 @@ def ma_structured(
cdef int k_max = i_max + 1

cdef double[:] variogram = np.zeros(k_max)
cdef long[:] counts = np.zeros(k_max, dtype=long)
cdef int64_t[:] counts = np.zeros(k_max, dtype=np.int64)
MuellerSeb marked this conversation as resolved.
Show resolved Hide resolved
cdef int i, j, k

cdef int num_threads_c = set_num_threads(num_threads)
Expand Down