Collimator Toolbox

Various helper functions for mlcs and jaws.

Available Functions

>>> from pymedphys.coll import (
...    calc_mu_density, mlc_equivalent_square_fs)

MU Density

Calculate the MU Density given mu, mlc, and jaw control points.

Warning

Although this is a useful tool in the toolbox for patient specific IMRT QA, in and of itself it is not a sufficient stand in replacement. This tool does not verify that the reported dose within the treatment planning system is delivered by the Linac.

Deficiencies or limitations in the agreement between the treatment planning system’s beam model and the Linac delivery will not be able to be highlighted by this tool. An example might be an overly modulated beam with many thin sweeping strips, the Linac may deliver those control points with positional accuracy but if the beam model in the TPS cannot sufficiently accurately model the dose effects of those MLC control points the dose delivery will not sufficiently agree with the treatment plan. In this case however, this tool will say everything is in agreement.

It also may be the case that due to a hardware or calibration fault the Linac itself may be incorrectly reporting its MLC and/or Jaw postions. In this case the logfile record can agree exactly with the planned positions while the true real world positions be in significant deviation.

The impact of these issues may be able to be limited by including with this tool an automated independent IMRT 3-D dose calculation tool as well as a daily automated MLC/jaw logfile to EPI to baseline agreement test that moves the EPI so as to measure the full set of leaf pairs and the full range of MLC and Jaw travel.

from pymedphys.coll import calc_mu_density, get_grid, display_mu_density

leaf_pair_widths = (5, 5, 5)
max_leaf_gap = 10

mu = [0, 2, 5, 10]
mlc = [
    [
        [1, 1],
        [2, 2],
        [3, 3]],
    [
        [2, 2],
        [3, 3],
        [4, 4]],
    [
        [-2, 3],
        [-2, 4],
        [-2, 5]],
    [
        [0, 0],
        [0, 0],
        [0, 0]]]

jaw = [
    [7.5, 7.5],
    [7.5, 7.5],
    [-2, 7.5],
    [0, 0]
]

grid = get_grid(max_leaf_gap=max_leaf_gap, leaf_pair_widths=leaf_pair_widths)

mu_density = calc_mu_density(
    mu, mlc, jaw, max_leaf_gap=max_leaf_gap, leaf_pair_widths=leaf_pair_widths)

display_mu_density(grid, mu_density)

(Source code, png, hires.png, pdf)

../_images/mudensity.png
import numpy as np
import matplotlib.pyplot as plt

from pymedphys.coll import single_mlc_pair

mlc_left = (-2.3, 3.1)  # (start position, end position)
mlc_right = (0, 7.7)

x, mu_density = single_mlc_pair(mlc_left, mlc_right)
plt.plot(x, mu_density, '-o')
plt.title('A single MLC')
plt.xlabel('MLC direction (mm)')
plt.ylabel('Open fraction')

(Source code, png, hires.png, pdf)

../_images/single_leaf.png

API

pymedphys.coll.calc_mu_density(mu, mlc, jaw, grid_resolution=1, max_leaf_gap=400, leaf_pair_widths=(5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5), min_step_per_pixel=10)[source]

Determine the MU Density.

Both jaw and mlc positions are defined in bipolar format for each control point. A negative value indicates travel over the isocentre. All positional arguments are defined at the isocentre projection with the units of mm.

Parameters:
mu : numpy.ndarray

1-D array containing an MU value for each control point.

mlc : numpy.ndarray

3-D array containing the MLC positions

axis 0: control point
axis 1: mlc pair
axis 2: leaf bank
jaw : numpy.ndarray

2-D array containing the jaw positions.

axis 0: control point
axis 1: diaphragm
grid_resolution : float, optional

The calc grid resolution. Defaults to 1 mm.

max_leaf_gap : float, optional

The maximum possible distance between opposing leaves. Defaults to 400 mm.

leaf_pair_widths : tuple, optional

The widths of each leaf pair in the MLC limiting device. The number of entries in the tuples defines the number of leaf pairs. Each entry itself defines that particular leaf pair width. Defaults to 80 leaf pairs each 5 mm wide.

