This page was generated from docs/user/examples/gamma_from_dicom.ipynb. Interactive online version: Binder badge

Gamma from DICOM

PyMedPhys has multiple ways to calculate Gamma. There are also a range of interfaces that can be used. Presented here is a simplified interface which receives as its input two DICOM file paths for the purpose of directly calculating Gamma from a pair of RT DICOM dose files.

[1]:
import os
import warnings
import urllib.request

import numpy as np
import matplotlib.pyplot as plt

from pymedphys.gamma import gamma_dicom

Downloading the DICOM files

For the purpose of this example we will be downloading two DICOM files. This code below achieves this download. It would not be required if you already have a pair of DICOM files on your computer.

[2]:
def download_and_save_zenodo_file(url):
    file_name = url.split('/')[-1]

    if not os.path.exists(file_name):
        request = urllib.request.urlopen(url)
        file_object = request.read()

        with open(file_name, 'wb') as a_file:
            a_file.write(file_object)

A range of files for PyMedPhys are stored at Zenodo, here are two DICOM files that are used for Gamma comparison.

[3]:
evaluation_url = 'https://zenodo.org/record/2614021/files/data_evaluation.dcm'
reference_url = 'https://zenodo.org/record/2614021/files/data_reference.dcm'

for url in [evaluation_url, reference_url]:
    download_and_save_zenodo_file(url)

Calculate and display Gamma

Due to the time it takes to run a full Gamma calculation we have chosen here to pass the parameter random_subset. This drastically speeds up the calculation at the cost of introducing uncertainty into reported pass rates. Each time these docs are built online the code is run, we don’t want to bog the documentation building down in a Gamma calc, so we apply this parameter here.

A second optional parameter is also passed, max_gamma. This informs the Gamma calculation to not search for Gamma values greater than 1.1, this also speeds up the calculation at the expense of losing some information.

The required parameters to gamma_dicom are dicom_ref_filepath, dicom_eval_filepath, dose_percent_threshold, and distance_mm_threshold.

These commands below have been wrapped up in a function simply so that they can be easily run three times to demonstrate the uncertainty introduced by using the random_subset parameter. Although it will certainly depend on the DICOM datasets being compared, we have found that a random_subset of 50 000 tends to converge on a consistent pass rate.

[4]:
def calculate_gamma_and_display():
    max_gamma = 1.1

    gamma = gamma_dicom(
        "data_reference.dcm", "data_evaluation.dcm", 3, 3,
        random_subset=1000, max_gamma=max_gamma)

    valid_gamma = gamma[~np.isnan(gamma)]
    plt.hist(valid_gamma, 30)
    plt.xlim([0, max_gamma])

    pass_ratio = np.sum(valid_gamma <= 1) / len(valid_gamma)

    plt.title("Gamma Percent Pass: {0:.2f} %".format(pass_ratio*100))
[ ]:

You’ll notice a warning about dose_from_dataset() in this first calculation. This function is currently used internally by gamma_dicom(), but it will have its API changed in a future version.

[5]:
calculate_gamma_and_display()
/opt/buildhome/python3.7/lib/python3.7/site-packages/pymedphys_dicom/dicom/dose.py:61: UserWarning: `dose_from_dataset` currently reshapes the dose grid. In a future version this will no longer occur. To begin using this function without the reshape pass the parameter `reshape=False` when calling `dose_from_dataset`.
  'when calling `dose_from_dataset`.'), UserWarning)
Calcing using global normalisation point for gamma
Global normalisation set to 5.9766182147356 Gy
Global dose threshold set to [0.17929855] Gy ([3]%)
Distance threshold set to [3] mm
Lower dose cutoff set to 1.1953236429471201 Gy (20%)

Current distance: 3.30 mm | Number of reference points remaining: 56 | Points tested per reference point: 1593 | RAM split count: 1
Complete!
../../_images/user_examples_gamma_from_dicom_10_2.png

The following plots are simply repeats of the above calculation with the previously seen warning supressed. Depending on randomness you’ll possibly see deviations on the order of ~4% for this dataset with a random_subset set to 1 000.

Try clicking the “launch binder” link at the top of this page to run this notebook live online and change the random_subset to something more like 50 000 to see the impact.

[6]:
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    calculate_gamma_and_display()
Calcing using global normalisation point for gamma
Global normalisation set to 5.9766182147356 Gy
Global dose threshold set to [0.17929855] Gy ([3]%)
Distance threshold set to [3] mm
Lower dose cutoff set to 1.1953236429471201 Gy (20%)

Current distance: 3.30 mm | Number of reference points remaining: 58 | Points tested per reference point: 1593 | RAM split count: 1
Complete!
../../_images/user_examples_gamma_from_dicom_12_1.png
[7]:
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    calculate_gamma_and_display()
Calcing using global normalisation point for gamma
Global normalisation set to 5.9766182147356 Gy
Global dose threshold set to [0.17929855] Gy ([3]%)
Distance threshold set to [3] mm
Lower dose cutoff set to 1.1953236429471201 Gy (20%)

Current distance: 3.30 mm | Number of reference points remaining: 46 | Points tested per reference point: 1593 | RAM split count: 1
Complete!
../../_images/user_examples_gamma_from_dicom_13_1.png