dicom_extract
Datasource-free extraction of image frames from DICOM / Zeiss files.
Holds the pixel-array, frame-count, frame-split, and Zeiss-routing logic as the
single source of truth: DICOMSource / DICOMOphthalmologySource and other
callers delegate here, so a caller can go path -> list[np.ndarray] without
constructing a full datasource (which pulls in pandas, schema, and splitters).
Module
Functions
extract_dicom_frames
def extract_dicom_frames( path: str,) ‑> list[numpy.ndarray[typing.Any, numpy.dtype[typing.Any]]]:Read a DICOM file and return its image frames as numpy arrays.
Thin wrapper over extract_dicom_scan for callers wanting only the pixels.
Arguments
path: Absolute path to the DICOM file.
Returns Ordered frame arrays.
extract_dicom_scan
def extract_dicom_scan( path: str,) ‑> DicomScan:Read a DICOM file and return its frames alongside its modality.
Branches to the Zeiss decoders for Zeiss-manufacturer files, otherwise uses the conventional pixel-array + frame-split path. No datasource is created. A Zeiss file the datasource would route straight to conventional decode (ophthalmic-photography SOP class, or PixelData with a disallowed transfer syntax) skips the CZM decoders entirely. The conventional path applies the same tag sanitization the ingestion datasource does before pixel decode.
The modality and the acquisition datetime are read before any decode:
_conventional_pixel_array strips private tags and applies Zeiss sanitization
in place, and the Zeiss decoders mutate the dataset too, so the header must be
inspected first.
Arguments
path: Absolute path to the DICOM file.
Returns The frames, the modality, and the acquisition datetime the header states.
get_ophthalmology_pixel_array
def get_ophthalmology_pixel_array( ds: pydicom.FileDataset, filename: str,) ‑> numpy.ndarray[typing.Any, numpy.dtype[typing.Any]]:Return the dtype-coerced pixel array for an ophthalmic DICOM dataset.
Body lifted verbatim from DICOMOphthalmologySource._get_pixel_array.
Arguments
ds: The parsed DICOM dataset.filename: The source filename (used only for log messages).
Returns
The pixel array coerced to uint8/float32 as the datasource does.
is_allowed_transfer_syntax
def is_allowed_transfer_syntax(ds: pydicom.FileDataset, filename: str) ‑> bool:Returns True if Transfer Syntax is an allowed type.
By default, Zeiss processing allows:
- JPEG2000Lossless (1.2.840.10008.1.2.4.90)
- JPEG2000 (lossy, 1.2.840.10008.1.2.4.91)
- ExplicitVRLittleEndian (1.2.840.10008.1.2.1)
- ImplicitVRLittleEndian (1.2.840.10008.1.2)
If
config.settings.allow_extra_zeiss_transfer_syntaxesis set it can also be any of: - JPEGLossless (1.2.840.10008.1.2.4.57)
- JPEGLosslessSV1 (1.2.840.10008.1.2.4.70)
- JPEGLSLossless (1.2.840.10008.1.2.4.80)
- JPEGLSNearLossless (1.2.840.10008.1.2.4.81)
Arguments
ds: The DICOM dataset.filename: The source filename (used only for log messages).
Returns True if the Transfer Syntax UID is allowed for Zeiss decoding.
is_ophthalmic_photography_sop_class
def is_ophthalmic_photography_sop_class(ds: pydicom.FileDataset) ‑> bool:Check if the SOP Class UID is an Ophthalmic Photography type.
Ophthalmic Photography images (8-bit or 16-bit) are standard DICOM images that do not use Zeiss CZM scrambling, even when produced by Zeiss devices. They should be processed via the conventional DICOM path.
Arguments
ds: The DICOM dataset.
Returns True if the SOP Class UID is an Ophthalmic Photography type.
num_frames
def num_frames(ds: pydicom.FileDataset, pixel_array: NDArray[Any], filename: str) ‑> int:Return NumberOfFrames when present, else infer from the array.
Mirrors DICOMSource._get_num_frames.
Arguments
ds: The parsed DICOM dataset.pixel_array: The DICOM pixel array.filename: The source filename (used only for error messages).
Returns The number of frames.
num_frames_from_pixel_array
def num_frames_from_pixel_array(pixel_array: NDArray[Any], filename: str) ‑> int:Infer the frame count from a pixel array's shape.
Body lifted verbatim from DICOMSource._get_num_frames_from_pixel_array.
Distinguishes between grayscale and color images.
Arguments
pixel_array: The DICOM pixel array.filename: The source filename (used only for error messages).
Returns The number of frames.
read_acquisition_datetime
def read_acquisition_datetime(ds: pydicom.Dataset) ‑> datetime.datetime | None:Read the instant a dataset's image was acquired.
Walks _ACQUISITION_DATETIME_ELEMENTS in order and returns the first element
(or date/time pair) that parses. A date whose paired time element is absent or
unparseable reads as midnight on that date rather than as unknown.
A datetime carrying a UTC offset is returned tz-aware, as stated; the rest are naive, since a DICOM date/time pair states no zone and inventing one would misreport the value by up to a day.
Arguments
ds: The parsed dataset. Only header elements are read, so a dataset read withstop_before_pixels=Trueis enough.
Returns
The acquisition datetime, or None when no element states one.
read_modality
def read_modality(ds: pydicom.FileDataset) ‑> Literal['OCT', 'SLO', None]:Read a dataset's ophthalmology modality from its acquisition device type.
The same two rules DICOMOphthalmologySource applies when it populates a
file's modality, so a caller reading a DICOM directly reports the modality
ingestion would have recorded: the acquisition-device-type code meaning,
except for Zeiss files, whose device type is absent and inferred from an
operator name naming a Cirrus (a known OCT device).
Arguments
ds: The parsed dataset. Only header elements are read, so a dataset read withstop_before_pixels=Trueis enough.
Returns
"OCT" or "SLO", or None when the tag is absent, empty, or carries a
device type outside the mapping (the file may still decode — an unknown
device type says nothing about the pixel data).
split_frames
def split_frames( pixel_array: NDArray[Any], num_frames: int,) ‑> list[numpy.ndarray[typing.Any, numpy.dtype[typing.Any]]]:Split a (multi-frame) pixel array into a list of per-frame arrays.
Pure form of the loop in DICOMSource._process_dicom_pixel_array (drops the
self.images_only error-handling branch, which is datasource policy). The
range is bounded to the frames the array actually holds, so a
NumberOfFrames that overstates a truncated/corrupt array yields the
extractable frames rather than raising an eager IndexError.
Arguments
pixel_array: The DICOM pixel array.num_frames: The number of frames the array is reported to hold.
Returns Per-frame 2D (or HxWxC) arrays in acquisition order.
Classes
DicomScan
class DicomScan( frames: ForwardRef('list[NDArray[Any]]'), modality: ForwardRef('OphthalmologyModalityType'), acquisition_datetime: ForwardRef('datetime | None') = None,):A decoded DICOM's frames plus the header metadata describing them.
Attributes
frames: Ordered frame arrays.modality: The file's ophthalmology modality, orNonewhen the header does not state one.acquisition_datetime: When the image was acquired, orNonewhen no header element states it. Seeread_acquisition_datetimefor which elements are read and in what order.
Variables
acquisition_datetime : datetime.datetime | None- Alias for field number 2
frames : list[numpy.ndarray[typing.Any, numpy.dtype[typing.Any]]]- Alias for field number 0
modality : Literal['OCT', 'SLO', None]- Alias for field number 1