Пример #1
0
def FScore(organ, threshold):
    model = Model.UNet()
    model.load_state_dict(torch.load(os.path.join(pathlib.Path(__file__).parent.absolute(), "Models/Model_" + organ.replace(" ", "") + ".pt")))  
    model = model.cuda()
    model = model.eval()
    dataPath = 'Processed_Data/' + organ + "_Val/"
    dataFolder = os.path.join(pathlib.Path(__file__).parent.absolute(), dataPath)
    dataFiles = sorted(os.listdir(dataFolder))
    d = 0
    print('Calculating Statistics')
    TP = 0
    FP = 0
    FN = 0

    xLen,yLen = [0,0]
    while d <  150:#len(dataFiles):
        numStack = min(3, len(dataFiles) - 1 - d) #loading 1400 images at a time (takes about 20GB RAM)
        p = 0
        concatList = []
        while p < numStack:
            imagePath = dataFiles[d]
            image = pickle.load(open(os.path.join(dataFolder, imagePath), 'rb'))
            image = image.reshape((2,1,image.shape[2], image.shape[2]))
            concatList.append(image)
            p+=1
            d+=1
        if len(concatList) == 0:
            break    
        data = np.concatenate(concatList, axis=1)  
        numSlices = data.shape[1]
        for sliceNum in range(numSlices):
            x = torch.from_numpy(data[0, sliceNum, :, :]).cuda()
            y = torch.from_numpy(data[1:2, sliceNum, :,:]).cuda()
            xLen, yLen = x.shape
            #need to reshape 
            x.requires_grad = True
            y.requires_grad = True
            x = torch.reshape(x, (1,1,xLen,yLen)).float()
            y = torch.reshape(y, (1,1,xLen,yLen)).float()
            predictionRaw = (model(x)).cpu().detach().numpy()
            prediction = PostProcessing.Process(predictionRaw, threshold)
            for x_idx in range(xLen):
                for y_idx in range(yLen):
                    if prediction[0,0,x_idx,y_idx] == 1:
                        if y[0,0,x_idx,y_idx] == 1:
                            TP += 1
                        else:
                            FP += 1
                    elif y[0,0,x_idx,y_idx] == 1:     
                        FN += 1  
            print("Finished a patient")            
        print("Finished " + str(d) + "patients...")                     
    totalPoints = d * xLen * yLen                    
    recall = TP / (TP + FN)
    precision = TP / (TP + FP)
    F_Score = 2 / (recall**(-1) + precision ** (-1))
    accuracy = (totalPoints - FP - FN) / totalPoints
    return F_Score, recall, precision, accuracy

        
Пример #2
0
def TestPlot(organ, threshold):
    model = Model.UNet()
    model.load_state_dict(torch.load(os.path.join(pathlib.Path(__file__).parent.absolute(), "Models/Model_" + organ.replace(" ", "") + ".pt")))    
    model = model.cuda()      
    model.eval()
    dataPath = 'Processed_Data/' + organ + "_Val/"
    dataFolder = os.path.join(pathlib.Path(__file__).parent.absolute(), dataPath)
    dataFiles = os.listdir(dataFolder)
    filesRange = list(range(len(dataFiles)))
    random.shuffle(filesRange)
    for d in filesRange:
        imagePath = dataFiles[d]
        #data has 4 dimensions, first is the type (image, contour, background), then slice, and then the pixels.
        data = pickle.load(open(os.path.join(dataFolder, imagePath), 'rb'))
        print("Validating with " + dataFiles[d])
        x = torch.from_numpy(data[0, :, :]).cuda()
        y = torch.from_numpy(data[1:2, :,:]).cuda()
        xLen, yLen = x.shape
        #need to reshape 
        x = torch.reshape(x, (1,1,xLen,yLen)).float()
        y = torch.reshape(y, (1,1,xLen,yLen)).float()   
        predictionRaw = (model(x)).cpu().detach().numpy()
        prediction = PostProcessing.Process(predictionRaw, threshold)
        x = x.cpu().numpy()
        y = y.cpu().numpy()
        maskOnImage = MaskOnImage(x[0,0,:,:], prediction[0,0,:,:])
        ROIOnImage = MaskOnImage(x[0,0,:,:], y[0,0,:,:])

        fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(15, 15))
        
        #predictedContour = PostProcessing.MaskToContour(prediction[0,0,:,:])
        #contour = PostProcessing.MaskToContourImage(y[0,0,:,:])
        axs[0,0].imshow(ROIOnImage, cmap = "gray")
        axs[0,0].set_title("Original Image")
        #axs[0,1].hist(predictionRaw[0,0,:,:], bins=5)
        axs[0,1].imshow(maskOnImage, cmap = "gray")
        axs[0,1].set_title("Mask on Image")
        axs[1,0].imshow(y[0,0, :,:], cmap = "gray")
        axs[1,0].set_title("Original Mask")
        axs[1,1].imshow(prediction[0,0, :,:], cmap="gray")
        axs[1,1].set_title("Predicted Mask")

        
        # axs[2,0].imshow(y[0,1, :,:], cmap = "gray")
        # axs[2,0].set_title("Original Background")
        # axs[2,1].imshow(prediction[0,1, :,:], cmap = "gray")
        # axs[2,1].set_title("Predicted Background")
        plt.show()
