예제 #1
0
    def it_can_generate_grid_tiles_with_no_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=False)
        tiles = [tile1, tile2]

        generated_tiles = list(grid_tiler._tiles_generator(slide))

        _grid_coordinates_generator.assert_called_once_with(grid_tiler, slide)
        assert _extract_tile.call_args_list == ([
            call(slide, CP(0, 10, 0, 10), 0),
            call(slide, CP(0, 10, 0, 10), 0)
        ])
        _has_enough_tissue.assert_not_called()
        assert len(generated_tiles) == expected_n_tiles
        for i, tile in enumerate(generated_tiles):
            assert tile[0] == tiles[i]
예제 #2
0
    def it_can_generate_grid_tiles(
        self,
        request,
        tmpdir,
        tile1,
        tile2,
        check_tissue,
        has_enough_tissue,
        expected_n_tiles,
    ):
        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, "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
        _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=check_tissue)
        tiles = [tile1, tile2]

        generated_tiles = list(grid_tiler._tiles_generator(slide))

        _grid_coordinates_generator.assert_called_once_with(grid_tiler, slide)
        assert _extract_tile.call_args_list == (
            [call(slide, CP(0, 10, 0, 10), 0), call(slide, CP(0, 10, 0, 10), 0)]
        )
        assert len(generated_tiles) == expected_n_tiles
        for i, tile in enumerate(generated_tiles):
            assert tile[0] == tiles[i]
예제 #3
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))
예제 #4
0
    def it_knows_its_biggest_tissue_box_mask(
        self,
        request,
        tmpdir,
        RgbToGrayscale_,
        OtsuThreshold_,
        BinaryDilation_,
        RemoveSmallHoles_,
        RemoveSmallObjects_,
    ):
        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, "processed")
        regions = [
            Region(index=0, area=33, bbox=(0, 0, 2, 2), center=(0.5, 0.5))
        ]
        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.slide.regions_from_binary_mask")
        regions_from_binary_mask.return_value = regions
        biggest_regions_ = method_mock(request,
                                       Slide,
                                       "_biggest_regions",
                                       autospec=False)
        biggest_regions_.return_value = regions
        region_coordinates_ = function_mock(
            request, "histolab.slide.region_coordinates")
        region_coordinates_.return_values = CP(0, 0, 2, 2)
        polygon_to_mask_array_ = function_mock(
            request, "histolab.util.polygon_to_mask_array")
        polygon_to_mask_array_((1000, 1000), CP(0, 0, 2, 2)).return_value = [
            [True, True],
            [False, True],
        ]

        biggest_mask_tissue_box = slide.biggest_tissue_box_mask

        region_coordinates_.assert_called_once_with(regions[0])
        biggest_regions_.assert_called_once_with(regions, n=1)
        polygon_to_mask_array_.assert_called_once_with((1000, 1000),
                                                       CP(x_ul=0,
                                                          y_ul=0,
                                                          x_br=2,
                                                          y_br=2))
        np.testing.assert_almost_equal(biggest_mask_tissue_box,
                                       np.zeros((500, 500)))
예제 #5
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)]
        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, "processed")

        generated_tiles = list(random_tiler._tiles_generator(slide))

        assert generated_tiles[0][1] == CP(0, 10, 0, 10)
        assert isinstance(generated_tiles[0][0], Tile)
예제 #6
0
    def it_can_extract_grid_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, 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", "tiles",
                         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)

        grid_tiler.extract(slide)

        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", "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(grid_tiler, slide)
예제 #7
0
    def it_knows_its_coords(self):
        _coords = CP(0, 0, 50, 50)
        tile = Tile(None, _coords, 0)

        coords = tile.coords

        assert coords == _coords
예제 #8
0
    def it_can_save_report(self, request, tmpdir):
        tmp_path_ = tmpdir.mkdir("path")
        coords = CP(0, 10, 0, 10)
        highest_score_tiles = [(0.8, coords), (0.7, coords)]
        highest_scaled_score_tiles = [(0.1, coords), (0.0, coords)]
        filenames = ["tile0.png", "tile1.png"]
        random_scorer_ = instance_mock(request, RandomScorer)
        score_tiler = ScoreTiler(random_scorer_, (10, 10), 2, 2)
        report_ = [
            "filename,score,scaled_score",
            "tile0.png,0.8,0.1",
            "tile1.png,0.7,0.0",
        ]

        score_tiler._save_report(
            os.path.join(tmp_path_, "report.csv"),
            highest_score_tiles,
            highest_scaled_score_tiles,
            filenames,
        )

        assert os.path.exists(os.path.join(tmp_path_, "report.csv"))
        with open(os.path.join(tmp_path_, "report.csv"), newline="") as f:
            reader = csv.reader(f)
            report = [",".join(row) for row in reader]
            assert report == report_
예제 #9
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),
        )
예제 #10
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)]
예제 #11
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)
예제 #12
0
    def it_knows_if_is_is_almost_white(self, tile_img, expected_result):
        coords = CP(0, 512, 0, 512)
        tile = Tile(tile_img, coords)

        is_almost_white = tile._is_almost_white

        assert is_almost_white == expected_result
예제 #13
0
    def it_can_generate_random_coordinates(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, "processed")
        _box_mask_thumb = method_mock(request, RandomTiler, "box_mask")
        _box_mask_thumb.return_value = NpArrayMock.ONES_500X500_BOOL
        _tile_size = property_mock(request, RandomTiler, "tile_size")
        _tile_size.return_value = (128, 128)
        _np_random_choice1 = function_mock(request, "numpy.random.choice")
        _np_random_choice1.return_value = 0
        _np_random_choice2 = function_mock(request, "numpy.random.choice")
        _np_random_choice2.return_value = 0
        _scale_coordinates = function_mock(request, "histolab.tiler.scale_coordinates")
        random_tiler = RandomTiler((128, 128), 10, 0)

        random_tiler._random_tile_coordinates(slide)

        _box_mask_thumb.assert_called_once_with(slide)
        _tile_size.assert_has_calls([call((128, 128))])
        _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),
        )
