def resetIslandSegments(self, islandSizes):
    self.segmentation.RemoveAllSegments()

    totalSize = 0
    voxelSizeSum = 0
    for size in islandSizes:
      totalSize += size + 1
      voxelSizeSum += size

    mergedLabelmap = vtkSegmentationCore.vtkOrientedImageData()
    mergedLabelmapExtent = [0, totalSize-1, 0, 0, 0, 0]
    self.setupIslandLabelmap(mergedLabelmap, mergedLabelmapExtent, 0)

    emptySegment = slicer.vtkSegment()
    emptySegment.SetName("Segment_1")
    emptySegment.AddRepresentation(self.binaryLabelmapReprName, mergedLabelmap)
    self.segmentation.AddSegment(emptySegment)
    self.segmentEditorNode.SetSelectedSegmentID("Segment_1")

    startExtent = 0
    for size in islandSizes:
      islandLabelmap = vtkSegmentationCore.vtkOrientedImageData()
      islandExtent = [startExtent, startExtent+size-1, 0, 0, 0, 0]
      self.setupIslandLabelmap(islandLabelmap, islandExtent)
      self.paintEffect.modifySelectedSegmentByLabelmap(islandLabelmap, self.paintEffect.ModificationModeAdd)
      startExtent += size + 1
    self.checkSegmentVoxelCount(0, voxelSizeSum)


    layerCount = self.segmentation.GetNumberOfLayers()
    self.assertEqual(layerCount, 1)
    def TestSection_01_GenerateInputData(self):
        logging.info('Test section 1: GenerateInputData')
        self.inputSegmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLSegmentationNode')

        # Create new segments
        import random
        for segmentName in ['first', 'second', 'third']:
            sphereSegment = slicer.vtkSegment()
            sphereSegment.SetName(segmentName)
            sphereSegment.SetColor(random.uniform(0.0, 1.0),
                                   random.uniform(0.0, 1.0),
                                   random.uniform(0.0, 1.0))

            sphere = vtk.vtkSphereSource()
            sphere.SetCenter(random.uniform(0, 100), random.uniform(0, 100),
                             random.uniform(0, 100))
            sphere.SetRadius(random.uniform(20, 30))
            sphere.Update()
            spherePolyData = sphere.GetOutput()
            sphereSegment.AddRepresentation(
                slicer.vtkSegmentationConverter.
                GetSegmentationClosedSurfaceRepresentationName(),
                spherePolyData)

            self.inputSegmentationNode.GetSegmentation().AddSegment(
                sphereSegment)

        self.assertEqual(
            self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(),
            3)

        self.inputSegmentationNode.CreateDefaultDisplayNodes()
        displayNode = self.inputSegmentationNode.GetDisplayNode()
        self.assertIsNotNone(displayNode)
Beispiel #3
0
def createSegNodeFromContourPoints(segmentationNode, contours, name):
    # set up contour objects
    contoursPolyData = vtk.vtkPolyData()
    contourPoints = vtk.vtkPoints()
    contourLines = vtk.vtkCellArray()
    contoursPolyData.SetLines(contourLines)
    contoursPolyData.SetPoints(contourPoints)

    for contour in contours:
        startPointIndex = contourPoints.GetNumberOfPoints()
        contourLine = vtk.vtkPolyLine()
        linePointIds = contourLine.GetPointIds()
        for point in contour:
            linePointIds.InsertNextId(contourPoints.InsertNextPoint(point))
        linePointIds.InsertNextId(
            startPointIndex)  # make the contour line closed
        contourLines.InsertNextCell(contourLine)

    segment = slicer.vtkSegment()
    segment.SetName(name)
    # segment.SetColor(segmentColor)
    segment.AddRepresentation("Planar contour", contoursPolyData)
    segmentationNode.GetSegmentation().SetMasterRepresentationName(
        "Planar contour")
    segmentationNode.GetSegmentation().AddSegment(segment)
