VMAT module documentation


The VMAT module consists of the class VMAT, which is capable of loading an EPID DICOM Open field image and MLC field image and analyzing the images according to the Varian RapidArc QA tests and procedures, specifically the Dose-Rate & Gantry-Speed (DRGS) and Dose-Rate & MLC speed (DRMLC) tests.


  • Do both tests - Pylinac can handle either DRGS or DRMLC tests.
  • Adjust for offsets - Older VMAT patterns were off-center. Easily account for the offset by passing it in.
  • Automatic identification using file names - If your file names are clear, the image type and test type don’t even have to be specified; just load and analyze.

Running the Demo

To run the VMAT demo, create a script or start an interpreter session and input:

from pylinac import VMAT
# alternatively, you can run the MLC Speed demo by:

Results will be printed to the console and a figure showing both the Open field and MLC field image will pop up:

Dose Rate & MLC Speed
Test Results (Tol. +/-1.5%): PASS
Max Deviation: 0.437%
Absolute Mean Deviation: 0.382%

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


Image Acquisition

If you want to perform these specific QA tests, you’ll need DICOM plan files that control the linac precisely to deliver the test fields. These can be downloaded from my.varian.com. Once logged in, search for RapidArc and you should see two items called “RapidArc QA Test Procedures and Files for TrueBeam”; there will be a corresponding one for C-Series. Use the RT Plan files and follow the instructions, not including the assessment procedure, which is the point of this module. Save & move the images to a place you can use pylinac.

Naming Convention

For VMAT analysis, pylinac needs to know which image is the DMLC image. You can specify this when loading an image and pass the test type directly. However, if you follow a simple naming convention, you can skip that step.

If the file has ‘open’ or ‘dmlc’ (case-insenitive) in the file name, pylinac will automatically assign the images. Also, if the filenames have ‘drmlc’ or ‘drgs’ in the file names, then the test type is automatically registered as well. The following example shows what this would look like:

# well-named files
img1 = r'C:/path/drmlc_open.dcm'  # note the drmlc, which is the test type and the open which is the delivery
img2 = r'C:/path/drmlc_dmlc.dcm'
# reading these in registers both image type and test type
vmat = VMAT(images=(img1, img2))
vmat.analyze() # no need for test type

If your files don’t follow this convention it’s okay; you just need to specify the image and test types manually. See below and analyze() for more info.

Typical Use

The VMAT QA analysis follows what is specified in the Varian RapidArc QA tests and assumes your tests will run the exact same way. Import the class:

from pylinac import VMAT

The minimum needed to get going is to:

  • Load images – Loading the EPID DICOM images into your VMAT class object can be done by passing the file paths, passing a ZIP archive, or passing a URL. While the image delivery types can be passed, using an easy Naming Convention can simplify the process:

    open_img = "C:/QA Folder/VMAT/open_field.dcm"  # note the 'open'
    dmlc_img = "C:/QA Folder/VMAT/dmlc_field.dcm"  # note the 'dmlc'
    myvmat = VMAT(images=(open_img, dmlc_img))  # the order doesn't matter in this case

    However, if our names weren’t so clearly named, we can just pass the delivery types, which assign the images:

    img1 = "C:/QA/vmat1.dcm"  # the open field
    img2 = "C:/QA/vmat2.dcm"  # the dmlc field
    myvmat = VMAT(images=[img1, img2], delivery_types=['open', 'dmlc'])

    A zip file holding both the images can be used, but must follow the Naming Convention:

    myvmat = VMAT.from_zip(r'C:/path/to/zip.zip')

    A URL can be passed which must point to a ZIP archive hosted on a server:

    myvmat = VMAT.from_url('http://myserver.org/vmat.zip')

    Finally, if you don’t have any images, you can use the demo ones provided:

    drgs_vmat = VMAT.from_demo_images(type='drgs')
    drmlc_vmat = VMAT.from_demo_images(type='drmlc')
  • Analyze the images – This is where pylinac does its work. Once the images are loaded, tell VMAT to analyze the images. See the Algorithm section for details on how this is done. Tolerance can also be passed, but has a default value of 1.5%:

    myvmat.analyze(test='drmlc', tolerance=1.5)


    The test parameter does not need to be specified if the Naming Convention for tests is followed.

  • View the results – The VMAT module can print out the summary of results to the console as well as draw a matplotlib image to show where the segments were placed and their values:

    # print results to the console
    # view analyzed images

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


    The individual plots can also be plotted and saved:

    myvmat.save_analyzed_subimage('myprofile.png', subimage='profile')

    PDF reports can also be generated:


