dicom_header
Single-read DICOM header access and metadata-only frame counting.
Reading a DICOM over a network share is dominated by round trips, not by bytes
transferred: every open() is an SMB2 CREATE. This module reads a file
once into memory and exposes the parsed dataset plus the bytes at the start of
the Pixel Data element, so callers can re-parse as often as they like without
touching the share again.
It also derives the frame count from element metadata rather than by decoding
pixel data. NumberOfFrames is absent from most single-frame images and from
non-image DICOMs, and some converted files omit it while genuinely holding
multiple frames, so a frame count has to come from somewhere; taking it from the
Pixel Data length costs twelve bytes instead of a full transfer and decode.
Module
Functions
frames_from_header
def frames_from_header(header: DicomHeaderRead) ‑> int | None:Derive the frame count from element metadata, without decoding pixels.
Tries, in order: the Number of Frames tag; the Pixel Data length divided by the size of one frame (exact for uncompressed data); the Extended Offset Table; the Basic Offset Table.
Arguments
header: A header read byread_dicom_header.
Returns
The frame count, or None if it cannot be determined from metadata
alone — in which case the caller must fall back to reading pixel data.
media_storage_sop_class_name
def media_storage_sop_class_name(ds: pydicom.Dataset) ‑> str:The Media Storage SOP Class UID's name, from an already-parsed dataset.
read_dicom_header
def read_dicom_header( filename: str | os.PathLike[str], *, head_bytes: int = 131072,) ‑> DicomHeaderRead:Read a DICOM file's header in a single open.
Reads head_bytes and parses from memory. If the parse runs out of bytes
before reaching the Pixel Data element, the rest of the file is read from
the same handle — an extra transfer, but not an extra open.
The file's size is never queried: a read returning fewer bytes than asked
for has reached the end, which answers the only question size would. Over
SMB a stat of an open handle is itself a round trip, which is the cost
this function exists to avoid.
Arguments
filename: The file to read.head_bytes: How much to read on the first attempt.
Returns The parsed header and the bytes it came from.
Raises
FileNotFoundError: If the file is missing. Callers are expected to handle this, since the file may reappear on a later run.
Classes
DicomHeaderRead
class DicomHeaderRead( ds: pydicom.FileDataset, raw: bytes, pixel_data_offset: int | None, reached_pixel_data: bool, complete: bool, whole_file: bool,):The result of reading a DICOM file's header in a single open.
Attributes
ds: The parsed dataset, stopping at the Pixel Data element.raw: The bytes read from the file.pixel_data_offset: Offset intorawof the Pixel Data element tag, orNoneif the parse did not reach one.reached_pixel_data: Whether the parse stopped because it found a Pixel Data element.FalsewithcompleteTrue means the file genuinely has no pixel data (e.g. a structured report).complete: Whetherrawholds the whole file, or enough of it to have reached the Pixel Data element. WhenFalsethe dataset may carry silently truncated element values.whole_file: Whetherrawis the entire file rather than a prefix of it. Stronger thancomplete, which a conventional file satisfies from its first megabyte: a caller that needs the pixel data itself - the Zeiss route, whose image lives in private tags - can parserawinstead of opening the file again only when this isTrue.
Variables
- static
complete : bool
- static
ds : pydicom.dataset.FileDataset
- static
pixel_data_offset : int | None
- static
raw : bytes
- static
reached_pixel_data : bool
- static
whole_file : bool