Ejemplo n.º 1
0
    def but_it_raises_exception_when_number_of_regions_is_wrong(
            self, n, expected_message):
        binary_mask = BiggestTissueBoxMask()

        with pytest.raises(ValueError) as e:
            binary_mask._regions([], n)

        assert str(e.value) == expected_message
Ejemplo n.º 2
0
    def it_can_construct_big_tissue_box_mask(self, wsi, expected_array):
        slide = Slide(wsi, os.path.join(wsi, "processed"))
        expected_array = load_expectation(expected_array, type_="npy")
        biggest_tissue_box = BiggestTissueBoxMask()

        np.testing.assert_array_almost_equal(biggest_tissue_box(slide),
                                             expected_array)
Ejemplo n.º 3
0
    def it_can_calculate_scores(self, request):
        slide = instance_mock(request, Slide)
        coords = CP(0, 10, 0, 10)
        image = PILIMG.RGB_RANDOM_COLOR_500X500
        tile = Tile(image, coords)
        _tiles_generator = method_mock(request, GridTiler, "_tiles_generator")
        # it needs to be a generator
        _tiles_generator.return_value = ((tile, coords) for i in range(3))
        _scorer = instance_mock(request, RandomScorer)
        _scorer.side_effect = [0.5, 0.7]
        score_tiler = ScoreTiler(_scorer, (10, 10), 2, 0)
        binary_mask = BiggestTissueBoxMask()

        scores = score_tiler._scores(slide, binary_mask)

        assert _tiles_generator.call_args_list == [
            call(score_tiler, slide, binary_mask),
            call(score_tiler, slide, binary_mask),
        ]
        assert _scorer.call_args_list == [call(tile), call(tile)]
        assert type(scores) == list
        assert type(scores[0]) == tuple
        assert type(scores[0][0]) == float
        assert type(scores[0][1]) == CP
        assert scores == [(0.5, coords), (0.7, coords)]
