From d55daf16f37094282eb151335cb80477ef792015 Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Sun, 1 Jan 2023 22:35:58 -0500 Subject: [PATCH 1/7] make modellib private --- wsinfer/{modellib => _modellib}/__init__.py | 0 wsinfer/{modellib => _modellib}/inceptionv4.py | 0 wsinfer/{modellib => _modellib}/inceptionv4_no_batchnorm.py | 0 wsinfer/{modellib => _modellib}/models.py | 0 wsinfer/{modellib => _modellib}/resnet_preact.py | 0 wsinfer/{modellib => _modellib}/run_inference.py | 0 wsinfer/{modellib => _modellib}/transforms.py | 0 wsinfer/{modellib => _modellib}/vgg16mod.py | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename wsinfer/{modellib => _modellib}/__init__.py (100%) rename wsinfer/{modellib => _modellib}/inceptionv4.py (100%) rename wsinfer/{modellib => _modellib}/inceptionv4_no_batchnorm.py (100%) rename wsinfer/{modellib => _modellib}/models.py (100%) rename wsinfer/{modellib => _modellib}/resnet_preact.py (100%) rename wsinfer/{modellib => _modellib}/run_inference.py (100%) rename wsinfer/{modellib => _modellib}/transforms.py (100%) rename wsinfer/{modellib => _modellib}/vgg16mod.py (100%) diff --git a/wsinfer/modellib/__init__.py b/wsinfer/_modellib/__init__.py similarity index 100% rename from wsinfer/modellib/__init__.py rename to wsinfer/_modellib/__init__.py diff --git a/wsinfer/modellib/inceptionv4.py b/wsinfer/_modellib/inceptionv4.py similarity index 100% rename from wsinfer/modellib/inceptionv4.py rename to wsinfer/_modellib/inceptionv4.py diff --git a/wsinfer/modellib/inceptionv4_no_batchnorm.py b/wsinfer/_modellib/inceptionv4_no_batchnorm.py similarity index 100% rename from wsinfer/modellib/inceptionv4_no_batchnorm.py rename to wsinfer/_modellib/inceptionv4_no_batchnorm.py diff --git a/wsinfer/modellib/models.py b/wsinfer/_modellib/models.py similarity index 100% rename from wsinfer/modellib/models.py rename to wsinfer/_modellib/models.py diff --git a/wsinfer/modellib/resnet_preact.py b/wsinfer/_modellib/resnet_preact.py similarity index 100% rename from wsinfer/modellib/resnet_preact.py rename to wsinfer/_modellib/resnet_preact.py diff --git a/wsinfer/modellib/run_inference.py b/wsinfer/_modellib/run_inference.py similarity index 100% rename from wsinfer/modellib/run_inference.py rename to wsinfer/_modellib/run_inference.py diff --git a/wsinfer/modellib/transforms.py b/wsinfer/_modellib/transforms.py similarity index 100% rename from wsinfer/modellib/transforms.py rename to wsinfer/_modellib/transforms.py diff --git a/wsinfer/modellib/vgg16mod.py b/wsinfer/_modellib/vgg16mod.py similarity index 100% rename from wsinfer/modellib/vgg16mod.py rename to wsinfer/_modellib/vgg16mod.py From f23930be5f2413f522409744697858472cfe6e21 Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Sun, 1 Jan 2023 22:36:08 -0500 Subject: [PATCH 2/7] expose public api in _modellib --- wsinfer/__init__.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wsinfer/__init__.py b/wsinfer/__init__.py index ecd3379..089a28f 100644 --- a/wsinfer/__init__.py +++ b/wsinfer/__init__.py @@ -1,3 +1,13 @@ +"""WSInfer is a toolkit for fast patch-based inference on whole slide images.""" from . import _version -__version__ = _version.get_versions()['version'] +from ._modellib.models import get_model_weights # noqa +from ._modellib.models import list_all_models_and_weights # noqa +from ._modellib.models import register_model_weights # noqa +from ._modellib.run_inference import run_inference # noqa +from ._modellib.run_inference import WholeSlideImagePatches # noqa +from ._modellib.transforms import PatchClassification # noqa + +__version__ = _version.get_versions()["version"] + +del _version From 7c65720f0bbe84965db87bf2f94ddbe9c1eaa581 Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Sun, 1 Jan 2023 23:01:28 -0500 Subject: [PATCH 3/7] add intersphinx and napoleon extensions --- docs/conf.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 8987b2b..0da0bef 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,7 +14,9 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ - "autoapi.extension", + "sphinx.ext.intersphinx", # for links + "sphinx.ext.napoleon", # for google style docstrings + "autoapi.extension", # to document the wsinfer api ] autoapi_type = "python" @@ -28,9 +30,15 @@ "special-members", "imported-members", ] +autoapi_ignore = ["*cli*"] + templates_path = ["_templates"] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "torch": ("https://pytorch.org/docs/stable", None), +} # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output From 972704a0791f68d497d41ea2b8f081324cf78c54 Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Sun, 1 Jan 2023 23:02:22 -0500 Subject: [PATCH 4/7] standardize pathlib imports --- wsinfer/_modellib/run_inference.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/wsinfer/_modellib/run_inference.py b/wsinfer/_modellib/run_inference.py index 404e75e..3cec0e5 100644 --- a/wsinfer/_modellib/run_inference.py +++ b/wsinfer/_modellib/run_inference.py @@ -5,7 +5,7 @@ > normalization of the color channels. """ -import pathlib +from pathlib import Path import typing import warnings @@ -25,9 +25,9 @@ ) import tqdm -from . import models +from .models import Weights -PathType = typing.Union[str, pathlib.Path] +PathType = typing.Union[str, Path] class WholeSlideImageDirectoryNotFound(FileNotFoundError): @@ -116,8 +116,8 @@ def __init__( self.um_px = float(um_px) self.transform = transform - assert pathlib.Path(wsi_path).exists(), "wsi path not found" - assert pathlib.Path(patch_path).exists(), "patch path not found" + assert Path(wsi_path).exists(), "wsi path not found" + assert Path(patch_path).exists(), "patch path not found" self.tilesource: large_image.tilesource.TileSource = large_image.getTileSource( self.wsi_path @@ -167,7 +167,7 @@ def __getitem__( def run_inference( wsi_dir: PathType, results_dir: PathType, - weights: models.Weights, + weights: Weights, batch_size: int = 32, num_workers: int = 0, ) -> None: @@ -180,12 +180,12 @@ def run_inference( Parameters ---------- - wsi_dir : str or pathlib.Path + wsi_dir : str or Path Directory containing whole slide images. This directory can *only* contain whole slide images. Otherwise, an error will be raised during model inference. - results_dir : str or pathlib.Path + results_dir : str or Path Directory containing results of patching. - weights : wsinfer.modellib.models.Weights + weights : wsinfer._modellib.models.Weights Instance of Weights including the model object and information about how to apply the model to new data. batch_size : int @@ -198,13 +198,13 @@ def run_inference( None """ # Make sure required directories exist. - wsi_dir = pathlib.Path(wsi_dir) + wsi_dir = Path(wsi_dir) if not wsi_dir.exists(): raise WholeSlideImageDirectoryNotFound(f"directory not found: {wsi_dir}") wsi_paths = list(wsi_dir.glob("*")) if not wsi_paths: raise WholeSlideImagesNotFound(wsi_dir) - results_dir = pathlib.Path(results_dir) + results_dir = Path(results_dir) if not results_dir.exists(): raise ResultsDirectoryNotFound(results_dir) @@ -237,7 +237,7 @@ def run_inference( print(f" Slide path: {wsi_path}") print(f" Patch path: {patch_path}") - slide_csv_name = pathlib.Path(wsi_path).with_suffix(".csv").name + slide_csv_name = Path(wsi_path).with_suffix(".csv").name slide_csv = model_output_dir / slide_csv_name if slide_csv.exists(): print("Output CSV exists... skipping.") From d686b9617e5d1628cf1703522eb974d066706a41 Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Sun, 1 Jan 2023 23:02:37 -0500 Subject: [PATCH 5/7] add docstring for patchclassification obj --- wsinfer/_modellib/transforms.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wsinfer/_modellib/transforms.py b/wsinfer/_modellib/transforms.py index 8cd97b5..1f329f4 100644 --- a/wsinfer/_modellib/transforms.py +++ b/wsinfer/_modellib/transforms.py @@ -31,6 +31,8 @@ class PatchClassification(torch.nn.Module): + """Transform module to process RGB patches.""" + def __init__( self, *, From 54573e3987f2f652114f1d2a61c33ed245b09b13 Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Sun, 1 Jan 2023 23:03:10 -0500 Subject: [PATCH 6/7] use private _modellib import --- wsinfer/cli/infer.py | 4 ++-- wsinfer/cli/list_models_and_weights.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wsinfer/cli/infer.py b/wsinfer/cli/infer.py index e53a19d..ee3df1a 100644 --- a/wsinfer/cli/infer.py +++ b/wsinfer/cli/infer.py @@ -11,8 +11,8 @@ import click -from ..modellib.run_inference import run_inference -from ..modellib import models +from .._modellib.run_inference import run_inference +from .._modellib import models from .._patchlib.create_dense_patch_grid import create_grid_and_save_multi_slides from .._patchlib.create_patches_fp import create_patches diff --git a/wsinfer/cli/list_models_and_weights.py b/wsinfer/cli/list_models_and_weights.py index 3a66b4e..cc75ffc 100644 --- a/wsinfer/cli/list_models_and_weights.py +++ b/wsinfer/cli/list_models_and_weights.py @@ -1,6 +1,6 @@ import click -from ..modellib import models +from .._modellib import models @click.command() From 0c3b975d2999ac63ff3924125375bfa516a66c01 Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Sun, 1 Jan 2023 23:19:08 -0500 Subject: [PATCH 7/7] fix imports for modellib --- tests/test_all.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_all.py b/tests/test_all.py index b32175d..a6d26fd 100644 --- a/tests/test_all.py +++ b/tests/test_all.py @@ -784,7 +784,7 @@ def test_cli_run_from_config(tiff_image: Path, tmp_path: Path): ], ) def test_invalid_modeldefs(modeldef, tmp_path: Path): - from wsinfer.modellib.models import Weights + from wsinfer._modellib.models import Weights path = tmp_path / "foobar.yaml" with open(path, "w") as f: @@ -795,7 +795,7 @@ def test_invalid_modeldefs(modeldef, tmp_path: Path): def test_model_registration(tmp_path: Path): - from wsinfer.modellib import models + from wsinfer._modellib import models # Test that registering duplicate weights will error. d = dict(