Beispiel #4
0
 def _polydataToNewSegment(polydata, segmentationNode, segmentID):
     segmentation = segmentationNode.GetSegmentation()
     baseSegment = segmentation.GetSegment(segmentID)
     segment = slicer.vtkSegment()
     segment.SetName(baseSegment.GetName() + "_solid")
     segment.AddRepresentation(
         vtkSegmentationCorePython.vtkSegmentationConverter.
         GetSegmentationClosedSurfaceRepresentationName(), polydata)
     segmentation.AddSegment(segment)
    def TestSection_03_qMRMLSegmentationGeometryWidget(self):
        logging.info('Test section 2: qMRMLSegmentationGeometryWidget')

        binaryLabelmapReprName = slicer.vtkSegmentationConverter.GetBinaryLabelmapRepresentationName(
        )
        closedSurfaceReprName = slicer.vtkSegmentationConverter.GetClosedSurfaceRepresentationName(
        )

        # Use MRHead and Tinypatient for testing
        import SampleData
        mrVolumeNode = SampleData.downloadSample("MRHead")
        [tinyVolumeNode,
         tinySegmentationNode] = SampleData.downloadSamples('TinyPatient')

        # Convert MRHead to oriented image data
        import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
        mrOrientedImageData = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.CreateOrientedImageDataFromVolumeNode(
            mrVolumeNode)
        mrOrientedImageData.UnRegister(None)

        # Create segmentation node with binary labelmap master and one segment with MRHead geometry
        segmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLSegmentationNode')
        segmentationNode.GetSegmentation().SetMasterRepresentationName(
            binaryLabelmapReprName)
        geometryStr = slicer.vtkSegmentationConverter.SerializeImageGeometry(
            mrOrientedImageData)
        segmentationNode.GetSegmentation().SetConversionParameter(
            slicer.vtkSegmentationConverter.
            GetReferenceImageGeometryParameterName(), geometryStr)

        threshold = vtk.vtkImageThreshold()
        threshold.SetInputData(mrOrientedImageData)
        threshold.ThresholdByUpper(16.0)
        threshold.SetInValue(1)
        threshold.SetOutValue(0)
        threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR)
        threshold.Update()
        segmentOrientedImageData = slicer.vtkOrientedImageData()
        segmentOrientedImageData.DeepCopy(threshold.GetOutput())
        mrImageToWorldMatrix = vtk.vtkMatrix4x4()
        mrOrientedImageData.GetImageToWorldMatrix(mrImageToWorldMatrix)
        segmentOrientedImageData.SetImageToWorldMatrix(mrImageToWorldMatrix)
        segment = slicer.vtkSegment()
        segment.SetName('Brain')
        segment.SetColor(0.0, 0.0, 1.0)
        segment.AddRepresentation(binaryLabelmapReprName,
                                  segmentOrientedImageData)
        segmentationNode.GetSegmentation().AddSegment(segment)

        # Create geometry widget
        geometryWidget = slicer.qMRMLSegmentationGeometryWidget()
        geometryWidget.setSegmentationNode(segmentationNode)
        geometryWidget.editEnabled = True
        geometryImageData = slicer.vtkOrientedImageData(
        )  # To contain the output later

        # Volume source with no transforms
        geometryWidget.setSourceNode(tinyVolumeNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

        # Transformed volume source
        translationTransformMatrix = vtk.vtkMatrix4x4()
        translationTransformMatrix.SetElement(0, 3, 24.5)
        translationTransformMatrix.SetElement(1, 3, 24.5)
        translationTransformMatrix.SetElement(2, 3, 11.5)
        translationTransformNode = slicer.vtkMRMLLinearTransformNode()
        translationTransformNode.SetName('TestTranslation')
        slicer.mrmlScene.AddNode(translationTransformNode)
        translationTransformNode.SetMatrixTransformToParent(
            translationTransformMatrix)

        tinyVolumeNode.SetAndObserveTransformNodeID(
            translationTransformNode.GetID())
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (273.3439, 272.7890, -112.25),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 94)

        # Volume source with isotropic spacing
        tinyVolumeNode.SetAndObserveTransformNodeID(None)
        geometryWidget.setIsotropicSpacing(True)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (23, 23, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 414)

        # Volume source with oversampling
        geometryWidget.setIsotropicSpacing(False)
        geometryWidget.setOversamplingFactor(2.0)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (24.5, 24.5, 11.5),
                (261.0939, 260.5390, -129.5),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 751)
        slicer.util.delayDisplay('Volume source cases - OK')

        # Segmentation source with binary labelmap master
        geometryWidget.setOversamplingFactor(1.0)
        geometryWidget.setSourceNode(tinySegmentationNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

        # Segmentation source with closed surface master
        tinySegmentationNode.GetSegmentation().SetConversionParameter(
            'Smoothing factor', '0.0')
        self.assertTrue(
            tinySegmentationNode.GetSegmentation().CreateRepresentation(
                closedSurfaceReprName))
        tinySegmentationNode.GetSegmentation().SetMasterRepresentationName(
            closedSurfaceReprName)
        tinySegmentationNode.Modified(
        )  # Trigger re-calculation of geometry (only generic Modified event is observed)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData,
                (1, 1, 1),
                (-86.645, 133.929,
                 116.786),  # current origin of the segmentation is kept
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223040)
        slicer.util.delayDisplay('Segmentation source cases - OK')

        # Model source with no transform
        shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(
            slicer.mrmlScene)
        outputFolderId = shNode.CreateFolderItem(shNode.GetSceneItemID(),
                                                 'ModelsFolder')
        success = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.ExportVisibleSegmentsToModels(
            tinySegmentationNode, outputFolderId)
        self.assertTrue(success)
        modelNode = slicer.util.getNode('Body_Contour')
        geometryWidget.setSourceNode(modelNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData,
                (1, 1, 1),
                (-86.645, 133.929,
                 116.786),  # current origin of the segmentation is kept
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223040)

        # Transformed model source
        rotationTransform = vtk.vtkTransform()
        rotationTransform.RotateX(45)
        rotationTransformMatrix = vtk.vtkMatrix4x4()
        rotationTransform.GetMatrix(rotationTransformMatrix)
        rotationTransformNode = slicer.vtkMRMLLinearTransformNode()
        rotationTransformNode.SetName('TestRotation')
        slicer.mrmlScene.AddNode(rotationTransformNode)
        rotationTransformNode.SetMatrixTransformToParent(
            rotationTransformMatrix)

        modelNode.SetAndObserveTransformNodeID(rotationTransformNode.GetID())
        modelNode.Modified()
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-86.645, 177.282, -12.122),
                [[0.0, 0.0, 1.0], [-0.7071, -0.7071, 0.0],
                 [0.7071, -0.7071, 0.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5229164)

        # ROI source
        roiNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLAnnotationROINode", 'SourceROI')
        xyz = [0.0, 0.0, 0.0]
        center = [0.0, 0.0, 0.0]
        slicer.vtkMRMLSliceLogic.GetVolumeRASBox(tinyVolumeNode, xyz, center)
        radius = [x / 2.0 for x in xyz]
        roiNode.SetXYZ(center)
        roiNode.SetRadiusXYZ(radius)
        geometryWidget.setSourceNode(roiNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (0.0, 0.0, 0.0),
                [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]))
        slicer.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5224232)
        slicer.util.delayDisplay('Model and ROI source cases - OK')

        slicer.util.delayDisplay('Segmentation geometry widget test passed')
    def splitSegments(self, minimumSize=0, maxNumberOfSegments=0, split=True):
        """
    minimumSize: if 0 then it means that all islands are kept, regardless of size
    maxNumberOfSegments: if 0 then it means that all islands are kept, regardless of how many
    """
        # This can be a long operation - indicate it to the user
        qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)

        self.scriptedEffect.saveStateForUndo()

        # Get modifier labelmap
        selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap()

        castIn = vtk.vtkImageCast()
        castIn.SetInputData(selectedSegmentLabelmap)
        castIn.SetOutputScalarTypeToUnsignedInt()

        # Identify the islands in the inverted volume and
        # find the pixel that corresponds to the background
        islandMath = vtkITK.vtkITKIslandMath()
        islandMath.SetInputConnection(castIn.GetOutputPort())
        islandMath.SetFullyConnected(False)
        islandMath.SetMinimumSize(minimumSize)
        islandMath.Update()

        islandImage = slicer.vtkOrientedImageData()
        islandImage.ShallowCopy(islandMath.GetOutput())
        selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4()
        selectedSegmentLabelmap.GetImageToWorldMatrix(
            selectedSegmentLabelmapImageToWorldMatrix)
        islandImage.SetImageToWorldMatrix(
            selectedSegmentLabelmapImageToWorldMatrix)

        islandCount = islandMath.GetNumberOfIslands()
        islandOrigCount = islandMath.GetOriginalNumberOfIslands()
        ignoredIslands = islandOrigCount - islandCount
        logging.info("%d islands created (%d ignored)" %
                     (islandCount, ignoredIslands))

        baseSegmentName = "Label"
        selectedSegmentID = self.scriptedEffect.parameterSetNode(
        ).GetSelectedSegmentID()
        segmentationNode = self.scriptedEffect.parameterSetNode(
        ).GetSegmentationNode()
        with slicer.util.NodeModify(segmentationNode):
            segmentation = segmentationNode.GetSegmentation()
            selectedSegment = segmentation.GetSegment(selectedSegmentID)
            selectedSegmentName = selectedSegment.GetName()
            if selectedSegmentName is not None and selectedSegmentName != "":
                baseSegmentName = selectedSegmentName

            labelValues = vtk.vtkIntArray()
            slicer.vtkSlicerSegmentationsModuleLogic.GetAllLabelValues(
                labelValues, islandImage)

            # Erase segment from in original labelmap.
            # Individuall islands will be added back later.
            threshold = vtk.vtkImageThreshold()
            threshold.SetInputData(selectedSegmentLabelmap)
            threshold.ThresholdBetween(0, 0)
            threshold.SetInValue(0)
            threshold.SetOutValue(0)
            threshold.Update()
            emptyLabelmap = slicer.vtkOrientedImageData()
            emptyLabelmap.ShallowCopy(threshold.GetOutput())
            emptyLabelmap.CopyDirections(selectedSegmentLabelmap)
            self.scriptedEffect.modifySegmentByLabelmap(
                segmentationNode, selectedSegmentID, emptyLabelmap,
                slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet)

            for i in range(labelValues.GetNumberOfTuples()):
                if (maxNumberOfSegments > 0 and i >= maxNumberOfSegments):
                    # We only care about the segments up to maxNumberOfSegments.
                    # If we do not want to split segments, we only care about the first.
                    break

                labelValue = int(labelValues.GetTuple1(i))
                segment = selectedSegment
                segmentID = selectedSegmentID
                if i != 0 and split:
                    segment = slicer.vtkSegment()
                    name = baseSegmentName + "_" + str(i + 1)
                    segment.SetName(name)
                    segment.AddRepresentation(
                        slicer.vtkSegmentationConverter.
                        GetSegmentationBinaryLabelmapRepresentationName(),
                        selectedSegment.GetRepresentation(
                            slicer.vtkSegmentationConverter.
                            GetSegmentationBinaryLabelmapRepresentationName()))
                    segmentation.AddSegment(segment)
                    segmentID = segmentation.GetSegmentIdBySegment(segment)
                    segment.SetLabelValue(
                        segmentation.GetUniqueLabelValueForSharedLabelmap(
                            selectedSegmentID))

                threshold = vtk.vtkImageThreshold()
                threshold.SetInputData(islandMath.GetOutput())
                threshold.ThresholdBetween(labelValue, labelValue)
                threshold.SetInValue(1)
                threshold.SetOutValue(0)
                threshold.Update()

                modificationMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeAdd
                if i == 0:
                    modificationMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet

                # Create oriented image data from output
                modifierImage = slicer.vtkOrientedImageData()
                modifierImage.DeepCopy(threshold.GetOutput())
                selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4()
                selectedSegmentLabelmap.GetImageToWorldMatrix(
                    selectedSegmentLabelmapImageToWorldMatrix)
                modifierImage.SetGeometryFromImageToWorldMatrix(
                    selectedSegmentLabelmapImageToWorldMatrix)
                # We could use a single slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode
                # method call to import all the resulting segments at once but that would put all the imported segments
                # in a new layer. By using modifySegmentByLabelmap, the number of layers will not increase.
                self.scriptedEffect.modifySegmentByLabelmap(
                    segmentationNode, segmentID, modifierImage,
                    modificationMode)

        qt.QApplication.restoreOverrideCursor()
