cutright / DVH-Analytics

A DICOM Database Application for Radiation Oncology
Other
82 stars 30 forks source link

New DTH calculation in v0.8.9 #111

Closed cutright closed 3 years ago

cutright commented 3 years ago

Although not accessible in the GUI, DVHA calculates a surface-based DTH which is stored in the DVHs table, under the dth_string column. Starting in v0.8.9, the DTH calculation will assign negative values to ROI points within the PTV. If you use this DTH or dist_to_ptv_?, you'll need to reimport your DICOM data (or at least recalculate the DTHs). I'll add a method to update these values for previously imported plans via the GUI before v0.8.9 is officially released.

Here is an example of how I access the information:

from dvha.db.sql_connector import DVH_SQL
import matplotlib.pyplot as plt
from dvha.tools.roi_geometry import process_dth_string
with DVH_SQL() as cnx:
    gtv = cnx.query('DVHs', 'dth_string', "mrn = 'ANON11264' and physician_roi = 'gtv'")[0][0]
bins, counts = process_dth_string(gtv)

figure, axes = plt.subplots()
axes.bar(bins, counts)
axes.set_title('DTH of GTV')
axes.set_xlabel('Distance from PTV Surface (mm)')
axes.set_ylabel('Fraction of GTV Surface')

Some example DTHs: gtv_dth mandible

cutright commented 3 years ago

Working on an OVH calculation, where the OAR is voxelized rather than using OAR surface points. Overall, looks very similar, but this method has a uniform distribution of OAR points, where as the previous "DTH" method was biased based on however many points were used for each OAR contour.

image

And here is a cumulative OVH:

image
cutright commented 3 years ago
image
cutright commented 3 years ago

If you get the latest DVHA code from the v0.9.4 branch, you can access an ovh_string just like dth_string above. However, this only applies to plans that have been imported with this new code. Additionally, if you're using SQLite, you'll have to import into a new database to make sure you have an 'ovh_string' column. PostgresSQL users will automatically get the new column on app launch.

cutright commented 3 years ago

I've also added 25th and 75th percentile values of DTH and OVH as chartable variables in the GUI.

Here is some quick code to plot OVH vs DTH. These OVH was calculated using a 3mm axial grid per ROI slice.

This requires v0.9.4 (currently in its own branch of the same name).

from dvha.db.sql_connector import DVH_SQL
import matplotlib.pyplot as plt
from dvha.tools.roi_geometry import process_dth_string
import numpy as np

with DVH_SQL() as cnx:
    condition = "mrn = 'ANON47250' and physician_roi = 'esophagus'"
    dth_string = cnx.query('DVHs', 'dth_string', condition)[0][0]
    ovh_string = cnx.query('DVHs', 'ovh_string', condition)[0][0]

bins1, counts1 = process_dth_string(dth_string)
bins2, counts2 = process_dth_string(ovh_string)

figure, axes = plt.subplots()

line1 = axes.plot(bins1, np.cumsum(counts1), label="DTH")
line2 = axes.plot(bins2, np.cumsum(counts2), label="OVH")

axes.set_title('Cumulative DTH/OVH of Esophagus')
axes.set_xlabel('Distance from PTV Surface (mm)')
axes.set_ylabel('Fraction of Esophagus')
plt.legend(handles=[line1[0], line2[0]])
image
cutright commented 3 years ago
image

The current DTH appears to have some issues. The above image was created by using Shapely's simplify method with a 0.5mm tolerance.