def __init__(self, path): self.path = path try: with open(self.path, 'r') as f: lines = f.readlines() except: print('Cannot read file!') start = [idx + 1 for idx, i in enumerate(lines) if i[0] == '#'] end = [idx - 1 for idx, i in enumerate(lines) if i[0] == '#'] end = end[1:] for idx, i in enumerate(lines[end[-1]:]): if i[0] == '[': end.append(end[-1] + idx) break pathes = [] for s, e in zip(start, end): a = np.array([[float(j) for j in i.split(' ') if j != ''] for i in lines[s:e]]) pathes.append(a[:, (2, 3, 4)]) g = Graph() for i in pathes: n = g.number_of_nodes() nodes = range(n, n + len(i)) g.add_nodes_from(nodes) for idx, k in enumerate(nodes): g.node[k]['pos'] = np.array(i[idx]) e1 = nodes[0:-1] e2 = nodes[1:] e = [[k1, k2] for k1, k2 in zip(e1, e2)] g.add_edges_from(e) self.graph = g
def __init__(self, filepath, sampling=1): from VascGraph.GeomGraph import Graph try: import h5py except: print('To run this function, \'h5py\' sould be installed.') return # ---- read ----# f=h5py.File(filepath, 'r') refs=[i[0] for i in f.get('GeodesicMSTs/CGPathContinuous')] pathes=[np.array(f[i]).T for i in refs] data=f.get('GeodesicMSTsMatrix/M/data') ir=np.array(f.get('GeodesicMSTsMatrix/M/ir')) jc=np.array(f.get('GeodesicMSTsMatrix/M/jc')) # ----- sampling of pathes nodes ----# ind=[len(i)/sampling for i in pathes] ind=[np.array(range(i))*sampling for i in ind] pathes=[i[indx] for i, indx in zip(pathes, ind)] # ----- build graph from pathes -----# path_ext=[] g=Graph() for path in pathes: n=g.number_of_nodes() nodes=np.array(range(len(path)))+n e1=nodes[1:] e2=nodes[:-1] e=np.array([e1,e2]).T path_ext.append([nodes[0], nodes[-1]]) g.add_nodes_from(nodes) g.add_edges_from(e) for node, pos in zip(nodes, path): g.node[node]['pos']=np.array([pos[1], pos[0], pos[2]]) # ------- connection between pathes ----# path_ext=np.array(path_ext) a = sparse.csc_matrix((data, ir, jc)) ind1, ind2 = np.where(a.todense()>0) e=[] for i,j in zip(ind1,ind2): ee=[[path_ext[i][0], path_ext[j][1]], [path_ext[i][1], path_ext[j][0]], [path_ext[i][0], path_ext[j][0]], [path_ext[i][1], path_ext[j][1]]] poss=np.array([[g.node[k[0]]['pos'], g.node[k[1]]['pos']] for k in ee]) poss= poss[:,0,:]-poss[:,1,:] norm=np.linalg.norm(poss, axis=1) indx=np.where(norm==norm.min())[0][0] e.append(ee[indx]) g.add_edges_from(e) self.graph=g
def UpdateWithStitching(self, size, niter1=10, niter2=5, is_parallel=False, n_parallel=5, ret=False): ''' this funtion allow to generate graphs as follows: 1) image patching --> 2) patch-based contraction (fixing boundary nodes) --> 3) graph stitching --> 4) boundary contraction --> 5) global contraction --> refinement it is helpful when graphing large inputs. Inputs: size: dimention of a 3D patch --> [size, size, size] niter1: number of contraction iterations on patches niter2: number of contraction iterations on boundary nodes is_parallel: if True, patch-based contraction will run in parallel using 'ray' n_parallel: number of parallel processes (note: for limited RAM memory, 'n_parallel' should be smaller) ret: if True, this function will return the output graph ''' try: from sklearn import neighbors except: print(' \'scikit-learn\' must be instaled to run this funtion!') if is_parallel: try: import ray except: print( ' \'ray\' must be installed to run patch-based contraction in parallel!' ) GraphParallel = activate_parallel() # obtain distance map #self.label=image.morphology.distance_transform_edt(self.label) self.label = DistMap3D(self.label) # patching print('--Extract patches ...') patches, patchesid = Decompose(self.label, size=size) # extract patches patches_shape = [patches.shape[0], patches.shape[1], patches.shape[2]] print('--Obtain semi-contracted graphs from patches ...') # run contraction avoiding boundary nodes for each patch graphs = [] inds = np.arange(0, len(patchesid), n_parallel) patchesid_ = [patchesid[ind:ind + n_parallel] for ind in inds] for inds in patchesid_: if is_parallel: # in parallel ray.init() subpatches = [ray.put(patches[ind]) for ind in inds] subgraphs = [ GraphParallel.remote( patch, niter=niter1, Sampling=self.sampling, DistParam=self.dist_param, MedParam=self.med_param, SpeedParam=self.speed_param, DegreeThreshold=self.degree_threshold, ClusteringResolution=self.clustering_resolution) for patch in subpatches ] subgraphs = [ray.get(g) for g in subgraphs] ray.shutdown() graphs.append(subgraphs) else: # in serial subpatches = [patches[ind] for ind in inds] subgraphs = [ GraphSerial( patch, niter=niter1, Sampling=self.sampling, DistParam=self.dist_param, MedParam=self.med_param, SpeedParam=self.speed_param, DegreeThreshold=self.degree_threshold, ClusteringResolution=self.clustering_resolution) for patch in subpatches ] subgraphs = [g for g in subgraphs] graphs.append(subgraphs) graphs = [k1 for k in graphs for k1 in k] # uravel del patches # adjust the position of graph nodes coming from each patch area = np.sum([k.Area for k in graphs if k is not None]) pluspos = (size) * np.array(patchesid) for plus, g in zip(pluspos, graphs): if g is not None: AddPos(g, plus) print('--Combine semi-contracted graphs ...') fullgraph = EmptyGraph() nnodes = 0 for idx, g in enumerate(graphs): if g is not None: print(' graph id ' + str(idx) + ' added') nnodes += fullgraph.number_of_nodes() new_nodes = nnodes + np.array(range(g.number_of_nodes())) mapping = dict(zip(g.GetNodes(), new_nodes)) g = nx.relabel_nodes(g, mapping) fullgraph.add_nodes_from(g.GetNodes()) fullgraph.add_edges_from(g.GetEdges()) for k in new_nodes: fullgraph.node[k]['pos'] = g.node[k]['pos'] fullgraph.node[k]['r'] = g.node[k]['r'] fullgraph.node[k]['ext'] = g.node[k]['ext'] else: print(' graph id ' + str(idx) + ' is None') fullgraph = fixG(fullgraph) fullgraph.Area = area del graphs print('--Stitch semi-contracted graphs ...') nodes = np.array( [k for k in fullgraph.GetNodes() if fullgraph.node[k]['ext'] == 1]) nodesid = dict(zip(range(len(nodes)), nodes)) pos = np.array([fullgraph.node[k]['pos'] for k in nodes]) pos_tree = neighbors.KDTree(pos) a = pos_tree.query_radius(pos, r=1.0) new_edges = [[(nodesid[k[0]], nodesid[k1]) for k1 in k[1:]] for k in a] new_edges = [k1 for k in new_edges for k1 in k] fullgraph.add_edges_from(new_edges) del a del nodes del pos del new_edges del pos_tree print('--Contract ext nodes ...') ContractExt(fullgraph, niter=niter2, DistParam=self.dist_param, MedParam=self.med_param, SpeedParam=self.speed_param, DegreeThreshold=self.degree_threshold, ClusteringResolution=self.clustering_resolution) print('--Generate final skeleton ...') contract_final = ContractGraph(Graph=fullgraph) contract_final.Update(DistParam=self.dist_param, MedParam=self.med_param, SpeedParam=self.speed_param, DegreeThreshold=self.degree_threshold, StopParam=self.stop_param, NFreeIteration=self.n_free_iteration) gc = contract_final.GetOutput() print('--Refine final skeleton ...') refine = RefineGraph(Graph=gc) refine.Update() gr = refine.GetOutput() gr = fixG(gr) # ----- return ----# if ret: return gr else: self.Graph = gr