Tips & Tricks

The VMAT test can be customized using the tolerance parameter to whatever tolerance is needed, whether simply using a default (1.5), or a clinical value.

Furthermore, the location of the segments can be adjusted. Older QA tests had the segments slightly offset from center. The new revision of tests is now centered. To account for this, just add an offset to analyze:

myvmat = VMAT.from_demo_images('drgs')

The test results are also not constricted to just printing out. Important results can be accessed directly. Continuing from the example above:

myvmat.max_r_deviation  # regardless of sign


The VMAT analysis algorithm is based on the Varian RapidArc QA Test Procedures for C-Series and Truebeam. Two tests (besides Picket Fence, which has its own module) are specified. Each test takes 10x0.5cm samples, each corresponding to a distinct section of radiation. A corrected reading of each segment is made, defined as: \(M_{corr}(x) = \frac{M_{DRGS}(x)}{M_{open}(x)} * 100\). The reading deviation of each segment is calculated as: \(M_{deviation}(x) = \frac{M_{corr}(x)}{M_{corr}} * 100 - 100\), where \(M_{corr}\) is the average of all segments.

The algorithm works like such:


  • The images can be acquired at any SID.
  • The images can be acquired with any EPID (aS500, aS1000, aS1200).



Analysis can fail or give unreliable results if any Restriction is violated.

  • The tests must be delivered using the DICOM RT plan files provided by Varian which follow the test layout of Ling et al.
  • The images must be acquired with the EPID.


  • Determine image scaling – Segment determination is based on offsets from the center pixel of the image. However, some physicists use 150 cm SID and others use 100 cm, and others can use a clinical setting that may be different than either of those. To account for this, the SID is determined and then scaling factors are determined to be able to perform properly-sized segment analysis.



Calculations tend to be lazy, computed only on demand. This represents a nominal analysis where all calculations are performed.

  • Calculate sample boundaries – Segment positions are always the same and are determined by offsets from the center pixel given by Varian. These values are then scaled with the image scaling factor determined above.
  • Calculate the corrected reading – For each segment, the mean pixel value is determined for both the open and DMLC image. These values are used to determine the corrected reading: \(M_{corr}\).
  • Calculate sample and segment ratios – Once the images are normalized to themselves, the sample values of the DMLC field are divided by their corresponding open field values.
  • Calculate segment deviations – Segment deviation is then calculated once all the corrected readings are determined. The average absolute deviation can also be calculated.


  • Test if segments pass tolerance – Each segment is checked to see if it was within the specified tolerance. If any samples fail, the whole test is considered failing.

API Documentation

class pylinac.vmat.VMAT(images, delivery_types=None)[source]

Bases: object

The VMAT class analyzes two DICOM images acquired via a linac’s EPID and analyzes regions of interest (segments) based on the Varian RapidArc QA specifications, specifically, the Dose Rate & Gantry Speed (DRGS) and Dose Rate & MLC speed (DRMLC) tests.



Run the DRGS demo:
>>> VMAT.run_demo_drgs()
Run the DRMLC demo:
>>> VMAT.run_demo_drmlc()
Load images directly:
>>> VMAT(images=('myvmat1.dcm', 'myvmat2.dcm'), delivery_types=['open', 'dmlc'])
Or load from a ZIP archive:
>>> VMAT.from_zip('myvmat.zip')
Or load from a URL:
>>> VMAT.from_url('http://myserver.com/vmat.zip')
A typical use case:
>>> open_img = "C:/QA Folder/VMAT/open_field.dcm"
>>> dmlc_img = "C:/QA Folder/VMAT/dmlc_field.dcm"
>>> myvmat = VMAT(images=(open_img, dmlc_img))
>>> myvmat.analyze(test='drmlc', tolerance=1.5)
>>> print(myvmat.results())
>>> myvmat.plot_analyzed_image()
  • images (iterable (list, tuple, etc)) – A sequence of paths to the image files.
  • delivery_types (iterable, None) –

    If None (default), the image paths names must follow the Naming Convention. If the image paths do not follow the naming convention, a 2-element string sequence for delivery_types must be passed in. E.g. ['open', 'dmlc'].

classmethod from_demo_images(type='drgs')[source]

Construct a VMAT instance using the demo images.

Parameters:type ({'drgs', 'drmlc'}) – Test type of images to load.
classmethod from_zip(path)[source]

