Skip to content

PyTorch Datasets

Bases: Dataset

Torch dataset yielding tile images and xywh-coordinates from reader (requires PyTorch).

Source code in histoslice/utils/_torch.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class SlideReaderDataset(Dataset):
    """Torch dataset yielding tile images and `xywh`-coordinates from reader (requires
    `PyTorch`)."""

    def __init__(
        self,
        reader: SlideReader,
        coordinates: Iterator[tuple[int, int, int, int]],
        level: int = 0,
        transform: Optional[Callable[[np.ndarray], Any]] = None,
    ) -> None:
        """Initialize SlideReaderDataset.

        Args:
            reader: `SlideReader` instance.
            coordinates: Iterator of xywh-coordinates.
            level: Slide level for reading tile image. Defaults to 0.
            transform: Transform function for tile images. Defaults to None.

        Raises:
            ImportError: Could not import `PyTorch`.
        """
        if not HAS_PYTORCH:
            raise ImportError(ERROR_PYTORCH)
        super().__init__()
        self.reader = reader
        self.coordinates = coordinates
        self.level = level
        self.transform = transform
        self.__first_sample = True

    def __len__(self) -> int:
        return len(self.coordinates)

    def __getitem__(self, index: int) -> tuple[Union[np.ndarray, Any], np.ndarray]:
        self.__first_sample = False
        xywh = self.coordinates[index]
        tile = self.reader.read_region(xywh, level=self.level)
        if self.transform is not None:
            tile = self.transform(tile)
        return tile, np.array(xywh)

__init__(reader, coordinates, level=0, transform=None)

Initialize SlideReaderDataset.

Parameters:

Name Type Description Default
reader SlideReader

SlideReader instance.

required
coordinates Iterator[tuple[int, int, int, int]]

Iterator of xywh-coordinates.

required
level int

Slide level for reading tile image. Defaults to 0.

0
transform Optional[Callable[[ndarray], Any]]

Transform function for tile images. Defaults to None.

None

Raises:

Type Description
ImportError

Could not import PyTorch.

Source code in histoslice/utils/_torch.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
def __init__(
    self,
    reader: SlideReader,
    coordinates: Iterator[tuple[int, int, int, int]],
    level: int = 0,
    transform: Optional[Callable[[np.ndarray], Any]] = None,
) -> None:
    """Initialize SlideReaderDataset.

    Args:
        reader: `SlideReader` instance.
        coordinates: Iterator of xywh-coordinates.
        level: Slide level for reading tile image. Defaults to 0.
        transform: Transform function for tile images. Defaults to None.

    Raises:
        ImportError: Could not import `PyTorch`.
    """
    if not HAS_PYTORCH:
        raise ImportError(ERROR_PYTORCH)
    super().__init__()
    self.reader = reader
    self.coordinates = coordinates
    self.level = level
    self.transform = transform
    self.__first_sample = True

Bases: Dataset

Torch dataset yielding tile images, image paths and optional labels (requires PyTorch).

