sequencing

MLC leaf sequencing algorithms for converting fluence maps to deliverable photon IMRT plans.

class matRad_PhotonLeafSequencerEngel(pln)

Bases: matRad_PhotonLeafSequencerAbstract

Property Summary
name = 'Photons Engel Leaf Sequencer'
shortName = 'engel'
possibleRadiationModes = {'photons'}
Method Summary
sequence(this, w, stf)
pragma Justify(metric, “cnest”,
“grandfathered: pre-existing nesting depth of the ported Engel algorithm”);
static isAvailable(pln, machine)

see superclass for information

class matRad_ParticleScanningSequencerSpill(pln)

Bases: matRad_SequencerBase

matRad_ParticleScanningSequencerSpill: Sequencer for scanned particle delivery. Computes the spot delivery order and timing (spill / lateral scanning model), e.g. for 4D dose calculation. It does not modify the fluence.

Constructor, forwards to the base class. An explicit constructor chain is required so that property assignment from pln persists under Octave.

Property Summary
name = 'Particle Spill Scanning Sequencer'
shortName = 'IMPT'
possibleRadiationModes = {'protons','helium','carbon','oxygen'}
weightPencilBeam = 1e6
esTime = 3*10^6

[mu s] time required for synchrotron to recharge it’ spill

spillRechargeTime = 2*10^6

[mu s] number of particles generated in each spill

spillSize = 4*10^10
scanSpeed = 10

[m/s] speed of synchrotron’s lateral scanning in an IES

spillIntensity = 4*10^8

number of particles per second

Method Summary
sequence(this, w, stf)
calcSpotOrder(~, stf)
calcSpotTime(this, sequence, w, stf)
static isAvailable(pln, machine)

see superclass for information

static makePhaseMatrix(sequence, numOfPhases, motionPeriod)
matRad_enforceDeliveryConstraints(apertureInfo, fast)

matRad: make an arc plan deliverable within the machine limits

Slows the gantry (and with it the dose rate) at each DAO control point until the realized leaf speed and monitor unit rate fit the machine constraints in apertureInfo.deliveryConstraints.

call

apertureInfo = matRad_enforceDeliveryConstraints(apertureInfo, fast)

input
apertureInfo: aperture shape info struct from DAO/sequencing

(requires apertureInfo.arc)

fast: 1 => fastest possible delivery

0 => multiply delivery time by 10%

output

apertureInfo: aperture shape info struct


Copyright 2016 the matRad development team.

This file is part of the matRad project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/e0404/matRad/LICENSE.md. No part of the matRad project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.


class matRad_PhotonLeafSequencerXia(pln)

Bases: matRad_PhotonLeafSequencerAbstract

Property Summary
name = 'Photons Xia Leaf Sequencer'
shortName = 'xia'
possibleRadiationModes = {'photons'}
mode = 'rl'

sliding window (sw) or reducing level (rl)

Method Summary
sequence(this, w, stf)
static isAvailable(pln, machine)

see superclass for information

class matRad_PhotonLeafSequencerVMATAbstract(pln)

Bases: matRad_PhotonLeafSequencerAbstract

Property Summary
isVMATCapable = true

cheap tag for isprop-style capability checks

runVMAT = false

toggle VMAT (dynamic/arc) delivery

continuousAperture = false

interpolate leaf positions between DAO angles

arcFluenceSmoothing = 'gaussian'

fluence smoothing kernel applied before stratification, see availableArcFluenceSmoothing

apertureSelection = 'doseAreaProduct'

how surplus apertures are discarded, see availableApertureSelection

weightToMU = 1

bixel weight -> MU conversion factor (from dij.weightToMU)

Method Summary
smoothFluenceForArc(this, fluenceMx)

Fluence smoothing prior to stratification, selected by the arcFluenceSmoothing property. Only applied for VMAT: it alters the fluence that is decomposed, so the sequenced result no longer reproduces the optimized fluence, which is exactly what static/IMRT sequencing relies on.

It defaults to ‘gaussian’ because VMAT needs one aperture per DAO control point: the graded field rim the blur produces is what lets the stratification yield more apertures as the level count is raised. A perfectly flat fluence decomposes into a single aperture at any number of levels, which no amount of re-stratification can fix (see sequenceDynamic).

applyArcSequencing(this, sequence, stf)

Spreads the shapes generated at each FMO-anchor beam across its DAO-angle children and computes gantry rotation speed / MU rate. arcSequencing needs sequence.deliveryConstraints to be set.

arcSequencing(this, sequencing, stf)

Distributes the shapes generated at each FMO-anchor beam to its DAO-angle children according to the sweep trajectory, then computes per-beam gantry rotation speed, MU rate and rescaled shape weights. Assumes shapes are already ordered in increasing (left to right) leaf position.

Input:
  • sequencing – shape sequencing structure (needs .beam and .deliveryConstraints)

  • stf – matRad steering struct (beam geometry etc.)

Output:

beam – beam struct with shapes and weights distributed to the correct optimized gantry angles

getMachineConstraints(~, stf)