Пример #3
0
def GetMasks(organ, patientName, path, threshold):
    #Returns a 3d array of predicted masks for a given patient name.
    if path == None:
        path = pathlib.Path(__file__).parent.absolute()
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model = Model.UNet()
    model.load_state_dict(
        torch.load(
            os.path.join(path,
                         "Models/Model_" + organ.replace(" ", "") + ".pt")))
    model = model.to(device)
    model.eval()

    dataPath = 'Processed_Data/' + organ  #+ "_Val/" #Currently looking for patients in the test folder.
    dataFolder = os.path.join(path, dataPath)
    dataFiles = os.listdir(dataFolder)
    filesRange = list(range(len(dataFiles)))

    patientImages = []
    for d in filesRange:  #First get the files for the patientName given
        if patientName in dataFiles[d]:
            patientImages.append(dataFiles[d])
    patientImages.sort()

    predictions = [
    ]  #First put 2d masks into predictions list and then at the end stack into a 3d array
    originalMasks = []
    for image in patientImages:
        #data has 4 dimensions, first is the type (image, contour, background), then slice, and then the pixels.
        data = pickle.load(open(os.path.join(dataFolder, image), 'rb'))
        x = torch.from_numpy(data[0, :, :])
        y = data[1, :, :]
        x = x.to(device)
        xLen, yLen = x.shape
        #need to reshape
        x = torch.reshape(x, (1, 1, xLen, yLen)).float()
        predictionRaw = (model(x)).cpu().detach().numpy()
        #now post-process the image
        x = x.cpu()
        x = x.numpy()
        prediction = PostProcessing.Process(predictionRaw[0, 0, :, :],
                                            threshold)
        predictions.append(prediction)
        originalMasks.append(y)
    #Stack into 3d array
    predictionsArray = np.stack(predictions, axis=0)
    originalsArray = np.stack(originalMasks, axis=0)
    return predictionsArray, originalsArray
