@@ -205,6 +205,90 @@ def is_ngff( # noqa: PLR0911
205205 return is_zarr (path )
206206
207207
208+ def _handle_virtual_wsi (
209+ last_suffix : str ,
210+ input_path : Path ,
211+ mpp : tuple [Number , Number ] | None ,
212+ power : Number | None ,
213+ ) -> VirtualWSIReader | None :
214+ """Handle virtual WSI cases.
215+
216+ Args:
217+ last_suffix (str):
218+ Suffix of the file to read.
219+ input_path (Path):
220+ Input path to virtual WSI.
221+ mpp (:obj:`tuple` or :obj:`list` or :obj:`None`, optional):
222+ The MPP of the WSI. If not provided, the MPP is approximated
223+ from the objective power.
224+ power (:obj:`float` or :obj:`None`, optional):
225+ The objective power of the WSI. If not provided, the power
226+ is approximated from the MPP.
227+
228+ Returns:
229+ VirtualWSIReader | None:
230+ :class:`VirtualWSIReader` if input_path is valid path to virtual WSI
231+ otherwise None.
232+
233+ """
234+
235+ # Handle homogeneous cases (based on final suffix)
236+ def np_virtual_wsi (
237+ input_path : np .ndarray ,
238+ * args : Number | tuple | str | WSIMeta | None ,
239+ ** kwargs : dict ,
240+ ) -> VirtualWSIReader :
241+ """Create a virtual WSI from a numpy array."""
242+ return VirtualWSIReader (input_path , * args , ** kwargs )
243+
244+ suffix_to_reader = {
245+ ".npy" : np_virtual_wsi ,
246+ ".jp2" : JP2WSIReader ,
247+ ".jpeg" : VirtualWSIReader ,
248+ ".jpg" : VirtualWSIReader ,
249+ ".png" : VirtualWSIReader ,
250+ ".tif" : VirtualWSIReader ,
251+ ".tiff" : VirtualWSIReader ,
252+ }
253+
254+ if last_suffix in suffix_to_reader :
255+ return suffix_to_reader [last_suffix ](input_path , mpp = mpp , power = power )
256+
257+ return None
258+
259+
260+ def _handle_tiff_wsi (
261+ input_path : Path , mpp : tuple [Number , Number ] | None , power : Number | None
262+ ) -> TIFFWSIReader | OpenSlideWSIReader | None :
263+ """Handle TIFF WSI cases.
264+
265+ Args:
266+ input_path (Path):
267+ Input path to virtual WSI.
268+ mpp (:obj:`tuple` or :obj:`list` or :obj:`None`, optional):
269+ The MPP of the WSI. If not provided, the MPP is approximated
270+ from the objective power.
271+ power (:obj:`float` or :obj:`None`, optional):
272+ The objective power of the WSI. If not provided, the power
273+ is approximated from the MPP.
274+
275+ Returns:
276+ OpenSlideWSIReader | TIFFWSIReader | None:
277+ :class:`OpenSlideWSIReader` or :class:`TIFFWSIReader` if input_path is
278+ valid path to tiff WSI otherwise None.
279+
280+ """
281+ if openslide .OpenSlide .detect_format (input_path ) is not None :
282+ try :
283+ return OpenSlideWSIReader (input_path , mpp = mpp , power = power )
284+ except openslide .OpenSlideError :
285+ pass
286+ if is_tiled_tiff (input_path ):
287+ return TIFFWSIReader (input_path , mpp = mpp , power = power )
288+
289+ return None
290+
291+
208292class WSIReader :
209293 """Base whole slide image (WSI) reader class.
210294
@@ -279,7 +363,6 @@ def open( # noqa: PLR0911
279363 WSIReader .verify_supported_wsi (input_path )
280364
281365 # Handle special cases first (DICOM, Zarr/NGFF, OME-TIFF)
282-
283366 if is_dicom (input_path ):
284367 return DICOMWSIReader (input_path , mpp = mpp , power = power )
285368
@@ -300,33 +383,17 @@ def open( # noqa: PLR0911
300383 if suffixes [- 2 :] in ([".ome" , ".tiff" ],):
301384 return TIFFWSIReader (input_path , mpp = mpp , power = power )
302385
303- if last_suffix in (".tif" , ".tiff" ) and is_tiled_tiff (input_path ):
304- try :
305- return OpenSlideWSIReader (input_path , mpp = mpp , power = power )
306- except openslide .OpenSlideError :
307- return TIFFWSIReader (input_path , mpp = mpp , power = power )
308-
309- # Handle homogeneous cases (based on final suffix)
310- def np_virtual_wsi (
311- input_path : np .ndarray ,
312- * args : Number | tuple | str | WSIMeta | None ,
313- ** kwargs : dict ,
314- ) -> VirtualWSIReader :
315- """Create a virtual WSI from a numpy array."""
316- return VirtualWSIReader (input_path , * args , ** kwargs )
317-
318- suffix_to_reader = {
319- ".npy" : np_virtual_wsi ,
320- ".jp2" : JP2WSIReader ,
321- ".jpeg" : VirtualWSIReader ,
322- ".jpg" : VirtualWSIReader ,
323- ".png" : VirtualWSIReader ,
324- ".tif" : VirtualWSIReader ,
325- ".tiff" : VirtualWSIReader ,
326- }
386+ if last_suffix in (".tif" , ".tiff" ):
387+ tiff_wsi = _handle_tiff_wsi (input_path , mpp = mpp , power = power )
388+ if tiff_wsi is not None :
389+ return tiff_wsi
390+
391+ virtual_wsi = _handle_virtual_wsi (
392+ last_suffix = last_suffix , input_path = input_path , mpp = mpp , power = power
393+ )
327394
328- if last_suffix in suffix_to_reader :
329- return suffix_to_reader [ last_suffix ]( input_path , mpp = mpp , power = power )
395+ if virtual_wsi is not None :
396+ return virtual_wsi
330397
331398 # Try openslide last
332399 return OpenSlideWSIReader (input_path , mpp = mpp , power = power )
0 commit comments