Load NIfTI format images based on Nibabel library. Args: channel_dim: the channel dimension of the input image, default is None. this is used to set original_channel_dim in the metadata, EnsureChannelFirstD reads this field. if None, `original_channel_dim` w
| 999 | |
| 1000 | @require_pkg(pkg_name="nibabel") |
| 1001 | class NibabelReader(ImageReader): |
| 1002 | """ |
| 1003 | Load NIfTI format images based on Nibabel library. |
| 1004 | |
| 1005 | Args: |
| 1006 | channel_dim: the channel dimension of the input image, default is None. |
| 1007 | this is used to set original_channel_dim in the metadata, EnsureChannelFirstD reads this field. |
| 1008 | if None, `original_channel_dim` will be either `no_channel` or `-1`. |
| 1009 | most Nifti files are usually "channel last", no need to specify this argument for them. |
| 1010 | as_closest_canonical: if True, load the image as closest to canonical axis format. |
| 1011 | squeeze_non_spatial_dims: if True, non-spatial singletons will be squeezed, e.g. (256,256,1,3) -> (256,256,3) |
| 1012 | to_gpu: If True, load the image into GPU memory using CuPy and Kvikio. This can accelerate data loading. |
| 1013 | Default is False. CuPy and Kvikio are required for this option. |
| 1014 | Note: For compressed NIfTI files, some operations may still be performed on CPU memory, |
| 1015 | and the acceleration may not be significant. In some cases, it may be slower than loading on CPU. |
| 1016 | kwargs: additional args for `nibabel.load` API. more details about available args: |
| 1017 | https://github.com/nipy/nibabel/blob/master/nibabel/loadsave.py |
| 1018 | |
| 1019 | """ |
| 1020 | |
| 1021 | def __init__( |
| 1022 | self, |
| 1023 | channel_dim: str | int | None = None, |
| 1024 | as_closest_canonical: bool = False, |
| 1025 | squeeze_non_spatial_dims: bool = False, |
| 1026 | to_gpu: bool = False, |
| 1027 | **kwargs, |
| 1028 | ): |
| 1029 | super().__init__() |
| 1030 | self.channel_dim = float("nan") if channel_dim == "no_channel" else channel_dim |
| 1031 | self.as_closest_canonical = as_closest_canonical |
| 1032 | self.squeeze_non_spatial_dims = squeeze_non_spatial_dims |
| 1033 | if to_gpu and (not has_cp or not has_kvikio): |
| 1034 | warnings.warn( |
| 1035 | "NibabelReader: CuPy and/or Kvikio not installed for GPU loading, falling back to CPU loading." |
| 1036 | ) |
| 1037 | to_gpu = False |
| 1038 | |
| 1039 | if to_gpu: |
| 1040 | self.warmup_kvikio() |
| 1041 | |
| 1042 | self.to_gpu = to_gpu |
| 1043 | self.kwargs = kwargs |
| 1044 | |
| 1045 | def warmup_kvikio(self): |
| 1046 | """ |
| 1047 | Warm up the Kvikio library to initialize the internal buffers, cuFile, GDS, etc. |
| 1048 | This can accelerate the data loading process when `to_gpu` is set to True. |
| 1049 | """ |
| 1050 | if has_cp and has_kvikio: |
| 1051 | a = cp.arange(100) |
| 1052 | with tempfile.NamedTemporaryFile() as tmp_file: |
| 1053 | tmp_file_name = tmp_file.name |
| 1054 | f = kvikio.CuFile(tmp_file_name, "w") |
| 1055 | f.write(a) |
| 1056 | f.close() |
| 1057 | |
| 1058 | b = cp.empty_like(a) |
no outgoing calls
searching dependent graphs…