Data Inputs and Containers¶
Metric functions operate on a small set of explicit inputs: image volumes,
Dose, Structure, and StructureSet. Dose and geometry remain separate so
the same structure can be evaluated against multiple plans.
flowchart LR
A[Scalar image volume] --> B[Dose]
C[Binary image volume] --> D[Structure]
D --> E[StructureSet]
B --> F[Metric function]
D --> F
E --> G[Batch DVH and plotting helpers]
B --> G
Image volumes¶
DoseMetrics does not expose a separate Image class. An image volume is a
three-dimensional NumPy array plus spatial metadata:
spacing: voxel size in millimetres;origin: physical coordinate of the grid origin in millimetres;- shape: the three array dimensions.
NIfTI and DICOM readers convert file-backed images into this representation.
Use load_volume when you need the raw values:
from dosemetrics.io import load_volume
array, spacing, origin = load_volume("Dose.nii.gz")
print(array.shape, spacing, origin)
The array alone is not sufficient for a spatial metric. Preserve its spacing and origin whenever you construct containers manually.
Dose¶
Dose stores a floating-point dose array in Gy and the grid metadata required
to align it with structures.
from dosemetrics import Dose
dose = Dose(
dose_array,
spacing=(2.0, 2.0, 2.0),
origin=(0.0, 0.0, 0.0),
name="Plan A",
)
Load a file-backed dose directly:
nifti_dose = Dose.from_nifti("Dose.nii.gz", name="NIfTI plan")
dicom_dose = Dose.from_dicom("RTDOSE.dcm", name="DICOM plan")
The main properties are dose_array, shape, spacing, origin, name,
min_dose, max_dose, and mean_dose.
Structure¶
A Structure contains one binary mask and the grid metadata for that mask.
Construct the concrete Target, OAR, or AvoidanceStructure classes rather
than the abstract base class.
from dosemetrics import OAR, Target
ptv = Target(
"PTV",
ptv_mask,
spacing=(2.0, 2.0, 2.0),
origin=(0.0, 0.0, 0.0),
)
brainstem = OAR(
"Brainstem",
brainstem_mask,
spacing=ptv.spacing,
origin=ptv.origin,
)
Masks are converted to Boolean arrays. Useful geometry methods include
volume_voxels(), volume_cc(), centroid(), and bounding_box().
Dose–structure compatibility¶
A dose and structure are compatible only when shape, spacing, and origin match. Check this explicitly before computing a metric:
if not dose.is_compatible_with_structure(ptv):
raise ValueError("Dose and PTV must use the same spatial grid")
Metric functions also validate compatibility and raise a ValueError rather
than silently resampling. Resample upstream when grids differ.
StructureSet¶
StructureSet is a named collection of structures on a common grid. It does
not contain a dose distribution.
Load from NIfTI or DICOM¶
from dosemetrics.io import load_structure_set
structures = load_structure_set("patient_001", format="nifti")
ptv = structures["PTV"]
For NIfTI, the folder normally contains one binary volume per structure. For
DICOM, load_structure_set reads an RTSTRUCT and uses the available image
grid to rasterize contours. See File Formats
for supported layouts.
Construct in memory¶
from dosemetrics import StructureSet, StructureType
structures = StructureSet(
spacing=(2.0, 2.0, 2.0),
origin=(0.0, 0.0, 0.0),
name="Patient 001",
)
structures.add_structure("PTV", ptv_mask, StructureType.TARGET)
structures.add_structure("Brainstem", brainstem_mask, StructureType.OAR)
Access and iterate¶
ptv = structures["PTV"]
brainstem = structures.get_structure("Brainstem")
for name, structure in structures:
print(name, structure.structure_type, structure.volume_cc())
targets = structures.get_targets()
oars = structures.get_oars()
Apply metrics across a set¶
import pandas as pd
from dosemetrics.metrics import dvh
rows = []
for name, structure in structures:
rows.append({
"structure": name,
"volume_cc": structure.volume_cc(),
**dvh.compute_dose_statistics(dose, structure),
})
statistics = pd.DataFrame(rows)
dvh_table = dvh.create_dvh_table(dose, structures, step_size=0.1)
Input checklist¶
Before calling a metric, confirm that:
- dose values are expressed in Gy;
- every mask is binary and non-empty;
- dose and mask shapes match;
- spacing and origin describe the same grid;
- the intended target or OAR type is assigned;
- reference-based functions receive
referencebeforeevaluated.