diff --git a/fileformats/medimage/__init__.py b/fileformats/medimage/__init__.py index ca8becb..8012aba 100644 --- a/fileformats/medimage/__init__.py +++ b/fileformats/medimage/__init__.py @@ -1,5 +1,6 @@ from ._version import __version__ # noqa: F401 from .base import MedicalImage # noqa: F401 + # import Dicom to alias to the medimage namespace it here as well from fileformats.application import Dicom # noqa: F401 from .misc import ( # noqa: F401 @@ -28,7 +29,8 @@ DicomCollection, DicomDir, DicomSeries, - # SiemensDicomDir, + # Vnd_Siemens_Vision, + # Vnd_Siemens_VisionDir, ) from .raw import ( # noqa: F401 Kspace, @@ -43,9 +45,7 @@ Vnd_Siemens_Biograph128Vision_Vr20b_PetCountRate, Vnd_Siemens_Biograph128Vision_Vr20b_PetNormalisation, ) -from .surface import ( - Gifti # noqa: F401 -) +from .surface import Gifti # noqa: F401 from .contents.imaging.modality import ( # noqa: F401 ImagingModality, CombinedModalities, @@ -89,10 +89,18 @@ RG, US, ) -from .contents.imaging.derivatives import ( - Derivative, - Mask +from .contents.imaging.derivatives import Derivative, Mask # noqa: F401 +from .contents.anatomical_entity.material_anatomical_entity.anatomical_structure import ( # noqa: F401 + Brain, + SpinalCord, +) +from .itk import ( # noqa: F401 + GDCM, + GIPL, + VTK, + PGM, + MetaImage, + Nrrd, + NrrdGz, + ItkSupported, ) -from .contents.anatomical_entity.material_anatomical_entity.anatomical_structure import ( - Brain, SpinalCord -) \ No newline at end of file diff --git a/fileformats/medimage/dicom.py b/fileformats/medimage/dicom.py index d393f46..e16c1a9 100644 --- a/fileformats/medimage/dicom.py +++ b/fileformats/medimage/dicom.py @@ -1,5 +1,4 @@ import typing as ty -from operator import itemgetter from collections import defaultdict, Counter from pathlib import Path from functools import cached_property @@ -40,8 +39,10 @@ class DicomDir(DicomCollection, DirectoryContaining[Dicom]): class DicomSeries(DicomCollection, SetOf[Dicom]): @classmethod def from_paths( - cls, fspaths: ty.Iterable[Path], common_ok: bool = False, - selected_keys: ty.Optional[ty.Sequence[str]] = None + cls, + fspaths: ty.Iterable[Path], + common_ok: bool = False, + selected_keys: ty.Optional[ty.Sequence[str]] = None, ) -> ty.Tuple[ty.Set["DicomSeries"], ty.Set[Path]]: """Separates a list of DICOM files into separate series from the file-system paths @@ -67,7 +68,10 @@ def from_paths( for dicom in dicoms: dicom.select_metadata(selected_keys) series_dict[ - (str(dicom.metadata["StudyInstanceUID"]), str(dicom.metadata["SeriesNumber"])) + ( + str(dicom.metadata["StudyInstanceUID"]), + str(dicom.metadata["SeriesNumber"]), + ) ].append(dicom) return set([cls(s) for s in series_dict.values()]), remaining @@ -83,14 +87,18 @@ def dicom_collection_read_metadata( # We use the "contents" property implementation in TypeSet instead of the overload # in DicomCollection because we don't want the metadata to be read ahead of the # the `select_metadata` call below - base_class = TypedSet if isinstance(collection, DicomSeries) else DirectoryContaining + base_class = ( + TypedSet if isinstance(collection, DicomSeries) else DirectoryContaining + ) for dicom in base_class.contents.fget(collection): dicom.select_metadata(selected_keys) for key, val in dicom.metadata.items(): try: prev_val = collated[key] except KeyError: - collated[key] = val # Insert initial value (should only happen on first iter) + collated[key] = ( + val # Insert initial value (should only happen on first iter) + ) key_repeats.update([key]) else: if key in varying_keys: @@ -103,3 +111,11 @@ def dicom_collection_read_metadata( else: key_repeats.update([key]) return collated + + +# class Vnd_Siemens_Vision(Dicom): +# ext = ".ima" + + +# class Vnd_Siemens_VisionDir(DicomDir): +# content_types = (Vnd_Siemens_Vision,) diff --git a/fileformats/medimage/itk.py b/fileformats/medimage/itk.py new file mode 100644 index 0000000..d04ee41 --- /dev/null +++ b/fileformats/medimage/itk.py @@ -0,0 +1,49 @@ +import typing as ty +from fileformats.core.mixin import WithMagicNumber +from fileformats.image import ( + RasterImage, + VectorImage, + Bitmap, + Jpeg, + Tiff, +) +from fileformats.application import Dicom, Gzip +from .nifti import Nifti1, NiftiGz + + +class GDCM(Dicom): + pass + + +class GIPL(RasterImage): + ext = ".gipl" + + +class VTK(VectorImage): + ext = ".vtk" + + +class PGM(RasterImage): + ext = ".pgm" + + +class MetaImage(RasterImage): + ext = ".mhd" + + +class Nrrd(WithMagicNumber, RasterImage): + + ext = ".nrrd" + alternate_exts = (".nhdr",) + magic_number = b"NRRD" + + +class NrrdGz(Gzip[Nrrd]): + + ext = ".nrrd.gz" + alternate_exts = (".nhdr.gz",) + + +ItkSupported = ty.Union[ + Nifti1, NiftiGz, Dicom, Bitmap, Tiff, Jpeg, GIPL, MetaImage, Nrrd, NrrdGz, PGM, VTK +]