Пример #4
0
def Best_Threshold(organ, testSize=10e6, onlyMasks=False, onlyBackground=False):
    #return the model output threshold that maximizes accuracy. onlyMasks if true will calculate statistics
    #only for images that have a mask on the plane, and onlyBackground will do it for images without masks.
    print("Determining most accurate threshold...")
    model = Model.UNet()
    model.load_state_dict(torch.load(os.path.join(pathlib.Path(__file__).parent.absolute(), "Models/Model_" + organ.replace(" ", "") + ".pt")))    
    model = model.cuda()      
    model.eval()
    dataPath = 'Processed_Data/' + organ + "_Val/"
    dataFolder = os.path.join(pathlib.Path(__file__).parent.absolute(), dataPath)
    dataFiles = os.listdir(dataFolder)

    #also get the bools to find if masks are on image plane
    boolPath = 'Processed_Data/' + organ + " bools"
    boolFolder = os.path.join(pathlib.Path(__file__).parent.absolute(), boolPath)
    boolFiles = os.listdir(boolFolder)

    #shuffle the order (boolFiles is in same order)
    filesRange = list(range(len(dataFiles)))
    random.shuffle(filesRange)

    
    accuracies = [] #make a list of average accuracies calculated using different thresholds
    falsePos = []
    falseNeg = []
    thresholds = np.linspace(0.05,0.7,15)
    
    for thres in thresholds:
        print("Checking Threshold: %0.3f"%(thres))
        d = 0
        #get the accuracy for the current threshold value
        thresAccuracy = []
        thresFP = []
        thresFN = [] #false pos, neg
        testSize = min(testSize, len(filesRange))
        while d < testSize:
            numStack = min(200, len(filesRange) - 1 - d)
            p = 0
            concatList = []
            while p < numStack:
                imagePath = dataFiles[d]
                if onlyMasks:
                    boolMask = pickle.load(open(os.path.join(boolFolder, boolFiles[d]), 'rb'))
                    if not boolMask:
                        p+=1
                        d+=1
                        continue
                elif onlyBackground:
                    boolMask = pickle.load(open(os.path.join(boolFolder, boolFiles[d]), 'rb'))
                    if boolMask:
                        p+=1
                        d+=1
                        continue    
                image = pickle.load(open(os.path.join(dataFolder, imagePath), 'rb'))
                image = image.reshape((2,1,image.shape[1], image.shape[2]))
                concatList.append(image)
                p+=1
                d+=1
            if len(concatList) == 0:
                break    
            data = np.concatenate(concatList, axis=1)    #data has 4 dimensions, first is the type (image, contour, background), then slice, and then the pixels.
            print('Loaded ' + str(data.shape[1]) + ' images. Proceeding...') 
            data = torch.from_numpy(data)
            numSlices = data.shape[1]
            slices = list(range(numSlices))
            random.shuffle(slices)


            for sliceNum in slices:
                x = data[0, sliceNum, :, :].cuda()
                y = data[1, sliceNum, :, :]
                xLen, yLen = x.shape
                #need to reshape 
                x = torch.reshape(x, (1,1,xLen,yLen)).float()
                y = torch.reshape(y, (xLen,yLen)).float()   
                predictionRaw = (model(x)).cpu().detach().numpy()
                prediction = PostProcessing.Process(predictionRaw,thres) 
                prediction = np.reshape(prediction, (xLen, yLen))
                #now judge accuracy: 
               
                thresPrediction = (prediction > thres)
                imageAccuracy = np.sum(thresPrediction == y.numpy())
                imageFP = np.sum(np.logical_and(thresPrediction != y.numpy(), thresPrediction == 1))
                imageFN = np.sum(np.logical_and(thresPrediction != y.numpy(), thresPrediction == 0))         
                imageAccuracy *= 100/float(prediction.size) 
                imageFN *= 100 / float(prediction.size)
                imageFP *= 100 / float(prediction.size)
                thresAccuracy.append(imageAccuracy)
                thresFP.append(imageFP)
                thresFN.append(imageFN) #false pos, neg

        accuracies.append(sum(thresAccuracy) / len(thresAccuracy))
        falseNeg.append(sum(thresFN)/len(thresFN))
        falsePos.append(sum(thresFP)/len(thresFP))
    #Now need to determine what the best threshold to use is. Also plot the accuracy, FP, FN:
    fig, axs = plt.subplots(nrows=3, ncols=1, figsize=(15, 15))

    axs[0].scatter(thresholds, accuracies)
    axs[0].plot(thresholds, accuracies)
    axs[0].set_title("Accuracy vs Threshold")
    axs[1].scatter(thresholds, falsePos)
    axs[1].plot(thresholds, falsePos)
    axs[1].set_title("False Positives vs Threshold")
    axs[2].scatter(thresholds, falseNeg)
    axs[2].plot(thresholds, falseNeg)
    axs[2].set_title("False Negatives vs Threshold")

    plt.show()    

    #Get maximimum accuracy 
    maxAccuracy = max(accuracies) 
    maxAccuracyIndices = [i for i, j in enumerate(accuracies) if j == maxAccuracy]
    bestThreshold = thresholds[maxAccuracyIndices[0]] 
    #save this threshold
    thresFile = open(os.path.join(pathlib.Path(__file__).parent.absolute(), "Models/Model_" + organ.replace(" ", "") + "_Thres.txt"),'w')
    thresFile.write(str(bestThreshold))
    thresFile.close()
    with open(os.path.join(pathlib.Path(__file__).parent.absolute(), "Models/Model_" + organ.replace(" ", "") + "_Accuracy.txt"),'wb') as fp:
        pickle.dump(accuracies, fp)      
    with open(os.path.join(pathlib.Path(__file__).parent.absolute(), "Models/Model_" + organ.replace(" ", "") + "_FalseNeg.txt"),'wb') as fp:
        pickle.dump(falseNeg, fp)   
    with open(os.path.join(pathlib.Path(__file__).parent.absolute(), "Models/Model_" + organ.replace(" ", "") + "_FalsePos.txt"),'wb') as fp:
        pickle.dump(falsePos, fp)            
    return bestThreshold
