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

Feat/qupath #209

Merged
merged 14 commits into from
Jan 5, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
added qupath flag in CLI tool, create project if flag is true
swaradgat19 committed Dec 7, 2023
commit 2a64d4a2a0bdd2414f5d4f9264a5a29a80e44041
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -172,5 +172,9 @@ cython_debug/
# Version
/wsinfer/_version.py

#QuPath Project
/QuPathProject
*.backup

# Extras
.DS_Store
11 changes: 11 additions & 0 deletions wsinfer/cli/infer.py
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
from ..modellib.run_inference import run_inference
from ..patchlib import segment_and_patch_directory_of_slides
from ..write_geojson import write_geojsons
from ..qupath import make_qupath_project


def _num_cpus() -> int:
@@ -252,6 +253,13 @@ def get_stdout(args: list[str]) -> str:
help="JIT-compile the model and apply inference optimizations. This imposes a"
" startup cost but may improve performance overall.",
)
@click.option(
"--qupath",
is_flag=True,
default=False,
show_default=True,
help="Creates a QuPath project",
)
def run(
ctx: click.Context,
*,
@@ -263,6 +271,7 @@ def run(
batch_size: int,
num_workers: int = 0,
speedup: bool = False,
qupath: bool = False
) -> None:
"""Run model inference on a directory of whole slide images.

@@ -378,3 +387,5 @@ def run(

csvs = list((results_dir / "model-outputs-csv").glob("*.csv"))
write_geojsons(csvs, results_dir, num_workers)
if qupath:
make_qupath_project(wsi_dir, results_dir)
74 changes: 74 additions & 0 deletions wsinfer/qupath.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from __future__ import annotations

import sys
import json
from pathlib import Path
import subprocess
import os
import paquo
from natsort import natsorted #add in dependencies?
os.environ['PAQUO_QUPATH_DIR'] = '/home/sggat/QuPath'

def add_image_and_geojson(
qupath_proj: QuPathProject, *, image_path: Path | str, geojson_path: Path | str
) -> None:
with open(geojson_path) as f:
# FIXME: check that a 'features' key is present and raise a useful error if not
geojson_features = json.load(f)["features"]

entry = qupath_proj.add_image(image_path)
# FIXME: test that the 'load_geojson' function exists. If not, raise a useful error
entry.hierarchy.load_geojson(geojson_features) # type: ignore


# Store a list of matched slides and geojson files. Linking the slides and geojson in
# this way prevents a potential mismatch by simply listing directories and relying on
# the order to be the same.


def make_qupath_project(wsi_dir, results_dir):

try:
from paquo.projects import QuPathProject
except Exception as e:
print(
'''QuPath is required to use this functionality but it cannot be found.
If QuPath is installed, please use define the environment variable
PAQUO_QUPATH_DIR with the location of the QuPath installation.
If QuPath is not installed, please install it from https://qupath.github.io/.''')
sys.exit(1)

print("Found QuPath successfully!")
QUPATH_PROJECT_DIRECTORY = "QuPathProject"

csv_files = list((results_dir/"model-outputs-csv").glob("*.csv"))
slides_and_geojsons = []

for csv_file in csv_files:
file_name = csv_file.stem

json_file = results_dir/"model-outputs-geojson"/ (file_name + ".json")
image_file = wsi_dir/(file_name + ".svs")

if json_file.exists() and image_file.exists():
matching_pair = (image_file, json_file)
slides_and_geojsons.append(matching_pair)
else:
print(f"Skipping CSV: {csv_file.name} (No corresponding JSON)")

# csv_list = natsorted([str(file) for file in wsi_dir.iterdir() if file.is_file()])
# json_list = natsorted([str(file) for file in Path(f"{results_dir}/model-outputs-geojson").iterdir() if file.is_file()])

# slides_and_geojsons = [
# (csv, json) for csv, json in zip(csv_list, json_list)
# ]

print(slides_and_geojsons)

with QuPathProject(QUPATH_PROJECT_DIRECTORY, mode="w") as qp:
for image_path, geojson_path in slides_and_geojsons:
try:
add_image_and_geojson(qp, image_path=image_path, geojson_path=geojson_path)
except Exception as e:
print(f"Failed to add image/geojson with error:: {e}")
print("Successfully created QuPath Project!")