Read image data from specified file or files, it can read a list of images and stack them together as multi-channel data in `get_data()`. If passing directory path instead of file path, will treat it as DICOM images series and read. Note that the returned object is I
(self, data: Sequence[PathLike] | PathLike, **kwargs)
| 226 | return has_itk |
| 227 | |
| 228 | def read(self, data: Sequence[PathLike] | PathLike, **kwargs): |
| 229 | """ |
| 230 | Read image data from specified file or files, it can read a list of images |
| 231 | and stack them together as multi-channel data in `get_data()`. |
| 232 | If passing directory path instead of file path, will treat it as DICOM images series and read. |
| 233 | Note that the returned object is ITK image object or list of ITK image objects. |
| 234 | |
| 235 | Args: |
| 236 | data: file name or a list of file names to read, |
| 237 | kwargs: additional args for `itk.imread` API, will override `self.kwargs` for existing keys. |
| 238 | More details about available args: |
| 239 | https://github.com/InsightSoftwareConsortium/ITK/blob/master/Wrapping/Generators/Python/itk/support/extras.py |
| 240 | |
| 241 | """ |
| 242 | img_ = [] |
| 243 | |
| 244 | filenames: Sequence[PathLike] = ensure_tuple(data) |
| 245 | kwargs_ = self.kwargs.copy() |
| 246 | kwargs_.update(kwargs) |
| 247 | for name in filenames: |
| 248 | name = f"{name}" |
| 249 | if Path(name).is_dir(): |
| 250 | # read DICOM series |
| 251 | # https://examples.itk.org/src/io/gdcm/readdicomseriesandwrite3dimage/documentation |
| 252 | names_generator = itk.GDCMSeriesFileNames.New() |
| 253 | names_generator.SetUseSeriesDetails(True) |
| 254 | names_generator.AddSeriesRestriction("0008|0021") # Series Date |
| 255 | names_generator.SetDirectory(name) |
| 256 | series_uid = names_generator.GetSeriesUIDs() |
| 257 | |
| 258 | if len(series_uid) < 1: |
| 259 | raise FileNotFoundError(f"no DICOMs in: {name}.") |
| 260 | if len(series_uid) > 1: |
| 261 | warnings.warn(f"the directory: {name} contains more than one DICOM series.") |
| 262 | series_identifier = series_uid[0] if not self.series_name else self.series_name |
| 263 | name = names_generator.GetFileNames(series_identifier) |
| 264 | |
| 265 | name = name[0] if len(name) == 1 else name # type: ignore |
| 266 | _obj = itk.imread(name, **kwargs_) |
| 267 | if self.series_meta: |
| 268 | _reader = itk.ImageSeriesReader.New(FileNames=name) |
| 269 | _reader.Update() |
| 270 | _meta = _reader.GetMetaDataDictionaryArray() |
| 271 | if len(_meta) > 0: |
| 272 | # TODO: using the first slice's meta. this could be improved to filter unnecessary tags. |
| 273 | _obj.SetMetaDataDictionary(_meta[0]) |
| 274 | img_.append(_obj) |
| 275 | else: |
| 276 | img_.append(itk.imread(name, **kwargs_)) |
| 277 | return img_ if len(filenames) > 1 else img_[0] |
| 278 | |
| 279 | def get_data(self, img) -> tuple[np.ndarray, dict]: |
| 280 | """ |