Skip to content
This repository has been archived by the owner on Feb 2, 2022. It is now read-only.

Fix dicompyler on ubuntu #94

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
7 changes: 5 additions & 2 deletions dicompyler/baseplugins/2dview.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ def GetDoseGridPixelData(self, pixlut, doselut):
spacing = imdata['pixelspacing']

# Transpose the dose grid LUT onto the image grid LUT
spacing = [float(x) for x in spacing]
x = (np.array(doselut[0]) - pixlut[0][0]) * prone * feetfirst / spacing[0]
y = (np.array(doselut[1]) - pixlut[1][0]) * prone / spacing[1]
return (x, y)
Expand Down Expand Up @@ -548,8 +549,10 @@ def OnUpdatePositionValues(self, evt=None):
# Rescale the slope and intercept of the image if present
if (image.ds.has_key('RescaleIntercept') and
image.ds.has_key('RescaleSlope')):
pixel_array = image.ds.pixel_array*image.ds.RescaleSlope + \
image.ds.RescaleIntercept
rescale_slope = int(image.ds.RescaleSlope)
rescale_intercept = int(image.ds.RescaleIntercept)
pixel_array = image.ds.pixel_array*rescale_slope + \
rescale_intercept
else:
pixel_array = image.ds.pixel_array
value = "Value: " + unicode(pixel_array[ypos, xpos])
Expand Down
9 changes: 8 additions & 1 deletion dicompyler/baseplugins/dvh.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def OnToggleConstraints(self, evt):
self.lblConstraintTypeUnits.SetLabel('% ')
self.lblResultType.SetLabel('Volume:')
rxDose = float(self.plan['rxdose'])
dvhdata = (len(dvh['data'])-1)*dvh['scaling']
dvhdata = float((len(dvh['data'])-1)*dvh['scaling'])
constraintrange = int(dvhdata*100/rxDose)
# never go over the max dose as data does not exist
if (constraintrange > int(dvh['max'])):
Expand All @@ -234,6 +234,13 @@ def OnToggleConstraints(self, evt):
# never go over the max dose as data does not exist
if (constraintrange*100 > maxdose):
constraintrange = maxdose
dvhdata = float((len(dvh['data'])-1)*dvh['scaling'])

if (constraintrange*100 > dvhdata):
print "Scaling could have been set improperly. Possible mistake in DICOM file."
new_scaling = constraintrange*100/dvhdat
self.dvhdata[self.structureid].scaling = new_scaling

