Skip to content

Commit

Permalink
fix: Add make_valid parameter to contoursToPolygons function as curre…
Browse files Browse the repository at this point in the history
…nt breaks conflicts resolving in nuclei seg, correct read_pathologist_annotations when containing multipolygons objects
  • Loading branch information
loic-lb committed Aug 12, 2024
1 parent dc16422 commit 2df9ea2
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 6 deletions.
17 changes: 12 additions & 5 deletions src/prismtoolbox/utils/qupath_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os
import uuid
import numpy as np
import geopandas
from shapely import MultiPolygon, Polygon, box
from shapely.geometry import mapping, shape
from shapely.affinity import translate
Expand All @@ -13,12 +12,13 @@
log = logging.getLogger(__name__)

def contoursToPolygons(
contours: List[np.ndarray], merge: Optional[bool] = False
contours: List[np.ndarray], merge: Optional[bool] = False, make_valid: Optional[bool] = False,
) -> Union[Polygon, MultiPolygon]:
"""Converts list of arrays to shapely polygons.
:param contours: list of contours to convert to shapely polygons
:param merge: optional boolean to merge the polygons
:param make_valid: optional boolean to enforce validity of the polygons
:return: MultiPolygon object containing the polygons created from the arrays
"""
polygons = [Polygon(contour.squeeze()).buffer(0) for contour in contours]
Expand All @@ -31,7 +31,7 @@ def contoursToPolygons(
else:
result.append(poly)
polygons = MultiPolygon(result)
if not polygons.is_valid:
if make_valid and not polygons.is_valid:
polygons = polygons.buffer(0)
if merge:
polygons = unary_union(polygons)
Expand All @@ -57,10 +57,17 @@ def read_qupath_annotations(path: str, offset: Optional[Tuple[int, int]] = (0, 0
:param offset: optional offset to add to each coordinate in the arrays
:param class_name: name of the class to select
:param column_to_select: optional column to select
:return:
:return: MultiPolygon object containing the polygons of the selected class.
"""
df = read_json_with_geopandas(path, offset)
polygons = df.loc[df[column_to_select] == class_name, "geometry"].values
polygons = []
for poly in df.loc[df[column_to_select] == class_name, "geometry"].values:
if poly.geom_type == "Polygon":
polygons.append(poly)
elif poly.geom_type == "MultiPolygon":
polygons.extend(poly.geoms)
else:
raise ValueError("Geometry type not supported.")
polygons = MultiPolygon(polygons)
if not polygons.is_valid:
polygons = polygons.buffer(0)
Expand Down
2 changes: 1 addition & 1 deletion src/prismtoolbox/wsicore/wsi.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ def apply_pathologist_annotations(self, path: str, class_name: str = "annotation
), "No tissue contours found for the slide, please run the detect_tissue method first"
offset = (-self.offset[0], -self.offset[1])
pathologist_annotations = read_qupath_annotations(path, offset=offset, class_name=class_name, column_to_select=column_to_select)
polygons = contoursToPolygons(self.tissue_contours)
polygons = contoursToPolygons(self.tissue_contours, make_valid=False)
intersection = intersectionPolygons(polygons, pathologist_annotations)
self.tissue_contours = PolygonsToContours(intersection)

Expand Down

0 comments on commit 2df9ea2

Please sign in to comment.