Skip to content

Commit

Permalink
Merge 5068384 into cc417ec
Browse files Browse the repository at this point in the history
  • Loading branch information
Alessia Marcolini committed Jun 23, 2020
2 parents cc417ec + 5068384 commit 8b61eef
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 19 deletions.
20 changes: 6 additions & 14 deletions src/histolab/tiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,7 @@ def max_iter(self, max_iter_: int = 1e4):
def box_mask(self, slide: Slide) -> sparse._coo.core.COO:
"""Return binary mask at level 0 of the box to consider for tiles extraction.
If `check_tissue` attribute is True, the mask pixels set to True will be the
ones corresponding to the tissue box. Otherwise, all the mask pixels will be set
to True.
The mask pixels set to True will be the ones corresponding to the tissue box.
Parameters
----------
Expand All @@ -116,18 +114,13 @@ def box_mask(self, slide: Slide) -> sparse._coo.core.COO:
Extraction mask at level 0
"""

if self.check_tissue:
return slide.biggest_tissue_box_mask
else:
return sparse.ones(slide.dimensions[::-1], dtype=bool)
return slide.biggest_tissue_box_mask

@lru_cache(maxsize=100)
def box_mask_lvl(self, slide: Slide) -> sparse._coo.core.COO:
"""Return binary mask at target level of the box to consider for the extraction.
If ``check_tissue`` attribute is True, the mask pixels set to True will be the
ones corresponding to the tissue box. Otherwise, all the mask pixels will be set
to True.
The mask pixels set to True will be the ones corresponding to the tissue box.
Parameters
----------
Expand Down Expand Up @@ -223,8 +216,6 @@ def _random_tiles_generator(self, slide: Slide) -> (Tile, CoordinatePair):

while True:

iteration += 1

tile_wsi_coords = self._random_tile_coordinates(slide)
try:
tile = slide.extract_tile(tile_wsi_coords, self.level)
Expand All @@ -235,11 +226,12 @@ def _random_tiles_generator(self, slide: Slide) -> (Tile, CoordinatePair):
if not self.check_tissue or tile.has_enough_tissue():
yield tile, tile_wsi_coords
valid_tile_counter += 1
iteration += 1

if self.max_iter and iteration > self.max_iter:
if self.max_iter and iteration >= self.max_iter:
break

if valid_tile_counter > self.n_tiles:
if valid_tile_counter >= self.n_tiles:
break

def _tile_filename(
Expand Down
102 changes: 97 additions & 5 deletions tests/unit/test_tiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sparse

from histolab.slide import Slide
from histolab.tile import Tile
from histolab.tiler import RandomTiler, Tiler
from histolab.types import CoordinatePair

Expand Down Expand Up @@ -152,7 +153,7 @@ def it_can_generate_random_coordinates(self, request, tmpdir):
@pytest.mark.parametrize(
"check_tissue, expected_box",
(
(False, SparseArrayMock.ONES_500X500_BOOL),
(False, SparseArrayMock.RANDOM_500X500_BOOL),
(True, SparseArrayMock.RANDOM_500X500_BOOL),
),
)
Expand All @@ -165,17 +166,108 @@ def it_knows_its_box_mask(self, request, tmpdir, check_tissue, expected_box):
_biggest_tissue_box_mask = property_mock(
request, Slide, "biggest_tissue_box_mask"
)
if check_tissue:
_biggest_tissue_box_mask.return_value = expected_box
_biggest_tissue_box_mask.return_value = expected_box
random_tiler = RandomTiler((128, 128), 10, 0, check_tissue=check_tissue)

box_mask = random_tiler.box_mask(slide)

if check_tissue:
_biggest_tissue_box_mask.assert_called_once_with()
_biggest_tissue_box_mask.assert_called_once_with()
assert type(box_mask) == sparse._coo.core.COO
np.testing.assert_array_almost_equal(box_mask.todense(), expected_box.todense())

@pytest.mark.parametrize(
"coords1, coords2, check_tissue, has_enough_tissue, max_iter, expected_n_tiles",
(
(
CoordinatePair(0, 10, 0, 10),
CoordinatePair(0, 10, 0, 10),
True,
[True, True],
10,
2,
),
(
CoordinatePair(0, 10, 0, 10),
CoordinatePair(0, 10, 0, 10),
True,
[True, False],
2,
1,
),
(
CoordinatePair(0, 10, 0, 10),
CoordinatePair(5900, 6000, 5900, 6000), # wrong coordinates
True,
[True, True],
2,
2,
),
(
CoordinatePair(0, 10, 0, 10),
CoordinatePair(0, 10, 0, 10),
False,
[True, True],
10,
2,
),
(
CoordinatePair(0, 10, 0, 10),
CoordinatePair(0, 10, 0, 10),
False,
[False, False],
10,
2,
),
(
CoordinatePair(0, 10, 0, 10),
CoordinatePair(0, 10, 0, 10),
True,
[False, False],
10,
0,
),
),
)
def it_can_generate_random_tiles(
self,
request,
tmpdir,
coords1,
coords2,
check_tissue,
has_enough_tissue,
max_iter,
expected_n_tiles,
):
tmp_path_ = tmpdir.mkdir("myslide")
image = PILImageMock.DIMS_500X500_RGBA_COLOR_155_249_240
image.save(os.path.join(tmp_path_, "mywsi.png"), "PNG")
slide_path = os.path.join(tmp_path_, "mywsi.png")
slide = Slide(slide_path, "processed")
_extract_tile = method_mock(request, Slide, "extract_tile")
_has_enough_tissue = method_mock(request, Tile, "has_enough_tissue")
_has_enough_tissue.side_effect = has_enough_tissue * (max_iter // 2)
_random_tile_coordinates = method_mock(
request, RandomTiler, "_random_tile_coordinates"
)
_random_tile_coordinates.side_effect = [coords1, coords2] * (max_iter // 2)
tile1 = Tile(image, coords1)
tile2 = Tile(image, coords2)
_extract_tile.side_effect = [tile1, tile2] * (max_iter // 2)
random_tiler = RandomTiler(
(10, 10), 2, level=0, max_iter=max_iter, check_tissue=check_tissue
)

generated_tiles = list(random_tiler._random_tiles_generator(slide))

_random_tile_coordinates.assert_called_with(random_tiler, slide)
assert _random_tile_coordinates.call_count <= random_tiler.max_iter

_extract_tile.call_args_list == ([call(coords1, 0), call(coords2, 0)])
assert len(generated_tiles) == expected_n_tiles
if expected_n_tiles == 2:
assert generated_tiles == [(tile1, coords1), (tile2, coords2)]

# fixtures -------------------------------------------------------

@pytest.fixture(
Expand Down

0 comments on commit 8b61eef

Please sign in to comment.