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

Dev #59

Merged
merged 41 commits into from
Aug 4, 2024
Merged

Dev #59

Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
0a59e46
Add faster `isin`
vovaf709 Jun 13, 2024
0c4816f
upd flake8 config
vovaf709 Jun 26, 2024
6a1ca2d
Add `make_immutable`
vovaf709 Jul 30, 2024
129c0fa
Bump `Cython`
vovaf709 Jul 30, 2024
4bfb6bd
Fix for zoom on immutable arrays
vovaf709 Jul 30, 2024
755a438
test `interp1d` on immutable arrays
vovaf709 Jul 30, 2024
9479458
Test immutable on `interp2d`
vovaf709 Jul 30, 2024
0be6aaa
Fix and test `imops.measure` on immutable arrays
vovaf709 Jul 30, 2024
9ebcc36
Fix & test `morphology` for immutable arrays
vovaf709 Jul 30, 2024
14454b1
Make & Fix `utils` for ummutable arrays
vovaf709 Jul 30, 2024
41c9e9f
immutability tests
vovaf709 Jul 30, 2024
c5d1f18
Make & test radon-s on immutable arrays
vovaf709 Jul 30, 2024
781ee73
test
vovaf709 Jul 30, 2024
53c4f61
:nail_care:
vovaf709 Jul 30, 2024
a1ea911
version
vovaf709 Jul 30, 2024
c010284
benchmark dev
vovaf709 Jul 30, 2024
84b3209
Bump macos
vovaf709 Jul 30, 2024
39c8019
Fix?
vovaf709 Jul 31, 2024
c97e408
maybe this
vovaf709 Jul 31, 2024
783cd25
specific python
vovaf709 Aug 1, 2024
1b99872
Fix build reqs, loose numpy
vovaf709 Aug 1, 2024
8ea6709
Some docs
vovaf709 Aug 1, 2024
4ea9ffc
const
vovaf709 Aug 1, 2024
3e56e26
Fix
vovaf709 Aug 1, 2024
956102e
Revert "maybe this"
vovaf709 Aug 1, 2024
c86362a
Maybe this
vovaf709 Aug 1, 2024
bc053e5
Fix
vovaf709 Aug 1, 2024
c5fee6a
Fix
vovaf709 Aug 1, 2024
2f12194
Remove some warnings
vovaf709 Aug 2, 2024
ccb9a0b
Fix
vovaf709 Aug 2, 2024
ea84287
Fix
vovaf709 Aug 2, 2024
e8c9e34
check gcc path
vovaf709 Aug 2, 2024
0f935d9
Fix
vovaf709 Aug 2, 2024
ccb2313
Maybe fix
vovaf709 Aug 2, 2024
0f9a69e
Fix
vovaf709 Aug 2, 2024
d3d378a
mb macos-12
vovaf709 Aug 2, 2024
cf9c7d1
`center_of_mass` in float32
vovaf709 Aug 2, 2024
fa5b230
macos-12 & :nail_care:
vovaf709 Aug 2, 2024
3ad886b
Fix
vovaf709 Aug 2, 2024
6b26529
compat
vovaf709 Aug 2, 2024
8c43e58
rtol
vovaf709 Aug 2, 2024
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
6 changes: 5 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
# I251: allow absolute imports in upper files
# B028: !r is not supported for python<3.8
# W604: backticks in str-s are ok
ignore = W503,E203,B028,W604
# S101: asserts are ok for now
# S102: exec in build scripts is ok
ignore = W503,E203,B028,W604,S101
per-file-ignores =
setup.py:S102
_build_utils.py:S102
__init__.py:F401
tests/*:I251
benchmarks/*:I251
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
needs: [ check_version ]
strategy:
matrix:
os: [ ubuntu-22.04, windows-2019, macOS-11 ]
os: [ ubuntu-22.04, windows-2019, macOS-12 ]

name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand All @@ -48,7 +48,7 @@ jobs:
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.17.0
- name: Install gcc for mac
if: matrix.os == 'macOS-11'
if: matrix.os == 'macOS-12'
run: |
brew install llvm libomp
echo $PATH
Expand Down Expand Up @@ -81,7 +81,7 @@ jobs:
CIBW_ENVIRONMENT_MACOS: >
PATH="/usr/local/opt/llvm/bin:$PATH" LDFLAGS="-L/usr/local/opt/llvm/lib" CPPFLAGS="-I/usr/local/opt/llvm/include"
CIBW_BUILD: cp37-* cp38-* cp39-* cp310-* cp311-* cp312-*
CIBW_BEFORE_BUILD_LINUX: 'if [ $(python -c "import sys; print(sys.version_info[1])") -ge 9 ]; then python -m pip install "numpy<2.0.0" --config-settings=setup-args="-Dallow-noblas=true"; fi'
CIBW_BEFORE_BUILD_LINUX: 'if [ $(python -c "import sys; print(sys.version_info[1])") -ge 9 ]; then python -m pip install "numpy<3.0.0" --config-settings=setup-args="-Dallow-noblas=true"; fi'
- uses: actions/upload-artifact@v3
with:
path: ./wheelhouse/*.whl
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
build_wheels:
strategy:
matrix:
os: [ubuntu-22.04, windows-2019, macOS-11 ]
os: [ubuntu-22.04, windows-2019, macOS-12 ]

name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand All @@ -22,7 +22,7 @@ jobs:
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.17.0
- name: Install gcc for mac
if: matrix.os == 'macOS-11'
if: matrix.os == 'macOS-12'
run: |
brew install llvm libomp
echo $PATH
Expand Down Expand Up @@ -56,4 +56,4 @@ jobs:
PATH="/usr/local/opt/llvm/bin:$PATH" LDFLAGS="-L/usr/local/opt/llvm/lib" CPPFLAGS="-I/usr/local/opt/llvm/include"
CIBW_BUILD: cp39-* cp312-*
CIBW_SKIP: "*musllinux* *manylinux_x86_64"
CIBW_BEFORE_BUILD_LINUX: 'if [ $(python -c "import sys; print(sys.version_info[1])") -ge 9 ]; then python -m pip install "numpy<2.0.0" --config-settings=setup-args="-Dallow-noblas=true"; fi'
CIBW_BEFORE_BUILD_LINUX: 'if [ $(python -c "import sys; print(sys.version_info[1])") -ge 9 ]; then python -m pip install "numpy<3.0.0" --config-settings=setup-args="-Dallow-noblas=true"; fi'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
__pycache__/
.pytest_cache/
build/
imops/src/*.cpp
imops/src/*.c
imops/src/*.so
imops/src/_fast*.pyx
Expand Down
13 changes: 12 additions & 1 deletion _build_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,16 @@ def get_ext_modules():
extra_compile_args=args + cpp_args,
extra_link_args=args + cpp_args,
language='c++',
)
),
Extension(
f'{name}.src._utils',
[f'{name}/src/_utils.pyx'],
language='c++',
include_dirs=[LazyImport('numpy')],
extra_compile_args=args + cpp_args,
extra_link_args=args + cpp_args,
define_macros=[('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')],
),
]
for module in modules:
libraries = []
Expand All @@ -93,6 +102,7 @@ def get_ext_modules():
if not on_windows:
libraries.append('m')

# TODO: mb throw `ffast-math` away?
# FIXME: import of `ffast-math` compiled modules changes global FPU state, so now `fast=True` will just
# fallback to standard `-O2` compiled versions until https://github.com/neuro-ml/imops/issues/37 is resolved
# for prefix, additional_args in zip(['', 'fast_'], [[], ['-ffast-math']])
Expand All @@ -101,6 +111,7 @@ def get_ext_modules():
Extension(
f'{name}.src._{prefix}{module}',
[f'{name}/src/_{prefix}{module}.pyx'],
language='c',
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
Expand Down
6 changes: 3 additions & 3 deletions asv.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
"project": "imops",
"project_url": "https://github.com/neuro-ml/imops",
"repo": ".",
"branches": ["master", "dev"],
"branches": ["dev"],
"dvcs": "git",
"environment_type": "conda",
"show_commit_url": "https://github.com/neuro-ml/imops/commit",
"pythons": ["3.10"],
"pythons": ["3.12.3"],
"conda_channels": ["defaults", "conda-forge"],
"matrix": {
"req": {
"numpy": [],
"Cython": ["0.29.36"],
"Cython": ["3.0.10"],
"scipy": [],
"scikit-image": [],
"numba": [],
Expand Down
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,5 @@ pip install imops[numba] # additionally install Numba backend
::: imops.radon.radon

::: imops.radon.inverse_radon

::: imops.utils.isin
2 changes: 1 addition & 1 deletion imops/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.8.8'
__version__ = '0.9.0'
5 changes: 3 additions & 2 deletions imops/measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
}


# TODO: Make it work and test on immutable arrays as soon as `cc3d` package is fixed
def label(
label_image: np.ndarray,
background: int = None,
Expand Down Expand Up @@ -209,8 +210,8 @@ def center_of_mass(

src_center_of_mass = _fast_labeled_center_of_mass if backend.fast else _labeled_center_of_mass

if array.dtype != 'float64':
array = array.astype(float)
if array.dtype not in ('float32', 'float64'):
array = array.astype(np.float32)

n_dummy = 3 - ndim
if n_dummy:
Expand Down
8 changes: 7 additions & 1 deletion imops/radon.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
from .utils import normalize_num_threads


try:
from numpy.lib.array_utils import normalize_axis_tuple
except ModuleNotFoundError:
from numpy.core.numeric import normalize_axis_tuple
Copy link
Member

Choose a reason for hiding this comment

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

create a compat.py file and move all such failsafe imports there. then just import from it



def radon(
image: np.ndarray,
axes: Tuple[int, int] = None,
Expand Down Expand Up @@ -204,7 +210,7 @@ def normalize_axes(x: np.ndarray, axes):
raise ValueError('For arrays of higher dimensionality the `axis` arguments is required')
axes = [0, 1]

axes = np.core.numeric.normalize_axis_tuple(axes, x.ndim, 'axes')
axes = normalize_axis_tuple(axes, x.ndim, 'axes')
x = np.moveaxis(x, axes, (-2, -1))
extra = x.shape[:-2]
x = x.reshape(-1, *x.shape[-2:])
Expand Down
12 changes: 6 additions & 6 deletions imops/src/_backprojection.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ctypedef np.uint8_t uint8

@cython.boundscheck(False)
@cython.wraparound(False)
cdef inline FLOAT interpolate(FLOAT x, FLOAT* ys, FLOAT radius, FLOAT right_limit) nogil:
cdef inline FLOAT interpolate(FLOAT x, const FLOAT* ys, FLOAT radius, FLOAT right_limit) noexcept nogil:
cdef Py_ssize_t idx
cdef FLOAT val, value

Expand All @@ -40,8 +40,8 @@ cdef inline FLOAT interpolate(FLOAT x, FLOAT* ys, FLOAT radius, FLOAT right_limi

@cython.boundscheck(False)
@cython.wraparound(False)
cdef FLOAT accumulate(FLOAT x, FLOAT y, FLOAT* sinuses, FLOAT* cosinuses, FLOAT* ys,
Py_ssize_t size, Py_ssize_t image_size, FLOAT radius, FLOAT right_limit) nogil:
cdef FLOAT accumulate(FLOAT x, FLOAT y, const FLOAT* sinuses, const FLOAT* cosinuses, const FLOAT* ys,
Py_ssize_t size, Py_ssize_t image_size, FLOAT radius, FLOAT right_limit) noexcept nogil:
cdef FLOAT accumulator = 0
cdef Py_ssize_t k

Expand All @@ -52,9 +52,9 @@ cdef FLOAT accumulate(FLOAT x, FLOAT y, FLOAT* sinuses, FLOAT* cosinuses, FLOAT*

@cython.boundscheck(False)
@cython.wraparound(False)
cpdef FLOAT[:, :, :] backprojection3d(FLOAT[:, :, :] sinogram, FLOAT[:] theta, FLOAT[:] xs,
uint8[:, :] inside_circle, FLOAT fill_value, int image_size, int output_size,
Py_ssize_t num_threads):
cpdef FLOAT[:, :, :] backprojection3d(const FLOAT[:, :, :] sinogram, const FLOAT[:] theta, const FLOAT[:] xs,
const uint8[:, :] inside_circle, FLOAT fill_value, int image_size,
int output_size, Py_ssize_t num_threads):
cdef FLOAT[:, :, :] result = np.zeros_like(sinogram, shape=(len(sinogram), output_size, output_size))
cdef Py_ssize_t slc, i, j, n_angles = len(theta), n_slices = len(sinogram)
cdef FLOAT min_val = image_size // 2, right_lim = image_size - 1
Expand Down
26 changes: 15 additions & 11 deletions imops/src/_measure.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@

import numpy as np

cimport cython
cimport numpy as np

from cython.parallel import prange


ctypedef cython.floating FLOAT

ctypedef fused LABEL:
signed char
short
Expand All @@ -23,7 +26,7 @@ ctypedef fused LABEL:
unsigned long long


cdef inline Py_ssize_t _find(LABEL num, LABEL[:] nums) nogil:
cdef inline Py_ssize_t _find(LABEL num, const LABEL[:] nums) noexcept nogil:
cdef Py_ssize_t i

for i in range(len(nums)):
Expand All @@ -33,15 +36,16 @@ cdef inline Py_ssize_t _find(LABEL num, LABEL[:] nums) nogil:
return -1


def _labeled_center_of_mass(double[:, :, :] nums, LABEL[:, :, :] labels, LABEL[:] index) -> np.ndarray:
cdef double[:, :, ::1] contiguous_nums = np.ascontiguousarray(nums)
cdef LABEL[:, :, ::1] contiguous_labels = np.ascontiguousarray(labels)
cdef LABEL[:] contiguous_index = np.ascontiguousarray(index)
def _labeled_center_of_mass(const FLOAT[:, :, :] nums, const LABEL[:, :, :] labels,
const LABEL[:] index) -> np.ndarray:
cdef const FLOAT[:, :, ::1] contiguous_nums = np.ascontiguousarray(nums)
cdef const LABEL[:, :, ::1] contiguous_labels = np.ascontiguousarray(labels)
cdef const LABEL[:] contiguous_index = np.ascontiguousarray(index)

cdef Py_ssize_t index_len = len(index)

cdef double[:, ::1] output = np.zeros((index_len, 3))
cdef double[:] normalizers = np.zeros(index_len)
cdef FLOAT[:, ::1] output = np.zeros_like(nums, shape=(index_len, 3))
cdef FLOAT[:] normalizers = np.zeros_like(nums, shape=(index_len,))

cdef Py_ssize_t rows = nums.shape[0], cols = nums.shape[1], dims = nums.shape[2]
cdef Py_ssize_t i, j, k, pos
Expand All @@ -66,11 +70,11 @@ def _labeled_center_of_mass(double[:, :, :] nums, LABEL[:, :, :] labels, LABEL[:
return np.asarray(output)


def _center_of_mass(double[:, :, :] nums, Py_ssize_t num_threads) -> np.ndarray:
cdef double[:, :, ::1] contiguous_nums = np.ascontiguousarray(nums)
def _center_of_mass(const FLOAT[:, :, :] nums, Py_ssize_t num_threads) -> np.ndarray:
cdef const FLOAT[:, :, ::1] contiguous_nums = np.ascontiguousarray(nums)

cdef double output_x = 0, output_y = 0, output_z = 0
cdef double normalizer = 0
cdef FLOAT output_x = 0, output_y = 0, output_z = 0
cdef FLOAT normalizer = 0

cdef Py_ssize_t rows = nums.shape[0], cols = nums.shape[1], dims = nums.shape[2]
cdef Py_ssize_t i, j, k
Expand Down
36 changes: 18 additions & 18 deletions imops/src/_morphology.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ cdef struct array_iterator:
int backstrides[3]


cdef int init_array_iterator(array_iterator *arr_iter, int *shape, int *strides) nogil:
cdef int init_array_iterator(array_iterator *arr_iter, const int *shape, const int *strides) noexcept nogil:
cdef int i

arr_iter.rank_m1 = 2
Expand All @@ -45,11 +45,11 @@ cdef struct filter_iterator:

cdef int init_filter_iterator(
filter_iterator *filter_iter,
int *a_shape,
int *f_shape,
const int *a_shape,
const int *f_shape,
int filter_size,
np.uint8_t is_dilation
) nogil:
) noexcept nogil:
cdef int i, rank = 3, step, orgn

filter_iter[0].strides[rank - 1] = filter_size
Expand All @@ -71,12 +71,12 @@ cdef int init_filter_iterator(


cdef int init_filter_offsets(
int *a_shape, int *a_strides,
np.uint8_t *footprint, int *f_shape,
const int *a_shape, const int *a_strides,
const np.uint8_t *footprint, const int *f_shape,
int footprint_size,
int **offsets, int *border_flag_value,
np.uint8_t is_dilation
) nogil:
) noexcept nogil:
cdef int i, j, k
cdef int filter_size = 1, offsets_size = 1
cdef int max_size = 0, max_stride = 0
Expand Down Expand Up @@ -165,7 +165,7 @@ cdef int init_filter_offsets(
return 0


cdef inline int filter_iterator_offset(filter_iterator *filter_iter, int *coordinates) nogil:
cdef inline int filter_iterator_offset(const filter_iterator *filter_iter, const int *coordinates) noexcept nogil:
cdef int i, position, offset = 0

for i in range(3):
Expand All @@ -184,14 +184,14 @@ cdef inline int filter_iterator_offset(filter_iterator *filter_iter, int *coordi


cdef inline int worker(
np.uint8_t *input, np.uint8_t *footprint, np.uint8_t *output,
const np.uint8_t *input, const np.uint8_t *footprint, np.uint8_t *output,
int *a_shape, int *a_strides, int *f_shape,
int footprint_size,
int *offsets, int border_flag_value,
int start, int end,
np.uint8_t border_value,
np.uint8_t is_dilation,
) nogil:
) noexcept nogil:
cdef np.uint8_t _true = not is_dilation
cdef np.uint8_t _false = not _true

Expand Down Expand Up @@ -252,15 +252,15 @@ cdef inline int worker(


def _binary_operation(
np.uint8_t[:, :, :] input,
np.uint8_t[:, :, :] footprint,
const np.uint8_t[:, :, :] input,
const np.uint8_t[:, :, :] footprint,
np.uint8_t[:, :, ::1] out,
Py_ssize_t num_threads,
np.uint8_t border_value,
np.uint8_t is_dilation,
) -> np.ndarray:
cdef np.uint8_t[:, :, ::1] c_input = np.ascontiguousarray(input)
cdef np.uint8_t[:, :, ::1] c_footprint = np.ascontiguousarray(footprint)
cdef const np.uint8_t[:, :, ::1] c_input = np.ascontiguousarray(input)
cdef const np.uint8_t[:, :, ::1] c_footprint = np.ascontiguousarray(footprint)

cdef int f_shape[3]
cdef int a_shape[3]
Expand Down Expand Up @@ -311,17 +311,17 @@ def _binary_operation(


def _binary_erosion(
np.uint8_t[:, :, :] input,
np.uint8_t[:, :, :] footprint,
const np.uint8_t[:, :, :] input,
const np.uint8_t[:, :, :] footprint,
np.uint8_t[:, :, ::1] out,
Py_ssize_t num_threads,
) -> np.ndarray:
return _binary_operation(input, footprint, out, num_threads, True, False)


def _binary_dilation(
np.uint8_t[:, :, :] input,
np.uint8_t[:, :, :] footprint,
const np.uint8_t[:, :, :] input,
const np.uint8_t[:, :, :] footprint,
np.uint8_t[:, :, ::1] out,
Py_ssize_t num_threads,
) -> np.ndarray:
Expand Down
Loading
Loading