예제 #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)

        generated_tiles = list(random_tiler._tiles_generator(slide))

        assert generated_tiles[0][1] == CP(0, 10, 0, 10)
        assert isinstance(generated_tiles[0][0], Tile)
예제 #15
0
def test_region_coordinates():
    region = Region(index=0,
                    area=14,
                    bbox=(0, 1, 1, 2),
                    center=(0.5, 0.5),
                    coords=None)
    region_coords_ = region_coordinates(region)

    assert region_coords_ == CP(x_ul=1, y_ul=0, x_br=2, y_br=1)
예제 #16
0
    def but_it_has_wrong_image_type(self):
        """This test simulates a wrong user behaviour, using a None object instead of a
        PIL Image for image param"""
        with pytest.raises(AttributeError) as err:
            tile = Tile(None, CP(0, 0, 50, 50), 0)
            tile.has_enough_tissue()

        assert isinstance(err.value, AttributeError)
        assert str(err.value) == "'NoneType' object has no attribute 'convert'"
예제 #17
0
    def it_constructs_from_args(self, request):
        _init = initializer_mock(request, Tile)
        _image = PILIMG.RGBA_COLOR_50X50_155_0_0
        _level = 0
        _coords = CP(0, 0, 50, 50)

        tile = Tile(_image, _coords, _level)

        _init.assert_called_once_with(ANY, _image, _coords, _level)
        assert isinstance(tile, Tile)
예제 #18
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)],
        )
예제 #19
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)

        generated_tiles = list(grid_tiler._tiles_generator(slide))

        _grid_coordinates_generator.assert_called_once_with(grid_tiler, slide)
        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
예제 #20
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))
        generated_tiles = list(grid_tiler._tiles_generator(slide))

        assert len(generated_tiles) == 0
        _grid_coordinates_generator.assert_called_once_with(grid_tiler, slide)
예제 #21
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]
예제 #22
0
    def it_can_scale_scores(self):
        coords = [CP(0, 10 * i, 0, 10) for i in range(3)]
        scores = [0.3, 0.4, 0.7]
        scores_ = list(zip(scores, coords))
        score_tiler = ScoreTiler(None, (10, 10), 2, 0)
        expected_scaled_coords = list(zip([0.0, 0.2500000000000001, 1.0], coords))

        scaled_scores = score_tiler._scale_scores(scores_)

        for (score, coords_), (expected_score, expected_coords) in zip(
            scaled_scores, expected_scaled_coords
        ):
            assert round(score, 5) == round(expected_score, 5)
            assert coords_ == expected_coords
예제 #23
0
    def but_with_wrong_coordinates(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, "processed")
        _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)

        generated_tiles = list(grid_tiler._tiles_generator(slide))

        _grid_coordinates_generator.assert_called_once_with(grid_tiler, slide)
        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
예제 #24
0
    def and_doesnt_raise_error_with_wrong_coordinates(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, "processed")
        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))
        generated_tiles = list(grid_tiler._tiles_generator(slide))

        assert len(generated_tiles) == 0
        _grid_coordinates_generator.assert_called_once_with(grid_tiler, slide)
예제 #25
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)

        highest_score_tiles = score_tiler._highest_score_tiles(slide)

        _scores.assert_called_once_with(score_tiler, slide)
        assert highest_score_tiles == expected_value
예제 #26
0
    def but_it_raises_error_with_negative_n_tiles_value(self, request):
        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), -1, 0)

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

        assert isinstance(err.value, ValueError)
        assert str(err.value) == "'n_tiles' cannot be negative (-1)"
예제 #27
0
    def it_can_extract_score_tiles(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"))
        _highest_score_tiles = method_mock(request, ScoreTiler, "_highest_score_tiles")
        coords = CP(0, 10, 0, 10)
        tile = Tile(image, coords)
        _extract_tile.return_value = tile
        _highest_score_tiles.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")
        random_scorer = RandomScorer()
        score_tiler = ScoreTiler(random_scorer, (10, 10), 2, 2)

        score_tiler.extract(slide)

        assert _extract_tile.call_args_list == [
            call(slide, coords, 2),
            call(slide, coords, 2),
        ]
        _highest_score_tiles.assert_called_once_with(score_tiler, slide)
        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", "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")
        )
        _save_report.assert_not_called()
예제 #28
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)
예제 #29
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, RandomTiler, "box_mask")
        _box_mask_thumb.return_value = NpArrayMock.ONES_500X500_BOOL
        _tile_size = property_mock(request, RandomTiler, "tile_size")
        _tile_size.return_value = (128, 128)
        _np_random_choice1 = function_mock(request, "numpy.random.choice")
        _np_random_choice1.return_value = 0
        _np_random_choice2 = function_mock(request, "numpy.random.choice")
        _np_random_choice2.return_value = 0
        _scale_coordinates = function_mock(request,
                                           "histolab.tiler.scale_coordinates")
        random_tiler = RandomTiler((128, 128), 10, 0)

        random_tiler._random_tile_coordinates(slide)

        _box_mask_thumb.assert_called_once_with(slide)
        _tile_size.assert_has_calls([call((128, 128))])
        _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),
        )
예제 #30
0
    def it_knows_if_it_has_only_some_tissue(self, tile_image, expected_value):
        tile = Tile(tile_image, CP(5, 5, 5, 5))

        assert tile._has_only_some_tissue() == expected_value