From 60b4e0fe7d90802e1f6ebfca4a327278a004586e Mon Sep 17 00:00:00 2001 From: Wim Pomp Date: Fri, 30 Oct 2026 18:25:05 +0100 Subject: [PATCH] - fix slicing bug - add pytest workflow --- .github/workflows/pytest.yml | 78 ++++++++++++++++++++++++++++++++ Cargo.toml | 3 +- ndbioimage/pyproject.toml | 2 +- ndbioimage/src/view.rs | 28 +++++++++--- ndbioimage/tests/test_slicing.py | 2 +- 5 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/pytest.yml diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 0000000..4ecd88b --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,78 @@ +name: pytest + +on: [ workflow_dispatch, workflow_call, push, pull_request ] + +permissions: + contents: read + +jobs: + pypi_publish: + name: Publish (pypi.org) + runs-on: ubuntu-latest + env: + CARGO_HOME: ${{ github.workspace }}/.cargo + RUSTUP_HOME: ${{ github.workspace }}/.rustup + RUSTUP_TOOLCHAIN: stable + steps: + - uses: actions/checkout@v6 + with: + submodules: recursive + - uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Restore cache + uses: actions/cache/restore@v4 + with: + path: | + ~/.cache/pip + ~/.cache/pip-wheel + ~/.cache/sccache + ${{ env.CARGO_HOME }} + key: cache-ubuntu-maturin-cross-compile + + - name: Install build dependencies + run: | + sudo apt update + sudo apt install -y build-essential cmake clang llvm lld libclang + shell: bash + + - name: Install Rust + run: | + export PATH="$CARGO_HOME/bin:$PATH" + if ! command -v rustup >/dev/null 2>&1; then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + fi + rustup toolchain install stable --profile minimal + rustup default stable + echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" + cargo --version + shell: bash + + - name: Install sccache and maturin + run: | + python -m pip install --upgrade pip maturin ziglang cargo-zigbuild + # in case an older copy was cargo-installed into the CARGO_HOME cache, + # prevent it from shadowing the pip-installed one + rm -f "${CARGO_HOME:?}/bin/cargo-zigbuild" || true + if ! command -v sccache >/dev/null 2>&1; then + cargo install sccache || pip install sccache + fi + shell: bash + + - name: PyTest + run: | + python -m pip install . + python -m pytest + + - name: Store cache + uses: actions/cache/save@v4 + with: + path: | + ~/.cache/pip + ~/.cache/pip-wheel + ~/.cache/sccache + ~/.cache/cargo-xwin + ${{ env.CARGO_HOME }} + ~/.osxcross + key: cache-ubuntu-maturin-cross-compile diff --git a/Cargo.toml b/Cargo.toml index c984541..7ab29a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["ndbioimage", "image-tiff", "image-registration"] [workspace.package] -version = "0.3.1" +version = "0.3.2" edition = "2024" rust-version = "1.94.1" authors = ["Wim Pomp "] @@ -20,6 +20,7 @@ inherits = "release" debug = true [profile.release] +#debug = true [profile.dev.package.backtrace] opt-level = 3 diff --git a/ndbioimage/pyproject.toml b/ndbioimage/pyproject.toml index 0adeb01..a4a3f33 100644 --- a/ndbioimage/pyproject.toml +++ b/ndbioimage/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "ndbioimage" -version = "2027.0.7" +version = "2027.0.8" requires-python = ">=3.10" classifiers = [ "License :: OSI Approved :: MIT License", diff --git a/ndbioimage/src/view.rs b/ndbioimage/src/view.rs index d3e768a..f6e895a 100644 --- a/ndbioimage/src/view.rs +++ b/ndbioimage/src/view.rs @@ -964,16 +964,19 @@ impl View { axes_out_idx[*ax as usize] = Some(i); } } - - for (c, z, t) in iproduct!(&slice_reader[0], &slice_reader[1], &slice_reader[2]) { + for ((ci, c), (zi, z), (ti, t)) in iproduct!( + slice_reader[0].enumerate(), + slice_reader[1].enumerate(), + slice_reader[2].enumerate() + ) { if let Some(i) = axes_out_idx[0] { - slice_out[i] = SliceInfoElem::Index(c) + slice_out[i] = SliceInfoElem::Index(ci as isize) }; if let Some(i) = axes_out_idx[1] { - slice_out[i] = SliceInfoElem::Index(z) + slice_out[i] = SliceInfoElem::Index(zi as isize) }; if let Some(i) = axes_out_idx[2] { - slice_out[i] = SliceInfoElem::Index(t) + slice_out[i] = SliceInfoElem::Index(ti as isize) }; #[cfg(feature = "transforms")] let transform = self @@ -1611,7 +1614,7 @@ mod tests { use crate::stats::MinMax; use crate::view::{Item, View}; use indexmap::IndexMap; - use ndarray::{Array, Array4, Array5, Ix5, NewAxis}; + use ndarray::{Array, Array4, Array5, Ix4, Ix5, NewAxis}; use ndarray::{Array2, ArrayD, IxDyn, SliceInfoElem, s}; use postcard::{from_bytes, to_stdvec}; use std::path::{Path, PathBuf}; @@ -2072,4 +2075,17 @@ mod tests { assert_eq!(t, t2); Ok(()) } + + #[cfg(feature = "tiffseq")] + #[test] + fn test_slice() -> Result<(), Error> { + let file = "tiff/20251014_20-Pos_000_000_max.tif"; + let reader = open(file)?; + let view: View = + View::new_with_axes(reader, vec![Axis::C, Axis::Z, Axis::Y, Axis::X])?; + let roi = view.slice(s![0, 1..2, 633..653, 853..873])?; + let arr = roi.as_array::()?; + println!("{:?}", arr); + Ok(()) + } } diff --git a/ndbioimage/tests/test_slicing.py b/ndbioimage/tests/test_slicing.py index 2130f23..b4d26f1 100644 --- a/ndbioimage/tests/test_slicing.py +++ b/ndbioimage/tests/test_slicing.py @@ -28,7 +28,7 @@ def image(array): "s", list( combinations_with_replacement( - (0, -1, 1, slice(None), slice(0, 1), slice(-1, 0), slice(1, 1)), 5 + (0, -1, 1, slice(None), slice(0, 1), slice(-1, 0), slice(1, 1), slice(1, 2)), 5 ) ), )