Loads the machine delivery constraints (gantry rotation speed, leaf speed, MU rate) referenced by the given stf, falling back to generic defaults if the machine file doesn’t define any.

buildVMATApertureInfo(this, sequence, stf)

Ports the VMAT branch of the former matRad_sequencing2ApertureInfo.m to build the full apertureInfo struct including apertureInfo.arc.*, then converts it to the DAO vector representation via matRad_OptimizationProblemVMAT.

postProcessVMATApertureInfo(~, apertureInfo)

Interpolates sub-child gantry segments, then runs the leaf-speed/dose-rate limiting pass (optDelivery).

static availableArcFluenceSmoothing()

Fluence smoothing kernels a VMAT sequencer can apply before stratifying an FMO fluence map into apertures.

class matRad_PhotonLeafSequencerSiochi(pln)

Bases: matRad_PhotonLeafSequencerVMATAbstract

Property Summary
name = 'Photons Siochi Leaf Sequencer'
shortName = 'siochi'
possibleRadiationModes = {'photons'}
Method Summary
sequence(this, w, stf)
sequenceStatic(this, w, stf)
sequenceDynamic(this, w, stf)

VMAT (dynamic/arc) sequencing: gates to FMO-anchor beams, optionally smooths the fluence before decomposition (see arcFluenceSmoothing), keeps re-decomposing at increasing numLevels until enough shapes exist for this beam’s DAO-angle children, then spreads the result across those children and builds the VMAT apertureInfo. Ported from the former matRad_siochiLeafSequencing.m functional implementation.

decomposePort(this, map)

Returns tops and bases of a fluence matrix “map” for Siochi leaf sequencing algorithm (rod pushing part). Accounts for collisions and tongue and groove (Tng) effects.

fixTnGPass(~, tops, bases, map, i, jRange, neighborOffset)

One directional tongue-and-groove correction pass over jRange, matching each rod j against its neighbor j+neighborOffset. Shared by decomposePort’s “down” (neighborOffset=1, comparing against j+1) and “up” (neighborOffset=-1, comparing against j-1) passes, which are otherwise identical.

convertToSegments(this, shapes, shapesWeight, k, tops, bases)

Convert tops and bases to shape matrices. These are taken as to be the shapes of uniform level/elevation after the rods are pushed.

differentSlab(~, tops, bases, level)

Returns 1 if slab level is different than slab level-1 0 otherwise

static isAvailable(pln, machine)

see superclass for information

matRad_calcMaxLeafSpeed(apertureInfo)

matRad calculation of maximum leaf speed

Records the leaf speed realized by an arc plan, per DAO control point and over the whole arc. This is the reporting/limiting computation used after sequencing; the differentiable leaf speed constraint used during DAO is computed separately in matRad_OptimizationProblemVMAT.

call

apertureInfo = matRad_calcMaxLeafSpeed(apertureInfo)

input

apertureInfo: aperture info struct (requires apertureInfo.arc)

output
apertureInfo: aperture info struct, with maxLeafSpeed set on each DAO

beam and on the struct itself


Copyright 2015 the matRad development team.

This file is part of the matRad project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/e0404/matRad/LICENSE.md. No part of the matRad project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.


class matRad_PhotonLeafSequencerAbstract(pln)

Bases: matRad_SequencerBase

Constructor, forwards to the base class. An explicit constructor chain is required so that property assignment from pln persists under Octave.

Property Summary
numOfMLCLeafPairs = 80
numLevels = 5

number of fluence stratification levels for leaf sequencing (for VMAT only a

preconditioner = false

it is increased automatically until every FMO beam yields at least as many apertures as it has DAO child angles)

Type:

starting value

sequencingLevel

deprecated alias for numLevels

Method Summary
sequence(this, w, stf)
initBeam(this, stf, wCurr)
sequencing2ApertureInfo(this, sequence, stf)

MLC parameters:

plotSegments(this, sequencing)

create the sequencing figure

static isAvailable(pln, machine)
static aperture2collimation(pln, stf, sequence, visBool)
static getMLCGeometry(stfBeam, numOfMLCLeafPairs, bixelIndOffset)

Derive the per-beam MLC geometry from an stf beam’s ray positions: bixel index map, leaf position limits, active leaf pairs and MLC window. Shared by aperture-info construction in the photon sequencers and the fine-angle recalculation.

Input:
  • stfBeam – single stf beam entry (stf(i))

  • numOfMLCLeafPairs – total number of physical MLC leaf pairs

  • bixelIndOffset – index of the last bixel of the preceding beams; the beam’s rays are numbered starting from bixelIndOffset + 1

Output:
  • geometry – struct with fields numOfActiveLeafPairs, leafPairPos, isActiveLeafPair, centralLeafPair, limLeft, limRight, bixelIndMap, posOfCornerBixel, MLCWindow

  • bixelIndOffset – updated offset (input + stfBeam.numOfRays)

static discardApertures(beam, numToKeep, selection)