Beispiel #7
0
    def importOsirixRoiFileToSegmentation(self,
                                          inputRoi,
                                          outputSegmentationNode,
                                          smoothing=True,
                                          labelmapOutput=False):
        """
    Run the processing algorithm.
    Can be used without GUI widget.
    :param inputRoi: input OsiriX ROI file path or text node
    :param outputSegmentation: output segmentation node
    """

        if not inputRoi or not outputSegmentationNode:
            raise ValueError(
                "Input file or output segmentation node is invalid")

        logging.info('Processing started')

        inputRoiData = None
        import json
        import plistlib
        if isinstance(inputRoi, str):
            filename, ext = os.path.splitext(inputRoi)
            if ext.lower() == '.json':
                with open(inputRoi) as f:
                    inputRoiData = json.load(f)
            else:
                inputRoiData = plistlib.readPlist(inputRoi)
        elif isinstance(inputRoi, slicer.vtkMRMLTextNode):
            try:
                inputRoiData = json.loads(inputRoi.GetText())
            except:
                inputRoiData = plistlib.readPlistFromBytes(inputRoi.GetText())
        else:
            raise TypeError(
                "inputRoi is expected to be a string or vtkMRMLTextNode")

        outputSegmentationNode.CreateDefaultDisplayNodes()
        segmentation = outputSegmentationNode.GetSegmentation()
        segmentation.SetMasterRepresentationName(
            slicer.vtkSegmentationConverter.GetPlanarContourRepresentationName(
            ))

        roiDescriptions = {}  # map from ROI name to RoiDescription

        class RoiDescription(object):
            def __init__(self):
                self.roiContourPoints = vtk.vtkPoints()
                self.roiContourCells = vtk.vtkCellArray()

            def addRoiPoints(self, roiPoints):
                cellPointIds = []
                for roiPoint in roiPoints:
                    cellPointIds.append(
                        self.roiContourPoints.InsertNextPoint(roiPoint))
                contourIndex = self.roiContourCells.InsertNextCell(
                    len(cellPointIds) + 1)
                for cellPointId in cellPointIds:
                    self.roiContourCells.InsertCellPoint(cellPointId)
                self.roiContourCells.InsertCellPoint(
                    cellPointIds[0])  # close the contour

        if "Images" not in inputRoiData:
            for contourIndex, contour in enumerate(inputRoiData):
                # Get/create ROI description
                name = contour["Name"]
                try:
                    roiDescription = roiDescriptions[name]
                except KeyError:
                    roiDescription = RoiDescription()
                    roiDescriptions[name] = roiDescription
                # Add points
                roiPoints = self._pointCoordinatesFromStringList(
                    contour["ROI3DPoints"], '[]')
                if smoothing:
                    roiPoints = self._smoothCurve(roiPoints)
                roiDescription.addRoiPoints(roiPoints)
                self.log(f"Importing {len(roiDescriptions)} ROIs",
                         25.0 * contourIndex / len(inputRoiData))
        else:
            # Output of OsiriX "Export ROIs" plugin
            for imageIndex, image in enumerate(inputRoiData['Images']):
                rois = image['ROIs']
                for roiIndex, roi in enumerate(rois):
                    # Get/create ROI description
                    name = roi["Name"]
                    try:
                        roiDescription = roiDescriptions[name]
                    except KeyError:
                        roiDescription = RoiDescription()
                        roiDescriptions[name] = roiDescription
                    # Add points
                    roiPoints = self._pointCoordinatesFromStringList(
                        roi['Point_mm'], '()')
                    if smoothing:
                        roiPoints = self._smoothCurve(roiPoints)
                    roiDescription.addRoiPoints(roiPoints)
                    self.log(f"Importing {len(roiDescriptions)} ROIs",
                             25.0 * imageIndex / len(inputRoiData["Images"]))

        colorNode = slicer.mrmlScene.GetNodeByID(
            slicer.modules.colors.logic().GetDefaultLabelMapColorNodeID())

        for segmentIndex, name in enumerate(roiDescriptions):
            self.log(
                f"Creating segment {segmentIndex+1} of {len(roiDescriptions)}",
                25.0 + 50.0 * segmentIndex / len(roiDescriptions))

            roiDescription = roiDescriptions[name]

            colorRGBA = [0, 0, 0, 0]
            colorNode.GetColor(segmentIndex + 1, colorRGBA)

            roiPolyData = vtk.vtkPolyData()
            roiPolyData.SetPoints(roiDescription.roiContourPoints)
            roiPolyData.SetLines(roiDescription.roiContourCells)

            normals = vtk.vtkPolyDataNormals()
            normals.SetInputData(roiPolyData)
            normals.Update()

            segment = slicer.vtkSegment()
            segment.SetName(name)
            segment.SetColor(colorRGBA[:3])
            segment.AddRepresentation(
                slicer.vtkSegmentationConverter.
                GetPlanarContourRepresentationName(), roiPolyData)

            segmentation.AddSegment(segment)

        self.log("Creating representations...", 80)
        if labelmapOutput:
            outputSegmentationNode.CreateBinaryLabelmapRepresentation()
            outputSegmentationNode.CreateClosedSurfaceRepresentation()
            outputSegmentationNode.GetDisplayNode(
            ).SetPreferredDisplayRepresentationName2D(
                slicer.vtkSegmentationConverter.
                GetBinaryLabelmapRepresentationName())
            outputSegmentationNode.GetDisplayNode(
            ).SetPreferredDisplayRepresentationName3D(
                slicer.vtkSegmentationConverter.
                GetClosedSurfaceRepresentationName())
        else:
            outputSegmentationNode.CreateClosedSurfaceRepresentation()
            outputSegmentationNode.GetDisplayNode(
            ).SetPreferredDisplayRepresentationName2D(
                slicer.vtkSegmentationConverter.
                GetClosedSurfaceRepresentationName())
            outputSegmentationNode.GetDisplayNode(
            ).SetPreferredDisplayRepresentationName3D(
                slicer.vtkSegmentationConverter.
                GetClosedSurfaceRepresentationName())

        logging.info('Processing completed')
    def ProceduralSegmentation(self, inputDir, outputDir):

        # Importing Dicom into temporary database
        dicomDataDir = inputDir
        from DICOMLib import DICOMUtils
        loadedNodeIDs = []

        with DICOMUtils.TemporaryDICOMDatabase() as db:
            DICOMUtils.importDicom(dicomDataDir, db)
            patientUIDs = db.patients()
            for patientUID in patientUIDs:
                loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))

