bastula / dicompyler

Extensible radiation therapy research platform and viewer for DICOM and DICOM RT
http://www.dicompyler.com
263 stars 99 forks source link

Bug in 2dview.py when DICOM images are Feetfirst Prone #107

Open ghost opened 6 years ago

ghost commented 6 years ago

There's a bug in 2dview.py when DICOM images are feetfirst prone. RTStruct are not displayed correctly, errors are in "def GetContourPixelData" . X values do not need to be reversed if patient position is feetfirst and prone at the same time.

I haven't checked the RTDOSE display but there might be another bug here also.

Check the arrow in the code below.

def GetContourPixelData(self, pixlut, contour, prone = False, feetfirst = False):
    """Convert structure data into pixel data using the patient to pixel LUT."""

    pixeldata = []
    # For each point in the structure data
    # look up the value in the LUT and find the corresponding pixel pair
    for p, point in enumerate(contour):
        for xv, xval in enumerate(pixlut[0]):
            if (xval > point[0] and not prone and not feetfirst):
                break
#-->Need another line like:    elif (xval > point[0] and  prone and  feetfirst): break
            elif (xval < point[0]):
                if feetfirst or prone:
#-->the line above should be if feetfirst ^ prone: (^ is simply an xor operator here....)
                    break
        for yv, yval in enumerate(pixlut[1]):
            if (yval > point[1] and not prone):
                break
            elif (yval < point[1] and prone):
                break
        pixeldata.append((xv, yv))

    return pixeldata
bastula commented 6 years ago

I've seen this. Just haven't had the time to resolve the issue. Thanks for the heads up and fixes.

ghost commented 6 years ago

The same bug exists for the RTDOSE in the case of feetfirst prone images. The error is in dicompylercore/dicomparser.py, 'def GetDoseGrid' when you check the ImageOrientationPatient.

def GetDoseGrid(self, z=0, threshold=0.5):
    """
    Return the 2d dose grid for the given slice position (mm).
    :param z:           Slice position in mm.
    :param threshold:   Threshold in mm to determine the max difference
                        from z to the closest dose slice without
                        using interpolation.
    :return:            An numpy 2d array of dose points.
    """

    # If this is a multi-frame dose pixel array,
    # determine the offset for each frame
    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]
# Last line should be:
# orientation = self.ds.ImageOrientationPatient[0]*self.ds.ImageOrientationPatient[4]
# self.ds.ImageOrientationPatient[0] is the x orienation. 
# For axial images you should also multiply with the y value self.ds.ImageOrientationPatient[4]
# Headfirst Supine vector looks like this [1,0,0,0,1,0]
# Feetfirst prone vector is  [1,0,0,0,-1,0]
SimonBiggs commented 5 years ago

A similar bug is also being worked on over at https://gitlab.com/pymedphys/pymedphys/merge_requests/49 if that helps.