def computeStatistics(self, segmentID): import vtkSegmentationCorePython as vtkSegmentationCore requestedKeys = self.getRequestedKeys() segmentationNode = slicer.mrmlScene.GetNodeByID( self.getParameterNode().GetParameter("Segmentation")) if len(requestedKeys) == 0: return {} containsLabelmapRepresentation = segmentationNode.GetSegmentation( ).ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter. GetSegmentationBinaryLabelmapRepresentationName()) if not containsLabelmapRepresentation: return {} segmentLabelmap = slicer.vtkOrientedImageData() segmentationNode.GetBinaryLabelmapRepresentation( segmentID, segmentLabelmap) if (not segmentLabelmap or not segmentLabelmap.GetPointData() or not segmentLabelmap.GetPointData().GetScalars()): # No input label data return {} # We need to know exactly the value of the segment voxels, apply threshold to make force the selected label value labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() thresh.SetInputData(segmentLabelmap) thresh.ThresholdByLower(0) thresh.SetInValue(backgroundValue) thresh.SetOutValue(labelValue) thresh.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) thresh.Update() # Use binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputData(thresh.GetOutput()) stencil.ThresholdByUpper(labelValue) stencil.Update() stat = vtk.vtkImageAccumulate() stat.SetInputData(thresh.GetOutput()) stat.SetStencilData(stencil.GetOutput()) stat.Update() # Add data to statistics list cubicMMPerVoxel = reduce(lambda x, y: x * y, segmentLabelmap.GetSpacing()) ccPerCubicMM = 0.001 stats = {} if "voxel_count" in requestedKeys: stats["voxel_count"] = stat.GetVoxelCount() if "volume_mm3" in requestedKeys: stats["volume_mm3"] = stat.GetVoxelCount() * cubicMMPerVoxel if "volume_cm3" in requestedKeys: stats["volume_cm3"] = stat.GetVoxelCount( ) * cubicMMPerVoxel * ccPerCubicMM return stats
def getLabelStats(self, image, roi, labelStats): # instantiate results dictionary labelStats["Image"].append(image.GetName()) # copied/modified from labelstatistics module # determine volume of a voxel and conversion factor to cubed centimeters cubicMMPerVoxel = reduce(lambda x, y: x * y, roi.GetSpacing()) ccPerCubicMM = 0.001 # calculate the min and max of the roi image stataccum = vtk.vtkImageAccumulate() stataccum.SetInputConnection(roi.GetImageDataConnection()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) # iterate through all the labels in the image for i in xrange(lo, hi + 1): # threshold roi image thresholder = vtk.vtkImageThreshold() thresholder.SetInputConnection(roi.GetImageDataConnection()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( image.GetImageData().GetScalarType()) thresholder.Update() # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputConnection(thresholder.GetOutputPort()) stencil.ThresholdBetween(1, 1) stat1 = vtk.vtkImageAccumulate() stat1.SetInputConnection(image.GetImageDataConnection()) stencil.Update() stat1.SetStencilData(stencil.GetOutput()) stat1.Update() # gather stats if count is greater than zero if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list labelStats["Labels"].append(i) labelStats[image.GetName(), i, "Image"] = image.GetName() labelStats[image.GetName(), i, "Index"] = i labelStats[image.GetName(), i, "Count"] = stat1.GetVoxelCount() labelStats[image.GetName(), i, "Volume mm^3"] = labelStats[ image.GetName(), i, "Count"] * cubicMMPerVoxel labelStats[image.GetName(), i, "Volume cc"] = labelStats[ image.GetName(), i, "Volume mm^3"] * ccPerCubicMM labelStats[image.GetName(), i, "Min"] = stat1.GetMin()[0] labelStats[image.GetName(), i, "Max"] = stat1.GetMax()[0] labelStats[image.GetName(), i, "Mean"] = stat1.GetMean()[0] labelStats[image.GetName(), i, "StdDev"] = stat1.GetStandardDeviation()[0] return hi
def splitPerStructureVolumes(masterNode, mergeNode): """Make a separate label map node for each non-empty label value in the merged label map""" colorNode = mergeNode.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() accum.SetInputConnection(mergeNode.GetImageDataConnection()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) thresholder = vtk.vtkImageThreshold() for index in xrange(lo,hi+1): logging.info( "Splitting label %d..."%index ) thresholder.SetInputConnection( mergeNode.GetImageDataConnection() ) thresholder.SetInValue( index ) thresholder.SetOutValue( 0 ) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween( index, index ) thresholder.SetOutputScalarType( mergeNode.GetImageData().GetScalarType() ) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): structureName = colorNode.GetColorName(index) logging.info( "Creating structure volume %s..."%structureName ) structureVolume = EditUtil.structureVolume( masterNode, structureName ) if not structureVolume: EditUtil.addStructure( masterNode, mergeNode, index ) structureVolume = EditUtil.structureVolume( masterNode, structureName ) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput() ) EditUtil.markVolumeNodeAsModified(structureVolume)
def get_histogram(image, maxval=0, minval=0, maxrange=0): """ Return the histogram of the image as a list of floats """ accu = vtk.vtkImageAccumulate() accu.SetInputConnection(image.GetProducerPort()) if maxval == 0: x0, x1 = getImageScalarRange(image) # x1 = int(math.floor(x1)) # x0 = int(math.ceil(x0)) else: # x0, x1 = (int(math.ceil(minval)),int(math.floor(maxval))) x0, x1 = (minval, maxval) # accu.SetComponentExtent(0, x1 - x0, 0, 0, 0, 0) # accu.SetComponentSpacing(1, 0, 0) if maxrange: accu.SetComponentExtent(0, x1 - x0, 0, 0, 0, 0) accu.SetComponentSpacing(1, 0, 0) else: accu.SetComponentExtent(0, 255, 0, 0, 0, 0) accu.SetComponentSpacing((x1 - x0 + 1) / 256.0, 0, 0) accu.SetComponentOrigin(x0, 0, 0) accu.Update() data = accu.GetOutput() values = [] x0, x1, y0, y1, z0, z1 = data.GetWholeExtent() for i in range(x0, x1 + 1): c = data.GetScalarComponentAsDouble(i, 0, 0, 0) values.append(c) return values
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__( self, module_manager, vtk.vtkImageAccumulate(), 'Processing.', ('vtkImageData', 'vtkImageStencilData'), ('vtkImageData',), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def splitPerStructureVolumes(masterNode, mergeNode): """Make a separate label map node for each non-empty label value in the merged label map""" colorNode = mergeNode.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() accum.SetInputConnection(mergeNode.GetImageDataConnection()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) thresholder = vtk.vtkImageThreshold() for index in xrange(lo,hi+1): logging.info( "Splitting label %d..."%index ) thresholder.SetInputConnection( mergeNode.GetImageDataConnection() ) thresholder.SetInValue( index ) thresholder.SetOutValue( 0 ) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween( index, index ) thresholder.SetOutputScalarType( mergeNode.GetImageData().GetScalarType() ) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): structureName = colorNode.GetColorName(index) logging.info( "Creating structure volume %s..."%structureName ) structureVolume = EditUtil.structureVolume( masterNode, structureName ) if not structureVolume: EditUtil.addStructure( masterNode, mergeNode, index ) structureVolume = EditUtil.structureVolume( masterNode, structureName ) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput() ) EditUtil.markVolumeNodeAsModified(structureVolume)
def get_histogram(image, maxval=0, minval=0, maxrange=0): """ Return the histogram of the image as a list of floats """ accu = vtk.vtkImageAccumulate() accu.SetInputConnection(image.GetProducerPort()) if maxval == 0: x0, x1 = getImageScalarRange(image) #x1 = int(math.floor(x1)) #x0 = int(math.ceil(x0)) else: #x0, x1 = (int(math.ceil(minval)),int(math.floor(maxval))) x0, x1 = (minval, maxval) #accu.SetComponentExtent(0, x1 - x0, 0, 0, 0, 0) #accu.SetComponentSpacing(1, 0, 0) if maxrange: accu.SetComponentExtent(0, x1 - x0, 0, 0, 0, 0) accu.SetComponentSpacing(1, 0, 0) else: accu.SetComponentExtent(0, 255, 0, 0, 0, 0) accu.SetComponentSpacing((x1 - x0 + 1) / 256.0, 0, 0) accu.SetComponentOrigin(x0, 0, 0) accu.Update() data = accu.GetOutput() values = [] x0, x1, y0, y1, z0, z1 = data.GetWholeExtent() for i in range(x0, x1 + 1): c = data.GetScalarComponentAsDouble(i, 0, 0, 0) values.append(c) return values
def setInputAsNumpy(self, numpyarray): if (len(numpy.shape(numpyarray)) == 3): doubleImg = vtk.vtkImageData() shape = numpy.shape(numpyarray) doubleImg.SetDimensions(shape[0], shape[1], shape[2]) doubleImg.SetOrigin(0, 0, 0) doubleImg.SetSpacing(1, 1, 1) doubleImg.SetExtent(0, shape[0] - 1, 0, shape[1] - 1, 0, shape[2] - 1) doubleImg.AllocateScalars(vtk.VTK_DOUBLE, 1) for i in range(shape[0]): for j in range(shape[1]): for k in range(shape[2]): doubleImg.SetScalarComponentFromDouble( i, j, k, 0, numpyarray[i][j][k]) # rescale to appropriate VTK_UNSIGNED_SHORT stats = vtk.vtkImageAccumulate() stats.SetInputData(doubleImg) stats.Update() iMin = stats.GetMin()[0] iMax = stats.GetMax()[0] scale = vtk.VTK_UNSIGNED_SHORT_MAX / (iMax - iMin) shiftScaler = vtk.vtkImageShiftScale() shiftScaler.SetInputData(doubleImg) shiftScaler.SetScale(scale) shiftScaler.SetShift(iMin) shiftScaler.SetOutputScalarType(vtk.VTK_UNSIGNED_SHORT) shiftScaler.Update() self.img3D = shiftScaler.GetOutput()
def TestSection_1_AddRemoveSegment(self): # Add/remove segment from segmentation (check display properties, color table, etc.) logging.info('Test section 1: Add/remove segment') # Get baseline values displayNode = self.inputSegmentationNode.GetDisplayNode() self.assertIsNotNone(displayNode) colorTableNode = displayNode.GetColorNode() self.assertIsNotNone(colorTableNode) self.assertEqual(colorTableNode.GetNumberOfColors(), 4) # If segments are not found then the returned color is the pre-defined invalid color bodyColor = displayNode.GetSegmentColor('Body_Contour') self.assertTrue(int(bodyColor[0]*100) == 33 and int(bodyColor[1]*100) == 66 and bodyColor[2] == 0.0) tumorColor = displayNode.GetSegmentColor('Tumor_Contour') self.assertTrue(tumorColor[0] == 1.0 and tumorColor[1] == 0.0 and tumorColor[2] == 0.0) # Create new segment sphere = vtk.vtkSphereSource() sphere.SetCenter(0,50,0) sphere.SetRadius(50) sphere.Update() spherePolyData = vtk.vtkPolyData() spherePolyData.DeepCopy(sphere.GetOutput()) self.sphereSegment = vtkSegmentationCore.vtkSegment() self.sphereSegment.SetName(self.sphereSegmentName) self.sphereSegment.SetDefaultColor(0.0,0.0,1.0) self.sphereSegment.AddRepresentation(self.closedSurfaceReprName, spherePolyData) # Add segment to segmentation self.inputSegmentationNode.GetSegmentation().AddSegment(self.sphereSegment) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) self.assertEqual(colorTableNode.GetNumberOfColors(), 5) sphereColor = displayNode.GetSegmentColor(self.sphereSegmentName) self.assertTrue(sphereColor[0] == 0.0 and sphereColor[1] == 0.0 and sphereColor[2] == 1.0) # Check merged labelmap imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(self.inputSegmentationNode.GetImageData()) imageStat.SetComponentExtent(0,4,0,0,0,0) imageStat.SetComponentOrigin(0,0,0) imageStat.SetComponentSpacing(1,1,1) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 1000) imageStatResult = imageStat.GetOutput() self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0,0,0,0), 814) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1,0,0,0), 0) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2,0,0,0), 175) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3,0,0,0), 4) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(4,0,0,0), 7) # Remove segment from segmentation self.inputSegmentationNode.GetSegmentation().RemoveSegment(self.sphereSegmentName) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 2) self.assertEqual(colorTableNode.GetNumberOfColors(), 5) sphereColorArray = [0]*4 colorTableNode.GetColor(4,sphereColorArray) self.assertTrue(int(sphereColorArray[0]*100) == 50 and int(sphereColorArray[1]*100) == 50 and int(sphereColorArray[2]*100) == 50) sphereColor = displayNode.GetSegmentColor(self.sphereSegmentName) self.assertTrue(sphereColor[0] == 0.5 and sphereColor[1] == 0.5 and sphereColor[2] == 0.5)
def __init__(self, binsCount, reader): self.Reader = reader self.BinsCount = binsCount self.BinStep = 0 self.ScalarRange = [0, 0] self.FreqArray = vtk.vtkDataArray.CreateDataArray(vtk.VTK_INT) self.FreqArray.SetNumberOfComponents(1) extract = vtk.vtkImageExtractComponents() extract.SetInputConnection(self.Reader.GetOutputPort()) extract.SetComponents(0) extract.Update() extract.GetOutput().GetScalarRange(self.ScalarRange) self.BinStep = (self.ScalarRange[1] - self.ScalarRange[0]) / self.BinsCount histo = vtk.vtkImageAccumulate() histo.SetInputConnection(extract.GetOutputPort()) histo.SetComponentExtent(0, self.BinsCount, 0, 0, 0, 0) histo.SetComponentOrigin(self.ScalarRange[0], 0, 0) histo.SetComponentSpacing(self.BinStep, 0, 0) histo.SetIgnoreZero(False) histo.Update() for j in range(0, self.BinsCount): compValue = histo.GetOutput().GetPointData().GetScalars().GetValue(j) self.FreqArray.InsertNextTuple1(compValue) lastBinValue = self.FreqArray.GetComponent(self.BinsCount - 1, 0) binValue = histo.GetOutput().GetPointData().GetScalars().GetValue(self.BinsCount) self.FreqArray.SetComponent(self.BinsCount - 1, 0, lastBinValue + binValue)
def getForegroundVoxelCount(self, imageData): if imageData is None: logging.error('Invalid input image data') return False imageAccumulate = vtk.vtkImageAccumulate() imageAccumulate.SetInputData(imageData) imageAccumulate.SetIgnoreZero(1) imageAccumulate.Update() return imageAccumulate.GetVoxelCount()
def getForegroundVoxelCount(self, imageData): if imageData is None: logging.error('Invalid input image data') return False imageAccumulate = vtk.vtkImageAccumulate() imageAccumulate.SetInputData(imageData) imageAccumulate.SetIgnoreZero(1) imageAccumulate.Update() return imageAccumulate.GetVoxelCount()
def computeStatistics(self, segmentID): import vtkSegmentationCorePython as vtkSegmentationCore requestedKeys = self.getRequestedKeys() segmentationNode = slicer.mrmlScene.GetNodeByID(self.getParameterNode().GetParameter("Segmentation")) if len(requestedKeys)==0: return {} containsLabelmapRepresentation = segmentationNode.GetSegmentation().ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()) if not containsLabelmapRepresentation: return {} segment = segmentationNode.GetSegmentation().GetSegment(segmentID) segBinaryLabelName = vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName() segmentLabelmap = segment.GetRepresentation(segBinaryLabelName) if (not segmentLabelmap or not segmentLabelmap.GetPointData() or not segmentLabelmap.GetPointData().GetScalars()): # No input label data return {} # We need to know exactly the value of the segment voxels, apply threshold to make force the selected label value labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() thresh.SetInputData(segmentLabelmap) thresh.ThresholdByLower(0) thresh.SetInValue(backgroundValue) thresh.SetOutValue(labelValue) thresh.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) thresh.Update() # Use binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputData(thresh.GetOutput()) stencil.ThresholdByUpper(labelValue) stencil.Update() stat = vtk.vtkImageAccumulate() stat.SetInputData(thresh.GetOutput()) stat.SetStencilData(stencil.GetOutput()) stat.Update() # Add data to statistics list cubicMMPerVoxel = reduce(lambda x,y: x*y, segmentLabelmap.GetSpacing()) ccPerCubicMM = 0.001 stats = {} if "voxel_count" in requestedKeys: stats["voxel_count"] = stat.GetVoxelCount() if "volume_mm3" in requestedKeys: stats["volume_mm3"] = stat.GetVoxelCount() * cubicMMPerVoxel if "volume_cm3" in requestedKeys: stats["volume_cm3"] = stat.GetVoxelCount() * cubicMMPerVoxel * ccPerCubicMM return stats
def TestSection_MergeLabelmapWithDifferentGeometries(self): # Merge labelmap when segments containing labelmaps with different geometries (both same directions, different directions) logging.info('Test section: Merge labelmap with different geometries') self.assertIsNotNone(self.sphereSegment) self.sphereSegment.RemoveRepresentation(self.binaryLabelmapReprName) self.assertIsNone(self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName)) # Create new segmentation with sphere segment self.secondSegmentationNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode', 'Second') self.secondSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.binaryLabelmapReprName) self.secondSegmentationNode.GetSegmentation().AddSegment(self.sphereSegment) # Check automatically converted labelmap. It is supposed to have the default geometry # (which is different than the one in the input segmentation) sphereLabelmap = self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName) self.assertIsNotNone(sphereLabelmap) sphereLabelmapSpacing = sphereLabelmap.GetSpacing() self.assertAlmostEqual(sphereLabelmapSpacing[0], 0.629257364931788, 8) self.assertAlmostEqual(sphereLabelmapSpacing[1], 0.629257364931788, 8) self.assertAlmostEqual(sphereLabelmapSpacing[2], 0.629257364931788, 8) # Create binary labelmap in segmentation that will create the merged labelmap from # different geometries so that labelmap is not removed from sphere segment when adding self.inputSegmentationNode.GetSegmentation().CreateRepresentation(self.binaryLabelmapReprName) # Copy segment to input segmentation self.inputSegmentationNode.GetSegmentation().CopySegmentFromSegmentation(self.secondSegmentationNode.GetSegmentation(), self.sphereSegmentName) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) # Check merged labelmap # Reference geometry has the tiny patient spacing, and it is oversampled to have similar # voxel size as the sphere labelmap with the uniform 0.629mm spacing mergedLabelmap = vtkSegmentationCore.vtkOrientedImageData() self.inputSegmentationNode.GenerateMergedLabelmapForAllSegments(mergedLabelmap, 0) mergedLabelmapSpacing = mergedLabelmap.GetSpacing() self.assertAlmostEqual(mergedLabelmapSpacing[0], 0.80327868852459, 8) self.assertAlmostEqual(mergedLabelmapSpacing[1], 0.80327868852459, 8) self.assertAlmostEqual(mergedLabelmapSpacing[2], 0.377049180327869, 8) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(mergedLabelmap) imageStat.SetComponentExtent(0, 5, 0, 0, 0, 0) imageStat.SetComponentOrigin(0, 0, 0) imageStat.SetComponentSpacing(1, 1, 1) imageStat.Update() imageStatResult = imageStat.GetOutput() for i in range(5): logging.info(f"Volume {i}: {imageStatResult.GetScalarComponentAsDouble(i,0,0,0)}") self.assertEqual(imageStat.GetVoxelCount(), 226981000) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0, 0, 0, 0), 178838889) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1, 0, 0, 0), 39705288) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2, 0, 0, 0), 890883) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3, 0, 0, 0), 7545940) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(4, 0, 0, 0), 0) # Built from color table and color four is removed in previous test section
def TestSection_MergeLabelmapWithDifferentGeometries(self): # Merge labelmap when segments containing labelmaps with different geometries (both same directions, different directions) logging.info('Test section: Merge labelmap with different geometries') self.assertIsNotNone(self.sphereSegment) self.sphereSegment.RemoveRepresentation(self.binaryLabelmapReprName) self.assertIsNone(self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName)) # Create new segmentation with sphere segment self.secondSegmentationNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode', 'Second') self.secondSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.binaryLabelmapReprName) self.secondSegmentationNode.GetSegmentation().AddSegment(self.sphereSegment) # Check automatically converted labelmap. It is supposed to have the default geometry # (which is different than the one in the input segmentation) sphereLabelmap = self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName) self.assertIsNotNone(sphereLabelmap) sphereLabelmapSpacing = sphereLabelmap.GetSpacing() self.assertAlmostEqual(sphereLabelmapSpacing[0], 0.629257364931788, 8) self.assertAlmostEqual(sphereLabelmapSpacing[1], 0.629257364931788, 8) self.assertAlmostEqual(sphereLabelmapSpacing[2], 0.629257364931788, 8) # Create binary labelmap in segmentation that will create the merged labelmap from # different geometries so that labelmap is not removed from sphere segment when adding self.inputSegmentationNode.GetSegmentation().CreateRepresentation(self.binaryLabelmapReprName) # Copy segment to input segmentation self.inputSegmentationNode.GetSegmentation().CopySegmentFromSegmentation(self.secondSegmentationNode.GetSegmentation(), self.sphereSegmentName) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) # Check merged labelmap # Reference geometry has the tiny patient spacing, and it is oversampled to have similar # voxel size as the sphere labelmap with the uniform 0.629mm spacing mergedLabelmap = vtkSegmentationCore.vtkOrientedImageData() self.inputSegmentationNode.GenerateMergedLabelmapForAllSegments(mergedLabelmap, 0) mergedLabelmapSpacing = mergedLabelmap.GetSpacing() self.assertAlmostEqual(mergedLabelmapSpacing[0], 0.80327868852459, 8) self.assertAlmostEqual(mergedLabelmapSpacing[1], 0.80327868852459, 8) self.assertAlmostEqual(mergedLabelmapSpacing[2], 0.377049180327869, 8) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(mergedLabelmap) imageStat.SetComponentExtent(0,5,0,0,0,0) imageStat.SetComponentOrigin(0,0,0) imageStat.SetComponentSpacing(1,1,1) imageStat.Update() imageStatResult = imageStat.GetOutput() for i in range(5): logging.info("Volume {0}: {1}".format(i, imageStatResult.GetScalarComponentAsDouble(i,0,0,0))) self.assertEqual(imageStat.GetVoxelCount(), 226981000) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0,0,0,0), 178838889) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1,0,0,0), 39705288) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2,0,0,0), 890883) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3,0,0,0), 7545940) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(4,0,0,0), 0) # Built from color table and color four is removed in previous test section
def getSignature(self, seg): if not 'labelmap' in self.__dict__ or not self.labelmap: self.labelmap = slicer.vtkMRMLLabelMapVolumeNode() slicer.mrmlScene.AddNode(self.labelmap) slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode( seg, self.labelmap) stat = vtk.vtkImageAccumulate() stat.SetInputData(self.labelmap.GetImageData()) stat.Update() return int(round(stat.GetMean()[0] * 1e10))
def mean(self, inputVolume, ROIVolume): "Executa a calculo da media dos volumes com a ROI" logging.info('Processing mean: ' + inputVolume.GetName()) if not self.isValidInputOutputData(inputVolume, ROIVolume): slicer.util.errorDisplay( 'Mean: Input volume is the same as output volume. Choose a different output volume.' ) return False stataccum = vtk.vtkImageAccumulate() stataccum.SetInputConnection(ROIVolume.GetImageDataConnection()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) a = slicer.util.array(ROIVolume.GetName()) print a.max() labelValue = a.max() # Create the binary volume of the label thresholder = vtk.vtkImageThreshold() thresholder.SetInputConnection(ROIVolume.GetImageDataConnection()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(labelValue, labelValue) thresholder.SetOutputScalarType( inputVolume.GetImageData().GetScalarType()) thresholder.Update() # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputConnection(thresholder.GetOutputPort()) stencil.ThresholdBetween(1, 1) stat1 = vtk.vtkImageAccumulate() stat1.SetInputConnection(inputVolume.GetImageDataConnection()) stencil.Update() stat1.SetStencilData(stencil.GetOutput()) stat1.Update() return stat1.GetMean()[0]
def TestSection_2_MergeLabelmapWithDifferentGeometries(self): # Merge labelmap when segments containing labelmaps with different geometries (both same directions, different directions) logging.info('Test section 2: Merge labelmap with different geometries') self.assertIsNotNone(self.sphereSegment) self.sphereSegment.RemoveRepresentation(self.binaryLabelmapReprName) self.assertIsNone(self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName)) # Create new segmentation with sphere segment self.secondSegmentationNode = slicer.vtkMRMLSegmentationNode() self.secondSegmentationNode.SetName('Second') self.secondSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.binaryLabelmapReprName) slicer.mrmlScene.AddNode(self.secondSegmentationNode) self.secondSegmentationNode.GetSegmentation().AddSegment(self.sphereSegment) # Check automatically converted labelmap. It is supposed to have the default geometry # (which is different than the one in the input segmentation) sphereLabelmap = self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName) self.assertIsNotNone(sphereLabelmap) sphereLabelmapSpacing = sphereLabelmap.GetSpacing() self.assertTrue(sphereLabelmapSpacing[0] == 1.0 and sphereLabelmapSpacing[1] == 1.0 and sphereLabelmapSpacing[2] == 1.0) # Create binary labelmap in segmentation that will create the merged labelmap from # different geometries so that labelmap is not removed from sphere segment when adding self.inputSegmentationNode.GetSegmentation().CreateRepresentation(self.binaryLabelmapReprName) # Copy segment to input segmentation self.inputSegmentationNode.GetSegmentation().CopySegmentFromSegmentation(self.secondSegmentationNode.GetSegmentation(), self.sphereSegmentName) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) # Check merged labelmap # Reference geometry has the tiny patient spacing, and it is oversampled to have smimilar # voxel size as the sphere labelmap with the uniform 1mm spacing mergedLabelmap = vtkSegmentationCore.vtkOrientedImageData() self.inputSegmentationNode.GenerateMergedLabelmapForAllSegments(mergedLabelmap, 0) mergedLabelmapSpacing = mergedLabelmap.GetSpacing() self.assertAlmostEqual(mergedLabelmapSpacing[0], 1.2894736842, 8) self.assertAlmostEqual(mergedLabelmapSpacing[1], 1.2894736842, 8) self.assertAlmostEqual(mergedLabelmapSpacing[2], 0.6052631578, 8) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(mergedLabelmap) imageStat.SetComponentExtent(0,5,0,0,0,0) imageStat.SetComponentOrigin(0,0,0) imageStat.SetComponentSpacing(1,1,1) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 54872000) imageStatResult = imageStat.GetOutput() self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0,0,0,0), 43573723) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1,0,0,0), 10601312) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2,0,0,0), 274360) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3,0,0,0), 422605) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(4,0,0,0), 0) # Built from color table and color four is removed in previous test section
def imageDataContainsData(self, imageData): if imageData is None: logging.error('Invalid input image data') return False acc = vtk.vtkImageAccumulate() acc.SetInputData(imageData) acc.SetIgnoreZero(1) acc.Update() if acc.GetVoxelCount() > 0: return True return False
def ResetWindowLevel(self): if self.IsLocked(): return if self.Image: return self.Image.UpdateInformation() self.Image.SetUpdateExtent(self.Image.GetWholeExtent()) self.Image.Update() if (self.Image.GetScalarType() == vtk.VTK_UNSIGNED_CHAR and (self.Image.GetNumberOfScalarComponents() == 3 or self.Image.GetNumberOfScalarComponents() == 4 )): return range = self.Image.GetScalarRange() histogram = vtk.vtkImageAccumulate() histogram.SetInput(self.Image) histogram.SetComponentExtent(0, 1000, 0, 0, 0, 0) histogram.SetComponentSpacing((range[1]-range[0])/1000.0, 0.0, 0.0) histogram.SetComponentOrigin(range[0], 0.0, 0.0) histogram.Update() output = histogram.GetOutput() ptData = output.GetPointData().GetScalars() if ptData: raise RuntimeError, "Error: Cannot cast point data to integers." numVox = histogram.GetVoxelCount() onePercent = numVox/100.0 start = 1 currentPercent = 0.0 while (currentPercent<0.1 and start<999): ptData.GetTuple(start, tuple) currentPercent = currentPercent + tuple/onePercent start = start+1 currentPercent = 0.0 end = 999 while (currentPercent<0.1 and end>0): ptData.GetTuple(start, tuple) currentPercent = currentPercent + tuple/onePercent end = end-1 window = (end-start)*(range[1]-range[0])/1000.0 level = 0.5*(start + end)*(range[1]-range[0])/1000.0 window = (window-self.Shift)/self.Scale level = (level-self.Shift)/self.Scale self.SetWindow(window) self.SetLevel(level) del histogram
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__( self, module_manager, vtk.vtkImageAccumulate(), "Processing.", ("vtkImageData", "vtkImageStencilData"), ("vtkImageData",), replaceDoc=True, inputFunctions=None, outputFunctions=None, )
def CalculateHistogram(self): proj = prj.Project() image = proj.imagedata r = int(image.GetScalarRange()[1] - image.GetScalarRange()[0]) accumulate = vtk.vtkImageAccumulate() accumulate.SetInput(image) accumulate.SetComponentExtent(0, r -1, 0, 0, 0, 0) accumulate.SetComponentOrigin(image.GetScalarRange()[0], 0, 0) accumulate.Update() n_image = numpy_support.vtk_to_numpy(accumulate.GetOutput().GetPointData().GetScalars()) ps.Publisher().sendMessage('Load histogram', (n_image, image.GetScalarRange()))
def test_seedconnect(self): """Test whether we can load and run a full network, select a point and do a region growing. This broke with the introduction of vtk 5.6.1 due to more strict casting. """ # load our little test network ##### self._ge._load_and_realise_network( os.path.join(self._devide_testing.get_networks_dir(), 'seedconnect.dvn')) # run the network once self._ge._handler_execute_network(None) self._ge.canvas.redraw() # now find the slice3dVWR ##### mm = self._devide_app.get_module_manager() svmod = mm.get_instance("svmod") # let's show the control frame svmod._handlerShowControls(None) if True: # we're doing this the long way to test more code paths svmod.sliceDirections.setCurrentCursor([20.0, 20.0, 20.0, 1.0]) # this handler should result in the whole network being auto-executed # but somehow it blocks execution (the vktImageSeedConnect sticks at 0.0) svmod.selectedPoints._handlerStoreCursorAsPoint(None) else: # it seems to block here as well: the whole network is linked up, # so it tries to execute when the storeCursor is called, and that # blocks everything. WHY?! #svmod.selectedPoints._storeCursor((20.0,20.0,20.0,1.0)) #self.failUnless(len(svmod.selectedPoints._pointsList) == 1) # execute the network self._ge._handler_execute_network(None) # now count the number of voxels in the segmented result import vtk via = vtk.vtkImageAccumulate() scmod = mm.get_instance("scmod") via.SetInput(scmod.get_output(0)) via.Update() # get second bin of output histogram: that should be the # number of voxels s = via.GetOutput().GetPointData().GetScalars() print s.GetTuple1(1) self.failUnless(s.GetTuple1(1) == 26728) via.SetInput(None) del via
def CalculateHistogram(self): image = self.image r = int(image.GetScalarRange()[1] - image.GetScalarRange()[0]) accumulate = vtk.vtkImageAccumulate() accumulate.SetInputData(image) accumulate.SetComponentExtent(0, r -1, 0, 0, 0, 0) accumulate.SetComponentOrigin(image.GetScalarRange()[0], 0, 0) # accumulate.ReleaseDataFlagOn() accumulate.Update() n_image = numpy_support.vtk_to_numpy(accumulate.GetOutput().GetPointData().GetScalars()) del accumulate Publisher.sendMessage('Load histogram', (n_image, image.GetScalarRange()))
def CalculateHistogram(self): image = self.image r = int(image.GetScalarRange()[1] - image.GetScalarRange()[0]) accumulate = vtk.vtkImageAccumulate() accumulate.SetInputData(image) accumulate.SetComponentExtent(0, r -1, 0, 0, 0, 0) accumulate.SetComponentOrigin(image.GetScalarRange()[0], 0, 0) # accumulate.ReleaseDataFlagOn() accumulate.Update() n_image = numpy_support.vtk_to_numpy(accumulate.GetOutput().GetPointData().GetScalars()) del accumulate Publisher.sendMessage('Load histogram', (n_image, image.GetScalarRange()))
def computeStatistics(self, segmentID): requestedKeys = self.getRequestedKeys() segmentationNode = slicer.mrmlScene.GetNodeByID( self.getParameterNode().GetParameter("Segmentation")) grayscaleNode = slicer.mrmlScene.GetNodeByID( self.getParameterNode().GetParameter("ScalarVolume")) if len(requestedKeys) == 0: return {} stencil = self.getStencilForVolume(segmentationNode, segmentID, grayscaleNode) if not stencil: return {} cubicMMPerVoxel = reduce(lambda x, y: x * y, grayscaleNode.GetSpacing()) ccPerCubicMM = 0.001 stat = vtk.vtkImageAccumulate() stat.SetInputData(grayscaleNode.GetImageData()) stat.SetStencilData(stencil.GetOutput()) stat.Update() medians = vtk.vtkImageHistogramStatistics() medians.SetInputData(grayscaleNode.GetImageData()) medians.SetStencilData(stencil.GetOutput()) medians.Update() # create statistics list stats = {} if "voxel_count" in requestedKeys: stats["voxel_count"] = stat.GetVoxelCount() if "volume_mm3" in requestedKeys: stats["volume_mm3"] = stat.GetVoxelCount() * cubicMMPerVoxel if "volume_cm3" in requestedKeys: stats["volume_cm3"] = stat.GetVoxelCount( ) * cubicMMPerVoxel * ccPerCubicMM if stat.GetVoxelCount() > 0: if "min" in requestedKeys: stats["min"] = stat.GetMin()[0] if "max" in requestedKeys: stats["max"] = stat.GetMax()[0] if "mean" in requestedKeys: stats["mean"] = stat.GetMean()[0] if "stdev" in requestedKeys: stats["stdev"] = stat.GetStandardDeviation()[0] if "median" in requestedKeys: stats["median"] = medians.GetMedian() return stats
def addSegmentLabelmapStatistics(self): import vtkSegmentationCorePython as vtkSegmentationCore containsLabelmapRepresentation = self.segmentationNode.GetSegmentation( ).ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter. GetSegmentationBinaryLabelmapRepresentationName()) if not containsLabelmapRepresentation: return for segmentID in self.statistics["SegmentIDs"]: segment = self.segmentationNode.GetSegmentation().GetSegment( segmentID) segmentLabelmap = segment.GetRepresentation( vtkSegmentationCore.vtkSegmentationConverter. GetSegmentationBinaryLabelmapRepresentationName()) # We need to know exactly the value of the segment voxels, apply threshold to make force the selected label value labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() thresh.SetInputData(segmentLabelmap) thresh.ThresholdByLower(0) thresh.SetInValue(backgroundValue) thresh.SetOutValue(labelValue) thresh.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) thresh.Update() # Use binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputData(thresh.GetOutput()) stencil.ThresholdByUpper(labelValue) stencil.Update() stat = vtk.vtkImageAccumulate() stat.SetInputData(thresh.GetOutput()) stat.SetStencilData(stencil.GetOutput()) stat.Update() # Add data to statistics list cubicMMPerVoxel = reduce(lambda x, y: x * y, segmentLabelmap.GetSpacing()) ccPerCubicMM = 0.001 self.statistics[segmentID, "LM voxel count"] = stat.GetVoxelCount() self.statistics[ segmentID, "LM volume mm3"] = stat.GetVoxelCount() * cubicMMPerVoxel self.statistics[segmentID, "LM volume cc"] = stat.GetVoxelCount( ) * cubicMMPerVoxel * ccPerCubicMM
def split(self): """split the merge volume into individual structures""" self.statusText("Splitting...") merge = self.merge if not merge: return colorNode = merge.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: accum.SetInput(merge.GetImageData()) else: accum.SetInputConnection(merge.GetImageDataConnection()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) # TODO: pending resolution of bug 1822, run the thresholding # in single threaded mode to avoid data corruption observed on mac release # builds thresholder = vtk.vtkImageThreshold() thresholder.SetNumberOfThreads(1) for i in xrange(lo, hi + 1): self.statusText("Splitting label %d..." % i) if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput(merge.GetImageData()) else: thresholder.SetInputConnection(merge.GetImageDataConnection()) thresholder.SetInValue(i) thresholder.SetOutValue(0) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( merge.GetImageData().GetScalarType()) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): labelName = colorNode.GetColorName(i) self.statusText("Creating structure volume %s..." % labelName) structureVolume = self.structureVolume(labelName) if not structureVolume: self.addStructure(i, "noEdit") structureVolume = self.structureVolume(labelName) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput()) EditUtil.markVolumeNodeAsModified(structureVolume) self.statusText("Finished splitting.")
def getLabelsFromLabelMap(self, labelMapNode): if not labelMapNode: return accum = vtk.vtkImageAccumulate() accum.SetInput(labelMapNode.GetImageData()) accum.UpdateWholeExtent() data = accum.GetOutput() data.Update() numBins = accum.GetComponentExtent()[1] nonZeroLabels = [] for i in range(0, numBins + 1): numVoxels = data.GetScalarComponentAsDouble(i, 0, 0, 0) if (numVoxels != 0): nonZeroLabels.append(i) return nonZeroLabels
def getLabelsFromLabelMap(self, labelMapNode): if not labelMapNode: return accum = vtk.vtkImageAccumulate() accum.SetInput(labelMapNode.GetImageData()) accum.UpdateWholeExtent() data = accum.GetOutput() data.Update() numBins = accum.GetComponentExtent()[1] nonZeroLabels = [] for i in range(0, numBins + 1): numVoxels = data.GetScalarComponentAsDouble(i,0,0,0) if (numVoxels != 0): nonZeroLabels.append(i) return nonZeroLabels
def AddSegmentNode(self, modelNode, volumeLabel): #This function creates a segmentation from the output model (ie cropped breast models) # and computed the volume of the segmentation, this is done to ensure the volume is computed correctly segmentationNode = slicer.vtkMRMLSegmentationNode() slicer.mrmlScene.AddNode(segmentationNode) displayNode = slicer.mrmlScene.GetNthNodeByClass(1, 'vtkMRMLScalarVolumeDisplayNode') if displayNode == None: displayNode = slicer.vtkMRMLScalarVolumeDisplayNode() segmentationNode.SetAndObserveDisplayNodeID(displayNode.GetID()) segmentationNode.SetName("Model Segmentation Node") slicer.modules.segmentations.logic().ImportModelToSegmentationNode(modelNode, segmentationNode) segment = segmentationNode.GetSegmentation().GetNthSegment(0) segBinaryLabelName = vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName() segmentLabelmap = segment.GetRepresentation(segBinaryLabelName) # We need to know exactly the value of the segment voxels, apply threshold to make force the selected label value labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() thresh.SetInputData(segmentLabelmap) thresh.ThresholdByLower(0) thresh.SetInValue(backgroundValue) thresh.SetOutValue(labelValue) thresh.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) thresh.Update() # Use binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputData(thresh.GetOutput()) stencil.ThresholdByUpper(labelValue) stencil.Update() stat = vtk.vtkImageAccumulate() stat.SetInputData(thresh.GetOutput()) stat.SetStencilData(stencil.GetOutput()) stat.Update() # Add data to statistics list cubicMMPerVoxel = reduce(lambda x, y: x * y, segmentLabelmap.GetSpacing()) ccPerCubicMM = 0.001 stats = {} volume = round(stat.GetVoxelCount() * cubicMMPerVoxel * ccPerCubicMM, 0) volumeLabel.setText(volume) slicer.mrmlScene.RemoveNode(segmentationNode) return volume
def histo(im): accumulate = vtk.vtkImageAccumulate() accumulate.SetInput(im) accumulate.SetComponentSpacing(1, 0, 0) accumulate.SetComponentOrigin(0, 0, 0) accumulate.SetComponentExtent(0, 12000, 0, 0, 0, 0) accumulate.Update() print "!- Histogram -------------------------------------------------------------" print " min %8.2f" % (accumulate.GetMin()[0]) print " max %8.2f" % (accumulate.GetMax()[0]) print " mean %8.2f" % (accumulate.GetMean()[0]) print " SD %8.2f" % (accumulate.GetStandardDeviation()[0]) print " voxel count %8d" % (accumulate.GetVoxelCount()) print "!-------------------------------------------------------------------------" print " "
def TestSection_2_MergeLabelmapWithDifferentGeometries(self): # Merge labelmap when segments containing labelmaps with different geometries (both same directions, different directions) logging.info('Test section 2: Merge labelmap with different geometries') self.assertIsNotNone(self.sphereSegment) self.sphereSegment.RemoveRepresentation(self.binaryLabelmapReprName) self.assertIsNone(self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName)) # Create new segmentation with sphere segment self.secondSegmentationNode = vtkMRMLSegmentationNode() self.secondSegmentationNode.SetName('Second') self.secondSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.binaryLabelmapReprName) slicer.mrmlScene.AddNode(self.secondSegmentationNode) self.secondSegmentationNode.GetSegmentation().AddSegment(self.sphereSegment) # Check automatically converted labelmap. It is supposed to have the default geometry # (which is different than the one in the input segmentation) sphereLabelmap = self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName) self.assertIsNotNone(sphereLabelmap) sphereLabelmapSpacing = sphereLabelmap.GetSpacing() self.assertTrue(sphereLabelmapSpacing[0] == 1.0 and sphereLabelmapSpacing[1] == 1.0 and sphereLabelmapSpacing[2] == 1.0) # Copy segment to input segmentation self.inputSegmentationNode.GetSegmentation().CopySegmentFromSegmentation(self.secondSegmentationNode.GetSegmentation(), self.sphereSegmentName) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) # Check merged labelmap mergedLabelmap = self.inputSegmentationNode.GetImageData() self.assertIsNotNone(mergedLabelmap) mergedLabelmapSpacing = sphereLabelmap.GetSpacing() self.assertTrue(mergedLabelmapSpacing[0] == 1.0 and mergedLabelmapSpacing[1] == 1.0 and mergedLabelmapSpacing[2] == 1.0) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(mergedLabelmap) imageStat.SetComponentExtent(0,5,0,0,0,0) imageStat.SetComponentOrigin(0,0,0) imageStat.SetComponentSpacing(1,1,1) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 54872000) imageStatResult = imageStat.GetOutput() self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0,0,0,0), 46678738) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1,0,0,0), 0) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2,0,0,0), 7618805) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3,0,0,0), 128968) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(4,0,0,0), 0) # Built from color table and color four is removed in previous test section self.assertEqual(imageStatResult.GetScalarComponentAsDouble(5,0,0,0), 445489)
def split(self): """split the merge volume into individual structures""" self.statusText( "Splitting..." ) merge = self.merge if not merge: return colorNode = merge.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: accum.SetInput(merge.GetImageData()) else: accum.SetInputConnection(merge.GetImageDataConnection()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) # TODO: pending resolution of bug 1822, run the thresholding # in single threaded mode to avoid data corruption observed on mac release # builds thresholder = vtk.vtkImageThreshold() thresholder.SetNumberOfThreads(1) for i in xrange(lo,hi+1): self.statusText( "Splitting label %d..."%i ) if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput( merge.GetImageData() ) else: thresholder.SetInputConnection( merge.GetImageDataConnection() ) thresholder.SetInValue( i ) thresholder.SetOutValue( 0 ) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween( i, i ) thresholder.SetOutputScalarType( merge.GetImageData().GetScalarType() ) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): labelName = colorNode.GetColorName(i) self.statusText( "Creating structure volume %s..."%labelName ) structureVolume = self.structureVolume( labelName ) if not structureVolume: self.addStructure( i, "noEdit" ) structureVolume = self.structureVolume( labelName ) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput() ) EditUtil.markVolumeNodeAsModified(structureVolume) self.statusText( "Finished splitting." )
def checkSegmentVoxelCount(self, segmentIndex, expectedVoxelCount): segment = self.segmentation.GetNthSegment(segmentIndex) self.assertIsNotNone(segment) labelmap = slicer.vtkOrientedImageData() segmentID = self.segmentation.GetNthSegmentID(segmentIndex) self.segmentationNode.GetBinaryLabelmapRepresentation(segmentID, labelmap) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(labelmap) imageStat.SetComponentExtent(0,4,0,0,0,0) imageStat.SetComponentOrigin(0,0,0) imageStat.SetComponentSpacing(1,1,1) imageStat.IgnoreZeroOn() imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), expectedVoxelCount)
def splitPerStructureVolumes(masterNode, mergeNode): """Make a separate label map node for each non-empty label value in the merged label map""" colorNode = mergeNode.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() accum.SetInputConnection(mergeNode.GetImageDataConnection()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) # TODO: pending resolution of bug 1822, run the thresholding # in single threaded mode to avoid data corruption observed on mac release # builds thresholder = vtk.vtkImageThreshold() thresholder.SetNumberOfThreads(1) for index in xrange(lo, hi + 1): logging.info("Splitting label %d..." % index) if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput(mergeNode.GetImageData()) else: thresholder.SetInputConnection( mergeNode.GetImageDataConnection()) thresholder.SetInValue(index) thresholder.SetOutValue(0) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween(index, index) thresholder.SetOutputScalarType( mergeNode.GetImageData().GetScalarType()) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): structureName = colorNode.GetColorName(index) logging.info("Creating structure volume %s..." % structureName) structureVolume = EditUtil.structureVolume( masterNode, structureName) if not structureVolume: EditUtil.addStructure(masterNode, mergeNode, index) structureVolume = EditUtil.structureVolume( masterNode, structureName) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput()) EditUtil.markVolumeNodeAsModified(structureVolume)
def __init__(self, module_manager): ModuleBase.__init__(self, module_manager) self._imageAccumulate = vtk.vtkImageAccumulate() module_utils.setup_vtk_object_progress(self, self._imageAccumulate, "Calculating histogram") self._viewFrame = None self._createViewFrame() self._bindEvents() self._config.numberOfBins = 256 self._config.minValue = 0.0 self._config.maxValue = 256.0 self.config_to_logic() self.logic_to_config() self.config_to_view() self.view()
def __init__(self, module_manager): ModuleBase.__init__(self, module_manager) self._imageAccumulate = vtk.vtkImageAccumulate() module_utils.setup_vtk_object_progress(self, self._imageAccumulate, 'Calculating histogram') self._viewFrame = None self._createViewFrame() self._bindEvents() self._config.numberOfBins = 256 self._config.minValue = 0.0 self._config.maxValue = 256.0 self.config_to_logic() self.logic_to_config() self.config_to_view() self.view()
def compareVolumes(self, volume1, volume2): subtractFilter = vtk.vtkImageMathematics() subtractFilter.SetOperationToSubtract() subtractFilter.SetInput1Data(volume1.GetImageData()) subtractFilter.SetInput2Data(volume2.GetImageData()) subtractFilter.Update() histogramFilter = vtk.vtkImageAccumulate() histogramFilter.SetComponentSpacing([1,0,0]) histogramFilter.SetInputData(subtractFilter.GetOutput()) histogramFilter.Update() # Both should be zero if generated scanlines == groundtruth maxValue = histogramFilter.GetMax() minValue = histogramFilter.GetMin() if (maxValue[0] == 0 and minValue[0] == 0): return True else: return False
def addSegmentLabelmapStatistics(self): import vtkSegmentationCorePython as vtkSegmentationCore containsLabelmapRepresentation = self.segmentationNode.GetSegmentation().ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()) if not containsLabelmapRepresentation: return for segmentID in self.statistics["SegmentIDs"]: segment = self.segmentationNode.GetSegmentation().GetSegment(segmentID) segmentLabelmap = segment.GetRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()) # We need to know exactly the value of the segment voxels, apply threshold to make force the selected label value labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() thresh.SetInputData(segmentLabelmap) thresh.ThresholdByLower(0) thresh.SetInValue(backgroundValue) thresh.SetOutValue(labelValue) thresh.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) thresh.Update() # Use binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputData(thresh.GetOutput()) stencil.ThresholdByUpper(labelValue) stencil.Update() stat = vtk.vtkImageAccumulate() stat.SetInputData(thresh.GetOutput()) stat.SetStencilData(stencil.GetOutput()) stat.Update() # Add data to statistics list cubicMMPerVoxel = reduce(lambda x,y: x*y, segmentLabelmap.GetSpacing()) ccPerCubicMM = 0.001 self.statistics[segmentID,"LM voxel count"] = stat.GetVoxelCount() self.statistics[segmentID,"LM volume mm3"] = stat.GetVoxelCount() * cubicMMPerVoxel self.statistics[segmentID,"LM volume cc"] = stat.GetVoxelCount() * cubicMMPerVoxel * ccPerCubicMM
def execute_module(self): # FIXME: if this module ever becomes anything other than an experiment, build # this logic into yet another ProgrammableSource # make sure marker is up to date self._markerSource.GetStructuredPointsOutput().Update() self._maskSource.GetStructuredPointsOutput().Update() tempJ = vtk.vtkStructuredPoints() tempJ.DeepCopy(self._markerSource.GetStructuredPointsOutput()) self._imageErode.SetInput(tempJ) self._diff = vtk.vtkImageMathematics() self._diff.SetOperationToSubtract() self._accum = vtk.vtkImageAccumulate() self._accum.SetInput(self._diff.GetOutput()) # now begin our loop stable = False while not stable: # do erosion, get supremum of erosion and mask I self._sup.GetOutput().Update() # compare this result with tempJ self._diff.SetInput1(tempJ) self._diff.SetInput2(self._sup.GetOutput()) self._accum.Update() print "%f == %f ?" % (self._accum.GetMin()[0], self._accum.GetMax()[0]) if abs(self._accum.GetMin()[0] - self._accum.GetMax()[0]) < 0.0001: stable = True else: # not stable yet... print "Trying again..." tempJ.DeepCopy(self._sup.GetOutput())
def UpdateSampleHistogram(obj, ev): # For viewport 3, construct the histogram of the sampled data using vtkImageAccumulate class histogram = vtk.vtkImageAccumulate() # retrieve the scalar range of the plane widget using GetScalarRange() range = obj.GetResliceOutput().GetScalarRange() r = int(range[1] - range[0]) # using GetResliceOutput() function to get sampled data from vtkImagePlaneWidget object histogram.SetInputData(obj.GetResliceOutput()) histogram.SetComponentExtent(0, r - 1, 0, 0, 0, 0) histogram.SetComponentOrigin(range[0], 0.0, 0.0) histogram.SetComponentSpacing(100, 0, 0) histogram.Update() # In viewport 3, using vtkXYPlotActor class for plotting the histogram plot = vtk.vtkXYPlotActor() plot.AddDataSetInputConnection(histogram.GetOutputPort()) plot.SetXRange(range[0], range[1]) plot.SetLabelFormat("%g") plot.SetXTitle("Scalar Value") plot.SetYTitle("Frequency") plot.SetXValuesToValue() ren[2].AddActor(plot)
def execute_module(self): # FIXME: if this module ever becomes anything other than an experiment, build # this logic into yet another ProgrammableSource # make sure marker is up to date self._markerSource.GetStructuredPointsOutput().Update() self._maskSource.GetStructuredPointsOutput().Update() tempJ = vtk.vtkStructuredPoints() tempJ.DeepCopy(self._markerSource.GetStructuredPointsOutput()) self._imageErode.SetInput(tempJ) self._diff = vtk.vtkImageMathematics() self._diff.SetOperationToSubtract() self._accum = vtk.vtkImageAccumulate() self._accum.SetInput(self._diff.GetOutput()) # now begin our loop stable = False while not stable: # do erosion, get supremum of erosion and mask I self._sup.GetOutput().Update() # compare this result with tempJ self._diff.SetInput1(tempJ) self._diff.SetInput2(self._sup.GetOutput()) self._accum.Update() print "%f == %f ?" % (self._accum.GetMin()[0], self._accum.GetMax()[0]) if abs(self._accum.GetMin()[0] - self._accum.GetMax()[0]) < 0.0001: stable = True else: # not stable yet... print "Trying again..." tempJ.DeepCopy(self._sup.GetOutput())
def __init__( self, *args ): wx.Panel.__init__( self, *args ) wx.EVT_PAINT(self, self.OnPaint) self.SetSize(wx.Size(100, 150)) from vtk import vtkImageAccumulate self.accumulateFilter = vtkImageAccumulate()
def TestSection_1_RunPlastimatchProtonDoseEngine(self): logging.info('Test section 1: Run Plastimatch proton dose engine') engineLogic = slicer.qSlicerDoseEngineLogic() engineLogic.setMRMLScene(slicer.mrmlScene) # Get input ctVolumeNode = slicer.util.getNode('TinyPatient_CT') segmentationNode = slicer.util.getNode('TinyPatient_Structures') self.assertIsNotNone(ctVolumeNode) self.assertIsNotNone(segmentationNode) # Create node for output dose totalDoseVolumeNode = slicer.vtkMRMLScalarVolumeNode() totalDoseVolumeNode.SetName('TotalDose') slicer.mrmlScene.AddNode(totalDoseVolumeNode) # Setup plan planNode = slicer.vtkMRMLRTPlanNode() planNode.SetName('TestProtonPlan') slicer.mrmlScene.AddNode(planNode) planNode.SetAndObserveReferenceVolumeNode(ctVolumeNode); planNode.SetAndObserveSegmentationNode(segmentationNode); planNode.SetAndObserveOutputTotalDoseVolumeNode(totalDoseVolumeNode); planNode.SetTargetSegmentID("Tumor_Contour"); planNode.SetIsocenterToTargetCenter(); planNode.SetDoseEngineName(self.plastimatchProtonDoseEngineName) # Add first beam firstBeamNode = engineLogic.createBeamInPlan(planNode) firstBeamNode.SetX1Jaw(-50.0) firstBeamNode.SetX2Jaw(50.0) firstBeamNode.SetY1Jaw(-50.0) firstBeamNode.SetY2Jaw(75.0) #TODO: For some reason the instance() function cannot be called as a class function although it's static engineHandler = slicer.qSlicerDoseEnginePluginHandler() engineHandlerSingleton = engineHandler.instance() plastimatchProtonEngine = engineHandlerSingleton.doseEngineByName(self.plastimatchProtonDoseEngineName) plastimatchProtonEngine.setParameter(firstBeamNode, 'EnergyResolution', 4.0) plastimatchProtonEngine.setParameter(firstBeamNode, 'RangeCompensatorSmearingRadius', 0.0) plastimatchProtonEngine.setParameter(firstBeamNode, 'ProximalMargin', 0.0) plastimatchProtonEngine.setParameter(firstBeamNode, 'DistalMargin', 0.0) # Calculate dose import time startTime = time.time() errorMessage = engineLogic.calculateDose(planNode) self.assertEqual(errorMessage, "") calculationTime = time.time() - startTime logging.info('Dose computation time: ' + str(calculationTime) + ' s') # Check computed output imageAccumulate = vtk.vtkImageAccumulate() imageAccumulate.SetInputConnection(totalDoseVolumeNode.GetImageDataConnection()) imageAccumulate.Update() doseMax = imageAccumulate.GetMax()[0] doseMean = imageAccumulate.GetMean()[0] doseStdDev = imageAccumulate.GetStandardDeviation()[0] doseVoxelCount = imageAccumulate.GetVoxelCount() logging.info("Dose volume properties:\n Max=" + str(doseMax) + ", Mean=" + str(doseMean) + ", StdDev=" + str(doseStdDev) + ", NumberOfVoxels=" + str(doseVoxelCount)) self.assertTrue(self.isEqualWithTolerance(doseMax, 1.09556)) self.assertTrue(self.isEqualWithTolerance(doseMean, 0.01670)) self.assertTrue(self.isEqualWithTolerance(doseStdDev, 0.12670)) self.assertTrue(self.isEqualWithTolerance(doseVoxelCount, 1000))
#!/usr/bin/env python import vtk from vtk.test import Testing from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() # Image pipeline reader = vtk.vtkPNGReader() reader.SetFileName("" + str(VTK_DATA_ROOT) + "/Data/fullhead15.png") smooth = vtk.vtkImageGaussianSmooth() smooth.SetDimensionality(2) smooth.SetStandardDeviations(1,1) smooth.SetInputConnection(reader.GetOutputPort()) imageAppend = vtk.vtkImageAppendComponents() imageAppend.AddInputConnection(reader.GetOutputPort()) imageAppend.AddInputConnection(smooth.GetOutputPort()) clip = vtk.vtkImageClip() clip.SetInputConnection(imageAppend.GetOutputPort()) clip.SetOutputWholeExtent(0,255,0,255,20,22) accum = vtk.vtkImageAccumulate() accum.SetInputConnection(clip.GetOutputPort()) accum.SetComponentExtent(0,255,0,255,0,0) accum.SetComponentSpacing(12,12,0.0) viewer = vtk.vtkImageViewer() viewer.SetInputConnection(accum.GetOutputPort()) viewer.SetColorWindow(4) viewer.SetColorLevel(2) viewer.Render() # --- end of script --
def __init__(self, grayscaleNode, labelNode, fileName=None): #import numpy self.keys = ("Index", "Count", "Volume mm^3", "Volume cc", "Min", "Max", "Mean", "StdDev") cubicMMPerVoxel = reduce(lambda x,y: x*y, labelNode.GetSpacing()) ccPerCubicMM = 0.001 # TODO: progress and status updates # this->InvokeEvent(vtkLabelStatisticsLogic::StartLabelStats, (void*)"start label stats") self.labelNode = labelNode self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: stataccum.SetInput(labelNode.GetImageData()) else: stataccum.SetInputConnection(labelNode.GetImageDataConnection()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) for i in xrange(lo,hi+1): # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkLabelStatisticsLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 LabelStatistics # to create the binary volume of the label # //logic copied from slicer2 LabelStatistics MaskStat # // create the binary volume of the label thresholder = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput(labelNode.GetImageData()) else: thresholder.SetInputConnection(labelNode.GetImageDataConnection()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i,i) thresholder.SetOutputScalarType(grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: stencil.SetInput(thresholder.GetOutput()) else: stencil.SetInputConnection(thresholder.GetOutputPort()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) else: stat1.SetInputConnection(grayscaleNode.GetImageDataConnection()) stencil.Update() stat1.SetStencilData(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i,"Index"] = i self.labelStats[i,"Count"] = stat1.GetVoxelCount() self.labelStats[i,"Volume mm^3"] = self.labelStats[i,"Count"] * cubicMMPerVoxel self.labelStats[i,"Volume cc"] = self.labelStats[i,"Volume mm^3"] * ccPerCubicMM self.labelStats[i,"Min"] = stat1.GetMin()[0] self.labelStats[i,"Max"] = stat1.GetMax()[0] self.labelStats[i,"Mean"] = stat1.GetMean()[0] self.labelStats[i,"StdDev"] = stat1.GetStandardDeviation()[0]
def TestSection_1_RunPlastimatchProtonDoseEngine(self): logging.info('Test section 1: Run Plastimatch proton dose engine') engineLogic = slicer.qSlicerDoseEngineLogic() engineLogic.setMRMLScene(slicer.mrmlScene) # Get input ctVolumeNode = slicer.util.getNode('TinyPatient_CT') segmentationNode = slicer.util.getNode('TinyPatient_Structures') self.assertIsNotNone(ctVolumeNode) self.assertIsNotNone(segmentationNode) # Create node for output dose totalDoseVolumeNode = slicer.vtkMRMLScalarVolumeNode() totalDoseVolumeNode.SetName('TotalDose') slicer.mrmlScene.AddNode(totalDoseVolumeNode) # Setup plan planNode = slicer.vtkMRMLRTPlanNode() planNode.SetName('TestProtonPlan') slicer.mrmlScene.AddNode(planNode) planNode.SetAndObserveReferenceVolumeNode(ctVolumeNode); planNode.SetAndObserveSegmentationNode(segmentationNode); planNode.SetAndObserveOutputTotalDoseVolumeNode(totalDoseVolumeNode); planNode.SetTargetSegmentID("Tumor_Contour"); planNode.SetIsocenterToTargetCenter(); planNode.SetDoseEngineName("Plastimatch proton") # Add first beam firstBeamNode = engineLogic.createBeamInPlan(planNode) firstBeamNode.SetX1Jaw(-50.0) firstBeamNode.SetX2Jaw(50.0) firstBeamNode.SetY1Jaw(-50.0) firstBeamNode.SetY2Jaw(75.0) #TODO: For some reason the instance() function cannot be called as a class function although it's static engineHandler = slicer.qSlicerDoseEnginePluginHandler() engineHandlerSingleton = engineHandler.instance() plastimatchProtonEngine = engineHandlerSingleton.doseEngineByName('Plastimatch proton') plastimatchProtonEngine.setParameter(firstBeamNode, 'EnergyResolution', 4.0) plastimatchProtonEngine.setParameter(firstBeamNode, 'RangeCompensatorSmearingRadius', 0.0) plastimatchProtonEngine.setParameter(firstBeamNode, 'ProximalMargin', 0.0) plastimatchProtonEngine.setParameter(firstBeamNode, 'DistalMargin', 0.0) # Calculate dose import time startTime = time.time() errorMessage = engineLogic.calculateDose(planNode) self.assertNotEqual(errorMessage, "") calculationTime = time.time() - startTime logging.info('Dose computation time: ' + str(calculationTime) + ' s') # Check computed output imageAccumulate = vtk.vtkImageAccumulate() imageAccumulate.SetInputConnection(totalDoseVolumeNode.GetImageDataConnection()) imageAccumulate.Update() doseMax = imageAccumulate.GetMax()[0] doseMean = imageAccumulate.GetMean()[0] doseStdDev = imageAccumulate.GetStandardDeviation()[0] doseVoxelCount = imageAccumulate.GetVoxelCount() logging.info("Dose volume properties:\n Max=" + str(doseMax) + ", Mean=" + str(doseMean) + ", StdDev=" + str(doseStdDev) + ", NumberOfVoxels=" + str(doseVoxelCount)) self.assertTrue(self.isEqualWithTolerance(doseMax, 1.05797)) self.assertTrue(self.isEqualWithTolerance(doseMean, 0.0251127)) self.assertTrue(self.isEqualWithTolerance(doseStdDev, 0.144932)) self.assertTrue(self.isEqualWithTolerance(doseVoxelCount, 1000))
def scatterPlot(imagedata1, imagedata2, z, countVoxels=True, wholeVolume=True, logarithmic=True, bitDepth=8): """ Create scatterplot """ imagedata1.SetUpdateExtent(imagedata1.GetWholeExtent()) imagedata2.SetUpdateExtent(imagedata1.GetWholeExtent()) imagedata1.Update() imagedata2.Update() range1 = imagedata1.GetScalarRange() range2 = imagedata2.GetScalarRange() n = 255 # n = min(max(sc1max,sc2max),255) # d = (n+1) / float(2**bitDepth) if bitDepth is None: spacing1 = float(abs(range1[1] - range1[0])) / (n + 1) spacing2 = float(abs(range2[1] - range2[0])) / (n + 1) else: spacing1 = float(2 ** bitDepth) / (n + 1) spacing2 = float(2 ** bitDepth) / (n + 1) app = vtk.vtkImageAppendComponents() app.AddInput(imagedata1) app.AddInput(imagedata2) # shiftscale = vtk.vtkImageShiftScale() # shiftscale.SetOutputScalarTypeToUnsignedChar() # shiftscale.SetScale(d) # shiftscale.SetInputConnection(app.GetOutputPort()) acc = vtk.vtkImageAccumulate() acc.SetComponentExtent(0, n, 0, n, 0, 0) acc.SetComponentOrigin(range1[0], range2[0], 0) acc.SetComponentSpacing(spacing1, spacing2, 0) # acc.SetInputConnection(shiftscale.GetOutputPort()) acc.SetInputConnection(app.GetOutputPort()) acc.Update() data = acc.GetOutput() origData = data originalRange = data.GetScalarRange() if logarithmic: Logging.info("Scaling scatterplot logarithmically", kw="imageop") logscale = vtk.vtkImageLogarithmicScale() logscale.SetInputConnection(acc.GetOutputPort()) logscale.Update() data = logscale.GetOutput() x0, x1 = data.GetScalarRange() if countVoxels: Logging.info("Scalar range of scatterplot = ", x0, x1, kw="imageop") ctf = fire(x0, x1) ctf = equalize(data, ctf, x1) maptocolor = vtk.vtkImageMapToColors() maptocolor.SetInputConnection(data.GetProducerPort()) maptocolor.SetLookupTable(ctf) maptocolor.SetOutputFormatToRGB() maptocolor.Update() data = maptocolor.GetOutput() ctf.originalRange = originalRange Logging.info("Scatterplot has dimensions: ", data.GetDimensions(), data.GetExtent(), kw="imageop") data.SetWholeExtent(data.GetExtent()) img = vtkImageDataToWxImage(data) # w, h = img.GetWidth(), img.GetHeight() # if w < 255 or h < 255: # dh = 255-h # img.Resize((255, 255),(0, 0), 0,0,0) return img, ctf, origData
def TestSection_AddRemoveSegment(self): # Add/remove segment from segmentation (check display properties, color table, etc.) logging.info('Test section: Add/remove segment') # Get baseline values displayNode = self.inputSegmentationNode.GetDisplayNode() self.assertIsNotNone(displayNode) # If segments are not found then the returned color is the pre-defined invalid color bodyColor = self.inputSegmentationNode.GetSegmentation().GetSegment(self.bodySegmentName).GetColor() logging.info("bodyColor: {0}".format(bodyColor)) self.assertEqual(int(bodyColor[0]*100), 33) self.assertEqual(int(bodyColor[1]*100), 66) self.assertEqual(int(bodyColor[2]*100), 0) tumorColor = self.inputSegmentationNode.GetSegmentation().GetSegment(self.tumorSegmentName).GetColor() logging.info("tumorColor: {0}".format(tumorColor)) self.assertEqual(int(tumorColor[0]*100), 100) self.assertEqual(int(tumorColor[1]*100), 0) self.assertEqual(int(tumorColor[2]*100), 0) # Create new segment sphere = vtk.vtkSphereSource() sphere.SetCenter(0,50,0) sphere.SetRadius(80) sphere.Update() spherePolyData = vtk.vtkPolyData() spherePolyData.DeepCopy(sphere.GetOutput()) self.sphereSegment = vtkSegmentationCore.vtkSegment() self.sphereSegment.SetName(self.sphereSegmentName) self.sphereSegment.SetColor(0.0,0.0,1.0) self.sphereSegment.AddRepresentation(self.closedSurfaceReprName, spherePolyData) # Add segment to segmentation self.inputSegmentationNode.GetSegmentation().AddSegment(self.sphereSegment) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) # Check merged labelmap mergedLabelmap = vtkSegmentationCore.vtkOrientedImageData() self.inputSegmentationNode.GetSegmentation().CreateRepresentation(self.binaryLabelmapReprName) self.inputSegmentationNode.GenerateMergedLabelmapForAllSegments(mergedLabelmap, 0) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(mergedLabelmap) imageStat.SetComponentExtent(0,4,0,0,0,0) imageStat.SetComponentOrigin(0,0,0) imageStat.SetComponentSpacing(1,1,1) imageStat.Update() imageStatResult = imageStat.GetOutput() for i in range(4): logging.info("Volume {0}: {1}".format(i, imageStatResult.GetScalarComponentAsDouble(i,0,0,0))) self.assertEqual(imageStat.GetVoxelCount(), 1000) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0,0,0,0), 786) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1,0,0,0), 170) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2,0,0,0), 4) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3,0,0,0), 40) # Check if segment reorder is taken into account in merged labelmap generation # Change segment order sphereSegmentId = self.inputSegmentationNode.GetSegmentation().GetSegmentIdBySegment(self.sphereSegment) self.inputSegmentationNode.GetSegmentation().SetSegmentIndex(sphereSegmentId, 1) # Re-generate merged labelmap self.inputSegmentationNode.GenerateMergedLabelmapForAllSegments(mergedLabelmap, 0) imageStat.SetInputData(mergedLabelmap) imageStat.Update() imageStatResult = imageStat.GetOutput() for i in range(4): logging.info("Volume {0}: {1}".format(i, imageStatResult.GetScalarComponentAsDouble(i,0,0,0))) self.assertEqual(imageStat.GetVoxelCount(), 1000) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0,0,0,0), 786) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1,0,0,0), 170) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2,0,0,0), 39) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3,0,0,0), 5) # Remove segment from segmentation self.inputSegmentationNode.GetSegmentation().RemoveSegment(self.sphereSegmentName) self.assertEqual(self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 2)
def TestSection_ImportExportSegment(self): # Import/export, both one label and all labels logging.info('Test section: Import/export segment') # Export single segment to model node bodyModelNode = slicer.vtkMRMLModelNode() bodyModelNode.SetName('BodyModel') slicer.mrmlScene.AddNode(bodyModelNode) bodySegment = self.inputSegmentationNode.GetSegmentation().GetSegment(self.bodySegmentName) result = slicer.vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode(bodySegment, bodyModelNode) self.assertTrue(result) self.assertIsNotNone(bodyModelNode.GetPolyData()) #TODO: Number of points increased to 1677 due to end-capping, need to investigate! #self.assertEqual(bodyModelNode.GetPolyData().GetNumberOfPoints(), 302) #TODO: On Linux and Windows it is 588, on Mac it is 580. Need to investigate # self.assertEqual(bodyModelNode.GetPolyData().GetNumberOfCells(), 588) #self.assertTrue(bodyModelNode.GetPolyData().GetNumberOfCells() == 588 or bodyModelNode.GetPolyData().GetNumberOfCells() == 580) # Export single segment to volume node bodyLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode() bodyLabelmapNode.SetName('BodyLabelmap') slicer.mrmlScene.AddNode(bodyLabelmapNode) result = slicer.vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode(bodySegment, bodyLabelmapNode) self.assertTrue(result) bodyImageData = bodyLabelmapNode.GetImageData() self.assertIsNotNone(bodyImageData) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(bodyImageData) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 792) self.assertEqual(imageStat.GetMin()[0], 0) self.assertEqual(imageStat.GetMax()[0], 1) # Export multiple segments to volume node allSegmentsLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode() allSegmentsLabelmapNode.SetName('AllSegmentsLabelmap') slicer.mrmlScene.AddNode(allSegmentsLabelmapNode) result = slicer.vtkSlicerSegmentationsModuleLogic.ExportAllSegmentsToLabelmapNode(self.inputSegmentationNode, allSegmentsLabelmapNode) self.assertTrue(result) allSegmentsImageData = allSegmentsLabelmapNode.GetImageData() self.assertIsNotNone(allSegmentsImageData) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(allSegmentsImageData) imageStat.SetComponentExtent(0,5,0,0,0,0) imageStat.SetComponentOrigin(0,0,0) imageStat.SetComponentSpacing(1,1,1) imageStat.Update() imageStatResult = imageStat.GetOutput() for i in range(4): logging.info("Volume {0}: {1}".format(i, imageStatResult.GetScalarComponentAsDouble(i,0,0,0))) self.assertEqual(imageStat.GetVoxelCount(), 127109360) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(0,0,0,0), 78967249) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(1,0,0,0), 39705288) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(2,0,0,0), 890883) self.assertEqual(imageStatResult.GetScalarComponentAsDouble(3,0,0,0), 7545940) # Import model to segment modelImportSegmentationNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode', 'ModelImport') modelImportSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.closedSurfaceReprName) modelSegment = slicer.vtkSlicerSegmentationsModuleLogic.CreateSegmentFromModelNode(bodyModelNode) modelSegment.UnRegister(None) # Need to release ownership self.assertIsNotNone(modelSegment) self.assertIsNotNone(modelSegment.GetRepresentation(self.closedSurfaceReprName)) # Import multi-label labelmap to segmentation multiLabelImportSegmentationNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode', 'MultiLabelImport') multiLabelImportSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.binaryLabelmapReprName) result = slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode(allSegmentsLabelmapNode, multiLabelImportSegmentationNode) self.assertTrue(result) self.assertEqual(multiLabelImportSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) # Import labelmap into single segment singleLabelImportSegmentationNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode', 'SingleLabelImport') singleLabelImportSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.binaryLabelmapReprName) # Should not import multi-label labelmap to segment nullSegment = slicer.vtkSlicerSegmentationsModuleLogic.CreateSegmentFromLabelmapVolumeNode(allSegmentsLabelmapNode) self.assertIsNone(nullSegment) logging.info('(This error message is a result of testing an impossible scenario, it is supposed to appear)') # Make labelmap single-label and import again threshold = vtk.vtkImageThreshold() threshold.SetInValue(0) threshold.SetOutValue(1) threshold.ReplaceInOn() threshold.ThresholdByLower(0) threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) if vtk.VTK_MAJOR_VERSION <= 5: threshold.SetInput(allSegmentsLabelmapNode.GetImageData()) else: threshold.SetInputData(allSegmentsLabelmapNode.GetImageData()) threshold.Update() allSegmentsLabelmapNode.GetImageData().ShallowCopy(threshold.GetOutput()) labelSegment = slicer.vtkSlicerSegmentationsModuleLogic.CreateSegmentFromLabelmapVolumeNode(allSegmentsLabelmapNode) labelSegment.UnRegister(None) # Need to release ownership self.assertIsNotNone(labelSegment) self.assertIsNotNone(labelSegment.GetRepresentation(self.binaryLabelmapReprName)) # Import/export with transforms logging.info('Test subsection: Import/export with transforms') # Create transform node that will be used to transform the tested nodes bodyModelTransformNode = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(bodyModelTransformNode) bodyModelTransform = vtk.vtkTransform() bodyModelTransform.Translate(1000.0, 0.0, 0.0) bodyModelTransformNode.ApplyTransformMatrix(bodyModelTransform.GetMatrix()) # Set transform as parent to input segmentation node self.inputSegmentationNode.SetAndObserveTransformNodeID(bodyModelTransformNode.GetID()) # Export single segment to model node from transformed segmentation bodyModelNodeTransformed = slicer.vtkMRMLModelNode() bodyModelNodeTransformed.SetName('BodyModelTransformed') slicer.mrmlScene.AddNode(bodyModelNodeTransformed) bodySegment = self.inputSegmentationNode.GetSegmentation().GetSegment(self.bodySegmentName) result = slicer.vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode(bodySegment, bodyModelNodeTransformed) self.assertTrue(result) self.assertIsNotNone(bodyModelNodeTransformed.GetParentTransformNode()) # Export single segment to volume node from transformed segmentation bodyLabelmapNodeTransformed = slicer.vtkMRMLLabelMapVolumeNode() bodyLabelmapNodeTransformed.SetName('BodyLabelmapTransformed') slicer.mrmlScene.AddNode(bodyLabelmapNodeTransformed) result = slicer.vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode(bodySegment, bodyLabelmapNodeTransformed) self.assertTrue(result) self.assertIsNotNone(bodyLabelmapNodeTransformed.GetParentTransformNode()) # Create transform node that will be used to transform the tested nodes modelTransformedImportSegmentationTransformNode = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(modelTransformedImportSegmentationTransformNode) modelTransformedImportSegmentationTransform = vtk.vtkTransform() modelTransformedImportSegmentationTransform.Translate(-500.0, 0.0, 0.0) modelTransformedImportSegmentationTransformNode.ApplyTransformMatrix(modelTransformedImportSegmentationTransform.GetMatrix()) # Import transformed model to segment in transformed segmentation modelTransformedImportSegmentationNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode', 'ModelImportTransformed') modelTransformedImportSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.closedSurfaceReprName) modelTransformedImportSegmentationNode.SetAndObserveTransformNodeID(modelTransformedImportSegmentationTransformNode.GetID()) modelSegmentTranformed = slicer.vtkSlicerSegmentationsModuleLogic.CreateSegmentFromModelNode(bodyModelNodeTransformed, modelTransformedImportSegmentationNode) modelSegmentTranformed.UnRegister(None) # Need to release ownership self.assertIsNotNone(modelSegmentTranformed) modelSegmentTransformedPolyData = modelSegmentTranformed.GetRepresentation(self.closedSurfaceReprName) self.assertIsNotNone(modelSegmentTransformedPolyData) self.assertEqual(int(modelSegmentTransformedPolyData.GetBounds()[0]), 1332) self.assertEqual(int(modelSegmentTransformedPolyData.GetBounds()[1]), 1675) # Clean up temporary nodes slicer.mrmlScene.RemoveNode(bodyModelNode) slicer.mrmlScene.RemoveNode(bodyLabelmapNode) slicer.mrmlScene.RemoveNode(allSegmentsLabelmapNode) slicer.mrmlScene.RemoveNode(modelImportSegmentationNode) slicer.mrmlScene.RemoveNode(multiLabelImportSegmentationNode) slicer.mrmlScene.RemoveNode(singleLabelImportSegmentationNode) slicer.mrmlScene.RemoveNode(bodyModelTransformNode) slicer.mrmlScene.RemoveNode(bodyModelNodeTransformed) slicer.mrmlScene.RemoveNode(bodyLabelmapNodeTransformed) slicer.mrmlScene.RemoveNode(modelTransformedImportSegmentationNode)
def computeStatistics(self, segmentID): import vtkSegmentationCorePython as vtkSegmentationCore requestedKeys = self.getRequestedKeys() segmentationNode = slicer.mrmlScene.GetNodeByID(self.getParameterNode().GetParameter("Segmentation")) grayscaleNode = slicer.mrmlScene.GetNodeByID(self.getParameterNode().GetParameter("ScalarVolume")) if len(requestedKeys)==0: return {} containsLabelmapRepresentation = segmentationNode.GetSegmentation().ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()) if not containsLabelmapRepresentation: return {} if grayscaleNode is None or grayscaleNode.GetImageData() is None: return {} # Get geometry of grayscale volume node as oriented image data # reference geometry in reference node coordinate system referenceGeometry_Reference = vtkSegmentationCore.vtkOrientedImageData() referenceGeometry_Reference.SetExtent(grayscaleNode.GetImageData().GetExtent()) ijkToRasMatrix = vtk.vtkMatrix4x4() grayscaleNode.GetIJKToRASMatrix(ijkToRasMatrix) referenceGeometry_Reference.SetGeometryFromImageToWorldMatrix(ijkToRasMatrix) # Get transform between grayscale volume and segmentation segmentationToReferenceGeometryTransform = vtk.vtkGeneralTransform() slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), grayscaleNode.GetParentTransformNode(), segmentationToReferenceGeometryTransform) cubicMMPerVoxel = reduce(lambda x,y: x*y, referenceGeometry_Reference.GetSpacing()) ccPerCubicMM = 0.001 segment = segmentationNode.GetSegmentation().GetSegment(segmentID) segBinaryLabelName = vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName() segmentLabelmap = segment.GetRepresentation(segBinaryLabelName) segmentLabelmap_Reference = vtkSegmentationCore.vtkOrientedImageData() vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage( segmentLabelmap, referenceGeometry_Reference, segmentLabelmap_Reference, False, # nearest neighbor interpolation False, # no padding segmentationToReferenceGeometryTransform) # We need to know exactly the value of the segment voxels, apply threshold to make force the selected label value labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() thresh.SetInputData(segmentLabelmap_Reference) thresh.ThresholdByLower(0) thresh.SetInValue(backgroundValue) thresh.SetOutValue(labelValue) thresh.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) thresh.Update() # Use binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputData(thresh.GetOutput()) stencil.ThresholdByUpper(labelValue) stencil.Update() stat = vtk.vtkImageAccumulate() stat.SetInputData(grayscaleNode.GetImageData()) stat.SetStencilData(stencil.GetOutput()) stat.Update() # create statistics list stats = {} if "voxel_count" in requestedKeys: stats["voxel_count"] = stat.GetVoxelCount() if "volume_mm3" in requestedKeys: stats["volume_mm3"] = stat.GetVoxelCount() * cubicMMPerVoxel if "volume_cm3" in requestedKeys: stats["volume_cm3"] = stat.GetVoxelCount() * cubicMMPerVoxel * ccPerCubicMM if stat.GetVoxelCount()>0: if "min" in requestedKeys: stats["min"] = stat.GetMin()[0] if "max" in requestedKeys: stats["max"] = stat.GetMax()[0] if "mean" in requestedKeys: stats["mean"] = stat.GetMean()[0] if "stdev" in requestedKeys: stats["stdev"] = stat.GetStandardDeviation()[0] return stats
def TestSection_3_ImportExportSegment(self): # Import/export, both one label and all labels logging.info('Test section 3: Import/export segment') # Export single segment to model node bodyModelNode = slicer.vtkMRMLModelNode() bodyModelNode.SetName('BodyModel') slicer.mrmlScene.AddNode(bodyModelNode) bodySegment = self.inputSegmentationNode.GetSegmentation().GetSegment( 'Body_Contour') result = vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode( bodySegment, bodyModelNode) self.assertTrue(result) self.assertIsNotNone(bodyModelNode.GetPolyData()) self.assertEqual(bodyModelNode.GetPolyData().GetNumberOfPoints(), 302) #TODO: On Linux and Windows it is 588, on Mac it is 580. Need to investigate # self.assertEqual(bodyModelNode.GetPolyData().GetNumberOfCells(), 588) self.assertTrue( bodyModelNode.GetPolyData().GetNumberOfCells() == 588 or bodyModelNode.GetPolyData().GetNumberOfCells() == 580) # Export single segment to volume node bodyLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode() bodyLabelmapNode.SetName('BodyLabelmap') slicer.mrmlScene.AddNode(bodyLabelmapNode) result = vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode( bodySegment, bodyLabelmapNode) self.assertTrue(result) bodyImageData = bodyLabelmapNode.GetImageData() self.assertIsNotNone(bodyImageData) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(bodyImageData) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 648) self.assertEqual(imageStat.GetMin()[0], 0) self.assertEqual(imageStat.GetMax()[0], 1) # Export multiple segments to volume node allSegmentsLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode() allSegmentsLabelmapNode.SetName('AllSegmentsLabelmap') slicer.mrmlScene.AddNode(allSegmentsLabelmapNode) result = vtkSlicerSegmentationsModuleLogic.ExportAllSegmentsToLabelmapNode( self.inputSegmentationNode, allSegmentsLabelmapNode) self.assertTrue(result) allSegmentsImageData = allSegmentsLabelmapNode.GetImageData() self.assertIsNotNone(allSegmentsImageData) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(allSegmentsImageData) imageStat.SetComponentExtent(0, 5, 0, 0, 0, 0) imageStat.SetComponentOrigin(0, 0, 0) imageStat.SetComponentSpacing(1, 1, 1) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 54872000) imageStatResult = imageStat.GetOutput() self.assertEqual( imageStatResult.GetScalarComponentAsDouble(0, 0, 0, 0), 46678738) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(1, 0, 0, 0), 0) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(2, 0, 0, 0), 7618805) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(3, 0, 0, 0), 128968) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(4, 0, 0, 0), 0 ) # Built from color table and color four is removed in previous test section self.assertEqual( imageStatResult.GetScalarComponentAsDouble(5, 0, 0, 0), 445489) # Import model to segment modelImportSegmentationNode = vtkMRMLSegmentationNode() modelImportSegmentationNode.SetName('ModelImport') modelImportSegmentationNode.GetSegmentation( ).SetMasterRepresentationName(self.closedSurfaceReprName) slicer.mrmlScene.AddNode(modelImportSegmentationNode) modelSegment = vtkSlicerSegmentationsModuleLogic.CreateSegmentFromModelNode( bodyModelNode) modelSegment.UnRegister(None) # Need to release ownership self.assertIsNotNone(modelSegment) self.assertIsNotNone( modelSegment.GetRepresentation(self.closedSurfaceReprName)) # Import multi-label labelmap to segmentation multiLabelImportSegmentationNode = vtkMRMLSegmentationNode() multiLabelImportSegmentationNode.SetName('MultiLabelImport') multiLabelImportSegmentationNode.GetSegmentation( ).SetMasterRepresentationName(self.binaryLabelmapReprName) slicer.mrmlScene.AddNode(multiLabelImportSegmentationNode) result = vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode( allSegmentsLabelmapNode, multiLabelImportSegmentationNode) self.assertTrue(result) self.assertEqual( multiLabelImportSegmentationNode.GetSegmentation(). GetNumberOfSegments(), 3) # Import labelmap into single segment singleLabelImportSegmentationNode = vtkMRMLSegmentationNode() singleLabelImportSegmentationNode.SetName('SingleLabelImport') singleLabelImportSegmentationNode.GetSegmentation( ).SetMasterRepresentationName(self.binaryLabelmapReprName) slicer.mrmlScene.AddNode(singleLabelImportSegmentationNode) # Should not import multi-label labelmap to segment nullSegment = vtkSlicerSegmentationsModuleLogic.CreateSegmentFromLabelmapVolumeNode( allSegmentsLabelmapNode) self.assertIsNone(nullSegment) logging.info( '(This error message tests an impossible scenario, it is supposed to appear)' ) # Make labelmap single-label and import again threshold = vtk.vtkImageThreshold() threshold.ThresholdByUpper(0.5) threshold.SetInValue(1) threshold.SetOutValue(0) threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR) if vtk.VTK_MAJOR_VERSION <= 5: threshold.SetInput(allSegmentsLabelmapNode.GetImageData()) else: threshold.SetInputData(allSegmentsLabelmapNode.GetImageData()) threshold.SetOutput(allSegmentsLabelmapNode.GetImageData()) threshold.Update() labelSegment = vtkSlicerSegmentationsModuleLogic.CreateSegmentFromLabelmapVolumeNode( allSegmentsLabelmapNode) labelSegment.UnRegister(None) # Need to release ownership self.assertIsNotNone(labelSegment) self.assertIsNotNone( labelSegment.GetRepresentation(self.binaryLabelmapReprName)) # Import/export with transforms logging.info('Test section 4/2: Import/export with transforms') # Create transform node that will be used to transform the tested nodes bodyModelTransformNode = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(bodyModelTransformNode) bodyModelTransform = vtk.vtkTransform() bodyModelTransform.Translate(1000.0, 0.0, 0.0) bodyModelTransformNode.ApplyTransformMatrix( bodyModelTransform.GetMatrix()) # Set transform as parent to input segmentation node self.inputSegmentationNode.SetAndObserveTransformNodeID( bodyModelTransformNode.GetID()) # Export single segment to model node from transformed segmentation bodyModelNodeTransformed = slicer.vtkMRMLModelNode() bodyModelNodeTransformed.SetName('BodyModelTransformed') slicer.mrmlScene.AddNode(bodyModelNodeTransformed) bodySegment = self.inputSegmentationNode.GetSegmentation().GetSegment( 'Body_Contour') result = vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode( bodySegment, bodyModelNodeTransformed) self.assertTrue(result) self.assertIsNotNone(bodyModelNodeTransformed.GetParentTransformNode()) # Export single segment to volume node from transformed segmentation bodyLabelmapNodeTransformed = slicer.vtkMRMLLabelMapVolumeNode() bodyLabelmapNodeTransformed.SetName('BodyLabelmapTransformed') slicer.mrmlScene.AddNode(bodyLabelmapNodeTransformed) result = vtkSlicerSegmentationsModuleLogic.ExportSegmentToRepresentationNode( bodySegment, bodyLabelmapNodeTransformed) self.assertTrue(result) self.assertIsNotNone( bodyLabelmapNodeTransformed.GetParentTransformNode()) # Create transform node that will be used to transform the tested nodes modelTransformedImportSegmentationTransformNode = slicer.vtkMRMLLinearTransformNode( ) slicer.mrmlScene.AddNode( modelTransformedImportSegmentationTransformNode) modelTransformedImportSegmentationTransform = vtk.vtkTransform() modelTransformedImportSegmentationTransform.Translate(-500.0, 0.0, 0.0) modelTransformedImportSegmentationTransformNode.ApplyTransformMatrix( modelTransformedImportSegmentationTransform.GetMatrix()) # Import transformed model to segment in transformed segmentation modelTransformedImportSegmentationNode = vtkMRMLSegmentationNode() modelTransformedImportSegmentationNode.SetName( 'ModelImportTransformed') modelTransformedImportSegmentationNode.GetSegmentation( ).SetMasterRepresentationName(self.closedSurfaceReprName) slicer.mrmlScene.AddNode(modelTransformedImportSegmentationNode) modelTransformedImportSegmentationNode.SetAndObserveTransformNodeID( modelTransformedImportSegmentationTransformNode.GetID()) modelSegmentTranformed = vtkSlicerSegmentationsModuleLogic.CreateSegmentFromModelNode( bodyModelNodeTransformed, modelTransformedImportSegmentationNode) modelSegmentTranformed.UnRegister(None) # Need to release ownership self.assertIsNotNone(modelSegmentTranformed) modelSegmentTransformedPolyData = modelSegmentTranformed.GetRepresentation( self.closedSurfaceReprName) self.assertIsNotNone(modelSegmentTransformedPolyData) self.assertEqual(int(modelSegmentTransformedPolyData.GetBounds()[0]), 1332) self.assertEqual(int(modelSegmentTransformedPolyData.GetBounds()[1]), 1675) # Clean up temporary nodes slicer.mrmlScene.RemoveNode(bodyModelNode) slicer.mrmlScene.RemoveNode(bodyLabelmapNode) slicer.mrmlScene.RemoveNode(allSegmentsLabelmapNode) slicer.mrmlScene.RemoveNode(modelImportSegmentationNode) slicer.mrmlScene.RemoveNode(multiLabelImportSegmentationNode) slicer.mrmlScene.RemoveNode(singleLabelImportSegmentationNode) slicer.mrmlScene.RemoveNode(bodyModelTransformNode) slicer.mrmlScene.RemoveNode(bodyModelNodeTransformed) slicer.mrmlScene.RemoveNode(bodyLabelmapNodeTransformed) slicer.mrmlScene.RemoveNode(modelTransformedImportSegmentationNode)
def TestSection_2_MergeLabelmapWithDifferentGeometries(self): # Merge labelmap when segments containing labelmaps with different geometries (both same directions, different directions) logging.info( 'Test section 2: Merge labelmap with different geometries') self.assertIsNotNone(self.sphereSegment) self.sphereSegment.RemoveRepresentation(self.binaryLabelmapReprName) self.assertIsNone( self.sphereSegment.GetRepresentation(self.binaryLabelmapReprName)) # Create new segmentation with sphere segment self.secondSegmentationNode = vtkMRMLSegmentationNode() self.secondSegmentationNode.SetName('Second') self.secondSegmentationNode.GetSegmentation( ).SetMasterRepresentationName(self.binaryLabelmapReprName) slicer.mrmlScene.AddNode(self.secondSegmentationNode) self.secondSegmentationNode.GetSegmentation().AddSegment( self.sphereSegment) # Check automatically converted labelmap. It is supposed to have the default geometry # (which is different than the one in the input segmentation) sphereLabelmap = self.sphereSegment.GetRepresentation( self.binaryLabelmapReprName) self.assertIsNotNone(sphereLabelmap) sphereLabelmapSpacing = sphereLabelmap.GetSpacing() self.assertTrue(sphereLabelmapSpacing[0] == 1.0 and sphereLabelmapSpacing[1] == 1.0 and sphereLabelmapSpacing[2] == 1.0) # Copy segment to input segmentation self.inputSegmentationNode.GetSegmentation( ).CopySegmentFromSegmentation( self.secondSegmentationNode.GetSegmentation(), self.sphereSegmentName) self.assertEqual( self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) # Check merged labelmap mergedLabelmap = self.inputSegmentationNode.GetImageData() self.assertIsNotNone(mergedLabelmap) mergedLabelmapSpacing = sphereLabelmap.GetSpacing() self.assertTrue(mergedLabelmapSpacing[0] == 1.0 and mergedLabelmapSpacing[1] == 1.0 and mergedLabelmapSpacing[2] == 1.0) imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(mergedLabelmap) imageStat.SetComponentExtent(0, 5, 0, 0, 0, 0) imageStat.SetComponentOrigin(0, 0, 0) imageStat.SetComponentSpacing(1, 1, 1) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 54872000) imageStatResult = imageStat.GetOutput() self.assertEqual( imageStatResult.GetScalarComponentAsDouble(0, 0, 0, 0), 46678738) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(1, 0, 0, 0), 0) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(2, 0, 0, 0), 7618805) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(3, 0, 0, 0), 128968) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(4, 0, 0, 0), 0 ) # Built from color table and color four is removed in previous test section self.assertEqual( imageStatResult.GetScalarComponentAsDouble(5, 0, 0, 0), 445489)
def TestSection_1_AddRemoveSegment(self): # Add/remove segment from segmentation (check display properties, color table, etc.) logging.info('Test section 1: Add/remove segment') # Get baseline values displayNode = self.inputSegmentationNode.GetDisplayNode() self.assertIsNotNone(displayNode) colorTableNode = displayNode.GetColorNode() self.assertIsNotNone(colorTableNode) self.assertEqual(colorTableNode.GetNumberOfColors(), 4) # If segments are not found then the returned color is the pre-defined invalid color bodyColor = displayNode.GetSegmentColor('Body_Contour') self.assertTrue( int(bodyColor[0] * 100) == 33 and int(bodyColor[1] * 100) == 66 and bodyColor[2] == 0.0) tumorColor = displayNode.GetSegmentColor('Tumor_Contour') self.assertTrue(tumorColor[0] == 1.0 and tumorColor[1] == 0.0 and tumorColor[2] == 0.0) # Create new segment sphere = vtk.vtkSphereSource() sphere.SetCenter(0, 50, 0) sphere.SetRadius(50) sphere.Update() spherePolyData = vtk.vtkPolyData() spherePolyData.DeepCopy(sphere.GetOutput()) self.sphereSegment = vtkSegmentationCore.vtkSegment() self.sphereSegment.SetName(self.sphereSegmentName) self.sphereSegment.SetDefaultColor(0.0, 0.0, 1.0) self.sphereSegment.AddRepresentation(self.closedSurfaceReprName, spherePolyData) # Add segment to segmentation self.inputSegmentationNode.GetSegmentation().AddSegment( self.sphereSegment) self.assertEqual( self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 3) self.assertEqual(colorTableNode.GetNumberOfColors(), 5) sphereColor = displayNode.GetSegmentColor(self.sphereSegmentName) self.assertTrue(sphereColor[0] == 0.0 and sphereColor[1] == 0.0 and sphereColor[2] == 1.0) # Check merged labelmap imageStat = vtk.vtkImageAccumulate() imageStat.SetInputData(self.inputSegmentationNode.GetImageData()) imageStat.SetComponentExtent(0, 4, 0, 0, 0, 0) imageStat.SetComponentOrigin(0, 0, 0) imageStat.SetComponentSpacing(1, 1, 1) imageStat.Update() self.assertEqual(imageStat.GetVoxelCount(), 1000) imageStatResult = imageStat.GetOutput() self.assertEqual( imageStatResult.GetScalarComponentAsDouble(0, 0, 0, 0), 814) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(1, 0, 0, 0), 0) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(2, 0, 0, 0), 175) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(3, 0, 0, 0), 4) self.assertEqual( imageStatResult.GetScalarComponentAsDouble(4, 0, 0, 0), 7) # Remove segment from segmentation self.inputSegmentationNode.GetSegmentation().RemoveSegment( self.sphereSegmentName) self.assertEqual( self.inputSegmentationNode.GetSegmentation().GetNumberOfSegments(), 2) self.assertEqual(colorTableNode.GetNumberOfColors(), 5) sphereColorArray = [0] * 4 colorTableNode.GetColor(4, sphereColorArray) self.assertTrue( int(sphereColorArray[0] * 100) == 50 and int(sphereColorArray[1] * 100) == 50 and int(sphereColorArray[2] * 100) == 50) sphereColor = displayNode.GetSegmentColor(self.sphereSegmentName) self.assertTrue(sphereColor[0] == 0.5 and sphereColor[1] == 0.5 and sphereColor[2] == 0.5)
def test_confidence_seed_connect(self): """Test confidenceSeedConnect and VTK<->ITK interconnect. """ # this will be the last big created thingy... from now on we'll # do DVNs. This simulates the user's actions creating the network # though. # create a slice3dVWR (svmod, svglyph) = self._ge.create_module_and_glyph( 200, 190, 'modules.viewers.slice3dVWR') self.failUnless(svmod and svglyph) # connect up the created volume and redraw ret = self._ge._connect(self.dtglyph, 0, svglyph, 0) # make sure it can connect self.failUnless(ret) # we need to execute before storeCursor can work self._ge._handler_execute_network(None) # storeCursor wants a 4-tuple and value - we know what these should be svmod.selectedPoints._storeCursor((20,20,0,1)) self.failUnless(len(svmod.selectedPoints._pointsList) == 1) # connect up the insight bits (v2imod, v2iglyph) = self._ge.create_module_and_glyph( 200, 10, 'modules.insight.VTKtoITK') self.failUnless(v2imod and v2iglyph) # make sure VTKtoITK will cast to float (because it's getting # double at the input!) c = v2imod.get_config() c.autotype = False c.type = 'float' v2imod.set_config(c) (cscmod, cscglyph) = self._ge.create_module_and_glyph( 200, 70, 'modules.insight.confidenceSeedConnect') self.failUnless(cscmod and cscglyph) (i2vmod, i2vglyph) = self._ge.create_module_and_glyph( 200, 130, 'modules.insight.ITKtoVTK') self.failUnless(i2vmod and i2vglyph) ret = self._ge._connect(self.dtglyph, 0, v2iglyph, 0) self.failUnless(ret) ret = self._ge._connect(v2iglyph, 0, cscglyph, 0) self.failUnless(ret) ret = self._ge._connect(cscglyph, 0, i2vglyph, 0) self.failUnless(ret) # there's already something on the 0'th input of the slice3dVWR ret = self._ge._connect(i2vglyph, 0, svglyph, 1) self.failUnless(ret) # connect up the selected points ret = self._ge._connect(svglyph, 0, cscglyph, 1) self.failUnless(ret) # redraw the canvas self._ge.canvas.redraw() # execute the network self._ge._handler_execute_network(None) # now count the number of voxels in the segmented result import vtk via = vtk.vtkImageAccumulate() via.SetInput(i2vmod.get_output(0)) via.Update() # get second bin of output histogram: that should be the # number of voxels s = via.GetOutput().GetPointData().GetScalars() print s.GetTuple1(1) self.failUnless(s.GetTuple1(1) == 26728) via.SetInput(None) del via