4545from monai .transforms .utility .array import EnsureChannelFirst
4646from monai .utils import (
4747 GridSamplePadMode ,
48- ImageMetaKey ,
48+ )
49+ from monai .utils import ImageMetaKey
50+ from monai .utils import ImageMetaKey as Key
51+ from monai .utils import (
4952 MetaKeys ,
5053 OptionalImportError ,
5154 convert_to_dst_type ,
@@ -138,6 +141,7 @@ def __init__(
138141 prune_meta_pattern : str | None = None ,
139142 prune_meta_sep : str = "." ,
140143 expanduser : bool = True ,
144+ raise_on_missing_reader : bool = False ,
141145 * args ,
142146 ** kwargs ,
143147 ) -> None :
@@ -161,9 +165,21 @@ def __init__(
161165 in the metadata (nested dictionary). default is ".", see also :py:class:`monai.transforms.DeleteItemsd`.
162166 e.g. ``prune_meta_pattern=".*_code$", prune_meta_sep=" "`` removes meta keys that ends with ``"_code"``.
163167 expanduser: if True cast filename to Path and call .expanduser on it, otherwise keep filename as is.
168+ raise_on_missing_reader: if True, raise `OptionalImportError` when a specified reader is not available;
169+ otherwise attempt to use fallback readers. Defaults to False (backward compatibility).
164170 args: additional parameters for reader if providing a reader name.
165171 kwargs: additional parameters for reader if providing a reader name.
166172
173+ Raises:
174+ OptionalImportError: If `raise_on_missing_reader=True` and the specified reader
175+ cannot be found or its optional dependency is not installed.
176+
177+ Accepted reader types:
178+ - str: name of a registered reader (e.g., `"ITKReader"`)
179+ - class: e.g., `ITKReader` or a custom reader class
180+ - instance: e.g., `ITKReader(pixel_type=itk.UC)`
181+ - list/tuple: multiple reader names or classes to try in order
182+
167183 Note:
168184
169185 - The transform returns a MetaTensor, unless `set_track_meta(False)` has been used, in which case, a
@@ -183,6 +199,7 @@ def __init__(
183199 self .pattern = prune_meta_pattern
184200 self .sep = prune_meta_sep
185201 self .expanduser = expanduser
202+ self .raise_on_missing_reader = raise_on_missing_reader
186203
187204 self .readers : list [ImageReader ] = []
188205 for r in SUPPORTED_READERS : # set predefined readers as default
@@ -206,18 +223,61 @@ def __init__(
206223 if not has_built_in :
207224 the_reader = locate (f"{ _r } " ) # search dotted path
208225 if the_reader is None :
209- the_reader = look_up_option (_r .lower (), SUPPORTED_READERS )
226+ try :
227+ the_reader = look_up_option (_r .lower (), SUPPORTED_READERS )
228+ except ValueError :
229+ # If the reader name is not recognized at all, raise OptionalImportError
230+ msg = f"Cannot find reader '{ _r } '. It may not be installed or recognized."
231+ if self .raise_on_missing_reader :
232+ raise OptionalImportError (msg )
233+ else :
234+ warnings .warn (
235+ f"{ msg } Will use fallback readers if available." ,
236+ category = UserWarning ,
237+ stacklevel = 2 ,
238+ )
239+ continue
210240 try :
211241 self .register (the_reader (* args , ** kwargs ))
212- except OptionalImportError :
213- warnings . warn (
214- f"required package for reader { _r } is not installed, or the version doesn't match requirement."
242+ except OptionalImportError as e :
243+ msg = (
244+ f"Required package for reader { _r } is not installed, or the version doesn't match requirement."
215245 )
246+ if self .raise_on_missing_reader :
247+ raise OptionalImportError (msg ) from e
248+ else :
249+ warnings .warn (
250+ f"{ msg } Will use fallback readers if available." ,
251+ category = UserWarning ,
252+ stacklevel = 2 ,
253+ )
216254 except TypeError : # the reader doesn't have the corresponding args/kwargs
217- warnings .warn (f"{ _r } is not supported with the given parameters { args } { kwargs } ." )
255+ warnings .warn (
256+ f"{ _r } is not supported with the given parameters { args } { kwargs } ." ,
257+ category = UserWarning ,
258+ stacklevel = 2 ,
259+ )
218260 self .register (the_reader ())
219261 elif inspect .isclass (_r ):
220- self .register (_r (* args , ** kwargs ))
262+ try :
263+ self .register (_r (* args , ** kwargs ))
264+ except OptionalImportError as e :
265+ msg = f"Required package for reader { _r .__name__ } is not installed, or the version doesn't match requirement."
266+ if self .raise_on_missing_reader :
267+ raise OptionalImportError (msg ) from e
268+ else :
269+ warnings .warn (
270+ f"{ msg } Will use fallback readers if available." ,
271+ category = UserWarning ,
272+ stacklevel = 2 ,
273+ )
274+ except TypeError :
275+ warnings .warn (
276+ f"{ _r .__name__ } is not supported with the given parameters { args } { kwargs } ." ,
277+ category = UserWarning ,
278+ stacklevel = 2 ,
279+ )
280+ self .register (_r ())
221281 else :
222282 self .register (_r ) # reader instance, ignoring the constructor args/kwargs
223283 return
0 commit comments