cerr.imrtp.dosecalc package
Dose-calculation back-ends used by IMRTP: ray tracing, influence-matrix assembly, Monte-Carlo, QIB data handling and RTPLAN recalculation.
Submodules
cerr.imrtp.dosecalc.influence module
influence
QIB influence (beamlet) generation and dose assembly.
- Python port of Matlab CERR:
IMRTP/generateQIBInfluence.m (per-structure, per-beam, per-PB dose) IMRTP/getIMDose.m (influence x beamlet weights -> dose3D) IMRTP/createIMBeamlet.m (sparse beamlet records)
Beamlets are stored on each beam as beam.beamlets – a flat list of
Beamlet, one per (structure, pencil
beam), holding the non-zero dose contributions (float32, uncompressed) and
the voxel indices into the scan grid.
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- cerr.imrtp.dosecalc.influence.generateQIBInfluence(im, planC, statusCallback=None)[source]
Generate QIB beamlet influence for every goal structure and beam.
Port of
generateQIBInfluence.m. Fillsbeam.beamletson every beam ofimand returnsim.
- cerr.imrtp.dosecalc.influence.getIMDose(im, weightsV: Sequence[float] | None, structNumsV, planC) ndarray[source]
Assemble a 3-D dose distribution from beamlets and PB weights.
Port of
getIMDose.m.- Parameters:
im – IMRTProblem with computed beamlets.
weightsV – one weight per pencil beam (flat, ordered beam-by-beam in PB order), or None for unit weights (open fields).
structNumsV – structure indices over which dose is assembled.
planC – plan container.
- Returns:
np.ndarray of dose on the scan grid (rows x cols x slices).
Note
Where Matlab CERR fills sub-sampled structures with 3-D linear interpolation, this port uses nearest-sampled-point filling inside the structure mask.
cerr.imrtp.dosecalc.montecarlo module
montecarlo
Placeholders for the Monte-Carlo dose engines of CERR’s
IMRTP/recompDose toolbox (DPM and VMC++).
The Matlab originals (https://github.com/cerr/CERR/tree/master/IMRTP/recompDose) drive compiled MC executables and a measurement-based photon source model:
- beam2MCdose.m / beam2MCdose_with_QIB.m
Build the fluence (leaf sequences, MLC transmission leak, wedges, tongue-and-groove, horn/softening corrections, source model) for one beam of an RTPLAN and run the selected solver.
- calcDoseByBeamMeterset.m
Read per-beam MC dose from disk and combine using the plan metersets (DPM path of
call_doseRecal.m).
Porting these requires the DPM / VMC++ binaries, their phase-space /
spectrum inputs (e.g. 6MV10x10MDA.spectrum) and the accelerator-head
source model, none of which ship with pyCERR. The functions below define
the intended Python interfaces and raise NotImplementedError with
pointers to the Matlab references; the parameter set mirrors
call_doseRecal.m so existing workflows translate directly.
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- cerr.imrtp.dosecalc.montecarlo.MC_SOLVER_DPM = 1
solver codes used by call_doseRecal.m
- class cerr.imrtp.dosecalc.montecarlo.MCRecompParams(leak: float = 0.032, spectrum_File: str = '6MV10x10MDA.spectrum', nhist: float = 100000.0, batch: int = 101, OutputError: int = 0, PBMaxWidth: float = 10.0, gradsense: float = 25.0, MCsolver: int = 1, saveIM: int = 0, sourceModel: int = 0, doseToWater: int = 0, fillWater: int = 0, useWedge: int = 0, inputPB: int = 0, inputIM: int = 1, Softening: int = 1, UseFlatFilter: int = 1, MLC: int = 0, TongueGroove: int = 0, interactiveMode: int = 0, LS_flag: int = 0, K: int = 1, scatterThreshold: float = 11.2)[source]
Bases:
objectInputs of
beam2MCdose.m(defaults fromcall_doseRecal.m).- leak: float = 0.032
- spectrum_File: str = '6MV10x10MDA.spectrum'
- nhist: float = 100000.0
- batch: int = 101
- OutputError: int = 0
- PBMaxWidth: float = 10.0
- gradsense: float = 25.0
- MCsolver: int = 1
- saveIM: int = 0
- sourceModel: int = 0
- doseToWater: int = 0
- fillWater: int = 0
- useWedge: int = 0
- inputPB: int = 0
- inputIM: int = 1
- Softening: int = 1
- UseFlatFilter: int = 1
- MLC: int = 0
- TongueGroove: int = 0
- interactiveMode: int = 0
- LS_flag: int = 0
- K: int = 1
- scatterThreshold: float = 11.2
- cerr.imrtp.dosecalc.montecarlo.beam2MCdose(im, planC, whichBeam: int, params: MCRecompParams = None, statusCallback=None)[source]
PLACEHOLDER – Monte-Carlo dose for one beam (DPM or VMC++).
Intended port of
beam2MCdose.m/beam2MCdose_with_QIB.mfrom the CERRrecompDosetoolbox: build the beam fluence map (including MLC leaf sequences, transmission, wedge and source model) and run the selected Monte-Carlo solver, returning the per-beam IM dosimetry and beamlet weights.
- cerr.imrtp.dosecalc.montecarlo.calcDoseByBeamMeterset(planC, nhist: float, batch: int)[source]
PLACEHOLDER – combine per-beam DPM doses using plan metersets.
Intended port of
calcDoseByBeamMeterset.m(DPM path ofcall_doseRecal.m): reads the per-beam MC dose files written by the DPM solver and sums them weighted by the beam metersets.
cerr.imrtp.dosecalc.qib module
qib
QIB (Quadrant Infinite Beam) photon pencil-beam dose calculation.
- Python port of Matlab CERR:
IMRTP/getQIBDose.m (the kernel evaluation, all DoseTerm modes) IMRTP/GetPBConsts.m (‘nearest’ branch) IMRTP/applyIMRTCompression.m (scatter compression of the influence) IMRTP/RTOGVectors2Gantry.m IMRTP/gantry2RTOGVectors.m
Algorithm (Ahnesjo et al., Med. Phys. 19, 263-273 (1992)): dose around a
pencil beam is A(z)exp(-a(z)r)/r + B(z)exp(-b(z)r)/r; the dose from a
finite-width beamlet is obtained by differencing precomputed quadrant
infinite integrals of the kernel. An optional Gaussian smear of the
incident fluence models the finite source size (sigma_100 = projected
source sigma at 100 cm).
Outputs are in relative energy deposited per (g/cm^3) from a point-monodirectional beam (same units as Matlab CERR).
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- cerr.imrtp.dosecalc.qib.getPBConsts(depthsV: ndarray, energy: float, qib: QIBDataS)[source]
Nearest-neighbour lookup of the Ahnesjo A, a, B, b constants vs depth.
Port of
GetPBConsts.mwith flag'nearest'(the branch used bygenerateQIBInfluence.m). Depths in g/cm^2 (radiological), clipped at the 50 cm dosimetry limit.
- cerr.imrtp.dosecalc.qib.getQIBDose(posU: ndarray, radDepthV: ndarray, widthUX: ndarray, widthUY: ndarray, qib: QIBDataS, A_zV, a_zV, B_zV, b_zV, energy: float, how2Compute: str, gaussSigma_100: float, distV: ndarray) ndarray[source]
Fast pencil-beam dose calculation for photon beams.
Port of
getQIBDose.m.- Parameters:
posU – (N, 2) beamlet-frame coordinates (Xb, Yb) of the dose points, cm.
radDepthV – radiological depths (g/cm^2) – unused by the lookup itself but kept for signature parity.
widthUX/Y – beamlet widths at each point’s source distance, cm.
qib – kernel data from
loadPBData().A_zV..b_zV – depth constants from
getPBConsts().energy – nominal beam energy (6 / 18 MV).
how2Compute – one of
'primary','scatter','nogauss+scatter'(a.k.a.'primary+scatter'),'GaussPrimary','GaussPrimary+scatter'.gaussSigma_100 – projected source sigma at 100 cm (cm).
distV – distance from source to each dose point, cm (needed for the Gaussian smear).
- Returns:
Dose vector (relative energy deposited per (g/cm^3)).
- cerr.imrtp.dosecalc.qib.applyIMRTCompression(params, doseV: ndarray) ndarray[source]
Selectively eliminate low-dose scatter components.
Port of
applyIMRTCompression.m;paramsis anIMParams(usesScatterMethod,Scatter.ThresholdandScatter.RandomStep).
cerr.imrtp.dosecalc.qib_data module
qib_data
Loader for the QIB (Quadrant Infinite Beam) pencil-beam kernel data.
Python port of Matlab CERR IMRTP/loadPBData.m.
The QIB algorithm is based on an analytical fit of Monte-Carlo generated pencil-beam data due to Ahnesjo et al. [Med. Phys. 19, 263-273 (1992)]:
D(r, z) = A(z) exp(-a(z) r)/r + B(z) exp(-b(z) r)/r
with fast table look-up of quadrant infinite integrals (integrals of the exponential / Gaussian kernel over an infinite 2-D quadrant).
- Data files (in
dosecalc/QIBData/): aahn_6b.dat / aahn_18b.dat depth tables of A, a, B, b for 6 / 18 MV qib_tables.npz
QIBandQIBGaussquadrant-integrallookup tables (1593 x 1593, originally
QIB_lin_0pt125.mat/QIBGauss_lin_0pt125.mat)
If qib_tables.npz is missing, the original .mat files are downloaded
from the CERR GitHub repository and converted (requires scipy).
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- class cerr.imrtp.dosecalc.qib_data.QIBDataS(aahn6b: ndarray = None, aahn18b: ndarray = None, QIB: ndarray = None, QIBGauss: ndarray = None, deltaQBM: float = 0.0125, QBMidIndexX: int = 792, QBMidIndexY: int = 792, k1: float = 1.1284, k2: float = 0.476, k3: float = 0.0354, k4: float = 0.715)[source]
Bases:
objectContainer mirroring the Matlab
QIBDataSstructure.- aahn6b: ndarray = None
- aahn18b: ndarray = None
- QIB: ndarray = None
- QIBGauss: ndarray = None
- deltaQBM: float = 0.0125
- QBMidIndexX: int = 792
- QBMidIndexY: int = 792
- k1: float = 1.1284
- k2: float = 0.476
- k3: float = 0.0354
- k4: float = 0.715
cerr.imrtp.dosecalc.raytrace module
raytrace
Pencil-beam geometry and CT ray tracing for IMRTP dose calculation.
- Python port of Matlab CERR:
IMRTP/IMRTP.m (getTargetSurfacePoints / getPBList helpers) IMRTP/getPBRays.m (which PBs are needed to cover the target) IMRTP/getPBRayData.m (radiological-depth trace through the CT)
Coordinates are pyCERR/CERR “virtual” coordinates as returned by
planC.scan[n].getScanXYZVals() (x ascending, y descending, z ascending),
all in cm. The scan array is indexed [row, col, slice] with row <-> y
and col <-> x.
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- class cerr.imrtp.dosecalc.raytrace.ScanGrid(planC, scanNum: int)[source]
Bases:
objectCached geometry of a pyCERR scan, plus trilinear density sampling.
- cerr.imrtp.dosecalc.raytrace.getTargetSurfacePoints(im, planC)[source]
Surface points of all target structures, expanded by PBMargin + 0.5 cm.
Returns (xS, yS, zS) coordinate vectors (cm) of the surface voxels of the (margin-expanded) union of the target structures, mirroring
getSurface(structTargetV, PBMarginV + 0.5, ...)inIMRTP.m.
- cerr.imrtp.dosecalc.raytrace.getPBRays(xS, yS, zS, beam)[source]
Determine the pencil beams required to cover the target.
Port of
getPBRays.m: target surface points are projected (through the source) onto the gantry frame at the isocenter distance, binned on the beamlet grid, row gaps are filled, and unit RTOG-frame direction vectors are generated for each pencil beam.- Returns:
- (RTOGPBVectorsM, RTOGPBVectorsM_MC, PBMaskM, rowPBV, colPBV,
xPBPosV, yPBPosV)
- class cerr.imrtp.dosecalc.raytrace.CTTrace(distSamplePts: ndarray = None, densityRay: ndarray = None, cumDensityRay: ndarray = None)[source]
Bases:
objectCumulative radiological depth along one pencil-beam ray.
- distSamplePts: ndarray = None
- densityRay: ndarray = None
- cumDensityRay: ndarray = None
- cerr.imrtp.dosecalc.raytrace.getPBRayData(xS, yS, zS, beam, numSamplePts: int, grid: ScanGrid)[source]
Pencil-beam geometry plus cumulative-density CT traces for one beam.
Port of
getPBRayData.m. Returns(ctTraceList, RTOGPBVectorsM, RTOGPBVectorsM_MC, pbMask, rowPBV, colPBV, xPBPosV, yPBPosV).
- cerr.imrtp.dosecalc.raytrace.setBeamRayData(im, planC, statusCallback=None)[source]
Populate ray-trace fields on every beam of
im.Port of the
getPBListhelper inIMRTP.m: computes the PB direction matrix and CT traces, and sets the absolute source position (xRel/yRel/zRel + isocenter) on each beam.
cerr.imrtp.dosecalc.recalc module
recalc
Dose recomputation driver – Python port of CERR’s
IMRTP/recompDose/call_doseRecal.m.
Workflow (as in the Matlab script):
(optional CT downsample – not yet ported, see note below)
choose the solver: QIB (implemented) or DPM / VMC++ (placeholders, see
cerr.imrtp.dosecalc.montecarlo)compute the beamlet influence for every beam over the requested structures / sample rates
store the IM dosimetry on
planC.imand assemble the 3-D doseoptionally scale the result to a clinical dose using a DVH metric of a target structure (mean dose or D98, as in call_doseRecal.m)
import the dose into
planC.dose
Example:
from cerr.imrtp.dosecalc import recalcDose
doseNum, dose3D, im = recalcDose(
planC, im,
structNumsV=[5, 6, 7], sampleRateV=[4, 2, 2],
imrtpName='QIB reCalc',
ptvStructNum=13, clinicDoseNum=0, scaleMetric='meanDose')
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- cerr.imrtp.dosecalc.recalc.structDoseMetric(planC, structNum: int, doseNum: int, metric: str = 'meanDose', x: float = 98.0, binWidth: float = 0.01) float[source]
DVH metric of a structure for a given dose (Dx / meanDose helpers used by
call_doseRecal.mfor clinical-dose scaling).
- cerr.imrtp.dosecalc.recalc.recalcDose(planC, im: IMRTProblem, structNumsV: Sequence[int] | None = None, sampleRateV: Sequence[int] | None = None, algorithm: str = 'QIB', imrtpName: str = 'QIB reCalc', beamletWeightsV: Sequence[float] | None = None, scatterThreshold: float | None = None, ptvStructNum: int | None = None, clinicDoseNum: int | None = None, scaleMetric: str = 'meanDose', dxPercent: float = 98.0, saveIM: bool = True, statusCallback=None)[source]
Recompute dose for an IMRT problem (port of
call_doseRecal.m).- Parameters:
planC – pyCERR plan container.
im – IMRTProblem describing beams, goals and params (build one with the IMRTP GUI or
cerr.imrtp.initIMRTProblem).structNumsV – structure indices where dose is computed. If None, the structures of
im.goalsare used.sampleRateV – per-structure in-plane sample rates (powers of 2; e.g. skin 8, targets/critical structures 2). Same length as
structNumsV.algorithm – ‘QIB’ (implemented), ‘DPM’ or ‘VMC++’ (placeholders; see dosecalc.montecarlo).
imrtpName – name of the IM dosimetry stored on
planC.im.beamletWeightsV – one weight per pencil beam (flat, beam-by-beam) or None for open (unit-weight) fields.
scatterThreshold – optional override of
im.params.Scatter.Threshold(QIB default in call_doseRecal.m: 0.1).ptvStructNum – target structure used to scale to the clinical dose (skipped when
clinicDoseNumis None).clinicDoseNum – index of the clinical dose in
planC.doseto scale against.scaleMetric – ‘meanDose’ (call_doseRecal.m default) or ‘Dx’.
dxPercent – x for the Dx metric (default 98).
saveIM – store the IM dosimetry on
planC.im.statusCallback – optional
fn(msg, frac).
- Returns:
index of the new dose in
planC.dose, the dose array, and the updated IMRTProblem.- Return type:
(doseNum, dose3D, im)
Note
The Matlab script optionally downsamples the CT by a factor of 2 before computing (
getplanCDownSample); CT downsampling is not yet available in pyCERR, so compute time is controlled throughsampleRateVand the beamlet size instead.
cerr.imrtp.dosecalc.rtplan module
rtplan
Build an IMRT problem from the beams of a DICOM RTPLAN stored on
planC.beams – the role of the beam-geometry section of CERR’s
recompDose/beam2MCdose.m (gantry / couch / collimator angles,
isocenter, SAD and nominal energy per beam).
Typical use (the call_doseRecal.m workflow on a DICOM dataset):
from cerr import plan_container as pc
from cerr.imrtp.dosecalc import imFromRTPlan, recalcDose
planC = pc.loadDcmDir(r'C:/data/myPlan') # CT + RTSTRUCT + RTPLAN
im = imFromRTPlan(planC, targetStructNum=ptvNum)
doseNum, dose3D, im = recalcDose(planC, im, structNumsV=[...],
sampleRateV=[...])
- What is taken from the RTPLAN (as in beam2MCdose.m):
gantry angle, couch (PatientSupportAngle) and collimator angles of the first control point of each TREATMENT beam,
isocenter position (converted from DICOM mm to pyCERR virtual cm via
scan.cerrToDcmTransM),source-axis distance (mm -> cm),
nominal beam energy (mapped to the nearest QIB kernel energy, 6 or 18 MV, with a warning when not exact).
What is NOT taken: MLC leaf sequences / fluence maps, wedges and per-beam
metersets. The QIB recomputation covers the target (+ PBMargin) with
open beamlets; use beamletWeightsV for IMRT weights and the
clinical-dose scaling of recalcDose() to set
absolute dose.
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- cerr.imrtp.dosecalc.rtplan.QIB_ENERGIES = (6.0, 18.0)
energies for which QIB kernel tables exist
- cerr.imrtp.dosecalc.rtplan.dcmIsocenterToCerr(isoDcm_mm, planC, scanNum: int)[source]
DICOM patient coordinates (mm) -> pyCERR virtual coordinates (cm).
Uses the scan’s
cerrToDcmTransM(pyCERR xyz cm -> DICOM mm); falls back to the simple HFS relation used bybeam2MCdose.m(x/10, -y/10, -z/10) if the matrix is unavailable.
- cerr.imrtp.dosecalc.rtplan.beamsFromRTPlan(planC, beamsNum: int = 0, scanNum: int | None = None, energyMap: bool = True) List[IMBeam][source]
Convert the TREATMENT beams of
planC.beams[beamsNum]to IMBeams.Mirrors the geometry import of
beam2MCdose.m: per beam the first control point supplies gantry / couch / collimator angles, nominal energy and isocenter; SAD comes from the beam sequence. Source positions are derived asxRel = SAD sin(g),yRel = SAD cos(g),zRel = 0, rotated by the couch angle.- Parameters:
planC – plan container with an RTPLAN loaded.
beamsNum – index into
planC.beams.scanNum – scan used for the DICOM->CERR isocenter transform (default 0).
energyMap – map nominal energies to the nearest QIB energy (6 / 18 MV). Set False to keep the RTPLAN value.
- Returns:
list of
IMBeam.
- cerr.imrtp.dosecalc.rtplan.imFromRTPlan(planC, beamsNum: int = 0, targetStructNum: int | None = None, structNumsV: Sequence[int] | None = None, sampleRateV: Sequence[int] | None = None, scanNum: int = 0, PBMargin: float = 0.5, beamletDelta: float = 1.0, name: str | None = None) IMRTProblem[source]
Build an
IMRTProblemfrom the RTPLAN ofplanC.- Parameters:
planC – plan container (CT + RTSTRUCT + RTPLAN loaded).
beamsNum – index into
planC.beams.targetStructNum –
planC.structureindex of the target (PTV) that the beamlets must cover.structNumsV – additional structures where dose is computed (default: target only);
planC.structureindices.sampleRateV – per-structure sample rates for
structNumsV(default 2 each).scanNum – associated scan.
PBMargin – beamlet margin around the target, cm (beam2MCdose.m uses 0.5).
beamletDelta – beamlet width at the isocenter, cm.
name – IM name (default: the RTPLAN label).
- Returns:
IMRTProblem ready for
recalcDose()/runIMRTP().
Module contents
cerr.imrtp.dosecalc
Dose-calculation engines for pyCERR’s IMRTP module.
- Implemented:
- QIB Quadrant Infinite Beam photon pencil-beam algorithm (Ahnesjo
analytical kernel with quadrant-integral lookup tables), ported from Matlab CERR
IMRTP/getQIBDose.mand friends.
Placeholders (interfaces defined, ports pending – see https://github.com/cerr/CERR/tree/master/IMRTP/recompDose):
DPM Dose Planning Method Monte Carlo VMC++ Voxel Monte Carlo
Importing this package registers ‘QIB’ (and the ‘DPM’ / ‘VMC++’
placeholders) with the cerr.imrtp engine registry, so they appear
in the IMRTP GUI’s algorithm drop-down and work with
cerr.imrtp.runIMRTP.
High-level entry point (port of recompDose/call_doseRecal.m):
from cerr.imrtp.dosecalc import recalcDose
doseNum, dose3D, im = recalcDose(planC, im, structNumsV=[1, 2],
sampleRateV=[2, 2])
This file is part of pyCERR and is distributed under the terms of the Lesser GNU Public License (same terms as CERR).
- class cerr.imrtp.dosecalc.QIBDataS(aahn6b: ndarray = None, aahn18b: ndarray = None, QIB: ndarray = None, QIBGauss: ndarray = None, deltaQBM: float = 0.0125, QBMidIndexX: int = 792, QBMidIndexY: int = 792, k1: float = 1.1284, k2: float = 0.476, k3: float = 0.0354, k4: float = 0.715)[source]
Bases:
objectContainer mirroring the Matlab
QIBDataSstructure.- aahn6b: ndarray = None
- aahn18b: ndarray = None
- QIB: ndarray = None
- QIBGauss: ndarray = None
- deltaQBM: float = 0.0125
- QBMidIndexX: int = 792
- QBMidIndexY: int = 792
- k1: float = 1.1284
- k2: float = 0.476
- k3: float = 0.0354
- k4: float = 0.715
- cerr.imrtp.dosecalc.loadPBData() QIBDataS[source]
Load (and cache) the QIB pencil-beam kernel data.
Port of
loadPBData.m.
- cerr.imrtp.dosecalc.getQIBDose(posU: ndarray, radDepthV: ndarray, widthUX: ndarray, widthUY: ndarray, qib: QIBDataS, A_zV, a_zV, B_zV, b_zV, energy: float, how2Compute: str, gaussSigma_100: float, distV: ndarray) ndarray[source]
Fast pencil-beam dose calculation for photon beams.
Port of
getQIBDose.m.- Parameters:
posU – (N, 2) beamlet-frame coordinates (Xb, Yb) of the dose points, cm.
radDepthV – radiological depths (g/cm^2) – unused by the lookup itself but kept for signature parity.
widthUX/Y – beamlet widths at each point’s source distance, cm.
qib – kernel data from
loadPBData().A_zV..b_zV – depth constants from
getPBConsts().energy – nominal beam energy (6 / 18 MV).
how2Compute – one of
'primary','scatter','nogauss+scatter'(a.k.a.'primary+scatter'),'GaussPrimary','GaussPrimary+scatter'.gaussSigma_100 – projected source sigma at 100 cm (cm).
distV – distance from source to each dose point, cm (needed for the Gaussian smear).
- Returns:
Dose vector (relative energy deposited per (g/cm^3)).
- cerr.imrtp.dosecalc.getPBConsts(depthsV: ndarray, energy: float, qib: QIBDataS)[source]
Nearest-neighbour lookup of the Ahnesjo A, a, B, b constants vs depth.
Port of
GetPBConsts.mwith flag'nearest'(the branch used bygenerateQIBInfluence.m). Depths in g/cm^2 (radiological), clipped at the 50 cm dosimetry limit.
- cerr.imrtp.dosecalc.applyIMRTCompression(params, doseV: ndarray) ndarray[source]
Selectively eliminate low-dose scatter components.
Port of
applyIMRTCompression.m;paramsis anIMParams(usesScatterMethod,Scatter.ThresholdandScatter.RandomStep).
- cerr.imrtp.dosecalc.rtogVectors2Gantry(rtogVectorsM: ndarray, gantryAngle: float) ndarray[source]
Rotate RTOG-frame vectors into the gantry frame.
Port of
RTOGVectors2Gantry.m. Gantry frame: Xb in-plane, Yb out-of-plane (along -z), Zb along the beam axis.
- cerr.imrtp.dosecalc.gantry2RTOGVectors(gantryVectorsM: ndarray, gantryAngle: float, couchAngle: float = 0.0) ndarray[source]
Rotate gantry-frame vectors back into the RTOG frame.
Port of
gantry2RTOGVectors.m(including couch rotation).
- class cerr.imrtp.dosecalc.ScanGrid(planC, scanNum: int)[source]
Bases:
objectCached geometry of a pyCERR scan, plus trilinear density sampling.
- cerr.imrtp.dosecalc.getTargetSurfacePoints(im, planC)[source]
Surface points of all target structures, expanded by PBMargin + 0.5 cm.
Returns (xS, yS, zS) coordinate vectors (cm) of the surface voxels of the (margin-expanded) union of the target structures, mirroring
getSurface(structTargetV, PBMarginV + 0.5, ...)inIMRTP.m.
- cerr.imrtp.dosecalc.getPBRays(xS, yS, zS, beam)[source]
Determine the pencil beams required to cover the target.
Port of
getPBRays.m: target surface points are projected (through the source) onto the gantry frame at the isocenter distance, binned on the beamlet grid, row gaps are filled, and unit RTOG-frame direction vectors are generated for each pencil beam.- Returns:
- (RTOGPBVectorsM, RTOGPBVectorsM_MC, PBMaskM, rowPBV, colPBV,
xPBPosV, yPBPosV)
- cerr.imrtp.dosecalc.getPBRayData(xS, yS, zS, beam, numSamplePts: int, grid: ScanGrid)[source]
Pencil-beam geometry plus cumulative-density CT traces for one beam.
Port of
getPBRayData.m. Returns(ctTraceList, RTOGPBVectorsM, RTOGPBVectorsM_MC, pbMask, rowPBV, colPBV, xPBPosV, yPBPosV).
- cerr.imrtp.dosecalc.setBeamRayData(im, planC, statusCallback=None)[source]
Populate ray-trace fields on every beam of
im.Port of the
getPBListhelper inIMRTP.m: computes the PB direction matrix and CT traces, and sets the absolute source position (xRel/yRel/zRel + isocenter) on each beam.
- class cerr.imrtp.dosecalc.CTTrace(distSamplePts: ndarray = None, densityRay: ndarray = None, cumDensityRay: ndarray = None)[source]
Bases:
objectCumulative radiological depth along one pencil-beam ray.
- distSamplePts: ndarray = None
- densityRay: ndarray = None
- cumDensityRay: ndarray = None
- cerr.imrtp.dosecalc.generateQIBInfluence(im, planC, statusCallback=None)[source]
Generate QIB beamlet influence for every goal structure and beam.
Port of
generateQIBInfluence.m. Fillsbeam.beamletson every beam ofimand returnsim.
- cerr.imrtp.dosecalc.getIMDose(im, weightsV: Sequence[float] | None, structNumsV, planC) ndarray[source]
Assemble a 3-D dose distribution from beamlets and PB weights.
Port of
getIMDose.m.- Parameters:
im – IMRTProblem with computed beamlets.
weightsV – one weight per pencil beam (flat, ordered beam-by-beam in PB order), or None for unit weights (open fields).
structNumsV – structure indices over which dose is assembled.
planC – plan container.
- Returns:
np.ndarray of dose on the scan grid (rows x cols x slices).
Note
Where Matlab CERR fills sub-sampled structures with 3-D linear interpolation, this port uses nearest-sampled-point filling inside the structure mask.
- class cerr.imrtp.dosecalc.MCRecompParams(leak: float = 0.032, spectrum_File: str = '6MV10x10MDA.spectrum', nhist: float = 100000.0, batch: int = 101, OutputError: int = 0, PBMaxWidth: float = 10.0, gradsense: float = 25.0, MCsolver: int = 1, saveIM: int = 0, sourceModel: int = 0, doseToWater: int = 0, fillWater: int = 0, useWedge: int = 0, inputPB: int = 0, inputIM: int = 1, Softening: int = 1, UseFlatFilter: int = 1, MLC: int = 0, TongueGroove: int = 0, interactiveMode: int = 0, LS_flag: int = 0, K: int = 1, scatterThreshold: float = 11.2)[source]
Bases:
objectInputs of
beam2MCdose.m(defaults fromcall_doseRecal.m).- leak: float = 0.032
- spectrum_File: str = '6MV10x10MDA.spectrum'
- nhist: float = 100000.0
- batch: int = 101
- OutputError: int = 0
- PBMaxWidth: float = 10.0
- gradsense: float = 25.0
- MCsolver: int = 1
- saveIM: int = 0
- sourceModel: int = 0
- doseToWater: int = 0
- fillWater: int = 0
- useWedge: int = 0
- inputPB: int = 0
- inputIM: int = 1
- Softening: int = 1
- UseFlatFilter: int = 1
- MLC: int = 0
- TongueGroove: int = 0
- interactiveMode: int = 0
- LS_flag: int = 0
- K: int = 1
- scatterThreshold: float = 11.2
- cerr.imrtp.dosecalc.beam2MCdose(im, planC, whichBeam: int, params: MCRecompParams = None, statusCallback=None)[source]
PLACEHOLDER – Monte-Carlo dose for one beam (DPM or VMC++).
Intended port of
beam2MCdose.m/beam2MCdose_with_QIB.mfrom the CERRrecompDosetoolbox: build the beam fluence map (including MLC leaf sequences, transmission, wedge and source model) and run the selected Monte-Carlo solver, returning the per-beam IM dosimetry and beamlet weights.
- cerr.imrtp.dosecalc.calcDoseByBeamMeterset(planC, nhist: float, batch: int)[source]
PLACEHOLDER – combine per-beam DPM doses using plan metersets.
Intended port of
calcDoseByBeamMeterset.m(DPM path ofcall_doseRecal.m): reads the per-beam MC dose files written by the DPM solver and sums them weighted by the beam metersets.
- cerr.imrtp.dosecalc.recalcDose(planC, im: IMRTProblem, structNumsV: Sequence[int] | None = None, sampleRateV: Sequence[int] | None = None, algorithm: str = 'QIB', imrtpName: str = 'QIB reCalc', beamletWeightsV: Sequence[float] | None = None, scatterThreshold: float | None = None, ptvStructNum: int | None = None, clinicDoseNum: int | None = None, scaleMetric: str = 'meanDose', dxPercent: float = 98.0, saveIM: bool = True, statusCallback=None)[source]
Recompute dose for an IMRT problem (port of
call_doseRecal.m).- Parameters:
planC – pyCERR plan container.
im – IMRTProblem describing beams, goals and params (build one with the IMRTP GUI or
cerr.imrtp.initIMRTProblem).structNumsV – structure indices where dose is computed. If None, the structures of
im.goalsare used.sampleRateV – per-structure in-plane sample rates (powers of 2; e.g. skin 8, targets/critical structures 2). Same length as
structNumsV.algorithm – ‘QIB’ (implemented), ‘DPM’ or ‘VMC++’ (placeholders; see dosecalc.montecarlo).
imrtpName – name of the IM dosimetry stored on
planC.im.beamletWeightsV – one weight per pencil beam (flat, beam-by-beam) or None for open (unit-weight) fields.
scatterThreshold – optional override of
im.params.Scatter.Threshold(QIB default in call_doseRecal.m: 0.1).ptvStructNum – target structure used to scale to the clinical dose (skipped when
clinicDoseNumis None).clinicDoseNum – index of the clinical dose in
planC.doseto scale against.scaleMetric – ‘meanDose’ (call_doseRecal.m default) or ‘Dx’.
dxPercent – x for the Dx metric (default 98).
saveIM – store the IM dosimetry on
planC.im.statusCallback – optional
fn(msg, frac).
- Returns:
index of the new dose in
planC.dose, the dose array, and the updated IMRTProblem.- Return type:
(doseNum, dose3D, im)
Note
The Matlab script optionally downsamples the CT by a factor of 2 before computing (
getplanCDownSample); CT downsampling is not yet available in pyCERR, so compute time is controlled throughsampleRateVand the beamlet size instead.
- cerr.imrtp.dosecalc.structDoseMetric(planC, structNum: int, doseNum: int, metric: str = 'meanDose', x: float = 98.0, binWidth: float = 0.01) float[source]
DVH metric of a structure for a given dose (Dx / meanDose helpers used by
call_doseRecal.mfor clinical-dose scaling).
- cerr.imrtp.dosecalc.qibEngine(im, planC, statusCallback=None)[source]
QIB dose engine for the cerr.imrtp registry.
Computes the beamlet influence over all goal structures and returns the unit-weight (open-field) dose on the scan grid.
- cerr.imrtp.dosecalc.imFromRTPlan(planC, beamsNum: int = 0, targetStructNum: int | None = None, structNumsV: Sequence[int] | None = None, sampleRateV: Sequence[int] | None = None, scanNum: int = 0, PBMargin: float = 0.5, beamletDelta: float = 1.0, name: str | None = None) IMRTProblem[source]
Build an
IMRTProblemfrom the RTPLAN ofplanC.- Parameters:
planC – plan container (CT + RTSTRUCT + RTPLAN loaded).
beamsNum – index into
planC.beams.targetStructNum –
planC.structureindex of the target (PTV) that the beamlets must cover.structNumsV – additional structures where dose is computed (default: target only);
planC.structureindices.sampleRateV – per-structure sample rates for
structNumsV(default 2 each).scanNum – associated scan.
PBMargin – beamlet margin around the target, cm (beam2MCdose.m uses 0.5).
beamletDelta – beamlet width at the isocenter, cm.
name – IM name (default: the RTPLAN label).
- Returns:
IMRTProblem ready for
recalcDose()/runIMRTP().
- cerr.imrtp.dosecalc.beamsFromRTPlan(planC, beamsNum: int = 0, scanNum: int | None = None, energyMap: bool = True) List[IMBeam][source]
Convert the TREATMENT beams of
planC.beams[beamsNum]to IMBeams.Mirrors the geometry import of
beam2MCdose.m: per beam the first control point supplies gantry / couch / collimator angles, nominal energy and isocenter; SAD comes from the beam sequence. Source positions are derived asxRel = SAD sin(g),yRel = SAD cos(g),zRel = 0, rotated by the couch angle.- Parameters:
planC – plan container with an RTPLAN loaded.
beamsNum – index into
planC.beams.scanNum – scan used for the DICOM->CERR isocenter transform (default 0).
energyMap – map nominal energies to the nearest QIB energy (6 / 18 MV). Set False to keep the RTPLAN value.
- Returns:
list of
IMBeam.
- cerr.imrtp.dosecalc.dcmIsocenterToCerr(isoDcm_mm, planC, scanNum: int)[source]
DICOM patient coordinates (mm) -> pyCERR virtual coordinates (cm).
Uses the scan’s
cerrToDcmTransM(pyCERR xyz cm -> DICOM mm); falls back to the simple HFS relation used bybeam2MCdose.m(x/10, -y/10, -z/10) if the matrix is unavailable.