Skip to content

Commit

Permalink
Changing the hardware setup (the image loader) for a more fine graine…
Browse files Browse the repository at this point in the history
…d image loader selection
  • Loading branch information
FabianHoerst committed Oct 23, 2024
1 parent 919c1d0 commit 647a6d5
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 86 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ test_database/3DHistech
test_database/XiaLab
test_database/dicom_files
test_database/dicom_leica
dpyproject.toml
test_database/dicom_leica_anonymized
test_database/dicom_wsidicomizer
mask_ihc.ipynb
pyproject.toml
test_output
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ In our Pre-Processing pipeline, we are able to extract quadratic patches from de
[--apply_prefilter APPLY_PREFILTER]
[--log_path LOG_PATH]
[--log_level {critical,error,warning,info,debug}]
[--hardware_selection {cucim,openslide}]
[--hardware_selection {cucim,openslide,wsidicom}]
[--wsi_magnification WSI_MAGNIFICATION]
[--wsi_mpp WSI_MPP]

Expand Down Expand Up @@ -256,9 +256,9 @@ In our Pre-Processing pipeline, we are able to extract quadratic patches from de
--log_level {critical,error,warning,info,debug}
Set the logging level. Options are ['critical', 'error',
'warning', 'info', 'debug'] (default: None)
--hardware_selection {cucim,openslide}
--hardware_selection {cucim,openslide,wsidicom}
Select hardware device (just if available, otherwise always
cucim). Defaults to cucim. (default: None)
cucim). Defaults to None. (default: None)
--wsi_magnification WSI_MAGNIFICATION
Manual WSI magnification, but just applies if metadata
cannot be derived from OpenSlide (e.g., for .tiff files).
Expand Down Expand Up @@ -370,6 +370,11 @@ In our Pre-Processing pipeline, we are able to extract quadratic patches from de
```
</details>
## A Note on DICOM
If you use DICOM files directly converted by vendors, first try to use OpenSlide which is the default setting. If this is slow, you could try to enforce the `wsidicom` image loader by setting the hardware to "wsidicom" (`hardware_selection: wsi_dicom`or `--hardware_selection wsidicom`) and check if this works.
If you converted files to DICOM with the `wsidicomizer` tool as explained below, please always set the image loader to "wsidicom" (`hardware_selection: wsi_dicom`or `--hardware_selection wsidicom`).
## Examples
An example notebook is given [here](PathoPatch.ipynb):
<a href="https://colab.research.google.com/github/TIO-IKIM/PathoPatcher/blob/main/PathoPatch.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
Expand Down
10 changes: 6 additions & 4 deletions docs/README_pypi.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ wsi_extraction [-h]
[--apply_prefilter APPLY_PREFILTER]
[--log_path LOG_PATH]
[--log_level {critical,error,warning,info,debug}]
[--hardware_selection {cucim,openslide}]
[--hardware_selection {cucim,openslide,wsidicom}]
[--wsi_magnification WSI_MAGNIFICATION]
[--wsi_mpp WSI_MPP]

Expand Down Expand Up @@ -230,9 +230,9 @@ options:
--log_level {critical,error,warning,info,debug}
Set the logging level. Options are ['critical', 'error',
'warning', 'info', 'debug'] (default: None)
--hardware_selection {cucim,openslide}
Select hardware device (just if available, otherwise always
cucim). Defaults to cucim. (default: None)
--hardware_selection {cucim,openslide,wsidicom}
Select hardware device (just if available, otherwise always
cucim). Defaults to None. (default: None)
--wsi_magnification WSI_MAGNIFICATION
Manual WSI magnification, but just applies if metadata
cannot be derived from OpenSlide (e.g., for .tiff files).
Expand Down Expand Up @@ -306,6 +306,8 @@ WSI_Name
├── patch_metadata.json # Patch metadata of WSI merged in one file
└── thumbnail.png # WSI thumbnail
```
## Further information
For more information, check out the git.
## License
Expand Down
2 changes: 1 addition & 1 deletion examples/patch_extraction.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ filter_patches: # Post-extraction patch filtering to sort out arte
# logging
log_path: # Path where log files should be stored. Otherwise, log files are stored in the output folder. [str][Optional, defaults to None]
log_level: # Set the logging level. [str][Optional, defaults to info]
hardware_selection: # Select hardware device (just if available, otherwise always cucim). [str] [Optional, defaults to cucim]
hardware_selection: # Select hardware device (just if available, otherwise always cucim). Options are openslide,cucim,wsidicom [str] [Optional, defaults to cucim]
8 changes: 4 additions & 4 deletions pathopatch/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class PreProcessingConfig(BaseModel):
apply_prefilter (bool, optional): Pre-extraction mask filtering to remove marker from mask before applying otsu. Defaults to False.
log_path (str, optional): Path where log files should be stored. Otherwise, log files are stored in the output folder. Defaults to None.
log_level (str, optional): Set the logging level. Defaults to "info".
hardware_selection (str, optional): Select hardware device (just if available, otherwise always cucim). Defaults to "cucim".
hardware_selection (str, optional): Select hardware device (just if available, otherwise always cucim). Defaults to None.
wsi_properties (dict, optional): Dictionary with manual WSI metadata, but just applies if metadata cannot be derived from OpenSlide (e.g., for .tiff files). Supported keys are slide_mpp and magnification
Raises:
Expand Down Expand Up @@ -209,7 +209,7 @@ class PreProcessingConfig(BaseModel):
# other
log_path: Optional[str]
log_level: Optional[str] = "info"
hardware_selection: Optional[str] = "cucim"
hardware_selection: Optional[str] = None
wsi_properties: Optional[dict]