Пример #5
0
def FScore(organ, path, threshold):
    if path == None:  #if no path supplied, assume that data folders are set up as default in the working directory.
        path = pathlib.Path(__file__).parent.absolute()
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    print("Device being used for training: " + device.type)
    model = Model.UNet()
    model.load_state_dict(
        torch.load(
            os.path.join(path,
                         "Models/Model_" + organ.replace(" ", "") + ".pt")))
    model = model.to(device)
    model = model.eval()
    dataPath = 'Processed_Data/' + organ + "_Val/"
    dataFolder = os.path.join(path, dataPath)
    dataFiles = sorted(os.listdir(dataFolder))
    d = 0
    print('Calculating Fscore Statistics')
    TP = 0
    FP = 0
    FN = 0

    xLen, yLen = [0, 0]
    while d < len(dataFiles):
        numStack = min(
            3,
            len(dataFiles) - 1 -
            d)  #loading 1400 images at a time (takes about 20GB RAM)
        p = 0
        concatList = []
        while p < numStack:
            imagePath = dataFiles[d]
            image = pickle.load(open(os.path.join(dataFolder, imagePath),
                                     'rb'))
            image = image.reshape((2, 1, image.shape[2], image.shape[2]))
            concatList.append(image)
            p += 1
            d += 1
        if len(concatList) == 0:
            break
        data = np.concatenate(concatList, axis=1)
        numSlices = data.shape[1]
        for sliceNum in range(numSlices):
            x = torch.from_numpy(data[0, sliceNum, :, :])
            y = torch.from_numpy(data[1:2, sliceNum, :, :])
            x = x.to(device)
            y = y.to(device)
            xLen, yLen = x.shape
            #need to reshape
            x.requires_grad = True
            y.requires_grad = True
            x = torch.reshape(x, (1, 1, xLen, yLen)).float()
            y = y.cpu().detach().numpy()
            y = np.reshape(y, (xLen, yLen))

            predictionRaw = (model(x)).cpu().detach().numpy()
            predictionRaw = np.reshape(predictionRaw, (xLen, yLen))
            prediction = PostProcessing.Process(predictionRaw, threshold)
            for x_idx in range(xLen):
                for y_idx in range(yLen):
                    if prediction[x_idx, y_idx] == 1:
                        if y[x_idx, y_idx] == 1:
                            TP += 1
                        else:
                            FP += 1
                    elif y[x_idx, y_idx] == 1:
                        FN += 1
        print("Finished " + str(d) + " out of " + str(len(dataFiles)) +
              " contours...")
    totalPoints = d * xLen * yLen
    recall = TP / (TP + FN)
    precision = TP / (TP + FP)
    F_Score = 2 / (recall**(-1) + precision**(-1))
    accuracy = (totalPoints - FP - FN) / totalPoints

    return F_Score, recall, precision, accuracy
