def it_can_extract_random_tiles(self, request, tmpdir): tmp_path_ = tmpdir.mkdir("myslide") image = PILIMG.RGBA_COLOR_500X500_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, os.path.join(tmp_path_, "processed")) _tiles_generator = method_mock(request, RandomTiler, "_tiles_generator") coords = CP(0, 10, 0, 10) tile = Tile(image, coords) _tiles_generator.return_value = [(tile, coords), (tile, coords)] _tile_filename = method_mock(request, RandomTiler, "_tile_filename") _tile_filename.side_effect = [ f"tile_{i}_level2_0-10-0-10.png" for i in range(2) ] _has_valid_tile_size = method_mock(request, RandomTiler, "_has_valid_tile_size") _has_valid_tile_size.return_value = True random_tiler = RandomTiler((10, 10), n_tiles=2, level=0) random_tiler.extract(slide) assert _tile_filename.call_args_list == [ call(random_tiler, coords, 0), call(random_tiler, coords, 1), ] assert os.path.exists( os.path.join(tmp_path_, "processed", "tiles", "tile_0_level2_0-10-0-10.png")) assert os.path.exists( os.path.join(tmp_path_, "processed", "tiles", "tile_1_level2_0-10-0-10.png")) _has_valid_tile_size.assert_called_once_with(random_tiler, slide)
def or_it_has_wrong_seed(self, tmpdir): slide, _ = base_test_slide(tmpdir, PILIMG.RGB_RANDOM_COLOR_500X500) random_tiler = RandomTiler((128, 128), 10, 0, seed=-1) with pytest.raises(ValueError) as err: random_tiler.extract(slide) assert isinstance(err.value, ValueError) assert str(err.value) == "Seed must be between 0 and 2**32 - 1"
def or_it_has_not_available_level_value(self, tmpdir): slide, _ = base_test_slide(tmpdir, PILIMG.RGB_RANDOM_COLOR_500X500) random_tiler = RandomTiler((128, 128), 10, 3) with pytest.raises(LevelError) as err: random_tiler.extract(slide) assert isinstance(err.value, LevelError) assert str(err.value ) == "Level 3 not available. Number of available levels: 1"
def or_it_has_wrong_seed(self, request, tmpdir): tmp_path_ = tmpdir.mkdir("myslide") image = PILImageMock.DIMS_50X50_RGB_RANDOM_COLOR image.save(os.path.join(tmp_path_, "mywsi.png"), "PNG") slide_path = os.path.join(tmp_path_, "mywsi.png") slide = Slide(slide_path, "processed") random_tiler = RandomTiler((512, 512), 10, 0, seed=-1) with pytest.raises(ValueError) as err: random_tiler.extract(slide) assert isinstance(err.value, ValueError) assert str(err.value) == "Seed must be between 0 and 2**32 - 1"
def or_it_has_not_available_level_value(self, tmpdir): tmp_path_ = tmpdir.mkdir("myslide") image = PILIMG.RGB_RANDOM_COLOR_500X500 image.save(os.path.join(tmp_path_, "mywsi.png"), "PNG") slide_path = os.path.join(tmp_path_, "mywsi.png") slide = Slide(slide_path, "processed") random_tiler = RandomTiler((128, 128), 10, 3) with pytest.raises(LevelError) as err: random_tiler.extract(slide) assert isinstance(err.value, LevelError) assert str(err.value) == "Level 3 not available. Number of available levels: 1"
def test_extract_tiles_respecting_the_given_tile_size( self, tmpdir, tile_size, level, seed, n_tiles): processed_path = os.path.join(tmpdir, "processed") slide = Slide(SVS.TCGA_CR_7395_01A_01_TS1, processed_path) random_tiles_extractor = RandomTiler( tile_size=tile_size, n_tiles=n_tiles, level=level, seed=seed, check_tissue=True, ) binary_mask = BiggestTissueBoxMask() random_tiles_extractor.extract(slide, binary_mask) for tile in os.listdir(processed_path): assert Image.open(os.path.join(processed_path, tile)).size == tile_size
def but_it_raises_tilesizeerror_if_tilesize_larger_than_slidesize( self, request, tmpdir, image, size): tmp_path_ = tmpdir.mkdir("myslide") image.save(os.path.join(tmp_path_, "mywsi.png"), "PNG") slide_path = os.path.join(tmp_path_, "mywsi.png") slide = Slide(slide_path, os.path.join(tmp_path_, "processed")) _has_valid_tile_size = method_mock(request, RandomTiler, "_has_valid_tile_size") _has_valid_tile_size.return_value = False random_tiler = RandomTiler((50, 52), n_tiles=10, level=0) with pytest.raises(TileSizeError) as err: random_tiler.extract(slide) assert isinstance(err.value, TileSizeError) assert (str( err.value ) == f"Tile size (50, 52) is larger than slide size {size} at level 0") _has_valid_tile_size.assert_called_once_with(random_tiler, slide)
def extract_random_tiles( dataset_dir: str, processed_path: str, tile_size: Tuple[int, int], n_tiles: int, level: int, seed: int, check_tissue: bool, ) -> None: """Save random tiles extracted from WSIs in `dataset_dir` into `processed_path`/tiles/ Parameters ---------- dataset_dir : str Path were the WSIs are saved processed_path : str Path where to store the tiles (will be concatenated with /tiles) tile_size : Tuple[int, int] width and height of the cropped tiles n_tiles : int Maximum number of tiles to extract level : int Magnification level from which extract the tiles seed : int Seed for RandomState check_tissue : bool Whether to check if the tile has enough tissue to be saved """ slideset = SlideSet(dataset_dir, processed_path, valid_extensions=[".svs"]) for slide in tqdm(slideset.slides): prefix = f"{slide.name}_" random_tiles_extractor = RandomTiler( tile_size=tile_size, n_tiles=n_tiles, level=level, seed=seed, check_tissue=check_tissue, prefix=prefix, ) random_tiles_extractor.extract(slide)
def it_can_extract_random_tiles(self, request, tmpdir, caplog): tmp_path_ = tmpdir.mkdir("myslide") image = PILIMG.RGBA_COLOR_500X500_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, os.path.join(tmp_path_, "processed")) _tiles_generator = method_mock(request, RandomTiler, "_tiles_generator") coords = CP(0, 10, 0, 10) tile = Tile(image, coords) _tiles_generator.return_value = [(tile, coords), (tile, coords)] _tile_filename = method_mock(request, RandomTiler, "_tile_filename") _tile_filename.side_effect = [ f"tile_{i}_level2_0-10-0-10.png" for i in range(2) ] _has_valid_tile_size = method_mock(request, RandomTiler, "_has_valid_tile_size") _has_valid_tile_size.return_value = True random_tiler = RandomTiler((10, 10), n_tiles=2, level=0) binary_mask = BiggestTissueBoxMask() with caplog.at_level(logging.INFO): random_tiler.extract(slide, binary_mask) assert re.sub(r":+\d{3}", "", caplog.text).splitlines() == [ "INFO tiler:tiler.py \t Tile 0 saved: tile_0_level2_0-10-0-10.png", "INFO tiler:tiler.py \t Tile 1 saved: tile_1_level2_0-10-0-10.png", "INFO tiler:tiler.py 2 Random Tiles have been saved.", ] assert _tile_filename.call_args_list == [ call(random_tiler, coords, 0), call(random_tiler, coords, 1), ] assert os.path.exists( os.path.join(tmp_path_, "processed", "tile_0_level2_0-10-0-10.png")) assert os.path.exists( os.path.join(tmp_path_, "processed", "tile_1_level2_0-10-0-10.png")) _has_valid_tile_size.assert_called_once_with(random_tiler, slide)