min_step_per_pixel : int, optional

The minimum number of time steps used per pixel for each control point. Defaults to 10.

Returns:
mu_density : numpy.ndarray

2-D array containing the calculated mu density.

axis 0: jaw direction
axis 1: mlc direction

Examples

>>> import numpy as np
>>>
>>> from pymedphys.coll import (
...     calc_mu_density, get_grid, display_mu_density)
>>>
>>> leaf_pair_widths = (5, 5, 5)
>>> max_leaf_gap = 10
>>> mu = np.array([0, 2, 5, 10])
>>> mlc = np.array([
...     [
...         [1, 1],
...         [2, 2],
...         [3, 3]
...     ],
...     [
...         [2, 2],
...         [3, 3],
...         [4, 4]
...     ],
...     [
...         [-2, 3],
...         [-2, 4],
...         [-2, 5]
...     ],
...     [
...         [0, 0],
...         [0, 0],
...         [0, 0]
...     ]
... ])
>>> jaw = np.array([
...     [7.5, 7.5],
...     [7.5, 7.5],
...     [-2, 7.5],
...     [0, 0]
... ])
>>>
>>> grid = get_grid(
...    max_leaf_gap=max_leaf_gap, leaf_pair_widths=leaf_pair_widths)
>>> grid['mlc']
array([-5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.,  5.])
>>>
>>> grid['jaw']
array([-8., -7., -6., -5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.,
        5.,  6.,  7.,  8.])