Ejemplo n.º 4
0
    def but_it_raises_error_with_negative_n_tiles_value(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"))
        _scores = method_mock(request, ScoreTiler, "_scores")
        coords = CP(0, 10, 0, 10)
        _scores.return_value = [
            (0.7, coords),
            (0.5, coords),
            (0.2, coords),
            (0.8, coords),
            (0.1, coords),
        ]
        _scorer = instance_mock(request, RandomScorer)
        score_tiler = ScoreTiler(_scorer, (10, 10), -1, 0)
        binary_mask = BiggestTissueBoxMask()

        with pytest.raises(ValueError) as err:
            score_tiler.extract(slide, binary_mask)

        assert isinstance(err.value, ValueError)
        assert str(err.value) == "'n_tiles' cannot be negative (-1)"
        _scores.assert_called_once_with(score_tiler, slide, binary_mask)
Ejemplo n.º 5
0
    def it_can_generate_random_coordinates(self, request, tmpdir):
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        _box_mask_thumb = method_mock(request, BiggestTissueBoxMask,
                                      "__call__")
        _box_mask_thumb.return_value = NpArrayMock.ONES_500X500_BOOL
        _tile_size = property_mock(request, RandomTiler, "tile_size")
        _tile_size.return_value = (128, 128)
        _random_choice_true_mask2d = function_mock(
            request, "histolab.tiler.random_choice_true_mask2d")
        _random_choice_true_mask2d.return_value = (0, 0)
        _scale_coordinates = function_mock(request,
                                           "histolab.tiler.scale_coordinates")
        random_tiler = RandomTiler((128, 128), 10, 0)
        binary_mask = BiggestTissueBoxMask()

        random_tiler._random_tile_coordinates(slide, binary_mask)

        _box_mask_thumb.assert_called_once_with(binary_mask, slide)
        _tile_size.assert_has_calls([call((128, 128))])
        _random_choice_true_mask2d.assert_called_once_with(
            NpArrayMock.ONES_500X500_BOOL)
        _scale_coordinates.assert_called_once_with(
            reference_coords=CP(x_ul=0, y_ul=0, x_br=128, y_br=128),
            reference_size=(500, 500),
            target_size=(500, 500),
        )
Ejemplo n.º 6
0
    def it_knows_its_mask(
        self,
        request,
        tmpdir,
        RgbToGrayscale_,
        OtsuThreshold_,
        BinaryDilation_,
        RemoveSmallHoles_,
        RemoveSmallObjects_,
    ):
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        regions = [
            Region(index=0,
                   area=33,
                   bbox=(0, 0, 2, 2),
                   center=(0.5, 0.5),
                   coords=None)
        ]
        main_tissue_areas_mask_filters_ = property_mock(
            request, _SlideFiltersComposition, "tissue_mask_filters")
        main_tissue_areas_mask_filters_.return_value = Compose([
            RgbToGrayscale_,
            OtsuThreshold_,
            BinaryDilation_,
            RemoveSmallHoles_,
            RemoveSmallObjects_,
        ])
        regions_from_binary_mask = function_mock(
            request, "histolab.masks.regions_from_binary_mask")
        regions_from_binary_mask.return_value = regions
        biggest_regions_ = method_mock(request,
                                       BiggestTissueBoxMask,
                                       "_regions",
                                       autospec=False)
        biggest_regions_.return_value = regions
        region_coordinates_ = function_mock(
            request, "histolab.masks.region_coordinates")
        region_coordinates_.return_values = CP(0, 0, 2, 2)
        rectangle_to_mask_ = function_mock(request,
                                           "histolab.util.rectangle_to_mask")
        rectangle_to_mask_((1000, 1000), CP(0, 0, 2, 2)).return_value = [
            [True, True],
            [False, True],
        ]
        biggest_mask_tissue_box = BiggestTissueBoxMask()

        binary_mask = biggest_mask_tissue_box(slide)

        np.testing.assert_almost_equal(binary_mask, np.zeros((500, 500)))
        region_coordinates_.assert_called_once_with(regions[0])
        biggest_regions_.assert_called_once_with(regions, n=1)
        rectangle_to_mask_.assert_called_once_with((1000, 1000),
                                                   CP(x_ul=0,
                                                      y_ul=0,
                                                      x_br=2,
                                                      y_br=2))
Ejemplo n.º 7
0
    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)
        binary_mask = BiggestTissueBoxMask()

        with pytest.raises(ValueError) as err:
            random_tiler.extract(slide, binary_mask)

        assert isinstance(err.value, ValueError)
        assert str(err.value) == "Seed must be between 0 and 2**32 - 1"
Ejemplo n.º 8
0
    def or_it_has_not_available_level_value(self, tmpdir):
        slide, _ = base_test_slide(tmpdir, PILIMG.RGB_RANDOM_COLOR_500X500)
        binary_mask = BiggestTissueBoxMask()
        grid_tiler = GridTiler((128, 128), 3)

        with pytest.raises(LevelError) as err:
            grid_tiler.extract(slide, binary_mask)

        assert isinstance(err.value, LevelError)
        assert str(err.value
                   ) == "Level 3 not available. Number of available levels: 1"
Ejemplo n.º 9
0
    def or_it_raises_levelerror_if_has_not_available_level_value(self, tmpdir):
        slide, _ = base_test_slide(tmpdir, PILIMG.RGB_RANDOM_COLOR_500X500)
        score_tiler = ScoreTiler(None, (10, 10), 2, 3)
        binary_mask = BiggestTissueBoxMask()

        with pytest.raises(LevelError) as err:
            score_tiler.extract(slide, binary_mask)

        assert isinstance(err.value, LevelError)
        assert str(err.value
                   ) == "Level 3 not available. Number of available levels: 1"
