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.
  • Automatic offset correction - Older VMAT tests had the ROIs offset, newer ones are centered. No worries, pylinac finds the ROIs automatically.
  • Automatic open/DMLC identification - Pass in both images–don’t worry about naming. Pylinac will automatically identify the right images.


There are two classes in the VMAT module: DRGS and DRMLC. Each have the exact same methods. Anytime one class is used here as an example, the other class can be used the same way.

Running the Demos

For this example we will use the DRGS class:

from pylinac import DRGS

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


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

Dose Rate & Gantry Speed
Test Results (Tol. +/-1.5%): PASS
Max Deviation: 1.01%
Absolute Mean Deviation: 0.459%

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 VMAT images to a place you can use pylinac.

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 appropriate class:

from pylinac import DRGS, DRMLC

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:

    open_img = "C:/QA Folder/VMAT/open_field.dcm"
    dmlc_img = "C:/QA Folder/VMAT/dmlc_field.dcm"
    mydrgs = DRGS(image_paths=(open_img, dmlc_img))  # use the DRMLC class the exact same way
    # from zip
    mydrmlc = DRMLC.from_zip(r'C:/path/to/zip.zip')
    # from a URL
    mydrgs = DRGS.from_url('http://myserver.org/vmat.zip')

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

    mydrgs = DRGS.from_demo_images()
    mydrmlc = DRMLC.from_demo_images()
  • Analyze the images – Once the images are loaded, tell the class to analyze the images. See the Algorithm section for details on how this is done. Tolerance can also be passed and has a default value of 1.5%:

  • View/Save 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)


    PDF reports can also be generated:


Customizing the analysis

You can alter both the segment size and segment positions as desired.

To change the segment size:

drgs = DRGS.from_demo_image()
drgs.analyze(..., segment_size_mm=(10, 150))  # ROI segments will now be 10mm wide by 150mm tall
# same story for DRMLC

To change the x-positions of the ROI segments, the class property must be changed. This is different behavior because by default the x-positions are different for the DRGS and DRMLC test:

from pylinac import DRGS, DRMLC

DRGS.SEGMENT_X_POSITIONS_MM = (-100, -80, ...)
# proceed as normal
my_drgs = DRGS(...)

# DRMLC must be addressed separately
DRMLC.SEGMENT_X_POSITIONS_MM = (-40, -10, 10, 40)
my_drmlc = DRMLC(...)

Accessing Data

As with most other modules, the raw data can be examined and use as part of a larger project, e.g. QATrack+. Perusing the documentation will show what is available, but a quick list is shown here by example:

mydrgs.avg_abs_r_deviation  # float
mydrgs.avg_r_deviation  # float; usually artificially low due to positive and negative R values
mydrgs.max_r_deviation  # float; regardless of sign
mydrgs.dmlc_image  # DicomImage instance
mydrgs.open_image  # DicomImage instance
mydrgs.passed  # bool
mydrgs.r_devs  # numpy array of all R_deviation values
mydrgs.segments[1].r_corr  # the 1st segment's R ratio
mydrgs.segments[0].passed  # whether the 0th segment passed based on the tolerance of ``analyze()``


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 within the image. The x-positions are based on the FWHM of the detected field. This allows for old and new style tests that have an x-offset from each other. 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 – 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 is also 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.DRGS(image_paths: Sequence[str])[source]

Bases: pylinac.vmat.VMATBase

Class representing a Dose-Rate, Gantry-speed VMAT test. Will accept, analyze, and return the results.

Parameters:image_paths (iterable (list, tuple, etc)) – A sequence of paths to the image files.
static run_demo()[source]

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

class pylinac.vmat.DRMLC(image_paths: Sequence[str])[source]

Bases: pylinac.vmat.VMATBase

Class representing a Dose-Rate, MLC speed VMAT test. Will accept, analyze, and return the results.

Parameters:image_paths (iterable (list, tuple, etc)) – A sequence of paths to the image files.
static run_demo()[source]

Run the demo for the MLC leaf speed test.

class pylinac.vmat.VMATBase(image_paths: Sequence[str])[source]

Bases: object

Parameters:image_paths (iterable (list, tuple, etc)) – A sequence of paths to the image files.
classmethod from_url(url: str)[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.
classmethod from_zip(path: str)[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_demo_images()[source]

Construct a VMAT instance using the demo images.


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

  • tolerance (float, int, optional) – The tolerance of the sample deviations in percent. Default is 1.5. Must be between 0 and 8.
  • segment_size_mm (tuple(int, int)) – The (width, height) of the ROI segments in mm.
results() → str[source]

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

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.

plot_analyzed_image(show: bool = True)[source]

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.
publish_pdf(filename: str, notes: str = None, open_file: bool = False, metadata: Optional[dict] = None)[source]

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

  • filename ((str, file-like object}) – The file to write the results to.
  • notes (str, list of strings) – Text; if str, prints single line. If list of strings, each list item is printed on its own line.
  • open_file (bool) – Whether to open the file using the default program after creation.
  • metadata (dict) – Extra data to be passed and shown in the PDF. The key and value will be shown with a colon. E.g. passing {‘Author’: ‘James’, ‘Unit’: ‘TrueBeam’} would result in text in the PDF like: ————– Author: James Unit: TrueBeam ————–
class pylinac.vmat.Segment(center_point: pylinac.core.geometry.Point, open_image: pylinac.core.image.DicomImage, dmlc_image: pylinac.core.image.DicomImage, tolerance: Union[float, int])[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_bg_color() → str[source]

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