diff --git a/src/histolab/filters/image_filters.py b/src/histolab/filters/image_filters.py index 8ec4063c..2baccbc1 100644 --- a/src/histolab/filters/image_filters.py +++ b/src/histolab/filters/image_filters.py @@ -40,7 +40,7 @@ class Filter(Protocol): def __call__( self, img: Union[PIL.Image.Image, np.ndarray] ) -> Union[PIL.Image.Image, np.ndarray]: - pass + pass # pragma: no cover def __repr__(self) -> str: return self.__class__.__name__ + "()" @@ -52,7 +52,7 @@ class ImageFilter(Filter, Protocol): @abstractmethod def __call__(self, img: PIL.Image.Image) -> Union[PIL.Image.Image, np.ndarray]: - pass + pass # pragma: no cover class Compose(ImageFilter): diff --git a/src/histolab/filters/morphological_filters.py b/src/histolab/filters/morphological_filters.py index 83b83850..c9c0053d 100644 --- a/src/histolab/filters/morphological_filters.py +++ b/src/histolab/filters/morphological_filters.py @@ -37,7 +37,7 @@ class MorphologicalFilter(Filter, Protocol): @abstractmethod def __call__(self, np_mask: np.ndarray) -> np.ndarray: - pass + pass # pragma: no cover class RemoveSmallObjects(MorphologicalFilter): diff --git a/src/histolab/masks.py b/src/histolab/masks.py index 377dbbb8..71780e3d 100644 --- a/src/histolab/masks.py +++ b/src/histolab/masks.py @@ -56,7 +56,7 @@ def __call__(self, slide): @abstractmethod def _mask(self, slide): # pragma: no cover # This property will be supplied by the inheriting classes individually - pass + pass # pragma: no cover class BiggestTissueBoxMask(BinaryMask): diff --git a/src/histolab/scorer.py b/src/histolab/scorer.py index 302bb268..58885ddb 100644 --- a/src/histolab/scorer.py +++ b/src/histolab/scorer.py @@ -41,7 +41,7 @@ class Scorer(Protocol): @abstractmethod def __call__(self, tile: Tile) -> float: - pass + pass # pragma: no cover class RandomScorer(Scorer): diff --git a/src/histolab/tiler.py b/src/histolab/tiler.py index d35b473b..b2a97290 100644 --- a/src/histolab/tiler.py +++ b/src/histolab/tiler.py @@ -75,13 +75,18 @@ def box_mask(self, slide: Slide) -> np.ndarray: return biggest_tissue_box_mask(slide) @abstractmethod - def extract(self, slide: Slide, extraction_mask: BinaryMask, log_level: str): - pass + def extract( + self, + slide: Slide, + log_level: str, + extraction_mask: BinaryMask = BiggestTissueBoxMask(), + ): + pass # pragma: no cover def locate_tiles( self, slide: Slide, - extraction_mask: BinaryMask, + extraction_mask: BinaryMask = BiggestTissueBoxMask(), scale_factor: int = 32, alpha: int = 128, outline: str = "red", @@ -94,6 +99,7 @@ def locate_tiles( Slide reference where placing the tiles extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask` scale_factor: int Scaling factor for the returned image. Default is 32. alpha: int @@ -172,9 +178,9 @@ def _tile_filename( return tile_filename def _tiles_generator( - self, slide: Slide, extraction_mask: BinaryMask + self, slide: Slide, extraction_mask: BinaryMask = BiggestTissueBoxMask() ) -> Tuple[Tile, CoordinatePair]: - pass + pass # pragma: no cover def _validate_level(self, slide: Slide) -> None: """Validate the Tiler's level according to the Slide. @@ -259,7 +265,10 @@ def __init__( self.suffix = suffix def extract( - self, slide: Slide, extraction_mask: BinaryMask, log_level: str = "INFO" + self, + slide: Slide, + extraction_mask: BinaryMask = BiggestTissueBoxMask(), + log_level: str = "INFO", ) -> None: """Extract tiles arranged in a grid and save them to disk, following this filename pattern: @@ -271,6 +280,7 @@ def extract( Slide from which to extract the tiles extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. log_level : str, {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"} Threshold level for the log messages. Default "INFO" @@ -351,7 +361,7 @@ def _grid_coordinates_from_bbox_coordinates( yield tile_wsi_coords def _grid_coordinates_generator( - self, slide: Slide, extraction_mask: BinaryMask + self, slide: Slide, extraction_mask: BinaryMask = BiggestTissueBoxMask() ) -> CoordinatePair: """Generate Coordinates at level 0 of grid tiles within the tissue. @@ -362,6 +372,7 @@ def _grid_coordinates_generator( tissue area. extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. Yields ------- @@ -384,7 +395,7 @@ def _grid_coordinates_generator( ) def _tiles_generator( - self, slide: Slide, extraction_mask: BinaryMask + self, slide: Slide, extraction_mask: BinaryMask = BiggestTissueBoxMask() ) -> Tuple[Tile, CoordinatePair]: """Generator of tiles arranged in a grid. @@ -394,6 +405,7 @@ def _tiles_generator( Slide from which to extract the tiles extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. Yields ------- @@ -504,7 +516,10 @@ def __init__( self.suffix = suffix def extract( - self, slide: Slide, extraction_mask: BinaryMask, log_level: str = "INFO" + self, + slide: Slide, + extraction_mask: BinaryMask = BiggestTissueBoxMask(), + log_level: str = "INFO", ) -> None: """Extract random tiles and save them to disk, following this filename pattern: `{prefix}tile_{tiles_counter}_level{level}_{x_ul_wsi}-{y_ul_wsi}-{x_br_wsi}-{y_br_wsi}{suffix}` @@ -515,6 +530,7 @@ def extract( Slide from which to extract the tiles extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. log_level: str, {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"} Threshold level for the log messages. Default "INFO" @@ -566,7 +582,7 @@ def tile_size(self, tile_size_: Tuple[int, int]): # ------- implementation helpers ------- def _random_tile_coordinates( - self, slide: Slide, extraction_mask: BinaryMask + self, slide: Slide, extraction_mask: BinaryMask = BiggestTissueBoxMask() ) -> CoordinatePair: """Return 0-level Coordinates of a tile picked at random within the box. @@ -576,6 +592,7 @@ def _random_tile_coordinates( Slide from which calculate the coordinates. Needed to calculate the box. extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. Returns ------- @@ -608,7 +625,7 @@ def _random_tile_coordinates( return tile_wsi_coords def _tiles_generator( - self, slide: Slide, extraction_mask: BinaryMask + self, slide: Slide, extraction_mask: BinaryMask = BiggestTissueBoxMask() ) -> Tuple[Tile, CoordinatePair]: """Generate Random Tiles within a slide box. @@ -622,6 +639,7 @@ def _tiles_generator( The Whole Slide Image from which to extract the tiles. extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. Yields ------ @@ -714,7 +732,7 @@ def __init__( def extract( self, slide: Slide, - extraction_mask: BinaryMask, + extraction_mask: BinaryMask = BiggestTissueBoxMask(), report_path: str = None, log_level: str = "INFO", ) -> None: @@ -730,6 +748,7 @@ def extract( Slide from which to extract the tiles extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. report_path : str, optional Path to the CSV report. If None, no report will be saved log_level: str, {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"} @@ -773,7 +792,7 @@ def extract( # ------- implementation helpers ------- def _tiles_generator( - self, slide: Slide, extraction_mask: BinaryMask + self, slide: Slide, extraction_mask: BinaryMask = BiggestTissueBoxMask() ) -> Tuple[List[Tuple[float, CoordinatePair]], List[Tuple[float, CoordinatePair]]]: r"""Calculate the tiles with the highest scores and their extraction coordinates @@ -783,6 +802,7 @@ def _tiles_generator( The slide to extract the tiles from. extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. Returns ------- @@ -892,7 +912,7 @@ def _scale_scores( return list(zip(scores_scaled, coords)) def _scores( - self, slide: Slide, extraction_mask: BinaryMask + self, slide: Slide, extraction_mask: BinaryMask = BiggestTissueBoxMask() ) -> List[Tuple[float, CoordinatePair]]: """Calculate the scores for all the tiles extracted from the ``slide``. @@ -902,6 +922,7 @@ def _scores( The slide to extract the tiles from. extraction_mask : BinaryMask BinaryMask object defining how to compute a binary mask from a Slide. + Default `BiggestTissueBoxMask`. Returns ------- diff --git a/tests/integration/test_tiler.py b/tests/integration/test_tiler.py index d1e9ef04..ab1ce2ce 100644 --- a/tests/integration/test_tiler.py +++ b/tests/integration/test_tiler.py @@ -210,11 +210,12 @@ def it_locates_tiles_on_the_slide( r"Input image must be RGB. NOTE: the image will be converted to RGB before" r" HED conversion." ) - binary_mask = BiggestTissueBoxMask() with pytest.warns(UserWarning, match=expected_warning_regex): + # no binary mask object passed to locate_tiles + # default value = BiggestTissueBoxMask tiles_location_img = scored_tiles_extractor.locate_tiles( - slide, binary_mask, scale_factor=10 + slide, scale_factor=10 ) # --- Expanding test report with actual and expected images --- expand_tests_report(request, expected=expected_img, actual=tiles_location_img)