Skip to content

Commit abbd2a3

Browse files
authored
🤖 AI Suggested Fixes (#1046)
This PR updates documentation and improves code clarity across the project. It revises Python version references to reflect supported/testing versions, fixes typos and formatting issues, and enhances several docstrings. Minor code quality improvements include clearer error messages, corrected variable names, and removal of redundant statements. The NuClick post‑processing logic is updated for compatibility with newer scikit‑image behavior. No functional or API-breaking changes are introduced.
1 parent 44558a8 commit abbd2a3

10 files changed

Lines changed: 53 additions & 39 deletions

File tree

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Before you submit a pull request, check that it meets these guidelines:
9898

9999
1. The pull request should include tests.
100100
2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the pull request description.
101-
3. The pull request should work for Python 3.11, 3.12, and 3.13 and for PyPy. Check https://github.com/TissueImageAnalytics/tiatoolbox/actions/workflows/python-package.yml and make sure that the tests pass for all supported Python versions.
101+
3. The pull request should work for all Python versions supported by the project (including CPython and PyPy). Check https://github.com/TissueImageAnalytics/tiatoolbox/actions/workflows/python-package.yml and make sure that the tests pass for all supported Python versions.
102102

103103
Tips
104104
----

docs/installation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ MacPorts
5959
Installing Stable Release
6060
=========================
6161

62-
Please note that TIAToolbox is tested for Python versions 3.11, 3.12, and 3.13.
62+
Please note that TIAToolbox is currently tested with Python versions 3.11, 3.12, and 3.13. For the full range of supported Python versions, please refer to the package metadata (for example, the ``python_requires`` setting in ``setup.py`` or ``pyproject.toml``)
6363

6464
Recommended
6565
-----------

docs/pretrained.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ The input output configuration is as follows:
173173
{'units': 'mpp', 'resolution': 0.25},
174174
{'units': 'mpp', 'resolution': 0.25}
175175
],
176-
margin=128
177-
tile_shape=[1024, 1024]
176+
margin=128,
177+
tile_shape=[1024, 1024],
178178
patch_input_shape=(256, 256),
179179
patch_output_shape=(164, 164),
180180
stride_shape=(164, 164),
@@ -256,8 +256,8 @@ The input output configuration is as follows:
256256
{'units': 'mpp', 'resolution': 0.25},
257257
{'units': 'mpp', 'resolution': 0.25}
258258
],
259-
margin=128
260-
tile_shape=[1024, 1024]
259+
margin=128,
260+
tile_shape=[1024, 1024],
261261
patch_input_shape=(270, 270),
262262
patch_output_shape=(80, 80),
263263
stride_shape=(80, 80),
@@ -289,7 +289,7 @@ The input output configuration is as follows:
289289
output_resolutions=[
290290
{'units': 'mpp', 'resolution': 0.25}
291291
],
292-
tile_shape=[2048, 2048]
292+
tile_shape=[2048, 2048],
293293
patch_input_shape=(252, 252),
294294
patch_output_shape=(252, 252),
295295
stride_shape=(150, 150),
@@ -323,8 +323,8 @@ The input output configuration is as follows:
323323
{'units': 'mpp', 'resolution': 0.25},
324324
{'units': 'mpp', 'resolution': 0.25}
325325
],
326-
margin=128
327-
tile_shape=[1024, 1024]
326+
margin=128,
327+
tile_shape=[1024, 1024],
328328
patch_input_shape=(270, 270),
329329
patch_output_shape=(80, 80),
330330
stride_shape=(80, 80),

tiatoolbox/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
__version__ = "2.0.1"
2020

2121
# This will set the tiatoolbox external data
22-
# default to be the user home folder, should work on both Window and Unix/Linux
22+
# default to be the user home folder, should work on both Windows and Unix/Linux
2323
# C:\Users\USER\.tiatoolbox
2424
# /home/USER/.tiatoolbox
2525

@@ -113,7 +113,10 @@ def read_registry_files(path_to_registry: str | Path) -> dict:
113113
def _lazy_import(name: str, module_location: Path) -> ModuleType:
114114
spec = importlib.util.spec_from_file_location(name, module_location)
115115
if spec is None or spec.loader is None:
116-
raise ModuleNotFoundError(name=name, path=str(module_location))
116+
msg = f"Cannot find module {name!r} at path {module_location}"
117+
raise ModuleNotFoundError(
118+
msg,
119+
)
117120
loader = importlib.util.LazyLoader(spec.loader)
118121
spec.loader = loader
119122
module = importlib.util.module_from_spec(spec)

tiatoolbox/annotation/storage.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def to_wkb(self: Annotation) -> bytes:
230230
return copy.copy(self.wkb)
231231