Source code in histoslice/utils/_torch.py
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
class TileImageDataset(Dataset):
    """Torch dataset yielding tile images, image paths and optional labels (requires
    `PyTorch`)."""

    def __init__(
        self,
        paths: list[Union[str, Path]],
        *,
        labels: Optional[list[str]] = None,
        transform: Optional[Callable[[np.ndarray], Any]] = None,
        use_cache: bool = False,
        tile_shape: Optional[tuple[int, ...]] = None,
    ) -> None:
        """Torch dataset yielding tile images from paths (requires `PyTorch`).

        Args:
            paths: Paths to tile images.
            labels: Indexable list of labels for each path. Defaults to None.
            transform: Transform function for tile images. Defaults to None.
            use_cache: Cache each image to shared array, requires that each tile has the
                same shape. Defaults to False.
            tile_shape: Tile shape for creating a shared cache array. Defaults to None.

        Raises:
            ImportError: Could not import `PyTorch`.
            ValueError: Label and path lengths differ.
            ValueError: Tile shape is undefined but `use_cache=True`.
        """
        super().__init__()
        if not HAS_PYTORCH:
            raise ImportError(ERROR_PYTORCH)
        if labels is not None and len(paths) != len(labels):
            raise ValueError(ERROR_LENGTH_MISMATCH.format(len(paths), len(labels)))
        if use_cache and tile_shape is None:
            raise ValueError(ERROR_TILE_SHAPE)
        self.paths = paths
        self.labels = labels
        self.transform = transform
        self._use_cache = use_cache
        self._cached_indices = set()
        self._cache_array = None
        if self._use_cache:
            self._cache_array = _create_shared_array(
                num_samples=len(self.paths), shape=tile_shape
            )

    def __len__(self) -> int:
        return len(self.paths)

    def __getitem__(self, index: int) -> tuple[Union[np.ndarray, Any], str]:
        path = self.paths[index]
        if isinstance(path, Path):
            path = str(path)
        if self._use_cache:
            if index not in self._cached_indices:
                self._cache_array[index] = np.array(Image.open(path))
                self._cached_indices.add(index)
            image = self._cache_array[index]
        else:
            image = np.array(Image.open(path))
        if self.transform is not None:
            image = self.transform(image)
        labels = () if self.labels is None else self.labels[index]
        if not isinstance(labels, (tuple, list)):
            labels = (labels,)
        return image, path, *labels

__init__(paths, *, labels=None, transform=None, use_cache=False, tile_shape=None)

Torch dataset yielding tile images from paths (requires PyTorch).

Parameters:

Name Type Description Default
paths list[Union[str, Path]]

Paths to tile images.

required
labels Optional[list[str]]

Indexable list of labels for each path. Defaults to None.

None
transform Optional[Callable[[ndarray], Any]]

Transform function for tile images. Defaults to None.

None
use_cache bool

Cache each image to shared array, requires that each tile has the same shape. Defaults to False.

False
tile_shape Optional[tuple[int, ...]]

Tile shape for creating a shared cache array. Defaults to None.

None

Raises:

Type Description
ImportError

Could not import PyTorch.

ValueError

Label and path lengths differ.

ValueError

Tile shape is undefined but use_cache=True.

Source code in histoslice/utils/_torch.py
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def __init__(
    self,
    paths: list[Union[str, Path]],
    *,
    labels: Optional[list[str]] = None,
    transform: Optional[Callable[[np.ndarray], Any]] = None,
    use_cache: bool = False,
    tile_shape: Optional[tuple[int, ...]] = None,
) -> None:
    """Torch dataset yielding tile images from paths (requires `PyTorch`).

    Args:
        paths: Paths to tile images.
        labels: Indexable list of labels for each path. Defaults to None.
        transform: Transform function for tile images. Defaults to None.
        use_cache: Cache each image to shared array, requires that each tile has the
            same shape. Defaults to False.
        tile_shape: Tile shape for creating a shared cache array. Defaults to None.

    Raises:
        ImportError: Could not import `PyTorch`.
        ValueError: Label and path lengths differ.
        ValueError: Tile shape is undefined but `use_cache=True`.
    """
    super().__init__()
    if not HAS_PYTORCH:
        raise ImportError(ERROR_PYTORCH)
    if labels is not None and len(paths) != len(labels):
        raise ValueError(ERROR_LENGTH_MISMATCH.format(len(paths), len(labels)))
    if use_cache and tile_shape is None:
        raise ValueError(ERROR_TILE_SHAPE)
    self.paths = paths
    self.labels = labels
    self.transform = transform
    self._use_cache = use_cache
    self._cached_indices = set()
    self._cache_array = None
    if self._use_cache:
        self._cache_array = _create_shared_array(
            num_samples=len(self.paths), shape=tile_shape
        )