def computeDifference(self, fieldA, fieldB, roi, differenceVolume): referenceVolume = self.createVectorVolumeFromRoi( roi, self.ReferenceVolumeSpacingMm) referenceVolume.SetName('ReferenceVolume') slicer.mrmlScene.AddNode(referenceVolume) resampledFieldA = self.resampleVolume(fieldA, referenceVolume) resampledFieldB = self.resampleVolume(fieldB, referenceVolume) subtractor = vtk.vtkImageMathematics() subtractor.SetOperationToSubtract() subtractor.SetInput1Data(resampledFieldA.GetImageData()) subtractor.SetInput2Data(resampledFieldB.GetImageData()) differenceVolume.SetImageDataConnection(subtractor.GetOutputPort()) ijkToRasMatrix = vtk.vtkMatrix4x4() referenceVolume.GetIJKToRASMatrix(ijkToRasMatrix) differenceVolume.SetIJKToRASMatrix(ijkToRasMatrix) differenceVolumeDisplayNode = slicer.vtkMRMLVectorVolumeDisplayNode() slicer.mrmlScene.AddNode(differenceVolumeDisplayNode) differenceVolumeDisplayNode.SetAndObserveColorNodeID( "vtkMRMLColorTableNodeRainbow") differenceVolume.SetAndObserveNthDisplayNodeID( 0, differenceVolumeDisplayNode.GetID()) slicer.mrmlScene.RemoveNode(resampledFieldA) slicer.mrmlScene.RemoveNode(resampledFieldB) slicer.mrmlScene.RemoveNode(referenceVolume)
def run(self, referenceVolumeNode, secondaryVolumeNode): referenceImageData = referenceVolumeNode.GetImageData() secondaryImageData = secondaryVolumeNode.GetImageData() # Apply image convolution to input imagedata imageMath = vtk.vtkImageMathematics() imageMath.SetInput1(referenceImageData) imageMath.SetInput2(secondaryImageData) imageMath.SetOperationToSubtract() imageMath.Update() imageAccumulate = vtk.vtkImageAccumulate() imageAccumulate.SetInput(referenceImageData) imageAccumulate.IgnoreZeroOn() imageAccumulate.Update() referenceVolumeVoxelCount = imageAccumulate.GetVoxelCount() # Update the volume with convolutionl operation result imageAccumulate2 = vtk.vtkImageAccumulate() imageAccumulate2.SetInput(imageMath.GetOutput()) imageAccumulate2.IgnoreZeroOn() imageAccumulate2.Update() differenceVolumeVoxelCount = imageAccumulate2.GetVoxelCount() self._volumeSimilarity = ( referenceVolumeVoxelCount - differenceVolumeVoxelCount) / referenceVolumeVoxelCount
def onHelloWorldButtonClicked(self): print "Hello World !" #frame volume sera el scalar volume de referencia# self.__mvNode = self.mvSelector.currentNode() #NODO REFERENCIA frameVolume = slicer.vtkMRMLScalarVolumeNode() frameVolume.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(frameVolume) nComponents = self.__mvNode.GetNumberOfFrames() f=int(self.__veInitial.value) frameId = min(f,nComponents-1) ras2ijk = vtk.vtkMatrix4x4() ijk2ras = vtk.vtkMatrix4x4() self.__mvNode.GetRASToIJKMatrix(ras2ijk) self.__mvNode.GetIJKToRASMatrix(ijk2ras) frameImage = frameVolume.GetImageData() if frameImage == None: frameVolume.SetRASToIJKMatrix(ras2ijk) frameVolume.SetIJKToRASMatrix(ijk2ras) mvImage = self.__mvNode.GetImageData() for i in range(nComponents-1): extract = vtk.vtkImageExtractComponents() extract.SetInput(mvImage) extract.SetComponents(i) extract.Update() if i == 0: frameVolume.SetAndObserveImageData(extract.GetOutput()) elif i < frameId+1 : s=vtk.vtkImageMathematics() s.SetOperationToAdd() s.SetInput1(frameVolume.GetImageData()) s.SetInput2(extract.GetOutput()) s.Update() frameVolume.SetAndObserveImageData(s.GetOutput()) frameName = 'Holaaa' frameVolume.SetName(frameName) selectionNode = slicer.app.applicationLogic().GetSelectionNode() selectionNode.SetReferenceActiveVolumeID(frameVolume.GetID()) slicer.app.applicationLogic().PropagateVolumeSelection(0)
def onHelloWorldButtonClicked(self): print "Hello World !" #frame volume sera el scalar volume de referencia# self.__mvNode = self.mvSelector.currentNode() #NODO REFERENCIA frameVolume = slicer.vtkMRMLScalarVolumeNode() frameVolume.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(frameVolume) nComponents = self.__mvNode.GetNumberOfFrames() f = int(self.__veInitial.value) frameId = min(f, nComponents - 1) ras2ijk = vtk.vtkMatrix4x4() ijk2ras = vtk.vtkMatrix4x4() self.__mvNode.GetRASToIJKMatrix(ras2ijk) self.__mvNode.GetIJKToRASMatrix(ijk2ras) frameImage = frameVolume.GetImageData() if frameImage == None: frameVolume.SetRASToIJKMatrix(ras2ijk) frameVolume.SetIJKToRASMatrix(ijk2ras) mvImage = self.__mvNode.GetImageData() for i in range(nComponents - 1): extract = vtk.vtkImageExtractComponents() extract.SetInput(mvImage) extract.SetComponents(i) extract.Update() if i == 0: frameVolume.SetAndObserveImageData(extract.GetOutput()) elif i < frameId + 1: s = vtk.vtkImageMathematics() s.SetOperationToAdd() s.SetInput1(frameVolume.GetImageData()) s.SetInput2(extract.GetOutput()) s.Update() frameVolume.SetAndObserveImageData(s.GetOutput()) frameName = 'Holaaa' frameVolume.SetName(frameName) selectionNode = slicer.app.applicationLogic().GetSelectionNode() selectionNode.SetReferenceActiveVolumeID(frameVolume.GetID()) slicer.app.applicationLogic().PropagateVolumeSelection(0)
def run(self,inputVolume1,inputVolume2,outputVolume,mathOperationType): """ Run the actual algorithm """ math = vtk.vtkImageMathematics() math.SetInput1(inputVolume1.GetImageData()) math.SetInput2(inputVolume2.GetImageData()) if mathOperationType == "Add": math.SetOperationToAdd() elif mathOperationType == "Subtract": math.SetOperationToSubtract() else: pass math.Update() outputVolume.CopyOrientation(input1VolumeNode) outputVolume.SetAndObserveImageData(math.GetOutput()) return True
def getSNR(self): qu=QCLib.QCUtil() imfirst=self.first.GetImageData() imsecond=self.second.GetImageData() if imfirst.GetScalarTypeMin()>=0: #unsigned imfirst.SetScalarType(imfirst.GetScalarType()-1) if imsecond.GetScalarTypeMin()>=0: #unsigned imsecond.SetScalarType(imsecond.GetScalarType()-1) stat=qu.getROIstats(self.first,self.label) statfirst=stat.values()[0] mathv=vtk.vtkImageMathematics() mathv.SetInput1Data(imfirst) mathv.SetInput2Data(imsecond) mathv.SetOperationToSubtract() mathv.Update() imsub=mathv.GetOutput() if imsub.GetScalarTypeMin()>=0: #unsigned imsub.SetScalarType(imsub.GetScalarType()-1) stat=qu.getROIstatsIM(imsub,self.label.GetImageData()) statsub=stat.values()[0] len=statfirst.__len__() SNRvalues={} for n in range(len): stat={} statfirstn=statfirst.values()[n] statsubn=statsub.values()[n] stat['count']=statfirstn['count'] stat['mean']=statfirstn['mean'] stat['sd']=statfirstn['sd'] stat['N']=statsubn['sd'] SNRvalues[statfirst.keys()[n]]=stat return SNRvalues
def computeDifference(self, fieldA, fieldB, roi, differenceVolume): referenceVolume = self.createVectorVolumeFromRoi(roi, self.ReferenceVolumeSpacingMm) referenceVolume.SetName('ReferenceVolume') slicer.mrmlScene.AddNode( referenceVolume ) resampledFieldA = self.resampleVolume(fieldA, referenceVolume) resampledFieldB = self.resampleVolume(fieldB, referenceVolume) subtractor = vtk.vtkImageMathematics() subtractor.SetOperationToSubtract() subtractor.SetInput1Data(resampledFieldA.GetImageData()) subtractor.SetInput2Data(resampledFieldB.GetImageData()) differenceVolume.SetImageDataConnection(subtractor.GetOutputPort()) ijkToRasMatrix = vtk.vtkMatrix4x4() referenceVolume.GetIJKToRASMatrix(ijkToRasMatrix) differenceVolume.SetIJKToRASMatrix(ijkToRasMatrix) differenceVolumeDisplayNode = slicer.vtkMRMLVectorVolumeDisplayNode() slicer.mrmlScene.AddNode( differenceVolumeDisplayNode ) differenceVolumeDisplayNode.SetAndObserveColorNodeID("vtkMRMLColorTableNodeRainbow"); differenceVolume.SetAndObserveNthDisplayNodeID(0, differenceVolumeDisplayNode.GetID()); slicer.mrmlScene.RemoveNode( resampledFieldA ) slicer.mrmlScene.RemoveNode( resampledFieldB ) slicer.mrmlScene.RemoveNode( referenceVolume )
def loadPetSeries(self, loadable): """Use the conversion factor to load the volume into Slicer""" conversionFactor = loadable.slope # Create volume node imageNode = self.scalarVolumePlugin.loadFilesWithArchetype(loadable.files, loadable.name) if imageNode: # apply the conversion factor multiplier = vtk.vtkImageMathematics() multiplier.SetOperationToMultiplyByK() multiplier.SetConstantK(float(conversionFactor)) if vtk.VTK_MAJOR_VERSION <= 5: multiplier.SetInput1(imageNode.GetImageData()) else: multiplier.SetInput1Data(imageNode.GetImageData()) multiplier.Update() imageNode.GetImageData().DeepCopy(multiplier.GetOutput()) # create list of DICOM instance UIDs corresponding to the loaded files instanceUIDs = "" for dicomFile in loadable.files: uid = slicer.dicomDatabase.fileValue(dicomFile,self.tags['sopInstanceUID']) if uid == "": uid = "Unknown" instanceUIDs += uid + " " instanceUIDs = instanceUIDs[:-1] # strip last space # get the instance UID for the RWVM object derivedItemUID = "" try: derivedItemUID = slicer.dicomDatabase.fileValue(loadable.rwvFile,self.tags['sopInstanceUID']) except AttributeError: # no derived items pass # Set Attributes imageNode.SetAttribute('DICOM.MeasurementUnitsCodeMeaning',loadable.unitName) imageNode.SetAttribute('DICOM.MeasurementUnitsCodeValue',loadable.units) # Keep references to the PET instances, as these may be needed to # establish correspondence between slice annotations and acutal slices, # but also keep the RWVM instance UID ... it's confusing, but not sure # if there is a better way in Slicer for now imageNode.SetAttribute("DICOM.instanceUIDs", instanceUIDs) imageNode.SetAttribute("DICOM.RWV.instanceUID", derivedItemUID) # automatically select the volume to display volumeLogic = slicer.modules.volumes.logic() appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetReferenceActiveVolumeID(imageNode.GetID()) appLogic.PropagateVolumeSelection() # Change display displayNode = imageNode.GetVolumeDisplayNode() displayNode.SetInterpolate(0) if loadable.referencedModality == 'PT': radiopharmaceuticalCode = '' try: radiopharmaceuticalCode = loadable.RadiopharmaceuticalCodeValue imageNode.SetAttribute('DICOM.RadiopharmaceuticalCodeValue',radiopharmaceuticalCode) print('Found Radiopharmaceutical Code ' + radiopharmaceuticalCode) except AttributeError: imageNode.SetAttribute('DICOM.RadiopharmaceuticalCodeValue','unknown') # use radionuclide info instead radionuclideCode = '' try: radionuclideCode = loadable.RadionuclideCodeValue imageNode.SetAttribute('DICOM.RadionuclideCodeValue',radionuclideCode) print('Found Radionuclide Code ' + radionuclideCode) except AttributeError: imageNode.SetAttribute('DICOM.RadionuclideCodeValue','unknown') if radiopharmaceuticalCode == 'C-B1031': # FDG displayNode.AutoWindowLevelOff() displayNode.SetWindowLevel(6,3) displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeInvertedGrey') elif radiopharmaceuticalCode == 'C-B1036': # FLT displayNode.AutoWindowLevelOff() displayNode.SetWindowLevel(4,2) displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeInvertedGrey') else: # Default W/L if no info about radiopharmaceutical can be found, often FDG displayNode.AutoWindowLevelOff() displayNode.SetWindowLevel(6,3) displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeInvertedGrey') else: displayNode.SetAutoWindowLevel(1) # Change name name = (loadable.name).replace(' ','_') imageNode.SetName(name) # create Subject Hierarchy nodes for the loaded series self.addSeriesInSubjectHierarchy(loadable,imageNode) return imageNode
def load(self,loadable): """Use the conversion factor to load the volume into Slicer""" conversionFactor = loadable.slope # Create volume node imageNode = self.scalarVolumePlugin.loadFilesWithArchetype(loadable.files, loadable.name) if imageNode: # apply the conversion factor multiplier = vtk.vtkImageMathematics() multiplier.SetOperationToMultiplyByK() multiplier.SetConstantK(float(conversionFactor)) multiplier.SetInput1Data(imageNode.GetImageData()) multiplier.Update() imageNode.GetImageData().DeepCopy(multiplier.GetOutput()) # create Subject Hierarchy nodes for the loaded series self.addSeriesInSubjectHierarchy(loadable,imageNode) # create list of DICOM instance UIDs corresponding to the loaded files instanceUIDs = "" for dicomFile in loadable.files: uid = slicer.dicomDatabase.fileValue(dicomFile,self.tags['sopInstanceUID']) if uid == "": uid = "Unknown" instanceUIDs += uid + " " instanceUIDs = instanceUIDs[:-1] # strip last space # get the instance UID for the RWVM object derivedItemUID = "" try: derivedItemUID = slicer.dicomDatabase.fileValue(loadable.derivedItems[0],self.tags['sopInstanceUID']) except AttributeError: # no derived items pass # Set Attributes patientName = self.__getSeriesInformation(loadable.files, self.tags['patientName']) patientBirthDate = self.__getSeriesInformation(loadable.files, self.tags['patientBirthDate']) patientSex = self.__getSeriesInformation(loadable.files, self.tags['patientSex']) patientHeight = self.__getSeriesInformation(loadable.files, self.tags['patientHeight']) patientWeight = self.__getSeriesInformation(loadable.files, self.tags['patientWeight']) imageNode.SetAttribute('DICOM.PatientID', loadable.patientID) imageNode.SetAttribute('DICOM.PatientName', patientName) imageNode.SetAttribute('DICOM.PatientBirthDate', patientBirthDate) imageNode.SetAttribute('DICOM.PatientSex', patientSex) imageNode.SetAttribute('DICOM.PatientHeight', patientHeight) imageNode.SetAttribute('DICOM.PatientWeight', patientWeight) imageNode.SetAttribute('DICOM.StudyDate', loadable.studyDate) imageNode.SetAttribute('DICOM.MeasurementUnitsCodeMeaning',loadable.unitName) imageNode.SetAttribute('DICOM.MeasurementUnitsCodeValue',loadable.units) imageNode.SetAttribute("DICOM.instanceUIDs", instanceUIDs) imageNode.SetAttribute("DICOM.RealWorldValueMappingUID", derivedItemUID) # automatically select the volume to display volumeLogic = slicer.modules.volumes.logic() appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetReferenceActiveVolumeID(imageNode.GetID()) appLogic.PropagateVolumeSelection() # Change display displayNode = imageNode.GetVolumeDisplayNode() displayNode.SetInterpolate(0) # Change name name = (loadable.name).replace(' ','_') imageNode.SetName(name) return imageNode
def test_ResectionVolume1(self): """ Ideally you should have several levels of tests. At the lowest level tests sould exercise the functionality of the logic with different inputs (both valid and invalid). At higher levels your tests should emulate the way the user would interact with your code and confirm that it still works the way you intended. One of the most important features of the tests is that it should alert other developers when their changes will have an impact on the behavior of your module. For example, if a developer removes a feature that you depend on, your test should break so they know that the feature is needed. """ self.delayDisplay("Starting the test") # # first, get some data # resectionVolumeWidget = slicer.modules.ResectionVolumeWidget # Confirm that generate surface checkbox will not stay checked resectionVolumeWidget.generateSurface.setChecked(True) self.assertTrue(resectionVolumeWidget.generateSurface.isChecked() == False) # Data is in local directory currently for initial development slicer.util.loadMarkupsFiducialList("C:\SlicerTestData\ResectionVolumePoints.fcsv") slicer.util.loadModel("C:\SlicerTestData\ResectionVolumeModel.vtk") slicer.util.loadLabelVolume("C:\SlicerTestData\ResectionVolumeTestLabel.nrrd") slicer.util.loadLabelVolume("C:\SlicerTestData\RecoloredResectionVolumeTestLabel.nrrd") # Set fiducial points node fiducialNode = slicer.util.getNode("ResectionVolumePoints") resectionVolumeWidget.fiducialSelector.setCurrentNode(fiducialNode) # Confirm that generate surface checkbox will not stay checked resectionVolumeWidget.generateSurface.setChecked(True) self.assertTrue(resectionVolumeWidget.generateSurface.isChecked() == False) # Set model node testModelNode = slicer.mrmlScene.CreateNodeByClass("vtkMRMLModelNode") testModelNode.SetName("ResectionVolumeModelTest") slicer.mrmlScene.AddNode(testModelNode) resectionVolumeWidget.modelSelector.setCurrentNode(testModelNode) # Check the generate surface box resectionVolumeWidget.generateSurface.setChecked(True) # Confirm that generate surface checkbox stays checked self.assertTrue(resectionVolumeWidget.generateSurface.isChecked()) # Compare newly generated model with loaded model by determining if # the maximum distance between the 2 sets of polydata is less than # a desired value loadedModelNode = slicer.util.getNode("ResectionVolumeModel") distanceFilter = vtk.vtkDistancePolyDataFilter() distanceFilter.SetInputData(0, testModelNode.GetPolyData()) distanceFilter.SetInputData(1, loadedModelNode.GetPolyData()) distanceFilter.Update() distancePolyData = distanceFilter.GetOutput() distanceRange = distancePolyData.GetScalarRange() maxDistance = max(abs(distanceRange[0]),abs(distanceRange[1])) self.assertTrue(maxDistance < 0.0001) # What value for cutoff # Recolor the test label labelNode = slicer.util.getNode("ResectionVolumeTestLabel") loadedLabelNode = slicer.util.getNode("RecoloredResectionVolumeTestLabel") resectionVolumeWidget.labelSelector.setCurrentNode(labelNode) resectionVolumeWidget.initialLabelValueSelector.setValue(1) resectionVolumeWidget.outputLabelValueSelector.setValue(2) resectionVolumeWidget.onRecolorLabelMap() # Compare the recolored test label with the loaded recolored test label # by subtracting the 2 images (which should be the same) and then finding # the min/max values, (which should be 0) imageMath = vtk.vtkImageMathematics() imageMath.SetOperationToSubtract() imageMath.SetInput1Data(labelNode.GetImageData()) imageMath.SetInput2Data(loadedLabelNode.GetImageData()) imageMath.Update() imageStatistics = vtk.vtkImageHistogramStatistics() imageStatistics.SetInputData(imageMath.GetOutput()) minimumValue = imageStatistics.GetMinimum() maximumValue = imageStatistics.GetMaximum() self.assertTrue(minimumValue == maximumValue == 0) self.delayDisplay('Test passed!')
def test_ResectionVolume1(self): """ Ideally you should have several levels of tests. At the lowest level tests sould exercise the functionality of the logic with different inputs (both valid and invalid). At higher levels your tests should emulate the way the user would interact with your code and confirm that it still works the way you intended. One of the most important features of the tests is that it should alert other developers when their changes will have an impact on the behavior of your module. For example, if a developer removes a feature that you depend on, your test should break so they know that the feature is needed. """ self.delayDisplay("Starting the test") slicer.util.selectModule('ResectionVolume') resectionVolumeWidget = slicer.modules.ResectionVolumeWidget # Confirm that generate surface checkbox will not stay checked resectionVolumeWidget.generateSurface.setChecked(True) self.assertTrue( resectionVolumeWidget.generateSurface.isChecked() == False) # Data is in local directory currently for initial development dir = os.path.dirname(__file__) slicer.util.loadMarkupsFiducialList( dir + "/TestData/ResectionVolumePoints.fcsv") slicer.util.loadModel(dir + "/TestData/ResectionVolumeModel.vtk") slicer.util.loadLabelVolume(dir + "/TestData/ResectionVolumeTestLabel.nrrd") slicer.util.loadLabelVolume( dir + "/TestData/RecoloredResectionVolumeTestLabel.nrrd") # Set fiducial points node fiducialNode = slicer.util.getNode("ResectionVolumePoints") resectionVolumeWidget.fiducialSelector.setCurrentNode(fiducialNode) # Confirm that generate surface checkbox will not stay checked resectionVolumeWidget.generateSurface.setChecked(True) self.assertTrue( resectionVolumeWidget.generateSurface.isChecked() == False) # Set model node testModelNode = slicer.mrmlScene.CreateNodeByClass("vtkMRMLModelNode") testModelNode.SetName("ResectionVolumeModelTest") slicer.mrmlScene.AddNode(testModelNode) resectionVolumeWidget.modelSelector.setCurrentNode(testModelNode) # Check the generate surface box resectionVolumeWidget.generateSurface.setChecked(True) # Confirm that generate surface checkbox stays checked self.assertTrue(resectionVolumeWidget.generateSurface.isChecked()) # Compare newly generated model with loaded model by determining if # the maximum distance between the 2 sets of polydata is less than # a desired value loadedModelNode = slicer.util.getNode("ResectionVolumeModel") distanceFilter = vtk.vtkDistancePolyDataFilter() distanceFilter.SetInputData(0, testModelNode.GetPolyData()) distanceFilter.SetInputData(1, loadedModelNode.GetPolyData()) distanceFilter.Update() distancePolyData = distanceFilter.GetOutput() distanceRange = distancePolyData.GetScalarRange() maxDistance = max(abs(distanceRange[0]), abs(distanceRange[1])) self.assertTrue(maxDistance < 0.0001) # What value for cutoff self.delayDisplay('Generate Model Test Passed!') # Recolor the test label labelNode = slicer.util.getNode("ResectionVolumeTestLabel") loadedLabelNode = slicer.util.getNode( "RecoloredResectionVolumeTestLabel") resectionVolumeWidget.labelSelector.setCurrentNode(labelNode) resectionVolumeWidget.initialLabelValueSelector.setValue(1) resectionVolumeWidget.outputLabelValueSelector.setValue(2) resectionVolumeWidget.onRecolorLabelMap() # Compare the recolored test label with the loaded recolored test label # by subtracting the 2 images (which should be the same) and then finding # the min/max values, (which should be 0) imageMath = vtk.vtkImageMathematics() imageMath.SetOperationToSubtract() imageMath.SetInput1Data(labelNode.GetImageData()) imageMath.SetInput2Data(loadedLabelNode.GetImageData()) imageMath.Update() imageStatistics = vtk.vtkImageHistogramStatistics() imageStatistics.SetInputData(imageMath.GetOutput()) minimumValue = imageStatistics.GetMinimum() maximumValue = imageStatistics.GetMaximum() self.assertTrue(minimumValue == maximumValue == 0) self.delayDisplay('Test passed!')
def preview(self,color=None): if not self.editUtil.getBackgroundImage() or not self.editUtil.getLabelImage(): return # # make a lookup table where inside the threshold is opaque and colored # by the label color, while the background is transparent (black) # - apply the threshold operation to the currently visible background # (output of the layer logic's vtkImageReslice instance) # if not color: color = self.getPaintColor if not self.lut: self.lut = vtk.vtkLookupTable() self.lut.SetRampToLinear() self.lut.SetNumberOfTableValues( 3 ) self.lut.SetTableRange( 0, 2 ) self.lut.SetTableValue( 0, 0, 0, 0, 0 ) r,g,b,a = color self.lut.SetTableValue( 1, r, g, b, a/3 ) self.lut.SetTableValue( 2, r, g, b, a ) if not self.map: self.map = vtk.vtkImageMapToRGBA() self.map.SetOutputFormatToRGBA() self.map.SetLookupTable( self.lut ) if not self.thresh: self.thresh = vtk.vtkImageThreshold() sliceLogic = self.sliceWidget.sliceLogic() backgroundLogic = sliceLogic.GetBackgroundLayer() self.thresh.SetInput( backgroundLogic.GetReslice().GetOutput() ) self.thresh.ThresholdBetween( self.min, self.max ) self.thresh.SetInValue( 1 ) self.thresh.SetOutValue( 0 ) self.thresh.SetOutputScalarTypeToUnsignedChar() if not self.outter_thresh: self.outter_thresh = vtk.vtkImageThreshold() sliceLogic = self.sliceWidget.sliceLogic() backgroundLogic = sliceLogic.GetBackgroundLayer() self.outter_thresh.SetInput( backgroundLogic.GetReslice().GetOutput() ) self.outter_thresh.ThresholdBetween( self.outer_min, self.outer_max ) self.outter_thresh.SetInValue( 1 ) self.outter_thresh.SetOutValue( 0 ) self.outter_thresh.SetOutputScalarTypeToUnsignedChar() if not self.add_thresh: self.add_thresh = vtk.vtkImageMathematics() self.add_thresh.SetInput1( self.thresh.GetOutput() ) self.add_thresh.SetInput2( self.outter_thresh.GetOutput() ) self.add_thresh.SetOperationToAdd() self.map.SetInput( self.add_thresh.GetOutput() ) self.map.Update() self.cursorMapper.SetInput( self.map.GetOutput() ) self.cursorActor.VisibilityOn() self.sliceView.scheduleRender()
def run(self, enableScreenshots=0, screenshotScaleFactor=1): """ Run the actual algorithm """ self.delayDisplay('Running the aglorithm') self.enableScreenshots = enableScreenshots self.screenshotScaleFactor = screenshotScaleFactor # Start in conventional layout lm = slicer.app.layoutManager() lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView) # without this delayed display, when running from the cmd line Slicer starts # up in a different layout and the seed won't get rendered in the right spot self.delayDisplay("Conventional view") # Download MRHead from sample data import SampleData sampleDataLogic = SampleData.SampleDataLogic() print("Getting MR Head Volume") mrHeadVolume = sampleDataLogic.downloadMRHead() # Place a fiducial on the red slice markupsLogic = slicer.modules.markups.logic() eye = [33.4975, 79.4042, -10.2143] fidIndex = markupsLogic.AddFiducial(eye[0], eye[1], eye[2]) fidID = markupsLogic.GetActiveListID() fidNode = slicer.mrmlScene.GetNodeByID(fidID) self.delayDisplay("Placed a fiducial") # Pan and zoom sliceWidget = slicer.app.layoutManager().sliceWidget('Red') sliceLogic = sliceWidget.sliceLogic() compositeNode = sliceLogic.GetSliceCompositeNode() sliceNode = sliceLogic.GetSliceNode() sliceNode.SetXYZOrigin(-71.7, 129.7, 0.0) sliceNode.SetFieldOfView(98.3, 130.5, 1.0) self.delayDisplay("Panned and zoomed") # Get the seed widget seed location startingSeedDisplayCoords = [0.0, 0.0, 0.0] helper = self.getFiducialSliceDisplayableManagerHelper('Red') if helper != None: seedWidget = helper.GetWidget(fidNode) seedRepresentation = seedWidget.GetSeedRepresentation() handleRep = seedRepresentation.GetHandleRepresentation(fidIndex) startingSeedDisplayCoords = handleRep.GetDisplayPosition() print('Starting seed display coords = %d, %d, %d' % (startingSeedDisplayCoords[0], startingSeedDisplayCoords[1], startingSeedDisplayCoords[2])) self.takeScreenshot('FiducialLayoutSwitchBug1914-StartingPosition', 'Fiducial starting position', slicer.qMRMLScreenShotDialog().Red) # Switch to red slice only lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView) self.delayDisplay("Red Slice only") # Switch to conventional layout lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView) self.delayDisplay("Conventional layout") # Get the current seed widget seed location endingSeedDisplayCoords = [0.0, 0.0, 0.0] helper = self.getFiducialSliceDisplayableManagerHelper('Red') if helper != None: seedWidget = helper.GetWidget(fidNode) seedRepresentation = seedWidget.GetSeedRepresentation() handleRep = seedRepresentation.GetHandleRepresentation(fidIndex) endingSeedDisplayCoords = handleRep.GetDisplayPosition() print('Ending seed display coords = %d, %d, %d' % (endingSeedDisplayCoords[0], endingSeedDisplayCoords[1], endingSeedDisplayCoords[2])) self.takeScreenshot('FiducialLayoutSwitchBug1914-EndingPosition', 'Fiducial ending position', slicer.qMRMLScreenShotDialog().Red) # Compare to original seed widget location diff = math.pow( (startingSeedDisplayCoords[0] - endingSeedDisplayCoords[0]), 2) + math.pow( (startingSeedDisplayCoords[1] - endingSeedDisplayCoords[1]), 2) + math.pow((startingSeedDisplayCoords[2] - endingSeedDisplayCoords[2]), 2) if diff != 0.0: diff = math.sqrt(diff) self.delayDisplay( "Difference between starting and ending seed display coordinates = %g" % diff) if diff > 1.0: # raise Exception("Display coordinate difference is too large!\nExpected < 1.0 but got %g" % (diff)) print( "Display coordinate difference is too large!\nExpected < 1.0 but got %g" % (diff)) return False if enableScreenshots == 1: # compare the screen snapshots startView = slicer.mrmlScene.GetFirstNodeByName( 'FiducialLayoutSwitchBug1914-StartingPosition') startShot = startView.GetScreenShot() endView = slicer.mrmlScene.GetFirstNodeByName( 'FiducialLayoutSwitchBug1914-EndingPosition') endShot = endView.GetScreenShot() imageMath = vtk.vtkImageMathematics() imageMath.SetOperationToSubtract() imageMath.SetInput1(startShot) imageMath.SetInput2(endShot) imageMath.Update() shotDiff = imageMath.GetOutput() # save it as a scene view annotationLogic = slicer.modules.annotations.logic() annotationLogic.CreateSnapShot( "FiducialLayoutSwitchBug1914-Diff", "Difference between starting and ending fiducial seed positions", slicer.qMRMLScreenShotDialog().Red, screenshotScaleFactor, shotDiff) # calculate the image difference imageStats = vtk.vtkImageHistogramStatistics() imageStats.SetInput(shotDiff) imageStats.GenerateHistogramImageOff() imageStats.Update() meanVal = imageStats.GetMean() self.delayDisplay("Mean of image difference = %g" % meanVal) if meanVal > 5.0: # raise Exception("Image difference is too great!\nExpected <= 5.0, but got %g" % (meanVal)) print( "Image difference is too great!\nExpected <= 5.0, but got %g" % (meanVal)) return False self.delayDisplay('Test passed!') return True
def performInitialization( self, image, lowerThreshold, upperThreshold, sourceSeedIds, targetSeedIds, ignoreSideBranches=0 ): ''' ''' # import the vmtk libraries try: #from libvtkvmtkSegmentationPython import * import libvtkvmtkSegmentationPython as s except ImportError: print "FAILURE: Unable to import the SlicerVmtk libraries!" cast = vtk.vtkImageCast() cast.SetInput( image ) cast.SetOutputScalarTypeToFloat() cast.Update() image = cast.GetOutput() scalarRange = image.GetScalarRange() imageDimensions = image.GetDimensions() maxImageDimensions = max( imageDimensions ) threshold = vtk.vtkImageThreshold() threshold.SetInput( image ) threshold.ThresholdBetween( lowerThreshold, upperThreshold ) threshold.ReplaceInOff() threshold.ReplaceOutOn() threshold.SetOutValue( scalarRange[0] - scalarRange[1] ) threshold.Update() thresholdedImage = threshold.GetOutput() scalarRange = thresholdedImage.GetScalarRange() shiftScale = vtk.vtkImageShiftScale() shiftScale.SetInput( thresholdedImage ) shiftScale.SetShift( -scalarRange[0] ) shiftScale.SetScale( 1.0 / ( scalarRange[1] - scalarRange[0] ) ) shiftScale.Update() speedImage = shiftScale.GetOutput() if ignoreSideBranches: # ignore sidebranches, use colliding fronts fastMarching = s.vtkvmtkCollidingFrontsImageFilter() fastMarching.SetInput( speedImage ) fastMarching.SetSeeds1( sourceSeedIds ) fastMarching.SetSeeds2( targetSeedIds ) fastMarching.ApplyConnectivityOn() fastMarching.StopOnTargetsOn() fastMarching.Update() subtract = vtk.vtkImageMathematics() subtract.SetInput( fastMarching.GetOutput() ) subtract.SetOperationToAddConstant() subtract.SetConstantC( -10 * fastMarching.GetNegativeEpsilon() ) subtract.Update() else: fastMarching = s.vtkvmtkFastMarchingUpwindGradientImageFilter() fastMarching.SetInput( speedImage ) fastMarching.SetSeeds( sourceSeedIds ) fastMarching.GenerateGradientImageOn() fastMarching.SetTargetOffset( 0.0 ) fastMarching.SetTargets( targetSeedIds ) if targetSeedIds.GetNumberOfIds() > 0: fastMarching.SetTargetReachedModeToOneTarget() else: fastMarching.SetTargetReachedModeToNoTargets() fastMarching.Update() if targetSeedIds.GetNumberOfIds() > 0: subtract = vtk.vtkImageMathematics() subtract.SetInput( fastMarching.GetOutput() ) subtract.SetOperationToAddConstant() subtract.SetConstantC( -fastMarching.GetTargetValue() ) subtract.Update() else: subtract = vtk.vtkImageThreshold() subtract.SetInput( fastMarching.GetOutput() ) subtract.ThresholdByLower( 2000 ) # TODO find robuste value subtract.ReplaceInOff() subtract.ReplaceOutOn() subtract.SetOutValue( -1 ) subtract.Update() outImageData = vtk.vtkImageData() outImageData.DeepCopy( subtract.GetOutput() ) outImageData.Update() return outImageData
def performInitialization(self, image, lowerThreshold, upperThreshold, sourceSeedIds, targetSeedIds, ignoreSideBranches=0): ''' ''' # import the vmtk libraries try: import vtkvmtkSegmentationPython as vtkvmtkSegmentation except ImportError: logging.error("Unable to import the SlicerVmtk libraries") cast = vtk.vtkImageCast() cast.SetInputData(image) cast.SetOutputScalarTypeToFloat() cast.Update() image = cast.GetOutput() scalarRange = image.GetScalarRange() imageDimensions = image.GetDimensions() maxImageDimensions = max(imageDimensions) threshold = vtk.vtkImageThreshold() threshold.SetInputData(image) threshold.ThresholdBetween(lowerThreshold, upperThreshold) threshold.ReplaceInOff() threshold.ReplaceOutOn() threshold.SetOutValue(scalarRange[0] - scalarRange[1]) threshold.Update() thresholdedImage = threshold.GetOutput() scalarRange = thresholdedImage.GetScalarRange() shiftScale = vtk.vtkImageShiftScale() shiftScale.SetInputData(thresholdedImage) shiftScale.SetShift(-scalarRange[0]) shiftScale.SetScale(1.0 / (scalarRange[1] - scalarRange[0])) shiftScale.Update() speedImage = shiftScale.GetOutput() if ignoreSideBranches: # ignore sidebranches, use colliding fronts fastMarching = vtkvmtkSegmentation.vtkvmtkCollidingFrontsImageFilter( ) fastMarching.SetInputData(speedImage) fastMarching.SetSeeds1(sourceSeedIds) fastMarching.SetSeeds2(targetSeedIds) fastMarching.ApplyConnectivityOn() fastMarching.StopOnTargetsOn() fastMarching.Update() subtract = vtk.vtkImageMathematics() subtract.SetInputData(fastMarching.GetOutput()) subtract.SetOperationToAddConstant() subtract.SetConstantC(-10 * fastMarching.GetNegativeEpsilon()) subtract.Update() else: fastMarching = vtkvmtkSegmentation.vtkvmtkFastMarchingUpwindGradientImageFilter( ) fastMarching.SetInputData(speedImage) fastMarching.SetSeeds(sourceSeedIds) fastMarching.GenerateGradientImageOn() fastMarching.SetTargetOffset(0.0) fastMarching.SetTargets(targetSeedIds) if targetSeedIds.GetNumberOfIds() > 0: fastMarching.SetTargetReachedModeToOneTarget() else: fastMarching.SetTargetReachedModeToNoTargets() fastMarching.Update() if targetSeedIds.GetNumberOfIds() > 0: subtract = vtk.vtkImageMathematics() subtract.SetInputData(fastMarching.GetOutput()) subtract.SetOperationToAddConstant() subtract.SetConstantC(-fastMarching.GetTargetValue()) subtract.Update() else: subtract = vtk.vtkImageThreshold() subtract.SetInputData(fastMarching.GetOutput()) subtract.ThresholdByLower(2000) # TODO find robuste value subtract.ReplaceInOff() subtract.ReplaceOutOn() subtract.SetOutValue(-1) subtract.Update() outImageData = vtk.vtkImageData() outImageData.DeepCopy(subtract.GetOutput()) return outImageData
def loadPetSeries(self, loadable): """Use the conversion factor to load the volume into Slicer""" conversionFactor = loadable.slope # Create volume node imageNode = self.scalarVolumePlugin.loadFilesWithArchetype(loadable.files, loadable.name) if imageNode: # apply the conversion factor multiplier = vtk.vtkImageMathematics() multiplier.SetOperationToMultiplyByK() multiplier.SetConstantK(float(conversionFactor)) if vtk.VTK_MAJOR_VERSION <= 5: multiplier.SetInput1(imageNode.GetImageData()) else: multiplier.SetInput1Data(imageNode.GetImageData()) multiplier.Update() imageNode.GetImageData().DeepCopy(multiplier.GetOutput()) # create list of DICOM instance UIDs corresponding to the loaded files instanceUIDs = "" for dicomFile in loadable.files: uid = slicer.dicomDatabase.fileValue(dicomFile,self.tags['sopInstanceUID']) if uid == "": uid = "Unknown" instanceUIDs += uid + " " instanceUIDs = instanceUIDs[:-1] # strip last space # get the instance UID for the RWVM object derivedItemUID = "" try: derivedItemUID = slicer.dicomDatabase.fileValue(loadable.rwvFile,self.tags['sopInstanceUID']) except AttributeError: # no derived items pass if loadable.quantity: imageNode.SetVoxelValueQuantity(loadable.quantity) if loadable.units: imageNode.SetVoxelValueUnits(loadable.units) # Keep references to the PET instances, as these may be needed to # establish correspondence between slice annotations and acutal slices, # but also keep the RWVM instance UID ... it's confusing, but not sure # if there is a better way in Slicer for now imageNode.SetAttribute("DICOM.instanceUIDs", instanceUIDs) imageNode.SetAttribute("DICOM.RWV.instanceUID", derivedItemUID) # automatically select the volume to display volumeLogic = slicer.modules.volumes.logic() appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetReferenceActiveVolumeID(imageNode.GetID()) appLogic.PropagateVolumeSelection() # Change display displayNode = imageNode.GetVolumeDisplayNode() displayNode.SetInterpolate(0) if loadable.referencedModality == 'PT': radiopharmaceuticalCode = '' try: radiopharmaceuticalCode = loadable.RadiopharmaceuticalCodeValue imageNode.SetAttribute('DICOM.RadiopharmaceuticalCodeValue',radiopharmaceuticalCode) print('Found Radiopharmaceutical Code ' + radiopharmaceuticalCode) except AttributeError: imageNode.SetAttribute('DICOM.RadiopharmaceuticalCodeValue','unknown') # use radionuclide info instead radionuclideCode = '' try: radionuclideCode = loadable.RadionuclideCodeValue imageNode.SetAttribute('DICOM.RadionuclideCodeValue',radionuclideCode) print('Found Radionuclide Code ' + radionuclideCode) except AttributeError: imageNode.SetAttribute('DICOM.RadionuclideCodeValue','unknown') if radiopharmaceuticalCode == 'C-B1031': # FDG displayNode.AutoWindowLevelOff() displayNode.SetWindowLevel(6,3) displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeInvertedGrey') elif radiopharmaceuticalCode == 'C-B1036': # FLT displayNode.AutoWindowLevelOff() displayNode.SetWindowLevel(4,2) displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeInvertedGrey') else: # Default W/L if no info about radiopharmaceutical can be found, often FDG displayNode.AutoWindowLevelOff() displayNode.SetWindowLevel(6,3) displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeInvertedGrey') else: displayNode.SetAutoWindowLevel(1) # Change name name = (loadable.name).replace(' ','_') imageNode.SetName(name) # create Subject Hierarchy nodes for the loaded series self.addSeriesInSubjectHierarchy(loadable,imageNode) return imageNode
def run(self,enableScreenshots=0,screenshotScaleFactor=1): """ Run the actual algorithm """ self.delayDisplay('Running the aglorithm') self.enableScreenshots = enableScreenshots self.screenshotScaleFactor = screenshotScaleFactor # Start in conventional layout lm = slicer.app.layoutManager() lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView) # without this delayed display, when running from the cmd line Slicer starts # up in a different layout and the seed won't get rendered in the right spot self.delayDisplay("Conventional view") # Download MRHead from sample data import SampleData sampleDataLogic = SampleData.SampleDataLogic() print("Getting MR Head Volume") mrHeadVolume = sampleDataLogic.downloadMRHead() # Place a fiducial on the red slice markupsLogic = slicer.modules.markups.logic() eye = [33.4975, 79.4042, -10.2143] fidIndex = markupsLogic.AddFiducial(eye[0], eye[1], eye[2]) fidID = markupsLogic.GetActiveListID() fidNode = slicer.mrmlScene.GetNodeByID(fidID) self.delayDisplay("Placed a fiducial") # Pan and zoom sliceWidget = slicer.app.layoutManager().sliceWidget('Red') sliceLogic = sliceWidget.sliceLogic() compositeNode = sliceLogic.GetSliceCompositeNode() sliceNode = sliceLogic.GetSliceNode() sliceNode.SetXYZOrigin(-71.7, 129.7, 0.0) sliceNode.SetFieldOfView(98.3, 130.5, 1.0) self.delayDisplay("Panned and zoomed") # Get the seed widget seed location startingSeedDisplayCoords = [0.0, 0.0, 0.0] helper = self.getFiducialSliceDisplayableManagerHelper('Red') if helper != None: seedWidget = helper.GetWidget(fidNode) seedRepresentation = seedWidget.GetSeedRepresentation() handleRep = seedRepresentation.GetHandleRepresentation(fidIndex) startingSeedDisplayCoords = handleRep.GetDisplayPosition() print('Starting seed display coords = %d, %d, %d' % (startingSeedDisplayCoords[0], startingSeedDisplayCoords[1], startingSeedDisplayCoords[2])) self.takeScreenshot('FiducialLayoutSwitchBug1914-StartingPosition','Fiducial starting position',slicer.qMRMLScreenShotDialog().Red) # Switch to red slice only lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView) self.delayDisplay("Red Slice only") # Switch to conventional layout lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView) self.delayDisplay("Conventional layout") # Get the current seed widget seed location endingSeedDisplayCoords = [0.0, 0.0, 0.0] helper = self.getFiducialSliceDisplayableManagerHelper('Red') if helper != None: seedWidget = helper.GetWidget(fidNode) seedRepresentation = seedWidget.GetSeedRepresentation() handleRep = seedRepresentation.GetHandleRepresentation(fidIndex) endingSeedDisplayCoords = handleRep.GetDisplayPosition() print('Ending seed display coords = %d, %d, %d' % (endingSeedDisplayCoords[0], endingSeedDisplayCoords[1], endingSeedDisplayCoords[2])) self.takeScreenshot('FiducialLayoutSwitchBug1914-EndingPosition','Fiducial ending position',slicer.qMRMLScreenShotDialog().Red) # Compare to original seed widget location diff = math.pow((startingSeedDisplayCoords[0] - endingSeedDisplayCoords[0]),2) + math.pow((startingSeedDisplayCoords[1] - endingSeedDisplayCoords[1]),2) + math.pow((startingSeedDisplayCoords[2] - endingSeedDisplayCoords[2]),2) if diff != 0.0: diff = math.sqrt(diff) self.delayDisplay("Difference between starting and ending seed display coordinates = %g" % diff) if diff > 1.0: # raise Exception("Display coordinate difference is too large!\nExpected < 1.0 but got %g" % (diff)) print("Display coordinate difference is too large!\nExpected < 1.0 but got %g" % (diff)) return False if enableScreenshots == 1: # compare the screen snapshots startView = slicer.mrmlScene.GetFirstNodeByName('FiducialLayoutSwitchBug1914-StartingPosition') startShot = startView.GetScreenShot() endView = slicer.mrmlScene.GetFirstNodeByName('FiducialLayoutSwitchBug1914-EndingPosition') endShot = endView.GetScreenShot() imageMath = vtk.vtkImageMathematics() imageMath.SetOperationToSubtract() imageMath.SetInput1(startShot) imageMath.SetInput2(endShot) imageMath.Update() shotDiff = imageMath.GetOutput() # save it as a scene view annotationLogic = slicer.modules.annotations.logic() annotationLogic.CreateSnapShot("FiducialLayoutSwitchBug1914-Diff", "Difference between starting and ending fiducial seed positions",slicer.qMRMLScreenShotDialog().Red, screenshotScaleFactor, shotDiff) # calculate the image difference imageStats = vtk.vtkImageHistogramStatistics() imageStats.SetInput(shotDiff) imageStats.GenerateHistogramImageOff() imageStats.Update() meanVal = imageStats.GetMean() self.delayDisplay("Mean of image difference = %g" % meanVal) if meanVal > 5.0: # raise Exception("Image difference is too great!\nExpected <= 5.0, but got %g" % (meanVal)) print("Image difference is too great!\nExpected <= 5.0, but got %g" % (meanVal)) return False self.delayDisplay('Test passed!') return True
def GetDistanceMap(self,edgeImg,altedgeImg): tmpimage=vtk.vtkImageData() cast=vtk.vtkImageCast() cast.SetOutputScalarTypeToDouble() cast.SetInputData(edgeImg) cast.Update() #invert edge image edge=0 and background=2x Math=vtk.vtkImageMathematics() Math.SetInput1Data(cast.GetOutput()) Math.SetConstantC(0) Math.SetConstantK(2) Math.SetOperationToReplaceCByK() Math.Update() tmpimage.DeepCopy(Math.GetOutput()) Math.SetInput1Data(tmpimage) Math.SetConstantC(1) Math.SetConstantK(0) Math.Update() cast.SetInputData(Math.GetOutput()) cast.Update() tmpimage.DeepCopy(cast.GetOutput()) tmpimage2=vtk.vtkImageData() #calculate distance map if self.distalg==0: dm=slicer.vtkITKSignedDistanceTransform() # tmpimage.SetSpacing(self.input.GetSpacing()) # dm.SetUseImageSpacing(True) dm.SetAlgorithmToSignedMaurer() dm.SetInputData(tmpimage) dm.Update() tmpimage2.DeepCopy(dm.GetOutput()) elif self.distalg==1: dm=slicer.vtkITKSignedDistanceTransform() dm.SetAlgorithmToApproximateSigned() dm.SetInputData(tmpimage) dm.Update() tmpimage2.DeepCopy(dm.GetOutput()) elif self.distalg==2: dm=slicer.vtkITKSignedDistanceTransform() # tmpimage.SetSpacing(self.input.GetSpacing()) # dm.SetUseImageSpacing(True) dm.SetAlgorithmToSignedDanielsson() dm.SetObjectValue(2) dm.SetInputData(tmpimage) dm.Update() tmpimage2.DeepCopy(dm.GetOutput()) elif self.distalg==3: dm=vtk.vtkImageEuclideanDistance() #tmpimage.SetSpacing(self.input.GetSpacing()) dm.InitializeOn() #dm.ConsiderAnisotropyOn() dm.SetInputData(tmpimage) dm.Update() Math.SetInputData(dm.GetOutput()) Math.SetOperationToSquareRoot() Math.Update() tmpimage2.DeepCopy(Math.GetOutput()) if not altedgeImg: altedgeImg=tmpimage2 qu=QCLib.QCUtil() rect=qu.minRectangle(self.ROI) for i in range(rect['xmin'].__len__()): if rect['xmin'][i]>=0: index=i break xmin=rect['xmin'][index] xmax=rect['xmax'][index] ymin=rect['ymin'][index] ymax=rect['ymax'][index] distMap=vtk.vtkImageData() distMap.DeepCopy(edgeImg) for x in range(xmin,xmax+1): for y in range(ymin,ymax+1): isedge=math.copysign(edgeImg.GetScalarComponentAsDouble(x,y,index,0)-1,1) if self.distalg!=3: val=math.copysign((math.fabs(tmpimage2.GetScalarComponentAsDouble(x,y,index,0))+1)*isedge,altedgeImg.GetScalarComponentAsDouble(x,y,index,0)) else: val=math.copysign((math.fabs(tmpimage2.GetScalarComponentAsDouble(x,y,index,0)))*isedge,altedgeImg.GetScalarComponentAsDouble(x,y,index,0)) distMap.SetScalarComponentFromDouble(x,y,index,0,val) return distMap
def load(self,loadable): """Use the conversion factor to load the volume into Slicer""" conversionFactor = loadable.slope # Create volume node imageNode = self.scalarVolumePlugin.loadFilesWithArchetype(loadable.files, loadable.name) if imageNode: # apply the conversion factor multiplier = vtk.vtkImageMathematics() multiplier.SetOperationToMultiplyByK() multiplier.SetConstantK(float(conversionFactor)) if vtk.VTK_MAJOR_VERSION <= 5: multiplier.SetInput1(imageNode.GetImageData()) else: multiplier.SetInput1Data(imageNode.GetImageData()) multiplier.Update() imageNode.GetImageData().DeepCopy(multiplier.GetOutput()) # create list of DICOM instance UIDs corresponding to the loaded files instanceUIDs = "" for dicomFile in loadable.files: uid = slicer.dicomDatabase.fileValue(dicomFile,self.tags['sopInstanceUID']) if uid == "": uid = "Unknown" instanceUIDs += uid + " " instanceUIDs = instanceUIDs[:-1] # strip last space # get the instance UID for the RWVM object derivedItemUID = "" try: derivedItemUID = slicer.dicomDatabase.fileValue(loadable.rwvFile,self.tags['sopInstanceUID']) except AttributeError: # no derived items pass # Set Attributes imageNode.SetAttribute('DICOM.MeasurementUnitsCodeMeaning',loadable.unitName) imageNode.SetAttribute('DICOM.MeasurementUnitsCodeValue',loadable.units) # Keep references to the PET instances, as these may be needed to # establish correspondence between slice annotations and acutal slices, # but also keep the RWVM instance UID ... it's confusing, but not sure # if there is a better way in Slicer for now imageNode.SetAttribute("DICOM.instanceUIDs", instanceUIDs) imageNode.SetAttribute("DICOM.RWV.instanceUID", derivedItemUID) # automatically select the volume to display volumeLogic = slicer.modules.volumes.logic() appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetReferenceActiveVolumeID(imageNode.GetID()) appLogic.PropagateVolumeSelection() # Change display displayNode = imageNode.GetVolumeDisplayNode() displayNode.SetInterpolate(0) # Change name name = (loadable.name).replace(' ','_') imageNode.SetName(name) # create Subject Hierarchy nodes for the loaded series self.addSeriesInSubjectHierarchy(loadable,imageNode) return imageNode