# Dose constraint
elif (constrainttype == 2):
self.lblConstraintType.SetLabel('Volume:')
Expand Down
6 changes: 3 additions & 3 deletions dicompyler/dicomgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ def DirectorySearchThread(self, parent, path, subfolders, terminate,
image['series'] = seinfo['id']
image['referenceframe'] = dp.GetFrameofReferenceUID()
patients[h]['series'][seinfo['id']]['numimages'] = \
patients[h]['series'][seinfo['id']]['numimages'] + 1
patients[h]['series'][seinfo['id']]['numimages'] + 1
patients[h]['images'][image['id']] = image
# Create each RT Structure Set
elif dp.ds.Modality in ['RTSTRUCT']:
Expand Down Expand Up @@ -732,15 +732,15 @@ def GetPatientData(self, path, filearray, RxDose, terminate, progressFunc):
if (i > 0):
iop0 = np.array(item.ImageOrientationPatient)
iop1 = np.array(images[i-1].ImageOrientationPatient)
if (np.any(np.array(np.round(iop0 - iop1),
if (np.any(np.array(np.round((iop0 - iop1).astype(np.int32)),
dtype=np.int32))):
parallel = False
break
# Also test ImagePositionPatient, as some series
# use the same patient position for every slice
ipp0 = np.array(item.ImagePositionPatient)
ipp1 = np.array(images[i-1].ImagePositionPatient)
if not (np.any(np.array(np.round(ipp0 - ipp1),
if not (np.any(np.array(np.round((ipp0 - ipp1).astype(np.int32)),
dtype=np.int32))):
parallel = False
break
Expand Down
29 changes: 19 additions & 10 deletions dicompyler/dicomparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,10 @@ def GetImage(self, window = 0, level = 0):
# Rescale the slope and intercept of the image if present
if (self.ds.has_key('RescaleIntercept') and
self.ds.has_key('RescaleSlope')):
rescaled_image = self.ds.pixel_array*self.ds.RescaleSlope + \
self.ds.RescaleIntercept
rescale_slope = int(self.ds.RescaleSlope)
rescale_intercept = int(self.ds.RescaleIntercept)
rescaled_image = self.ds.pixel_array*rescale_slope + \
rescale_intercept
else:
rescaled_image = self.ds.pixel_array
image = self.GetLUTValue(rescaled_image, window, level)
Expand Down Expand Up @@ -230,8 +232,10 @@ def GetDefaultImageWindowLevel(self):
# Rescale the slope and intercept of the image if present
if (self.ds.has_key('RescaleIntercept') and
self.ds.has_key('RescaleSlope')):
pixel_array = self.ds.pixel_array*self.ds.RescaleSlope + \
self.ds.RescaleIntercept
rescale_slope = int(self.ds.RescaleSlope)
rescale_intercept = int(self.ds.RescaleIntercept)
pixel_array = self.ds.pixel_array*rescale_slope + \
rescale_intercept
else:
pixel_array = self.ds.pixel_array
if (pixel_array.max() > wmax):
Expand Down Expand Up @@ -264,6 +268,11 @@ def GetPatientToPixelLUT(self):
orientation = self.ds.ImageOrientationPatient
position = self.ds.ImagePositionPatient

di = float(di)
dj = float(dj)
orientation = [float(x) for x in orientation]
position = [float(x) for x in position]

m = np.matrix(
[[orientation[0]*di, orientation[3]*dj, 0, position[0]],
[orientation[1]*di, orientation[4]*dj, 0, position[1]],
Expand Down Expand Up @@ -467,7 +476,7 @@ def GenerateCDVH(self, data):
"""Generate a cumulative DVH (cDVH) from a differential DVH (dDVH)"""

dDVH = np.array(data)
# Separate the dose and volume values into distinct arrays
# Separate the dose and volume values into distinct arrays
dose = data[0::2]
volume = data[1::2]

Expand Down Expand Up @@ -513,12 +522,12 @@ def GetDoseGrid(self, z = 0, threshold = 0.5):
if 'GridFrameOffsetVector' in self.ds:
z = float(z)
# Get the initial dose grid position (z) in patient coordinates
imagepatpos = self.ds.ImagePositionPatient[2]
orientation = self.ds.ImageOrientationPatient[0]
imagepatpos = float(self.ds.ImagePositionPatient[2])
orientation = float(self.ds.ImageOrientationPatient[0])
# Add the position to the offset vector to determine the
# z coordinate of each dose plane
planes = orientation * np.array(self.ds.GridFrameOffsetVector) + \
imagepatpos
planes = (orientation * np.array(self.ds.GridFrameOffsetVector, dtype=float) + \
imagepatpos)
frame = -1
# Check to see if the requested plane exists in the array
if (np.amin(np.fabs(planes - z)) < threshold):
Expand Down Expand Up @@ -606,7 +615,7 @@ def GetDoseData(self):
data['doseunits'] = self.ds.DoseUnits
data['dosetype'] = self.ds.DoseType
data['dosesummationtype'] = self.ds.DoseSummationType
data['dosegridscaling'] = self.ds.DoseGridScaling
data['dosegridscaling'] = float(self.ds.DoseGridScaling)
data['dosemax'] = float(self.ds.pixel_array.max())

return data
Expand Down
15 changes: 9 additions & 6 deletions dicompyler/dvhcalc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
logger = logging.getLogger('dicompyler.dvhcalc')
import numpy as np
import numpy.ma as ma
import matplotlib.nxutils as nx
from matplotlib import path

def get_dvh(structure, dose, limit=None, callback=None):
"""Get a calculated cumulative DVH along with the associated parameters."""
Expand Down Expand Up @@ -100,8 +100,8 @@ def calculate_dvh(structure, dose, limit=None, callback=None):
else:
contour['inside'] = False
for point in contour['data']:
if nx.pnpoly(point[0], point[1],
np.array(contours[largestIndex]['data'])):
p = path.Path(np.array(contours[largestIndex]['data']))
if p.contains_point(point, transform=None, radius=0.0):
contour['inside'] = True
# Assume if one point is inside, all will be inside
break
Expand Down Expand Up @@ -161,7 +161,8 @@ def calculate_contour_areas(plane):
def get_contour_mask(doselut, dosegridpoints, contour):
"""Get the mask for the contour with respect to the dose plane."""

grid = nx.points_inside_poly(dosegridpoints, contour)
p = path.Path(contour)
grid = p.contains_points(dosegridpoints, transform=None, radius=0.0)
grid = grid.reshape((len(doselut[1]), len(doselut[0])))

return grid
Expand All @@ -177,9 +178,11 @@ def calculate_contour_dvh(mask, doseplane, maxdose, dd, id, structure):
range=(0,maxdose))

# Calculate the volume for the contour for the given dose plane
id['pixelspacing'][0] = float(id['pixelspacing'][0])
id['pixelspacing'][1] = float(id['pixelspacing'][1])
vol = sum(hist) * ((id['pixelspacing'][0]) *
(id['pixelspacing'][1]) *
(structure['thickness']))
(id['pixelspacing'][1]) *
(structure['thickness']))
return hist, vol

def get_cdvh(ddvh):
Expand Down
7 changes: 6 additions & 1 deletion dicompyler/dvhdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,25 @@ def __init__(self, dvh):
def GetVolumeConstraint(self, dose):
""" Return the volume (in percent) of the structure that receives at
least a specific dose in cGy. i.e. V100, V150."""

return self.dvh[int(dose/self.scaling)]

def GetVolumeConstraintCC(self, dose, volumecc):
""" Return the volume (in cc) of the structure that receives at least a
specific dose in cGy. i.e. V100, V150."""

volumepercent = self.GetVolumeConstraint(dose)
volumepercent = float(self.GetVolumeConstraint(dose))
volumecc = float(volumecc)

return volumepercent * volumecc / 100

def GetDoseConstraint(self, volume):
""" Return the maximum dose (in cGy) that a specific volume (in percent)
receives. i.e. D90, D20."""

self.dvh = np.array(self.dvh, dtype=float)
volume = float(volume)

return np.argmin(np.fabs(self.dvh - volume))*self.scaling

def CalculateVolume(structure):
Expand Down