232232
def to_wkt(self: Annotation) -> str:
233-
"""Returns the geometry as Well-Know Text (WKT).
233+
"""Returns the geometry as Well-Known Text (WKT).
234234
235235
Returns:
236236
Annotation:
@@ -1877,7 +1877,7 @@ def _load_cases(
18771877
@classmethod
18781878
def from_geojson(
18791879
cls: type[AnnotationStore],
1880-
fp: IO | str,
1880+
fp: IO | str | Path,
18811881
scale_factor: tuple[float, float] = (1, 1),
18821882
origin: tuple[float, float] = (0, 0),
18831883
transform: Callable[[Annotation], Annotation] | None = None,
@@ -1897,7 +1897,7 @@ def from_geojson(
18971897
A function to apply to each annotation after loading. Should take an
18981898
annotation as input and return an annotation. Defaults to None.
18991899
Intended to facilitate modifying the way annotations are loaded to
1900-
accomodate the specifics of different annotation formats.
1900+
accommodate the specifics of different annotation formats.
19011901
19021902
Returns:
19031903
AnnotationStore:
@@ -1939,7 +1939,7 @@ def transform(annotation: Annotation) -> Annotation:
19391939

19401940
def add_from_geojson(
19411941
self: AnnotationStore,
1942-
fp: IO | str,
1942+
fp: IO | str | Path,
19431943
scale_factor: tuple[float, float] = (1, 1),
19441944
origin: tuple[float, float] = (0, 0),
19451945
transform: Callable[[Annotation], Annotation] = lambda x: x,

tiatoolbox/models/architecture/nuclick.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def get_block(
108108
out_channels: int,
109109
kernel_size: int | tuple[int, int],
110110
strides: IntPair,
111-
dilation_rate: int or IntPair,
111+
dilation_rate: int | IntPair,
112112
activation: str,
113113
*,
114114
do_batchnorm: bool,
@@ -306,7 +306,7 @@ def __init__(
306306
num_output_channels,
307307
kernel_size=kernel_size,
308308
strides=strides,
309-
activation="None",
309+
activation=None,
310310
use_bias=use_bias,
311311
dilation_rate=dilation_rate,
312312
do_batchnorm=True,
@@ -316,7 +316,7 @@ def __init__(
316316
num_output_channels,
317317
kernel_size=kernel_size,
318318
strides=strides,
319-
activation="None",
319+
activation=None,
320320
use_bias=use_bias,
321321
dilation_rate=dilation_rate,
322322
do_batchnorm=True,
@@ -599,27 +599,39 @@ def postproc(
599599
"""Post-processing.
600600
601601
Args:
602-
preds (ndarray): list of prediction output of each patch and
602+
preds (ndarray):
603+
List of prediction output of each patch and
603604
assumed to be in the order of (no.patch, h, w) (match with the output
604605
of `infer_batch`).
605-
thresh (float): Threshold value. If a pixel has a predicted value larger
606+
thresh (float):
607+
Threshold value. If a pixel has a predicted value larger
606608
than the threshold, it will be classified as nuclei.
607-
min_size (int): The smallest allowable object size.
608-
min_hole_size (int): The maximum area, in pixels, of a contiguous hole
609+
min_size (int):
610+
The smallest allowable object size (objects with
611+
fewer pixels than this will be removed).
612+
min_hole_size (int):
613+
The maximum area, in pixels, of a contiguous hole
609614
that will be filled.
610-
do_reconstruction (bool): Whether to perform a morphological reconstruction
615+
do_reconstruction (bool):
616+
Whether to perform a morphological reconstruction
611617
of an image.
612-
nuc_points (ndarray): In the order of (no.patch, h, w).
618+
nuc_points (ndarray):
619+
In the order of (no.patch, h, w).
613620
In each patch, The pixel that has been 'clicked' is set to 1 and the
614621
rest pixels are set to 0.
615622
616623
Returns:
617-
masks (ndarray): pixel-wise nuclei instance segmentation
618-
prediction, shape:(no.patch, h, w).
624+
masks (ndarray):
625+
Pixel-wise nuclei instance segmentation prediction,
626+
shape:(no.patch, h, w).
619627
620628
"""
621629
masks = preds > thresh
622-
masks = remove_small_objects(masks, max_size=min_size - 1)
630+
# For scikit-image >=0.26.0, `remove_small_objects` uses `max_size` to
631+
# specify the largest object size to be removed. To keep objects with
632+
# at least `min_size` pixels, we remove objects with size <= min_size - 1.
633+
max_size = max(min_size - 1, 0)
634+
masks = remove_small_objects(masks, max_size=max_size)
623635
masks = remove_small_holes(masks, area_threshold=min_hole_size)
624636
if do_reconstruction:
625637
for i in range(len(masks)):

tiatoolbox/models/engine/engine_abc.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,6 @@ def infer_patches(
536536

537537
if self.return_labels:
538538
keys.append("labels")
539-
labels = []
540539

541540
if return_coordinates:
542541
keys.append("coordinates")
@@ -1208,7 +1207,6 @@ def _validate_input_numbers(
12081207
raise ValueError(
12091208
msg,
12101209
)
1211-
return
12121210

12131211
def _update_run_params(
12141212
self: EngineABC,

tiatoolbox/models/engine/multi_task_segmentor.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class MultiTaskSegmentorRunParams(SemanticSegmentorRunParams, total=False):
210210
Shape of output patches (height, width).
211211
return_labels (bool):
212212
Whether to return labels with predictions.
213-
return_predictions (tuple(bool, ...):
213+
return_predictions (tuple[bool, ...]):
214214
Whether to return array predictions for individual tasks.
215215
return_probabilities (bool):
216216
Whether to return per-class probabilities.
@@ -533,7 +533,7 @@ def infer_wsi(
533533
Shape of output patches (height, width).
534534
return_labels (bool):
535535
Whether to return labels with predictions.
536-
return_predictions (tuple(bool, ...):
536+
return_predictions (tuple[bool, ...]):
537537
Whether to return array predictions for individual tasks.
538538
return_probabilities (bool):
539539
Whether to return per-class probabilities.
@@ -783,7 +783,7 @@ def post_process_patches( # skipcq: PYL-R0201
783783
Shape of output patches (height, width).
784784
return_labels (bool):
785785
Whether to return labels with predictions.
786-
return_predictions (tuple(bool, ...):
786+
return_predictions (tuple[bool, ...]):
787787
Whether to return array predictions for individual tasks.
788788
return_probabilities (bool):
789789
Whether to return per-class probabilities.
@@ -893,7 +893,7 @@ def post_process_wsi( # skipcq: PYL-R0201
893893
Shape of output patches (height, width).
894894
return_labels (bool):
895895
Whether to return labels with predictions.
896-
return_predictions (tuple(bool, ...):
896+
return_predictions (tuple[bool, ...]):
897897
Whether to return array predictions for individual tasks.
898898
return_probabilities (bool):
899899
Whether to return per-class probabilities.

tiatoolbox/utils/misc.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def load_stain_matrix(stain_matrix_input: np.ndarray | PathLike) -> np.ndarray:
234234
235235
"""
236236
if isinstance(stain_matrix_input, (str, Path)):
237-
_, __, suffixes = split_path_name_ext(stain_matrix_input)
237+
_dir, _file, suffixes = split_path_name_ext(stain_matrix_input)
238238
if suffixes[-1] not in [".csv", ".npy"]:
239239
msg = (
240240
"If supplying a path to a stain matrix, use either a npy or a csv file"
@@ -914,12 +914,12 @@ def get_bounding_box(img: np.ndarray) -> np.ndarray:
914914
rows = np.any(img, axis=1)
915915
cols = np.any(img, axis=0)
916916
r_min, r_max = np.where(rows)[0][[0, -1]]
917-
c_min, cmax = np.where(cols)[0][[0, -1]]
917+
c_min, c_max = np.where(cols)[0][[0, -1]]
918918
# due to python indexing, need to add 1 to max
919919
# else accessing will be 1px in the box, not out
920920
r_max += 1
921-
cmax += 1
922-
return np.array([c_min, r_min, cmax, r_max])
921+
c_max += 1
922+
return np.array([c_min, r_min, c_max, r_max])
923923

924924

925925
def string_to_tuple(in_str: str) -> tuple[str, ...]:

tiatoolbox/visualization/tileserver.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,6 @@ def update_renderer(self: TileServer, prop: str) -> str:
470470
if val in ["None", "null"]:
471471
val = None
472472
self.renderers[session_id].__setattr__(prop, val)
473-
self.renderers[session_id].__setattr__(prop, val)
474473
if prop == "blur_radius":
475474
self.overlaps[session_id] = int(1.5 * val)
476475
self.get_ann_layer(session_id).overlap = self.overlaps[session_id]
@@ -633,8 +632,10 @@ def unpack_qupath(ann: Annotation) -> Annotation:
633632
return ann
634633

635634
sq = SQLiteStore.from_geojson(overlay_path, transform=unpack_qupath)
636-
elif overlay_path.suffix == ".dat":
635+
636+
if overlay_path.suffix == ".dat":
637637
sq = store_from_dat(overlay_path)
638+
638639
if overlay_path.suffix == ".db":
639640
sq = SQLiteStore(overlay_path, auto_commit=False)
640641
else:

0 commit comments

Comments
 (0)