diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index cd1486d6d3..a2ddb74334 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -25,21 +25,17 @@ from .utils import is_supported_format if TYPE_CHECKING: - import cucim import itk # type: ignore import nibabel as nib - import openslide from nibabel.nifti1 import Nifti1Image from PIL import Image as PILImage - has_itk = has_nib = has_pil = has_cim = has_osl = True + has_itk = has_nib = has_pil = True else: itk, has_itk = optional_import("itk", allow_namespace_pkg=True) nib, has_nib = optional_import("nibabel") Nifti1Image, _ = optional_import("nibabel.nifti1", name="Nifti1Image") PILImage, has_pil = optional_import("PIL.Image") - cucim, has_cim = optional_import("cucim") - openslide, has_osl = optional_import("openslide") __all__ = ["ImageReader", "ITKReader", "NibabelReader", "NumpyReader", "PILReader", "WSIReader"] @@ -670,11 +666,9 @@ def __init__(self, reader_lib: str = "OpenSlide"): super().__init__() self.reader_lib = reader_lib.lower() if self.reader_lib == "openslide": - if has_osl: - self.wsi_reader = openslide.OpenSlide + self.wsi_reader, *_ = optional_import("openslide", name="OpenSlide") elif self.reader_lib == "cucim": - if has_cim: - self.wsi_reader = cucim.CuImage + self.wsi_reader, *_ = optional_import("cucim", name="CuImage") else: raise ValueError('`reader_lib` should be either "cuCIM" or "OpenSlide"') @@ -697,11 +691,6 @@ def read(self, data: Union[Sequence[str], str, np.ndarray], **kwargs): data: file name or a list of file names to read. """ - if (self.reader_lib == "openslide") and (not has_osl): - raise ImportError("No module named 'openslide'") - if (self.reader_lib == "cucim") and (not has_cim): - raise ImportError("No module named 'cucim'") - img_: List = [] filenames: Sequence[str] = ensure_tuple(data) diff --git a/requirements-dev.txt b/requirements-dev.txt index ed8739ded8..e28f85b244 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -31,8 +31,10 @@ Sphinx==3.5.3 recommonmark==0.6.0 sphinx-autodoc-typehints==1.11.1 sphinx-rtd-theme==0.5.2 -cucim~=0.19.0; platform_system == "Linux" +cucim>=21.8.2; platform_system == "Linux" openslide-python==1.1.2 +imagecodecs; platform_system == "Linux" +tifffile; platform_system == "Linux" pandas requests einops diff --git a/setup.cfg b/setup.cfg index f7ed90a14a..eddb898b0d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,7 +40,7 @@ all = tqdm>=4.47.0 lmdb psutil - cucim~=0.19.0 + cucim>=21.8.2 openslide-python==1.1.2 pandas einops @@ -68,7 +68,7 @@ lmdb = psutil = psutil cucim = - cucim~=0.19.0 + cucim>=21.8.2 openslide = openslide-python==1.1.2 pandas = diff --git a/tests/test_cuimage_reader.py b/tests/test_cuimage_reader.py index 2cbfaec113..34df4b5fe4 100644 --- a/tests/test_cuimage_reader.py +++ b/tests/test_cuimage_reader.py @@ -21,10 +21,11 @@ from monai.data.image_reader import WSIReader from monai.utils import optional_import -_, has_cim = optional_import("cucim") +cucim, has_cucim = optional_import("cucim") +has_cucim = has_cucim and hasattr(cucim, "CuImage") PILImage, has_pil = optional_import("PIL.Image") -FILE_URL = "http://openslide.cs.cmu.edu/download/openslide-testdata/Generic-TIFF/CMU-1.tiff" +FILE_URL = "https://drive.google.com/uc?id=1sGTKZlJBIz53pfqTxoTqiIQzIoEzHLAe" FILE_PATH = os.path.join(os.path.dirname(__file__), "testing_data", "temp_" + os.path.basename(FILE_URL)) HEIGHT = 32914 @@ -83,7 +84,7 @@ class TestCuCIMReader(unittest.TestCase): - @skipUnless(has_cim, "Requires CuCIM") + @skipUnless(has_cucim, "Requires CuCIM") def setUp(self): download_url(FILE_URL, FILE_PATH, "5a3cfd4fd725c50578ddb80b517b759f") @@ -112,6 +113,7 @@ def test_read_patches(self, file_path, patch_info, expected_img): @parameterized.expand([TEST_CASE_RGB_0, TEST_CASE_RGB_1]) @skipUnless(has_pil, "Requires PIL") + @skipUnless(has_cucim and cucim.__version__ == "0.19.0", "Skipped for cicum>0.19.0") def test_read_rgba(self, img_expected): image = {} reader = WSIReader("cuCIM") diff --git a/tests/test_lesion_froc.py b/tests/test_lesion_froc.py index 2454de88fa..4a67c8d0b3 100644 --- a/tests/test_lesion_froc.py +++ b/tests/test_lesion_froc.py @@ -19,18 +19,19 @@ from monai.apps.pathology.metrics import LesionFROC from monai.utils import optional_import -_, has_cucim = optional_import("cucim") +_cucim, has_cucim = optional_import("cucim") +has_cucim = has_cucim and hasattr(_cucim, "CuImage") _, has_skimage = optional_import("skimage.measure") _, has_sp = optional_import("scipy.ndimage") -PILImage, has_pil = optional_import("PIL.Image") +imwrite, has_tif = optional_import("tifffile", name="imwrite") def save_as_tif(filename, array): array = array[::-1, ...] # Upside-down - img = PILImage.fromarray(array) if not filename.endswith(".tif"): filename += ".tif" - img.save(os.path.join("tests", "testing_data", filename)) + file_path = os.path.join("tests", "testing_data", filename) + imwrite(file_path, array, compress="jpeg", tile=(16, 16)) def around(val, interval=3): @@ -301,7 +302,7 @@ class TestEvaluateTumorFROC(unittest.TestCase): @skipUnless(has_cucim, "Requires cucim") @skipUnless(has_skimage, "Requires skimage") @skipUnless(has_sp, "Requires scipy") - @skipUnless(has_pil, "Requires PIL") + @skipUnless(has_tif, "Requires tifffile") def setUp(self): prepare_test_data() diff --git a/tests/test_masked_inference_wsi_dataset.py b/tests/test_masked_inference_wsi_dataset.py index 361c17e106..7dc322cefa 100644 --- a/tests/test_masked_inference_wsi_dataset.py +++ b/tests/test_masked_inference_wsi_dataset.py @@ -25,7 +25,7 @@ _, has_cim = optional_import("cucim") _, has_osl = optional_import("openslide") -FILE_URL = "http://openslide.cs.cmu.edu/download/openslide-testdata/Generic-TIFF/CMU-1.tiff" +FILE_URL = "https://drive.google.com/uc?id=1sGTKZlJBIz53pfqTxoTqiIQzIoEzHLAe" base_name, extension = os.path.splitext(os.path.basename(FILE_URL)) FILE_NAME = "temp_" + base_name FILE_PATH = os.path.join(os.path.dirname(__file__), "testing_data", FILE_NAME + extension) diff --git a/tests/test_openslide_reader.py b/tests/test_openslide_reader.py index c0b395fd02..efbd611579 100644 --- a/tests/test_openslide_reader.py +++ b/tests/test_openslide_reader.py @@ -24,7 +24,7 @@ _, has_osl = optional_import("openslide") -FILE_URL = "http://openslide.cs.cmu.edu/download/openslide-testdata/Generic-TIFF/CMU-1.tiff" +FILE_URL = "https://drive.google.com/uc?id=1sGTKZlJBIz53pfqTxoTqiIQzIoEzHLAe" FILE_PATH = os.path.join(os.path.dirname(__file__), "testing_data", "temp_" + os.path.basename(FILE_URL)) HEIGHT = 32914 diff --git a/tests/test_patch_wsi_dataset.py b/tests/test_patch_wsi_dataset.py index f775f28376..50b0e13859 100644 --- a/tests/test_patch_wsi_dataset.py +++ b/tests/test_patch_wsi_dataset.py @@ -21,10 +21,11 @@ from monai.apps.utils import download_url from monai.utils import optional_import -_, has_cim = optional_import("cucim") +_cucim, has_cim = optional_import("cucim") +has_cim = has_cim and hasattr(_cucim, "CuImage") _, has_osl = optional_import("openslide") -FILE_URL = "http://openslide.cs.cmu.edu/download/openslide-testdata/Generic-TIFF/CMU-1.tiff" +FILE_URL = "https://drive.google.com/uc?id=1sGTKZlJBIz53pfqTxoTqiIQzIoEzHLAe" FILE_PATH = os.path.join(os.path.dirname(__file__), "testing_data", "temp_" + os.path.basename(FILE_URL)) TEST_CASE_0 = [ diff --git a/tests/test_smartcache_patch_wsi_dataset.py b/tests/test_smartcache_patch_wsi_dataset.py index c484e5fc69..a2605ec525 100644 --- a/tests/test_smartcache_patch_wsi_dataset.py +++ b/tests/test_smartcache_patch_wsi_dataset.py @@ -21,9 +21,10 @@ from monai.apps.utils import download_url from monai.utils import optional_import -_, has_cim = optional_import("cucim") +_cucim, has_cim = optional_import("cucim") +has_cim = has_cim and hasattr(_cucim, "CuImage") -FILE_URL = "http://openslide.cs.cmu.edu/download/openslide-testdata/Generic-TIFF/CMU-1.tiff" +FILE_URL = "https://drive.google.com/uc?id=1sGTKZlJBIz53pfqTxoTqiIQzIoEzHLAe" FILE_PATH = os.path.join(os.path.dirname(__file__), "testing_data", "temp_" + os.path.basename(FILE_URL)) TEST_CASE_0 = [