def setNewFiducial(self, newSceneNode): # Allow click to set the new fiducial to the list if self.fixed.fiducialList: self.fixed.fiducialList.RemoveObserver( vtk.vtkCommand.ModifiedEvent) self.fixed.fiducialList.AddObserver(vtk.vtkCommand.ModifiedEvent, self.onMRMLNodeAdded) self.fixed.fiducialList.UpdateScene(newSceneNode) collection = vtk.vtkCollection() self.fixed.fiducialList.GetDirectChildren(collection) print collection.GetNumberOfItems() ###### # create fiducial in volume labeled with fiducial list index # add fiducial to appropriate list # else: # self.createNewFiducial() (i.e. ignore) # if volume is not marked done: # mark volume as done # else: # give warning # if both are marked done: # reset done flag # quit # else: # self.createNewFiducial() # elif right-click: # ignore # elif ESC: # remove latest fiducial if lengths not equal (assumes ordered list!!!) # reset done flags # elif RET: # ignore (both fiducials need to be set (i.e. both flags need to == 'done')) # self.selector.AddNewAnnotationIDToList(self.fixed.newFiducial.GetID()) print "Created a new fiducial node"
def examineForImport(self,fileLists): """ Returns a list of qSlicerDICOMLoadable instances corresponding to ways of interpreting the fileLists parameter. """ import vtkSlicerDicomRtImportExportModuleLogic # Create loadables for each file list loadables = [] for fileList in fileLists: # Each file list corresponds to one series, so do loadables # Convert file list to VTK object to be able to pass it for examining # (VTK class cannot have Qt object as argument, otherwise it is not python wrapped) vtkFileList = vtk.vtkStringArray() for file in fileList: vtkFileList.InsertNextValue(file) # Examine files loadablesCollection = vtk.vtkCollection() slicer.modules.dicomrtimportexport.logic().ExamineForLoad(vtkFileList, loadablesCollection) for loadableIndex in xrange(0,loadablesCollection.GetNumberOfItems()): vtkLoadable = loadablesCollection.GetItemAsObject(loadableIndex) # Create Qt loadable if confidence is greater than 0 if vtkLoadable.GetConfidence() > 0: # Convert to Qt loadable to pass it back qtLoadable = slicer.qSlicerDICOMLoadable() qtLoadable.copyFromVtkLoadable(vtkLoadable) qtLoadable.tooltip = 'Valid RT object in selection' qtLoadable.selected = True loadables.append(qtLoadable) return loadables
def setNewFiducial(self, newSceneNode): # Allow click to set the new fiducial to the list if self.fixed.fiducialList: self.fixed.fiducialList.RemoveObserver(vtk.vtkCommand.ModifiedEvent) self.fixed.fiducialList.AddObserver(vtk.vtkCommand.ModifiedEvent, self.onMRMLNodeAdded) self.fixed.fiducialList.UpdateScene(newSceneNode) collection = vtk.vtkCollection() self.fixed.fiducialList.GetDirectChildren(collection) print collection.GetNumberOfItems() ###### # create fiducial in volume labeled with fiducial list index # add fiducial to appropriate list # else: # self.createNewFiducial() (i.e. ignore) # if volume is not marked done: # mark volume as done # else: # give warning # if both are marked done: # reset done flag # quit # else: # self.createNewFiducial() # elif right-click: # ignore # elif ESC: # remove latest fiducial if lengths not equal (assumes ordered list!!!) # reset done flags # elif RET: # ignore (both fiducials need to be set (i.e. both flags need to == 'done')) # self.selector.AddNewAnnotationIDToList(self.fixed.newFiducial.GetID()) print "Created a new fiducial node"
def convertFiducialHierarchyToVtkIdList(hierarchyNode,volumeNode): ''' ''' outputIds = vtk.vtkIdList() if not hierarchyNode or not volumeNode: return outputIds if isinstance(hierarchyNode,slicer.vtkMRMLAnnotationHierarchyNode) and isinstance(volumeNode,slicer.vtkMRMLScalarVolumeNode): childrenNodes = vtk.vtkCollection() image = volumeNode.GetImageData() hierarchyNode.GetChildrenDisplayableNodes(childrenNodes) # now we have the children which are fiducialNodes - let's loop! for n in range(childrenNodes.GetNumberOfItems()): currentFiducial = childrenNodes.GetItemAsObject(n) currentCoordinatesRAS = [0,0,0] # grab the current coordinates currentFiducial.GetFiducialCoordinates(currentCoordinatesRAS) # convert the RAS to IJK currentCoordinatesIJK = Helper.ConvertRAStoIJK(volumeNode,currentCoordinatesRAS) # strip the last element since we need a 3based tupel currentCoordinatesIJKlist = (int(currentCoordinatesIJK[0]),int(currentCoordinatesIJK[1]),int(currentCoordinatesIJK[2])) outputIds.InsertNextId(int(image.ComputePointId(currentCoordinatesIJKlist))) # IdList was created, return it even if it might be empty return outputIds
def getRulerNodeForVolumeAndStructure(self, volumeId, structureId, createIfNotExist=True, callbackWhenRulerModified=None): """ Search for the right ruler node to be created based on the volume and the selected structure (Aorta or PA). It also creates the necessary node hierarchy if it doesn't exist. :param volumeId: :param structureId: Aorta (1), PA (2) :param createIfNotExist: create the ruler node if it doesn't exist yet :param callbackWhenRulerModified: function to call when the ruler node is modified :return: node and a boolean indicating if the node has been created now """ isNewNode = False if structureId == 0: # none return None, isNewNode if structureId == self.AORTA: # Aorta #nodeName = volumeId + '_paaRulers_aorta' nodeName = "A" elif structureId == self.PA: # 'Pulmonary Arterial': # nodeName = volumeId + '_paaRulers_pa' nodeName = "PA" # Get the node that contains all the rulers for this volume rulersListNode = self.getRulersListNode( volumeId, createIfNotExist=createIfNotExist) node = None if rulersListNode: # Search for the node for i in range(rulersListNode.GetNumberOfChildrenNodes()): nodeWrapper = rulersListNode.GetNthChildNode(i) # nodeWrapper is also a HierarchyNode. We need to look for its only child that will be the rulerNode col = vtk.vtkCollection() nodeWrapper.GetChildrenDisplayableNodes(col) rulerNode = col.GetItemAsObject(0) if rulerNode.GetName() == nodeName: node = rulerNode break if node is None and createIfNotExist: # Create the node # Set the active node, so that the new ruler is a child node annotationsLogic = slicer.modules.annotations.logic() annotationsLogic.SetActiveHierarchyNodeID( rulersListNode.GetID()) node = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLAnnotationRulerNode') node.SetName(nodeName) self.__changeColor__(node, self.defaultColor) slicer.mrmlScene.AddNode(node) isNewNode = True node.AddObserver(vtk.vtkCommand.ModifiedEvent, callbackWhenRulerModified) logging.debug("Created node " + nodeName + " for volume " + volumeId) return node, isNewNode
def RemoveModels(modelHierarchyNode): collection = vtk.vtkCollection() modelHierarchyNode.GetAssociatedChildrenNodes(collection) if collection: nModels = collection.GetNumberOfItems() for i in range(nModels): model = collection.GetItemAsObject(i) slicer.mrmlScene.RemoveNode(model) return True
def __init__(self, fiducialListNode, dl=0.5): import numpy self.dl = dl # desired world space step size (in mm) self.dt = dl # current guess of parametric stepsize self.fids = fiducialListNode # hermite interpolation functions self.h00 = lambda t: 2 * t ** 3 - 3 * t ** 2 + 1 self.h10 = lambda t: t ** 3 - 2 * t ** 2 + t self.h01 = lambda t: -2 * t ** 3 + 3 * t ** 2 self.h11 = lambda t: t ** 3 - t ** 2 # n is the number of control points in the piecewise curve if self.fids.GetClassName() == "vtkMRMLAnnotationHierarchyNode": # slicer4 style hierarchy nodes collection = vtk.vtkCollection() self.fids.GetChildrenDisplayableNodes(collection) self.n = collection.GetNumberOfItems() if self.n == 0: return self.p = numpy.zeros((self.n, 3)) for i in xrange(self.n): f = collection.GetItemAsObject(i) coords = [0, 0, 0] f.GetFiducialCoordinates(coords) self.p[i] = coords else: # slicer3 style fiducial lists self.n = self.fids.GetNumberOfFiducials() n = self.n if n == 0: return # get control point data # sets self.p self.p = numpy.zeros((n, 3)) for i in xrange(n): self.p[i] = self.fids.GetNthFiducialXYZ(i) # calculate the tangent vectors # - fm is forward difference # - m is average of in and out vectors # - first tangent is out vector, last is in vector # - sets self.m n = self.n fm = numpy.zeros((n, 3)) for i in xrange(0, n - 1): fm[i] = self.p[i + 1] - self.p[i] self.m = numpy.zeros((n, 3)) for i in xrange(1, n - 1): self.m[i] = (fm[i - 1] + fm[i]) / 2.0 self.m[0] = fm[0] self.m[n - 1] = fm[n - 2] self.path = [self.p[0]] self.calculatePath()
def __init__(self, fiducialListNode, dl=0.5): import numpy self.dl = dl # desired world space step size (in mm) self.dt = dl # current guess of parametric stepsize self.fids = fiducialListNode # hermite interpolation functions self.h00 = lambda t: 2 * t**3 - 3 * t**2 + 1 self.h10 = lambda t: t**3 - 2 * t**2 + t self.h01 = lambda t: -2 * t**3 + 3 * t**2 self.h11 = lambda t: t**3 - t**2 # n is the number of control points in the piecewise curve if self.fids.GetClassName() == "vtkMRMLAnnotationHierarchyNode": # slicer4 style hierarchy nodes collection = vtk.vtkCollection() self.fids.GetChildrenDisplayableNodes(collection) self.n = collection.GetNumberOfItems() if self.n == 0: return self.p = numpy.zeros((self.n, 3)) for i in xrange(self.n): f = collection.GetItemAsObject(i) coords = [0, 0, 0] f.GetFiducialCoordinates(coords) self.p[i] = coords else: # slicer3 style fiducial lists self.n = self.fids.GetNumberOfFiducials() n = self.n if n == 0: return # get control point data # sets self.p self.p = numpy.zeros((n, 3)) for i in xrange(n): self.p[i] = self.fids.GetNthFiducialXYZ(i) # calculate the tangent vectors # - fm is forward difference # - m is average of in and out vectors # - first tangent is out vector, last is in vector # - sets self.m n = self.n fm = numpy.zeros((n, 3)) for i in xrange(0, n - 1): fm[i] = self.p[i + 1] - self.p[i] self.m = numpy.zeros((n, 3)) for i in xrange(1, n - 1): self.m[i] = (fm[i - 1] + fm[i]) / 2. self.m[0] = fm[0] self.m[n - 1] = fm[n - 2] self.path = [self.p[0]] self.calculatePath()
def __init__(self,pytripCube): self.name = pytripCube.patient_name self.pixel_size = pytripCube.pixel_size self.slice_distance = pytripCube.slice_distance self.dimx = pytripCube.dimx self.dimy = pytripCube.dimy self.dimz = pytripCube.dimz self.vois=[] self.vtkCollection = vtk.vtkCollection() self.filePath=''
def getFiducialSliceDisplayableManagerHelper(self,sliceName='Red'): sliceWidget = slicer.app.layoutManager().sliceWidget(sliceName) sliceView = sliceWidget.sliceView() collection = vtk.vtkCollection() sliceView.getDisplayableManagers(collection) for i in range(collection.GetNumberOfItems()): m = collection.GetItemAsObject(i) if m.GetClassName() == "vtkMRMLMarkupsFiducialDisplayableManager2D": return m.GetHelper() return None
def loadFile(self, title, fileType, nodeComboBox): manager = slicer.app.ioManager() loadedNodes = vtk.vtkCollection() properties = {} res = manager.openDialog(fileType, slicer.qSlicerFileDialog.Read, properties, loadedNodes) loadedNode = loadedNodes.GetItemAsObject(0) if res == True: nodeComboBox.setCurrentNode(loadedNode) self.reset3DViews() return loadedNode
def makeModels(study, finding, colorTable): if (study == None) | (finding == None) | (colorTable == None): return seg = finding.GetSegmentationMappedByStudyNodeID(study.GetID()) if seg: labelVolume = seg.GetLabelVolumeNode() #create a temporary model hierarchy for generating models tempMH = slicer.vtkMRMLModelHierarchyNode() slicer.mrmlScene.AddNode(tempMH) if (labelVolume != None) & (tempMH != None): parameters = {} parameters['InputVolume'] = labelVolume.GetID() parameters['ColorTable'] = colorTable.GetID() parameters['ModelSceneFile'] = tempMH.GetID() parameters['GenerateAll'] = False parameters['StartLabel'] = finding.GetColorID() parameters['EndLabel'] = finding.GetColorID() parameters['Name'] = labelVolume.GetName() + "_" + finding.GetName()+"_M" cliModelMaker = None cliModelMaker = slicer.cli.run(slicer.modules.modelmaker, cliModelMaker, parameters, wait_for_completion = True) genModelNodes = vtk.vtkCollection() tempMH.GetChildrenModelNodes(genModelNodes) if genModelNodes.GetNumberOfItems() > 0: modelNode = genModelNodes.GetItemAsObject(0) if modelNode: if modelNode.IsA('vtkMRMLModelNode'): hnode = slicer.vtkMRMLHierarchyNode.GetAssociatedHierarchyNode(modelNode.GetScene(), modelNode.GetID()) if hnode: if seg.GetModelHierarchyNode(): SlicerLongitudinalPETCTModuleViewHelper.removeModelHierarchyAndChildModelNodesFromScene(seg.GetModelHierarchyNode()) hnode.SetName(seg.GetName()+"_Model") seg.SetAndObserveModelHierarchyNodeID(hnode.GetID()) modelNode.SetName(labelVolume.GetName() + "_" + finding.GetName()+"_M") if modelNode.GetDisplayNode(): modelNode.GetDisplayNode().SetName(labelVolume.GetName() + "_" + finding.GetName()+"_D") modelNode.GetDisplayNode().AddViewNodeID(SlicerLongitudinalPETCTModuleViewHelper.getStandardViewNode().GetID()) hnode.SetName(labelVolume.GetName() + "_" + finding.GetName()+"_H") modelNode.SetHideFromEditors(False) else: seg.SetAndObserveModelHierarchyNodeID("") slicer.mrmlScene.RemoveNode(modelNode) slicer.mrmlScene.RemoveNode(hnode) slicer.mrmlScene.RemoveNode(tempMH.GetDisplayNode()) slicer.mrmlScene.RemoveNode(tempMH)
def volumeFiducialsAsList(self,volumeNode): """return a list of annotation nodes that are children of the list associated with the given volume node""" children = [] listName = volumeNode.GetName() + "-landmarks" fidListHierarchyNode = slicer.util.getNode(listName) if fidListHierarchyNode: childCollection = vtk.vtkCollection() fidListHierarchyNode.GetAllChildren(childCollection) for childIndex in range(childCollection.GetNumberOfItems()): children.append(childCollection.GetItemAsObject(childIndex)) return children
def widgetVisible(self, fidNode, viewNodeID): lm = slicer.app.layoutManager() for v in range(lm.threeDViewCount): td = lm.threeDWidget(v) ms = vtk.vtkCollection() td.getDisplayableManagers(ms) for i in range(ms.GetNumberOfItems()): m = ms.GetItemAsObject(i) if m.GetClassName() == "vtkMRMLMarkupsFiducialDisplayableManager3D" and m.GetMRMLViewNode().GetID() == viewNodeID: h = m.GetHelper() seedWidget = h.GetWidget(fidNode) return seedWidget.GetEnabled() return 0
def removeModelHierarchyAndChildModelNodesFromScene(modelHierarchyNode): if modelHierarchyNode: cmn = vtk.vtkCollection() modelHierarchyNode.GetChildrenModelNodes(cmn) for i in range(cmn.GetNumberOfItems()): model = cmn.GetItemAsObject(i) if model.IsA('vtkMRMLModelNode'): slicer.mrmlScene.RemoveNode(model) slicer.mrmlScene.RemoveNode(modelHierarchyNode)
def getRulerNodeForVolumeAndStructure( self, volumeId, structureId, createIfNotExist=True, callbackWhenRulerModified=None ): """ Search for the right ruler node to be created based on the volume and the selected structure (Aorta or PA). It also creates the necessary node hierarchy if it doesn't exist. :param volumeId: :param structureId: Aorta (1), PA (2) :param createIfNotExist: create the ruler node if it doesn't exist yet :param callbackWhenRulerModified: function to call when the ruler node is modified :return: node and a boolean indicating if the node has been created now """ isNewNode = False if structureId == 0: # none return None, isNewNode if structureId == self.AORTA: # Aorta # nodeName = volumeId + '_paaRulers_aorta' nodeName = "A" elif structureId == self.PA: # 'Pulmonary Arterial': # nodeName = volumeId + '_paaRulers_pa' nodeName = "PA" # Get the node that contains all the rulers for this volume rulersListNode = self.getRulersListNode(volumeId, createIfNotExist=createIfNotExist) node = None if rulersListNode: # Search for the node for i in range(rulersListNode.GetNumberOfChildrenNodes()): nodeWrapper = rulersListNode.GetNthChildNode(i) # nodeWrapper is also a HierarchyNode. We need to look for its only child that will be the rulerNode col = vtk.vtkCollection() nodeWrapper.GetChildrenDisplayableNodes(col) rulerNode = col.GetItemAsObject(0) if rulerNode.GetName() == nodeName: node = rulerNode break if node is None and createIfNotExist: # Create the node # Set the active node, so that the new ruler is a child node annotationsLogic = slicer.modules.annotations.logic() annotationsLogic.SetActiveHierarchyNodeID(rulersListNode.GetID()) node = slicer.mrmlScene.CreateNodeByClass("vtkMRMLAnnotationRulerNode") node.SetName(nodeName) self.__changeColor__(node, self.defaultColor) slicer.mrmlScene.AddNode(node) isNewNode = True node.AddObserver(vtk.vtkCommand.ModifiedEvent, callbackWhenRulerModified) logging.debug("Created node " + nodeName + " for volume " + volumeId) return node, isNewNode
def onAnnotationsFontSizeChanged(self, size): lm = slicer.app.layoutManager() for sliceName in lm.sliceViewNames(): sWidget = lm.sliceWidget(sliceName) sView = sWidget.sliceView() DisplayableManagersCollection = vtk.vtkCollection() sView.getDisplayableManagers(DisplayableManagersCollection) for DisplayableManagersIndex in range( DisplayableManagersCollection.GetNumberOfItems()): AstroDisplayableManager = DisplayableManagersCollection.GetItemAsObject( DisplayableManagersIndex) if AstroDisplayableManager.GetClassName( ) == "vtkMRMLAstroTwoDAxesDisplayableManager": AstroDisplayableManager.SetAnnotationsFontSize(size)
def export(self,exportables): import vtkSlicerDicomRtImportExportModuleLogic from vtkSlicerDICOMLibModuleLogicPython import vtkSlicerDICOMExportable # Convert Qt loadables to VTK ones for the RT export logic exportablesCollection = vtk.vtkCollection() for exportable in exportables: vtkExportable = slicer.vtkSlicerDICOMExportable() exportable.copyToVtkExportable(vtkExportable) exportablesCollection.AddItem(vtkExportable) # Export RT study message = slicer.modules.dicomrtimportexport.logic().ExportDicomRTStudy(exportablesCollection) return message
def widgetVisibleOnSlice(self, fidNode, sliceNodeID): lm = slicer.app.layoutManager() sliceNames = lm.sliceViewNames() for sliceName in sliceNames: sliceWidget = lm.sliceWidget(sliceName) sliceView = sliceWidget.sliceView() ms = vtk.vtkCollection() sliceView.getDisplayableManagers(ms) for i in range(ms.GetNumberOfItems()): m = ms.GetItemAsObject(i) if m.GetClassName() == 'vtkMRMLMarkupsFiducialDisplayableManager2D' and m.GetSliceNode().GetID() == sliceNodeID: h = m.GetHelper() seedWidget = h.GetWidget(fidNode) return seedWidget.GetEnabled() return 0
def TransformModelHierarchy(modelHierarchyNode, transformNode): if not transformNode: return False # modelLabelNode.SetAndObserveTransformNodeID(transformNode.GetID()) # slicer.vtkSlicerTransformLogic.hardenTransform(modelLabelNode) collection = vtk.vtkCollection() modelHierarchyNode.GetAssociatedChildrenNodes(collection) if collection: nModels = collection.GetNumberOfItems() for i in range(nModels): model = collection.GetItemAsObject(i) model.SetAndObserveTransformNodeID(transformNode.GetID()) slicer.vtkSlicerTransformLogic.hardenTransform(model) return True
def volumeFiducialsByName(self,volumeNode): """return a dictionary of annotation nodes that are children of the list associated with the given volume node, where the keys are fiducial names and the values are fiducial nodes""" fiducialsByName = {} listName = volumeNode.GetName() + "-landmarks" fidListHierarchyNode = slicer.util.getNode(listName) if fidListHierarchyNode: childCollection = vtk.vtkCollection() fidListHierarchyNode.GetAllChildren(childCollection) for childIndex in range(childCollection.GetNumberOfItems()): fiducialNode = childCollection.GetItemAsObject(childIndex) fiducialsByName[fiducialNode.GetName()] = fiducialNode return fiducialsByName
def UpdateSelfAndChildMetrics( allMetrics, transformName, absTime, metricsTable ): if ( PythonMetricsCalculatorLogic.GetMRMLScene() == None or PythonMetricsCalculatorLogic.GetPerkEvaluatorLogic() == None ): return # Get the recorded transform node updatedTransformNode = PythonMetricsCalculatorLogic.GetMRMLScene().GetFirstNode( transformName, "vtkMRMLLinearTransformNode", [ False ] ) # TODO: Is there an error in this function? # Get all transforms in the scene transformCollection = vtk.vtkCollection() PythonMetricsCalculatorLogic.GetPerkEvaluatorLogic().GetSceneVisibleTransformNodes( transformCollection ) # Update all metrics associated with children of the recorded transform for i in range( transformCollection.GetNumberOfItems() ): currentTransformNode = transformCollection.GetItemAsObject( i ) if ( PythonMetricsCalculatorLogic.GetPerkEvaluatorLogic().IsSelfOrDescendentTransformNode( updatedTransformNode, currentTransformNode ) ): PythonMetricsCalculatorLogic.UpdateMetrics( allMetrics, currentTransformNode, absTime, metricsTable )
def onAnnotationsColorChanged(self, color): lm = slicer.app.layoutManager() for sliceName in lm.sliceViewNames(): sWidget = lm.sliceWidget(sliceName) sView = sWidget.sliceView() DisplayableManagersCollection = vtk.vtkCollection() sView.getDisplayableManagers(DisplayableManagersCollection) for DisplayableManagersIndex in range( DisplayableManagersCollection.GetNumberOfItems()): AstroDisplayableManager = DisplayableManagersCollection.GetItemAsObject( DisplayableManagersIndex) if AstroDisplayableManager.GetClassName() == "vtkMRMLAstroTwoDAxesDisplayableManager" or \ AstroDisplayableManager.GetClassName() == "vtkMRMLAstroBeamDisplayableManager" : AstroDisplayableManager.SetAnnotationsColor( color.red() / 255., color.green() / 255., color.blue() / 255.)
def populateRulers(self, annotationHierarchy, verterbraeNames): completeVerterbraeNames = [] for verterbraeName in verterbraeNames: completeVerterbraeNames.append(verterbraeName + "-s") completeVerterbraeNames.append(verterbraeName + "-i") if annotationHierarchy != None: rulerNodes = vtk.vtkCollection() annotationHierarchy.GetDirectChildren(rulerNodes) rulerNodeNames = [] for nodeIndex in range(rulerNodes.GetNumberOfItems()): if rulerNodes.GetItemAsObject(nodeIndex).GetClassName( ) == "vtkMRMLAnnotationRulerNode": rulerNodeNames.append( rulerNodes.GetItemAsObject(nodeIndex).GetName()) addedRulerNodesList = [] addedVerterbrae = 200 for completeVerterbraeName in completeVerterbraeNames: if completeVerterbraeName not in rulerNodeNames: newRulerNode = slicer.vtkMRMLAnnotationRulerNode() newRulerNode.SetName(completeVerterbraeName) newRulerNode.SetPosition1(0, addedVerterbrae, 0) newRulerNode.SetPosition2(-300, addedVerterbrae, 0) newRulerNode.SetPointColour([0, 0, 1]) newRulerNode.Initialize(slicer.mrmlScene) annotationHierarchy.SetAndObserveDisplayNodeID( newRulerNode.GetDisplayNodeID()) addedVerterbrae -= 50 addedRulerNodesList.append(newRulerNode) else: addedVerterbrae = 200 for completeVerterbraeName in completeVerterbraeNames: newRulerNode = slicer.vtkMRMLAnnotationRulerNode() newRulerNode.SetName(completeVerterbraeName) newRulerNode.SetPosition1(0, addedVerterbrae, 0) newRulerNode.SetPosition2(-300, addedVerterbrae, 0) newRulerNode.Initialize(slicer.mrmlScene) annotationHierarchy.SetAndObserveDisplayNodeID( newRulerNode.GetDisplayNodeID()) addedVerterbrae -= 50 return addedRulerNodesList
def load(self,loadable): """ Call Reporting logic to load the DICOM SEG object """ print('DICOM SEG load()') labelNodes = vtk.vtkCollection() uid = None try: reportingLogic = slicer.modules.reporting.logic() uid = loadable.uid print 'in load(): uid = ', uid except AttributeError: return False res = False # default color node will be used res = reportingLogic.DicomSegRead(labelNodes, uid) print 'Read this many labels:',labelNodes.GetNumberOfItems() defaultColorNode = reportingLogic.GetDefaultColorNode() for i in range(labelNodes.GetNumberOfItems()): # create and initialize the display node to use default color node displayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLLabelMapVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount()-1) displayNode.SetAndObserveColorNodeID(defaultColorNode.GetID()) slicer.mrmlScene.AddNode(displayNode) # assign it to the label node # this is done here as opposed to Reporting logic to minimize the # dependencies of the DICOM SEG functionality in the Slicer internals labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNode) # create Subject hierarchy nodes for the loaded series self.addSeriesInSubjectHierarchy(loadable, labelNode) return True
def convertFiducialHierarchyToVtkIdList(hierarchyNode, volumeNode): ''' ''' outputIds = vtk.vtkIdList() if not hierarchyNode or not volumeNode: return outputIds if isinstance(hierarchyNode, slicer.vtkMRMLAnnotationHierarchyNode) and isinstance( volumeNode, slicer.vtkMRMLScalarVolumeNode): childrenNodes = vtk.vtkCollection() image = volumeNode.GetImageData() hierarchyNode.GetChildrenDisplayableNodes(childrenNodes) # now we have the children which are fiducialNodes - let's loop! for n in range(childrenNodes.GetNumberOfItems()): currentFiducial = childrenNodes.GetItemAsObject(n) currentCoordinatesRAS = [0, 0, 0] # grab the current coordinates currentFiducial.GetFiducialCoordinates(currentCoordinatesRAS) # convert the RAS to IJK currentCoordinatesIJK = Helper.ConvertRAStoIJK( volumeNode, currentCoordinatesRAS) # strip the last element since we need a 3based tupel currentCoordinatesIJKlist = (int(currentCoordinatesIJK[0]), int(currentCoordinatesIJK[1]), int(currentCoordinatesIJK[2])) outputIds.InsertNextId( int(image.ComputePointId(currentCoordinatesIJKlist))) # IdList was created, return it even if it might be empty return outputIds
def onLabelExport(self): ''' TODO: add a check that the selected label is associated with a volume that has DICOM.instanceUIDs attribute set ''' label = self.segmentationSelector.currentNode() scalar = self.volumeSelector.currentNode() # assuming here the user does the if label == None or scalar == None: self.exportButton.enabled = 0 return labelImage = label.GetImageData() scalarImage = label.GetImageData() lDim = labelImage.GetDimensions() sDim = scalarImage.GetDimensions() if lDim[0]!=sDim[0] or lDim[1]!=sDim[1] or lDim[2]!=sDim[2]: self.__helpLabel.text = 'Geometries do not match' return label = self.segmentationSelector.currentNode() scalar = self.volumeSelector.currentNode() # need to set up the associated node ID label.SetAttribute('AssociatedNodeID', scalar.GetID()) labelCollection = vtk.vtkCollection() labelCollection.AddItem(label) reportingLogic = slicer.modules.reporting.logic() dirName = self.outputDir fileName = reportingLogic.DicomSegWrite(labelCollection, dirName) if fileName == '': self.__helpLabel.text = 'Error!' else: self.__helpLabel.text = 'Exported to '+fileName.split('/')[-1]
def onLabelExport(self): ''' TODO: add a check that the selected label is associated with a volume that has DICOM.instanceUIDs attribute set ''' label = self.segmentationSelector.currentNode() scalar = self.volumeSelector.currentNode() # assuming here the user does the if label == None or scalar == None: self.exportButton.enabled = 0 return labelImage = label.GetImageData() scalarImage = label.GetImageData() lDim = labelImage.GetDimensions() sDim = scalarImage.GetDimensions() if lDim[0] != sDim[0] or lDim[1] != sDim[1] or lDim[2] != sDim[2]: self.__helpLabel.text = 'Geometries do not match' return label = self.segmentationSelector.currentNode() scalar = self.volumeSelector.currentNode() # need to set up the associated node ID label.SetAttribute('AssociatedNodeID', scalar.GetID()) labelCollection = vtk.vtkCollection() labelCollection.AddItem(label) reportingLogic = slicer.modules.reporting.logic() dirName = self.outputDir fileName = reportingLogic.DicomSegWrite(labelCollection, dirName) if fileName == '': self.__helpLabel.text = 'Error!' else: self.__helpLabel.text = 'Exported to ' + fileName.split('/')[-1]
def createFiducialMatrix(self): self.fiducialMatrixStatus = True # extracting the effects of transform parameters transformNode1 = self.templateSelector.currentNode().GetParentTransformNode() #print transformNode1 shiftTransform1 = [0 , 0, 0] rotationTransform1 = [[1, 0,0],[0,1,0],[0,0,1]] #shiftTransform2 = [0, 0, 0] #rotationTransform2 = [1, 0,0],[0,1,0],[0,0,1]] if transformNode1 != None: m = vtk.vtkMatrix4x4() transformNode1.GetMatrixTransformToWorld(m) shiftTransform1 = [ m.GetElement(0,3), m.GetElement(1,3), m.GetElement(2,3) ] rotationTransform1 = [[m.GetElement(0,0), m.GetElement(0,1),m.GetElement(0,2)],[m.GetElement(1,0), m.GetElement(1,1),m.GetElement(1,2)],[m.GetElement(2,0), m.GetElement(2,1),m.GetElement(2,2)]] self.fids = self.inputFiducialsNodeSelector.currentNode(); if self.fids.GetClassName() == "vtkMRMLAnnotationHierarchyNode": # slicer4 style hierarchy nodes collection = vtk.vtkCollection() self.fids.GetChildrenDisplayableNodes(collection) self.n = collection.GetNumberOfItems() if self.n == 0: return self.p = numpy.zeros((self.n,3)) for i in xrange(self.n): f = collection.GetItemAsObject(i) coords = [0,0,0] # Need to change to consider the transform that is applied to the points # offset for template width, moving the needle holes in z direction f.GetFiducialCoordinates(coords) print coords coords = numpy.add(coords,[ 0, 0, self.templateWidth]) print coords self.p[i] = numpy.add(numpy.dot(rotationTransform1,coords),shiftTransform1)
def load(self,loadable): """ Call Reporting logic to load the DICOM SEG object """ print('DICOM SEG load()') labelNodes = vtk.vtkCollection() uid = None try: reportingLogic = slicer.modules.reporting.logic() uid = loadable.uid print 'in load(): uid = ', uid except AttributeError: return False res = False # default color node will be used res = reportingLogic.DicomSegRead(labelNodes, uid) print 'Read this many labels:',labelNodes.GetNumberOfItems() defaultColorNode = reportingLogic.GetDefaultColorNode() for i in range(labelNodes.GetNumberOfItems()): # create and initialize the display node to use default color node displayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLLabelMapVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount()-1) displayNode.SetAndObserveColorNodeID(defaultColorNode.GetID()) slicer.mrmlScene.AddNode(displayNode) # assign it to the label node # this is done here as opposed to Reporting logic to minimize the # dependencies of the DICOM SEG functionality in the Slicer internals labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNode) return True
def start(self, preview=False): ''' ''' SlicerVmtkCommonLib.Helper.Debug("Starting Level Set Segmentation..") # first we need the nodes currentVolumeNode = self.__inputVolumeNodeSelector.currentNode() currentSeedsNode = self.__seedFiducialsNodeSelector.currentNode() currentVesselnessNode = self.__vesselnessVolumeNodeSelector.currentNode( ) currentStoppersNode = self.__stopperFiducialsNodeSelector.currentNode() currentLabelMapNode = self.__outputVolumeNodeSelector.currentNode() currentModelNode = self.__outputModelNodeSelector.currentNode() if not currentVolumeNode: # we need a input volume node return 0 if not currentSeedsNode: # we need a seeds node return 0 if not currentStoppersNode or currentStoppersNode.GetID( ) == currentSeedsNode.GetID(): # we need a current stopper node # self.__stopperFiducialsNodeSelector.addNode() pass if not currentLabelMapNode or currentLabelMapNode.GetID( ) == currentVolumeNode.GetID(): # we need a current labelMap node newLabelMapDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLLabelMapVolumeDisplayNode") newLabelMapDisplayNode.SetScene(slicer.mrmlScene) newLabelMapDisplayNode.SetDefaultColorMap() slicer.mrmlScene.AddNode(newLabelMapDisplayNode) newLabelMapNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLScalarVolumeNode") newLabelMapNode.CopyOrientation(currentVolumeNode) newLabelMapNode.SetScene(slicer.mrmlScene) newLabelMapNode.SetName( slicer.mrmlScene.GetUniqueNameByString( self.__outputVolumeNodeSelector.baseName)) newLabelMapNode.LabelMapOn() newLabelMapNode.SetAndObserveDisplayNodeID( newLabelMapDisplayNode.GetID()) slicer.mrmlScene.AddNode(newLabelMapNode) currentLabelMapNode = newLabelMapNode self.__outputVolumeNodeSelector.setCurrentNode(currentLabelMapNode) if not currentModelNode: # we need a current model node, the display node is created later newModelNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelNode") newModelNode.SetScene(slicer.mrmlScene) newModelNode.SetName( slicer.mrmlScene.GetUniqueNameByString( self.__outputModelNodeSelector.baseName)) slicer.mrmlScene.AddNode(newModelNode) currentModelNode = newModelNode self.__outputModelNodeSelector.setCurrentNode(currentModelNode) # now we need to convert the fiducials to vtkIdLists seeds = SlicerVmtkCommonLib.Helper.convertFiducialHierarchyToVtkIdList( currentSeedsNode, currentVolumeNode) # stoppers = SlicerVmtkCommonLib.Helper.convertFiducialHierarchyToVtkIdList(currentStoppersNode, currentVolumeNode) stoppers = vtk.vtkIdList() # TODO # the input image for the initialization inputImage = vtk.vtkImageData() # check if we have a vesselnessNode - this will be our input for the initialization then if currentVesselnessNode: # yes, there is one inputImage.DeepCopy(currentVesselnessNode.GetImageData()) else: # no, there is none - we use the original image inputImage.DeepCopy(currentVolumeNode.GetImageData()) inputImage.Update() # initialization initImageData = vtk.vtkImageData() # evolution evolImageData = vtk.vtkImageData() # perform the initialization initImageData.DeepCopy(self.GetLogic().performInitialization( inputImage, self.__thresholdSlider.minimumValue, self.__thresholdSlider.maximumValue, seeds, stoppers, 0)) # TODO sidebranch ignore feature initImageData.Update() if not initImageData.GetPointData().GetScalars(): # something went wrong, the image is empty SlicerVmtkCommonLib.Helper.Info( "Segmentation failed - the output was empty..") return -1 # check if it is a preview call if preview: # if this is a preview call, we want to skip the evolution evolImageData.DeepCopy(initImageData) else: # no preview, run the whole thing! we never use the vesselness node here, just the original one evolImageData.DeepCopy(self.GetLogic().performEvolution( currentVolumeNode.GetImageData(), initImageData, self.__iterationSpinBox.value, self.__inflationSlider.value, self.__curvatureSlider.value, self.__attractionSlider.value, 'geodesic')) evolImageData.Update() # create segmentation labelMap labelMap = vtk.vtkImageData() labelMap.DeepCopy(self.GetLogic().buildSimpleLabelMap( evolImageData, 0, 5)) labelMap.Update() currentLabelMapNode.CopyOrientation(currentVolumeNode) # propagate the label map to the node currentLabelMapNode.SetAndObserveImageData(labelMap) currentLabelMapNode.Modified() # deactivate the threshold in the GUI self.resetThresholdOnDisplayNode() # self.onInputVolumeChanged() # show the segmentation results in the GUI selectionNode = slicer.app.applicationLogic().GetSelectionNode() if preview and currentVesselnessNode: # if preview and a vesselnessNode was configured, show it selectionNode.SetReferenceActiveVolumeID( currentVesselnessNode.GetID()) else: # if not preview, show the original volume if currentVesselnessNode: selectionNode.SetReferenceSecondaryVolumeID( currentVesselnessNode.GetID()) selectionNode.SetReferenceActiveVolumeID(currentVolumeNode.GetID()) selectionNode.SetReferenceActiveLabelVolumeID( currentLabelMapNode.GetID()) slicer.app.applicationLogic().PropagateVolumeSelection() # generate 3D model model = vtk.vtkPolyData() # we need the ijkToRas transform for the marching cubes call ijkToRasMatrix = vtk.vtkMatrix4x4() currentLabelMapNode.GetIJKToRASMatrix(ijkToRasMatrix) # call marching cubes model.DeepCopy(self.GetLogic().marchingCubes(evolImageData, ijkToRasMatrix, 0.0)) model.Update() # propagate model to nodes currentModelNode.SetAndObservePolyData(model) currentModelNode.Modified() currentModelDisplayNode = currentModelNode.GetDisplayNode() if not currentModelDisplayNode: # create new displayNode currentModelDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode") slicer.mrmlScene.AddNode(currentModelDisplayNode) # always configure the displayNode to show the model currentModelDisplayNode.SetInputPolyData( currentModelNode.GetPolyData()) currentModelDisplayNode.SetColor(1.0, 0.55, 0.4) # red currentModelDisplayNode.SetBackfaceCulling(0) currentModelDisplayNode.SetSliceIntersectionVisibility(0) currentModelDisplayNode.SetVisibility(1) currentModelDisplayNode.SetOpacity(1.0) currentModelDisplayNode.Modified() # update the reference between model node and it's display node currentModelNode.SetAndObserveDisplayNodeID( currentModelDisplayNode.GetID()) currentModelNode.Modified() # fit slice to all sliceviewers slicer.app.applicationLogic().FitSliceToAll() # jump all sliceViewers to the first fiducial point, if one was used if currentSeedsNode: currentCoordinatesRAS = [0, 0, 0] if isinstance(currentSeedsNode, slicer.vtkMRMLAnnotationHierarchyNode): childrenNodes = vtk.vtkCollection() currentSeedsNode.GetChildrenDisplayableNodes(childrenNodes) # now we have the children, let's get the first one currentFiducial = childrenNodes.GetItemAsObject(0) # grab the current coordinates currentFiducial.GetFiducialCoordinates(currentCoordinatesRAS) elif isinstance(currentSeedsNode, slicer.vtkMRMLAnnotationFiducialNode): # grab the current coordinates currentSeedsNode.GetFiducialCoordinates(currentCoordinatesRAS) numberOfSliceNodes = slicer.mrmlScene.GetNumberOfNodesByClass( 'vtkMRMLSliceNode') for n in xrange(numberOfSliceNodes): sliceNode = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLSliceNode") if sliceNode: sliceNode.JumpSliceByOffsetting(currentCoordinatesRAS[0], currentCoordinatesRAS[1], currentCoordinatesRAS[2]) # center 3D view(s) on the new model if currentCoordinatesRAS: for d in range(slicer.app.layoutManager().threeDViewCount): threeDView = slicer.app.layoutManager().threeDWidget( d).threeDView() # reset the focal point threeDView.resetFocalPoint() # and fly to our seed point interactor = threeDView.interactor() renderer = threeDView.renderWindow().GetRenderers( ).GetItemAsObject(0) interactor.FlyTo(renderer, currentCoordinatesRAS[0], currentCoordinatesRAS[1], currentCoordinatesRAS[2]) SlicerVmtkCommonLib.Helper.Debug("End of Level Set Segmentation..")
def start( self, preview=False ): ''' ''' SlicerVmtkCommonLib.Helper.Debug( "Starting Level Set Segmentation.." ) # first we need the nodes currentVolumeNode = self.__inputVolumeNodeSelector.currentNode() currentSeedsNode = self.__seedFiducialsNodeSelector.currentNode() currentVesselnessNode = self.__vesselnessVolumeNodeSelector.currentNode() currentStoppersNode = self.__stopperFiducialsNodeSelector.currentNode() currentLabelMapNode = self.__outputVolumeNodeSelector.currentNode() currentModelNode = self.__outputModelNodeSelector.currentNode() if not currentVolumeNode: # we need a input volume node return 0 if not currentSeedsNode: # we need a seeds node return 0 if not currentStoppersNode or currentStoppersNode.GetID() == currentSeedsNode.GetID(): # we need a current stopper node # self.__stopperFiducialsNodeSelector.addNode() pass if not currentLabelMapNode or currentLabelMapNode.GetID() == currentVolumeNode.GetID(): # we need a current labelMap node newLabelMapDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLLabelMapVolumeDisplayNode" ) newLabelMapDisplayNode.SetScene( slicer.mrmlScene ) newLabelMapDisplayNode.SetDefaultColorMap() slicer.mrmlScene.AddNode( newLabelMapDisplayNode ) newLabelMapNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLScalarVolumeNode" ) newLabelMapNode.CopyOrientation( currentVolumeNode ) newLabelMapNode.SetScene( slicer.mrmlScene ) newLabelMapNode.SetName( slicer.mrmlScene.GetUniqueNameByString( self.__outputVolumeNodeSelector.baseName ) ) newLabelMapNode.LabelMapOn() newLabelMapNode.SetAndObserveDisplayNodeID( newLabelMapDisplayNode.GetID() ) slicer.mrmlScene.AddNode( newLabelMapNode ) currentLabelMapNode = newLabelMapNode self.__outputVolumeNodeSelector.setCurrentNode( currentLabelMapNode ) if not currentModelNode: # we need a current model node, the display node is created later newModelNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelNode" ) newModelNode.SetScene( slicer.mrmlScene ) newModelNode.SetName( slicer.mrmlScene.GetUniqueNameByString( self.__outputModelNodeSelector.baseName ) ) slicer.mrmlScene.AddNode( newModelNode ) currentModelNode = newModelNode self.__outputModelNodeSelector.setCurrentNode( currentModelNode ) # now we need to convert the fiducials to vtkIdLists seeds = SlicerVmtkCommonLib.Helper.convertFiducialHierarchyToVtkIdList( currentSeedsNode, currentVolumeNode ) # stoppers = SlicerVmtkCommonLib.Helper.convertFiducialHierarchyToVtkIdList(currentStoppersNode, currentVolumeNode) stoppers = vtk.vtkIdList() # TODO # the input image for the initialization inputImage = vtk.vtkImageData() # check if we have a vesselnessNode - this will be our input for the initialization then if currentVesselnessNode: # yes, there is one inputImage.DeepCopy( currentVesselnessNode.GetImageData() ) else: # no, there is none - we use the original image inputImage.DeepCopy( currentVolumeNode.GetImageData() ) inputImage.Update() # initialization initImageData = vtk.vtkImageData() # evolution evolImageData = vtk.vtkImageData() # perform the initialization initImageData.DeepCopy( self.GetLogic().performInitialization( inputImage, self.__thresholdSlider.minimumValue, self.__thresholdSlider.maximumValue, seeds, stoppers, 0 ) ) # TODO sidebranch ignore feature initImageData.Update() if not initImageData.GetPointData().GetScalars(): # something went wrong, the image is empty SlicerVmtkCommonLib.Helper.Info( "Segmentation failed - the output was empty.." ) return -1 # check if it is a preview call if preview: # if this is a preview call, we want to skip the evolution evolImageData.DeepCopy( initImageData ) else: # no preview, run the whole thing! we never use the vesselness node here, just the original one evolImageData.DeepCopy( self.GetLogic().performEvolution( currentVolumeNode.GetImageData(), initImageData, self.__iterationSpinBox.value, self.__inflationSlider.value, self.__curvatureSlider.value, self.__attractionSlider.value, 'geodesic' ) ) evolImageData.Update() # create segmentation labelMap labelMap = vtk.vtkImageData() labelMap.DeepCopy( self.GetLogic().buildSimpleLabelMap( evolImageData, 0, 5 ) ) labelMap.Update() currentLabelMapNode.CopyOrientation( currentVolumeNode ) # propagate the label map to the node currentLabelMapNode.SetAndObserveImageData( labelMap ) currentLabelMapNode.Modified() # deactivate the threshold in the GUI self.resetThresholdOnDisplayNode() # self.onInputVolumeChanged() # show the segmentation results in the GUI selectionNode = slicer.app.applicationLogic().GetSelectionNode() if preview and currentVesselnessNode: # if preview and a vesselnessNode was configured, show it selectionNode.SetReferenceActiveVolumeID( currentVesselnessNode.GetID() ) else: # if not preview, show the original volume if currentVesselnessNode: selectionNode.SetReferenceSecondaryVolumeID( currentVesselnessNode.GetID() ) selectionNode.SetReferenceActiveVolumeID( currentVolumeNode.GetID() ) selectionNode.SetReferenceActiveLabelVolumeID( currentLabelMapNode.GetID() ) slicer.app.applicationLogic().PropagateVolumeSelection() # generate 3D model model = vtk.vtkPolyData() # we need the ijkToRas transform for the marching cubes call ijkToRasMatrix = vtk.vtkMatrix4x4() currentLabelMapNode.GetIJKToRASMatrix( ijkToRasMatrix ) # call marching cubes model.DeepCopy( self.GetLogic().marchingCubes( evolImageData, ijkToRasMatrix, 0.0 ) ) model.Update() # propagate model to nodes currentModelNode.SetAndObservePolyData( model ) currentModelNode.Modified() currentModelDisplayNode = currentModelNode.GetDisplayNode() if not currentModelDisplayNode: # create new displayNode currentModelDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode" ) slicer.mrmlScene.AddNode( currentModelDisplayNode ) # always configure the displayNode to show the model currentModelDisplayNode.SetInputPolyData( currentModelNode.GetPolyData() ) currentModelDisplayNode.SetColor( 1.0, 0.55, 0.4 ) # red currentModelDisplayNode.SetBackfaceCulling( 0 ) currentModelDisplayNode.SetSliceIntersectionVisibility( 0 ) currentModelDisplayNode.SetVisibility( 1 ) currentModelDisplayNode.SetOpacity( 1.0 ) currentModelDisplayNode.Modified() # update the reference between model node and it's display node currentModelNode.SetAndObserveDisplayNodeID( currentModelDisplayNode.GetID() ) currentModelNode.Modified() # fit slice to all sliceviewers slicer.app.applicationLogic().FitSliceToAll() # jump all sliceViewers to the first fiducial point, if one was used if currentSeedsNode: currentCoordinatesRAS = [0, 0, 0] if isinstance( currentSeedsNode, slicer.vtkMRMLAnnotationHierarchyNode ): childrenNodes = vtk.vtkCollection() currentSeedsNode.GetChildrenDisplayableNodes( childrenNodes ) # now we have the children, let's get the first one currentFiducial = childrenNodes.GetItemAsObject( 0 ) # grab the current coordinates currentFiducial.GetFiducialCoordinates( currentCoordinatesRAS ) elif isinstance( currentSeedsNode, slicer.vtkMRMLAnnotationFiducialNode ): # grab the current coordinates currentSeedsNode.GetFiducialCoordinates( currentCoordinatesRAS ) numberOfSliceNodes = slicer.mrmlScene.GetNumberOfNodesByClass( 'vtkMRMLSliceNode' ) for n in xrange( numberOfSliceNodes ): sliceNode = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLSliceNode" ) if sliceNode: sliceNode.JumpSliceByOffsetting( currentCoordinatesRAS[0], currentCoordinatesRAS[1], currentCoordinatesRAS[2] ) # center 3D view(s) on the new model if currentCoordinatesRAS: for d in range( slicer.app.layoutManager().threeDViewCount ): threeDView = slicer.app.layoutManager().threeDWidget( d ).threeDView() # reset the focal point threeDView.resetFocalPoint() # and fly to our seed point interactor = threeDView.interactor() renderer = threeDView.renderWindow().GetRenderers().GetItemAsObject( 0 ) interactor.FlyTo( renderer, currentCoordinatesRAS[0], currentCoordinatesRAS[1], currentCoordinatesRAS[2] ) SlicerVmtkCommonLib.Helper.Debug( "End of Level Set Segmentation.." )
def onRegistrationButtonClicked(self): print "Hello Registration :) " self.referenceAttachmentCollapsibleButton.enabled = True linearTransformExistence = False linearTransformNodes = slicer.util.getNodes('vtkMRMLlinearTransformNode*') for linearTransformNode in linearTransformNodes.keys(): if linearTransformNode=='ModelToTemplateTransform': linearTransformExistence = True if linearTransformExistence == False: followupTransform = slicer.vtkMRMLLinearTransformNode() followupTransform.SetName('ModelToTemplateTransform') followupTransform.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(followupTransform) self.followupTransform = followupTransform self.fiducialListNode = slicer.util.getNode('Template Fiducials') movingLandmarksListID = self.fiducialListNode.GetID() modelFiducials = self.modelFiducialSelector.currentNode() # extracting the effects of transform parameters transformNode1 = self.templateSelector.currentNode().GetParentTransformNode() #print transformNode1 shiftTransform1 = [0 , 0, 0] rotationTransform1 = [[1, 0,0],[0,1,0],[0,0,1]] #shiftTransform2 = [0, 0, 0] #rotationTransform2 = [1, 0,0],[0,1,0],[0,0,1]] if transformNode1 != None: m = vtk.vtkMatrix4x4() transformNode1.GetMatrixTransformToWorld(m) shiftTransform1 = [ m.GetElement(0,3), m.GetElement(1,3), m.GetElement(2,3) ] rotationTransform1 = [[m.GetElement(0,0), m.GetElement(0,1),m.GetElement(0,2)],[m.GetElement(1,0), m.GetElement(1,1),m.GetElement(1,2)],[m.GetElement(2,0), m.GetElement(2,1),m.GetElement(2,2)]] #transformNode2 = transformNode1.GetParentTransformNode() #if transformNode2 != None: #transformNode2.GetMatrixTransformToWorld(m) #shiftTransform2 = [ m.GetElement(0,3), m.GetElement(1,3), m.GetElement(2,3) ] #rotationTransform2 = [[m.GetElement(0,0), m.GetElement(0,1),m.GetElement(0,2)],[m.GetElement(1,0), m.GetElement(1,1),m.GetElement(1,2)],[m.GetElement(2,0), m.GetElement(2,1),m.GetElement(2,2)] #shiftTransform = numpy.add(shiftTransform1,shiftTransform2) # Changing the fiducial coordinates according to the transform if modelFiducials.GetClassName() == "vtkMRMLAnnotationHierarchyNode": # slicer4 style hierarchy nodes collection = vtk.vtkCollection() modelFiducials.GetChildrenDisplayableNodes(collection) n = collection.GetNumberOfItems() if n != 6: return # output an error and ask user to select a fiducial with 6 points listExitence = False hierarchyNodes = slicer.util.getNodes('vtkMRMLAnnotationHierarchyNode*') for hierarchyNode in hierarchyNodes.keys(): if hierarchyNode=='New Model Fiducials': listExitence = True self.newModelFiducialAnnotationList.RemoveAllChildrenNodes() if listExitence == False: newModelFiducialAnnotationList = slicer.vtkMRMLAnnotationHierarchyNode() newModelFiducialAnnotationList.SetName('New Model Fiducials') # hide the fiducial list from the scene newModelFiducialAnnotationList.SetHideFromEditors(1) newModelFiducialAnnotationList.SetScene(self.scene) self.scene.AddNode(newModelFiducialAnnotationList) self.newModelFiducialAnnotationList = newModelFiducialAnnotationList self.logic.SetActiveHierarchyNodeID(self.newModelFiducialAnnotationList.GetID()) #self.logic.AddHierarchy #a=self.logic.GetActiveHierarchyNode() #a.SetName('New Model Fiducials') p = numpy.zeros((n,3)) for i in xrange(n): f = collection.GetItemAsObject(i) coords = [0,0,0] # Need to change to consider the transform that is applied to the points f.GetFiducialCoordinates(coords) newCoords = numpy.add(numpy.dot(rotationTransform1,coords),shiftTransform1) newfid = slicer.vtkMRMLAnnotationFiducialNode() newfid.SetFiducialCoordinates(newCoords) newfid.SetHideFromEditors(0) newfid.SetName(str(i)) self.scene.AddNode(newfid) fixedLandmarksListID = self.newModelFiducialAnnotationList.GetID() self.OutputMessage = "" parameters = {} parameters["fixedLandmarks"] = fixedLandmarksListID parameters["movingLandmarks"] = movingLandmarksListID parameters["saveTransform"] = self.followupTransform parameters["transformType"] = "Rigid" parameters["rms"] = self.RMS parameters["outputMessage"] = self.OutputMessage fidreg = slicer.modules.fiducialregistration self.__cliNode = None self.__cliNode = slicer.cli.run(fidreg, self.__cliNode, parameters) print "RMS is", self.RMS #self.__cliObserverTag = self.__cliNode.AddObserver('ModifiedEvent', self.processRegistrationCompletion) #self.__registrationStatus.setText('Wait ...') #self.firstRegButton.setEnabled(0) stylusNode = self.stylusTrackerSelector.currentNode() stylusNode.SetAndObserveTransformNodeID(self.followupTransform.GetID())
def onCalculateButton(self): logic = SpinalCurvatureMeasurementLogic() (self.superiorAnglesList, self.inferiorAnglesList) = logic.calculateAngles( self.inputSelector.currentNode(), self.projectionPlaneBox.currentText) superiorAnglesListCount = 0 for superiorAngle in self.superiorAnglesList: self.angleTable.item(superiorAnglesListCount, 1).setText(str(superiorAngle)) superiorAnglesListCount += 1 inferiorAnglesListCount = 0 for inferiorAngle in self.inferiorAnglesList: self.angleTable.item(inferiorAnglesListCount, 2).setText(str(inferiorAngle)) inferiorAnglesListCount += 1 # Refresh observers for rulerNode, tag in self.observerTags: rulerNode.RemoveObserver(tag) rulerNodes = vtk.vtkCollection() self.inputSelector.currentNode().GetDirectChildren(rulerNodes) rulerNodesList = [] for nodeIndex in range(rulerNodes.GetNumberOfItems()): if rulerNodes.GetItemAsObject( nodeIndex).GetClassName() == "vtkMRMLAnnotationRulerNode": rulerNodesList.append(rulerNodes.GetItemAsObject(nodeIndex)) for rulerNode in rulerNodesList: def update(caller, ev): import re angle = logic.updateAngle(caller, self.projectionPlaneBox.currentText) rulerName = caller.GetName() #nameSearch.group(1) - Region (C, T, or L) #nameSearch.group(2) - Number (1, 2, 3, etc.) #nameSearch.group(3) - Superior or Inferior (s or i) nameSearch = re.search(r"^([CTL])(\d+)-([si])$", rulerName) if nameSearch != None: if nameSearch.group(1) == "C": index = int(nameSearch.group(2)) - 1 elif nameSearch.group(1) == "T": index = int(nameSearch.group( 2)) + self.CONST_NUMBER_OF_CERVICAL_VERTERBRAE - 1 elif nameSearch.group(1) == "L": index = int( nameSearch.group(2) ) + self.CONST_NUMBER_OF_CERVICAL_VERTERBRAE + self.CONST_NUMBER_OF_THORACIC_VERTERBRAE - 1 if nameSearch.group(3) == "s": self.angleTable.item(index, 1).setText(str(angle)) elif nameSearch.group(3) == "i": self.angleTable.item(index, 2).setText(str(angle)) tag = rulerNode.AddObserver(rulerNode.ControlPointModifiedEvent, update) self.observerTags.append([rulerNode, tag])
def calculateAngles(self, annotationHierarchy, planeOrientation): import re, math superiorCervicalAngles = [None ] * self.CONST_NUMBER_OF_CERVICAL_VERTERBRAE superiorThoracicAngles = [None ] * self.CONST_NUMBER_OF_THORACIC_VERTERBRAE superiorLumbarAngles = [None] * self.CONST_NUMBER_OF_LUMBAR_VERTERBRAE inferiorCervicalAngles = [None ] * self.CONST_NUMBER_OF_CERVICAL_VERTERBRAE inferiorThoracicAngles = [None ] * self.CONST_NUMBER_OF_THORACIC_VERTERBRAE inferiorLumbarAngles = [None] * self.CONST_NUMBER_OF_LUMBAR_VERTERBRAE if planeOrientation == "Coronal": planeNormal = [0, 1, 0] baseAngleVector = [1, 0, 0] elif planeOrientation == "Axial": planeNormal = [0, 0, 1] baseAngleVector = [1, 0, 0] else: planeNormal = [1, 0, 0] baseAngleVector = [0, 1, 0] rulerNodes = vtk.vtkCollection() annotationHierarchy.GetDirectChildren(rulerNodes) rulerNodesList = [] for nodeIndex in range(rulerNodes.GetNumberOfItems()): if rulerNodes.GetItemAsObject( nodeIndex).GetClassName() == "vtkMRMLAnnotationRulerNode": rulerNodesList.append(rulerNodes.GetItemAsObject(nodeIndex)) for ruler in rulerNodesList: angle = self.updateAngle(ruler, planeOrientation) rulerName = ruler.GetName() #nameSearch.group(1) - Region (C, T, or L) #nameSearch.group(2) - Number (1, 2, 3, etc.) #nameSearch.group(3) - Superior or Inferior (s or i) nameSearch = re.search(r"^([CTL])(\d+)-([si])$", rulerName) if nameSearch != None: if nameSearch.group(1) == "C": if nameSearch.group(3) == "s": superiorCervicalAngles[int(nameSearch.group(2)) - 1] = angle elif nameSearch.group(3) == "i": inferiorCervicalAngles[int(nameSearch.group(2)) - 1] = angle elif nameSearch.group(1) == "T": if nameSearch.group(3) == "s": superiorThoracicAngles[int(nameSearch.group(2)) - 1] = angle elif nameSearch.group(3) == "i": inferiorThoracicAngles[int(nameSearch.group(2)) - 1] = angle elif nameSearch.group(1) == "L": if nameSearch.group(3) == "s": superiorLumbarAngles[int(nameSearch.group(2)) - 1] = angle elif nameSearch.group(3) == "i": inferiorLumbarAngles[int(nameSearch.group(2)) - 1] = angle return (superiorCervicalAngles + superiorThoracicAngles + superiorLumbarAngles, inferiorCervicalAngles + inferiorThoracicAngles + inferiorLumbarAngles)
def __init__(self, markersFiducialsNode, targetFiducialNode, entryFiducialNode): self.fids = [markersFiducialsNode, targetFiducialNode, entryFiducialNode] # Get the point's coordinates in the markers, target and entry fiducials self.position = [] #save the points' position for i in range(len(self.fids)): if self.fids[i].GetClassName() == "vtkMRMLAnnotationHierarchyNode": # slicer4 style hierarchy nodes collection = vtk.vtkCollection() self.fids[i].GetChildrenDisplayableNodes(collection) self.n = collection.GetNumberOfItems() if self.n == 0: return self.p = numpy.zeros((self.n,3)) for j in xrange(self.n): f = collection.GetItemAsObject(j) coords = [0,0,0] f.GetFiducialCoordinates(coords) self.p[j] = coords elif self.fids[i].GetClassName() == 'vtkMRMLMarkupsFiducialNode': # slicer4 Markups node self.n = self.fids[i].GetNumberOfFiducials() n = self.n if n == 0: return # get fiducial positions # sets self.p self.p = numpy.zeros((n,3)) for j in xrange(n): coord = [0.0, 0.0, 0.0] self.fids[i].GetNthFiducialPosition(j, coord) self.p[j] = coord else: # slicer3 style fiducial lists self.n = self.fids[i].GetNumberOfFiducials() n = self.n if n == 0: return #sets self.p self.p = numpy.zeros((n,3)) for j in xrange(n): self.p[j] = self.fids[i].GetNthFiducialXYZ(j) self.position.append(self.p) #Vectors of the points and the normals of the reference plane vector1 = self.position[0][0] - self.position[0][1] #a vector in the plane red vector2 = self.position[0][0] - self.position[0][2] #a vector in the plane red normalRed = numpy.cross(vector1,vector2) #normal of the plane red using the 'numpy.cross()' to calculate the cross product of two vector vector3 = self.position[0][3] - self.position[0][4] #a vector in the plane green normalGreen = numpy.cross(vector3, normalRed) #normal of the plane green normalBlue = numpy.cross(normalRed, normalGreen)#normal of the plane blue #Vector of the target and entry point vectorTargetEntry = self.position[1][0] - self.position[2][0]# the vector the target and entry point #Distance between target and entry point distance = round(numpy.linalg.norm(vectorTargetEntry), 1) #Angles between the puncture path and the reference plane sinAngleRed = numpy.abs(numpy.dot(vectorTargetEntry, normalRed)) / (numpy.linalg.norm(normalRed)*numpy.linalg.norm(vectorTargetEntry)) sinAngleGreen = numpy.abs(numpy.dot(vectorTargetEntry, normalGreen)) / (numpy.linalg.norm(normalGreen)*numpy.linalg.norm(vectorTargetEntry)) sinAngleBlue = numpy.abs(numpy.dot(vectorTargetEntry, normalBlue)) / (numpy.linalg.norm(normalBlue)*numpy.linalg.norm(vectorTargetEntry)) angleRed = round(numpy.arcsin(sinAngleRed) / numpy.pi * 180.0, 1) # angle of the puncture path relative to the plane red angleGreen = round(numpy.arcsin(sinAngleGreen) / numpy.pi * 180.0, 1) # angle of the puncture path relative to the plane green angleBlue = round(numpy.arcsin(sinAngleBlue) / numpy.pi * 180.0, 1) # angle of the puncture path relative to the plane blue self.normalRed = normalRed self.normalGreen = normalGreen self.normalBlue = normalBlue self.angleRed = angleRed self.angleGreen = angleGreen self.angleBlue = angleBlue self.distance = distance
def DoIt(inputDir, rgbDir, outputDir): # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm) - dcm.rfind('.dcm') == 4: dcmList.append(inputDir + '/' + dcm) scalarVolumePlugin = slicer.modules.dicomPlugins[ 'DICOMScalarVolumePlugin']() print 'Will examine: ', dcmList indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir) indexer.waitForImportFinished() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' exit() inputVolume = scalarVolumePlugin.load(loadables[0]) sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() ''' sNode.ResetFileNameList() for f in loadables[0].files: sNode.AddFileName(f) sNode.SetFileName(loadables[0].files[0]) sNode.SetSingleFile(0) inputVolume = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(inputVolume) ''' sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir, 'input_volume.nrrd')) sNode.WriteData(inputVolume) # # Order the input RGBs and rename in a temp directory # rgbList = [] for rgb in os.listdir(rgbDir): if len(rgb) - rgb.rfind('.bmp') == 4: rgbList.append(rgb) tmpDir = slicer.app.settings().value('Modules/TemporaryDirectory') tmpDir = tmpDir + '/PNGStackLabelConverter' if not os.path.exists(tmpDir): os.mkdir(tmpDir) oldFiles = os.listdir(tmpDir) # just in case there is anything in that directory for f in oldFiles: os.unlink(tmpDir + '/' + f) rgbOrdered = [None] * len(loadables[0].files) rgbCnt = 0 rgbExt = rgbList[0][rgbList[0].rfind('.') + 1:len(rgbList[0])] print 'Extension for RGBs: ', rgbExt dcmFileList = loadables[0].files rgbRenamedList = [] print 'Number of dcm files: ', len(dcmFileList), ' and rgb files: ', len( rgbOrdered) dcmIdx = 0 for dcm in dcmFileList: rgbIdx = 0 for rgb in rgbList: dcmPrefix = dcm[dcm.rfind('/') + 1:dcm.rfind('.')] if rgb.find(dcmPrefix) != -1: name = string.zfill(str(dcmIdx), 5) rgbCnt = rgbCnt + 1 src = rgbDir + '/' + rgb dest = tmpDir + '/' + name + '.' + rgbExt rgbRenamedList.append(dest) shutil.copy(src, dest) break rgbIdx = rgbIdx + 1 # remove the matched DICOM file from the list if rgbIdx == len(rgbList): print('ERROR: failed to find matching label file for DICOM file ' + dcm) return del rgbList[rgbIdx] dcmIdx = dcmIdx + 1 if len(rgbRenamedList) == 0: print 'Could not parse the DICOM Study!' return sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList() for f in rgbRenamedList: sNode.AddFileName(f) sNode.SetFileName(rgbRenamedList[0]) sNode.SetSingleFile(0) inputRGBVolume = slicer.vtkMRMLVectorVolumeNode() sNode.ReadData(inputRGBVolume) # run the filter # - extract the RGB portions extract = vtk.vtkImageExtractComponents() extract.SetComponents(0, 1, 2) if vtk.vtkVersion().GetVTKMajorVersion() < 6: extract.SetInput(inputRGBVolume.GetImageData()) else: extract.SetInputData(inputRGBVolume.GetImageData()) luminance = vtk.vtkImageLuminance() if vtk.vtkVersion().GetVTKMajorVersion() < 6: luminance.SetInput(extract.GetOutput()) else: luminance.SetInputData(extract.GetOutput()) cast = vtk.vtkImageCast() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(luminance.GetOutput()) else: cast.SetInputData(luminance.GetOutput()) cast.SetOutputScalarTypeToShort() cast.GetOutput().Update() ijkToRAS = vtk.vtkMatrix4x4() inputVolume.GetIJKToRASMatrix(ijkToRAS) outputLabel = slicer.vtkMRMLLabelMapVolumeNode() outputLabel.SetIJKToRASMatrix(ijkToRAS) outputLabel.SetAndObserveImageData(cast.GetOutput()) reportingLogic = slicer.modules.reporting.logic() displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID( reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) outputLabel.SetAndObserveDisplayNodeID(displayNode.GetID()) sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir, 'label_output.nrrd')) sNode.WriteData(outputLabel) # save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(outputLabel) slicer.mrmlScene.AddNode(inputVolume) outputLabel.SetAttribute('AssociatedNodeID', inputVolume.GetID()) slicer.mrmlScene.AddNode(outputLabel) # initialize the DICOM DB for Reporting logic settings = qt.QSettings() dbFileName = settings.value('DatabaseDirectory', '') if dbFileName == '': print('ERROR: database must be initialized') else: dbFileName = dbFileName + '/ctkDICOM.sql' reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir)
def LoadAIMFile(newReportID, fileName): dom = xml.dom.minidom.parse(fileName) SlicerReportingModuleWidgetHelper.Debug('Parsed AIM report:') SlicerReportingModuleWidgetHelper.Debug(dom.toxml()) volumeList = [] ddb = slicer.dicomDatabase volId = 1 volume = None # get the annotation element and retrieve its name annotations = dom.getElementsByTagName('ImageAnnotation') if len(annotations) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM file does not contain any annotations!') return ann = annotations[0] desc = ann.getAttribute('name') # get the anatomic entity element and initialize the report node based on # it anatomics = dom.getElementsByTagName('AnatomicEntity') if len(anatomics) != 1: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM file does not contain any anatomic entities or contains more than one! This is not supported.') return anatomy = anatomics[0] labelValue = anatomy.getAttribute('codeValue') labelName = anatomy.getAttribute('codeMeaning') codingSchemeDesignator = anatomy.getAttribute('codingSchemeDesignator') if codingSchemeDesignator != '3DSlicer': SlicerReportingModuleWidgetHelper.WarningPopup('Code scheme designator '+codingSchemeDesignator+' is not supported. Default will be used instead.') labelValue = "1" newReport = slicer.mrmlScene.GetNodeByID(newReportID) newReport.SetFindingLabel(int(labelValue)) # pull all the volumes that are referenced into the scene for node in dom.getElementsByTagName('ImageSeries'): instanceUID = node.getAttribute('instanceUID') filelist = ddb.filesForSeries(instanceUID) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() scalarVolumeLoadables = scalarVolumePlugin.examine([filelist]) if len(scalarVolumeLoadables) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup('Error loading AIM: Failed to load the volume node reference in the file') volumeName = scalarVolumeLoadables[0].name newReport.SetName('Report for Volume '+volumeName) volume = scalarVolumePlugin.load(scalarVolumeLoadables[0]) volume.SetName(volumeName) if volume == None: SlicerReportingModuleWidgetHelper.Error('Failed to read series!') return if len(volumeList) != 0: SlicerReportingModuleWidgetHelper.ErrorPopup('Error importing AIM report: Report references more than one volume, which is not allowed!') return volumeList.append(volume) SlicerReportingModuleWidgetHelper.Debug('Volume read from AIM report:') slicer.modules.reporting.logic().AddVolumeToReport(volume) newReport.SetVolumeNodeID(volume.GetID()) if len(volumeList) > 1: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM does not allow to have more than one volume per file!') return if len(volumeList) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM file you requested to load does not reference any volumes, cannot process it!') return #if volume != None: # self.__volumeSelector.setCurrentNode(volume) instanceUIDs = volume.GetAttribute('DICOM.instanceUIDs') instanceUIDList = instanceUIDs.split() # AF: GeometricShape is inside geometricShapeCollection, but # there's no need to parse at that level, I think # # geometricShapeCollection # | # +-spatialCoordinateCollection # | # +-SpatialCoordinate # for node in dom.getElementsByTagName('GeometricShape'): ijCoordList = [] rasPointList = [] uidList = [] elementType = node.getAttribute('xsi:type') for child in node.childNodes: if child.nodeName == 'spatialCoordinateCollection': for coord in child.childNodes: if coord.nodeName == 'SpatialCoordinate': ijCoordList.append(float(coord.getAttribute('x'))) ijCoordList.append(float(coord.getAttribute('y'))) uid = coord.getAttribute('imageReferenceUID') uidList.append(uid) SlicerReportingModuleWidgetHelper.Debug('Coordinate list: '+str(ijCoordList)) ijk2ras = vtk.vtkMatrix4x4() volume.GetIJKToRASMatrix(ijk2ras) # convert each point from IJ to RAS for ij in range(len(uidList)): pointUID = uidList[ij] # locate the UID in the list assigned to the volume totalSlices = len(instanceUIDList) for k in range(len(instanceUIDList)): if pointUID == instanceUIDList[k]: break # print "k = ",k,", totalSlices = ",totalSlices pointIJK = [ijCoordList[ij*2], ijCoordList[ij*2+1], k, 1.] pointRAS = ijk2ras.MultiplyPoint(pointIJK) SlicerReportingModuleWidgetHelper.Debug('Input point: '+str(pointIJK)) SlicerReportingModuleWidgetHelper.Debug('Converted point: '+str(pointRAS)) rasPointList.append(pointRAS[0:3]) # instantiate the markup elements if elementType == 'Point': SlicerReportingModuleWidgetHelper.Debug("Importing a fiducial!") if len(ijCoordList) != 2: SlicerReportingModuleWidgetHelper.Error('Number of coordinates not good for a fiducial') return fiducial = slicer.mrmlScene.CreateNodeByClass('vtkMRMLAnnotationFiducialNode') fiducial.SetReferenceCount(fiducial.GetReferenceCount()-1) # associate it with the report fiducial.SetAttribute('ReportingReportNodeID', newReport.GetID()) # associate it with the volume fiducial.SetAttribute('AssociatedNodeID', volume.GetID()) # ??? Why the API is so inconsistent -- there's no SetPosition1() ??? fiducial.SetFiducialCoordinates(rasPointList[0]) fiducial.Initialize(slicer.mrmlScene) # adding to hierarchy is handled by the Reporting logic if elementType == 'MultiPoint': SlicerReportingModuleWidgetHelper.Debug("Importing a ruler!") if len(ijCoordList) != 4: SlicerReportingModuleWidgetHelper.Error('Number of coordinates not good for a ruler') return ruler = slicer.mrmlScene.CreateNodeByClass('vtkMRMLAnnotationRulerNode') ruler.SetReferenceCount(ruler.GetReferenceCount()-1) # associate it with the report ruler.SetAttribute('ReportingReportNodeID', newReport.GetID()) # associate it with the volume ruler.SetAttribute('AssociatedNodeID', volume.GetID()) SlicerReportingModuleWidgetHelper.Debug('Initializing with points '+str(rasPointList[0])+' and '+str(rasPointList[1])) ruler.SetPosition1(rasPointList[0]) ruler.SetPosition2(rasPointList[1]) ruler.Initialize(slicer.mrmlScene) # AF: Initialize() adds to the scene ... for node in dom.getElementsByTagName('Segmentation'): # read all labels that are available in the SEG object # check if the referenced volume is already in the scene # if not, load it # initialize AssociatedNodeID for the label node to point to the # reference SlicerReportingModuleWidgetHelper.Debug('Importing a segmentation') labelNodes = vtk.vtkCollection() referenceNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLScalarVolumeNode') referenceNode.SetReferenceCount(referenceNode.GetReferenceCount()-1) uid = node.getAttribute('sopInstanceUID') res = False colorNode = slicer.mrmlScene.GetNodeByID(newReport.GetColorNodeID()) res = slicer.modules.reporting.logic().DicomSegRead(labelNodes, uid, colorNode) SlicerReportingModuleWidgetHelper.Debug('Read this many labels from the seg object:'+str(labelNodes.GetNumberOfItems())) if labelNodes.GetNumberOfItems() == 0: print("Error loading segmentation object, have 0 labels") else: # read the reference node label0 = labelNodes.GetItemAsObject(0) referenceUIDs = label0.GetAttribute('DICOM.referenceInstanceUIDs') SlicerReportingModuleWidgetHelper.Debug('Seg object reference uids: '+referenceUIDs) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLLabelMapVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount()-1) displayNode.SetAndObserveColorNodeID(newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('ReportingReportNodeID', newReport.GetID()) labelNode.SetAttribute('AssociatedNodeID', volumeList[0].GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNode) # AF: this shuould not be necessary with the "proper" AIM input, since # only one volume should be present in the report, and only one item in # that volume should be annotated if 0: # if referenceUIDs != None: reader = slicer.vtkMRMLVolumeArchetypeStorageNode() reader.ResetFileNameList() for uid in string.split(referenceUIDs, ' '): fname = slicer.modules.reporting.logic().GetFileNameFromUID(uid) reader.AddFileName(fname) reader.SetFileName(string.split(referenceUIDs, ' ')[0]) reader.SetSingleFile(0) referenceVolume = slicer.mrmlScene.CreateNodeByClass('vtkMRMLScalarVolumeNode') referenceVolumeUIDs = referenceVolume.GetAttribute('DICOM.instanceUIDs') reader.ReadData(referenceVolume) nodeToAdd = referenceVolume allVolumeNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLScalarVolumeNode') allVolumeNodes.SetReferenceCount(allVolumeNodes.GetReferenceCount()-1) for i in range(allVolumeNodes.GetNumberOfItems()): v = allVolumeNodes.GetItemAsObject(i) uids = v.GetAttribute('DICOM.instanceUIDs') if uids == referenceNodeUIDs: print('Referenced node is already in the scene!') nodeToAdd = None referenceNode = v break if nodeToAdd != None: slicer.mrmlScene.AddNode(nodeToAdd) slicer.modules.reporting.logic().AddVolumeToReport(referenceNode) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLScalarVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount()-1) displayNode.SetAndObserveColorNodeID(newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('ReportingReportNodeID', newReport.GetID()) labelNode.SetAttribute('AssociatedNodeID', referenceNode.GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNodes.GetItemAsObject(i))
def LoadAIMFile(newReportID, fileName): dom = xml.dom.minidom.parse(fileName) SlicerReportingModuleWidgetHelper.Debug('Parsed AIM report:') SlicerReportingModuleWidgetHelper.Debug(dom.toxml()) volumeList = [] ddb = slicer.dicomDatabase volId = 1 volume = None # get the annotation element and retrieve its name annotations = dom.getElementsByTagName('ImageAnnotation') if len(annotations) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM file does not contain any annotations!') return ann = annotations[0] desc = ann.getAttribute('name') # get the anatomic entity element and initialize the report node based on # it anatomics = dom.getElementsByTagName('AnatomicEntity') if len(anatomics) != 1: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM file does not contain any anatomic entities or contains more than one! This is not supported.' ) return anatomy = anatomics[0] labelValue = anatomy.getAttribute('codeValue') labelName = anatomy.getAttribute('codeMeaning') codeSchemeDesignator = anatomy.getAttribute('codeSchemeDesignator') if codeSchemeDesignator != '3DSlicer': SlicerReportingModuleWidgetHelper.WarningPopup( 'Code scheme designator ' + codeSchemeDesignator + ' is not supported. Default will be used instead.') labelValue = "1" newReport = slicer.mrmlScene.GetNodeByID(newReportID) newReport.SetFindingLabel(int(labelValue)) # pull all the volumes that are referenced into the scene for node in dom.getElementsByTagName('ImageSeries'): instanceUID = node.getAttribute('instanceUID') filelist = ddb.filesForSeries(instanceUID) scalarVolumePlugin = slicer.modules.dicomPlugins[ 'DICOMScalarVolumePlugin']() scalarVolumeLoadables = scalarVolumePlugin.examine([filelist]) if len(scalarVolumeLoadables) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'Error loading AIM: Failed to load the volume node reference in the file' ) volumeName = scalarVolumeLoadables[0].name newReport.SetName('Report for Volume ' + volumeName) volume = scalarVolumePlugin.load(scalarVolumeLoadables[0]) volume.SetName(volumeName) if volume == None: SlicerReportingModuleWidgetHelper.Error( 'Failed to read series!') return if len(volumeList) != 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'Error importing AIM report: Report references more than one volume, which is not allowed!' ) return volumeList.append(volume) SlicerReportingModuleWidgetHelper.Debug( 'Volume read from AIM report:') slicer.modules.reporting.logic().InitializeHierarchyForVolume( volume) newReport.SetVolumeNodeID(volume.GetID()) if len(volumeList) > 1: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM does not allow to have more than one volume per file!') return if len(volumeList) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM file you requested to load does not reference any volumes, cannot process it!' ) return #if volume != None: # self.__volumeSelector.setCurrentNode(volume) instanceUIDs = volume.GetAttribute('DICOM.instanceUIDs') instanceUIDList = instanceUIDs.split() # AF: GeometricShape is inside geometricShapeCollection, but # there's no need to parse at that level, I think # # geometricShapeCollection # | # +-spatialCoordinateCollection # | # +-SpatialCoordinate # for node in dom.getElementsByTagName('GeometricShape'): ijCoordList = [] rasPointList = [] uidList = [] elementType = node.getAttribute('xsi:type') for child in node.childNodes: if child.nodeName == 'spatialCoordinateCollection': for coord in child.childNodes: if coord.nodeName == 'SpatialCoordinate': ijCoordList.append(float(coord.getAttribute('x'))) ijCoordList.append(float(coord.getAttribute('y'))) uid = coord.getAttribute('imageReferenceUID') uidList.append(uid) SlicerReportingModuleWidgetHelper.Debug('Coordinate list: ' + str(ijCoordList)) ijk2ras = vtk.vtkMatrix4x4() volume.GetIJKToRASMatrix(ijk2ras) # convert each point from IJ to RAS for ij in range(len(uidList)): pointUID = uidList[ij] # locate the UID in the list assigned to the volume totalSlices = len(instanceUIDList) for k in range(len(instanceUIDList)): if pointUID == instanceUIDList[k]: break # print "k = ",k,", totalSlices = ",totalSlices pointIJK = [ ijCoordList[ij * 2], ijCoordList[ij * 2 + 1], k, 1. ] pointRAS = ijk2ras.MultiplyPoint(pointIJK) SlicerReportingModuleWidgetHelper.Debug('Input point: ' + str(pointIJK)) SlicerReportingModuleWidgetHelper.Debug('Converted point: ' + str(pointRAS)) rasPointList.append(pointRAS[0:3]) # instantiate the markup elements if elementType == 'Point': SlicerReportingModuleWidgetHelper.Debug( "Importing a fiducial!") if len(ijCoordList) != 2: SlicerReportingModuleWidgetHelper.Error( 'Number of coordinates not good for a fiducial') return fiducial = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLAnnotationFiducialNode') fiducial.SetReferenceCount(fiducial.GetReferenceCount() - 1) # associate it with the volume fiducial.SetAttribute("AssociatedNodeID", volume.GetID()) # ??? Why the API is so inconsistent -- there's no SetPosition1() ??? fiducial.SetFiducialCoordinates(rasPointList[0]) fiducial.Initialize(slicer.mrmlScene) # adding to hierarchy is handled by the Reporting logic if elementType == 'MultiPoint': SlicerReportingModuleWidgetHelper.Debug("Importing a ruler!") if len(ijCoordList) != 4: SlicerReportingModuleWidgetHelper.Error( 'Number of coordinates not good for a ruler') return ruler = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLAnnotationRulerNode') ruler.SetReferenceCount(ruler.GetReferenceCount() - 1) # associate it with the volume ruler.SetAttribute("AssociatedNodeID", volume.GetID()) SlicerReportingModuleWidgetHelper.Debug( 'Initializing with points ' + str(rasPointList[0]) + ' and ' + str(rasPointList[1])) ruler.SetPosition1(rasPointList[0]) ruler.SetPosition2(rasPointList[1]) ruler.Initialize(slicer.mrmlScene) # AF: Initialize() adds to the scene ... for node in dom.getElementsByTagName('Segmentation'): # read all labels that are available in the SEG object # check if the referenced volume is already in the scene # if not, load it # initialize AssociatedNodeID for the label node to point to the # reference SlicerReportingModuleWidgetHelper.Debug('Importing a segmentation') labelNodes = vtk.vtkCollection() referenceNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLScalarVolumeNode') referenceNode.SetReferenceCount(referenceNode.GetReferenceCount() - 1) uid = node.getAttribute('sopInstanceUID') res = False colorNode = slicer.mrmlScene.GetNodeByID( newReport.GetColorNodeID()) res = slicer.modules.reporting.logic().DicomSegRead( labelNodes, uid, colorNode) SlicerReportingModuleWidgetHelper.Debug( 'Read this many labels from the seg object:' + str(labelNodes.GetNumberOfItems())) # read the reference node label0 = labelNodes.GetItemAsObject(0) referenceUIDs = label0.GetAttribute('DICOM.referenceInstanceUIDs') SlicerReportingModuleWidgetHelper.Debug( 'Seg object reference uids: ' + referenceUIDs) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLLabelMapVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount() - 1) displayNode.SetAndObserveColorNodeID( newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('AssociatedNodeID', volumeList[0].GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNode) # AF: this shuould not be necessary with the "proper" AIM input, since # only one volume should be present in the report, and only one item in # that volume should be annotated if 0: # if referenceUIDs != None: reader = slicer.vtkMRMLVolumeArchetypeStorageNode() reader.ResetFileNameList() for uid in string.split(referenceUIDs, ' '): fname = slicer.modules.reporting.logic( ).GetFileNameFromUID(uid) reader.AddFileName(fname) reader.SetFileName(string.split(referenceUIDs, ' ')[0]) reader.SetSingleFile(0) referenceVolume = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLScalarVolumeNode') referenceVolumeUIDs = referenceVolume.GetAttribute( 'DICOM.instanceUIDs') reader.ReadData(referenceVolume) nodeToAdd = referenceVolume allVolumeNodes = slicer.mrmlScene.GetNodesByClass( 'vtkMRMLScalarVolumeNode') allVolumeNodes.SetReferenceCount( allVolumeNodes.GetReferenceCount() - 1) for i in range(allVolumeNodes.GetNumberOfItems()): v = allVolumeNodes.GetItemAsObject(i) uids = v.GetAttribute('DICOM.instanceUIDs') if uids == referenceNodeUIDs: print('Referenced node is already in the scene!') nodeToAdd = None referenceNode = v break if nodeToAdd != None: slicer.mrmlScene.AddNode(nodeToAdd) slicer.modules.reporting.logic().InitializeHierarchyForVolume( referenceNode) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLScalarVolumeDisplayNode') displayNode.SetReferenceCount( displayNode.GetReferenceCount() - 1) displayNode.SetAndObserveColorNodeID( newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('AssociatedNodeID', referenceNode.GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNodes.GetItemAsObject(i))
def DoIt(inputDir, rgbDir, outputDir): # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(inputDir+'/'+dcm) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() print 'Will examine: ',dcmList indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir) indexer.waitForImportFinished() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' exit() inputVolume = scalarVolumePlugin.load(loadables[0]) sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() ''' sNode.ResetFileNameList() for f in loadables[0].files: sNode.AddFileName(f) sNode.SetFileName(loadables[0].files[0]) sNode.SetSingleFile(0) inputVolume = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(inputVolume) ''' sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir,'input_volume.nrrd')) sNode.WriteData(inputVolume) # # Order the input RGBs and rename in a temp directory # rgbList = [] for rgb in os.listdir(rgbDir): if len(rgb)-rgb.rfind('.bmp') == 4: rgbList.append(rgb) tmpDir = slicer.app.settings().value('Modules/TemporaryDirectory') tmpDir = tmpDir+'/PNGStackLabelConverter' if not os.path.exists(tmpDir): os.mkdir(tmpDir) oldFiles = os.listdir(tmpDir) # just in case there is anything in that directory for f in oldFiles: os.unlink(tmpDir+'/'+f) rgbOrdered = [None] * len(loadables[0].files) rgbCnt = 0 rgbExt = rgbList[0][rgbList[0].rfind('.')+1:len(rgbList[0])] print 'Extension for RGBs: ',rgbExt dcmFileList = loadables[0].files rgbRenamedList = [] print 'Number of dcm files: ',len(dcmFileList), ' and rgb files: ',len(rgbOrdered) dcmIdx = 0 for dcm in dcmFileList: rgbIdx = 0 for rgb in rgbList: dcmPrefix = dcm[dcm.rfind('/')+1:dcm.rfind('.')] if rgb.find(dcmPrefix) != -1: name = string.zfill(str(dcmIdx),5) rgbCnt = rgbCnt+1 src = rgbDir+'/'+rgb dest = tmpDir+'/'+name+'.'+rgbExt rgbRenamedList.append(dest) shutil.copy(src,dest) break rgbIdx = rgbIdx+1 # remove the matched DICOM file from the list if rgbIdx == len(rgbList): print('ERROR: failed to find matching label file for DICOM file '+dcm) return del rgbList[rgbIdx] dcmIdx = dcmIdx+1 if len(rgbRenamedList) == 0: print 'Could not parse the DICOM Study!' return sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList() for f in rgbRenamedList: sNode.AddFileName(f) sNode.SetFileName(rgbRenamedList[0]) sNode.SetSingleFile(0) inputRGBVolume = slicer.vtkMRMLVectorVolumeNode() sNode.ReadData(inputRGBVolume) # run the filter # - extract the RGB portions extract = vtk.vtkImageExtractComponents() extract.SetComponents(0,1,2) if vtk.vtkVersion().GetVTKMajorVersion() < 6: extract.SetInput(inputRGBVolume.GetImageData()) else: extract.SetInputData(inputRGBVolume.GetImageData()) luminance = vtk.vtkImageLuminance() if vtk.vtkVersion().GetVTKMajorVersion() < 6: luminance.SetInput(extract.GetOutput()) else: luminance.SetInputData(extract.GetOutput()) cast = vtk.vtkImageCast() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(luminance.GetOutput()) else: cast.SetInputData(luminance.GetOutput()) cast.SetOutputScalarTypeToShort() cast.GetOutput().Update() ijkToRAS = vtk.vtkMatrix4x4() inputVolume.GetIJKToRASMatrix(ijkToRAS) outputLabel = slicer.vtkMRMLLabelMapVolumeNode() outputLabel.SetIJKToRASMatrix(ijkToRAS) outputLabel.SetAndObserveImageData(cast.GetOutput()) reportingLogic = slicer.modules.reporting.logic() displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID(reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) outputLabel.SetAndObserveDisplayNodeID(displayNode.GetID()) sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir,'label_output.nrrd')) sNode.WriteData(outputLabel) # save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(outputLabel) slicer.mrmlScene.AddNode(inputVolume) outputLabel.SetAttribute('AssociatedNodeID',inputVolume.GetID()) slicer.mrmlScene.AddNode(outputLabel) # initialize the DICOM DB for Reporting logic settings = qt.QSettings() dbFileName = settings.value('DatabaseDirectory','') if dbFileName =='': print('ERROR: database must be initialized') else: dbFileName = dbFileName +'/ctkDICOM.sql' reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir)
def DoIt(inputDir, labelFile, outputDir, forceLabel, forceResample): dbDir1 = slicer.app.temporaryPath+'/LabelConverter' if not hasattr(slicer.modules, 'reporting'): print 'The Reporting module has not been loaded into Slicer, script cannot run!\n\tTry setting the --additional-module-path parameter.' sys.exit(1) reportingLogic = slicer.modules.reporting.logic() print('Temporary directory location: '+dbDir1) qt.QDir().mkpath(dbDir1) dbDir0 = None if slicer.dicomDatabase: dbDir0 = os.path.split(slicer.dicomDatabase.databaseFilename)[0] dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(dbDir1) # import DICOM study indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir, None) indexer.waitForImportFinished() print('DICOM import finished!') # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(inputDir+'/'+dcm) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' sys.exit(1) inputVolume = scalarVolumePlugin.load(loadables[0]) print 'Input volume loaded! ID = ', inputVolume.GetID() # read the label volume labelVolume = slicer.vtkMRMLLabelMapVolumeNode() sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.SetFileName(labelFile) sNode.ReadData(labelVolume) if forceLabel>0: # print('Forcing label to '+str(forceLabel)) labelImage = labelVolume.GetImageData() thresh = vtk.vtkImageThreshold() if vtk.vtkVersion().GetVTKMajorVersion() < 6: thresh.SetInput(labelImage) else: thresh.SetInputData(labelImage) thresh.ThresholdBetween(1, labelImage.GetScalarRange()[1]) thresh.SetInValue(int(forceLabel)) thresh.SetOutValue(0) thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.Update() labelImage = thresh.GetOutput() labelVolume.SetAndObserveImageData(labelImage) slicer.mrmlScene.AddNode(labelVolume) print 'Label volume added, id = ', labelVolume.GetID() # ensure that the label volume scalar type is unsigned short if labelVolume.GetImageData() != None: scalarType = labelVolume.GetImageData().GetScalarType() if scalarType != vtk.VTK_UNSIGNED_SHORT: print 'Label volume has pixel type of ',vtk.vtkImageScalarTypeNameMacro(scalarType),', casting to unsigned short' cast = vtk.vtkImageCast() cast.SetOutputScalarTypeToUnsignedShort() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(labelVolume.GetImageData()) cast.Update() labelVolume.SetAndObserveImageData(cast.GetOutput()) else: cast.SetInputConnection(labelVolume.GetImageDataConnection()) cast.Update() labelVolume.SetImageDataConnection(cast.GetOutputPort()) if labelVolume.GetImageData().GetScalarType() != vtk.VTK_UNSIGNED_SHORT: print 'Failed to cast label volume to unsigned short, type is ', vtk.vtkImageScalarTypeNameMacro(labelVolume.GetImageData().GetScalarType()) sys.exit(1) volumesLogic = slicer.modules.volumes.logic() geometryCheckString = volumesLogic.CheckForLabelVolumeValidity(inputVolume, labelVolume) if geometryCheckString != "": # has the user specified that forced resampling is okay? if forceResample == False: print 'Label volume mismatch with input volume:\n',geometryCheckString,'\nForced resample not specified, aborting. Re-run with --force option to ignore geometric inconsistencies' sys.exit(1) # resample label to the input volume raster resampledLabel = slicer.vtkMRMLLabelMapVolumeNode() slicer.mrmlScene.AddNode(resampledLabel) print 'Resampled label added, id = ', resampledLabel.GetID() resampledLabel = volumesLogic.ResampleVolumeToReferenceVolume(labelVolume, inputVolume) labelVolume = resampledLabel displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID(reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) labelVolume.SetAttribute('AssociatedNodeID',inputVolume.GetID()) labelVolume.SetAndObserveDisplayNodeID(displayNode.GetID()) # initialize the DICOM DB for Reporting logic, save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(labelVolume) print('About to write DICOM SEG!') dbFileName = slicer.dicomDatabase.databaseFilename reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir) dicomWidget.onDatabaseDirectoryChanged(dbDir0) exit()
def DoIt(inputDir, labelFile, outputDir, forceLabel): dbDir1 = slicer.app.temporaryPath+'/LabelConverter' reportingLogic = slicer.modules.reporting.logic() print('Temporary directory location: '+dbDir1) qt.QDir().mkpath(dbDir1) dbDir0 = None if slicer.dicomDatabase: dbDir0 = os.path.split(slicer.dicomDatabase.databaseFilename)[0] try: dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(dbDir1) # import DICOM study indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir, None) indexer.waitForImportFinished() print('DICOM import finished!') # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(inputDir+'/'+dcm) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' exit() inputVolume = scalarVolumePlugin.load(loadables[0]) slicer.mrmlScene.AddNode(inputVolume) print('Input volume loaded!') # read the label volume labelVolume = slicer.vtkMRMLScalarVolumeNode() sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.SetFileName(labelFile) sNode.ReadData(labelVolume) labelVolume.LabelMapOn() if forceLabel>0: print('Forcing label to '+str(forceLabel)) labelImage = labelVolume.GetImageData() thresh = vtk.vtkImageThreshold() thresh.SetInput(labelImage) thresh.ThresholdBetween(1, labelImage.GetScalarRange()[1]) thresh.SetInValue(int(forceLabel)) thresh.SetOutValue(0) thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.Update() labelImage = thresh.GetOutput() labelVolume.SetAndObserveImageData(labelImage) slicer.mrmlScene.AddNode(labelVolume) # resample label to the input volume raster resampledLabel = slicer.vtkMRMLScalarVolumeNode() slicer.mrmlScene.AddNode(resampledLabel) eye = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(eye) parameters = {} parameters['inputVolume'] = labelVolume.GetID() parameters['referenceVolume'] = inputVolume.GetID() parameters['outputVolume'] = resampledLabel.GetID() parameters['warpTransform'] = eye.GetID() parameters['interpolationMode'] = 'NearestNeighbor' parameters['pixelType'] = 'ushort' cliNode = None cliNode = slicer.cli.run(slicer.modules.brainsresample, None, parameters, 1) labelVolume = resampledLabel displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID(reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) labelVolume.SetAttribute('AssociatedNodeID',inputVolume.GetID()) labelVolume.LabelMapOn() labelVolume.SetAndObserveDisplayNodeID(displayNode.GetID()) # initialize the DICOM DB for Reporting logic, save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(labelVolume) print('About to write DICOM SEG!') dbFileName = slicer.dicomDatabase.databaseFilename reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir) except: print('Error occurred!') dicomWidget.onDatabaseDirectoryChanged(dbDir0) exit()