Ejemplo n.º 10
0
    def it_can_extract_score_tiles_and_save_report(self, request, tmpdir):
        _extract_tile = method_mock(request, Slide, "extract_tile")
        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"))
        coords = CP(0, 10, 0, 10)
        _tiles_generator = method_mock(
            request,
            ScoreTiler,
            "_tiles_generator",
        )
        tile = Tile(image, coords)
        _extract_tile.return_value = tile
        _tiles_generator.return_value = (
            [(0.8, coords), (0.7, coords)],
            [(0.8, coords), (0.7, coords)],
        )
        _tile_filename = method_mock(request, GridTiler, "_tile_filename")
        _tile_filename.side_effect = [
            f"tile_{i}_level2_0-10-0-10.png" for i in range(2)
        ]
        _save_report = method_mock(request,
                                   ScoreTiler,
                                   "_save_report",
                                   autospec=False)
        random_scorer = RandomScorer()
        score_tiler = ScoreTiler(random_scorer, (10, 10), 2, 0)
        binary_mask = BiggestTissueBoxMask()

        score_tiler.extract(slide, binary_mask, "report.csv")

        assert _extract_tile.call_args_list == [
            call(slide, coords, 0, (10, 10)),
            call(slide, coords, 0, (10, 10)),
        ]
        _tiles_generator.assert_called_with(score_tiler, slide, binary_mask)
        assert _tile_filename.call_args_list == [
            call(score_tiler, coords, 0),
            call(score_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"))
        _save_report.assert_called_once_with(
            "report.csv",
            [(0.8, coords), (0.7, coords)],
            [(0.8, coords), (0.7, coords)],
            [f"tile_{i}_level2_0-10-0-10.png" for i in range(2)],
        )
Ejemplo n.º 11
0
    def and_doesnt_raise_error_with_wrong_coordinates(self, request, tmpdir):
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        coords = CP(5800, 6000, 5800, 6000)
        _grid_coordinates_generator = method_mock(
            request, GridTiler, "_grid_coordinates_generator")
        _grid_coordinates_generator.return_value = [coords]
        grid_tiler = GridTiler((10, 10))
        binary_mask = BiggestTissueBoxMask()
        generated_tiles = list(grid_tiler._tiles_generator(slide, binary_mask))

        assert len(generated_tiles) == 0
        _grid_coordinates_generator.assert_called_once_with(
            grid_tiler, slide, binary_mask)
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
    def but_it_raises_runtimeerror_if_no_tiles_are_extracted(self, request):
        slide = instance_mock(request, Slide)
        _tiles_generator = method_mock(request, GridTiler, "_tiles_generator")
        # it needs to be an empty generator
        _tiles_generator.return_value = (n for n in [])
        score_tiler = ScoreTiler(None, (10, 10), 2, 0)
        binary_mask = BiggestTissueBoxMask()

        with pytest.raises(RuntimeError) as err:
            score_tiler._scores(slide, binary_mask)

        _tiles_generator.assert_called_once_with(score_tiler, slide,
                                                 binary_mask)
        assert isinstance(err.value, RuntimeError)
        assert (
            str(err.value) ==
            "No tiles have been generated. This could happen if `check_tissue=True`"
        )
Ejemplo n.º 14
0
    def it_can_generate_random_tiles_even_when_coords_are_not_valid(
            self, tmpdir, _random_tile_coordinates):
        random_tiler = RandomTiler((10, 10),
                                   1,
                                   level=0,
                                   max_iter=1,
                                   check_tissue=False)
        _random_tile_coordinates.side_effect = [
            CP(-1, -1, -1, -1), CP(0, 10, 0, 10)
        ]
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        binary_mask = BiggestTissueBoxMask()

        generated_tiles = list(
            random_tiler._tiles_generator(slide, binary_mask))

        assert generated_tiles[0][1] == CP(0, 10, 0, 10)
        assert isinstance(generated_tiles[0][0], Tile)
Ejemplo n.º 15
0
    def it_can_extract_grid_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, GridTiler, "_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, GridTiler, "_tile_filename")
        _tile_filename.side_effect = [
            os.path.join(tmp_path_, "processed",
                         f"tile_{i}_level2_0-10-0-10.png") for i in range(2)
        ]
        _has_valid_tile_size = method_mock(request, GridTiler,
                                           "_has_valid_tile_size")
        _has_valid_tile_size.return_value = True
        grid_tiler = GridTiler((10, 10), level=0)
        binary_mask = BiggestTissueBoxMask()

        with caplog.at_level(logging.ERROR):
            grid_tiler.extract(slide, binary_mask)

        assert caplog.text == ""
        assert _tile_filename.call_args_list == [
            call(grid_tiler, coords, 0),
            call(grid_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(grid_tiler, slide)
        _tiles_generator.assert_called_once_with(grid_tiler, slide,
                                                 binary_mask)
        assert _tile_filename.call_args_list == [
            call(grid_tiler, coords, 0),
            call(grid_tiler, coords, 1),
        ]
Ejemplo n.º 16
0
    def it_can_generate_grid_tiles_with_check_tissue(
        self,
        request,
        tmpdir,
        tile1,
        tile2,
        has_enough_tissue,
        expected_n_tiles,
    ):
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        _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
        _grid_coordinates_generator = method_mock(
            request, GridTiler, "_grid_coordinates_generator")
        _grid_coordinates_generator.return_value = [
            CP(0, 10, 0, 10), CP(0, 10, 0, 10)
        ]
        _extract_tile.side_effect = [tile1, tile2]
        grid_tiler = GridTiler((10, 10),
                               level=0,
                               check_tissue=True,
                               tissue_percent=60)
        tiles = [tile1, tile2]
        binary_mask = BiggestTissueBoxMask()

        generated_tiles = list(grid_tiler._tiles_generator(slide, binary_mask))

        _grid_coordinates_generator.assert_called_once_with(
            grid_tiler, slide, binary_mask)

        assert _extract_tile.call_args_list == ([
            call(slide, CP(0, 10, 0, 10), 0, (10, 10)),
            call(slide, CP(0, 10, 0, 10), 0, (10, 10)),
        ])
        assert _has_enough_tissue.call_args_list == [
            call(tile1, 60), call(tile2, 60)
        ]
        assert len(generated_tiles) == expected_n_tiles
        for i, tile in enumerate(generated_tiles):
            assert tile[0] == tiles[i]
Ejemplo n.º 17
0
    def it_locates_tiles_on_the_slide(self, request, fixture_slide, level,
                                      check_tissue, expectation, tmpdir):
        slide = Slide(fixture_slide, os.path.join(tmpdir, "processed"))
        grid_tiles_extractor = GridTiler(
            tile_size=(512, 512),
            level=level,
            check_tissue=check_tissue,
        )
        expected_img = load_expectation(expectation, type_="png")
        mask = BiggestTissueBoxMask()

        tiles_location_img = grid_tiles_extractor.locate_tiles(slide,
                                                               mask,
                                                               scale_factor=10)
        # --- Expanding test report with actual and expected images ---
        expand_tests_report(request,
                            expected=expected_img,
                            actual=tiles_location_img)

        np.testing.assert_array_almost_equal(tiles_location_img, expected_img)
Ejemplo n.º 18
0
    def it_can_calculate_highest_score_tiles(self, request, n_tiles,
                                             expected_value):
        slide = instance_mock(request, Slide)
        _scores = method_mock(request, ScoreTiler, "_scores")
        coords = CP(0, 10, 0, 10)
        _scores.return_value = [
            (0.7, coords),
            (0.5, coords),
            (0.2, coords),
            (0.8, coords),
            (0.1, coords),
        ]
        _scorer = instance_mock(request, RandomScorer)
        score_tiler = ScoreTiler(_scorer, (10, 10), n_tiles, 0)
        binary_mask = BiggestTissueBoxMask()

        highest_score_tiles = score_tiler._tiles_generator(slide, binary_mask)

        _scores.assert_called_once_with(score_tiler, slide, binary_mask)
        assert highest_score_tiles == expected_value
Ejemplo n.º 19
0
    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, GridTiler,
                                           "_has_valid_tile_size")
        _has_valid_tile_size.return_value = False
        grid_tiler = GridTiler((50, 52), level=0)
        binary_mask = BiggestTissueBoxMask()

        with pytest.raises(TileSizeError) as err:
            grid_tiler.extract(slide, binary_mask)

        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(grid_tiler, slide)
Ejemplo n.º 20
0
    def it_can_generate_random_tiles_with_check_tissue(
        self,
        request,
        tmpdir,
        tile1,
        tile2,
        has_enough_tissue,
        max_iter,
        expected_value,
        _random_tile_coordinates,
    ):
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        _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)
        binary_mask = BiggestTissueBoxMask()
        tiles = [tile1, tile2]
        _extract_tile.side_effect = tiles * (max_iter // 2)
        random_tiler = RandomTiler(
            (10, 10),
            2,
            level=0,
            max_iter=max_iter,
            check_tissue=True,
            tissue_percent=60,
        )

        generated_tiles = list(
            random_tiler._tiles_generator(slide, binary_mask))

        _random_tile_coordinates.assert_called_with(random_tiler, slide,
                                                    binary_mask)
        assert _has_enough_tissue.call_args_list == [
            call(tile1, 60), call(tile2, 60)
        ]
        assert _random_tile_coordinates.call_count <= random_tiler.max_iter
        assert len(generated_tiles) == expected_value
        for i, tile in enumerate(generated_tiles):
            assert tile[0] == tiles[i]
Ejemplo n.º 21
0
    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)
Ejemplo n.º 22
0
    def it_can_generate_random_tiles_with_check_tissue_but_tiles_without_tissue(
        self,
        request,
        tmpdir,
        _random_tile_coordinates,
    ):
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        _extract_tile = method_mock(request, Slide, "extract_tile")
        _has_enough_tissue = method_mock(request, Tile, "has_enough_tissue")
        _has_enough_tissue.side_effect = [False, False] * 5
        binary_mask = BiggestTissueBoxMask()
        tiles = [
            Tile(PILIMG.RGBA_COLOR_500X500_155_249_240, CP(0, 10, 0, 10)),
            Tile(PILIMG.RGBA_COLOR_500X500_155_249_240, CP(0, 10, 0, 10)),
        ]
        _extract_tile.side_effect = tiles * 5
        random_tiler = RandomTiler(
            (10, 10),
            2,
            level=0,
            max_iter=10,
            check_tissue=True,
            tissue_percent=60,
        )

        generated_tiles = list(
            random_tiler._tiles_generator(slide, binary_mask))

        _random_tile_coordinates.assert_called_with(random_tiler, slide,
                                                    binary_mask)
        assert (_has_enough_tissue.call_args_list == [
            call(tiles[0], 60),
            call(tiles[1], 60),
        ] * 5)
        assert _random_tile_coordinates.call_count <= random_tiler.max_iter
        assert len(generated_tiles) == 0
        for i, tile in enumerate(generated_tiles):
            assert tile[0] == tiles[i]
Ejemplo n.º 23
0
    def but_with_wrong_coordinates(self, request, tmpdir):
        slide, _ = base_test_slide(tmpdir,
                                   PILIMG.RGBA_COLOR_500X500_155_249_240)
        _has_enough_tissue = method_mock(request, Tile, "has_enough_tissue")
        _has_enough_tissue.return_value = False
        _grid_coordinates_generator = method_mock(
            request, GridTiler, "_grid_coordinates_generator")
        coords1 = CP(600, 610, 600, 610)
        coords2 = CP(0, 10, 0, 10)
        _grid_coordinates_generator.return_value = [coords1, coords2]
        grid_tiler = GridTiler((10, 10), level=0, check_tissue=False)
        binary_mask = BiggestTissueBoxMask()

        generated_tiles = list(grid_tiler._tiles_generator(slide, binary_mask))

        _grid_coordinates_generator.assert_called_once_with(
            grid_tiler, slide, binary_mask)
        assert len(generated_tiles) == 1
        # generated_tiles[0][0] is a Tile object but we don't know what object it is
        # because Slide.extract_tile is not mocked (for the exception to happen inside)
        assert isinstance(generated_tiles[0][0], Tile)
        assert generated_tiles[0][1] == coords2
Ejemplo n.º 24
0
import pytest

from histolab.masks import BiggestTissueBoxMask, TissueMask
from histolab.slide import Slide
from histolab.util import random_choice_true_mask2d

from ..fixtures import SVS, TIFF


@pytest.mark.parametrize(
    "fixture_slide, binary_mask",
    [
        (TIFF.KIDNEY_48_5, BiggestTissueBoxMask()),
        (TIFF.KIDNEY_48_5, TissueMask()),
        (SVS.TCGA_CR_7395_01A_01_TS1, BiggestTissueBoxMask()),
        (SVS.TCGA_CR_7395_01A_01_TS1, TissueMask()),
    ],
)
def test_random_choice_true_mask2d_find_right_coordinates(fixture_slide, binary_mask):
    slide = Slide(fixture_slide, "")
    bbox = binary_mask(slide)

    x, y = random_choice_true_mask2d(bbox)
    assert bbox[x, y]
Ejemplo n.º 25
0
class DescribeRandomTiler:
    @pytest.mark.parametrize(
        "fixture_slide, binary_mask, tile_size, level, check_tissue, expectation",
        [
            (
                SVS.CMU_1_SMALL_REGION,
                BiggestTissueBoxMask(),
                (512, 512),
                0,
                False,
                "tiles-location-images/cmu-1-small-region-tl-random-BTB-false-512x512",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                TissueMask(),
                (512, 512),
                -2,
                False,
                "tiles-location-images/tcga-cr-7395-01a-01-ts1-tl-random-TM-f-512x512",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                BiggestTissueBoxMask(),
                (512, 530),
                0,
                False,
                "tiles-location-images/tcga-cr-7395-01a-01-ts1-tl-random-BTB-f-512x530",
            ),
            (
                SVS.CMU_1_SMALL_REGION,
                TissueMask(),
                (512, 530),
                0,
                True,
                "tiles-location-images/cmu-1-small-region-tl-random-TM-true-512x530",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                TissueMask(),
                (128, 128),
                0,
                True,
                "tiles-location-images/tcga-cr-7395-01a-01-ts1-tl-random-TM-t-128x128",
            ),
            (
                TIFF.KIDNEY_48_5,
                TissueMask(),
                (10, 10),
                0,
                True,
                "tiles-location-images/kidney-48-5-random-TM-true-10x10",
            ),
            (
                TIFF.KIDNEY_48_5,
                BiggestTissueBoxMask(),
                (20, 20),
                0,
                False,
                "tiles-location-images/kidney-48-5-random-TM-false-20x20",
            ),
        ],
    )
    def it_locates_tiles_on_the_slide(
        self,
        request,
        fixture_slide,
        binary_mask,
        tile_size,
        level,
        check_tissue,
        expectation,
    ):
        slide = Slide(fixture_slide, "")
        random_tiles_extractor = RandomTiler(
            tile_size=tile_size,
            n_tiles=2,
            level=level,
            seed=42,
            check_tissue=check_tissue,
        )
        expected_img = load_expectation(
            expectation,
            type_="png",
        )

        tiles_location_img = random_tiles_extractor.locate_tiles(
            slide, binary_mask, scale_factor=10)

        # --- Expanding test report with actual and expected images ---
        expand_tests_report(request,
                            actual=tiles_location_img,
                            expected=expected_img)

        np.testing.assert_array_almost_equal(tiles_location_img, expected_img)

    @pytest.mark.parametrize(
        "fixture_slide, tile_size, level, seed, n_tiles",
        (
            # Squared tile size
            (SVS.TCGA_CR_7395_01A_01_TS1, (128, 128), 1, 42, 20),
            (SVS.TCGA_CR_7395_01A_01_TS1, (128, 128), 0, 42, 10),
            (SVS.TCGA_CR_7395_01A_01_TS1, (128, 128), 1, 2, 20),
            (SVS.TCGA_CR_7395_01A_01_TS1, (128, 128), 0, 2, 10),
            (TIFF.KIDNEY_48_5, (10, 10), 0, 20, 20),
            (TIFF.KIDNEY_48_5, (20, 20), 0, 20, 10),
            # Not squared tile size
            (SVS.TCGA_CR_7395_01A_01_TS1, (135, 128), 1, 42, 20),
            (SVS.TCGA_CR_7395_01A_01_TS1, (135, 128), 0, 42, 10),
            (SVS.TCGA_CR_7395_01A_01_TS1, (135, 128), 1, 2, 20),
            (TIFF.KIDNEY_48_5, (10, 20), 0, 2, 10),
            (TIFF.KIDNEY_48_5, (20, 10), 0, 20, 20),
            (TIFF.KIDNEY_48_5, (10, 15), 0, 20, 10),
        ),
    )
    def test_extract_tiles_respecting_the_given_tile_size(
            self, tmpdir, fixture_slide, tile_size, level, seed, n_tiles):
        processed_path = os.path.join(tmpdir, "processed")
        slide = Slide(fixture_slide, 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
Ejemplo n.º 26
0
class Describe_Slide:
    def it_knows_its_name(self):
        slide = Slide(SVS.CMU_1_SMALL_REGION,
                      os.path.join(SVS.CMU_1_SMALL_REGION, "processed"))

        name = slide.name

        assert name == ntpath.basename(SVS.CMU_1_SMALL_REGION).split(".")[0]

    def it_calculate_resampled_nparray_from_small_region_svs_image(self):
        slide = Slide(SVS.CMU_1_SMALL_REGION,
                      os.path.join(SVS.CMU_1_SMALL_REGION, "processed"))

        resampled_array = slide.resampled_array(scale_factor=32)

        expected_value = load_expectation(
            "svs-images/small-region-svs-resampled-array", type_="npy")
        np.testing.assert_almost_equal(resampled_array, expected_value)

    def it_knows_the_right_slide_dimension(self):
        slide = Slide(SVS.CMU_1_SMALL_REGION,
                      os.path.join(SVS.CMU_1_SMALL_REGION, "processed"))
        image = PIL.Image.open(SVS.CMU_1_SMALL_REGION)

        dimensions = slide.dimensions

        assert image.size == dimensions
        assert slide.dimensions == (2220, 2967)
        assert image.size == (2220, 2967)

    def it_raises_openslideerror_with_broken_wsi(self):
        slide = Slide(SVS.BROKEN, os.path.join(SVS.BROKEN, "processed"))

        with pytest.raises(PIL.UnidentifiedImageError) as err:
            slide._wsi

        assert isinstance(err.value, PIL.UnidentifiedImageError)
        assert (str(err.value) ==
                "Your wsi has something broken inside, a doctor is needed")

    @pytest.mark.parametrize(
        "slide_fixture, tissue_mask, binary_mask, expectation",
        [
            (
                SVS.CMU_1_SMALL_REGION,
                True,
                BiggestTissueBoxMask(),
                "cmu-1-small-region-bbox-location-tissue-mask-true",
            ),
            (
                SVS.CMU_1_SMALL_REGION,
                False,
                BiggestTissueBoxMask(),
                "cmu-1-small-region-bbox-location-tissue-mask-false",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                True,
                BiggestTissueBoxMask(),
                "tcga-cr-7395-01a-01-ts1-bbox-location-tissue-mask-true",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                False,
                BiggestTissueBoxMask(),
                "tcga-cr-7395-01a-01-ts1-bbox-location-tissue-mask-false",
            ),
            (
                SVS.CMU_1_SMALL_REGION,
                True,
                TissueMask(),
                "cmu-1-small-region-tissue-location-tissue-mask-true",
            ),
            (
                SVS.CMU_1_SMALL_REGION,
                False,
                TissueMask(),
                "cmu-1-small-region-tissue-location-tissue-mask-false",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                True,
                TissueMask(),
                "tcga-cr-7395-01a-01-ts1-tissue-location-tissue-mask-true",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                False,
                TissueMask(),
                "tcga-cr-7395-01a-01-ts1-tissue-location-tissue-mask-false",
            ),
        ],
    )
    def it_locates_the_mask(self, tmpdir, slide_fixture, tissue_mask,
                            binary_mask, expectation):
        slide = Slide(slide_fixture, os.path.join(tmpdir, "processed"))
        expected_img = load_expectation(
            os.path.join("mask-location-images", expectation),
            type_="png",
        )

        mask_location_img = slide.locate_mask(binary_mask,
                                              tissue_mask=tissue_mask,
                                              scale_factor=3)

        np.testing.assert_array_almost_equal(np.asarray(mask_location_img),
                                             expected_img)

    def it_knows_its_properties(self):
        slide = Slide(SVS.CMU_1_SMALL_REGION, "processed")

        properties = slide.properties

        assert isinstance(properties, dict)
        assert properties == load_python_expression(
            "python-expr/slide_properties_dict")
Ejemplo n.º 27
0
class DescribeGridTiler:
    @pytest.mark.parametrize(
        "fixture_slide, binary_mask, tile_size, level,check_tissue, expectation",
        [
            (
                SVS.CMU_1_SMALL_REGION,
                BiggestTissueBoxMask(),
                (512, 512),
                0,
                False,
                "tiles-location-images/cmu-1-small-region-tl-grid-BTB-false-512x512",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                TissueMask(),
                (512, 550),
                -2,
                False,
                "tiles-location-images/tcga-cr-7395-01a-01-ts1-tl-grid-TM-f-512x550",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                BiggestTissueBoxMask(),
                (512, 512),
                0,
                False,
                "tiles-location-images/tcga-cr-7395-01a-01-ts1-tl-grid-BTB-f-512x512",
            ),
            (
                SVS.CMU_1_SMALL_REGION,
                TissueMask(),
                (128, 120),
                0,
                True,
                "tiles-location-images/cmu-1-small-region-tl-grid-TM-true-128x120",
            ),
            (
                SVS.CMU_1_SMALL_REGION,
                TissueMask(),
                (128, 120),
                0,
                False,
                "tiles-location-images/cmu-1-small-region-tl-grid-TM-false-128x120",
            ),
            (
                SVS.TCGA_CR_7395_01A_01_TS1,
                TissueMask(),
                (128, 128),
                0,
                True,
                "tiles-location-images/tcga-cr-7395-01a-01-ts1-tl-grid-TM-true-128x128",
            ),
            (
                TIFF.KIDNEY_48_5,
                TissueMask(),
                (15, 10),
                0,
                True,
                "tiles-location-images/kidney-48-5-grid-TM-true-15x10",
            ),
            (
                TIFF.KIDNEY_48_5,
                BiggestTissueBoxMask(),
                (20, 20),
                0,
                False,
                "tiles-location-images/kidney-48-5-grid-TM-false-20x20",
            ),
            pytest.param(
                EXTERNAL_SVS.CMU_3,
                BiggestTissueBoxMask(),
                (512, 512),
                1,
                False,
                "tiles-location-images/external-cmu-3-grid-BTB-false-512x512",
                marks=pytest.mark.skipif(not on_ci(),
                                         reason="To run only on CI"),
            ),
            pytest.param(
                EXTERNAL_SVS.CMU_3,
                TissueMask(),
                (512, 512),
                1,
                False,
                "tiles-location-images/external-cmu-3-grid-TM-false-512x512",
                marks=pytest.mark.skipif(not on_ci(),
                                         reason="To run only on CI"),
            ),
        ],
    )
    def it_locates_tiles_on_the_slide(
        self,
        request,
        fixture_slide,
        binary_mask,
        tile_size,
        level,
        check_tissue,
        expectation,
    ):
        slide = Slide(fixture_slide, "")
        grid_tiles_extractor = GridTiler(
            tile_size=tile_size,
            level=level,
            check_tissue=check_tissue,
        )
        expected_img = load_expectation(expectation, type_="png")

        tiles_location_img = grid_tiles_extractor.locate_tiles(slide,
                                                               binary_mask,
                                                               scale_factor=10)

        # --- Expanding test report with actual and expected images ---
        expand_tests_report(request,
                            expected=expected_img,
                            actual=tiles_location_img)

        np.testing.assert_array_almost_equal(tiles_location_img, expected_img)