Skip to content

Commit

Permalink
fix: numpy2 C api (#38)
Browse files Browse the repository at this point in the history
* fix: numpy2 C api
* test: add numpy<2 and >=2 tests
  • Loading branch information
glichtner authored Oct 2, 2024
1 parent 7f8b5a8 commit 89df317
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 38 deletions.
40 changes: 31 additions & 9 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,53 @@ on:
- main
pull_request:


jobs:
test:
name: test ${{ matrix.python-version }} - ${{ matrix.os }}
name: test py==${{ matrix.python-version }} - numpy==${{ matrix.numpy-version }} - ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
fail-fast: true
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
exclude:
- os: macos-latest
python-version: "3.7"
python-version: ["3.9", "3.10", "3.11", "3.12"]
numpy-version: ["1.26", "2.0"]
include:

- python-version: "3.7"
os: windows-latest
numpy-version: "1.21"

- python-version: "3.7"
os: ubuntu-latest
numpy-version: "1.21"

- python-version: "3.8"
os: windows-latest
numpy-version: "1.24"

- python-version: "3.8"
os: macos-latest
numpy-version: "1.24"

- python-version: "3.8"
os: ubuntu-latest
numpy-version: "1.24"

steps:
- uses: actions/checkout@v4

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

- name: Install tox and dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade pip setuptools wheel
pip install tox
- name: Test with tox
- name: Run tests with numpy ${{ matrix.numpy-version }}
env:
NUMPY_VERSION: ${{ matrix.numpy-version }} # Pass numpy version to tox
run: |
tox -e py
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools", "wheel", "numpy<2.0"]
requires = ["setuptools", "wheel", "numpy"]
build-backend = "setuptools.build_meta"


Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-

import os
from setuptools import setup, Extension, find_packages

from setuptools import Extension, find_packages, setup

__version__ = "" # placeholder for linters
exec(open("pystackreg/version.py").read())
Expand Down Expand Up @@ -53,7 +54,7 @@ def __str__(self):
)
],
setup_requires=["numpy"],
install_requires=["numpy<2", "tqdm"],
install_requires=["numpy", "tqdm"],
classifiers=[
# complete list: http://pypi.python.org/pypi?%3Aaction=list_classifiers
"Development Status :: 5 - Production/Stable",
Expand Down
43 changes: 30 additions & 13 deletions src/pymain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Author: Gregor Lichtner
*/

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <Python.h>
#include <numpy/arrayobject.h>

Expand All @@ -31,7 +32,7 @@ typedef struct regMat {
} regMat;

static PyObject *turbogreg_register(PyObject *self, PyObject *args);
static PyObject *turbogreg_transform(PyObject *self, PyObject *args);
static PyArrayObject *turbogreg_transform(PyObject *self, PyObject *args);

static char pystackreg_docs[] = "PyStackReg\n";
static PyMethodDef module_methods[] = {
Expand Down Expand Up @@ -147,8 +148,16 @@ PyObject *turbogreg_register(PyObject *self, PyObject *args) {
}

/* Interpret the input objects as numpy arrays. */
PyObject *ref_array = PyArray_FROM_OTF(ref, NPY_DOUBLE, NPY_IN_ARRAY);
PyObject *mov_array = PyArray_FROM_OTF(mov, NPY_DOUBLE, NPY_IN_ARRAY);
PyObject *po_ref_array = PyArray_FROM_OTF(ref, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
PyObject *po_mov_array = PyArray_FROM_OTF(mov, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);

if (!PyArray_Check(po_ref_array) || !PyArray_Check(po_mov_array)) {
PyErr_SetString(PyExc_TypeError, "Expected a numpy array");
return NULL;
}

PyArrayObject *ref_array = (PyArrayObject *)po_ref_array;
PyArrayObject *mov_array = (PyArrayObject *)po_mov_array;

/* If that didn't work, throw an exception. */
if (ref_array == NULL || mov_array == NULL) {
Expand Down Expand Up @@ -199,9 +208,9 @@ PyObject *turbogreg_register(PyObject *self, PyObject *args) {
dims_pts[0] = rm.refPts.nrows();
dims_pts[1] = rm.refPts.ncols();

PyObject *retMat = PyArray_SimpleNew(2, (npy_intp *)&dims_mat, NPY_DOUBLE);
PyObject *retPtsRef = PyArray_SimpleNew(2, (npy_intp *)&dims_pts, NPY_DOUBLE);
PyObject *retPtsMov = PyArray_SimpleNew(2, (npy_intp *)&dims_pts, NPY_DOUBLE);
PyArrayObject *retMat = (PyArrayObject*)PyArray_SimpleNew(2, (npy_intp *)&dims_mat, NPY_DOUBLE);
PyArrayObject *retPtsRef = (PyArrayObject*)PyArray_SimpleNew(2, (npy_intp *)&dims_pts, NPY_DOUBLE);
PyArrayObject *retPtsMov = (PyArrayObject*)PyArray_SimpleNew(2, (npy_intp *)&dims_pts, NPY_DOUBLE);

memcpy((void *)PyArray_DATA(retMat), rm.mat.begin(),
(dims_mat[0] * dims_mat[1] * sizeof(double)));
Expand All @@ -213,7 +222,7 @@ PyObject *turbogreg_register(PyObject *self, PyObject *args) {
return Py_BuildValue("OOO", retMat, retPtsRef, retPtsMov);
}

PyObject *turbogreg_transform(PyObject *self, PyObject *args) {
PyArrayObject *turbogreg_transform(PyObject *self, PyObject *args) {
PyObject *mov;
PyObject *mat;

Expand All @@ -223,16 +232,24 @@ PyObject *turbogreg_transform(PyObject *self, PyObject *args) {
}

/* Interpret the input objects as numpy arrays. */
PyObject *mov_array = PyArray_FROM_OTF(mov, NPY_DOUBLE, NPY_IN_ARRAY);
PyObject *mat_array = PyArray_FROM_OTF(mat, NPY_DOUBLE, NPY_IN_ARRAY);
PyObject *po_mov_array = PyArray_FROM_OTF(mov, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
PyObject *po_mat_array = PyArray_FROM_OTF(mat, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);

/* If that didn't work, throw an exception. */
if (mov_array == NULL || mat_array == NULL) {
Py_XDECREF(mat_array);
Py_XDECREF(mov_array);
if (po_mov_array == NULL || po_mat_array == NULL) {
Py_XDECREF(po_mat_array);
Py_XDECREF(po_mov_array);
return NULL;
}

if (!PyArray_Check(po_mat_array) || !PyArray_Check(po_mov_array)) {
PyErr_SetString(PyExc_TypeError, "Expected a numpy array");
return NULL;
}

PyArrayObject *mov_array = (PyArrayObject *)po_mov_array;
PyArrayObject *mat_array = (PyArrayObject *)po_mat_array;

int ndim_mov = (int)PyArray_NDIM(mov_array);
int ndim_mat = (int)PyArray_NDIM(mat_array);

Expand Down Expand Up @@ -275,7 +292,7 @@ PyObject *turbogreg_transform(PyObject *self, PyObject *args) {

npy_intp dims[2] = {Nx_mov, Ny_mov};

PyObject *ret = PyArray_SimpleNew(2, (npy_intp *)&dims, NPY_DOUBLE);
PyArrayObject *ret = (PyArrayObject*)PyArray_SimpleNew(2, (npy_intp *)&dims, NPY_DOUBLE);

memcpy((void *)PyArray_DATA(ret), &imgout[0],
(Nx_mov * Ny_mov * sizeof(double)));
Expand Down
24 changes: 11 additions & 13 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
[tox]
requires =
numpy
tqdm
envlist = py

[testenv]
deps=
-rrequirements.txt
tifffile
pytest
setuptools
numpy<2
deps =
pytest
tifffile
numpy=={env:NUMPY_VERSION}
setuptools
wheel
-rrequirements.txt

commands=
pip install -e .
python setup.py install
pytest {posargs:}
commands =
pip install -e .
pytest {posargs:}

0 comments on commit 89df317

Please sign in to comment.