Repository navigation
PortPy 1.2.0
Highlights
Beamlet dose prediction (portpy.ai) — a full pipeline for predicting individual
beamlet dose columns with a 3D deep-learning model, and assembling them into a predicted
influence matrix A_pred. This lets you build a plannable influence matrix without a
dose engine. Includes preprocessing, dataset, training/testing, and matrix assembly, with
an end-to-end example (examples/beamlet_dose_prediction.ipynb).
New portpy.ai.inference subpackage — the inference half of the above, usable on its
own: beam-frame geometry (gantry/collimator/couch), ray-aligned BEV patch extraction,
GPU resampling via torch.grid_sample, and two predictors (RayUNetPredictor,
PatientGridPredictor) behind build_ray_unet_predictor / build_patient_grid_predictor.
Importing the package pulls no torch; torch loads lazily inside the predictors.
Two sampling grids — beamlet dose can be predicted on a world-aligned patient grid or
a ray-aligned BEV patch, selectable with grid="patient" | "bev" through preprocessing,
training and inference.
Plan quality scorecards — Evaluation.compute_total_quality_score() scores a plan
against a scorecard and returns a per-criterion table. Two scorecards ship with the
package (Lung 60Gy and Prostate SBRT), plus adapt_scorecard_prescription() to
rescale a scorecard written for a different prescription.
New models — UNet3D alongside an expanded networks3d
registry (beamlet_unet, ray_unet3d, ray_attention_resunet3d, mednext).
New protocol — Prostate_5Gy_5Fx, with clinical criteria and IMRT/VMAT optimization
parameters.
Bug fixes
- Influence matrix: crash on some of the shipped patients.
preprocess_beamsraised
IndexErrorwhile slicingMLC_leaf_idxfor patients whose stored leaf table is
inconsistent with the beamlet grid. The field is no longer needed: the VMAT RT-plan
writer now derives leaf pairs per row fromleaf_pair_row_match, which is also correct
for rows spanning different numbers of leaves. - Leaf sequencing worked for only some patients.
leaf_sequencing_siochimatched
beamlet rows against the stored leaf table with an exactint()comparison, which only
succeeded when that table happened to be whole-millimetre. It now resolves leaf rows
from the MLC leaf edges and works for every patient. - Influence matrix assembly was quadratic in beam count.
get_influence_matrixgrew
the matrix one beam at a time; it now concatenates once. Output is bit-identical.
Largest measured effect: a 191-beam breast case went from 306 s to 5.4 s. - Windows:
import portpy.photonbroke a laterimport torch. The VMAT SCP utilities
loaded the Intel MKL runtime eagerly; that import is now deferred until first use. - Clinical criteria: negative or unresolvable dose limits and goals are dropped instead
of raising, and "coldest" (CV/DC) dose-volume constraints are supported.
Installation fixes
pip install -r requirements.txt previously failed because the file was UTF-16 encoded.
It is now UTF-8 and mirrors the core dependencies in pyproject.toml.
- Removed
ecosandqdldl— C extensions that required a compiler when no wheel matched
the user's Python. They are unused by PortPy. - Added
clarabelto core dependencies, so a fast free solver is available by default. - Relaxed the exact
jinja2==3.1.5pin, which conflicted with other packages. requirements.txtno longer forces the commercialMoseksolver on source installs;
it stays an optional extra (pip install portpy[mosek]).
Testing
New tests/test_ai_module.py (26 tests) covering beam geometry conventions, the 3D UNet
forward pass, and GPU resampling accuracy. CI installs CPU-only torch so these run on
every push.
Full changelog: v1.1.4...v1.2.0