Skip to content

Commit

Permalink
Adding in-memory patch extraction module as a dataset with custom dat…
Browse files Browse the repository at this point in the history
…aloader, useful for CellViT
  • Loading branch information
FabianHoerst committed Mar 25, 2024
1 parent ff284c9 commit 6d2cc17
Show file tree
Hide file tree
Showing 9 changed files with 835 additions and 109 deletions.
735 changes: 735 additions & 0 deletions pathopatch/patch_extraction/dataset.py

Large diffs are not rendered by default.

26 changes: 7 additions & 19 deletions pathopatch/patch_extraction/patch_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from pathlib import Path
from shutil import rmtree
from typing import Any, Callable, List, Tuple, Union

import matplotlib
import torch

Expand Down Expand Up @@ -990,7 +989,7 @@ def process_queue(
wsi_file (Union[Path, str]): Path to the WSI file from which the patches should be extracted from
wsi_metadata (dict): Dictionary with important WSI metadata
level (int): The tile level for sampling.
polygons (List[Polygon]): Annotations of this WSI as a list of polygons (referenced to highest level of WSI).
polygons (List[Polygon]): Annotations of this WSI as a list of polygons -> on reference downsample level
If no annotations, pass an empty list [].
region_labels (List[str]): List of labels for the annotations provided as polygons parameter.
If no annotations, pass an empty list [].
Expand Down Expand Up @@ -1085,7 +1084,9 @@ def process_queue(
)
intersected_labels = [] # Zero means background
ratio = {}
patch_mask = np.zeros((tile_size, tile_size), dtype=np.uint8)
patch_mask = np.zeros(
(tile_size, tile_size), dtype=np.uint8
) # TODO: continue missing?
else:
intersected_labels, ratio, patch_mask = get_intersected_labels(
tile_size=tile_size,
Expand All @@ -1094,16 +1095,16 @@ def process_queue(
row=row,
polygons=polygons,
label_map=self.config.label_map,
min_intersection_ratio=0, # self.config.min_intersection_ratio,
min_intersection_ratio=0, # self.config.min_intersection_ratio, # TODO: check
region_labels=region_labels,
overlapping_labels=self.config.overlapping_labels,
store_masks=self.config.store_masks,
)
background_ratio = 1 - np.sum(ratio)
if len(ratio) != 0:
background_ratio = 1 - np.sum(ratio)
ratio = {k: v for k, v in zip(intersected_labels, ratio)}
if len(intersected_labels) == 0 and self.config.save_only_annotated_patches:
continue

patch_metadata = {
"row": row,
"col": col,
Expand Down Expand Up @@ -1142,19 +1143,6 @@ def process_queue(
# for scale, scale_patch in context_patches.items():
# context_patches[scale] = standardize_brightness(scale_patch)
# context_patches[scale] = standardize_brightness(scale_patch)
if self.config.normalize_stains:
patch, _, _ = macenko_normalization(
[patch],
normalization_vector_path=self.config.normalization_vector_json,
)
patch = patch[0]
for c_scale, scale_patch in context_patches.items():
c_patch, _, _ = macenko_normalization(
[scale_patch],
normalization_vector_path=self.config.normalization_vector_json,
)
context_patches[c_scale] = c_patch[0]
# context_patches[scale] = standardize_brightness(scale_patch)
if self.config.normalize_stains:
patch, _, _ = macenko_normalization(
[patch],
Expand Down
2 changes: 1 addition & 1 deletion pathopatch/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def format(self, record):


class Logger:
""" "A Logger for sys-logging and RotatingFileHandler-logging using the python logging module.
"""A Logger for sys-logging and RotatingFileHandler-logging using the python logging module.
Initialize a Logger for sys-logging and RotatingFileHandler-logging by using python logging module.
The logger can be used out of the box without any changes, but is also adaptable for specific use cases.
Expand Down
4 changes: 3 additions & 1 deletion pathopatch/utils/patch_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ def compute_interesting_patches(
mask_otsu: bool = False,
otsu_annotation: Union[List[str], str] = "object",
apply_prefilter: bool = False,
fast_mode: bool = False,
) -> Tuple[List[Tuple[int, int, float]], dict, dict]:
"""Compute interesting patches for a WSI.
Expand Down Expand Up @@ -297,6 +298,7 @@ def compute_interesting_patches(
otsu_annotation (Union[List[str], str], optional): List with annotation names or string with annotation name to use for a masked otsu thresholding.
Defaults to "object".
apply_prefilter (bool, optional): If a prefilter should be used to remove markers before applying otsu. Defaults to False.
fast_mode (bool, optional): If fast mode is used, no annotation masks for plotting are generated. Defaults to False.
Returns:
Tuple[List[Tuple[int, int, float]], dict, dict]:
Expand Down Expand Up @@ -472,7 +474,7 @@ def compute_interesting_patches(
"tissue_grid": tissue_grid,
}
mask_images_annotations = {}
if polygons is not None:
if polygons is not None and not fast_mode:
if len(polygons) != 0:
mask_images_annotations = generate_polygon_overview(
polygons=polygons,
Expand Down
Loading

0 comments on commit 6d2cc17

Please sign in to comment.