Skip to main content

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_syntaxes is 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 with stop_before_pixels=True is 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 with stop_before_pixels=True is 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, or None when the header does not state one.
  • acquisition_datetime: When the image was acquired, or None when no header element states it. See read_acquisition_datetime for which elements are read and in what order.

Variables

  • modality : Literal['OCT', 'SLO', None] - Alias for field number 1