|
8 | 8 | import torch |
9 | 9 | import zarr |
10 | 10 |
|
| 11 | +from tiatoolbox.annotation.storage import SQLiteStore |
11 | 12 | from tiatoolbox.models import NucleusInstanceSegmentor |
12 | 13 | from tiatoolbox.wsicore import WSIReader |
13 | 14 |
|
14 | 15 | device = "cuda:0" if torch.cuda.is_available() else "cpu" |
15 | 16 |
|
16 | 17 |
|
17 | | -def test_functionality_patch_mode( |
| 18 | +def test_functionality_patch_mode( # noqa: PLR0915 |
18 | 19 | remote_sample: Callable, track_tmp_path: Path |
19 | 20 | ) -> None: |
20 | 21 | """Patch mode functionality test for nuclei instance segmentor.""" |
@@ -138,43 +139,63 @@ def test_functionality_patch_mode( |
138 | 139 | for a, b in zip(output["type"][1], output_["type"][1], strict=False) |
139 | 140 | ) |
140 | 141 |
|
141 | | - |
142 | | -def test_functionality_patch_mode_anns( |
143 | | - remote_sample: Callable, track_tmp_path: Path |
144 | | -) -> None: |
145 | | - """Patch mode functionality test for nuclei instance segmentor.""" |
146 | | - mini_wsi_svs = Path(remote_sample("wsi4_1k_1k_svs")) |
147 | | - mini_wsi = WSIReader.open(mini_wsi_svs) |
148 | | - size = (256, 256) |
149 | | - resolution = 0.25 |
150 | | - units: Final = "mpp" |
151 | | - patch1 = mini_wsi.read_rect( |
152 | | - location=(0, 0), |
153 | | - size=size, |
154 | | - resolution=resolution, |
155 | | - units=units, |
156 | | - ) |
157 | | - patch2 = mini_wsi.read_rect( |
158 | | - location=(512, 512), |
159 | | - size=size, |
160 | | - resolution=resolution, |
161 | | - units=units, |
162 | | - ) |
163 | | - |
164 | | - # Test dummy input, should result in no output segmentation |
165 | | - patch3 = np.zeros_like(patch1) |
166 | | - |
167 | | - patches = np.stack(arrays=[patch1, patch2, patch3], axis=0) |
168 | | - |
169 | 142 | inst_segmentor = NucleusInstanceSegmentor( |
170 | 143 | batch_size=1, |
171 | 144 | num_workers=0, |
172 | 145 | model="hovernet_fast-pannuke", |
173 | 146 | ) |
174 | | - _ = inst_segmentor.run( |
| 147 | + output = inst_segmentor.run( |
175 | 148 | images=patches, |
176 | 149 | patch_mode=True, |
177 | 150 | device=device, |
178 | 151 | output_type="annotationstore", |
179 | 152 | save_dir=track_tmp_path / "patch_output_annotationstore", |
180 | 153 | ) |
| 154 | + |
| 155 | + assert output[0] == track_tmp_path / "patch_output_annotationstore" / "0.db" |
| 156 | + assert len(output) == 3 |
| 157 | + store_ = SQLiteStore.open(output[0]) |
| 158 | + annotations_ = store_.values() |
| 159 | + annotations_geometry_type = [ |
| 160 | + str(annotation_.geometry_type) for annotation_ in annotations_ |
| 161 | + ] |
| 162 | + assert "Polygon" in annotations_geometry_type |
| 163 | + |
| 164 | + annotations_list = list(annotations_) |
| 165 | + ann_properties = [ann.properties for ann in annotations_list] |
| 166 | + |
| 167 | + result = {} |
| 168 | + for d in ann_properties: |
| 169 | + for key, value in d.items(): |
| 170 | + result.setdefault(key, []).append(value) |
| 171 | + |
| 172 | + polygons = [ann.geometry for ann in annotations_list] |
| 173 | + result["contour"] = [list(poly.exterior.coords) for poly in polygons] |
| 174 | + |
| 175 | + assert all( |
| 176 | + np.array_equal(a, b) |
| 177 | + for a, b in zip(result["box"], output_["box"][0], strict=False) |
| 178 | + ) |
| 179 | + |
| 180 | + assert all( |
| 181 | + np.array_equal(a, b) |
| 182 | + for a, b in zip(result["centroid"], output_["centroid"][0], strict=False) |
| 183 | + ) |
| 184 | + |
| 185 | + assert all( |
| 186 | + np.array_equal(a, b) |
| 187 | + for a, b in zip(result["prob"], output_["prob"][0], strict=False) |
| 188 | + ) |
| 189 | + |
| 190 | + assert all( |
| 191 | + np.array_equal(a, b) |
| 192 | + for a, b in zip(result["type"], output_["type"][0], strict=False) |
| 193 | + ) |
| 194 | + |
| 195 | + assert all( |
| 196 | + np.array_equal( |
| 197 | + np.array(a[:-1], dtype=int), # discard last point |
| 198 | + np.array(b, dtype=int), |
| 199 | + ) |
| 200 | + for a, b in zip(result["contour"], output_["contour"][0], strict=False) |
| 201 | + ) |
0 commit comments