Load VMAT images from a ZIP file that contains both images. Must follow the naming convention.

Parameters:path (str) – Path to the ZIP archive which holds the VMAT image files.
classmethod from_url(url)[source]

Load a ZIP archive from a URL. Must follow the naming convention.

Parameters:url (str) – Must point to a valid URL that is a ZIP archive of two VMAT images.
static run_demo_drgs(tolerance=1.5)[source]

Run the VMAT demo for the Dose Rate & Gantry Speed test.

static run_demo_drmlc(tolerance=1.5)[source]

Run the VMAT demo for the MLC leaf speed test.

analyze(test=None, tolerance=1.5, x_offset=0)[source]

Analyze the open and DMLC field VMAT images, according to 1 of 2 possible tests.

  • test ({'drgs', 'mlcs', None}) –

    The test to perform, either Dose Rate Gantry Speed (‘drgs’) or MLC Speed (‘mlcs’). If None (default), the images passed in must have followed the clear Naming Convention. If the images did not follow the naming convention then a string specifying the test type must be passed in.

  • tolerance (float, int, optional) – The tolerance of the sample deviations in percent. Default is 1.5. Must be between 0 and 8.
  • x_offset (int) –

    New in version 0.8.

    If the VMAT segments aren’t aligned to the CAX (older VMAT images), the segments need a shift. Positive moves the segments right, negative to the left.


Return the average of the absolute R_deviation values.


Return the average of the R_deviation values, including the sign.


Return the value of the maximum R_deviation segment.


Returns whether all the segment ratios passed the given tolerance.


Plot the analyzed images. Shows the open and dmlc images with the segments drawn; also plots the median profiles of the two images for visual comparison.

Parameters:show (bool) – Whether to actually show the image.
save_analyzed_image(filename, **kwargs)[source]

Save the analyzed images as a png file.

  • filename (str, file-object) – Where to save the file to.
  • kwargs – Passed to matplotlib.
plot_analyzed_subimage(subimage='dmlc', show=True, ax=None)[source]

Plot an individual piece of the VMAT analysis.

  • subimage (str) – Specifies which image to plot.
  • show (bool) – Whether to actually plot the image.
  • ax (matplotlib Axes, None) – If None (default), creates a new figure to plot to, otherwise plots to the given axes.
save_analyzed_subimage(filename, subimage='dmlc', **kwargs)[source]

Save a subplot to file.

  • filename (str, file-object) – Where to save the file to.
  • subimage (str) – Which subplot to save.
  • kwargs – Passed to matplotlib.

Return two median profiles from the open and dmlc image. For visual comparison.


A string of the summary of the analysis results.

Returns:The results string showing the overall result and deviation statistics by segment.
Return type:str
publish_pdf(filename, author=None, unit=None, notes=None, open_file=False)[source]

Publish (print) a PDF containing the analysis and quantitative results.

Parameters:filename ((str, file-like object}) – The file to write the results to.
class pylinac.vmat.Settings(test_type, tolerance)[source]

Bases: object

A helper class to hold analysis settings.


The test type being done; either drgs or mlcs


The tolerance value in percentage; e.g. 0.03 == 3%


Offset in pixels to apply to all segments.


Offset in pixels to apply to all segments.

class pylinac.vmat.SegmentManager(open_img, dmlc_img, settings)[source]

Bases: object

A class to handle the VMAT segments and perform actions across all segments.


Draw the segments onto a plot.

Parameters:plot (matplotlib.axes.Axes) – The plot to draw the objects on.

Return the deviations of all segments as an array.


Return the average of the absolute R_deviation values.


Return the average of the R_deviation values, including the sign.


Return the value of the maximum R_deviation segment.


Return whether all the images passed.

class pylinac.vmat.Segment(center_point, open_image, dmlc_image, tolerance)[source]

Bases: pylinac.core.geometry.Rectangle

A class for holding and analyzing segment data of VMAT tests.

For VMAT tests, there are either 4 or 7 ‘segments’, which represents a section of the image that received radiation under the same conditions.


The reading deviation (R_dev) from the average readings of all the segments. See RTD for equation info.


The corrected reading (R_corr) of the pixel values. See RTD for explanation and equation info.


Specifies where the segment reading deviation was under tolerance.


Return the ratio of the mean pixel values of DMLC/OPEN images.


Return whether the segment passed or failed.


Get the background color of the segment when plotted, based on the pass/fail status.