def __init__(__pydantic_self__, **data: Any) -> None:
Expand Down Expand Up @@ -577,8 +577,8 @@ def __init__(self) -> None:
parser.add_argument(
"--hardware_selection",
type=str,
choices=["cucim", "openslide"],
help="Select hardware device (just if available, otherwise always cucim). Defaults to cucim.",
choices=["cucim", "openslide", "wsidicom"],
help="Select hardware device (just if available, otherwise always cucim). Defaults to None.",
)
parser.add_argument(
"--wsi_magnification",
Expand Down
54 changes: 41 additions & 13 deletions pathopatch/patch_extraction/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
from PIL import Image
from pathopatch.utils.exceptions import WrongParameterException
from pathopatch.wsi_interfaces.openslide_deepzoom import DeepZoomGeneratorOS
from pathopatch.wsi_interfaces.wsidicomizer_openslide import (
DicomSlide,
DeepZoomGeneratorDicom,
)
from pathopatch.utils.patch_util import (
calculate_background_ratio,
compute_interesting_patches,
Expand Down Expand Up @@ -280,20 +284,44 @@ def __init__(

def _set_hardware(self) -> None:
"""Either load CuCIM (GPU-accelerated) or OpenSlide"""
if module_exists("cucim", error="ignore"):
self.logger.debug("Using CuCIM")
from cucim import CuImage
wsi_file = Path(self.config.wsi_path)
if wsi_file.is_dir():
if len(list(wsi_file.glob("*.dcm"))) != 0:
self.logger.debug("Detected dicom files")
try:
dcm_files = list(wsi_file.glob("*.dcm"))
dcm_files = [(f, os.path.getsize(f.resolve())) for f in dcm_files]
dcm_files = sorted(dcm_files, key=lambda x: x[1], reverse=True)
OpenSlide(str(dcm_files[0][0]))
wsi_file = dcm_files[0][0]
self.image_loader = OpenSlide
self.deepzoomgenerator = DeepZoomGeneratorOS
self.slide_metadata_loader = OpenSlide
except:
try:
DicomSlide(wsi_file)
except Exception as e:
raise e
self.deepzoomgenerator = DeepZoomGeneratorDicom
self.image_loader = DicomSlide
self.slide_metadata_loader = DicomSlide
else:
if module_exists("cucim", error="ignore"):
self.logger.debug("Using CuCIM")
from cucim import CuImage

from pathopatch.wsi_interfaces.cucim_deepzoom import (
DeepZoomGeneratorCucim,
)
from pathopatch.wsi_interfaces.cucim_deepzoom import (
DeepZoomGeneratorCucim,
)

self.deepzoomgenerator = DeepZoomGeneratorCucim
self.image_loader = CuImage
else:
self.logger.debug("Using OpenSlide")
self.deepzoomgenerator = DeepZoomGeneratorOS
self.image_loader = OpenSlide
self.deepzoomgenerator = DeepZoomGeneratorCucim
self.image_loader = CuImage
self.slide_metadata_loader = OpenSlide
else:
self.logger.debug("Using OpenSlide")
self.deepzoomgenerator = DeepZoomGeneratorOS
self.image_loader = OpenSlide
self.slide_metadata_loader = OpenSlide

def _set_tissue_detector(self) -> None:
"""Set up the tissue detection model and transformations.
Expand Down Expand Up @@ -364,7 +392,7 @@ def _prepare_slide(
* List[Polygon]: List of polygons, downsampled to the target level
* List[str]: List of region labels
"""
self.slide_openslide = OpenSlide(str(self.config.wsi_path))
self.slide_openslide = self.slide_metadata_loader(str(self.config.wsi_path))
self.slide = self.image_loader(str(self.config.wsi_path))

if (
Expand Down
Loading

0 comments on commit 647a6d5

Please sign in to comment.