>>>
>>> mu_density = calc_mu_density(
...    mu, mlc, jaw, max_leaf_gap=max_leaf_gap,
...    leaf_pair_widths=leaf_pair_widths)
>>> display_mu_density(grid, mu_density)
>>>
>>> np.round(mu_density, 1)
array([[0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
       [0. , 0. , 0. , 0.3, 1.9, 2.2, 1.9, 0.4, 0. , 0. , 0. ],
       [0. , 0. , 0. , 0.4, 2.2, 2.5, 2.2, 0.6, 0. , 0. , 0. ],
       [0. , 0. , 0. , 0.4, 2.4, 2.8, 2.5, 0.8, 0. , 0. , 0. ],
       [0. , 0. , 0. , 0.4, 2.5, 3.1, 2.8, 1. , 0. , 0. , 0. ],
       [0. , 0. , 0. , 0.4, 2.5, 3.4, 3.1, 1.3, 0. , 0. , 0. ],
       [0. , 0. , 0.4, 2.3, 3.2, 3.7, 3.7, 3.5, 1.6, 0. , 0. ],
       [0. , 0. , 0.4, 2.3, 3.2, 3.8, 4. , 3.8, 1.9, 0.1, 0. ],
       [0. , 0. , 0.4, 2.3, 3.2, 3.8, 4.3, 4.1, 2.3, 0.1, 0. ],
       [0. , 0. , 0.4, 2.3, 3.2, 3.9, 5.2, 4.7, 2.6, 0.2, 0. ],
       [0. , 0. , 0.4, 2.3, 3.2, 3.8, 5.4, 6.6, 3.8, 0.5, 0. ],
       [0. , 0.3, 2.2, 3. , 3.5, 4. , 5.1, 7.5, 6.7, 3.9, 0.5],
       [0. , 0.3, 2.2, 3. , 3.5, 4. , 4.7, 6.9, 6.7, 3.9, 0.5],
       [0. , 0.3, 2.2, 3. , 3.5, 4. , 4.5, 6.3, 6.4, 3.9, 0.5],
       [0. , 0.3, 2.2, 3. , 3.5, 4. , 4.5, 5.6, 5.7, 3.8, 0.5],
       [0. , 0.3, 2.2, 3. , 3.5, 4. , 4.5, 5.1, 5.1, 3.3, 0.5],
       [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]])

MU Density from a Mosaiq record

>>> from pymedphys.coll import (
...     calc_mu_density, get_grid, display_mu_density)
>>>
>>> from pymedphys.msq import (
...     mosaiq_connect, multi_fetch_and_verify_mosaiq)
>>>
>>> def mu_density_from_mosaiq(msq_server_name, field_id):
...     with mosaiq_connect(msq_server_name) as cursor:
...         delivery_data = multi_fetch_and_verify_mosaiq(
...             cursor, field_id)
...
...
...     mu = delivery_data.monitor_units
...     mlc = delivery_data.mlc
...     jaw = delivery_data.jaw
...
...     grid = get_grid()
...     mu_density = calc_mu_density(mu, mlc, jaw)
...     display_mu_density(grid, mu_density)
>>>
>>> mu_density_from_mosaiq('a_server_name', 11111) 

MU Density from a logfile at a given filepath

>>> from pymedphys.coll import (
...     calc_mu_density, get_grid, display_mu_density)
>>>
>>> from pymedphys.trf import delivery_data_from_logfile
>>>
>>> def mu_density_from_logfile(filepath):
...     delivery_data = delivery_data_from_logfile(filepath)
...
...     mu = delivery_data.monitor_units
...     mlc = delivery_data.mlc
...     jaw = delivery_data.jaw
...
...     grid = get_grid()
...     mu_density = calc_mu_density(mu, mlc, jaw)
...     display_mu_density(grid, mu_density)
>>>
>>> mu_density_from_logfile(r"a/path/goes/here") 
pymedphys.coll.calc_single_control_point(mlc, jaw, delivered_mu=1, leaf_pair_widths=(5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5), grid_resolution=1, min_step_per_pixel=10)[source]

Calculate the MU Density for a single control point.

Examples

>>> import numpy as np
>>> from pymedphys.coll import (
...     calc_single_control_point, display_mu_density)
>>>
>>> leaf_pair_widths = (2, 2)
>>> mlc = np.array([
...     [
...         [1, 1],
...         [2, 2],
...     ],
...     [
...         [2, 2],
...         [3, 3],
...     ]
... ])
>>> jaw = np.array([
...     [1.5, 1.2],
...     [1.5, 1.2]
... ])
>>> grid, mu_density = calc_single_control_point(
...     mlc, jaw, leaf_pair_widths=leaf_pair_widths)
>>> display_mu_density(grid, mu_density)
>>>
>>> grid['mlc']
array([-3., -2., -1.,  0.,  1.,  2.,  3.])
>>>
>>> grid['jaw']
array([-1.5, -0.5,  0.5,  1.5])
>>>
>>> np.round(mu_density, 2)
array([[0.  , 0.07, 0.43, 0.5 , 0.43, 0.07, 0.  ],
       [0.  , 0.14, 0.86, 1.  , 0.86, 0.14, 0.  ],
       [0.14, 0.86, 1.  , 1.  , 1.  , 0.86, 0.14],
       [0.03, 0.17, 0.2 , 0.2 , 0.2 , 0.17, 0.03]])
pymedphys.coll.single_mlc_pair(left_mlc, right_mlc, grid_resolution=1, min_step_per_pixel=10)[source]

Calculate the MU Density of a single leaf pair.

Examples

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>>
>>> from pymedphys.coll import single_mlc_pair
>>>
>>> mlc_left = (-2.3, 3.1)  # (start position, end position)
>>> mlc_right = (0, 7.7)
>>>
>>> x, mu_density = single_mlc_pair(mlc_left, mlc_right)
>>> fig = plt.plot(x, mu_density, '-o')
>>>
>>> x
array([-2., -1.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.])
>>>
>>> np.round(mu_density, 3)
array([0.064, 0.244, 0.408, 0.475, 0.53 , 0.572, 0.481, 0.352, 0.224,
       0.096, 0.004])
pymedphys.coll.get_grid(max_leaf_gap=400, grid_resolution=1, leaf_pair_widths=(5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5))[source]

Get the MU Density grid for plotting purposes.

Examples

See pymedphys.coll.calc_mu_density.

pymedphys.coll.find_relevant_control_points(mu)[source]

Removes control points that will not contribute to the MU Density.

pymedphys.coll.display_mu_density(grid, mu_density, grid_resolution=None)[source]

Prints a colour plot of the MU Density.

Examples

See pymedphys.coll.calc_mu_density.