def get_node_data_n(self, file_name): """ Reads mesh information. Returns a numpy arrays of nodes & elements in 'abaqus' format. """ meshSource=vtk.vtkUnstructuredGridReader() meshSource.SetFileName(file_name) meshSource.Update() #get nodes & elements returned to numpy arrays nread=v2n(meshSource.GetOutput().GetPoints().GetData()) #allocate for extra node numbers to be input node_data=np.zeros((np.shape(nread)[0],np.shape(nread)[1]+1)) #reshape according to 'abaqus' standards (node num, coord1, 2 ...) node_data[:,0]=np.arange(np.shape(nread)[0])+1 node_data[:,1:]=nread # print([np.shape(np.arange(np.shape(n)[0])].transpose())) e=v2n(meshSource.GetOutput().GetCells().GetData()) #get cell types & reshape element array as needed. tcs=vtk.vtkCellTypes() meshSource.GetOutput().GetCellTypes(tcs) #reshape according to 'abaqus' standards (elem number, connectivity1 2 ...) if tcs.IsType(12)==1: self.mainCellType=12 #1st order quad element_data=np.resize(e,(int(len(e)/float(9)),9)) element_data[:,0]=np.arange(np.shape(element_data)[0])+1 elif tcs.IsType(24)==1: self.mainCellType=24 #2nd order tet element_data=np.resize(e,(int(len(e)/float(11)),11)) element_data[:,0]=np.arange(np.shape(element_data)[0])+1 # print(np.shape(node_data),np.shape(element_data)) #debug return node_data, element_data+1 #add one to the element number to match abaqus format
def write_h5(self): ''' method which writes to an hdf5 file if there is anything to write ''' if self.file is None: self.file = initialize_HDF5() #itinerary from this interactor is just the model. If there is an existing unstructured grid, then nothing needs to be written if hasattr(self,'active_vtu') and isinstance(self.active_vtu, str): w = HDF5vtkug_writer() reader = vtk.vtkXMLUnstructuredGridReader() reader.SetFileName(self.active_vtu) reader.Update() w.SetInputConnection(reader.GetOutputPort()) w.SetFileName(self.file) w.Update() self.display_info('Saved to data file.') with h5py.File(self.file, 'r+') as f: f.attrs['date_modified'] = datetime.today().strftime('%Y-%m-%d %H:%M:%S') #if there's an stl file if hasattr(self,'model_boundary'): # get points and verts from the boundary polydata, clearing anything that might already be there del f['model_boundary/points'] del f['model_boundary/vertices'] np_pts = v2n(self.model_boundary.GetPoints().GetData()) np_verts = v2n(self.model_boundary.GetPolys().GetData()) f.create_dataset('model_boundary/points', data=np_pts) f.create_dataset('model_boundary/vertices', data=np_verts) self.display_info('Saved to data file.') else: return
def get_1d_3d_map(self): """ Create a map from centerine to volume mesh through region growing """ # get points points_vol = v2n(self.geos['vol'].GetPoints().GetData()) points_1d = v2n(self.geos['cent'].GetPoints().GetData()) # get volume points closest to centerline cp_vol = ClosestPoints(self.geos['vol']) seed_points = np.unique(cp_vol.search(points_1d)) # map centerline points to selected volume points cp_1d = ClosestPoints(self.geos['cent']) seed_ids = np.array(cp_1d.search(points_vol[seed_points])) # call region growing algorithm ids, dist, rad = region_grow(self.geos['vol'], seed_points, seed_ids, self.logger, n_max=999) # check 1d to 3d map assert np.max(ids) <= self.geos['cent'].GetNumberOfPoints( ) - 1, '1d-3d map non-conforming' return ids, dist, rad
def get_vtk_data(reader, sstream): if issubclass(type(sstream), (str, os.PathLike)): reader.SetFileName(str(sstream)) else: reader.SetReadFromInputString(True) reader.SetInputString(sstream.getvalue()) reader.Update() output = reader.GetOutput() return (v2n(output.GetPointData().GetArray('point')), v2n(output.GetCellData().GetArray('cell')), v2n(output.GetFieldData().GetArray('field')))
def get_vtk_data(reader, sstream): if isinstance(sstream, str): reader.SetFileName(sstream) else: reader.SetReadFromInputString(True) reader.SetInputString(sstream.getvalue()) reader.Update() output = reader.GetOutput() return (v2n(output.GetPointData().GetArray('point')), v2n(output.GetCellData().GetArray('cell')), v2n(output.GetFieldData().GetArray('field')))
def get_connectivity(cent): """ Extract the connectivity (which branches are connected to which bifurcation) from a centerline """ # read arrays from centerline branch = v2n(cent.GetPointData().GetArray('BranchId')) bifurcation = v2n(cent.GetPointData().GetArray('BifurcationId')) bifurcation_list = np.unique(bifurcation).tolist() bifurcation_list.remove(-1) # get centerline connectivity: which branches are attached to which bifurcation? connectivity = {} for bf in bifurcation_list: connectivity[bf] = Bifurcation() # loop all cells for c in range(cent.GetNumberOfCells()): ele = cent.GetCell(c) point_ids = np.array([ ele.GetPointIds().GetId(i) for i in range(ele.GetPointIds().GetNumberOfIds()) ]) br_ids = branch[point_ids].tolist() # find cells that are at borders of bifurcations (two unique RegionIds) if np.unique(br_ids).shape[0] == 2: # should be one branch and one bifurcation assert -1 in br_ids, 'No bifurcation in cell' # local node ids of branch and bifurcation (0 or 1) i_bf_ele = br_ids.index(-1) i_br_ele = int(not i_bf_ele) # branch and bifurcation id bf = bifurcation[point_ids[i_bf_ele]] br = branch[point_ids[i_br_ele]] assert bf != -1, 'Multiple bifurcations in cell' assert br != -1, 'Multiple branches in cell' # branch node is upstream in cell? if i_br_ele == 0: connectivity[bf].add_inflow(br) else: connectivity[bf].add_outflow(br) for bf, bifurcation in connectivity.items(): assert len(bifurcation.outflow) >= 2, 'bifurcation ' + str( bf) + ' has less then two outlets' return connectivity
def vtkIntersectWithSegment(surf,lines,tol=0.0): """ Computes the intersection of surf with lines. Returns a list of the intersection points lists and of the element number of surf where the point lies. The position in the list is equal to the line number. If there is no intersection with the correspondent lists are empty Parameters: surf : can be Formex, Mesh or TriSurface lines : a mesh of segments """ from vtk import vtkOBBTree surf = convert2VPD(surf,clean=False) loc = vtkOBBTree() loc.SetDataSet(vm) loc.SetTolerance(tol) loc.BuildLocator() loc.Update() cellids = [[],]*lines.nelems() pts = [[],]*lines.nelems() for i in range(lines.nelems()): ptstmp = vtkPoints() cellidstmp = vtkIdList() loc.IntersectWithLine(lines.coords[lines.elems][i][1],lines.coords[lines.elems][i][0],ptstmp, cellidstmp) if cellidstmp.GetNumberOfIds(): cellids[i] = [cellidstmp.GetId(j) for j in range(cellidstmp.GetNumberOfIds())] pts[i] = Coords(v2n(ptstmp.GetData()).squeeze()) loc.FreeSearchStructure() del loc return pts,cellids
def collect_arrays(output): res = {} for i in range(output.GetNumberOfArrays()): name = output.GetArrayName(i) data = output.GetArray(i) res[name] = v2n(data) return res
def get_junction_length(self, br): """ Get the length of the part of a branch that is within the upstream junction Args: br: BranchId Returns: path length within junction """ # does not apply to inlet branch if br == 0: return 0.0 # get arrays from centerline cent = self.get_point_data(self.PointDataFields.CENT) branch = self.get_point_data(self.PointDataFields.BRANCH) bifurcation = self.get_point_data(self.PointDataFields.BIFURCATION) points = v2n(self.centerline.GetPoints().GetData()) # first point id of branch ip = np.where(branch == br)[0][0] # id of upstream junction jc = bifurcation[ip - 1] # pick a centerline that passes through branch (and upstream junction) cid = np.where(cent[ip])[0][0] # points of centerline within upstream junction point_ids = np.where(np.logical_and(bifurcation == jc, cent[:, cid]))[0] # calculate path length return np.sum( np.linalg.norm(np.diff(points[point_ids], axis=0), axis=1))
def line_query(output,q1,q2,numPoints,component): """ Interpolate the data from output over q1 to q2 (list of x,y,z) """ query_point = [q1,q2] line = vtk.vtkLineSource() line.SetResolution(numPoints) line.SetPoint1(q1) line.SetPoint2(q2) line.Update() probe = vtk.vtkProbeFilter() probe.SetInputConnection(line.GetOutputPort()) probe.SetSourceData(output) probe.Update() #initialize numpy array - number of points in probe potentially != numPoints line_pts = np.empty((probe.GetOutput().GetNumberOfPoints(),3)) #x,y,z #get all points: could also iterate over probe.GetOutput().GetNumberOfPoints() for i in range(numPoints): line_pts[i,:] = probe.GetOutput().GetPoint(i) #stack probe value on end column of line_pts line_pts = np.hstack((line_pts, \ np.array([v2n(probe.GetOutput().GetPointData().GetArray(component))]).T)) return line_pts
def evaluate(self, res_name): """ Evaluate integral. Distinguishes between scalar integration (e.g. pressure) and normal projection (velocity) Optionally divides integral by integrated area Args: field: pressure, velocity, ... res_name: name of array Returns: Scalar integral """ # type of result field = res_name.split('_')[0] if field == 'velocity': int_name = 'normal_' + res_name else: int_name = res_name # evaluate integral integral = v2n( self.integrator.GetOutput().GetPointData().GetArray(int_name))[0] # choose if integral should be divided by area if field == 'velocity': return integral else: return integral / self.area()
def probeOverLine(self, line): """ Interpolate the data from the VTK-file on the created line. """ data = self.mesh_reader_output probe = vtk.vtkProbeFilter() #probe.SetInputConnection(line.GetOutputPort()) probe.SetInputConnection(line.GetOutputPort()) probe.SetSourceData(data) probe.Update() # get the data from the VTK-object (probe) to an numpy array q = v2n(probe.GetOutput().GetPointData().GetArray(self.active_scalar_field)) numPoints = probe.GetOutput().GetNumberOfPoints() # get the number of points on the line # intialise the points on the line x = np.zeros(numPoints) y = np.zeros(numPoints) z = np.zeros(numPoints) points = np.zeros((numPoints , 3)) # get the coordinates of the points on the line for i in range(numPoints): x[i], y[i], z[i] = probe.GetOutput().GetPoint(i) points[i, 0] = x[i] points[i, 1] = y[i] points[i, 2] = z[i] return points, q
def MeshToVolume(Filename): reader = vtk.vtkPolyDataReader() pol2stenc = vtk.vtkPolyDataToImageStencil() imgstenc = vtk.vtkImageStencil() reader.SetFileName(os.path.join(subjects_dir,subject_dir,Filename)) reader.Update() ref_mesh = reader.GetOutput() ref_volume = vtk.vtkImageData() # define output volume dimension spacing = (0.5,0.5,0.5) ref_volume.SetSpacing(spacing) bounds = ref_mesh.GetBounds() dim = [math.ceil(bounds[ii*2+1] - bounds[ii*2] / spacing[ii]) for ii in range(0,3)] origin = [bounds[ii*2] + spacing[ii] / 2 for ii in range(0,3)] extent = (0,dim[0] - 1,0,dim[1] -1 ,0,dim[2]-1) ref_volume.SetOrigin(origin) ref_volume.SetDimensions(dim) ref_volume.SetExtent(extent) ref_volume.SetScalarTypeToUnsignedChar() ref_volume.AllocateScalars() # Fill the image with white voxels for i in range(0,ref_volume.GetNumberOfPoints()): ref_volume.GetPointData().GetScalars().SetTuple1(i,255) print ref_volume.GetNumberOfPoints() pol2stenc.SetInput(ref_mesh) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(ref_volume.GetExtent()) pol2stenc.Update() imgstenc.SetInput(ref_volume) imgstenc.SetStencil(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0) imgstenc.Update() tmp = imgstenc.GetOutput() writer = vtk.vtkImageWriter() writer.SetFileName('prova.nii.gz') writer.SetInput(ref_volume) writer.Update() out = v2n(tmp.GetPointData().GetScalars()) return np.reshape(out, (dim[0],dim[1],dim[2]))
def region_grow(geo, seed_points, seed_ids, logger, n_max=99): # initialize output arrays array_ids = -1 * np.ones(geo.GetNumberOfPoints(), dtype=int) array_rad = np.zeros(geo.GetNumberOfPoints()) array_dist = -1 * np.ones(geo.GetNumberOfPoints(), dtype=int) array_ids[seed_points] = seed_ids # initialize ids cids_all = set() pids_all = set(seed_points.tolist()) pids_new = set(seed_points.tolist()) # get points pts = v2n(geo.GetPoints().GetData()) # loop until region stops growing or reaches maximum number of iterations i = 0 while len(pids_new) > 0 and i < n_max: # update pids_old = pids_new # print progress print_str = 'Iteration ' + str(i) print_str += '\tNew points ' + str(len(pids_old)) + ' ' print_str += '\tTotal points ' + str(len(pids_all)) logger.info(print_str) # grow region one step pids_new = grow(geo, array_ids, pids_old, pids_all, cids_all) # convert to array pids_old_arr = list(pids_old) # create point locator with old wave front points = vtk.vtkPoints() points.Initialize() for i_old in pids_old: points.InsertNextPoint(geo.GetPoint(i_old)) dataset = vtk.vtkPolyData() dataset.SetPoints(points) locator = vtk.vtkPointLocator() locator.Initialize() locator.SetDataSet(dataset) locator.BuildLocator() # find closest point in new wave front for i_new in pids_new: i_old = pids_old_arr[locator.FindClosestPoint(geo.GetPoint(i_new))] array_ids[i_new] = array_ids[i_old] array_rad[i_new] = array_rad[i_old] + np.linalg.norm(pts[i_new] - pts[i_old]) array_dist[i_new] = i # count grow iterations i += 1 return array_ids, array_dist + 1, array_rad
def area(self): """ Evaluate integrated surface area Returns: Area """ return v2n( self.integrator.GetOutput().GetCellData().GetArray('Area'))[0]
def get_points_cells(inp): cells = [] for i in range(inp.GetOutput().GetNumberOfCells()): cell_points = [] for j in range(inp.GetOutput().GetCell(i).GetNumberOfPoints()): cell_points += [inp.GetOutput().GetCell(i).GetPointId(j)] cells += [cell_points] return v2n(inp.GetOutput().GetPoints().GetData()), np.array(cells)
def convertFromVPD(vpd): """Convert a vtkPolyData into pyFormex objects. Convert a vtkPolyData into pyFormex objects. Parameters: - `vpd`: a vtkPolyData Returns a tuple with points, polygons, lines, vertices numpy arrays. Returns None for the missing data. """ pts = polys = lines = verts = None # getting points coords if vpd.GetPoints().GetData().GetNumberOfTuples(): ntype = gnat(vpd.GetPoints().GetDataType()) pts = asarray(v2n(vpd.GetPoints().GetData()), dtype=ntype) print('Saved points coordinates array') # getting Polygons if vpd.GetPolys().GetData().GetNumberOfTuples(): ntype = gnat(vpd.GetPolys().GetData().GetDataType()) Nplex = vpd.GetPolys().GetMaxCellSize() polys = asarray(v2n(vpd.GetPolys().GetData()), dtype=ntype).reshape(-1, Nplex + 1)[:, 1:] print('Saved polys connectivity array') # getting Lines if vpd.GetLines().GetData().GetNumberOfTuples(): ntype = gnat(vpd.GetLines().GetData().GetDataType()) Nplex = vpd.GetLines().GetMaxCellSize() lines = asarray(v2n(vpd.GetLines().GetData()), dtype=ntype).reshape(-1, Nplex + 1)[:, 1:] print('Saved lines connectivity array') # getting Vertices if vpd.GetVerts().GetData().GetNumberOfTuples(): ntype = gnat(vpd.GetVerts().GetData().GetDataType()) Nplex = vpd.GetVerts().GetMaxCellSize() verts = asarray(v2n(vpd.GetVerts().GetData()), dtype=ntype).reshape(-1, Nplex + 1)[:, 1:] print('Saved verts connectivity array') return pts, polys, lines, verts
def convertFromVPD(vpd): """Convert a vtkPolyData into pyFormex objects. Convert a vtkPolyData into pyFormex objects. Parameters: - `vpd`: a vtkPolyData Returns a tuple with points, polygons, lines, vertices numpy arrays. Returns None for the missing data. """ pts=polys=lines=verts=None # getting points coords if vpd.GetPoints().GetData().GetNumberOfTuples(): ntype=gnat(vpd.GetPoints().GetDataType()) pts = asarray(v2n(vpd.GetPoints().GetData()),dtype=ntype) print('Saved points coordinates array') # getting Polygons if vpd.GetPolys().GetData().GetNumberOfTuples(): ntype=gnat(vpd.GetPolys().GetData().GetDataType()) Nplex = vpd.GetPolys().GetMaxCellSize() polys = asarray(v2n(vpd.GetPolys().GetData()),dtype=ntype).reshape(-1,Nplex+1)[:,1:] print('Saved polys connectivity array') # getting Lines if vpd.GetLines().GetData().GetNumberOfTuples(): ntype=gnat(vpd.GetLines().GetData().GetDataType()) Nplex = vpd.GetLines().GetMaxCellSize() lines = asarray(v2n(vpd.GetLines().GetData()),dtype=ntype).reshape(-1,Nplex+1)[:,1:] print('Saved lines connectivity array') # getting Vertices if vpd.GetVerts().GetData().GetNumberOfTuples(): ntype=gnat(vpd.GetVerts().GetData().GetDataType()) Nplex = vpd.GetVerts().GetMaxCellSize() verts = asarray(v2n(vpd.GetVerts().GetData()),dtype=ntype).reshape(-1,Nplex+1)[:,1:] print('Saved verts connectivity array') return pts, polys, lines, verts
def arePointsPenetrating(vtkData, vtkPoints): pointChecker = vtk.vtkSelectEnclosedPoints() pointChecker.SetInput(vtkPoints) pointChecker.SetSurface(vtkData) pointChecker.SetCheckSurface(1) pointChecker.SetTolerance(0) pointChecker.Update() insideArr = v2n( pointChecker.GetOutput().GetPointData().GetArray('SelectedPoints')) penetration = (insideArr.sum() > 0) return penetration
def get_node_data_n(self, file_name): """ Reads mesh information. Returns a numpy arrays of nodes & elements in 'abaqus' format. """ meshSource = vtk.vtkUnstructuredGridReader() meshSource.SetFileName(file_name) meshSource.Update() #get nodes & elements returned to numpy arrays nread = v2n(meshSource.GetOutput().GetPoints().GetData()) #allocate for extra node numbers to be input node_data = np.zeros((np.shape(nread)[0], np.shape(nread)[1] + 1)) #reshape according to 'abaqus' standards (node num, coord1, 2 ...) node_data[:, 0] = np.arange(np.shape(nread)[0]) + 1 node_data[:, 1:] = nread # print([np.shape(np.arange(np.shape(n)[0])].transpose())) e = v2n(meshSource.GetOutput().GetCells().GetData()) #get cell types & reshape element array as needed. tcs = vtk.vtkCellTypes() meshSource.GetOutput().GetCellTypes(tcs) #reshape according to 'abaqus' standards (elem number, connectivity1 2 ...) if tcs.IsType(12) == 1: mainCellType = 12 #1st order quad element_data = np.resize(e, (int(len(e) / float(9)), 9)) element_data[:, 0] = np.arange(np.shape(element_data)[0]) + 1 print('Quaaad') #debug self.ui.quadButton.setChecked(True) elif tcs.IsType(24) == 1: mainCellType = 24 #2nd order tet element_data = np.resize(e, (int(len(e) / float(11)), 11)) element_data[:, 0] = np.arange(np.shape(element_data)[0]) + 1 print('Tet tet tet') #debug self.ui.tetButton.setChecked(True) # print(np.shape(node_data),np.shape(element_data)) #debug return node_data, element_data + 1 #add one to the element number to match abaqus format
def vtkPointInsideObject(S,P,tol=0.): """vtk function to test which of the points P are inside surface S""" from vtk import vtkSelectEnclosedPoints vpp = convert2VPD(P) vps =convert2VPD(S,clean=False) enclosed_pts = vtkSelectEnclosedPoints() enclosed_pts.SetInput(vpp) enclosed_pts.SetTolerance(tol) enclosed_pts.SetSurface(vps) enclosed_pts.SetCheckSurface(1) enclosed_pts.Update() inside_arr = enclosed_pts.GetOutput().GetPointData().GetArray('SelectedPoints') enclosed_pts.ReleaseDataFlagOn() enclosed_pts.Complete() del enclosed_pts return asarray(v2n(inside_arr),'bool')
def vtkPointInsideObject(S, P, tol=0.): """vtk function to test which of the points P are inside surface S""" from vtk import vtkSelectEnclosedPoints vpp = convert2VPD(P) vps = convert2VPD(S, clean=False) enclosed_pts = vtkSelectEnclosedPoints() enclosed_pts.SetInput(vpp) enclosed_pts.SetTolerance(tol) enclosed_pts.SetSurface(vps) enclosed_pts.SetCheckSurface(1) enclosed_pts.Update() inside_arr = enclosed_pts.GetOutput().GetPointData().GetArray( 'SelectedPoints') enclosed_pts.ReleaseDataFlagOn() enclosed_pts.Complete() del enclosed_pts return asarray(v2n(inside_arr), 'bool')
def translate_amphyon_vtu(infile=None, outfile=None): ''' Function that modifies/converts Amphyon VTU file with single component data arrays from the three component 'Stress [MPa]' array that is written by Amphyon. Writes to an OpenRS formatted vtu file. Returns an unstructured grid object ''' if infile is None: infile,startdir=get_file('*.vtu') if infile is None: #dialog cancelled return if not(os.path.isfile(infile)): return reader = vtk.vtkXMLUnstructuredGridReader() reader.SetFileName(infile) reader.Update() output = reader.GetOutput() c= v2n(output.GetPointData().GetArray('Stress [MPa]')) #nx3 stresses Sxx = c[:,0].ravel() Syy = c[:,1].ravel() Szz = c[:,2].ravel() o = vtk.vtkUnstructuredGrid() o.CopyStructure(output) new = dsa.WrapDataObject(o) new.PointData.append(Sxx, 'S11') new.PointData.append(Syy, 'S22') new.PointData.append(Szz, 'S33') if outfile is None: outfile, _ = get_save_file('*.Amphyon_to_OpenRS.vtu') if outfile is None: #dialog cancelled return writer = vtk.vtkXMLUnstructuredGridWriter() writer.SetFileName(outfile) writer.SetInputData(new.VTKObject) writer.Write() return new #return new vtu object
def line_query(output,q1,q2,numPoints,component): """ Interpolate the data from output over q1 to q2 (list of x,y,z) """ query_point = [q1,q2] line = vtk.vtkLineSource() line.SetResolution(numPoints) line.SetPoint1(q1) line.SetPoint2(q2) line.Update() probe = vtk.vtkProbeFilter() probe.SetInputConnection(line.GetOutputPort()) probe.SetSourceData(output) probe.Update() # get the data from the VTK-object (probe) to an numpy array q = v2n(probe.GetOutput().GetPointData().GetArray(component)) return q
def vtkIntersectWithSegment(surf, lines, tol=0.0): """ Computes the intersection of surf with lines. Returns a list of the intersection points lists and of the element number of surf where the point lies. The position in the list is equal to the line number. If there is no intersection with the correspondent lists are empty Parameters: surf : can be Formex, Mesh or TriSurface lines : a mesh of segments """ from vtk import vtkOBBTree surf = convert2VPD(surf, clean=False) loc = vtkOBBTree() loc.SetDataSet(vm) loc.SetTolerance(tol) loc.BuildLocator() loc.Update() cellids = [ [], ] * lines.nelems() pts = [ [], ] * lines.nelems() for i in range(lines.nelems()): ptstmp = vtkPoints() cellidstmp = vtkIdList() loc.IntersectWithLine(lines.coords[lines.elems][i][1], lines.coords[lines.elems][i][0], ptstmp, cellidstmp) if cellidstmp.GetNumberOfIds(): cellids[i] = [ cellidstmp.GetId(j) for j in range(cellidstmp.GetNumberOfIds()) ] pts[i] = Coords(v2n(ptstmp.GetData()).squeeze()) loc.FreeSearchStructure() del loc return pts, cellids
def sample_branch(self, br, sample=None): """ Sample points and areas of a centerline group along a path Args: br: BranchId sample: optional, sample points in [0, 1] (default: sample at centerline points) Returns: path of centerline points in [0, 1],sampled points, sampled areas """ # get point arrays from centerline area = self.get_point_data(self.PointDataFields.AREA) distance = self.get_point_data(self.PointDataFields.PATH) branch = self.get_point_data(self.PointDataFields.BRANCH) points = v2n(self.centerline.GetPoints().GetData()) # get all branch points point_ids = np.where(branch == br) # distance between points dist = distance[point_ids] # branch length length = dist[-1] # map path to [0, 1] path_1d = dist / dist[-1] # get curvature curvature = curvature_radius(points) if sample is not None: # if sampling is given, interpolate along 1d centerline f = lambda x: interp1d(sample, path_1d, x[point_ids]) else: # return quantities along original path f = lambda x: x[point_ids] return length, path_1d, f(area), f(points), f(curvature)
def main(argv): import vtk from vtk.util.numpy_support import vtk_to_numpy as v2n if len(argv) < 4: print('usage: vtktonumpy.py <PVD input file> <n-innermost ... n-outermost> <NPY output file>', file=sys.stderr) sys.exit(1) pvd = argv[1] n_cells = [int(x) for x in argv[2:-1]] n_dims = len(n_cells) npy = argv[-1] if n_dims > 3: print('warning: not sure if this will work with >3 dimensions', file=sys.stderr) timeslots = [] with io.open(pvd, 'rt') as f: for line in f: if '<DataSet' not in line: continue t = None filename = None for bit in line.strip().split(): if bit.startswith('timestep="'): t = float(bit[10:-1]) elif bit.startswith('file="'): filename = bit[6:-1] assert t is not None assert filename is not None timeslots.append((t, filename)) first = True tot_cells = np.prod(n_cells) cell_shape = tuple(n_cells[::-1]) times = np.array([t[0] for t in timeslots]) datacube = np.empty((times.size,) + cell_shape) coord_vals = [None] * n_dims for i, (t, filename) in enumerate(timeslots): r = vtk.vtkXMLUnstructuredGridReader() r.SetFileName(filename) r.Update() o = r.GetOutput() if first: coords = v2n(o.GetPoints().GetData()).T if coords.shape[1] != tot_cells: print('error: expected %d cells total; found %d' % (tot_cells, coords.shape[1]), file=sys.stderr) sys.exit(1) assert coords.shape[0] >= n_dims coords = coords.reshape((-1,) + cell_shape) for j in range(n_dims): vals_slice = [0] * (n_dims + 1) vals_slice[0] = j vals_slice[n_dims - j] = slice(None) coord_vals[j] = coords[tuple(vals_slice)] orthog_slice = [slice(None)] * (n_dims + 1) orthog_slice[0] = j orthog_slice[n_dims - j] = 0 orthog_samp = coords[tuple(orthog_slice)] assert orthog_samp.min() == orthog_samp.max(), 'did you order the axes correctly?' first = False vals = v2n(o.GetPointData().GetArray(0)).reshape(cell_shape) datacube[i] = vals with io.open(npy, 'wb') as f: np.save(f, datacube) np.save(f, times) for cv in coord_vals: np.save(f, cv)
def MeshToVolume(Filename): reader = vtk.vtkPolyDataReader() pol2stenc = vtk.vtkPolyDataToImageStencil() imgstenc = vtk.vtkImageStencil() reader.SetFileName(os.path.join(subjects_dir, subject_dir, Filename)) reader.Update() ref_mesh = reader.GetOutput() ref_volume = vtk.vtkImageData() # define output volume dimension spacing = (0.5, 0.5, 0.5) ref_volume.SetSpacing(spacing) bounds = ref_mesh.GetBounds() dim = [ math.ceil(bounds[ii * 2 + 1] - bounds[ii * 2] / spacing[ii]) for ii in range(0, 3) ] origin = [bounds[ii * 2] + spacing[ii] / 2 for ii in range(0, 3)] extent = (0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1) ref_volume.SetOrigin(origin) ref_volume.SetDimensions(dim) ref_volume.SetExtent(extent) ref_volume.SetScalarTypeToUnsignedChar() ref_volume.AllocateScalars() # Fill the image with white voxels for i in range(0, ref_volume.GetNumberOfPoints()): ref_volume.GetPointData().GetScalars().SetTuple1(i, 255) print ref_volume.GetNumberOfPoints() pol2stenc.SetInput(ref_mesh) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(ref_volume.GetExtent()) pol2stenc.Update() imgstenc.SetInput(ref_volume) imgstenc.SetStencil(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0) imgstenc.Update() tmp = imgstenc.GetOutput() writer = vtk.vtkImageWriter() writer.SetFileName('prova.nii.gz') writer.SetInput(ref_volume) writer.Update() out = v2n(tmp.GetPointData().GetScalars()) return np.reshape(out, (dim[0], dim[1], dim[2]))
def get_point_data(self, field): """ Get the data for the given cell field names. """ point_data = self.centerline.GetPointData().GetArray(field) return v2n(point_data)
def get_cell_data(self, field): """ Get the data for the given cell field names. """ cell_data = self.centerline.GetCellData().GetArray(field) return v2n(cell_data)
def VTKScalarData2Numpy(vtkPolyData): nodes = v2n(vtkPolyData.GetPoints().GetData()) scalars = v2n(vtkPolyData.GetPointData().GetScalars()) return nodes, scalars
def get_polydata_centroid(poly_data): """ Calculate the centroid of polydata """ return np.mean(v2n(poly_data.GetPoints().GetData()), axis=0).tolist()
def project_1d_to_centerline(self): """ Project 1D results onto the centerline """ # assemble output dict rec_dd = lambda: defaultdict(rec_dd) arrays = rec_dd() # extract point arrays from geometries arrays_cent = collect_arrays(self.geos['cent'].GetPointData()) arrays_1d = collect_arrays(self.geos['1d'].GetPointData()) # add centerline arrays for name, data in arrays_cent.items(): arrays[name] = data # centerline points points = v2n(self.geos['cent'].GetPoints().GetData()) # loop all result fields for f in self.params.data_names: array_f = np.zeros( (arrays_cent['Path'].shape[0], len(self.params.times))) n_outlet = np.zeros(arrays_cent['Path'].shape[0]) # loop all branches for br in self.results_1d[f].keys(): # results of this branch res_br = self.results_1d[f][br] # get centerline path path_cent = arrays_cent['Path'][arrays_cent['BranchId'] == br] # get 1d path path_1d_geo = arrays_1d['Path'][arrays_1d['BranchId'] == br] # map results to branches path_1d_res, f_res = res_1d_to_path(path_1d_geo, res_br) # map 1d results to centerline using paths f_cent = interp1d(path_1d_res, f_res.T, fill_value='extrapolate')(path_cent).T # store results of this path array_f[arrays_cent['BranchId'] == br] = f_cent # add upstream part of branch within junction if br == 0: continue # first point of branch ip = np.where(arrays_cent['BranchId'] == br)[0][0] # centerline that passes through branch (first occurence) cid = np.where(arrays_cent['CenterlineId'][ip])[0][0] # id of upstream junction jc = arrays_cent['BifurcationId'][ip - 1] # centerline within junction jc_cent = np.where( np.logical_and(arrays_cent['BifurcationId'] == jc, arrays_cent['CenterlineId'][:, cid]))[0] # length of centerline within junction jc_path = np.append( 0, np.cumsum( np.linalg.norm(np.diff(points[jc_cent], axis=0), axis=1))) jc_path /= jc_path[-1] # results at upstream branch res_br_u = self.results_1d[f][arrays_cent['BranchId'][ jc_cent[0] - 1]] # results at beginning and end of centerline within junction f0 = res_br_u[sorted(res_br_u.keys())[-1]][-1] f1 = res_br[0][0] # map 1d results to centerline using paths array_f[jc_cent] += interp1d( [0, 1], np.vstack( (f0, f1)).T, fill_value='extrapolate')(jc_path).T # count number of outlets of this junction n_outlet[jc_cent] += 1 # normalize by number of outlets array_f[n_outlet > 0] = (array_f[n_outlet > 0].T / n_outlet[n_outlet > 0]).T # assemble time steps for i, t in enumerate(self.params.times): arrays[f + '_' + str(t)] = array_f[:, i] for f, a in arrays.items(): out_array = n2v(a) out_array.SetName(f) self.geos['cent'].GetPointData().AddArray(out_array) f_out = os.path.join(self.params.output_directory, self.params.output_file_name + '.vtp') write_geo(f_out, self.geos['cent'])