def jaccard3D_pd(pd1,pd2): """ computes the jaccard distance error for two polydata objects returns (error) float """ union = vtk.vtkBooleanOperationPolyDataFilter() union.SetOperationToUnion() union.SetInputData(0,pd1) union.SetInputData(1,pd2) union.Update() u = union.GetOutput() massUnion = vtk.vtkMassProperties() massUnion.SetInputData(u) intersection = vtk.vtkBooleanOperationPolyDataFilter() intersection.SetOperationToIntersection() intersection.SetInputData(0,pd1) intersection.SetInputData(1,pd2) intersection.Update() i = intersection.GetOutput() massIntersection = vtk.vtkMassProperties() massIntersection.SetInputData(i) return 1 - massIntersection.GetVolume()/massUnion.GetVolume()
def computeDiceDistance(mesh1Path, mesh2Path): if mesh1Path == mesh2Path: return 1. #Reading reader1 = vtkPolyDataReader() reader1.SetFileName(mesh1Path) reader1.Update() reader2 = vtkPolyDataReader() reader2.SetFileName(mesh2Path) reader2.Update() #First volume mass1 = vtkMassProperties() mass1.SetInputConnection(reader1.GetOutputPort()) mass1.Update() volume1 = mass1.GetVolume() #Second volume mass2 = vtkMassProperties() mass2.SetInputConnection(reader2.GetOutputPort()) mass2.Update() volume2 = mass2.GetVolume() #Intersection # intersectionOperation = vtkIntersectionPolyDataFilter() intersectionOperation = vtkBooleanOperationPolyDataFilter() intersectionOperation.SetOperationToIntersection() intersectionOperation.SetInputConnection(0, reader1.GetOutputPort()) intersectionOperation.SetInputConnection(1, reader2.GetOutputPort()) intersectionOperation.Update() #Volume of the intersection massInter = vtkMassProperties() massInter.SetInputConnection(intersectionOperation.GetOutputPort()) massInter.Update() intersectionVolume = massInter.GetVolume() dice = 2 * intersectionVolume / (volume1 + volume2) assert 0 <= dice <= 1, "Warning : suspicious behavior detected in the intersection filter." return dice
def obj(x, sF, devF, R, sv, mv, tv, material, spatial, rc, sc): nF = np.dot(R, x[0] * sF) + np.dot(R, x[1] * devF) #Make a copy of material configuration and deform this with nF nm = vtk.vtkPolyData() nm.DeepCopy(material) pcoords = vtk.vtkFloatArray() pcoords.SetNumberOfComponents(3) pcoords.SetNumberOfTuples(nm.GetNumberOfPoints()) for i in xrange(nm.GetNumberOfPoints()): p = [0., 0., 0.] nm.GetPoint(i, p) p = np.dot(nF, p - rc) p.flatten() pcoords.SetTuple3(i, p[0] + sc[0], p[1] + sc[1], p[2] + sc[2]) points = vtk.vtkPoints() points.SetData(pcoords) nm.SetPoints(points) nm.GetPoints().Modified() #calculate both the intersection and the union of the two polydata intersect = vtk.vtkBooleanOperationPolyDataFilter() intersect.SetOperation(1) intersect.SetInputData(0, nm) intersect.SetInputData(1, spatial) intersect.Update() union = vtk.vtkBooleanOperationPolyDataFilter() union.SetOperation(0) union.SetInputData(0, nm) union.SetInputData(1, spatial) union.Update() unionmass = vtk.vtkMassProperties() unionmass.SetInputConnection(union.GetOutputPort()) vol_union = unionmass.GetVolume() if intersect.GetOutput().GetNumberOfPoints() > 0: intmass = vtk.vtkMassProperties() intmass.SetInputConnection(intersect.GetOutputPort()) vol_int = intmass.GetVolume() else: #penalize with distance between centroids w = sc.T - np.dot(nF, rc.T) c = np.linalg.norm(w) vol_int = c * vol_union diff = max([abs(sv - vol_int), abs(sv - vol_union)]) return diff
def obj(x,sF,devF,R,sv,mv,tv,material,spatial,rc,sc): nF = np.dot(R,x[0]*sF)+np.dot(R,x[1]*devF) #Make a copy of material configuration and deform this with nF nm = vtk.vtkPolyData() nm.DeepCopy(material) pcoords = vtk.vtkFloatArray() pcoords.SetNumberOfComponents(3) pcoords.SetNumberOfTuples(nm.GetNumberOfPoints()) for i in xrange(nm.GetNumberOfPoints()): p = [0.,0.,0.] nm.GetPoint(i,p) p = np.dot(nF,p-rc) p.flatten() pcoords.SetTuple3(i,p[0]+sc[0],p[1]+sc[1],p[2]+sc[2]) points = vtk.vtkPoints() points.SetData(pcoords) nm.SetPoints(points) nm.GetPoints().Modified() #calculate both the intersection and the union of the two polydata intersect = vtk.vtkBooleanOperationPolyDataFilter() intersect.SetOperation(1) intersect.SetInputData(0,nm) intersect.SetInputData(1,spatial) intersect.Update() union = vtk.vtkBooleanOperationPolyDataFilter() union.SetOperation(0) union.SetInputData(0,nm) union.SetInputData(1,spatial) union.Update() unionmass = vtk.vtkMassProperties() unionmass.SetInputConnection(union.GetOutputPort()) vol_union = unionmass.GetVolume() if intersect.GetOutput().GetNumberOfPoints() > 0: intmass = vtk.vtkMassProperties() intmass.SetInputConnection(intersect.GetOutputPort()) vol_int = intmass.GetVolume() else: #penalize with distance between centroids w = sc.T-np.dot(nF,rc.T) c = np.linalg.norm(w) vol_int = c*vol_union diff = max([abs(sv-vol_int),abs(sv-vol_union)]) return diff
def computeStatistics(self, segmentID): import vtkSegmentationCorePython as vtkSegmentationCore requestedKeys = self.getRequestedKeys() segmentationNode = slicer.mrmlScene.GetNodeByID( self.getParameterNode().GetParameter("Segmentation")) if len(requestedKeys) == 0: return {} containsClosedSurfaceRepresentation = segmentationNode.GetSegmentation( ).ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter. GetSegmentationClosedSurfaceRepresentationName()) if not containsClosedSurfaceRepresentation: return {} segmentClosedSurface = vtk.vtkPolyData() segmentationNode.GetClosedSurfaceRepresentation( segmentID, segmentClosedSurface) # Compute statistics massProperties = vtk.vtkMassProperties() massProperties.SetInputData(segmentClosedSurface) # Add data to statistics list ccPerCubicMM = 0.001 stats = {} if "surface_mm2" in requestedKeys: stats["surface_mm2"] = massProperties.GetSurfaceArea() if "volume_mm3" in requestedKeys: stats["volume_mm3"] = massProperties.GetVolume() if "volume_cm3" in requestedKeys: stats["volume_cm3"] = massProperties.GetVolume() * ccPerCubicMM return stats
def vtk_get_mesh_info(vtk_poly): if vtk_poly.GetNumberOfPolys() == 0: return 0 Mass = vtk.vtkMassProperties() Mass.SetInputData(vtk_poly) Mass.Update() return Mass.GetVolume(), Mass.GetSurfaceArea()
def computeStatistics(self, segmentID): import vtkSegmentationCorePython as vtkSegmentationCore requestedKeys = self.getRequestedKeys() segmentationNode = slicer.mrmlScene.GetNodeByID(self.getParameterNode().GetParameter("Segmentation")) if len(requestedKeys)==0: return {} containsClosedSurfaceRepresentation = segmentationNode.GetSegmentation().ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName()) if not containsClosedSurfaceRepresentation: return {} segment = segmentationNode.GetSegmentation().GetSegment(segmentID) closedSurfaceName = vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName() segmentClosedSurface = segment.GetRepresentation(closedSurfaceName) # Compute statistics massProperties = vtk.vtkMassProperties() massProperties.SetInputData(segmentClosedSurface) # Add data to statistics list ccPerCubicMM = 0.001 stats = {} if "surface_mm2" in requestedKeys: stats["surface_mm2"] = massProperties.GetSurfaceArea() if "volume_mm3" in requestedKeys: stats["volume_mm3"] = massProperties.GetVolume() if "volume_cm3" in requestedKeys: stats["volume_cm3"] = massProperties.GetVolume() * ccPerCubicMM return stats
def GetSurfaceArea(self,modelNode): massProperties = vtk.vtkMassProperties() triangleFilter = vtk.vtkTriangleFilter() massProperties.SetInputConnection(triangleFilter.GetOutputPort()) triangleFilter.SetInputData(modelNode.GetPolyData()) surfaceArea = massProperties.GetSurfaceArea() return surfaceArea
def test_vtk_surface_and_volume(self): import teigen.geometry3d as g3 height = 1.0 radius = 1.0 input1 = teigen.tb_vtk.get_cylinder([0.25, 0, -.5], height=height, radius=radius, direction=[0.0, .0, .0], resolution=50) object1Tri = vtk.vtkTriangleFilter() object1Tri.SetInputData(input1) object1Tri.Update() mass = vtk.vtkMassProperties() mass.SetInputData(object1Tri.GetOutput()) surf = mass.GetSurfaceArea() vol = mass.GetVolume() surf_analytic = g3.cylinder_surface(radius, height) vol_analytic = g3.cylinder_volume(radius, height) err_surf = np.abs(surf_analytic - surf) / surf_analytic err_vol = np.abs(vol_analytic - vol) / vol_analytic # print surf, surf_analytic, err_surf # print vol, vol_analytic, err_vol max_error = 0.01 self.assertLess(err_surf, max_error) self.assertLess(err_vol, max_error)
def MakeText(primitive): tf.update({primitive: vtk.vtkTriangleFilter()}) tf[primitive].SetInputConnection(primitive.GetOutputPort()) mp.update({primitive: vtk.vtkMassProperties()}) mp[primitive].SetInputConnection(tf[primitive].GetOutputPort()) # here we capture stdout and write it to a variable for processing. summary = StringIO.StringIO() # save the original stdout old_stdout = sys.stdout sys.stdout = summary print mp[primitive] summary = summary.getvalue() startSum = summary.find(" VolumeX") endSum = len(summary) print summary[startSum:] # Restore stdout sys.stdout = old_stdout vt.update({primitive: vtk.vtkVectorText()}) vt[primitive].SetText(summary[startSum:]) pdm.update({primitive: vtk.vtkPolyDataMapper()}) pdm[primitive].SetInputConnection(vt[primitive].GetOutputPort()) ta.update({primitive: vtk.vtkActor()}) ta[primitive].SetMapper(pdm[primitive]) ta[primitive].SetScale(0.2, 0.2, 0.2) return ta[primitive]
def volume(polydata): mass = vtk.vtkMassProperties() mass.SetInput(polydata) mass.Update() return mass.GetVolume()
def surface_area(polydata): mass = vtk.vtkMassProperties() mass.SetInput(polydata) mass.Update() return mass.GetSurfaceArea()
def MakeText(primitive): tf.update({primitive: vtk.vtkTriangleFilter()}) tf[primitive].SetInputConnection(primitive.GetOutputPort()) mp.update({primitive: vtk.vtkMassProperties()}) mp[primitive].SetInputConnection(tf[primitive].GetOutputPort()) # here we capture stdout and write it to a variable for processing. summary = StringIO.StringIO() # save the original stdout old_stdout = sys.stdout sys.stdout = summary print mp[primitive] summary = summary.getvalue() startSum = summary.find(" VolumeX") endSum = len(summary) print summary[startSum:] # Restore stdout sys.stdout = old_stdout vt.update({primitive: vtk.vtkVectorText()}) vt[primitive].SetText(summary[startSum:]) pdm.update({primitive: vtk.vtkPolyDataMapper()}) pdm[primitive].SetInputConnection(vt[primitive].GetOutputPort()) ta.update({primitive: vtk.vtkActor()}) ta[primitive].SetMapper(pdm[primitive]) ta[primitive].SetScale(.2, .2, .2) return ta[primitive]
def Execute(self): if self.Surface == None: if self.Input == None: self.PrintError('Error: no Surface.') self.Surface = self.Input # estimates surface area to estimate the point density cleaner = vtk.vtkCleanPolyData() cleaner.SetInputData(self.Surface) cleaner.Update() triangleFilter = vtk.vtkTriangleFilter() triangleFilter.SetInputConnection(cleaner.GetOutputPort()) triangleFilter.Update() massProps = vtk.vtkMassProperties() massProps.SetInputConnection(triangleFilter.GetOutputPort()) massProps.Update() print(massProps.GetSurfaceArea()) area = massProps.GetSurfaceArea() target_area = 3.0**0.5/4.0*self.EdgeLength**2.0 print ("target number of cells: {0}".format(area / target_area)) # A_total = N*(area_equilateral_triangle) print ("target number of points: {0}".format(area / target_area / 2.0)) #in the limit of equilateral triangles ratio ,Ncells/Npoints = 2
def addSegmentClosedSurfaceStatistics(self): import vtkSegmentationCorePython as vtkSegmentationCore containsClosedSurfaceRepresentation = self.segmentationNode.GetSegmentation( ).ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter. GetSegmentationClosedSurfaceRepresentationName()) if not containsClosedSurfaceRepresentation: return for segmentID in self.statistics["SegmentIDs"]: segment = self.segmentationNode.GetSegmentation().GetSegment( segmentID) segmentClosedSurface = segment.GetRepresentation( vtkSegmentationCore.vtkSegmentationConverter. GetSegmentationClosedSurfaceRepresentationName()) # Compute statistics massProperties = vtk.vtkMassProperties() massProperties.SetInputData(segmentClosedSurface) # Add data to statistics list ccPerCubicMM = 0.001 self.statistics[ segmentID, "CS surface mm2"] = massProperties.GetSurfaceArea() self.statistics[segmentID, "CS volume mm3"] = massProperties.GetVolume() self.statistics[ segmentID, "CS volume cc"] = massProperties.GetVolume() * ccPerCubicMM
def Execute(args): reader = vmtkscripts.vmtkSurfaceReader() reader.InputFileName = args.surface reader.Execute() Surface = reader.Surface # estimates surface area to estimate the point density cleaner = vtk.vtkCleanPolyData() cleaner.SetInputData(Surface) cleaner.Update() triangleFilter = vtk.vtkTriangleFilter() triangleFilter.SetInputConnection(cleaner.GetOutputPort()) triangleFilter.Update() massProps = vtk.vtkMassProperties() massProps.SetInputConnection(triangleFilter.GetOutputPort()) massProps.Update() print(massProps.GetSurfaceArea()) area = massProps.GetSurfaceArea() target_area = 3.0**0.5 / 4.0 * args.edge_length**2.0 print("target number of cells: {0}".format( area / target_area)) # A_total = N*(area_equilateral_triangle) print("target number of points: {0}".format( area / target_area / 2.0)) #in the limit of equilateral triangles ratio ,Ncells/Npoints = 2
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__( self, module_manager, vtk.vtkMassProperties(), 'Processing.', ('vtkPolyData',), (), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def CalculateSurfaceArea(polydata): """ Calculate the volume from the given polydata """ # Filter used to calculate volume and area from a polydata measured_polydata = vtk.vtkMassProperties() measured_polydata.SetInputData(polydata) return measured_polydata.GetSurfaceArea()
def find_vtp_area(infile): reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(infile) reader.Update() poly = reader.GetOutputPort() masser = vtk.vtkMassProperties() masser.SetInputConnection(poly) masser.Update() return masser.GetSurfaceArea()
def _readstls(self): """ Reads in all STL files contained in directories indicated by **ref_dir** and **def_dir**. Also calls **_make3Dmesh()** to create 3-D tetrahedral meshes. Returns ------- rsurfs, dsurfs """ for fname in sorted(os.listdir(self._ref_dir)): if '.stl' in fname.lower(): reader = vtk.vtkSTLReader() reader.SetFileName( str(os.path.normpath(self._ref_dir + os.sep + fname))) reader.Update() triangles = vtk.vtkTriangleFilter() triangles.SetInputConnection(reader.GetOutputPort()) triangles.Update() self.rsurfs.append(triangles.GetOutput()) massProps = vtk.vtkMassProperties() massProps.SetInputData(self.rsurfs[-1]) massProps.Update() print(("Generating tetrahedral mesh from {:s}".format(fname))) self._make3Dmesh( str(os.path.normpath(self._ref_dir + os.sep + fname)), 'MATERIAL', massProps.GetVolume()) for fname in sorted(os.listdir(self._def_dir)): if '.stl' in fname.lower(): reader = vtk.vtkSTLReader() reader.SetFileName( str(os.path.normpath(self._def_dir + os.sep + fname))) reader.Update() triangles = vtk.vtkTriangleFilter() triangles.SetInputConnection(reader.GetOutputPort()) triangles.Update() self.dsurfs.append(triangles.GetOutput()) massProps = vtk.vtkMassProperties() massProps.SetInputData(self.dsurfs[-1]) massProps.Update() print(("Generating tetrahedral mesh from {:s}".format(fname))) self._make3Dmesh( str(os.path.normpath(self._def_dir + os.sep + fname)), 'SPATIAL', massProps.GetVolume())
def createMassProperties( pdata, verbose=1): myVTK.myPrint(verbose, "*** createMassProperties ***") mass_properties = vtk.vtkMassProperties() mass_properties.SetInputData(pdata) return mass_properties
def getProps(bX): err = ErrorObserver() props = vtk.vtkMassProperties() props.AddObserver('ErrorEvent', err) props.SetInputConnection(bX.GetOutputPort()) props.Update() if err.ErrorOccurred(): return -100000.,-100000. else: return props.GetVolume(),props.GetSurfaceArea()
def volume(self): """ Computes volume by extracting the external surface and computing interior volume """ surf = self.ExtractSurface().TriFilter() mass = vtk.vtkMassProperties() mass.SetInputData(surf) return mass.GetVolume()
def createMassProperties(pdata, verbose=0): myVTK.myPrint(verbose, "*** createMassProperties ***") mass_properties = vtk.vtkMassProperties() if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): mass_properties.SetInputData(pdata) else: mass_properties.SetInput(pdata) return mass_properties
def computeVolume(meshPath): #Reading reader = vtkPolyDataReader() reader.SetFileName(meshPath) reader.Update() #First volume mass = vtkMassProperties() mass.SetInputConnection(reader.GetOutputPort()) mass.Update() volume = mass.GetVolume() assert 0 <= volume, "Warning : negative volume, that's weird." return volume
def area(self): """Return the mesh surface area. Return ------ area : float Total area of the mesh. """ mprop = vtk.vtkMassProperties() mprop.SetInputData(self) return mprop.GetSurfaceArea()
def createMassProperties( pdata, verbose=1): myVTK.myPrint(verbose, "*** createMassProperties ***") mass_properties = vtk.vtkMassProperties() if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): mass_properties.SetInputData(pdata) else: mass_properties.SetInput(pdata) return mass_properties
def getMassProperties( pdata, verbose=0): mypy.my_print(verbose, "*** getMassProperties ***") mass_properties = vtk.vtkMassProperties() if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): mass_properties.SetInputData(pdata) else: mass_properties.SetInput(pdata) return mass_properties
def GetVolume(self): """Returns the volume of the vessel""" """ capSurface=vtk.vtkFillHolesFilter() capSurface.SetInputData(self.Surface) capSurface.Update()""" capSurface = vmtkscripts.vmtkSurfaceCapper() capSurface.Interactive = 0 capSurface.Surface = self.Surface capSurface.Execute() vesselVolume = vtk.vtkMassProperties() vesselVolume.SetInputData(capSurface.Surface) print("Vessel Volume:{}", vesselVolume.GetVolume())
def volume(self): """ Mesh volume - will throw a VTK error/warning if not a closed surface Returns ------- volume : float Total volume of the mesh. """ mprop = vtk.vtkMassProperties() mprop.SetInputData(self.tri_filter()) return mprop.GetVolume()
def volume(self): """Return the mesh volume. This will throw a VTK error/warning if not a closed surface Return ------ volume : float Total volume of the mesh. """ mprop = vtk.vtkMassProperties() mprop.SetInputData(self.triangulate()) return mprop.GetVolume()
def get_polydata_volume(poly): """ Compute volume of a enclosed vtk polydata Args: poly: vtk PolyData Returns: volume: PolyData volume """ mass = vtk.vtkMassProperties() mass.SetInputData(poly) volume = mass.GetVolume() return volume
def surface_area_vtk(self): if self.VTK_installed is False: raise VTK_Exception('VTK must be installed to access the surface_area_vtk property') if self._surface_area_vtk is None: tri_converter = vtk.vtkTriangleFilter() tri_converter.SetInputDataObject(self.vtp_mesh) tri_converter.Update() tri_mesh = tri_converter.GetOutput() mass_props = vtk.vtkMassProperties() mass_props.SetInputDataObject(tri_mesh) self._surface_area_vtk = mass_props.GetSurfaceArea() print 'Calculated mesh surface area using VTK Python bindings' return self._surface_area_vtk
def getVolumeByIsosurface(self, threshold=0): isoSurface = vtk.vtkContourFilter() isoSurface.SetInputConnection(self.Reader.GetOutputPort()) isoSurface.SetValue(0, threshold) clean_data = vtk.vtkCleanPolyData() clean_data.SetInputConnection(isoSurface.GetOutputPort()) triangles = vtk.vtkTriangleFilter() triangles.SetInputConnection(isoSurface.GetOutputPort()) mass = vtk.vtkMassProperties() mass.SetInputConnection(triangles.GetOutputPort()) return mass.GetVolume()
def volume_vtk(self): if self.VTK_installed is False: raise VTK_Exception('VTK must be installed to access the volume_vtk property') if self._volume_vtk is None: tri_converter = vtk.vtkTriangleFilter() tri_converter.SetInputDataObject(self.vtp_mesh) tri_converter.Update() tri_mesh = tri_converter.GetOutput() mass_props = vtk.vtkMassProperties() mass_props.SetInputDataObject(tri_mesh) self._volume_vtk = mass_props.GetVolume() print 'Calculated mesh volume using VTK library' return self._volume_vtk
def calculateVolume(polyData): """ Calculates the volume of a polydata cell. Input: polyData - vtkPolyData object - Contains a cell defined by triangular polygons and needs to be waterthight. Returns: float - The volume of the cell in the respecitve units. """ # Mass prop mp = vtk.vtkMassProperties() # Set the input mp.SetInputData(polyData) return float(mp.GetVolume())
def writeToIschemicVolumeFile(heart, name_of_array, flow_ids, flows, norm_flows): thresholds = [ .01, .02, .03, .04, .05, .06, .07, .08, .09, .1, .12, .14, .16, .18, .2, .25, .3, .35, .4, .45, .5, .55, .6, .65, .7, .75, .8, .85, .9, .95, .96, .97, .98, .99, 1 ] numPts = heart.GetNumberOfPoints() #get flow ids and flow percent recovery flow_recovery_fraction = dict() for i in norm_flows: if i in flows and norm_flows[i] > 0: flow_recovery_fraction[i] = flows[i] / norm_flows[i] #if percent recovery lower than threshold, then assign it to ischemic volume and add it to growing sum ischemic_volume = dict() for it in thresholds: ischemic_nodes = vtk.vtkIdList() for ip in range(0, numPts): if heart.GetPointData().GetArray( name_of_array + '_FlowPerfusion').GetValue( ip) < it and heart.GetPointData().GetArray( name_of_array + '_FlowPerfusion').GetValue(ip) > 0: ischemic_nodes.InsertNextId(ip) region = vtk.vtkThreshold() region.SetInputData(heart) region.SetInputArrayToProcess( 0, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS, name_of_array + '_FlowPerfusion') region.ThresholdBetween(0, it) region.Update() dssf = vtk.vtkDataSetSurfaceFilter() dssf.SetInputConnection(region.GetOutputPort()) dssf.Update() Mass = vtk.vtkMassProperties() Mass.SetInputData(dssf.GetOutput()) Mass.Update() ischemic_volume[it] = Mass.GetVolume() ischemic_nodes.Reset() file = open('Summary_ischemic_collateral.csv', 'a+') out_string = name_of_array for i in thresholds: out_string = out_string + ',' + str(ischemic_volume[i]) file.write(out_string + '\n') file.close()
def _test(): # import the stl surfaces bonePolydata = importStlSurf('oks001_MRC_FMB_LVTIT_10.stl') # cartPolydata = importStlSurf('oks001_MRC_FMC_LVTIT_10.stl') # # boolFilter = vtk.vtkBooleanOperationPolyDataFilter() # boolFilter.SetOperationToIntersection() # Define the type of boolean filter # boolFilter.SetInputData(0, bonePolydata) # boolFilter.SetInputData(1, cartPolydata) # # boolFilter.Update() # overlapPolydata = boolFilter.GetOutput() volFilter = vtk.vtkMassProperties() volFilter.SetInputData(bonePolydata) volFilter.Update() print volFilter.GetVolume() return
def CreateCrossSections(files, outputAreas, outputGeometryFile): areaFile = open(outputAreas, 'w') appender = vtk.vtkAppendPolyData() mp = vtk.vtkMassProperties() for idx in range(len(files)): file = files[idx] polydata = CreateCrossSectionPolyDataFromFile(file) mp.SetInputData(polydata) mp.Update() areaFile.write(str(mp.GetSurfaceArea())) areaFile.write('\n') appender.AddInputData(polydata) writer = vtk.vtkXMLPolyDataWriter() writer.SetFileName(outputGeometryFile) writer.SetInputConnection(appender.GetOutputPort()) writer.Update() areaFile.close()
def Execute(self): if self.Surface == None: self.PrintError('Error: No input surface.') cleaner = vtk.vtkCleanPolyData() cleaner.SetInput(self.Surface) cleaner.Update() triangleFilter = vtk.vtkTriangleFilter() triangleFilter.SetInput(cleaner.GetOutput()) triangleFilter.Update() massProps = vtk.vtkMassProperties() massProps.SetInput(triangleFilter.GetOutput()) massProps.Update() self.SurfaceArea = massProps.GetSurfaceArea() self.Volume = massProps.GetVolume() self.ShapeIndex = massProps.GetNormalizedShapeIndex()
def addSegmentClosedSurfaceStatistics(self): import vtkSegmentationCorePython as vtkSegmentationCore containsClosedSurfaceRepresentation = self.segmentationNode.GetSegmentation().ContainsRepresentation( vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName()) if not containsClosedSurfaceRepresentation: return for segmentID in self.statistics["SegmentIDs"]: segment = self.segmentationNode.GetSegmentation().GetSegment(segmentID) segmentClosedSurface = segment.GetRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName()) # Compute statistics massProperties = vtk.vtkMassProperties() massProperties.SetInputData(segmentClosedSurface) # Add data to statistics list ccPerCubicMM = 0.001 self.statistics[segmentID,"CS surface mm2"] = massProperties.GetSurfaceArea() self.statistics[segmentID,"CS volume mm3"] = massProperties.GetVolume() self.statistics[segmentID,"CS volume cc"] = massProperties.GetVolume() * ccPerCubicMM
def UpdateMathValues(self): connection = self._app_states[self._current_image_index].GetFactory().GetInputConnection() object = connection.GetProducer().GetOutput() # determine number of connected components _f = vtk.vtkPolyDataConnectivityFilter() _f.SetInputConnection(connection) _f.Update() nregions = _f.GetNumberOfExtractedRegions() self._app_states[self._current_image_index]._poly_count = object.GetNumberOfPolys() self._app_states[self._current_image_index]._volume, self._app_states[self._current_image_index]._area = ( 0.0, 0.0, ) self._app_states[self._current_image_index]._region_count = nregions if self._app_states[self._current_image_index]._poly_count > 0: math0 = vtk.vtkMassProperties() math0.SetInputConnection(connection) math0.Update() self._app_states[self._current_image_index]._volume, self._app_states[self._current_image_index]._area = ( math0.GetVolume(), math0.GetSurfaceArea(), ) self.UpdateStatisticsText() # log some results logger = logging.getLogger("results") logger.info( "Isosurface plugin (%s):" % (component.getUtility(ICurrentViewportManager).GetPageState().GetTitle()) ) logger.info(u"\tArea: %0.3f mm\u00B2" % self._app_states[self._current_image_index]._area) logger.info(u"\tVolume: %0.3f mm\u00B3" % (self._app_states[self._current_image_index]._volume)) logger.info("\tPolygon Count: %d" % (self._app_states[self._current_image_index]._poly_count)) logger.info("\tRegion Count: %d" % (self._app_states[self._current_image_index]._region_count)) logger.info("")
def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxation_factor, decimate_reduction, keep_largest, fill_holes, options, msg_queue): def send_message(msg): try: msg_queue.put_nowait(msg) except queue.Full as e: print(e) log_path = tempfile.mktemp('vtkoutput.txt') fow = vtk.vtkFileOutputWindow() fow.SetFileName(log_path) ow = vtk.vtkOutputWindow() ow.SetInstance(fow) send_message('Joining surfaces ...') polydata_append = vtk.vtkAppendPolyData() for f in filenames: reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(f) reader.Update() polydata = reader.GetOutput() polydata_append.AddInputData(polydata) del reader del polydata polydata_append.Update() # polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del polydata_append send_message('Cleaning surface ...') clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean if algorithm == 'ca_smoothing': send_message('Calculating normals ...') normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() # polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean # try: # polydata.BuildLinks() # except TypeError: # polydata.BuildLinks(0) # polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], # options['max distance'], # options['min weight'], # options['steps']) send_message('Context Aware smoothing ...') mesh = cy_mesh.Mesh(polydata) cy_mesh.ca_smoothing(mesh, options['angle'], options['max distance'], options['min weight'], options['steps']) # polydata = mesh.to_vtk() # polydata.SetSource(None) # polydata.DebugOn() # else: # #smoother = vtk.vtkWindowedSincPolyDataFilter() # send_message('Smoothing ...') # smoother = vtk.vtkSmoothPolyDataFilter() # smoother_ref = weakref.ref(smoother) # # smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: # # UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) # smoother.SetInputData(polydata) # smoother.SetNumberOfIterations(smooth_iterations) # smoother.SetRelaxationFactor(smooth_relaxation_factor) # smoother.SetFeatureAngle(80) # #smoother.SetEdgeAngle(90.0) # #smoother.SetPassBand(0.1) # smoother.BoundarySmoothingOn() # smoother.FeatureEdgeSmoothingOn() # #smoother.NormalizeCoordinatesOn() # #smoother.NonManifoldSmoothingOn() # # smoother.ReleaseDataFlagOn() # # smoother.GetOutput().ReleaseDataFlagOn() # smoother.Update() # del polydata # polydata = smoother.GetOutput() # #polydata.Register(None) # # polydata.SetSource(None) # del smoother if not decimate_reduction: print("Decimating", decimate_reduction) send_message('Decimating ...') decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) # decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() # decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del decimation #to_measure.Register(None) # to_measure.SetSource(None) if keep_largest: send_message('Finding the largest ...') conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInputData(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) # conn_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() # conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: send_message('Filling holes ...') filled_polydata = vtk.vtkFillHolesFilter() # filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) # filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() # filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) # polydata.SetSource(None) # polydata.DebugOn() del filled_polydata to_measure = polydata normals = vtk.vtkPolyDataNormals() # normals.ReleaseDataFlagOn() # normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) normals.SetFeatureAngle(80) normals.SplittingOn() normals.AutoOrientNormalsOn() normals.NonManifoldTraversalOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del normals # # Improve performance # stripper = vtk.vtkStripper() # # stripper.ReleaseDataFlagOn() # # stripper_ref = weakref.ref(stripper) # # stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: # # UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) # stripper.SetInputData(polydata) # stripper.PassThroughCellIdsOn() # stripper.PassThroughPointIdsOn() # # stripper.GetOutput().ReleaseDataFlagOn() # stripper.Update() # del polydata # polydata = stripper.GetOutput() # #polydata.Register(None) # # polydata.SetSource(None) # del stripper send_message('Calculating area and volume ...') measured_polydata = vtk.vtkMassProperties() measured_polydata.SetInputData(to_measure) measured_polydata.Update() volume = float(measured_polydata.GetVolume()) area = float(measured_polydata.GetSurfaceArea()) del measured_polydata filename = tempfile.mktemp(suffix='_full.vtp') writer = vtk.vtkXMLPolyDataWriter() writer.SetInputData(polydata) writer.SetFileName(filename) writer.Write() del writer print("MY PID", os.getpid()) return filename, {'volume': volume, 'area': area}
def extractfeatures(self, DICOMImages, image_pos_pat, image_ori_pat, series_path, phases_series, VOI_mesh): """ Start pixVals for collection pixel values at VOI """ pixVals_margin = []; pixVals = [] Fmargin = {}; voxel_frameS = {} # necessary to read point coords VOIPnt = [0,0,0] ijk = [0,0,0] pco = [0,0,0] for i in range(len(DICOMImages)): # find mapping to Dicom space [transformed_image, transform_cube] = Display().dicomTransform(DICOMImages[i], image_pos_pat, image_ori_pat) if (i==0): # create mask from segmenation np_VOI_mask = self.createMaskfromMesh(VOI_mesh, transformed_image) for j in range( VOI_mesh.GetNumberOfPoints() ): VOI_mesh.GetPoint(j, VOIPnt) # extract pixID at location VOIPnt pixId = transformed_image.FindPoint(VOIPnt[0], VOIPnt[1], VOIPnt[2]) im_pt = [0,0,0] transformed_image.GetPoint(pixId,im_pt) inorout = transformed_image.ComputeStructuredCoordinates( im_pt, ijk, pco) if(inorout == 0): pass else: pixValx = transformed_image.GetScalarComponentAsFloat( ijk[0], ijk[1], ijk[2], 0) pixVals_margin.append(pixValx) # Now collect pixVals print "\n Saving %s" % 'Fmargin'+str(i) Fmargin['Fmargin'+str(i)] = pixVals_margin pixVals_margin = [] # extract pixID at inside VOIPnt VOI_scalars = transformed_image.GetPointData().GetScalars() np_VOI_imagedata = vtk_to_numpy(VOI_scalars) dims = transformed_image.GetDimensions() spacing = transformed_image.GetSpacing() np_VOI_imagedata = np_VOI_imagedata.reshape(dims[2], dims[1], dims[0]) np_VOI_imagedata = np_VOI_imagedata.transpose(2,1,0) #################### HERE GET INTERNAL PIXELS IT AND MASK IT OUT VOI_imagedata = np_VOI_imagedata[nonzero(np_VOI_mask)] for j in range( len(VOI_imagedata) ): pixValx = VOI_imagedata[j] pixVals.append(pixValx) # Now collect pixVals print "\n Saving %s" % 'F'+str(i) voxel_frameS['F'+str(i)] = pixVals pixVals = [] ############################################################## # Initialize features self.i_var = []; self.alln_F_r_i=[]; self.allmin_F_r_i=[]; self.allmax_F_r_i=[]; self.allmean_F_r_i=[]; self.allvar_F_r_i=[]; self.allskew_F_r_i=[]; self.allkurt_F_r_i=[] F_r_0 = array(voxel_frameS['F'+str(0)]).astype(float) n, min_max, meanFr, var_F_r_0, skew, kurt = stats.describe(F_r_0) self.i_var_max = 0 # Collect to Compute inhomogeneity variance of uptake and other variables for k in range(1,len(DICOMImages)): F_r_i = array(voxel_frameS['F'+str(k)]).astype(float) print "\nF_r_i parameters %s" % str(k) n_F_r_i, min_max_F_r_i, mean_F_r_i, var_F_r_i, skew_F_r_i, kurt_F_r_i = stats.describe(F_r_i) print("Number of internal voxels: {0:d}".format(n_F_r_i)) self.alln_F_r_i.append(n_F_r_i) print("Minimum: {0:8.6f} Maximum: {1:8.6f}".format(min_max_F_r_i[0], min_max_F_r_i[1])) self.allmin_F_r_i.append(min_max_F_r_i[0]) self.allmax_F_r_i.append(min_max_F_r_i[1]) print("Mean: {0:8.6f}".format(mean_F_r_i)) self.allmean_F_r_i.append(mean_F_r_i) print("Variance F_r_i: {0:8.6f}".format(var_F_r_i)) self.allvar_F_r_i.append(var_F_r_i) print("Skew : {0:8.6f}".format(skew_F_r_i)) self.allskew_F_r_i.append(skew_F_r_i) print("Kurtosis: {0:8.6f}".format(kurt_F_r_i)) self.allkurt_F_r_i.append(kurt_F_r_i) print("Variance of uptake: {0:8.6f}".format(var_F_r_i/var_F_r_0)) self.i_var.append( var_F_r_i/var_F_r_0 ) # Find max of change in variance of uptake if( self.i_var[k-1] > self.i_var_max): self.i_var_max = self.i_var[k-1] print("\nMax Variance of uptake: {0:8.6f}\n".format( self.i_var_max )) # Collect to Compute change in variance of uptake self.ii_var = [] self.ii_var_min = 1000 for k in range(len(DICOMImages)-1): F_r_i = array(voxel_frameS['F'+str(k)]).astype(float) F_r_iplus = array(voxel_frameS['F'+str(k+1)]).astype(float) n, min_max, meanFr, var_F_r_ith, skew, kurt = stats.describe(F_r_i) n, min_max, meanFr, var_F_r_iplus, skew, kurt = stats.describe(F_r_iplus) """change Variance of uptake:""" self.ii_var.append( var_F_r_ith/var_F_r_iplus ) # Find max of change in variance of uptake if( var_F_r_ith/var_F_r_iplus < self.ii_var_min): self.ii_var_min = var_F_r_ith/var_F_r_iplus print("Min change Variance of uptake: {0:8.6f}\n".format( self.ii_var_min )) # Extract features for sharpness of lesion margin, compute Margin gradient iii_var # The gradient is computed using convolution with a 3D sobel filter using scipy.ndimage.filters.sobel # The function generic_gradient_magnitude calculates a gradient magnitude using the function passed through derivative to calculate first derivatives. F_rmargin_0 = array(Fmargin['Fmargin'+str(0)]).astype(float) self.iii_var_max = -1000 iii_Sobelvar = [] # Collect to Compute variance of uptake and other variables for k in range(1,len(DICOMImages)): F_rmargin_i = array(Fmargin['Fmargin'+str(k)]).astype(float) margin_delta = F_rmargin_i-F_rmargin_0 # using first sobel and then prewitt sobel_grad_margin_delta = generic_gradient_magnitude(margin_delta, sobel) # compute feature Margin Gradient n, min_max, mean_sobel_grad_margin, var, skew, kurt = stats.describe(sobel_grad_margin_delta) n, min_max, mean_F_rmargin_i, var_F_r_ith, skew, kurt = stats.describe(F_rmargin_i) """Margin Gradient""" iii_Sobelvar.append( mean_sobel_grad_margin/mean_F_rmargin_i ) # Find max of Margin Gradient if( iii_Sobelvar[k-1] > self.iii_var_max): self.iii_var_max = iii_Sobelvar[k-1] self.iii_var_max_k = k print("Max Margin Gradient: {0:8.6f}".format( self.iii_var_max )) print("k for Max Margin Gradient: {0:8.6f}".format( self.iii_var_max_k )) # compute iv feature Variance of Margin Gradient # note: only computed from the subtraction frames of i and 0 where the margin gradient iii_var is maximum. self.ivVariance = [] F_rmargin_iv = array(Fmargin['Fmargin'+str(self.iii_var_max_k)]).astype(float) n, min_max, mean_F_rmargin_iv, var_F_r_ith, skew, kurt = stats.describe(F_rmargin_iv) margin_delta_iv = F_rmargin_iv-F_rmargin_0 # using first sobel and then prewitt sobel_grad_margin_delta_iv = generic_gradient_magnitude(margin_delta_iv, sobel) n, min_max, mean_sobel, var_sobel_grad_margin_delta_iv, skew, kurt = stats.describe(sobel_grad_margin_delta_iv) self.ivVariance = var_sobel_grad_margin_delta_iv/mean_F_rmargin_iv**2 print("Variance of spatial Margin Gradient: {0:8.6f}".format( self.ivVariance )) # Extract Shape features: pre-requisite is the Volume and the diameter of the lesion #################################### # Measure VOI ################################### VOI_massProperty = vtk.vtkMassProperties() VOI_massProperty.SetInputData(VOI_mesh) VOI_massProperty.Update() # get VOI volume # VTK is unitless. The units you get out are the units you put in. # If your input polydata has points defined in terms of millimetres, then # the volume will be in cubic millimetres. VOI_vol = VOI_massProperty.GetVolume() # mm3 VOI_surface = VOI_massProperty.GetSurfaceArea() # mm2 # just print the results print "\nVolume lesion = ", VOI_vol print "Surface lesion = ", VOI_surface # Calculate the effective diameter of the surface D=2(sqrt3(3V/(4pi))) diam_root = (3*VOI_vol)/(4*pi) self.VOI_efect_diameter = 2*pow(diam_root,1.0/3) print "VOI_efect_diameter = ", self.VOI_efect_diameter centerOfMassFilter = vtk.vtkCenterOfMass() centerOfMassFilter.SetInputData( VOI_mesh ) centerOfMassFilter.SetUseScalarsAsWeights(False) centerOfMassFilter.Update() # centroid of lesion self.lesion_centroid = [0,0,0] self.lesion_centroid = centerOfMassFilter.GetCenter() print "lesion_centroid = ", self.lesion_centroid # create a sphere to compute the volume of lesion within a sphere of effective diameter sphere_effectD = vtk.vtkSphereSource() sphere_effectD.SetRadius(self.VOI_efect_diameter/2) #VOI_diameter/2 sphere_effectD.SetCenter(self.lesion_centroid) sphere_effectD.Update() # compute volume of lesion within a sphere of effective diameter sphereVOI_massProperty = vtk.vtkMassProperties() sphereVOI_massProperty.SetInputData(sphere_effectD.GetOutput()) sphereVOI_massProperty.Update() sphereVOI_vol = sphereVOI_massProperty.GetVolume() # mm3 # just print the results print "Volume sphereVOI = ", sphereVOI_vol # Compute Shape of lesion in 3D # Circularity epsilon = 0.001 self.circularity = sphereVOI_vol/(VOI_vol+epsilon) print("\nCircularity: {0:8.6f}".format( self.circularity )) self.irregularity = 1 - pi*(self.VOI_efect_diameter/VOI_surface) print("Irregularity: {0:8.6f}".format( self.irregularity )) #################################### # Radial gradient analysis ref[9] white paper ################################### # Radial gradient analysis is based on examination of the angles between voxel-value gradients # and lines intersecting a single point near the center of the suspect lesion, lines in radial directions. # Radial gradient values are given by the dot product of the gradient direction and the radial direction. RGH_mean = []; self.max_RGH_mean = 0; self.max_RGH_mean_k = 0; RGH_var = []; self.max_RGH_var = 0; self.max_RGH_var_k = 0; H_norm_p = [] # do subtraction of timepost-pre #################### for i in range(1,len(DICOMImages)): subtractedImage = Display().subImage(DICOMImages, i) [transformed_image, transform_cube] = Display().dicomTransform(subtractedImage, image_pos_pat, image_ori_pat) for j in range( VOI_mesh.GetNumberOfPoints() ): VOI_mesh.GetPoint(j, VOIPnt) r = array(VOIPnt) rc = array(self.lesion_centroid) norm_rdir = (r-rc)/linalg.norm(r-rc) # Find point for gradient vectors at the margin point pixId = transformed_image.FindPoint(VOIPnt[0], VOIPnt[1], VOIPnt[2]) sub_pt = [0,0,0] transformed_image.GetPoint(pixId, sub_pt) ijk = [0,0,0] pco = [0,0,0] grad_pt = [0,0,0]; inorout = transformed_image.ComputeStructuredCoordinates( sub_pt, ijk, pco) if(inorout == 0): print "point outside data" else: transformed_image.GetPointGradient( ijk[0], ijk[1], ijk[2], transformed_image.GetPointData().GetScalars(), grad_pt) ############# # Compute vector in the direction gradient at margin point grad_marginpt = array([grad_pt]) norm_grad_marginpt = grad_marginpt/linalg.norm(grad_marginpt) # Compute dot product (unit vector for dot product) p_dot = dot(norm_grad_marginpt, norm_rdir) norm_p_dot = np.abs(p_dot)[0] #linalg.norm(p_dot) H_norm_p.append(norm_p_dot) # The histogram of radial gradient values quantifying the frequency of occurrence of the dot products in a given region of interest # radial gradient histogram. The hist() function now has a lot more options # first create a single histogram # the histogram of the data with histtype='step' # plt.figure() # nsamples, bins, patches = plt.hist(array(H_norm_p), 50, normed=1, histtype='bar',facecolor='blue', alpha=0.75) # n, min_max, mean_bins, var_bins, skew, kurt = stats.describe(nsamples) mean_bins = np.mean(H_norm_p) var_bins = np.var(H_norm_p) print("\n mean RGB: {0:8.6f}".format( mean_bins )) print("variance RGB: {0:8.6f}".format( var_bins )) # Append data RGH_mean.append( mean_bins ) RGH_var.append( var_bins ) # Find max of RGH Gradient if( RGH_mean[i-1] > self.max_RGH_mean): self.max_RGH_mean = RGH_mean[i-1] self.max_RGH_mean_k = i if( RGH_var[i-1] > self.max_RGH_var): self.max_RGH_var = RGH_var[i-1] self.max_RGH_var_k = i # add a line showing the expected distribution # create a histogram by providing the bin edges (unequally spaced) plt.xlabel('normalized dot product |R.G|') plt.ylabel('Probability') plt.title('radial gradient histogram') plt.grid(True) ################# Jacob's lesion margin sharpness #initializations VOI_outlinept_normal = [0,0,0]; VOI_outlinept = [0,0,0]; inpt = [0,0,0]; outpt = [0,0,0] im_pts = [0,0,0]; ijk_in = [0,0,0]; ijk_out = [0,0,0]; pco = [0,0,0]; SIout_pixVal=[]; lastSIout_pixVal=[] # get model_point_normals VOI_point_normals = vtk.vtkPolyDataNormals() VOI_point_normals.SetInputData( VOI_mesh ) VOI_point_normals.SetComputePointNormals(1) VOI_point_normals.SetComputeCellNormals(0) VOI_point_normals.SplittingOff() VOI_point_normals.FlipNormalsOff() VOI_point_normals.ConsistencyOn() VOI_point_normals.Update() # Retrieve model normals VOI_normalsRetrieved = VOI_point_normals.GetOutput().GetPointData().GetNormals() VOI_n = VOI_normalsRetrieved.GetNumberOfTuples() # obtain vols of interest [transf_pre_dicomReader, transform_cube] = Display().dicomTransform(DICOMImages[0], image_pos_pat, image_ori_pat) [transf_last_dicomReader, transform_cube] = Display().dicomTransform(DICOMImages[len(DICOMImages)-1], image_pos_pat, image_ori_pat) num_margin = [] den_margin = [] for i in range(1,len(DICOMImages)): #initializations SIout_pixVal=[] lastSIout_pixVal=[] subtractedImage = Display().subImage(DICOMImages, i) [transf_sub_pre_dicomReader, transform_cube] = Display().dicomTransform(subtractedImage, image_pos_pat, image_ori_pat) for k in range( VOI_n ): VOI_outlinept_normal = VOI_normalsRetrieved.GetTuple3(k) VOI_mesh.GetPoint(k, VOI_outlinept) # "d for radial lenght: %f" % d d = sqrt(spacing[0]**2 + spacing[1]**2 + spacing[2]**2) inpt[0] = VOI_outlinept[0] - VOI_outlinept_normal[0]*d inpt[1] = VOI_outlinept[1] - VOI_outlinept_normal[1]*d inpt[2] = VOI_outlinept[2] - VOI_outlinept_normal[2]*d outpt[0] = VOI_outlinept[0] + VOI_outlinept_normal[0]*d outpt[1] = VOI_outlinept[1] + VOI_outlinept_normal[1]*d outpt[2] = VOI_outlinept[2] + VOI_outlinept_normal[2]*d # get pre-contrast SIin to normalized RSIgroup [See equation 1] from paper prepixin = transf_pre_dicomReader.FindPoint(inpt[0], inpt[1], inpt[2]) transf_pre_dicomReader.GetPoint(prepixin,im_pts) transf_pre_dicomReader.ComputeStructuredCoordinates( im_pts, ijk_in, pco) #print ijk_in # get pre-contrast SIout in 6-c-neighbordhood to normalized RSIgroup [See equation 1] from paper prepixout = transf_pre_dicomReader.FindPoint(outpt[0], outpt[1], outpt[2]) transf_pre_dicomReader.GetPoint(prepixout,im_pts) transf_pre_dicomReader.ComputeStructuredCoordinates( im_pts, ijk_out, pco) #print ijk_out # get t-post SIin SIin_pixVal = transf_sub_pre_dicomReader.GetScalarComponentAsFloat( ijk_in[0], ijk_in[1], ijk_in[2], 0 ) preSIin_pixVal = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_in[0], ijk_in[1], ijk_in[2], 0 )+epsilon RSIin = SIin_pixVal/preSIin_pixVal #### # get t-post SIout 6-c-neighbordhood #cn1 SIout = transf_sub_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0]+1, ijk_out[1], ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0]+1, ijk_out[1], ijk_out[2], 0 )+epsilon SIout_pixVal.append(float(SIout/preSIout)) #cn2 SIout = transf_sub_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0]-1, ijk_out[1], ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0]-1, ijk_out[1], ijk_out[2], 0 )+epsilon SIout_pixVal.append(float(SIout/preSIout)) #cn3 SIout = transf_sub_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]+1, ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]+1, ijk_out[2], 0 )+epsilon SIout_pixVal.append(float(SIout/preSIout)) #cn4 SIout = transf_sub_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2], 0 )+epsilon SIout_pixVal.append(float(SIout/preSIout)) #cn5 SIout = transf_sub_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1], ijk_out[2]+1, 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1], ijk_out[2]+1, 0 )+epsilon SIout_pixVal.append(float(SIout/preSIout)) #cn6 SIout = transf_sub_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2]-1, 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2]-1, 0 )+epsilon SIout_pixVal.append(float(SIout/preSIout)) RSIout = mean( SIout_pixVal ) ### # get last-post SIout 6-c-neighbordhood #cn1 SIout = transf_last_dicomReader.GetScalarComponentAsFloat( ijk_out[0]+1, ijk_out[1], ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0]+1, ijk_out[1], ijk_out[2], 0 )+epsilon lastSIout_pixVal.append(float(SIout/preSIout)) #cn2 SIout = transf_last_dicomReader.GetScalarComponentAsFloat( ijk_out[0]-1, ijk_out[1], ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0]-1, ijk_out[1], ijk_out[2], 0 )+epsilon lastSIout_pixVal.append(float(SIout/preSIout)) #cn3 SIout = transf_last_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]+1, ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]+1, ijk_out[2], 0 )+epsilon lastSIout_pixVal.append(float(SIout/preSIout)) #cn4 SIout = transf_last_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2], 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2], 0 )+epsilon lastSIout_pixVal.append(float(SIout/preSIout)) #cn5 SIout = transf_last_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1], ijk_out[2]+1, 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1], ijk_out[2]+1, 0 )+epsilon lastSIout_pixVal.append(float(SIout/preSIout)) #cn6 SIout = transf_last_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2]-1, 0 ) preSIout = transf_pre_dicomReader.GetScalarComponentAsFloat( ijk_out[0], ijk_out[1]-1, ijk_out[2]-1, 0 )+epsilon lastSIout_pixVal.append(float(SIout/preSIout)) # calculate RSIoutf = mean( lastSIout_pixVal ) ### compute feature num_margin.append( RSIin-RSIout ) den_margin.append( RSIin-RSIoutf ) #print num_margin #print den_margin SIout_pixVal=[] lastSIout_pixVal=[] self.edge_sharp_mean = mean(array(num_margin).astype(float)) / mean(array(den_margin).astype(float)) self.edge_sharp_std = std(array(num_margin).astype(float)) / std(array(den_margin).astype(float)) print "\n edge_sharp_mean: " print self.edge_sharp_mean print "\n edge_sharp_std: " print self.edge_sharp_std ################################################## # orgamize into dataframe self.morphologyFeatures = DataFrame( data=array([[ mean(self.allmin_F_r_i), mean(self.allmax_F_r_i),mean(self.allmean_F_r_i), mean(self.allvar_F_r_i), mean(self.allskew_F_r_i), mean(self.allkurt_F_r_i), self.i_var_max, self.ii_var_min, self.iii_var_max, self.iii_var_max_k, self.ivVariance, self.circularity, self.irregularity, self.edge_sharp_mean, self.edge_sharp_std, self.max_RGH_mean, self.max_RGH_mean_k, self.max_RGH_var, self.max_RGH_var_k ]]), columns=['min_F_r_i', 'max_F_r_i', 'mean_F_r_i', 'var_F_r_i', 'skew_F_r_i', 'kurt_F_r_i', 'iMax_Variance_uptake', 'iiMin_change_Variance_uptake', 'iiiMax_Margin_Gradient', 'k_Max_Margin_Grad', 'ivVariance', 'circularity', 'irregularity', 'edge_sharp_mean', 'edge_sharp_std', 'max_RGH_mean', 'max_RGH_mean_k', 'max_RGH_var', 'max_RGH_var_k']) return self.morphologyFeatures
def addSegment(self, lesion3D, color, interact): '''Add segmentation to current display''' # Set the planes based on seg bounds self.lesion_bounds = lesion3D.GetBounds() print "\n Mesh DICOM bounds: " print "xmin, xmax= [%d, %d]" % (self.lesion_bounds[0], self.lesion_bounds[1]) print "yin, ymax= [%d, %d]" % (self.lesion_bounds[2], self.lesion_bounds[3]) print "zmin, zmax= [%d, %d]" % (self.lesion_bounds[4], self.lesion_bounds[5]) ### GEt semgnetation information self.no_pts_segm = lesion3D.GetNumberOfPoints() print "no pts %d" % self.no_pts_segm # get VOI volume VOI_massProperty = vtk.vtkMassProperties() VOI_massProperty.SetInput(lesion3D) VOI_massProperty.Update() # VTK is unitless. The units you get out are the units you put in. # If your input polydata has points defined in terms of millimetres, then # the volume will be in cubic millimetres. self.VOI_vol = VOI_massProperty.GetVolume() # mm3 self.VOI_surface = VOI_massProperty.GetSurfaceArea() # mm2 # just print the results print "\nVolume lesion = ", self.VOI_vol print "Surface lesion = ", self.VOI_surface # Calculate the effective diameter of the surface D=2(sqrt3(3V/(4pi))) diam_root = (3*self.VOI_vol)/(4*pi) self.VOI_efect_diameter = 2*pow(diam_root,1.0/3) print "VOI_efect_diameter = ", self.VOI_efect_diameter centerOfMassFilter = vtk.vtkCenterOfMass() centerOfMassFilter.SetInput( lesion3D ) centerOfMassFilter.SetUseScalarsAsWeights(False) centerOfMassFilter.Update() # centroid of lesion self.lesion_centroid = [0,0,0] self.lesion_centroid = centerOfMassFilter.GetCenter() print "lesion_centroid = ", self.lesion_centroid self.lesioncentroidijk() # Add ICPinit_mesh.vtk to the render self.mapper_mesh = vtk.vtkPolyDataMapper() self.mapper_mesh.SetInput( lesion3D ) self.mapper_mesh.ScalarVisibilityOff() self.actor_mesh = vtk.vtkActor() self.actor_mesh.SetMapper(self.mapper_mesh) self.actor_mesh.GetProperty().SetColor(color) #R,G,B self.actor_mesh.GetProperty().SetOpacity(0.3) self.actor_mesh.GetProperty().SetPointSize(5.0) self.actor_mesh.GetProperty().SetRepresentationToWireframe() self.xImagePlaneWidget.SetSliceIndex(0) self.yImagePlaneWidget.SetSliceIndex(0) self.zImagePlaneWidget.SetSliceIndex( 0 ) self.renderer1.AddActor(self.actor_mesh) # Initizalize self.renderer1.Modified() self.renWin1.Render() self.renderer1.Render() if(interact==True): self.iren1.Start() return
def execute(self, inputs, update = 0, last = 0): """ Execute the filter with given inputs and return the output """ if not lib.ProcessingFilter.ProcessingFilter.execute(self, inputs): return None self.progressObj.setProgress(0.0) self.updateProgress(None, "ProgressEvent") rightDataType = True labelImage = self.getInput(1) labelImage.Update() if "vtkImageData" in str(labelImage.__class__): rightDataType = (labelImage.GetScalarType() == 9) elif not "itkImageUL" in str(labelImage.__class__): rightDataType = False if not rightDataType: Logging.error("Incompatible data type", "Please convert the input to label data of type unsigned long. Segmented data can be labeled with 'Connected component labeling' or 'Object separation' in 'Segmentation -> Object Processing'.") origImage = self.getInput(2) origImage.Update() origRange = origImage.GetScalarRange() print "Input for label shape=",self.getInputDataUnit(1) print "Orig. dataunit = ",self.getInputDataUnit(2) diritk = dir(itk) if "LabelImageToStatisticsLabelMapFilter" in diritk and "LabelMap" in diritk and "StatisticsLabelObject" and "LabelGeometryImageFilter" in diritk: newITKStatistics = 1 else: newITKStatistics = 0 # Do necessary conversions of datatype origVTK = origImage if self.parameters["AvgInt"] or self.parameters["NonZero"] or newITKStatistics: origITK = self.convertVTKtoITK(origVTK) # Cannot have two convertVTKtoITK in same filter if self.parameters["AvgInt"] or self.parameters["Area"]: labelVTK = self.convertITKtoVTK(labelImage) if "itkImage" not in str(labelImage.__class__): extent = labelImage.GetWholeExtent() if extent[5] - extent[4] == 0: dim = 2 else: dim = 3 scalarType = labelImage.GetScalarType() if scalarType != 9: # Convert to unsigned long castVTK = vtk.vtkImageCast() castVTK.SetOutputScalarTypeToUnsignedLong() castVTK.SetInput(labelImage) labelImage = castVTK.GetOutput() labelImage.Update() vtkItk = eval("itk.VTKImageToImageFilter.IUL%d.New()"%dim) vtkItk.SetInput(labelImage) labelITK = vtkItk.GetOutput() labelITK.Update() else: labelITK = labelImage dim = labelITK.GetLargestPossibleRegion().GetSize().GetSizeDimension() # Initializations spacing = self.dataUnit.getSpacing() x, y, z = self.dataUnit.getVoxelSize() x *= 1000000 y *= 1000000 z *= 1000000 if z == 0: z = 1.0 vol = x * y * z voxelSizes = [x, y, z] values = [] centersofmass = [] umcentersofmass = [] avgints = [] avgintsstderrs = [] objIntSums = [] avgDists = [] avgDistsStdErrs = [] objAreasUm = [] objRoundness = [] objMinorLength = [] objMajorLength = [] objElongation = [] objAngleMinX = [] objAngleMinY = [] objAngleMinZ = [] objAngleMajX = [] objAngleMajY = [] objAngleMajZ = [] objSmoothness = [] ignoreLargest = 1 currFilter = self while currFilter: if currFilter.ignoreObjects > ignoreLargest: ignoreLargest = currFilter.ignoreObjects currFilter = currFilter.prevFilter startIntensity = ignoreLargest print "Ignoring",startIntensity,"first objects" if newITKStatistics: # Change spacing for correct results, or not #changeInfoLabel = itk.ChangeInformationImageFilter[labelITK].New() #changeInfoLabel.SetInput(labelITK) #changeInfoLabel.ChangeSpacingOn() #changeInfoOrig = itk.ChangeInformationImageFilter[origITK].New() #changeInfoOrig.SetInput(origITK) #changeInfoOrig.ChangeSpacingOn() if dim == 3: lm = itk.LabelMap._3.New() #changeInfoLabel.SetOutputSpacing(voxelSizes) #changeInfoOrig.SetOutputSpacing(voxelSizes) else: lm = itk.LabelMap._2.New() #changeInfoLabel.SetOutputSpacing(voxelSizes[:2]) #changeInfoOrig.SetOutputSpacing(voxelSizes[:2]) labelStatistics = itk.LabelImageToStatisticsLabelMapFilter[labelITK,origITK,lm].New() #labelStatistics.SetInput1(changeInfoLabel.GetOutput()) #labelStatistics.SetInput2(changeInfoOrig.GetOutput()) labelStatistics.SetInput1(labelITK) labelStatistics.SetInput2(origITK) if self.parameters["Area"]: labelStatistics.ComputePerimeterOn() labelStatistics.Update() labelMap = labelStatistics.GetOutput() numberOfLabels = labelMap.GetNumberOfLabelObjects() else: labelShape = itk.LabelShapeImageFilter[labelITK].New() labelShape.SetInput(labelITK) data = labelShape.GetOutput() data.Update() numberOfLabels = labelShape.GetNumberOfLabels() if self.parameters["AvgInt"]: avgintCalc = itk.LabelStatisticsImageFilter[origITK,labelITK].New() avgintCalc.SetInput(origITK) avgintCalc.SetLabelInput(labelITK) avgintCalc.Update() self.progressObj.setProgress(0.2) self.updateProgress(None, "ProgressEvent") # Area calculation pipeline if self.parameters["Area"]: voxelArea = x*y*2 + x*z*2 + y*z*2 largestSize = labelITK.GetLargestPossibleRegion().GetSize() # if 2D image, calculate area using volume if largestSize.GetSizeDimension() > 2 and largestSize.GetElement(2) > 1: areaSpacing = labelVTK.GetSpacing() objectThreshold = vtk.vtkImageThreshold() objectThreshold.SetInput(labelVTK) objectThreshold.SetOutputScalarTypeToUnsignedChar() objectThreshold.SetInValue(255) objectThreshold.SetOutValue(0) marchingCubes = vtk.vtkMarchingCubes() #marchingCubes.SetInput(labelVTK) marchingCubes.SetInput(objectThreshold.GetOutput()) massProperties = vtk.vtkMassProperties() massProperties.SetInput(marchingCubes.GetOutput()) areaDiv = (areaSpacing[0] / x)**2 if self.parameters["Smoothness"]: smoothDecimate = vtk.vtkDecimatePro() smoothProperties = vtk.vtkMassProperties() smoothDecimate.SetTargetReduction(0.9) smoothDecimate.PreserveTopologyOff() smoothDecimate.SetInput(marchingCubes.GetOutput()) smoothProperties.SetInput(smoothDecimate.GetOutput()) # Filter needed for axes calculations if self.parameters["Axes"] and newITKStatistics: labelGeometry = itk.LabelGeometryImageFilter[labelITK,labelITK].New() labelGeometry.SetCalculateOrientedBoundingBox(1) labelGeometry.SetInput(labelITK) labelGeometry.Update() # Get results and do some calculations for each object tott = 0 voxelSize = voxelSizes[0] * voxelSizes[1] * voxelSizes[2] for i in range(startIntensity, numberOfLabels+1): areaInUm = 0.0 avgInt = 0 avgIntStdErr = 0.0 roundness = 0.0 objIntSum = 0.0 minorLength = 0.0 majorLength = 0.0 elongation = 0.0 angleMinX = 0.0 angleMinY = 0.0 angleMinZ = 0.0 angleMajX = 0.0 angleMajY = 0.0 angleMajZ = 0.0 smoothness = 0.0 if newITKStatistics: try: labelObj = labelMap.GetLabelObject(i) except: continue volume = labelObj.GetSize() #com = labelObj.GetCenterOfGravity() com = labelObj.GetCentroid() c = [] c2 = [] for k in range(0,com.GetPointDimension()): v = com[k] v /= spacing[k] c.append(v) c2.append(v * voxelSizes[k]) if com.GetPointDimension() == 2: c.append(0) c2.append(0.0) if self.parameters["AvgInt"]: avgInt = labelObj.GetMean() avgIntStdErr = math.sqrt(labelObj.GetVariance()) / math.sqrt(volume) objIntSum = avgInt * volume #if self.parameters["Area"]: # areaInUm = labelObj.GetPerimeter() # roundness = labelObj.GetRoundness() # Get area of object, copied old way because roundness is not # working if self.parameters["Area"]: if largestSize.GetSizeDimension() > 2 and largestSize.GetElement(2) > 1: objectThreshold.ThresholdBetween(i,i) marchingCubes.SetValue(0,255) polydata = marchingCubes.GetOutput() polydata.Update() if polydata.GetNumberOfPolys() > 0: massProperties.Update() areaInUm = massProperties.GetSurfaceArea() / areaDiv else: areaInUm = voxelArea # Calculate roundness hypersphereR = ((3*volume*vol)/(4*math.pi))**(1/3.0) hypersphereArea = 3 * volume * vol / hypersphereR roundness = hypersphereArea / areaInUm # Calculate surface smoothness if self.parameters["Smoothness"]: # Smooth surface with vtkDecimatePro. polydata = smoothDecimate.GetOutput() polydata.Update() if polydata.GetNumberOfPolys() > 0: smoothProperties.Update() smoothArea = smoothProperties.GetSurfaceArea() / areaDiv smoothness = smoothArea / areaInUm else: areaInUm = volume * x * y if self.parameters["Axes"]: vert = labelGeometry.GetOrientedBoundingBoxVertices(i) vertices = [] for vNum in range(vert.size()): vertices.append(vert.pop()) boxVect = [] if dim == 3: vertNums = [1,2,4] else: vertNums = [1,2] for vertNum in vertNums: vertex1 = vertices[0] vertex2 = vertices[vertNum] boxVect.append([abs(vertex2[dimN]-vertex1[dimN]) * voxelSizes[dimN] for dimN in range(dim)]) boxVectLen = [] minAxNum = -1 majAxNum = -1 minorLength = -1 majorLength = -1 for num,vect in enumerate(boxVect): length = 0.0 for vectComp in vect: length += vectComp**2 length = math.sqrt(length) boxVectLen.append(length) if length > majorLength: majorLength = length majAxNum = num if length < minorLength or minorLength < 0: minorLength = length minAxNum = num elongation = majorLength / minorLength # Calculate angle between major, minor axes and x,y,z axes for dimN in range(dim): boxVect[minAxNum][dimN] /= minorLength boxVect[majAxNum][dimN] /= majorLength vecX = (1.0, 0.0, 0.0) vecY = (0.0, 1.0, 0.0) vecZ = (0.0, 0.0, 1.0) angleMinX = lib.Math.angle(boxVect[minAxNum], vecX) angleMinY = lib.Math.angle(boxVect[minAxNum], vecY) angleMinZ = lib.Math.angle(boxVect[minAxNum], vecZ) angleMajX = lib.Math.angle(boxVect[majAxNum], vecX) angleMajY = lib.Math.angle(boxVect[majAxNum], vecY) angleMajZ = lib.Math.angle(boxVect[majAxNum], vecZ) else: if not labelShape.HasLabel(i): continue else: volume = labelShape.GetVolume(i) centerOfMass = labelShape.GetCenterOfGravity(i) if self.parameters["AvgInt"]: avgInt = avgintCalc.GetMean(i) avgIntStdErr = math.sqrt(abs(avgintCalc.GetVariance(i))) / math.sqrt(volume) objIntSum = avgintCalc.GetSum(i) c = [] c2 = [] for k in range(0, dim): v = centerOfMass.GetElement(k) c.append(v) c2.append(v * voxelSizes[k]) if dim == 2: c.append(0) c2.append(0.0) # Get area of object if self.parameters["Area"]: if largestSize.GetSizeDimension() > 2 and largestSize.GetElement(2) > 1: objectThreshold.ThresholdBetween(i,i) marchingCubes.SetValue(0,255) polydata = marchingCubes.GetOutput() polydata.Update() if polydata.GetNumberOfPolys() > 0: massProperties.Update() areaInUm = massProperties.GetSurfaceArea() / areaDiv else: areaInUm = voxelArea # Calculate roundness hypersphereR = ((3*volume*vol)/(4*math.pi))**(1/3.0) hypersphereArea = 3 * volume * vol / hypersphereR roundness = hypersphereArea / areaInUm else: areaInUm = volume * x * y # Add object results to result arrays centersofmass.append(tuple(c)) umcentersofmass.append(tuple(c2)) values.append((volume, volume * vol)) avgints.append(avgInt) avgintsstderrs.append(avgIntStdErr) objIntSums.append(objIntSum) objAreasUm.append(areaInUm) objRoundness.append(roundness) objMinorLength.append(minorLength) objMajorLength.append(majorLength) objElongation.append(elongation) objAngleMinX.append(angleMinX) objAngleMinY.append(angleMinY) objAngleMinZ.append(angleMinZ) objAngleMajX.append(angleMajX) objAngleMajY.append(angleMajY) objAngleMajZ.append(angleMajZ) objSmoothness.append(smoothness) self.progressObj.setProgress(0.7) self.updateProgress(None, "ProgressEvent") # Do distance calculations t0 = time.time() for i, cm in enumerate(umcentersofmass): distList = [] if self.parameters["AvgDist"]: for j, cm2 in enumerate(umcentersofmass): if i == j: continue dx = cm[0] - cm2[0] dy = cm[1] - cm2[1] dz = cm[2] - cm2[2] dist = math.sqrt(dx*dx+dy*dy+dz*dz) distList.append(dist) avgDist, avgDistStd, avgDistStdErr = lib.Math.meanstdeverr(distList) avgDists.append(avgDist) avgDistsStdErrs.append(avgDistStdErr) print "Distance calculations took", time.time()-t0 self.progressObj.setProgress(0.8) self.updateProgress(None, "ProgressEvent") # Calculate average values and errors n = len(values) avgint, avgintstd, avgintstderr = lib.Math.meanstdeverr(avgints) intSum = sum(objIntSums, 0.0) ums = [x[1] for x in values] avgums, avgumsstd, avgumsstderr = lib.Math.meanstdeverr(ums) sumums = sum(ums, 0.0) pxs = [x[0] for x in values] avgpxs, avgpxsstd, avgpxsstderr = lib.Math.meanstdeverr(pxs) distMean, distStd, distStdErr = lib.Math.meanstdeverr(avgDists) avground, avgroundstd, avgroundstderr = lib.Math.meanstdeverr(objRoundness) avgAreaUm, avgAreaUmStd, avgAreaUmStdErr = lib.Math.meanstdeverr(objAreasUm) areaSumUm = sum(objAreasUm, 0.0) avgminlen, avgminlenstd, avgminlenstderr = lib.Math.meanstdeverr(objMinorLength) avgmajlen, avgmajlenstd, avgmajlenstderr = lib.Math.meanstdeverr(objMajorLength) avgelon, avgelonstd, avgelonstderr = lib.Math.meanstdeverr(objElongation) avgangminx, avgangminxstd, avgangminxstderr = lib.Math.meanstdeverr(objAngleMinX) avgangminy, avgangminystd, avgangminystderr = lib.Math.meanstdeverr(objAngleMinY) avgangminz, avgangminzstd, avgangminzstderr = lib.Math.meanstdeverr(objAngleMinZ) avgangmajx, avgangmajxstd, avgangmajxstderr = lib.Math.meanstdeverr(objAngleMajX) avgangmajy, avgangmajystd, avgangmajystderr = lib.Math.meanstdeverr(objAngleMajY) avgangmajz, avgangmajzstd, avgangmajzstderr = lib.Math.meanstdeverr(objAngleMajZ) avgsmooth, avgsmoothstd, avgsmoothstderr = lib.Math.meanstdeverr(objSmoothness) # Calculate average intensity outside objects avgIntOutsideObjs = 0.0 avgIntOutsideObjsStdErr = 0.0 avgIntOutsideObjsNonZero = 0.0 avgIntOutsideObjsNonZeroStdErr = 0.0 nonZeroVoxels = -1 if self.parameters["AvgInt"]: variances = 0.0 allVoxels = 0 for i in range(0,startIntensity): if newITKStatistics: try: labelObj = labelMap.GetLabelObject(i) voxelAmount = labelObj.GetSize() allVoxels += voxelAmount avgIntOutsideObjs += labelObj.GetMean() * voxelAmount variances += voxelAmount * abs(labelObj.GetVariance()) except: pass else: if labelShape.HasLabel(i): voxelAmount = labelShape.GetVolume(i) allVoxels += voxelAmount avgIntOutsideObjs += avgintCalc.GetMean(i) * voxelAmount if voxelAmount > 1: variances += voxelAmount * abs(avgintCalc.GetVariance(i)) if allVoxels > 0: avgIntOutsideObjs /= allVoxels avgIntOutsideObjsStdErr = math.sqrt(variances / allVoxels) / math.sqrt(allVoxels) labelAverage = vtkbxd.vtkImageLabelAverage() labelAverage.AddInput(origVTK) labelAverage.AddInput(labelVTK) labelAverage.SetBackgroundLevel(startIntensity) labelAverage.Update() avgIntOutsideObjsNonZero = labelAverage.GetAverageOutsideLabels() if labelAverage.GetVoxelsOutsideLabels() == 0: avgIntOutsideObjsNonZeroStdErr = 0.0 else: avgIntOutsideObjsNonZeroStdErr = labelAverage.GetOutsideLabelsStdDev() / math.sqrt(labelAverage.GetVoxelsOutsideLabels()) # Get also non zero voxels here that there is no need to recalculate nonZeroVoxels = labelAverage.GetNonZeroVoxels() self.progressObj.setProgress(0.9) self.updateProgress(None, "ProgressEvent") # Calculate average intensity inside objects avgIntInsideObjs = 0.0 avgIntInsideObjsStdErr = 0.0 if self.parameters["AvgInt"]: variances = 0.0 allVoxels = 0 for i in range(startIntensity, numberOfLabels+1): if newITKStatistics: try: labelObj = labelMap.GetLabelObject(i) voxelAmount = labelObj.GetSize() allVoxels += voxelAmount avgIntInsideObjs += labelObj.GetMean() * voxelAmount if voxelAmount > 1: variances += voxelAmount * abs(labelObj.GetVariance()) except: pass else: if labelShape.HasLabel(i): voxelAmount = labelShape.GetVolume(i) allVoxels += voxelAmount avgIntInsideObjs += avgintCalc.GetMean(i) * voxelAmount variances += voxelAmount * abs(avgintCalc.GetVariance(i)) if allVoxels > 0: avgIntInsideObjs /= allVoxels avgIntInsideObjsStdErr = math.sqrt(variances / allVoxels) / math.sqrt(allVoxels) # Calculate non-zero voxels if self.parameters["NonZero"] and nonZeroVoxels < 0: labelShape = itk.LabelShapeImageFilter[origITK].New() labelShape.SetInput(origITK) labelShape.Update() for i in range(1, int(origRange[1]) + 1): if labelShape.HasLabel(i): nonZeroVoxels += labelShape.GetVolume(i) # Set results self.values = values self.centersofmass = centersofmass self.umcentersofmass = umcentersofmass self.avgIntList = avgints self.avgIntStdErrList = avgintsstderrs self.intSums = objIntSums self.avgDistList = avgDists self.avgDistStdErrList = avgDistsStdErrs self.objAreasUm = objAreasUm self.objRoundness = objRoundness self.objMinorLength = objMinorLength self.objMajorLength = objMajorLength self.objElongation = objElongation self.objAngleMinX = objAngleMinX self.objAngleMinY = objAngleMinY self.objAngleMinZ = objAngleMinZ self.objAngleMajX = objAngleMajX self.objAngleMajY = objAngleMajY self.objAngleMajZ = objAngleMajZ self.intSum = intSum self.objSmoothness = objSmoothness #self.distMean = distMean #self.distStdErr = distStdErr #self.avgRoundness = avground #self.avgRoundnessStdErr = avgroundstderr #self.avgIntInsideObjs = avgIntInsideObjs #self.avgIntInsideObjsStdErr = avgIntInsideObjsStdErr #self.avgIntOutsideObjs = avgIntOutsideObjs #self.avgIntOutsideObjsStdErr = avgIntOutsideObjsStdErr #self.avgIntOutsideObjsNonZero = avgIntOutsideObjsNonZero #self.avgIntOutsideObjsNonZeroStdErr = avgIntOutsideObjsNonZeroStdErr self.setResultVariable("NumberOfObjects",len(values)) self.setResultVariable("ObjAvgVolInVoxels",avgpxs) self.setResultVariable("ObjAvgVolInUm",avgums) self.setResultVariable("ObjVolSumInUm",sumums) self.setResultVariable("ObjAvgAreaInUm",avgAreaUm) self.setResultVariable("ObjAreaSumInUm",areaSumUm) self.setResultVariable("ObjAvgIntensity",avgint) self.setResultVariable("AvgIntOutsideObjs", avgIntOutsideObjs) self.setResultVariable("AvgIntOutsideObjsNonZero", avgIntOutsideObjsNonZero) self.setResultVariable("AvgIntInsideObjs", avgIntInsideObjs) self.setResultVariable("NonZeroVoxels", nonZeroVoxels) self.setResultVariable("AverageDistance", distMean) self.setResultVariable("AvgDistanceStdErr", distStdErr) self.setResultVariable("ObjAvgVolInVoxelsStdErr",avgpxsstderr) self.setResultVariable("ObjAvgVolInUmStdErr",avgumsstderr) self.setResultVariable("ObjAvgAreaInUmStdErr",avgAreaUmStdErr) self.setResultVariable("ObjAvgIntensityStdErr",avgintstderr) self.setResultVariable("AvgIntOutsideObjsStdErr",avgIntOutsideObjsStdErr) self.setResultVariable("AvgIntOutsideObjsNonZeroStdErr",avgIntOutsideObjsNonZeroStdErr) self.setResultVariable("AvgIntInsideObjsStdErr",avgIntInsideObjsStdErr) self.setResultVariable("ObjIntensitySum", intSum) self.setResultVariable("ObjAvgRoundness",avground) self.setResultVariable("ObjAvgRoundnessStdErr",avgroundstderr) self.setResultVariable("ObjAvgMajorAxisLen",avgmajlen) self.setResultVariable("ObjAvgMajorAxisLenStdErr",avgmajlenstderr) self.setResultVariable("ObjAvgMinorAxisLen",avgminlen) self.setResultVariable("ObjAvgMinorAxisLenStdErr",avgminlenstderr) self.setResultVariable("ObjAvgElongation",avgelon) self.setResultVariable("ObjAvgElongationStdErr",avgelonstderr) self.setResultVariable("ObjAvgAngleXMajorAxis",avgangmajx) self.setResultVariable("ObjAvgAngleXMajorAxisStdErr",avgangmajxstderr) self.setResultVariable("ObjAvgAngleYMajorAxis",avgangmajy) self.setResultVariable("ObjAvgAngleYMajorAxisStdErr",avgangmajystderr) self.setResultVariable("ObjAvgAngleZMajorAxis",avgangmajz) self.setResultVariable("ObjAvgAngleZMajorAxisStdErr",avgangmajzstderr) self.setResultVariable("ObjAvgAngleXMinorAxis",avgangminx) self.setResultVariable("ObjAvgAngleXMinorAxisStdErr",avgangminxstderr) self.setResultVariable("ObjAvgAngleYMinorAxis",avgangminy) self.setResultVariable("ObjAvgAngleYMinorAxisStdErr",avgangminystderr) self.setResultVariable("ObjAvgAngleZMinorAxis",avgangminz) self.setResultVariable("ObjAvgAngleZMinorAxisStdErr",avgangminzstderr) self.setResultVariable("ObjAvgSmoothness",avgsmooth) self.setResultVariable("ObjAvgSmoothnessStdErr",avgsmoothstderr) self.stats = [n, avgums, avgumsstderr, avgpxs, avgpxsstderr, avgAreaUm, avgAreaUmStdErr, avgint, avgintstderr, avgIntOutsideObjs, avgIntOutsideObjsStdErr, distMean, distStdErr, sumums, areaSumUm, avgIntOutsideObjsNonZero, avgIntOutsideObjsNonZeroStdErr, avgIntInsideObjs, avgIntInsideObjsStdErr, nonZeroVoxels, avground, avgroundstderr, intSum, avgmajlen, avgmajlenstderr, avgminlen, avgminlenstderr, avgelon, avgelonstderr, avgangmajx, avgangmajxstderr, avgangmajy, avgangmajystderr, avgangmajz, avgangmajzstderr, avgangminx, avgangminxstderr, avgangminy, avgangminystderr, avgangminz, avgangminzstderr, avgsmooth, avgsmoothstderr] if self.reportGUI: self.reportGUI.DeleteAllItems() self.reportGUI.setVolumes(values) self.reportGUI.setCentersOfMass(centersofmass) self.reportGUI.setAverageIntensities(avgints, avgintsstderrs) self.reportGUI.setIntensitySums(objIntSums) self.reportGUI.setAverageDistances(avgDists, avgDistsStdErrs) self.reportGUI.setAreasUm(objAreasUm) self.reportGUI.setRoundness(objRoundness) self.reportGUI.setMajorAxisLengths(objMajorLength) self.reportGUI.setMinorAxisLengths(objMinorLength) self.reportGUI.setElongations(objElongation) self.reportGUI.setMajorAngles(objAngleMajX, objAngleMajY, objAngleMajZ) self.reportGUI.setMinorAngles(objAngleMinX, objAngleMinY, objAngleMinZ) self.reportGUI.setSmoothness(objSmoothness) self.totalGUI.setStats(self.stats) self.progressObj.setProgress(1.0) self.updateProgress(None, "ProgressEvent") return self.getInput(1)
def AddNewActor(self, pubsub_evt): """ Create surface actor, save into project and send it to viewer. """ slice_, mask, surface_parameters = pubsub_evt.data matrix = slice_.matrix filename_img = slice_.matrix_filename spacing = slice_.spacing algorithm = surface_parameters['method']['algorithm'] options = surface_parameters['method']['options'] surface_name = surface_parameters['options']['name'] quality = surface_parameters['options']['quality'] fill_holes = surface_parameters['options']['fill'] keep_largest = surface_parameters['options']['keep_largest'] mode = 'CONTOUR' # 'GRAYSCALE' min_value, max_value = mask.threshold_range colour = mask.colour try: overwrite = surface_parameters['options']['overwrite'] except KeyError: overwrite = False mask.matrix.flush() if quality in const.SURFACE_QUALITY.keys(): imagedata_resolution = const.SURFACE_QUALITY[quality][0] smooth_iterations = const.SURFACE_QUALITY[quality][1] smooth_relaxation_factor = const.SURFACE_QUALITY[quality][2] decimate_reduction = const.SURFACE_QUALITY[quality][3] #if imagedata_resolution: #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution) pipeline_size = 4 if decimate_reduction: pipeline_size += 1 if (smooth_iterations and smooth_relaxation_factor): pipeline_size += 1 if fill_holes: pipeline_size += 1 if keep_largest: pipeline_size += 1 ## Update progress value in GUI UpdateProgress = vu.ShowProgress(pipeline_size) UpdateProgress(0, _("Creating 3D surface...")) language = ses.Session().language if (prj.Project().original_orientation == const.CORONAL): flip_image = False else: flip_image = True n_processors = multiprocessing.cpu_count() pipe_in, pipe_out = multiprocessing.Pipe() o_piece = 1 piece_size = 2000 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) q_in = multiprocessing.Queue() q_out = multiprocessing.Queue() p = [] for i in xrange(n_processors): sp = surface_process.SurfaceProcess(pipe_in, filename_img, matrix.shape, matrix.dtype, mask.temp_file, mask.matrix.shape, mask.matrix.dtype, spacing, mode, min_value, max_value, decimate_reduction, smooth_relaxation_factor, smooth_iterations, language, flip_image, q_in, q_out, algorithm != 'Default', algorithm, imagedata_resolution) p.append(sp) sp.start() for i in xrange(n_pieces): init = i * piece_size end = init + piece_size + o_piece roi = slice(init, end) q_in.put(roi) print "new_piece", roi for i in p: q_in.put(None) none_count = 1 while 1: msg = pipe_out.recv() if(msg is None): none_count += 1 else: UpdateProgress(msg[0]/(n_pieces * pipeline_size), msg[1]) if none_count > n_pieces: break polydata_append = vtk.vtkAppendPolyData() polydata_append.ReleaseDataFlagOn() t = n_pieces while t: filename_polydata = q_out.get() reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(filename_polydata) reader.ReleaseDataFlagOn() reader.Update() reader.GetOutput().ReleaseDataFlagOn() polydata = reader.GetOutput() polydata.SetSource(None) polydata_append.AddInput(polydata) del reader del polydata t -= 1 polydata_append.Update() polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) polydata.SetSource(None) del polydata_append if algorithm == 'ca_smoothing': normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) normals_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInput(polydata) normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() clean.ReleaseDataFlagOn() clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) clean_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInput(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() polydata.SetSource(None) del clean try: polydata.BuildLinks() except TypeError: polydata.BuildLinks(0) polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], options['max distance'], options['min weight'], options['steps']) polydata.SetSource(None) polydata.DebugOn() else: #smoother = vtk.vtkWindowedSincPolyDataFilter() smoother = vtk.vtkSmoothPolyDataFilter() smoother_ref = weakref.ref(smoother) smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) smoother.SetInput(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetRelaxationFactor(smooth_relaxation_factor) smoother.SetFeatureAngle(80) #smoother.SetEdgeAngle(90.0) #smoother.SetPassBand(0.1) smoother.BoundarySmoothingOn() smoother.FeatureEdgeSmoothingOn() #smoother.NormalizeCoordinatesOn() #smoother.NonManifoldSmoothingOn() smoother.ReleaseDataFlagOn() smoother.GetOutput().ReleaseDataFlagOn() smoother.Update() del polydata polydata = smoother.GetOutput() #polydata.Register(None) polydata.SetSource(None) del smoother if decimate_reduction: print "Decimating", decimate_reduction decimation = vtk.vtkQuadricDecimation() decimation.ReleaseDataFlagOn() decimation.SetInput(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) polydata.SetSource(None) del decimation to_measure = polydata #to_measure.Register(None) to_measure.SetSource(None) if keep_largest: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInput(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) conn_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: filled_polydata = vtk.vtkFillHolesFilter() filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInput(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) polydata.SetSource(None) polydata.DebugOn() del filled_polydata normals = vtk.vtkPolyDataNormals() normals.ReleaseDataFlagOn() normals_ref = weakref.ref(normals) normals_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInput(polydata) normals.SetFeatureAngle(80) normals.AutoOrientNormalsOn() normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) polydata.SetSource(None) del normals # Improve performance stripper = vtk.vtkStripper() stripper.ReleaseDataFlagOn() stripper_ref = weakref.ref(stripper) stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) stripper.SetInput(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() stripper.GetOutput().ReleaseDataFlagOn() stripper.Update() del polydata polydata = stripper.GetOutput() #polydata.Register(None) polydata.SetSource(None) del stripper # Map polygonal data (vtkPolyData) to graphics primitives. mapper = vtk.vtkPolyDataMapper() mapper.SetInput(polydata) mapper.ScalarVisibilityOff() mapper.ReleaseDataFlagOn() mapper.ImmediateModeRenderingOn() # improve performance # Represent an object (geometry & properties) in the rendered scene actor = vtk.vtkActor() actor.SetMapper(mapper) del mapper #Create Surface instance if overwrite: surface = Surface(index = self.last_surface_index) else: surface = Surface(name=surface_name) surface.colour = colour surface.polydata = polydata del polydata # Set actor colour and transparency actor.GetProperty().SetColor(colour) actor.GetProperty().SetOpacity(1-surface.transparency) prop = actor.GetProperty() interpolation = int(ses.Session().surface_interpolation) prop.SetInterpolation(interpolation) proj = prj.Project() if overwrite: proj.ChangeSurface(surface) else: index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index session = ses.Session() session.ChangeProject() # The following lines have to be here, otherwise all volumes disappear measured_polydata = vtk.vtkMassProperties() measured_polydata.ReleaseDataFlagOn() measured_polydata.SetInput(to_measure) volume = float(measured_polydata.GetVolume()) surface.volume = volume self.last_surface_index = surface.index del measured_polydata del to_measure Publisher.sendMessage('Load surface actor into viewer', actor) # Send actor by pubsub to viewer's render if overwrite and self.actors_dict.keys(): old_actor = self.actors_dict[self.last_surface_index] Publisher.sendMessage('Remove surface actor from viewer', old_actor) # Save actor for future management tasks self.actors_dict[surface.index] = actor Publisher.sendMessage('Update surface info in GUI', (surface.index, surface.name, surface.colour, surface.volume, surface.transparency)) #When you finalize the progress. The bar is cleaned. UpdateProgress = vu.ShowProgress(1) UpdateProgress(0, _("Ready")) Publisher.sendMessage('Update status text in GUI', _("Ready")) Publisher.sendMessage('End busy cursor') del actor
def CreateSurfaceFromPolydata(self, polydata, overwrite=False, name=None, colour=None, transparency=None, volume=None): normals = vtk.vtkPolyDataNormals() normals.SetInput(polydata) normals.SetFeatureAngle(80) normals.AutoOrientNormalsOn() mapper = vtk.vtkPolyDataMapper() mapper.SetInput(normals.GetOutput()) mapper.ScalarVisibilityOff() mapper.ImmediateModeRenderingOn() # improve performance actor = vtk.vtkActor() actor.SetMapper(mapper) if overwrite: surface = Surface(index = self.last_surface_index) else: surface = Surface() if not colour: surface.colour = random.choice(const.SURFACE_COLOUR) else: surface.colour = colour surface.polydata = polydata if transparency: surface.transparency = transparency if name: surface.name = name # Append surface into Project.surface_dict proj = prj.Project() if overwrite: proj.ChangeSurface(surface) else: index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index # Set actor colour and transparency actor.GetProperty().SetColor(surface.colour) actor.GetProperty().SetOpacity(1-surface.transparency) self.actors_dict[surface.index] = actor session = ses.Session() session.ChangeProject() # The following lines have to be here, otherwise all volumes disappear if not volume: triangle_filter = vtk.vtkTriangleFilter() triangle_filter.SetInput(polydata) triangle_filter.Update() measured_polydata = vtk.vtkMassProperties() measured_polydata.SetInput(triangle_filter.GetOutput()) volume = measured_polydata.GetVolume() surface.volume = volume print ">>>>", surface.volume else: surface.volume = volume self.last_surface_index = surface.index Publisher.sendMessage('Load surface actor into viewer', actor) Publisher.sendMessage('Update surface info in GUI', (surface.index, surface.name, surface.colour, surface.volume, surface.transparency)) return surface.index
def volume(surface): """Compute volume of a closed triangulated surface mesh.""" properties = vtk.vtkMassProperties() properties.SetInput(surface) properties.Update() return properties.GetVolume()
def getMassProperties(triangles): mass = vtk.vtkMassProperties() mass.SetInputConnection(triangles.GetOutputPort()) return mass.GetVolume(), mass.GetSurfaceArea()
model_avg_cur_g = np.zeros(1) model_avg_cur_g_std = np.zeros(1) model_sum_cur_m = np.zeros(1) model_sum_cur_m_std = np.zeros(1) model_avg_cur_m = np.zeros(1) model_avg_cur_m_std = np.zeros(1) for bound in range(1, lith, 1): #contacts = vtk.vtkDiscreteMarchingCubes() #contacts.SetInputData(input) contacts = vtk.vtkMarchingCubes() contacts.SetInputData(input) true_bound = bound+0.5 contacts.SetValue(0,true_bound) contacts.Update() surface_area = vtk.vtkMassProperties() surface_area.SetInputConnection(contacts.GetOutputPort()) surface_area.Update() curvature = vtk.vtkCurvatures() curvature.SetInputConnection(contacts.GetOutputPort()) curvature.SetCurvatureTypeToMinimum() #curvature.SetCurvatureTypeToMaximum() #curvature.SetCurvatureTypeToGaussian() #curvature.SetCurvatureTypeToMean() curvature.Update() gauss = np.frombuffer(curvature.GetOutput().GetPointData().GetArray("Gauss_Curvature"), dtype = float) mean = np.frombuffer(curvature.GetOutput().GetPointData().GetArray("Mean_Curvature"), dtype = float) if (true_bound ==1.5): model_area[0] = surface_area.GetSurfaceArea() model_sum_cur_g[0] = np.sum(gauss)
def _makeSTL(self): local_dir = self._gray_dir surface_dir = self._vol_dir+'_surfaces'+self._path_dlm try: os.mkdir(surface_dir) except: pass files = fnmatch.filter(sorted(os.listdir(local_dir)),'*.tif') counter = re.search("[0-9]*\.tif", files[0]).group() prefix = self._path_dlm+string.replace(files[0],counter,'') counter = str(len(counter)-4) prefixImageName = local_dir + prefix ### Create the renderer, the render window, and the interactor. The renderer # The following reader is used to read a series of 2D slices (images) # that compose the volume. The slice dimensions are set, and the # pixel spacing. The data Endianness must also be specified. The reader v16=vtk.vtkTIFFReader() v16.SetFilePrefix(prefixImageName) v16.SetDataExtent(0,100,0,100,1,len(files)) v16.SetFilePattern("%s%0"+counter+"d.tif") v16.Update() im = v16.GetOutput() im.SetSpacing(self._pixel_dim[0],self._pixel_dim[1],self._pixel_dim[2]) v = vte.vtkImageExportToArray() v.SetInputData(im) n = np.float32(v.GetArray()) idx = np.argwhere(n) (ystart,xstart,zstart), (ystop,xstop,zstop) = idx.min(0),idx.max(0)+1 I,J,K = n.shape if ystart > 5: ystart -= 5 else: ystart = 0 if ystop < I-5: ystop += 5 else: ystop = I if xstart > 5: xstart -= 5 else: xstart = 0 if xstop < J-5: xstop += 5 else: xstop = J if zstart > 5: zstart -= 5 else: zstart = 0 if zstop < K-5: zstop += 5 else: zstop = K a = n[ystart:ystop,xstart:xstop,zstart:zstop] itk_img = sitk.GetImageFromArray(a) itk_img.SetSpacing([self._pixel_dim[0],self._pixel_dim[1],self._pixel_dim[2]]) print "\n" print "-------------------------------------------------------" print "-- Applying Patch Based Denoising - this can be slow --" print "-------------------------------------------------------" print "\n" pb = sitk.PatchBasedDenoisingImageFilter() pb.KernelBandwidthEstimationOn() pb.SetNoiseModel(3) #use a Poisson noise model since this is confocal pb.SetNoiseModelFidelityWeight(1) pb.SetNumberOfSamplePatches(20) pb.SetPatchRadius(4) pb.SetNumberOfIterations(10) fimg = pb.Execute(itk_img) b = sitk.GetArrayFromImage(fimg) intensity = b.max() #grad = sitk.GradientMagnitudeRecursiveGaussianImageFilter() #grad.SetSigma(0.05) gf = sitk.GradientMagnitudeImageFilter() gf.UseImageSpacingOn() grad = gf.Execute(fimg) edge = sitk.Cast(sitk.BoundedReciprocal( grad ),sitk.sitkFloat32) print "\n" print "-------------------------------------------------------" print "---- Thresholding to deterimine initial level sets ----" print "-------------------------------------------------------" print "\n" t = 0.5 seed = sitk.BinaryThreshold(fimg,t*intensity) #Opening (Erosion/Dilation) step to remove islands smaller than 2 voxels in radius) seed = sitk.BinaryMorphologicalOpening(seed,2) seed = sitk.BinaryFillhole(seed!=0) #Get connected regions r = sitk.ConnectedComponent(seed) labels = sitk.GetArrayFromImage(r) ids = sorted(np.unique(labels)) N = len(ids) if N > 2: i = np.copy(N) while i == N and (t-self._tratio)>-1e-7: t -= 0.01 seed = sitk.BinaryThreshold(fimg,t*intensity) #Opening (Erosion/Dilation) step to remove islands smaller than 2 voxels in radius) seed = sitk.BinaryMorphologicalOpening(seed,2) seed = sitk.BinaryFillhole(seed!=0) #Get connected regions r = sitk.ConnectedComponent(seed) labels = sitk.GetArrayFromImage(r) i = len(np.unique(labels)) if i > N: N = np.copy(i) t+=0.01 else: t = np.copy(self._tratio) seed = sitk.BinaryThreshold(fimg,t*intensity) #Opening (Erosion/Dilation) step to remove islands smaller than 2 voxels in radius) seed = sitk.BinaryMorphologicalOpening(seed,2) seed = sitk.BinaryFillhole(seed!=0) #Get connected regions r = sitk.ConnectedComponent(seed) labels = sitk.GetArrayFromImage(r) labels = np.unique(labels)[1:] ''' labels[labels==0] = -1 labels = sitk.GetImageFromArray(labels) labels.SetSpacing([self._pixel_dim[0],self._pixel_dim[1],self._pixel_dim[2]]) #myshow3d(labels,zslices=range(20)) #plt.show() ls = sitk.ScalarChanAndVeseDenseLevelSetImageFilter() ls.UseImageSpacingOn() ls.SetLambda2(1.5) #ls.SetCurvatureWeight(1.0) ls.SetAreaWeight(1.0) #ls.SetReinitializationSmoothingWeight(1.0) ls.SetNumberOfIterations(100) seg = ls.Execute(sitk.Cast(labels,sitk.sitkFloat32),sitk.Cast(fimg,sitk.sitkFloat32)) seg = sitk.Cast(seg,sitk.sitkUInt8) seg = sitk.BinaryMorphologicalOpening(seg,1) seg = sitk.BinaryFillhole(seg!=0) #Get connected regions #r = sitk.ConnectedComponent(seg) contours = sitk.BinaryContour(seg) myshow3d(sitk.LabelOverlay(sitk.Cast(fimg,sitk.sitkUInt8),contours),zslices=range(fimg.GetSize()[2])) plt.show() ''' segmentation = sitk.Image(r.GetSize(),sitk.sitkUInt8) segmentation.SetSpacing([self._pixel_dim[0],self._pixel_dim[1],self._pixel_dim[2]]) for l in labels: d = sitk.SignedMaurerDistanceMap(r==l,insideIsPositive=False,squaredDistance=True,useImageSpacing=True) #d = sitk.BinaryThreshold(d,-1000,0) #d = sitk.Cast(d,edge.GetPixelIDValue() )*-1+0.5 #d = sitk.Cast(d,edge.GetPixelIDValue() ) seg = sitk.GeodesicActiveContourLevelSetImageFilter() seg.SetPropagationScaling(1.0) seg.SetAdvectionScaling(1.0) seg.SetCurvatureScaling(0.5) seg.SetMaximumRMSError(0.01) levelset = seg.Execute(d,edge) levelset = sitk.BinaryThreshold(levelset,-1000,0) segmentation = sitk.Add(segmentation,levelset) print ("RMS Change for Cell %d: "% l,seg.GetRMSChange()) print ("Elapsed Iterations for Cell %d: "% l, seg.GetElapsedIterations()) ''' contours = sitk.BinaryContour(segmentation) myshow3d(sitk.LabelOverlay(sitk.Cast(fimg,sitk.sitkUInt8),contours),zslices=range(fimg.GetSize()[2])) plt.show() ''' n[ystart:ystop,xstart:xstop,zstart:zstop] = sitk.GetArrayFromImage(segmentation)*100 i = vti.vtkImageImportFromArray() i.SetDataSpacing([self._pixel_dim[0],self._pixel_dim[1],self._pixel_dim[2]]) i.SetDataExtent([0,100,0,100,1,len(files)]) i.SetArray(n) i.Update() thres=vtk.vtkImageThreshold() thres.SetInputData(i.GetOutput()) thres.ThresholdByLower(0) thres.ThresholdByUpper(101) iso=vtk.vtkImageMarchingCubes() iso.SetInputConnection(thres.GetOutputPort()) iso.SetValue(0,1) regions = vtk.vtkConnectivityFilter() regions.SetInputConnection(iso.GetOutputPort()) regions.SetExtractionModeToAllRegions() regions.ColorRegionsOn() regions.Update() N = regions.GetNumberOfExtractedRegions() for i in xrange(N): r = vtk.vtkConnectivityFilter() r.SetInputConnection(iso.GetOutputPort()) r.SetExtractionModeToSpecifiedRegions() r.AddSpecifiedRegion(i) g = vtk.vtkExtractUnstructuredGrid() g.SetInputConnection(r.GetOutputPort()) geo = vtk.vtkGeometryFilter() geo.SetInputConnection(g.GetOutputPort()) geo.Update() t = vtk.vtkTriangleFilter() t.SetInputConnection(geo.GetOutputPort()) t.Update() cleaner = vtk.vtkCleanPolyData() cleaner.SetInputConnection(t.GetOutputPort()) s = vtk.vtkSmoothPolyDataFilter() s.SetInputConnection(cleaner.GetOutputPort()) s.SetNumberOfIterations(50) dl = vtk.vtkDelaunay3D() dl.SetInputConnection(s.GetOutputPort()) dl.Update() self.cells.append(dl) for i in xrange(N): g = vtk.vtkGeometryFilter() g.SetInputConnection(self.cells[i].GetOutputPort()) t = vtk.vtkTriangleFilter() t.SetInputConnection(g.GetOutputPort()) #get the surface points of the cells and save to points attribute v = t.GetOutput() points = [] for j in xrange(v.GetNumberOfPoints()): p = [0,0,0] v.GetPoint(j,p) points.append(p) self.points.append(points) #get the volume of the cell vo = vtk.vtkMassProperties() vo.SetInputConnection(t.GetOutputPort()) self.volumes.append(vo.GetVolume()) stl = vtk.vtkSTLWriter() stl.SetInputConnection(t.GetOutputPort()) stl.SetFileName(surface_dir+'cell%02d.stl' % (i+self._counter)) stl.Write() if self._display: skinMapper = vtk.vtkDataSetMapper() skinMapper.SetInputConnection(regions.GetOutputPort()) skinMapper.SetScalarRange(regions.GetOutput().GetPointData().GetArray("RegionId").GetRange()) skinMapper.SetColorModeToMapScalars() #skinMapper.ScalarVisibilityOff() skinMapper.Update() skin = vtk.vtkActor() skin.SetMapper(skinMapper) #skin.GetProperty().SetColor(0,0,255) # An outline provides context around the data. # outlineData = vtk.vtkOutlineFilter() outlineData.SetInputConnection(v16.GetOutputPort()) mapOutline = vtk.vtkPolyDataMapper() mapOutline.SetInputConnection(outlineData.GetOutputPort()) outline = vtk.vtkActor() #outline.SetMapper(mapOutline) #outline.GetProperty().SetColor(0,0,0) colorbar = vtk.vtkScalarBarActor() colorbar.SetLookupTable(skinMapper.GetLookupTable()) colorbar.SetTitle("Cells") colorbar.SetNumberOfLabels(N) # Create the renderer, the render window, and the interactor. The renderer # draws into the render window, the interactor enables mouse- and # keyboard-based interaction with the data within the render window. # aRenderer = vtk.vtkRenderer() renWin = vtk.vtkRenderWindow() renWin.AddRenderer(aRenderer) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) # It is convenient to create an initial view of the data. The FocalPoint # and Position form a vector direction. Later on (ResetCamera() method) # this vector is used to position the camera to look at the data in # this direction. aCamera = vtk.vtkCamera() aCamera.SetViewUp (0, 0, -1) aCamera.SetPosition (0, 1, 0) aCamera.SetFocalPoint (0, 0, 0) aCamera.ComputeViewPlaneNormal() # Actors are added to the renderer. An initial camera view is created. # The Dolly() method moves the camera towards the FocalPoint, # thereby enlarging the image. aRenderer.AddActor(outline) aRenderer.AddActor(skin) aRenderer.AddActor(colorbar) aRenderer.SetActiveCamera(aCamera) aRenderer.ResetCamera () aCamera.Dolly(1.5) # Set a background color for the renderer and set the size of the # render window (expressed in pixels). aRenderer.SetBackground(0.0,0.0,0.0) renWin.SetSize(800, 600) # Note that when camera movement occurs (as it does in the Dolly() # method), the clipping planes often need adjusting. Clipping planes # consist of two planes: near and far along the view direction. The # near plane clips out objects in front of the plane the far plane # clips out objects behind the plane. This way only what is drawn # between the planes is actually rendered. aRenderer.ResetCameraClippingRange() im=vtk.vtkWindowToImageFilter() im.SetInput(renWin) iren.Initialize(); iren.Start(); #remove gray directory shutil.rmtree(local_dir)
def surfacearea(surface): """Compute surface area of input surface.""" properties = vtk.vtkMassProperties() properties.SetInput(surface) properties.Update() return properties.GetSurfaceArea()
def surfacearea(polydata): properties = vtk.vtkMassProperties() properties.SetInputData(polydata) properties.Update() return properties.GetSurfaceArea()