🔖 Release 2.1.2#1083
Merged
Merged
Conversation
Currently, `utils.imwrite` does not check whether the write operation succeeded. This can return to unexpected behaviour: for example, nothing will happen if you write to a folder that does not exist. --------- Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Fix return value of prealignment function. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
Files are first downloaded as temporary files and then transferred to the targeted location. This prevents corrupted files from being stored if the download is terminated. ------ Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
- Remove redundant `_rm_dir` in tests.
- Add `flake8-annotations` to visualisation
I have created this as a proof of concept in regard to my comments on #632. This PR extends the `Annotation` class to enable the creation from either a set of coordinates and a geometry type (int) for direct decoding of the WKB OR from a shapely geometry object. The shapely geometry is created lazily, and vice versa; the coordinates can be accessed lazily if the Annotation was created from a Shapely object. # Summary 1. Enables init of `Annotation` from WKB bytes instead of from Shapely geometry object. This can shorten the path from database WKB -> Shapely -> Numpy Array for applications which just need the raw coordinates and not any Shapely/geos methods. 1. Move `decode_wkb` to an Annotation static method. This could potentially be optimized with numba or similar in future. 1. Lazily create a Shapely geometry object, WKB, or raw numpy coordinates as needed. This can avoid converting WKB to shapely and then to coordinates and go directly from WKB to coordinates. 1. Add tests. 1. Update code relying on `as_wkb`. 1. Bug fixes including fixing exceptions on appending unsupported geometry and generation of coordinates from WKB in `decode_wkb`. 2. Ensures the coordinates generates from Shapely and from `decode_wkb` via `Annotation.coords` are in the same format as each other. I.e. 1x2 array for points, nx2 array for lines, list of nx2 arrays for poylgons and lists for the multi forms. --------- Co-authored-by: measty <20169086+measty@users.noreply.github.com> Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Add `flake8-annotations` checks for `examples`
- Add `flake8-annotations` Checks for `engine`
Adds the ability to run tests using several workers using [pytest-xdist](https://github.com/pytest-dev/pytest-xdist), significantly improving processing time. For example, on M1 Max (no CUDA), processing time dropped **from 14 minutes to 4 minutes 💨💨💨.** <img width="1614" alt="image" src="https://github.com/TissueImageAnalytics/tiatoolbox/assets/19199204/fbb607b0-3bf1-48c3-b14a-be4acf2b1ec3"> However, this optimization comes at a cost. Previously, tests depended on serial execution. For example, segmentation and prediction methods used to rely on "output" as a folder to store intermediate results. If many functions modified this folder at the same time, the result would be unpredictable. To address this, I made some tweaks alongside #641 and #673 so that functions will not depend on each other. If we merge this pull request, we will need to start checking that new tests are ready for parallel execution. **Depends on #641 and #673
- Fixes PatchExtractors `within_bound ` has an incorrect description.
- Upgrade `ruff` to version `0.0.286`
updates: - [github.com/executablebooks/mdformat: 0.7.16 → 0.7.17](hukkin/mdformat@0.7.16...0.7.17) - [github.com/astral-sh/ruff-pre-commit: v0.0.285 → v0.0.286](astral-sh/ruff-pre-commit@v0.0.285...v0.0.286) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Add `flake8-annotations` Checks to `pre-commit` and `conftest.py` - Add `flake8-annotations` Checks to `conftest.py` - Add `flake8-annotations` Checks to `tests\models`
- Fix Add `flake8-annotations` checks for `enums.py` - Fix Add `flake8-annotations` checks for `test_graph.py` - Fix Add `flake8-annotations` checks for `test_patch_extraction.py` - Fix Add `flake8-annotations` checks for `test_pyramid.py` - Fix Add `flake8-annotations` checks for `tests/test_save_tiles.py ` - Fix Add `flake8-annotations` checks for `tests/test_slide_thumbnail.py` and `tests/test_slide_info.py` - Fix Add `flake8-annotations` checks for `tests/test_stainnorm.py` and `tests/test_stainaugment.py` - Fix Add `flake8-annotations` checks for `tests/test_utils.py` - Fix Add `flake8-annotations` checks for `tests/test_tissuemask.py` and `tests/test_tiffreader.py` - Fix `tests/test_tileserver.py` - Fix `flake8-annotations` for test_wsi_registration.py - Fix `flake8-annotations` for test_docs.py - Fix `flake8-annotations` for test_wsireader.py
- Add `IOConfig` for NuClick in `pretrained_model.yaml`
<!--pre-commit.ci start--> updates: - [github.com/psf/black: 23.7.0 → 23.9.1](psf/black@23.7.0...23.9.1) - [github.com/astral-sh/ruff-pre-commit: v0.0.286 → v0.0.288](astral-sh/ruff-pre-commit@v0.0.286...v0.0.288) <!--pre-commit.ci end-->
updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.288 → v0.0.290](astral-sh/ruff-pre-commit@v0.0.288...v0.0.290) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Fix flake8-annotation errors in tests and annotation. --------- Co-authored-by: Abdol A <u2271662@live.warwick.ac.uk> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.290 → v0.0.291](astral-sh/ruff-pre-commit@v0.0.290...v0.0.291) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Add `ruff` checks with selected options. --------- Signed-off-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: John Pocock <John-P@users.noreply.github.com>
updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.291 → v0.0.292](astral-sh/ruff-pre-commit@v0.0.291...v0.0.292) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Update minimum requirement for torch to `2.1.0`
- Replace direct `Polygon` construction with validated geometry via `feature2geometry` and `make_valid_poly`. - Ensure all shapes are repaired and valid before JSON export. - Prevents malformed or invalid polygons from breaking QuPath JSON outputs. --------- Co-authored-by: Jiaqi Lv <lvjiaqi9@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* 🧑💻 pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.9 → v0.15.12](astral-sh/ruff-pre-commit@v0.15.9...v0.15.12) * 📌 Update `ruff` version * 🐛 Fix pip install workflow --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
## ✅ Summary - Enables compatibility with Zarr v3+ - Simplifies error handling across Zarr versions - Removes deprecated storage backends and APIs - Lays groundwork for full Zarr v3 migration This PR updates TIAToolbox to support **Zarr v3+**, addressing breaking changes introduced in Zarr ≥ 3.0 and aligning internal APIs, storage handling, and error handling accordingly. --- Zarr v3 removed `zarr.errors.FSPathExistNotDir`. In Zarr ≥ 3.0, equivalent failure modes now raise standard Python exceptions (e.g. `FileNotFoundError`). To avoid fragile version-specific logic: - Removed checks for specific Zarr exception types - Replaced them with generic exception handling that works consistently across Zarr versions --- ## 🔧 Key changes ### Dependency updates - 🆙 Upgrade to: - `zarr >= 3.0.8` - `tifffile >= 2025.5.21` ### Zarr API & storage migration - Refactor `zarr.core.Array` → `zarr.Array` - Replace `zarr.DirectoryStore` with `zarr.storage.LocalStore` - Remove `ngff.sqlitestore` (Zarr v3 no longer supports `zarr.SQLiteStore`) - Replace `canvas_zarr.store.path` with `canvas_zarr.store.root` - Ensure Zarr paths explicitly use string keys (`key / str(i)` instead of `key / i`) ### Dask & array handling - Remove unsupported `object_codec` usage in `dask.to_zarr` - Update `zarr.resize` calls to use tuple inputs - Replace `output.items()` with `output.members()` --- ##⚠️ Known limitations & follow‑ups Zarr v3 removes or significantly changes several APIs still used by TIAToolbox, including: - `zarr.LRUStoreCache` - `zarr.DirectoryStore` - `zarr.SQLiteStore` While this PR resolves immediate incompatibilities and enables Zarr v3 usage, **additional refactoring will be required** to fully replace or redesign components that depend on these removed features. In addition, **full compatibility with `tifffile` depends on upstream Zarr v3 support**, and some workflows may remain limited until that stabilises. 📖 For a detailed overview of breaking changes, see the official Zarr v3 migration guide: https://zarr.readthedocs.io/en/latest/user-guide/v3_migration.html --------- Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Aleksandar Acic <32873451+aacic@users.noreply.github.com> Co-authored-by: Jiaqi Lv <lvjiaqi9@gmail.com>
This PR introduces **Python 3.14 support** and refactors the **conda environment testing workflow** to improve maintainability, reproducibility, and cross-platform compatibility.
---
## ✨ Key Changes
### ✅ 1. Python 3.14 Support
- Updated package metadata:
- Extended supported Python versions in documentation:
- Updated installation docs accordingly
---
### ✅ 2. Single Source of Truth for Dependencies
- Added a new script:
```requirements/generate_conda_env.py```
- This script
- Parses `requirements.txt`
- Converts pip dependencies → conda-forge equivalents
- Generates:
```
requirements.conda.generated.yml
```
- Eliminates the need to maintain multiple conda YAML files
---
### ✅ 3. Simplified Conda Workflow
- Refactored `.github/workflows/conda-env-create.yml`:
- Uses generated environment dynamically
- Matrix testing across:
- OS: **Linux, macOS, Windows**
- Python: **3.11, 3.12, 3.13, 3.14**
- Ensures cross-platform compatibility (no shell-specific syntax)
---
### ✅ 4. Removed Redundant Environment Files
Deleted:
- `requirements.dev.conda.yml`
- `requirements.win64.conda.yml`
- `requirements.win64.dev.conda.yml`
➡️ Replaced by automated environment generation
---
### ✅ 5. Test Stability Improvements (Python 3.14)
- Updated test expectations for changed Python 3.14 error messages
- Replaced multiprocessing with threading in tests to:
- Improve CI stability
- Avoid platform-specific multiprocessing issues
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
## TIAToolbox v2.1.0 (2026-05-19) ### ✨ Major Updates and Feature Improvements - Python ≥3.11 required - Supports up to 3.14 (#1035) - Drops support for 3.10 (#1034) - Zarr v3 Support (#904) - New storage APIs (zarr.Array, LocalStore, FsspecStore) - Removal of object arrays → rectangular storage via pad_contours - Update `FsspecJsonWSIReader` to support Zarr v3 (#1049), thanks to @aacic ###⚠️ API Changes - Python requirement updated → >=3.11, \<3.15 ### 🐞 Bug Fixes and Other Changes - Fixed - Contour serialization and padding issues (Zarr compatibility) (#904) - Invalid Geometry in JSON Outputs (#1057) - Fix typographical errors in `pre-trained` documentation (#1043, #1062) ### 🛠️ Development-Related Changes - Use `uv` to set up CI environments, reduces installation time - Update instructions for `uv` install - Use `max_image` for `remove_small_objects` in `scikit-image` usage (#1048) - Improve `mypy` workflow and typing errors (#1045)
- Add Python 3.14 docker --------- Co-authored-by: Jiaqi Lv <lvjiaqi9@gmail.com>
In fcn_resnet50_unet-bcss ignore_index is defined as 0 which corresponds to the tumor class which leads to exclusion of tumor class during annotation store writing. Addresses #1068 --------- Co-authored-by: Jiaqi Lv <lvjiaqi9@gmail.com>
* 🧑💻 pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.12 → v0.15.15](astral-sh/ruff-pre-commit@v0.15.12...v0.15.15) * 📌 Update ruff version --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This PR fixes #1070. It standardizes the way tensors are moved to a device and cast to `float32` across multiple model architectures in the codebase. The updates ensure that both the device and data type are explicitly specified in a single call to `.to()`, improving code clarity and consistency. Additionally, the image preprocessing in `kongnet.py` is updated to enforce float32 precision throughout. * Updated all instances of `.to(device).type(torch.float32)` to `.to(device=device, dtype=torch.float32)` in various `infer_batch` functions, ensuring that tensors are moved to the correct device and cast to `float32` in a single step. This change affects the following files: `efficientunet_tissue_mask_model.py` [[1]](diffhunk://#diff-a8291e12107b0b9ca0f341fe353d0ac55ccb44ec721c5c6699c384a906e7755aL930-R930) `grandqc.py` [[2]](diffhunk://#diff-d729ed5d7a23c56dfb32667bd7e1419e045cc20fb136ec2a8db41785178f5f6aL630-R630) `hovernet.py` [[3]](diffhunk://#diff-0fb5e006f0559cba393f7e9f4b2eac85e9f9ff0927d26a5259400370ca0da50eL893-R893) `hovernetplus.py` [[4]](diffhunk://#diff-7c263e43928fb3549f990b4b2b63f1377da03a0396feda30da2bbc70a3b7859eL443-R443) `kongnet.py` [[5]](diffhunk://#diff-4a72853e6e2ebccee27d15fd6c0599d3b113bed534df85a17e2250575f8aa9e5L861-R862) `mapde.py` [[6]](diffhunk://#diff-5baef788a6c73d46453555207a71569b38f137d8b8e3113bc908e4b3807c2fa0L323-R323) `micronet.py` [[7]](diffhunk://#diff-fe9060463fd23bee3f1869571d3222afc5a997c2c7a0588d73d8b289a3111254L723-R723) `nuclick.py` [[8]](diffhunk://#diff-51e6d16bc1e04e7ef0f2b6ecbdfbd6ba8d15e67e7551a9a3f0219cd66f2c8044L682-R682) `sccnn.py` [[9]](diffhunk://#diff-9661859042b5ab55880371b6a64a833fd4d49e0e426cbd1a60bdf50d53b97371L418-R418) `unet.py` [[10]](diffhunk://#diff-ee0e538ba47dc8c73367638c4fbcdef48c130aaba1f1e093a0a28f9f8bcd0970L456-R456) and `vanilla.py` [[11]](diffhunk://#diff-a84858f695910c0026d8a467831bf4f1e12fe67d6f15365d6143b257f7445692L242-R244). Co-authored-by: Jiaqi Lv <jiaqilv@Jiaqis-MacBook-Pro.local>
- Update `mamba-org/setup-micromamba` `checkout`
- Fixing an issue on - Windows urlparse converts the input to str causing WSI reading to fail - Fix s3 links to test cloud ngff read
…ector` (#1074) Follow-up to the earlier multi-GPU fix. kongnet and nucleus_detector were missed and still crash on multi-GPU machines with: AttributeError: 'DataParallel' object has no attribute 'target_channels' When multi-gpu, the model is wrapped in `nn.DataParallel` / `DistributedDataParallel`, so these need to go through **the `_get_model_attr()` wrapper helper function** (or a similar approach) which unwraps the module before reading the attribute. ### Changes - `nucleus_detector.py`: read `min_distance` / `tile_shape` via the `_get_model_attr` helper instead of directly off `self.model`. - `kongnet.py`: unwrap the module before reading `target_channels` in `infer_batch`. This can't reach the helper function, so it applies the same unwrap inline. - `engine_abc.py`: simplify _get_model_attr to a single getattr-based unwrap and clarify its docstring. --- Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
Fixes a bug in MultiTaskSegmentor’s WSI probability-map vertical merging when spilling intermediate probability rows to Zarr. Previously, once a head spilled to Zarr, subsequent chunks for that same head could continue accumulating in memory instead of being appended to the Zarr. At finalization, the code preferred the Zarr array and discarded the in-memory chunks, producing truncated probability maps for only the heads that spilled resulting in the shape mismatch that was being seen by me and Jiaqi. The fix keeps hold of the opened Zarr group after the first spill and routes later chunks for that head into the same Zarr dataset. This preserves the full merged probability-map height across all heads. --------- Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
## TIAToolbox v2.1.1 (2026-06-10) ### 🐞 Bug Fixes and Other Changes - Fix errors while running engines on an `mps` device (#1073) - Fix `pre-trained.yaml` typos and errors (#1069) - Fix WSI reading on Windows (#1076) - Fix `multi-gpu` run error (#1074) - Fix broken margin behaviour while generating output using semantic segmentor and multi-task segmentor (#1067). ### 🛠️ Development-Related Changes - Add and update Python 3.14 docker image (#1066) - Pin `sphinx>=9.0.0` (#1050) - Update `ruff` versions to `0.15.15` (#1072) - Update `conda-resolve` workflow (#1077)
- Add albucore dependency - Update `matplotlib` and fix bugs
- Fix JSON output for semantic segmentation
# Conflicts: # examples/01-wsi-reading.ipynb # examples/02-stain-normalization.ipynb # examples/03-tissue-masking.ipynb # examples/04-patch-extraction.ipynb # examples/05-patch-prediction.ipynb # examples/06-semantic-segmentation.ipynb # examples/07-advanced-modeling.ipynb # examples/08-nucleus-instance-segmentation.ipynb # examples/09-multi-task-segmentation.ipynb # examples/10-wsi-registration.ipynb # examples/11-import-foundation-models.ipynb # examples/12-nucleus-detection.ipynb # examples/inference-pipelines/idars.ipynb # examples/inference-pipelines/slide-graph.ipynb # requirements/requirements.txt # tiatoolbox/models/engine/multi_task_segmentor.py # tiatoolbox/models/engine/nucleus_detector.py # tiatoolbox/utils/misc.py
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1083 +/- ##
==========================================
- Coverage 99.88% 99.88% -0.01%
==========================================
Files 85 85
Lines 11661 11659 -2
Branches 1530 1530
==========================================
- Hits 11648 11646 -2
Misses 7 7
Partials 6 6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TIAToolbox v2.1.2 (2026-06-12)
🐞 Bug Fixes and Other Changes
albucoredependency and Updatematplotlib#1081)🛠️ Development-Related Changes
albucoredependency for conda build (📌 Addalbucoredependency and Updatematplotlib#1081)matplotlibto3.10.0