Пример #6
0
def TestPlot(organ, path, threshold):
    if path == None:  #if no path supplied, assume that data folders are set up as default in the working directory.
        path = pathlib.Path(__file__).parent.absolute()
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model = Model.UNet()
    model.load_state_dict(
        torch.load(
            os.path.join(path,
                         "Models/Model_" + organ.replace(" ", "") + ".pt")))
    model = model.to(device)
    model.eval()
    dataPath = 'Processed_Data/' + organ + "_Val/"
    dataFolder = os.path.join(path, dataPath)
    dataFiles = os.listdir(dataFolder)
    filesRange = list(range(len(dataFiles)))
    random.shuffle(filesRange)
    for d in filesRange:
        imagePath = dataFiles[d]
        #data has 4 dimensions, first is the type (image, contour, background), then slice, and then the pixels.
        data = pickle.load(open(os.path.join(dataFolder, imagePath), 'rb'))
        x = torch.from_numpy(data[0, :, :])
        y = torch.from_numpy(data[1:2, :, :])
        x = x.to(device)
        y = y.to(device)
        xLen, yLen = x.shape
        #need to reshape
        x = torch.reshape(x, (1, 1, xLen, yLen)).float()
        y = torch.reshape(y, (1, 1, xLen, yLen)).float()
        predictionRaw = (model(x)).cpu().detach().numpy()
        #now post-process the image
        x = x.cpu()
        y = y.cpu()
        x = x.numpy()
        y = y.numpy()
        print(np.amax(y))
        print(np.amin(y))
        prediction = PostProcessing.Process(predictionRaw[0, 0, :, :],
                                            threshold)

        maskOnImage = MaskOnImage(
            x[0,
              0, :, :], prediction)  #this puts the mask ontop of the CT image
        ROIOnImage = MaskOnImage(x[0, 0, :, :], y[0, 0, :, :])

        fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(15, 15))

        #predictedContour = PostProcessing.MaskToContour(prediction[0,0,:,:])
        #contour = PostProcessing.MaskToContourImage(y[0,0,:,:])
        axs[0, 0].imshow(ROIOnImage, cmap="gray")
        axs[0, 0].set_title("Original Image")
        #axs[0,1].hist(predictionRaw[0,0,:,:], bins=5)
        axs[0, 1].imshow(maskOnImage, cmap="gray")
        axs[0, 1].set_title("Mask on Image")
        axs[1, 0].imshow(y[0, 0, :, :], cmap="gray")
        axs[1, 0].set_title("Original Mask")
        axs[1, 1].imshow(prediction, cmap="gray")
        axs[1, 1].set_title("Predicted Mask")

        # axs[2,0].imshow(y[0,1, :,:], cmap = "gray")
        # axs[2,0].set_title("Original Background")
        # axs[2,1].imshow(prediction[0,1, :,:], cmap = "gray")
        # axs[2,1].set_title("Predicted Background")
        plt.show()
