def read_amira_spatialGraph(filename=None, resolution=1.0, lUnit='um', **kwargs): """Reads an AMIRA spatial graph file (AmiraMesh 3D ASCII 2.0 format) and constructs the corresponding vascular graph from it. INPUT: filename: AMIRA spatial graph file (including path). If not provided, a graphical file-selection dialog will display. resolution: The resolution of the srXTM scan, i.e. voxel size (isotropic resolution is assumend). The default is 1.0. lUnit: The unit of length properties in the spatialGraph (i.e. radii, and position vectors). The default is microns. **kwargs: defaultUnits: The defaultUnits of the VascularGraph created (see __init__ of the VascularGraph class for details). OUTPUT: G: Vascular graph in iGraph format. """ #if filename is None: # filename = guiTools.uigetfile('Select Amira spatialGraph (.am) file') f = open(filename,'r') def advanceToToken(token,searchdepth=2): done = False while not done: l = f.readline() if l == '': # eof break if l[0:searchdepth] == token: done = True log.debug('Found ' + token) return l # Get file statistics l = advanceToToken('define VERTEX',13) n_vertices = int(l.split()[-1]) l = advanceToToken('define EDGE',11) n_edges = int(l.split()[-1]) l = advanceToToken('define POINT',12) n_points = int(l.split()[-1]) log.info("Vertices: " + str(n_vertices)) log.info("Edges: " + str(n_edges)) log.info("Points: " + str(n_points)) # Create VascularGraph and compute scaling factor G = VascularGraph(n_vertices, **kwargs) sf = units.scaling_factor_du(lUnit, G['defaultUnits']) # Add vertices log.info("reading and adding vertices") advanceToToken('@1') edgeConnectivity = [] numEdgePoints = [] r = [[] for i in xrange(n_vertices)] for i in xrange(n_vertices): l = f.readline() l = l.split() r[i] = sp.array([float(l[0]),float(l[1]),float(l[2])]) * resolution * sf G.vs['r'] = r # Read connectivity information log.info("reading connectivity information") advanceToToken('@2') for i in xrange(n_edges): l = f.readline() l = l.split() edgeConnectivity.append((int(l[0]),int(l[1]))) # Read number of edge points log.info("reading number of edge points") advanceToToken('@3') for i in xrange(n_edges): l = f.readline() numEdgePoints.append(int(l)) # Read edge point coordinates # Compute length log.info("reading point coordinates") advanceToToken('@4') l_edge = [] edgepoints = [] for edge in xrange(n_edges): tmppoints = sp.zeros([numEdgePoints[edge],3]) for point in xrange(numEdgePoints[edge]): l = f.readline() tmppoints[point] = map(float, l.split()) l_edge.append([ np.linalg.norm(tmppoints[i]-tmppoints[i+1]) for i in xrange(len(tmppoints)-1) ]) l_edge[edge].insert(0, 0.0) l_edge[edge].extend([0.0]) l_edge[edge] = [(l_edge[edge][i-1] + l_edge[edge][i]) / 2.0 for i in xrange(1,len(l_edge[edge]))] # iGraph, unlike Amira orders edge vertices by index. Make sure that # this is reflected in the points that make up the edge: if edgeConnectivity[edge][0] > edgeConnectivity[edge][1]: tmppoints = tmppoints[::-1,:] edgepoints.append(tmppoints) if sp.mod(edge+1,sp.floor(n_edges/10)) == 0: log.info(str(10*(edge+1)/sp.floor(n_edges/10)) + "%") # Read edge radii log.info("reading radii") advanceToToken('@5') d_edge = [] for edge in xrange(n_edges): tmpdiameters = [] for point in xrange(numEdgePoints[edge]): l = f.readline() tmpdiameters.append(float(l)*2.0) # conversion radius to diameter d_edge.append(tmpdiameters) f.close() # Add edges log.info("adding edges") G.add_edges(edgeConnectivity) d_edge = [sp.array(d_edge[i],dtype=float) * resolution * sf for i in xrange(n_edges)] l_edge = [sp.array(l_edge[i],dtype=float) * resolution * sf for i in xrange(n_edges)] G.es['diameters'] = d_edge G.es['points'] = [p * resolution * sf for p in edgepoints] # Compute average diameter, weighted by length: # - volume = pi * d**2 /4 * length # - morphologically representative because of length-weighting # - individual diameters scale with identical factors as average diameter G.es['diameter'] = [np.sqrt(np.average(d_edge[i]**2, weights=l_edge[i])) for i in xrange(n_edges)] G.es['lengths'] = l_edge G.es['length'] = [sum(l) for l in l_edge] return G
def read_amira_spatialGraph(filename=None, resolution=1.0, lUnit='um', **kwargs): """Reads an AMIRA spatial graph file (AmiraMesh 3D ASCII 2.0 format) and constructs the corresponding vascular graph from it. INPUT: filename: AMIRA spatial graph file (including path). If not provided, a graphical file-selection dialog will display. resolution: The resolution of the srXTM scan, i.e. voxel size (isotropic resolution is assumend). The default is 1.0. lUnit: The unit of length properties in the spatialGraph (i.e. radii, and position vectors). The default is microns. **kwargs: defaultUnits: The defaultUnits of the VascularGraph created (see __init__ of the VascularGraph class for details). OUTPUT: G: Vascular graph in iGraph format. """ #if filename is None: # filename = guiTools.uigetfile('Select Amira spatialGraph (.am) file') f = open(filename, 'r') def advanceToToken(token, searchdepth=2): done = False while not done: l = f.readline() if l == '': # eof break if l[0:searchdepth] == token: done = True log.debug('Found ' + token) return l # Get file statistics l = advanceToToken('define VERTEX', 13) n_vertices = int(l.split()[-1]) l = advanceToToken('define EDGE', 11) n_edges = int(l.split()[-1]) l = advanceToToken('define POINT', 12) n_points = int(l.split()[-1]) log.info("Vertices: " + str(n_vertices)) log.info("Edges: " + str(n_edges)) log.info("Points: " + str(n_points)) # Create VascularGraph and compute scaling factor G = VascularGraph(n_vertices, **kwargs) sf = units.scaling_factor_du(lUnit, G['defaultUnits']) # Add vertices log.info("reading and adding vertices") advanceToToken('@1') edgeConnectivity = [] numEdgePoints = [] r = [[] for i in xrange(n_vertices)] for i in xrange(n_vertices): l = f.readline() l = l.split() r[i] = sp.array([float(l[0]), float(l[1]), float(l[2])]) * resolution * sf G.vs['r'] = r # Read connectivity information log.info("reading connectivity information") advanceToToken('@2') for i in xrange(n_edges): l = f.readline() l = l.split() edgeConnectivity.append((int(l[0]), int(l[1]))) # Read number of edge points log.info("reading number of edge points") advanceToToken('@3') for i in xrange(n_edges): l = f.readline() numEdgePoints.append(int(l)) # Read edge point coordinates # Compute length log.info("reading point coordinates") advanceToToken('@4') l_edge = [] edgepoints = [] for edge in xrange(n_edges): tmppoints = sp.zeros([numEdgePoints[edge], 3]) for point in xrange(numEdgePoints[edge]): l = f.readline() tmppoints[point] = map(float, l.split()) l_edge.append([ np.linalg.norm(tmppoints[i] - tmppoints[i + 1]) for i in xrange(len(tmppoints) - 1) ]) l_edge[edge].insert(0, 0.0) l_edge[edge].extend([0.0]) l_edge[edge] = [(l_edge[edge][i - 1] + l_edge[edge][i]) / 2.0 for i in xrange(1, len(l_edge[edge]))] # iGraph, unlike Amira orders edge vertices by index. Make sure that # this is reflected in the points that make up the edge: if edgeConnectivity[edge][0] > edgeConnectivity[edge][1]: tmppoints = tmppoints[::-1, :] edgepoints.append(tmppoints) if sp.mod(edge + 1, sp.floor(n_edges / 10)) == 0: log.info(str(10 * (edge + 1) / sp.floor(n_edges / 10)) + "%") # Read edge radii log.info("reading radii") advanceToToken('@5') d_edge = [] for edge in xrange(n_edges): tmpdiameters = [] for point in xrange(numEdgePoints[edge]): l = f.readline() tmpdiameters.append(float(l) * 2.0) # conversion radius to diameter d_edge.append(tmpdiameters) f.close() # Add edges log.info("adding edges") G.add_edges(edgeConnectivity) d_edge = [ sp.array(d_edge[i], dtype=float) * resolution * sf for i in xrange(n_edges) ] l_edge = [ sp.array(l_edge[i], dtype=float) * resolution * sf for i in xrange(n_edges) ] G.es['diameters'] = d_edge G.es['points'] = [p * resolution * sf for p in edgepoints] # Compute average diameter, weighted by length: # - volume = pi * d**2 /4 * length # - morphologically representative because of length-weighting # - individual diameters scale with identical factors as average diameter G.es['diameter'] = [ np.sqrt(np.average(d_edge[i]**2, weights=l_edge[i])) for i in xrange(n_edges) ] G.es['lengths'] = l_edge G.es['length'] = [sum(l) for l in l_edge] return G
def read_amira_spatialGraph_v2(filename=None, resolution=1.0, lUnit='um', **kwargs): """Reads an AMIRA spatial graph file (AmiraMesh 3D ASCII 2.0 format) and constructs the corresponding vascular graph from it. This version accounts for the fact that some spatialGraph files have colocalized vertices, which are actually identical (this happens especially after conversion from an mv3d file). INPUT: filename: AMIRA spatial graph file (including path). If not provided, a graphical file-selection dialog will display. resolution: The resolution of the srXTM scan, i.e. voxel size (isotropic resolution is assumend). The default is 1.0. lUnit: The unit of length properties in the spatialGraph (i.e. radii, and position vectors). The default is microns. **kwargs: defaultUnits: The defaultUnits of the VascularGraph created (see __init__ of the VascularGraph class for details). OUTPUT: G: Vascular graph in iGraph format. """ #if filename is None: # filename = guiTools.uigetfile('Select Amira spatialGraph (.am) file') f = open(filename,'r') def advanceToToken(token,searchdepth=2): done = False while not done: l = f.readline() if l == '': # eof break if l[0:searchdepth] == token: done = True log.debug('Found ' + token) return l # Get file statistics l = advanceToToken('define VERTEX',13) n_vertices = int(l.split()[-1]) l = advanceToToken('define EDGE',11) n_edges = int(l.split()[-1]) l = advanceToToken('define POINT',12) n_points = int(l.split()[-1]) log.info("Vertices: " + str(n_vertices)) log.info("Edges: " + str(n_edges)) log.info("Points: " + str(n_points)) log.info("reading and adding vertices") # Add vertices advanceToToken('@1') edgeConnectivity = [] numEdgePoints = [] rDict = {} # relates coordinates to first vertex occurence vDict = {} # relates later vertex occurences to first one vCounter = 0 for i in xrange(n_vertices): l = f.readline() l = l.split() rTmp = (float(l[0]),float(l[1]),float(l[2])) if rDict.has_key(rTmp): vDict[i] = rDict[rTmp] else: rDict[rTmp] = vCounter vDict[i] = vCounter vCounter += 1 # Create VascularGraph and compute scaling factor G = VascularGraph(len(rDict), **kwargs) # len(rDict) <= n_vertices sf = units.scaling_factor_du(lUnit, G['defaultUnits']) # sort r by vertex number and scale with 'resolution' and 'sf': G.vs['r'] = sp.array([x[0] for x in sorted(rDict.items(), key=itemgetter(1))]) * resolution * sf # Read connectivity information log.info("reading connectivity information") advanceToToken('@2') for i in xrange(n_edges): l = f.readline() l = l.split() edgeConnectivity.append((vDict[int(l[0])],vDict[int(l[1])])) # Read number of edge points log.info("reading number of edge points") advanceToToken('@3') for i in xrange(n_edges): l = f.readline() numEdgePoints.append(int(l)) # Read edge point coordinates # Compute length log.info("reading point coordinates") advanceToToken('@4') # Assign a length to each point (i.e.: #lengths == #points): l_edge = [] edgepoints = [] for edge in xrange(n_edges): tmppoints = sp.zeros([numEdgePoints[edge],3]) for point in xrange(numEdgePoints[edge]): l = f.readline() tmppoints[point] = map(float, l.split()) l_edge.append([ np.linalg.norm(tmppoints[i]-tmppoints[i+1]) for i in xrange(len(tmppoints)-1) ]) l_edge[edge].insert(0, 0.0) l_edge[edge].extend([0.0]) l_edge[edge] = [(l_edge[edge][i-1] + l_edge[edge][i]) / 2.0 for i in xrange(1,len(l_edge[edge]))] # iGraph, unlike Amira orders edge vertices by index. Make sure that # this is reflected in the points that make up the edge: if edgeConnectivity[edge][0] > edgeConnectivity[edge][1]: tmppoints = tmppoints[::-1,:] edgepoints.append(tmppoints) if sp.mod(edge+1,sp.floor(n_edges/10)) == 0: log.info(str(10*(edge+1)/sp.floor(n_edges/10)) + "%") # Read edge radii log.info("reading radii") advanceToToken('@5') d_edge = [] for edge in xrange(n_edges): tmpdiameters = [] for point in xrange(numEdgePoints[edge]): l = f.readline() tmpdiameters.append(float(l)*2.0) # conversion radius to diameter d_edge.append(tmpdiameters) f.close() # Add edges: log.info("adding edges") G.add_edges(edgeConnectivity) d_edge = [sp.array(d_edge[i],dtype=float) * resolution * sf for i in xrange(n_edges)] l_edge = [sp.array(l_edge[i],dtype=float) * resolution * sf for i in xrange(n_edges)] # Compute average diameter, weighted by length: # - volume = pi * d**2 /4 * length # - morphologically representative because of length-weighting # - individual diameters scale with identical (multiplicative) factors as # the average diameter try: G.es['diameter'] = [np.sqrt(np.average(d_edge[i]**2, weights=l_edge[i])) for i in xrange(n_edges)] except: # Length-weighting is not possible for zero-length edges. These # pathological edges need to be removed: length = [sum(l) for l in l_edge] zeroLength = np.nonzero(np.array(length) == 0.0)[0] nonzeroLength = np.nonzero(np.array(length) != 0.0)[0] d_edge = [x for i,x in enumerate(d_edge) if i in nonzeroLength] l_edge = [x for i,x in enumerate(l_edge) if i in nonzeroLength] edgepoints = [x for i,x in enumerate(edgepoints) if i in nonzeroLength] G.delete_edges(zeroLength.tolist()) n_edges = G.ecount() log.warning('%i zero-length edges were removed. %i edges remaining' % \ (len(zeroLength), n_edges)) G.es['diameter'] = [np.sqrt(np.average(d_edge[i]**2, weights=l_edge[i])) for i in xrange(n_edges)] G.es['diameters'] = d_edge G.es['points'] = [p * resolution * sf for p in edgepoints] G.es['lengths'] = l_edge G.es['length'] = [sum(l) for l in l_edge] return G
def read_amira_spatialGraph_v2(filename=None, resolution=1.0, lUnit='um', **kwargs): """Reads an AMIRA spatial graph file (AmiraMesh 3D ASCII 2.0 format) and constructs the corresponding vascular graph from it. This version accounts for the fact that some spatialGraph files have colocalized vertices, which are actually identical (this happens especially after conversion from an mv3d file). INPUT: filename: AMIRA spatial graph file (including path). If not provided, a graphical file-selection dialog will display. resolution: The resolution of the srXTM scan, i.e. voxel size (isotropic resolution is assumend). The default is 1.0. lUnit: The unit of length properties in the spatialGraph (i.e. radii, and position vectors). The default is microns. **kwargs: defaultUnits: The defaultUnits of the VascularGraph created (see __init__ of the VascularGraph class for details). OUTPUT: G: Vascular graph in iGraph format. """ #if filename is None: # filename = guiTools.uigetfile('Select Amira spatialGraph (.am) file') f = open(filename, 'r') def advanceToToken(token, searchdepth=2): done = False while not done: l = f.readline() if l == '': # eof break if l[0:searchdepth] == token: done = True log.debug('Found ' + token) return l # Get file statistics l = advanceToToken('define VERTEX', 13) n_vertices = int(l.split()[-1]) l = advanceToToken('define EDGE', 11) n_edges = int(l.split()[-1]) l = advanceToToken('define POINT', 12) n_points = int(l.split()[-1]) log.info("Vertices: " + str(n_vertices)) log.info("Edges: " + str(n_edges)) log.info("Points: " + str(n_points)) log.info("reading and adding vertices") # Add vertices advanceToToken('@1') edgeConnectivity = [] numEdgePoints = [] rDict = {} # relates coordinates to first vertex occurence vDict = {} # relates later vertex occurences to first one vCounter = 0 for i in xrange(n_vertices): l = f.readline() l = l.split() rTmp = (float(l[0]), float(l[1]), float(l[2])) if rDict.has_key(rTmp): vDict[i] = rDict[rTmp] else: rDict[rTmp] = vCounter vDict[i] = vCounter vCounter += 1 # Create VascularGraph and compute scaling factor G = VascularGraph(len(rDict), **kwargs) # len(rDict) <= n_vertices sf = units.scaling_factor_du(lUnit, G['defaultUnits']) # sort r by vertex number and scale with 'resolution' and 'sf': G.vs['r'] = sp.array( [x[0] for x in sorted(rDict.items(), key=itemgetter(1))]) * resolution * sf # Read connectivity information log.info("reading connectivity information") advanceToToken('@2') for i in xrange(n_edges): l = f.readline() l = l.split() edgeConnectivity.append((vDict[int(l[0])], vDict[int(l[1])])) # Read number of edge points log.info("reading number of edge points") advanceToToken('@3') for i in xrange(n_edges): l = f.readline() numEdgePoints.append(int(l)) # Read edge point coordinates # Compute length log.info("reading point coordinates") advanceToToken('@4') # Assign a length to each point (i.e.: #lengths == #points): l_edge = [] edgepoints = [] for edge in xrange(n_edges): tmppoints = sp.zeros([numEdgePoints[edge], 3]) for point in xrange(numEdgePoints[edge]): l = f.readline() tmppoints[point] = map(float, l.split()) l_edge.append([ np.linalg.norm(tmppoints[i] - tmppoints[i + 1]) for i in xrange(len(tmppoints) - 1) ]) l_edge[edge].insert(0, 0.0) l_edge[edge].extend([0.0]) l_edge[edge] = [(l_edge[edge][i - 1] + l_edge[edge][i]) / 2.0 for i in xrange(1, len(l_edge[edge]))] # iGraph, unlike Amira orders edge vertices by index. Make sure that # this is reflected in the points that make up the edge: if edgeConnectivity[edge][0] > edgeConnectivity[edge][1]: tmppoints = tmppoints[::-1, :] edgepoints.append(tmppoints) if sp.mod(edge + 1, sp.floor(n_edges / 10)) == 0: log.info(str(10 * (edge + 1) / sp.floor(n_edges / 10)) + "%") # Read edge radii log.info("reading radii") advanceToToken('@5') d_edge = [] for edge in xrange(n_edges): tmpdiameters = [] for point in xrange(numEdgePoints[edge]): l = f.readline() tmpdiameters.append(float(l) * 2.0) # conversion radius to diameter d_edge.append(tmpdiameters) f.close() # Add edges: log.info("adding edges") G.add_edges(edgeConnectivity) d_edge = [ sp.array(d_edge[i], dtype=float) * resolution * sf for i in xrange(n_edges) ] l_edge = [ sp.array(l_edge[i], dtype=float) * resolution * sf for i in xrange(n_edges) ] # Compute average diameter, weighted by length: # - volume = pi * d**2 /4 * length # - morphologically representative because of length-weighting # - individual diameters scale with identical (multiplicative) factors as # the average diameter try: G.es['diameter'] = [ np.sqrt(np.average(d_edge[i]**2, weights=l_edge[i])) for i in xrange(n_edges) ] except: # Length-weighting is not possible for zero-length edges. These # pathological edges need to be removed: length = [sum(l) for l in l_edge] zeroLength = np.nonzero(np.array(length) == 0.0)[0] nonzeroLength = np.nonzero(np.array(length) != 0.0)[0] d_edge = [x for i, x in enumerate(d_edge) if i in nonzeroLength] l_edge = [x for i, x in enumerate(l_edge) if i in nonzeroLength] edgepoints = [ x for i, x in enumerate(edgepoints) if i in nonzeroLength ] G.delete_edges(zeroLength.tolist()) n_edges = G.ecount() log.warning('%i zero-length edges were removed. %i edges remaining' % \ (len(zeroLength), n_edges)) G.es['diameter'] = [ np.sqrt(np.average(d_edge[i]**2, weights=l_edge[i])) for i in xrange(n_edges) ] G.es['diameters'] = d_edge G.es['points'] = [p * resolution * sf for p in edgepoints] G.es['lengths'] = l_edge G.es['length'] = [sum(l) for l in l_edge] return G