CT and Structure Set#

Patient data in pyRadPlan is represented by two objects: the CT image (ct) and the structure set (cst). Both are pydantic models that enforce data integrity and expose a to_matrad() method for interoperability.

Loading patient data#

The most common entry point is load_patient(), which reads a matRad-format *.mat file and returns a validated (CT, StructureSet) pair:

from importlib import resources
from pyRadPlan import load_patient

tg119_path = resources.files("pyRadPlan.data.phantoms").joinpath("TG119.mat")
ct, cst = load_patient(tg119_path)

The CT object#

CT stores the CT image together with its spatial metadata. Internally the image is held as a SimpleITK image, which provides sub-millimetre-accurate coordinate transforms and easy resampling.

Attribute

Description

cube_hu

sitk.Image in Hounsfield Units. NumPy arrays are automatically converted.

resolution

Voxel spacing as {"x": ..., "y": ..., "z": ...} in mm.

size

Grid dimensions (nx, ny, nz) in voxels.

origin

World coordinates of the image origin in mm (LPS convention).

direction

Direction cosines matrix (3×3) describing the image axes in world space.

import numpy as np

print(ct.resolution)          # {'x': 3.0, 'y': 3.0, 'z': 3.0}
print(ct.size)                # (nx, ny, nz)
hu_array = sitk.GetArrayFromImage(ct.cube_hu)  # (nz, ny, nx) NumPy array

The StructureSet object#

StructureSet holds a list of VOI (Volume of Interest) objects and keeps a reference to the associated CT image so that spatial queries always use consistent coordinates.

print(len(cst.vois))          # number of structures
for voi in cst.vois:
    print(voi.name, voi.voi_type)

Volumes of Interest (VOI)#

Each VOI carries:

Attribute

Description

name

Structure name (e.g. "PTV", "Spinal_Cord").

voi_type

One of "TARGET", "OAR", "HELPER", "EXTERNAL".

mask

Boolean sitk.Image (1 = inside structure, 0 = outside) on the CT grid.

indices

Flattened voxel indices (Fortran/column-major order) for efficient sparse lookups.

alpha_x

Linear-quadratic α parameter (Gy⁻¹, default 0.1). Used for biological modelling.

beta_x

Linear-quadratic β parameter (Gy⁻², default 0.05).

overlap_priority

Determines which VOI “wins” in overlapping regions (lower = higher priority).

objectives

List of optimization objectives attached to this structure (see Optimization).

Attaching optimization objectives#

Objectives are stored directly on each VOI and are automatically picked up during optimization. They can be added programmatically:

from pyRadPlan.optimization.objectives import SquaredDeviation, MaxDVH

# Add a squared-deviation objective to the PTV
ptv = next(v for v in cst.vois if v.voi_type == "TARGET")
ptv.objectives.append(
    SquaredDeviation(priority=1000, d_ref=60.0, quantity="physical_dose")
)

# Penalize dose above 45 Gy in more than 2% of the spinal cord volume
cord = next(v for v in cst.vois if v.name == "Spinal_Cord")
cord.objectives.append(
    MaxDVH(priority=100, d=45.0, v_max=2.0)
)

matRad interoperability#

matrad_ct  = ct.to_matrad()   # dict with 'cubeHU', 'resolution', etc.
matrad_cst = cst.to_matrad()  # cell array compatible with matRad's cst