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

[TEST] add test for WholeSlideImagePatches class #151

Open
kaczmarj opened this issue Jul 18, 2023 · 0 comments
Open

[TEST] add test for WholeSlideImagePatches class #151

kaczmarj opened this issue Jul 18, 2023 · 0 comments
Labels
help wanted Extra attention is needed test Create a test for this issue

Comments

@kaczmarj
Copy link
Member

kaczmarj commented Jul 18, 2023

add tests for the torch dataset child class WholeSlideImagePatches.

class WholeSlideImagePatches(torch.utils.data.Dataset):
"""Dataset of one whole slide image.
This object retrieves patches from a whole slide image on the fly.
Parameters
----------
wsi_path : str, Path
Path to whole slide image file.
patch_path : str, Path
Path to npy file with coordinates of input image.
um_px : float
Scale of the resulting patches. For example, 0.5 for ~20x magnification.
patch_size : int
The size of patches in pixels.
transform : callable, optional
A callable to modify a retrieved patch. The callable must accept a
PIL.Image.Image instance and return a torch.Tensor.
roi_path : str, Path, optional
Path to GeoJSON file that outlines the region of interest (ROI). Only patches
within the ROI(s) will be used.
"""
def __init__(
self,
wsi_path: str | Path,
patch_path: str | Path,
um_px: float,
patch_size: int,
transform: Optional[Callable[[Image.Image], torch.Tensor]] = None,
roi_path: Optional[str | Path] = None,
):
self.wsi_path = wsi_path
self.patch_path = patch_path
self.um_px = float(um_px)
self.patch_size = int(patch_size)
self.transform = transform
self.roi_path = roi_path
assert Path(wsi_path).exists(), "wsi path not found"
assert Path(patch_path).exists(), "patch path not found"
if roi_path is not None:
assert Path(roi_path).exists(), "roi path not found"
self.patches = _read_patch_coords(self.patch_path)
# If an ROI is given, keep patches that intersect it.
if self.roi_path is not None:
self.patches = _filter_patches_in_rois(
geojson_path=self.roi_path, coords=self.patches
)
if self.patches.shape[0] == 0:
raise ValueError("No patches left after taking intersection with ROI")
assert self.patches.ndim == 2, "expected 2D array of patch coordinates"
# x, y, width, height
assert self.patches.shape[1] == 4, "expected second dimension to have len 4"
def worker_init(self, *_):
self.slide = WSI(self.wsi_path)
def __len__(self):
return self.patches.shape[0]
def __getitem__(
self, idx: int
) -> Tuple[Union[Image.Image, torch.Tensor], torch.Tensor]:
coords: Sequence[int] = self.patches[idx]
assert len(coords) == 4, "expected 4 coords (minx, miny, width, height)"
minx, miny, width, height = coords
patch_im = self.slide.read_region(
location=(minx, miny), level=0, size=(width, height)
)
patch_im = patch_im.convert("RGB")
if self.transform is not None:
patch_im = self.transform(patch_im)
return patch_im, torch.as_tensor([minx, miny, width, height])

you may want to create your own reference tiff image, as in

def tiff_image(tmp_path: Path) -> Path:
x = np.empty((4096, 4096, 3), dtype="uint8")
x[...] = [160, 32, 240] # rgb for purple
path = Path(tmp_path / "images" / "purple.tif")
path.parent.mkdir(exist_ok=True)
tifffile.imwrite(
path,
data=x,
compression="zlib",
tile=(256, 256),
# 0.25 micrometers per pixel.
resolution=(40_000, 40_000),
resolutionunit=tifffile.RESUNIT.CENTIMETER,
)
return path

@kaczmarj kaczmarj added the test Create a test for this issue label Jul 18, 2023
@kaczmarj kaczmarj added the help wanted Extra attention is needed label Feb 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed test Create a test for this issue
Projects
None yet
Development

No branches or pull requests

1 participant