The sequencing algorithm generates an a priori unknown number of apertures. We only want to keep a certain number of them (numToKeep), see availableApertureSelection for how they are picked. The kept shapes are preserved in their original trajectory order and get new weights.

Input:
  • beam – beam struct containing original shapes and intensities

  • numToKeep – number of apertures to keep

  • selection – ‘doseAreaProduct’ (default) or ‘leastSquares’

Output:

newBeam – beam struct with shapes and re-scaled intensities

static availableApertureSelection()

Strategies for reducing the generated apertures of a beam to the number that can actually be delivered:

doseAreaProduct  keep the apertures with the highest product of
                 open area and weight, and rescale them so that
                 the total dose-area product is maintained.
                 Since the stratification gives every segment
                 the same weight, this ranks by open area.
leastSquares     keep the apertures that best reconstruct the
                 fluence the full decomposition would deliver,
                 with the weights refit to that fluence.
static selectByDoseAreaProduct(beam, numToKeep)

Original selection: highest open-area x weight, rescaled to preserve the total dose-area product.

static selectByLeastSquares(beam, numToKeep)

Pick the subset of apertures that best reproduces the fluence the full decomposition delivers, and refit their weights to it.

Forward stepwise selection: in each step try every aperture that is not selected yet, refit ALL weights by non-negative least squares, and keep the candidate with the smallest residual. Refitting before choosing matters - picking by the residual reduction of a single aperture (plain matching pursuit) commits to an aperture before the weights of the others can adapt, and then never recovers from overshooting.

Cost is numToKeep x numOfShapes tiny least squares solves, which is nothing next to the decomposition itself.

static solveNonNegativeLeastSquares(designMx, rhs)

Minimal non-negative least squares for the handful of columns used here: solve unconstrained, drop the most negative coefficient, repeat. Not a full Lawson-Hanson (coefficients are never re-admitted), which is adequate for numToKeep columns.

matRad_aperture2collimation(pln, stf, sequencing, apertureInfo)

matRad function to convert sequencing information / aperture information into collimation information in pln and stf for field-based dose calculation

call

[pln,stf] = matRad_aperture2collimation(pln,stf,sequencing,apertureInfo)

Input:
  • pln – pln file used to generate the sequenced plan

  • stf – stf file used to generate the sequenced plan

  • sequencing – sequencing information (from resultGUI)

  • apertureInfo – apertureInfo (from resultGUI)

Output:
  • pln – matRad pln struct with collimation information

  • stf – matRad stf struct with shapes instead of beamlets

References

Copyright 2022-2026 the matRad development team. Author: wahln

This file is part of the matRad project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/e0404/matRad/LICENSE.md. No part of the matRad project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.


matRad_leafTouching(apertureInfo)

matRad function to improve instances of leaf touching by moving leaves from the centre to sweep with the non-touching leaves.

Currently only works with VMAT, add option to work with IMRT (not as crucial)

call

apertureInfo = matRad_leafTouching(apertureInfo)

input
apertureInfo: matRad aperture weight and shape info struct (requires

apertureInfo.arc)

output

apertureInfo: matRad aperture weight and shape info struct

Note on the two sampling modes below: the function dispatches on whether shape(1) already carries leftLeafPosInitial/Final, sampling the trajectory either once (beam centre) or twice (dose sector borders) per DAO beam. Only the once-per-beam mode has ever run. The sole call site (matRad_PhotonLeafSequencerVMATAbstract) does not set those fields beforehand – this function creates them itself, at the end of its own run – and that has been true since the function was first added. The twice-per-beam mode was presumably written for a second, post-DAO cleanup invocation that was never wired up; it read a field that never existed on apertureInfo.beam, so it would have errored on its first execution. Its output has therefore never been validated: do not enable a second invocation without checking the sweep-reset semantics (the limLeft/limRight substitution at FMO sector borders) against intent.

References


Copyright 2015 the matRad development team.

This file is part of the matRad project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/e0404/matRad/LICENSE.md. No part of the matRad project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.


class matRad_SequencerBase(pln)

Bases: handle

matRad_SequencerBase: Abstract base class for all matRad sequencers. Defines the common interface and the factory/lookup machinery (see getSequencerFromPln / getAvailableSequencers) shared by the photon leaf sequencers and the particle spot sequencer.

Constructs standalone sequencer with or without pln

Property Summary
isSequencer = true

const boolean for inheritance quick check

name

Descriptive Name

shortName

Short name for referencing

possibleRadiationModes

Possible radiation modes for the respective Sequencer

radiationMode

Radiation Mode

visMode = 0

vis bool

Method Summary
setDefaults(this)

set default values from MatRad_Config

warnDeprecatedProperty(this, oldProp, msg, newProp)
assignPropertiesFromPln(this, pln, warnWhenPropertyChanged)

Assign properties from pln.propSeq to the sequencer

sequence(this, w, stf)
static getSequencerFromPln(pln, warnDefault)

Returns a sequencer instance selected from the given pln struct, falling back to the configured default sequencer if none fits.

static getAvailableSequencers(pln, optionalPaths)
static isAvailable(pln, machine)