Пример #7
0
def GetContours(organ,
                patientFileName,
                threshold,
                withReal=True,
                tryLoad=True):
    #with real loads pre=existing DICOM roi to compare the prediction with
    model = Model.UNet()
    model.load_state_dict(
        torch.load(
            os.path.join(
                pathlib.Path(__file__).parent.absolute(),
                "Models/Model_" + organ.replace(" ", "") + ".pt")))
    model = model.cuda()
    model.eval()

    #Make a list for all the contour images
    try:
        CTs = pickle.load(
            open(
                os.path.join(
                    pathlib.Path(__file__).parent.absolute(),
                    str("Prediction_Patients/" + patientFileName +
                        "_Processed.txt")), 'rb'))
    except:

        CTs = DicomParsing.GetPredictionData(patientFileName, organ)
    if tryLoad:
        try:
            contourImages, contours = pickle.load(
                open(
                    os.path.join(
                        pathlib.Path(__file__).parent.absolute(),
                        str("Prediction_Patients/" + organ + "/" +
                            patientFileName + "_predictedContours.txt")),
                    'rb'))
        except:

            contours = []
            zValues = []  #keep track of z position to add to contours after
            contourImages = []

            exportNum = 0
            for CT in CTs:
                ipp = CT[1]
                zValues.append(float(ipp[2]))
                pixelSpacing = CT[2]
                sliceThickness = CT[3]
                x = torch.from_numpy(CT[0]).cuda()
                xLen, yLen = x.shape
                #need to reshape
                x = torch.reshape(x, (1, 1, xLen, yLen)).float()

                predictionRaw = (model(x)).cpu().detach().numpy()
                prediction = PostProcessing.Process(predictionRaw, threshold)
                contourImage, contourPoints = PostProcessing.MaskToContour(
                    prediction[0, 0, :, :])
                contourImages.append(contourImage)
                contours.append(contourPoints)

            contours = PostProcessing.FixContours(contours)
            contours = PostProcessing.AddZToContours(contours, zValues)
            contours = DicomParsing.PixelToContourCoordinates(
                contours, ipp, zValues, pixelSpacing, sliceThickness)
            with open(
                    os.path.join(
                        pathlib.Path(__file__).parent.absolute(),
                        str("Prediction_Patients/" + organ + "/" +
                            patientFileName + "_predictedContours.txt")),
                    "wb") as fp:
                pickle.dump([contourImages, contours], fp)
    else:
        contours = []
        zValues = []  #keep track of z position to add to contours after
        contourImages = []
        for CT in CTs:
            ipp = CT[1]
            zValues.append(float(ipp[2]))
            pixelSpacing = CT[2]
            sliceThickness = CT[3]
            x = torch.from_numpy(CT[0]).cuda()
            xLen, yLen = x.shape
            #need to reshape
            x = torch.reshape(x, (1, 1, xLen, yLen)).float()

            predictionRaw = (model(x)).cpu().detach().numpy()
            prediction = PostProcessing.Process(predictionRaw, threshold)
            contourImage, contourPoints = PostProcessing.MaskToContour(
                prediction[0, 0, :, :])
            contourImages.append(contourImage)
            contours.append(contourPoints)

        contours = PostProcessing.FixContours(contours)
        contours = PostProcessing.AddZToContours(contours, zValues)
        contours = DicomParsing.PixelToContourCoordinates(
            contours, ipp, zValues, pixelSpacing, sliceThickness)
        with open(
                os.path.join(
                    pathlib.Path(__file__).parent.absolute(),
                    str("Prediction_Patients/" + organ + "/" +
                        patientFileName + "_predictedContours.txt")),
                "wb") as fp:
            pickle.dump([contourImages, contours], fp)
    existingContours = []
    if withReal:
        try:
            existingContours = pickle.load(
                open(
                    os.path.join(
                        pathlib.Path(__file__).parent.absolute(),
                        str("Prediction_Patients/" + organ + "/" +
                            patientFileName + "_ExistingContours.txt")), "rb"))
        except:
            pass
    Test.PlotPatientContours(contours, existingContours)
