From 3a779c8af88fd7c658dfe707b66867c3c1eccef3 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Mon, 29 Nov 2021 20:42:15 +0000 Subject: [PATCH 1/9] Update WSIReader level/location/size calculation Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- monai/data/image_reader.py | 73 ++++++++++++++++++++++++++++---------- tests/test_wsireader.py | 12 +++++-- 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index 6e9cbca809..7834d2b1d5 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -765,19 +765,23 @@ def get_data( grid_shape: (row, columns) tuple define a grid to extract patches on that patch_size: (height, width) the size of extracted patches at the given level """ - if level is None: - level = self.level - - if self.backend == "openslide" and size is None: - # the maximum size is set to WxH at the specified level - size = (img.shape[0] // (2 ** level) - location[0], img.shape[1] // (2 ** level) - location[1]) + # Verify inputs + level = self._check_level(img, level) + location = self._check_location(img, level, location) + size = self._check_image_size(img, size, level, location) + # Extract patch (or the whole image) region = self._extract_region(img, location=location, size=size, level=level, dtype=dtype) + # Add necessary metadata metadata: Dict = {} metadata["spatial_shape"] = np.asarray(region.shape[:-1]) metadata["original_channel_dim"] = -1 + + # Make it channel first region = EnsureChannelFirst()(region, metadata) + + # Split into patches if patch_size is None: patches = region else: @@ -788,10 +792,49 @@ def get_data( return patches, metadata + def _check_level(self, img, level): + if level is None: + level = self.level + + level_count = 0 + if self.backend == "openslide": + level_count = img.level_count + elif self.backend == "cucim": + level_count = img.resolutions["level_count"] + elif self.backend == "tifffile": + level_count = len(img.pages) + + if level > level_count - 1: + raise ValueError(f"The maximum level of this image is {level_count - 1} while level={level} is requested)!") + + return level + + def _check_location(self, img, level, location): + if self.backend == "tifffile" and location != (0, 0): + level0_size = img.pages[0].shape[:2] + max_size = img.pages[level].shape[:2] + location = [int(location[i] / level0_size[i] * max_size[i]) for i in range(len(location))] + return location + + def _check_image_size(self, img, size, level, location): + if size is None: + max_size = [] + if self.backend == "openslide": + max_size = img.level_dimensions[level][::-1] + elif self.backend == "cucim": + max_size = img.resolutions["level_dimensions"][level][::-1] + elif self.backend == "tifffile": + max_size = img.pages[level].shape[:2] + + # subtract the top left corner of the patch from maximum size + size = [max_size[i] - location[i] for i in range(len(max_size))] + + return size + def _extract_region( self, img_obj, - size: Optional[Tuple[int, int]], + size: Tuple[int, int], location: Tuple[int, int] = (0, 0), level: int = 0, dtype: DtypeLike = np.uint8, @@ -799,19 +842,12 @@ def _extract_region( if self.backend == "tifffile": with img_obj: region = img_obj.asarray(level=level) - if size is None: - region = region[location[0] :, location[1] :] - else: - region = region[location[0] : location[0] + size[0], location[1] : location[1] + size[1]] - + region = region[location[0] : location[0] + size[0], location[1] : location[1] + size[1]] else: - # reverse the order of dimensions for size and location to be compatible with image shape + # reverse the order of dimensions for size and location to become WxH location = location[::-1] - if size is None: - region = img_obj.read_region(location=location, level=level) - else: - size = size[::-1] - region = img_obj.read_region(location=location, size=size, level=level) + size = size[::-1] + region = img_obj.read_region(location=location, size=size, level=level) region = self.convert_to_rgb_array(region, dtype) return region @@ -824,6 +860,7 @@ def convert_to_rgb_array(self, raw_region, dtype: DtypeLike = np.uint8): # convert to numpy (if not already in numpy) raw_region = np.asarray(raw_region, dtype=dtype) + # remove alpha channel if exist (RGBA) if raw_region.shape[-1] > 3: raw_region = raw_region[..., :3] diff --git a/tests/test_wsireader.py b/tests/test_wsireader.py index 61eb2d82ce..3af1389aad 100644 --- a/tests/test_wsireader.py +++ b/tests/test_wsireader.py @@ -69,6 +69,12 @@ np.array([[[[239]], [[239]], [[239]]], [[[243]], [[243]], [[243]]]]), ] +TEST_CASE_5 = [ + FILE_PATH, + {"location": (171, 128), "level": 8, "grid_shape": (2, 1), "patch_size": 1}, + np.array([[[[239]], [[239]], [[239]]], [[[243]], [[243]], [[243]]]]), +] + TEST_CASE_RGB_0 = [np.ones((3, 2, 2), dtype=np.uint8)] # CHW TEST_CASE_RGB_1 = [np.ones((3, 100, 100), dtype=np.uint8)] # CHW @@ -92,7 +98,7 @@ def save_rgba_tiff(array: np.ndarray, filename: str, mode: str): return filename -@skipUnless(has_cucim or has_osl, "Requires cucim or openslide!") +@skipUnless(has_cucim or has_osl or has_tiff, "Requires cucim, openslide, or tifffile!") def setUpModule(): # noqa: N802 download_url(FILE_URL, FILE_PATH, "5a3cfd4fd725c50578ddb80b517b759f") @@ -114,7 +120,9 @@ def test_read_region(self, file_path, patch_info, expected_img): img_obj = reader.read(file_path) # Read twice to check multiple calls img = reader.get_data(img_obj, **patch_info)[0] - img = reader.get_data(img_obj, **patch_info)[0] + img2 = reader.get_data(img_obj, **patch_info)[0] + self.assertTupleEqual(img.shape, img2.shape) + self.assertIsNone(assert_array_equal(img, img2)) self.assertTupleEqual(img.shape, expected_img.shape) self.assertIsNone(assert_array_equal(img, expected_img)) From da259889b0ad0b50df1fdd4448b03723d719ef53 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Mon, 29 Nov 2021 22:50:52 +0000 Subject: [PATCH 2/9] Update location downsampling Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- monai/data/image_reader.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index 7834d2b1d5..c039da670a 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -686,8 +686,8 @@ class WSIReader(ImageReader): This is overridden if the level argument is provided in `get_data`. Note: - While "cucim" and "OpenSlide" backends both can load patches from large whole slide images - without loading the entire image into memory, "Tifffile" backend needs to load the entire image into memory + While "cuCim" and "OpenSlide" backends both can load patches from large whole slide images + without loading the entire image into memory, "TiffFile" backend needs to load the entire image into memory before extracting any patch; thus, memory consideration is needed when using "Tifffile" backend for patch extraction. """ @@ -767,7 +767,6 @@ def get_data( """ # Verify inputs level = self._check_level(img, level) - location = self._check_location(img, level, location) size = self._check_image_size(img, size, level, location) # Extract patch (or the whole image) @@ -809,25 +808,24 @@ def _check_level(self, img, level): return level - def _check_location(self, img, level, location): - if self.backend == "tifffile" and location != (0, 0): - level0_size = img.pages[0].shape[:2] - max_size = img.pages[level].shape[:2] - location = [int(location[i] / level0_size[i] * max_size[i]) for i in range(len(location))] - return location - def _check_image_size(self, img, size, level, location): if size is None: max_size = [] + downsampling_factor = [] if self.backend == "openslide": + downsampling_factor = img.level_downsamples[level] max_size = img.level_dimensions[level][::-1] elif self.backend == "cucim": + downsampling_factor = img.resolutions["level_downsamples"][level] max_size = img.resolutions["level_dimensions"][level][::-1] elif self.backend == "tifffile": + level0_size = img.pages[0].shape[:2] max_size = img.pages[level].shape[:2] + downsampling_factor = np.mean([level0_size[i] / max_size[i] for i in range(len(max_size))]) # subtract the top left corner of the patch from maximum size - size = [max_size[i] - location[i] for i in range(len(max_size))] + level_location = [round(location[i] / downsampling_factor) for i in range(len(location))] + size = [max_size[i] - level_location[i] for i in range(len(max_size))] return size @@ -840,8 +838,12 @@ def _extract_region( dtype: DtypeLike = np.uint8, ): if self.backend == "tifffile": - with img_obj: - region = img_obj.asarray(level=level) + # with img_obj: + region = img_obj.asarray(level=level) + if level != 0: + level0_size = img_obj.pages[0].shape[:2] + max_size = img_obj.pages[level].shape[:2] + location = [int(location[i] / level0_size[i] * max_size[i]) for i in range(len(location))] region = region[location[0] : location[0] + size[0], location[1] : location[1] + size[1]] else: # reverse the order of dimensions for size and location to become WxH From 44fd4e49522514553f8cdfc0253a97eb01c0856a Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Mon, 29 Nov 2021 23:06:32 +0000 Subject: [PATCH 3/9] Update tests and add a new test case Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- tests/test_wsireader.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/tests/test_wsireader.py b/tests/test_wsireader.py index 3af1389aad..119a3dd74b 100644 --- a/tests/test_wsireader.py +++ b/tests/test_wsireader.py @@ -71,10 +71,11 @@ TEST_CASE_5 = [ FILE_PATH, - {"location": (171, 128), "level": 8, "grid_shape": (2, 1), "patch_size": 1}, - np.array([[[[239]], [[239]], [[239]]], [[[243]], [[243]], [[243]]]]), + {"location": (HEIGHT - 2, WIDTH - 2), "level": 0, "grid_shape": (1, 1)}, + np.array([[[239, 239], [239, 239]], [[239, 239], [239, 239]], [[237, 237], [237, 237]]]), ] + TEST_CASE_RGB_0 = [np.ones((3, 2, 2), dtype=np.uint8)] # CHW TEST_CASE_RGB_1 = [np.ones((3, 100, 100), dtype=np.uint8)] # CHW @@ -107,20 +108,20 @@ class WSIReaderTests: class Tests(unittest.TestCase): backend = None - @parameterized.expand([TEST_CASE_0]) - def test_read_whole_image(self, file_path, level, expected_shape): - reader = WSIReader(self.backend, level=level) - img_obj = reader.read(file_path) - img = reader.get_data(img_obj)[0] - self.assertTupleEqual(img.shape, expected_shape) + # @parameterized.expand([TEST_CASE_0]) + # def test_read_whole_image(self, file_path, level, expected_shape): + # reader = WSIReader(self.backend, level=level) + # with reader.read(file_path) as img_obj: + # img = reader.get_data(img_obj)[0] + # self.assertTupleEqual(img.shape, expected_shape) - @parameterized.expand([TEST_CASE_1, TEST_CASE_2]) + @parameterized.expand([TEST_CASE_1, TEST_CASE_2, TEST_CASE_5]) def test_read_region(self, file_path, patch_info, expected_img): reader = WSIReader(self.backend) - img_obj = reader.read(file_path) # Read twice to check multiple calls - img = reader.get_data(img_obj, **patch_info)[0] - img2 = reader.get_data(img_obj, **patch_info)[0] + with reader.read(file_path) as img_obj: + img = reader.get_data(img_obj, **patch_info)[0] + img2 = reader.get_data(img_obj, **patch_info)[0] self.assertTupleEqual(img.shape, img2.shape) self.assertIsNone(assert_array_equal(img, img2)) self.assertTupleEqual(img.shape, expected_img.shape) @@ -129,8 +130,8 @@ def test_read_region(self, file_path, patch_info, expected_img): @parameterized.expand([TEST_CASE_3, TEST_CASE_4]) def test_read_patches(self, file_path, patch_info, expected_img): reader = WSIReader(self.backend) - img_obj = reader.read(file_path) - img = reader.get_data(img_obj, **patch_info)[0] + with reader.read(file_path) as img_obj: + img = reader.get_data(img_obj, **patch_info)[0] self.assertTupleEqual(img.shape, expected_img.shape) self.assertIsNone(assert_array_equal(img, expected_img)) @@ -148,8 +149,8 @@ def test_read_rgba(self, img_expected): os.path.join(os.path.dirname(__file__), "testing_data", f"temp_tiff_image_{mode}.tiff"), mode=mode, ) - img_obj = reader.read(file_path) - image[mode], _ = reader.get_data(img_obj) + with reader.read(file_path) as img_obj: + image[mode], _ = reader.get_data(img_obj) self.assertIsNone(assert_array_equal(image["RGB"], img_expected)) self.assertIsNone(assert_array_equal(image["RGBA"], img_expected)) From 2ab1e15ddb624581ef9092e7d1e1b05607079687 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Mon, 29 Nov 2021 23:16:42 +0000 Subject: [PATCH 4/9] Update few names and logics Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- monai/data/image_reader.py | 51 ++++++++++++++++++++------------------ tests/test_wsireader.py | 12 ++++----- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index c039da670a..defae7a95f 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -766,8 +766,10 @@ def get_data( patch_size: (height, width) the size of extracted patches at the given level """ # Verify inputs - level = self._check_level(img, level) - size = self._check_image_size(img, size, level, location) + if level is None: + level = self._evaluate_level(img, level) + if size is None: + size = self._evaluate_image_size(img, size, level, location) # Extract patch (or the whole image) region = self._extract_region(img, location=location, size=size, level=level, dtype=dtype) @@ -791,9 +793,8 @@ def get_data( return patches, metadata - def _check_level(self, img, level): - if level is None: - level = self.level + def _evaluate_level(self, img, level): + level = self.level level_count = 0 if self.backend == "openslide": @@ -808,24 +809,23 @@ def _check_level(self, img, level): return level - def _check_image_size(self, img, size, level, location): - if size is None: - max_size = [] - downsampling_factor = [] - if self.backend == "openslide": - downsampling_factor = img.level_downsamples[level] - max_size = img.level_dimensions[level][::-1] - elif self.backend == "cucim": - downsampling_factor = img.resolutions["level_downsamples"][level] - max_size = img.resolutions["level_dimensions"][level][::-1] - elif self.backend == "tifffile": - level0_size = img.pages[0].shape[:2] - max_size = img.pages[level].shape[:2] - downsampling_factor = np.mean([level0_size[i] / max_size[i] for i in range(len(max_size))]) - - # subtract the top left corner of the patch from maximum size - level_location = [round(location[i] / downsampling_factor) for i in range(len(location))] - size = [max_size[i] - level_location[i] for i in range(len(max_size))] + def _evaluate_image_size(self, img, size, level, location): + max_size = [] + downsampling_factor = [] + if self.backend == "openslide": + downsampling_factor = img.level_downsamples[level] + max_size = img.level_dimensions[level][::-1] + elif self.backend == "cucim": + downsampling_factor = img.resolutions["level_downsamples"][level] + max_size = img.resolutions["level_dimensions"][level][::-1] + elif self.backend == "tifffile": + level0_size = img.pages[0].shape[:2] + max_size = img.pages[level].shape[:2] + downsampling_factor = np.mean([level0_size[i] / max_size[i] for i in range(len(max_size))]) + + # subtract the top left corner of the patch from maximum size + level_location = [round(location[i] / downsampling_factor) for i in range(len(location))] + size = [max_size[i] - level_location[i] for i in range(len(max_size))] return size @@ -843,7 +843,10 @@ def _extract_region( if level != 0: level0_size = img_obj.pages[0].shape[:2] max_size = img_obj.pages[level].shape[:2] - location = [int(location[i] / level0_size[i] * max_size[i]) for i in range(len(location))] + location = ( + int(location[0] / level0_size[0] * max_size[0]), + int(location[1] / level0_size[1] * max_size[1]), + ) region = region[location[0] : location[0] + size[0], location[1] : location[1] + size[1]] else: # reverse the order of dimensions for size and location to become WxH diff --git a/tests/test_wsireader.py b/tests/test_wsireader.py index 119a3dd74b..1bba10a807 100644 --- a/tests/test_wsireader.py +++ b/tests/test_wsireader.py @@ -108,12 +108,12 @@ class WSIReaderTests: class Tests(unittest.TestCase): backend = None - # @parameterized.expand([TEST_CASE_0]) - # def test_read_whole_image(self, file_path, level, expected_shape): - # reader = WSIReader(self.backend, level=level) - # with reader.read(file_path) as img_obj: - # img = reader.get_data(img_obj)[0] - # self.assertTupleEqual(img.shape, expected_shape) + @parameterized.expand([TEST_CASE_0]) + def test_read_whole_image(self, file_path, level, expected_shape): + reader = WSIReader(self.backend, level=level) + with reader.read(file_path) as img_obj: + img = reader.get_data(img_obj)[0] + self.assertTupleEqual(img.shape, expected_shape) @parameterized.expand([TEST_CASE_1, TEST_CASE_2, TEST_CASE_5]) def test_read_region(self, file_path, patch_info, expected_img): From 6f8f01525cd7a84092ed3310ba0e4154db41d1b0 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Tue, 30 Nov 2021 18:57:34 +0000 Subject: [PATCH 5/9] Fix the dependency issue Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- monai/data/image_reader.py | 6 +++--- tests/test_wsireader.py | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index defae7a95f..2b148b24cd 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -681,14 +681,14 @@ class WSIReader(ImageReader): Read whole slide images and extract patches. Args: - backend: backend library to load the images, available options: "cuCIM", "OpenSlide" and "Tifffile". + backend: backend library to load the images, available options: "cuCIM", "OpenSlide" and "TiffFile". level: the whole slide image level at which the image is extracted. (default=0) This is overridden if the level argument is provided in `get_data`. Note: - While "cuCim" and "OpenSlide" backends both can load patches from large whole slide images + While "cuCIM" and "OpenSlide" backends both can load patches from large whole slide images without loading the entire image into memory, "TiffFile" backend needs to load the entire image into memory - before extracting any patch; thus, memory consideration is needed when using "Tifffile" backend for + before extracting any patch; thus, memory consideration is needed when using "TiffFile" backend for patch extraction. """ diff --git a/tests/test_wsireader.py b/tests/test_wsireader.py index 1bba10a807..1968779eb1 100644 --- a/tests/test_wsireader.py +++ b/tests/test_wsireader.py @@ -158,7 +158,10 @@ def test_read_rgba(self, img_expected): @parameterized.expand([TEST_CASE_TRANSFORM_0]) def test_with_dataloader(self, file_path, level, expected_spatial_shape, expected_shape): train_transform = Compose( - [LoadImaged(keys=["image"], reader=WSIReader, backend="cuCIM", level=level), ToTensord(keys=["image"])] + [ + LoadImaged(keys=["image"], reader=WSIReader, backend=self.backend, level=level), + ToTensord(keys=["image"]), + ] ) dataset = Dataset([{"image": file_path}], transform=train_transform) data_loader = DataLoader(dataset) From b9a75ab4d988984c96b2c1a7987e81e6bd3de7a4 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Tue, 30 Nov 2021 20:06:54 +0000 Subject: [PATCH 6/9] Check for imagecodecs + tifffile Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- tests/test_wsireader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_wsireader.py b/tests/test_wsireader.py index 1968779eb1..0d778f9e88 100644 --- a/tests/test_wsireader.py +++ b/tests/test_wsireader.py @@ -28,6 +28,8 @@ has_cucim = has_cucim and hasattr(cucim, "CuImage") _, has_osl = optional_import("openslide") imsave, has_tiff = optional_import("tifffile", name="imsave") +_, has_codec = optional_import("imagecodecs") +has_tiff = has_tiff and has_codec FILE_URL = "https://drive.google.com/uc?id=1sGTKZlJBIz53pfqTxoTqiIQzIoEzHLAe" base_name, extension = FILE_URL.split("id=")[1], ".tiff" From 6051abf9be286babfff7252dc4be72a197bb96b0 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Tue, 30 Nov 2021 21:07:23 +0000 Subject: [PATCH 7/9] Remove new test case that uses too much memory Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- tests/test_wsireader.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/test_wsireader.py b/tests/test_wsireader.py index 0d778f9e88..907a2dcf6c 100644 --- a/tests/test_wsireader.py +++ b/tests/test_wsireader.py @@ -71,12 +71,6 @@ np.array([[[[239]], [[239]], [[239]]], [[[243]], [[243]], [[243]]]]), ] -TEST_CASE_5 = [ - FILE_PATH, - {"location": (HEIGHT - 2, WIDTH - 2), "level": 0, "grid_shape": (1, 1)}, - np.array([[[239, 239], [239, 239]], [[239, 239], [239, 239]], [[237, 237], [237, 237]]]), -] - TEST_CASE_RGB_0 = [np.ones((3, 2, 2), dtype=np.uint8)] # CHW @@ -117,7 +111,7 @@ def test_read_whole_image(self, file_path, level, expected_shape): img = reader.get_data(img_obj)[0] self.assertTupleEqual(img.shape, expected_shape) - @parameterized.expand([TEST_CASE_1, TEST_CASE_2, TEST_CASE_5]) + @parameterized.expand([TEST_CASE_1, TEST_CASE_2]) def test_read_region(self, file_path, patch_info, expected_img): reader = WSIReader(self.backend) # Read twice to check multiple calls From fc6d0aa536aa8496c9a83d733cdebf0163e580e4 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Wed, 1 Dec 2021 16:07:03 +0000 Subject: [PATCH 8/9] Add new case and ignore level=0 for TiffFile Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- tests/test_wsireader.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_wsireader.py b/tests/test_wsireader.py index 907a2dcf6c..e47a22908a 100644 --- a/tests/test_wsireader.py +++ b/tests/test_wsireader.py @@ -71,6 +71,12 @@ np.array([[[[239]], [[239]], [[239]]], [[[243]], [[243]], [[243]]]]), ] +TEST_CASE_5 = [ + FILE_PATH, + {"location": (HEIGHT - 2, WIDTH - 2), "level": 0, "grid_shape": (1, 1)}, + np.array([[[239, 239], [239, 239]], [[239, 239], [239, 239]], [[237, 237], [237, 237]]]), +] + TEST_CASE_RGB_0 = [np.ones((3, 2, 2), dtype=np.uint8)] # CHW @@ -111,8 +117,11 @@ def test_read_whole_image(self, file_path, level, expected_shape): img = reader.get_data(img_obj)[0] self.assertTupleEqual(img.shape, expected_shape) - @parameterized.expand([TEST_CASE_1, TEST_CASE_2]) + @parameterized.expand([TEST_CASE_1, TEST_CASE_2, TEST_CASE_5]) def test_read_region(self, file_path, patch_info, expected_img): + # Due to CPU memory limitation ignore tifffile at level 0. + if self.backend == "tifffile" and patch_info["level"] == 0: + return reader = WSIReader(self.backend) # Read twice to check multiple calls with reader.read(file_path) as img_obj: From f581114debe3b72b67a7d4902a2d00de310ccfb8 Mon Sep 17 00:00:00 2001 From: Behrooz <3968947+drbeh@users.noreply.github.com> Date: Wed, 1 Dec 2021 16:50:37 +0000 Subject: [PATCH 9/9] Address comments Signed-off-by: Behrooz <3968947+drbeh@users.noreply.github.com> --- monai/data/image_reader.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index 2b148b24cd..a620e06216 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -767,9 +767,9 @@ def get_data( """ # Verify inputs if level is None: - level = self._evaluate_level(img, level) + level = self._check_level(img, level) if size is None: - size = self._evaluate_image_size(img, size, level, location) + size = self._get_image_size(img, size, level, location) # Extract patch (or the whole image) region = self._extract_region(img, location=location, size=size, level=level, dtype=dtype) @@ -793,7 +793,7 @@ def get_data( return patches, metadata - def _evaluate_level(self, img, level): + def _check_level(self, img, level): level = self.level level_count = 0 @@ -809,7 +809,7 @@ def _evaluate_level(self, img, level): return level - def _evaluate_image_size(self, img, size, level, location): + def _get_image_size(self, img, size, level, location): max_size = [] downsampling_factor = [] if self.backend == "openslide":