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 #46

Merged
merged 25 commits into from
Apr 24, 2024
Merged

Dev #46

Show file tree
Hide file tree
Changes from 23 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
3 changes: 2 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# F401: unused imports in __init__.py-s
# I251: allow absolute imports in upper files
# B028: !r is not supported for python<3.8
ignore = W503,E203,B028
# W604: backticks in str-s are ok
ignore = W503,E203,B028,W604
per-file-ignores =
__init__.py:F401
tests/*:I251
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- uses: fregante/setup-git-user@v1
- run: git fetch origin gh-pages --depth=1
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install
Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.9
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.9

Expand Down Expand Up @@ -42,9 +42,9 @@ jobs:

steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.10.0
run: python -m pip install cibuildwheel==2.17.0
- name: Install gcc for mac
if: matrix.os == 'macOS-11'
run: |
Expand Down Expand Up @@ -76,9 +76,10 @@ jobs:
python -m pip install --upgrade pip
python -m cibuildwheel --output-dir wheelhouse
env:
CIBW_ARCHS_MACOS: "x86_64 arm64"
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: cp36-* cp37-* cp38-* cp39-* cp310-* cp311-*
CIBW_BUILD: cp36-* 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'
- uses: actions/upload-artifact@v3
with:
Expand All @@ -90,9 +91,11 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.9
uses: actions/setup-python@v4
uses: actions/setup-python@v5
- name: Build
run: python setup.py sdist
run: |
pip install build
python -m build --sdist
- uses: actions/upload-artifact@v3
with:
path: dist/*.tar.gz
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ jobs:

steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.9'
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.10.0
run: python -m pip install cibuildwheel==2.17.0
- name: Install gcc for mac
if: matrix.os == 'macOS-11'
run: |
Expand Down Expand Up @@ -52,6 +54,6 @@ jobs:
env:
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: cp39-* cp36-*
CIBW_BUILD: cp39-* cp36-* 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'
9 changes: 5 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [ '3.6', '3.7', '3.8', '3.9', '3.10', '3.11']
python-version: [ '3.6', '3.7', '3.8', '3.9', '3.10', '3.11', '3.12']

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

Expand All @@ -28,7 +28,8 @@ jobs:
if [ "$GITHUB_BASE_REF" = "master" ] && [ "$MATCH" != "" ]; then exit 1; fi
- name: Build the package
run: |
python setup.py sdist
pip install build
python -m build --sdist

- name: Install
run: |
Expand Down Expand Up @@ -73,7 +74,7 @@ jobs:
if: ${{ always() }}

- name: Upload coverage results
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
files: reports/coverage-${{ matrix.python-version }}.xml
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ y = zoom(x, 2, axis=[0, 1])
# without the need to compute the scale factor
z = zoom_to_shape(x, (4, 120, 67))
```
Works faster only for `ndim<=4, dtype=float32 or float64 (and bool-int16-32-64 if order == 0), output=None, order=0 or 1, mode='constant', grid_mode=False`
Works faster only for `ndim<=4, dtype=float32 or float64 (and bool-int16-32-64-uint8-16-32 if order == 0), output=None, order=0 or 1, mode='constant', grid_mode=False`
### Fast 1d linear interpolation

```python
Expand Down
2 changes: 1 addition & 1 deletion imops/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.8.6'
__version__ = '0.8.7'
8 changes: 7 additions & 1 deletion imops/crop.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .backend import BackendLike
from .numeric import _NUMERIC_DEFAULT_NUM_THREADS
from .pad import pad
from .utils import AxesLike, AxesParams, broadcast_axis, fill_by_indices
from .utils import AxesLike, AxesParams, assert_subdtype, broadcast_axis, fill_by_indices


def crop_to_shape(x: np.ndarray, shape: AxesLike, axis: AxesLike = None, ratio: AxesParams = 0.5) -> np.ndarray:
Expand Down Expand Up @@ -35,6 +35,9 @@ def crop_to_shape(x: np.ndarray, shape: AxesLike, axis: AxesLike = None, ratio:
>>> cropped = crop_to_shape(x, [3, 4, 5]) # fail due to bigger resulting shape
"""
x = np.asarray(x)
shape = np.asarray(shape)
assert_subdtype(shape.dtype, np.integer, 'shape')

axis, shape, ratio = broadcast_axis(axis, x.ndim, shape, ratio)

old_shape, new_shape = np.array(x.shape), np.array(fill_by_indices(x.shape, shape, axis))
Expand Down Expand Up @@ -89,6 +92,9 @@ def crop_to_box(
>>> cropped = crop_to_box(x, np.array([[0], [5]]), axis=0, padding_values=0) # pad with 0-s to shape [5, 3, 4]
"""
x = np.asarray(x)
box = np.asarray(box)
assert_subdtype(box.dtype, np.integer, 'box')

start, stop = box
axis, start, stop = broadcast_axis(axis, x.ndim, start, stop)

Expand Down
4 changes: 2 additions & 2 deletions imops/morphology.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ def wrapped(
raise ValueError('Input image and footprint number of dimensions must be the same.')

if not image.any():
warn(f'{op_name} is applied to the fully False mask (mask.any() == False).', stacklevel=3)
warn(f'{op_name} is applied to the fully False mask (mask.any() == False).', stacklevel=3) # noqa
output.fill(False)

return output

if image.all():
warn(f'{op_name} is applied to the fully True mask (mask.all() == True).', stacklevel=3)
warn(f'{op_name} is applied to the fully True mask (mask.all() == True).', stacklevel=3) # noqa
output.fill(True)

return output
Expand Down
2 changes: 2 additions & 0 deletions imops/src/_zoom.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ from libc.math cimport floor, sqrt
ctypedef cython.floating FLOAT
ctypedef fused NUM:
np.uint8_t
np.uint16_t
np.uint32_t
short
int
long long
Expand Down
5 changes: 5 additions & 0 deletions imops/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,8 @@ def check_len(*args) -> None:
lengths = list(map(len, args))
if any(length != lengths[0] for length in lengths):
raise ValueError(f'Arguments of equal length are required: {", ".join(map(str, lengths))}')


def assert_subdtype(dtype, ref_dtype, name):
if not np.issubdtype(dtype, ref_dtype):
raise ValueError(f'`{name}` must be of {ref_dtype.__name__} dtype, got {dtype}')
13 changes: 7 additions & 6 deletions imops/zoom.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def zoom(
"""
Rescale `x` according to `scale_factor` along the `axis`.

Uses a fast parallelizable implementation for fp32 / fp64 (and bool-int16-32-64 if order == 0) inputs,
Uses a fast parallelizable implementation for fp32-fp64 and bool-int16-32-64-uint8-16-32 if order == 0 inputs,
ndim <= 4 and order = 0 or 1.

Parameters
Expand Down Expand Up @@ -136,7 +136,7 @@ def zoom_to_shape(
"""
Rescale `x` to match `shape` along the `axis`.

Uses a fast parallelizable implementation for fp32 / fp64 (and bool-int16-32-64 if order == 0) inputs,
Uses a fast parallelizable implementation for fp32-fp64 and bool-int16-32-64-uint8-16-32 if order == 0 inputs,
ndim <= 4 and order = 0 or 1.

Parameters
Expand Down Expand Up @@ -198,7 +198,7 @@ def _zoom(
backend: BackendLike = None,
) -> np.ndarray:
"""
Faster parallelizable version of `scipy.ndimage.zoom` for fp32 / fp64 (and bool-int16-32-64 if order == 0) inputs.
Faster parallelizable version of `scipy.ndimage.zoom` for fp32-fp64 and bool-int16-32-64-uint8-16-32 if order == 0

Works faster only for ndim <= 4. Shares interface with `scipy.ndimage.zoom`
except for
Expand Down Expand Up @@ -228,16 +228,17 @@ def _zoom(
or (
dtype not in (np.float32, np.float64)
if order == 1
else dtype not in (bool, np.float32, np.float64, np.int16, np.int32, np.int64)
else dtype
not in (bool, np.float32, np.float64, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32)
)
or ndim > 4
or output is not None
or mode != 'constant'
or grid_mode
):
warn(
'Fast zoom is only supported for ndim<=4, dtype=fp32 or fp64 (and bool-int16-32-64 if order == 0), '
"output=None, order=0 or 1, mode='constant', grid_mode=False. Falling back to scipy's implementation.",
'Fast zoom is only supported for ndim<=4, dtype=fp32-fp64 and bool-int16-32-64-uint8-16-32 if order == 0, '
"output=None, order=0 or 1 , mode='constant', grid_mode=False. Falling back to scipy's implementation.",
stacklevel=3,
)
return scipy_zoom(
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ classifiers = [
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
]

[options]
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
]

with open(root / 'requirements.txt', encoding='utf-8') as file:
Expand Down
16 changes: 15 additions & 1 deletion tests/test_crop.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,21 @@ def test_raises():
@seeded_by(SEED)
def test_crop_to_shape():
x = np.random.rand(3, 10, 10)
shape = 3, 4, 8
shape = (3, 4, 8)
assert crop_to_shape(x, shape).shape == shape
with pytest.raises(ValueError):
crop_to_shape(x, (3, 15, 10))


def test_crop_to_float_shape():
x = np.random.rand(3, 10, 10)
float_shape = (1.337, 3.1415, 2.7182)
with pytest.raises(ValueError):
crop_to_shape(x, float_shape)


def test_crop_to_float_box():
x = np.random.rand(3, 10, 10)
float_box = [[0, 1], [4, 4.5], [3.1, 9]]
with pytest.raises(ValueError):
crop_to_box(x, float_box)
3 changes: 3 additions & 0 deletions tests/test_pad.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ def test_restore_crop_invalid_box():
with pytest.raises(ValueError):
restore_crop(x, np.array([[0, 0, 0], [1, 1, 1]]), [4, 4, 4])

with pytest.raises(ValueError):
restore_crop(x, np.array([[0.5, 0.5, 0.5], [1.5, 1.5, 1.5]]), [4.5, 4.5, 4.5])


def test_pad_to_divisible():
x = np.zeros((4, 8, 12))
Expand Down
2 changes: 1 addition & 1 deletion tests/test_zoom.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def order(request):
return request.param


@pytest.fixture(params=[np.float32, np.float64, bool, np.int16, np.int32, np.int64])
@pytest.fixture(params=[np.float32, np.float64, bool, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32])
def dtype(request):
return request.param

Expand Down
Loading