Пример #8
0
def GetContours(organ,
                patientFileName,
                path,
                threshold,
                withReal=True,
                tryLoad=True,
                plot=True):

    #with real loads pre=existing DICOM roi to compare the prediction with
    if path == None:  #if no path supplied, assume that data folders are set up as default in the working directory.
        path = pathlib.Path(__file__).parent.absolute()
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    print("Device being used for predicting: " + device.type)
    model = Model.UNet()
    model.load_state_dict(
        torch.load(
            os.path.join(path,
                         "Models/Model_" + organ.replace(" ", "") + ".pt")))
    model = model.to(device)
    model.eval()
    contoursList = []  #The 1d contours list to be returned
    existingContoursList = []
    #Make a list for all the contour images
    try:
        CTs = pickle.load(
            open(
                os.path.join(
                    path,
                    str("Predictions_Patients/" + patientFileName +
                        "_Processed.txt")), 'rb'))
    except:

        CTs = DicomParsing.GetPredictionCTs(patientFileName, path)
    if tryLoad:
        try:
            contourImages, contours = pickle.load(
                open(
                    os.path.join(
                        path,
                        str("Predictions_Patients/" + organ + "/" +
                            patientFileName + "_predictedContours.txt")),
                    'rb'))
        except:

            contours = []
            zValues = []  #keep track of z position to add to contours after
            contourImages = []

            exportNum = 0
            for CT in CTs:
                ipp = CT[1]
                zValues.append(float(ipp[2]))
                pixelSpacing = CT[2]
                sliceThickness = CT[3]
                x = torch.from_numpy(CT[0]).to(device)
                xLen, yLen = x.shape
                #need to reshape
                x = torch.reshape(x, (1, 1, xLen, yLen)).float()

                predictionRaw = (model(x)).cpu().detach().numpy()
                prediction = PostProcessing.Process(predictionRaw, threshold)
                contourImage, contourPoints = PostProcessing.MaskToContour(
                    prediction[0, 0, :, :])
                contourImages.append(contourImage)
                contours.append(contourPoints)

            contours = PostProcessing.FixContours(contours)
            contours = PostProcessing.AddZToContours(contours, zValues)
            contours = DicomParsing.PixelToContourCoordinates(
                contours, ipp, zValues, pixelSpacing, sliceThickness)
            for layer_idx in range(len(contours)):
                if len(contours[layer_idx]) > 0:
                    for point_idx in range(len(contours[layer_idx])):
                        x = contours[layer_idx][point_idx][0]
                        y = contours[layer_idx][point_idx][1]
                        z = contours[layer_idx][point_idx][2]
                        contoursList.append(x)
                        contoursList.append(y)
                        contoursList.append(z)
            with open(
                    os.path.join(
                        path,
                        str("Predictions_Patients/" + organ + "/" +
                            patientFileName + "_predictedContours.txt")),
                    "wb") as fp:
                pickle.dump([contourImages, contours], fp)
    else:
        contours = []
        zValues = []  #keep track of z position to add to contours after
        contourImages = []
        for CT in CTs:
            ipp = CT[1]
            zValues.append(float(ipp[2]))
            pixelSpacing = CT[2]
            sliceThickness = CT[3]
            x = torch.from_numpy(CT[0]).to(device)

            xLen, yLen = x.shape
            #need to reshape
            x = torch.reshape(x, (1, 1, xLen, yLen)).float()

            predictionRaw = (model(x)).cpu().detach().numpy()
            prediction = predictionRaw
            prediction[0, 0, :, :] = PostProcessing.Process(
                predictionRaw[0, 0, :, :], threshold)
            contourImage, contourPoints = PostProcessing.MaskToContour(
                prediction[0, 0, :, :])
            contourImages.append(contourImage)
            contours.append(contourPoints)

        contours = PostProcessing.FixContours(contours)
        contours = PostProcessing.AddZToContours(contours, zValues)
        contours = DicomParsing.PixelToContourCoordinates(
            contours, ipp, zValues, pixelSpacing, sliceThickness)

        for layer_idx in range(len(contours)):
            if len(contours[layer_idx]) > 0:
                for point_idx in range(len(contours[layer_idx])):
                    x = contours[layer_idx][point_idx][0]
                    y = contours[layer_idx][point_idx][1]
                    z = contours[layer_idx][point_idx][2]
                    contoursList.append(x)
                    contoursList.append(y)
                    contoursList.append(z)

        with open(
                os.path.join(
                    path,
                    str("Predictions_Patients/" + organ + "/" +
                        patientFileName + "_predictedContours.txt")),
                "wb") as fp:
            pickle.dump([contourImages, contours], fp)

    existingContours = []

    if withReal:
        try:
            existingContours = pickle.load(
                open(
                    os.path.join(
                        path,
                        str("Predictions_Patients/" + organ + "/" +
                            patientFileName + "_ExistingContours.txt")), "rb"))
            for layer_idx in range(len(existingContours)):
                if len(existingContours[layer_idx]) > 0:
                    for point_idx in range(len(existingContours[layer_idx])):
                        x = existingContours[layer_idx][point_idx][0]
                        y = existingContours[layer_idx][point_idx][1]
                        z = existingContours[layer_idx][point_idx][2]
                        existingContoursList.append(x)
                        existingContoursList.append(y)
                        existingContoursList.append(z)
        except:
            existingContours = DicomParsing.GetDICOMContours(
                patientFileName, organ, path)
            for layer_idx in range(len(existingContours)):
                if len(existingContours[layer_idx]) > 0:
                    for point_idx in range(len(existingContours[layer_idx])):
                        x = existingContours[layer_idx][point_idx][0]
                        y = existingContours[layer_idx][point_idx][1]
                        z = existingContours[layer_idx][point_idx][2]
                        existingContoursList.append(x)
                        existingContoursList.append(y)
                        existingContoursList.append(z)
    if plot == True:
        Test.PlotPatientContours(contours, existingContours)
    return contoursList, existingContoursList