# Loading Dicom into scene
        seriesVolumeNode = slicer.util.getNode(loadedNodeIDs[0])
        storageVolumeNode = seriesVolumeNode.CreateDefaultStorageNode()
        slicer.mrmlScene.AddNode(storageVolumeNode)
        storageVolumeNode.UnRegister(slicer.mrmlScene)
        seriesVolumeNode.SetAndObserveStorageNodeID(storageVolumeNode.GetID())

        # Access segmentation module
        slicer.util.selectModule('Segment Editor')
        segmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLSegmentationNode")
        slicer.mrmlScene.AddNode(segmentationNode)
        segmentationNode.CreateDefaultDisplayNodes()  # only needed for display
        segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(
            seriesVolumeNode)

        # TODO Automate creation of different segments in the future (using some form of -type argument)
        # Create spine segment
        segmentTypeID = "Spine"
        newSegment = slicer.vtkSegment()
        newSegment.SetName(segmentTypeID)
        newSegment.SetColor([0.89, 0.85, 0.78])
        segmentationNode.GetSegmentation().AddSegment(newSegment,
                                                      segmentTypeID)

        # Create segment editor widget to get access to effects
        segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
        segmentEditorWidget.setMRMLScene(slicer.mrmlScene)

        # Access segment editor node
        segmentEditorNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLSegmentEditorNode")
        slicer.mrmlScene.AddNode(segmentEditorNode)
        segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
        segmentEditorWidget.setSegmentationNode(segmentationNode)
        segmentEditorWidget.setMasterVolumeNode(seriesVolumeNode)

        # Segment Editor Effect: Thresholding
        segmentEditorWidget.setActiveEffectByName("Threshold")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("MinimumThreshold", "90")
        effect.setParameter("MaximumThreshold", "1600")
        effect.self().onApply()

        # Setting Closed Surface Representation Values
        segmentationNode.GetSegmentation().SetConversionParameter(
            "Oversampling factor", "1.0")
        segmentationNode.GetSegmentation().SetConversionParameter(
            "Joint smoothing", "0.50")
        segmentationNode.GetSegmentation().SetConversionParameter(
            "Smoothing factor", "0.50")

        # Segment Editor Effect: Smoothing
        segmentEditorWidget.setActiveEffectByName("Smoothing")
        effect = segmentEditorWidget.activeEffect()
        # 2mm MEDIAN Smoothing
        effect.setParameter("SmoothingMethod", "MEDIAN")
        effect.setParameter("KernelSizeMm", 2.5)
        effect.self().onApply()
        # 2mm OPEN Smoothing
        #effect.setParameter("SmoothingMethod", "MORPHOLOGICAL_OPENING")
        #effect.setParameter("KernelSizeMm", 2)
        #effect.self().onApply
        # 1.5mm CLOSED Smoothing
        #effect.setParameter("SmoothingMethod", "MORPHOLOGICAL_CLOSING")
        #effect.setParameter("KernelSizeMm", 1.5)
        #effect.self().onApply

        # Create Closed Surface Representation
        segmentationNode.CreateClosedSurfaceRepresentation()

        # Export Segmentation to Model Node
        shNode = slicer.mrmlScene.GetSubjectHierarchyNode()
        exportFolderItemId = shNode.CreateFolderItem(shNode.GetSceneItemID(),
                                                     "Segments")
        slicer.modules.segmentations.logic().ExportAllSegmentsToModels(
            segmentationNode, exportFolderItemId)

        segmentID = segmentationNode.GetSegmentation().GetNthSegmentID(0)
        surfaceMesh = segmentationNode.GetClosedSurfaceInternalRepresentation(
            segmentID)

        # Decimate Model
        decimator = vtk.vtkDecimatePro()
        decimator.SplittingOff()
        decimator.PreserveTopologyOn()
        decimator.SetTargetReduction(0.95)
        decimator.SetInputData(surfaceMesh)
        decimator.Update()
        surfaceMesh = decimator.GetOutput()

        # Smooth the Model
        smoothingFactor = 0.5
        smoother = vtk.vtkWindowedSincPolyDataFilter()
        smoother.SetInputData(surfaceMesh)
        smoother.SetNumberOfIterations(50)
        smoother.SetPassBand(pow(10.0, -4.0 * smoothingFactor))
        smoother.BoundarySmoothingOff()
        smoother.FeatureEdgeSmoothingOff()
        smoother.NonManifoldSmoothingOn()
        smoother.NormalizeCoordinatesOn()
        smoother.Update()
        surfaceMesh = smoother.GetOutput()

        # Clean up Model
        cleaner = vtk.vtkCleanPolyData()
        #cleaner.PointMergingOff()
        #cleaner.ConvertLinesToPointsOn()
        #cleaner.ConvertPolysToLinesOn()
        #cleaner.ConvertStripsToPolysOn()
        cleaner.SetInputData(surfaceMesh)
        cleaner.Update()
        surfaceMesh = cleaner.GetOutput()

        # Write to OBJ File
        outputFileName = outputDir + "segmentation.obj"
        writer = vtk.vtkOBJWriter()
        writer.SetFileName(outputFileName)
        writer.SetInputData(surfaceMesh)
        writer.Update()

        # Clean up
        segmentEditorWidget = None
        slicer.mrmlScene.RemoveNode(segmentEditorNode)
    def cornerstoneannotationsToSlicerSegments(self, masterVolume, auth_token,
                                               jobid, projectjson, useremail):
        print('cornerstoneannotationsToSlicerSegments()', flush=True)
        # voxels = slicer.util.arrayFromVolume(masterVolume)
        ijkToRasMatrix = vtk.vtkMatrix4x4()
        masterVolume.GetIJKToRASMatrix(ijkToRasMatrix)
        imageData = masterVolume.GetImageData()
        transformVolumeRasToRas = vtk.vtkGeneralTransform()
        slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(
            masterVolume.GetParentTransformNode(), None,
            transformVolumeRasToRas)
        tdioClientAPI = TDIOClientAPI()
        instanceindex = -1
        contoursmap = {}
        colorsmap = {}
        segmentsmap = {}

        seriesjson = projectjson['images']['seriesList'][0]
        for instance in seriesjson['instanceList']:
            instanceindex = instanceindex + 1
            instanceid = instance['instanceId']
            response = tdioClientAPI.getcornerstoneannotation(
                'https://app.trainingdata.io', auth_token, jobid,
                seriesjson['seriesId'], instanceid, useremail)
            cannotations = []
            cannotations = response
            if len(cannotations) == 0:
                continue
            jsonobj = json.loads(cannotations[0]['jsonstring'])
            annotations = jsonobj['annotations']
            print('instanceid1', instanceid, len(annotations))
            for annotation in annotations:
                # print(annotation)
                toolData = annotation['toolData']
                toolType = annotation['toolName']
                color = annotation['selectedColor']
                color = TDIOUtils.hex_to_rgb(annotation['selectedColor'])
                aclass = annotation['annotationClass']
                label = ''.join(filter(lambda x: x in printable, aclass))
                for data in toolData:
                    if not not data['color']:
                        if len(data['color']) == 0:
                            continue
                        color = TDIOUtils.hex_to_rgb(data['color'])
                        if toolType == 'freehand':
                            if label not in contoursmap:
                                contoursmap[label] = []
                            points = getPointsFromPolygon(data)
                            # points = [[10,10], [110,10], [110,110], [10, 110]]
                            contour = []
                            for p in points:
                                try:
                                    ras = self.ijkToRas(
                                        ijkToRasMatrix,
                                        transformVolumeRasToRas, p[0], p[1],
                                        instanceindex)
                                    # print('ras:', ras)
                                    contour.append(
                                        np.array([p[0], p[1], instanceindex],
                                                 dtype=(np.int)))
                                except Exception as ex:
                                    print(ex)
                            contoursmap[label].append(contour)
                            colorsmap[label] = color

        segmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLSegmentationNode")
        segmentationNode.CreateDefaultDisplayNodes()
        segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(
            masterVolume)  #I tried with and without this line

        labelinginterface = projectjson['labelinginterface']
        if 'tools' in labelinginterface and len(
                labelinginterface['tools']) > 0:
            for tool in labelinginterface['tools']:
                name = tool['name']
                color = TDIOUtils.hex_to_rgb(tool['color'])
                print(color)
                segment = slicer.vtkSegment()
                segment.SetName(name)
                segment.SetColor(color)
                segmentsmap[name] = segment

        # print(colorsmap, contoursmap)
        for key in contoursmap:
            segmentName = key
            segment = segmentsmap[key]
            contours = contoursmap[key]
            self.addContoursToSegment(ijkToRasMatrix, transformVolumeRasToRas,
                                      segment, contours, segmentName)

        for key in segmentsmap:
            segment = segmentsmap[key]
            segmentationNode.GetSegmentation().AddSegment(segment)