def run(self): layout = np.empty((self.max, 2)) forceatlas2 = ForceAtlas2(adjustSizes=True, scalingRatio=RADIUS, verbose=False) clusters = sorted(self.graph.clusters(), key=len, reverse=True) dx, dy = 0, 0 max_height = 0 max_width = 0 total_count = 0 for i, ids in enumerate(clusters): if self.isStopped(): self.canceled.emit() return False graph = self.graph.subgraph(ids) vcount = graph.vcount() radii = [ self.radii[x] if self.radii[x] > 0 else RADIUS for x in ids ] if vcount == 1: lyt = ig.Layout([(0, 0)]) border = 2 * radii[0] elif vcount == 2: lyt = ig.Layout([(0, -2 * radii[0]), (0, 2 * radii[1])]) border = 2 * max(radii) else: lyt = forceatlas2.forceatlas2_igraph_layout( graph, pos=None, sizes=radii, iterations=1000, weight_attr='__weight') border = 5 * max(radii) bb = lyt.bounding_box(border=border) lyt.translate(dx - bb.left, dy - bb.top) for coord, index in zip(lyt, ids): layout[index] = coord if max_width == 0: max_width = bb.width * 2 dx += bb.width max_height = max(max_height, bb.height) if dx >= max_width: dx = 0 dy += max_height max_height = 0 total_count += vcount self.updated.emit(total_count) return layout, np.where(np.asarray(self.graph.degree()) < 1)[0]
def __call__(self, layout): """ Process a MDS """ from sklearn import manifold import scipy.spatial.distance as d if len(layout) > 0 and len(layout) != layout.dim: raise ValueError( 'The layout should have same number of vertices and dimensions' ) mat = np.array(layout.coords) mat = d.cdist(mat, mat, metric="cosine") if len(layout) == 0: result = [] else: if layout.dim <= self.out_dim: result = np.hstack( (mat, np.zeros( (len(layout), self.out_dim - layout.dim)))).tolist() else: mds = manifold.MDS(self.out_dim, max_iter=600, n_init=30, dissimilarity="precomputed") result = mds.fit_transform(mat).tolist() return ig.Layout(result, dim=self.out_dim)
def plot_the_result(dict_mdp, mdp_challenge): edge_list=topology_to_edge_list(mdp_challenge['T']) g = ig.Graph(edge_list) g.vs["name"] = dict_mdp['S'] g.vs["reward"] = dict_mdp['R'] g.vs["label"] = g.vs["name"] P_2D=list(mdp_challenge['P'].values()) x_vec = [wlt[0] for wlt in P_2D] y_vec = [wlt[1] for wlt in P_2D] layout = ig.Layout(P_2D) g.vs["vertex_size"] = 20 visual_style = {} visual_style["edge_curved"] = False colors = [(1, 0, 1) for i in range(0, len(dict_mdp['S']))] g.vs["color"] = colors fig = go.Figure() fig.add_trace(go.Scattergl(x=x_vec, y=y_vec, text=dict_mdp['S'], mode='markers', name='grid_points')) fig.add_trace(go.Scattergl(x=x_vec, y=y_vec, mode='markers', name='value_markers', marker=dict(size=dict_mdp['U'], color=dict_mdp['U']) )) fig.show()
def visualize_temporal_unweighted(adja_mat,feature_names,full_feature_names,lag_range,all_variable_names,plotname="graph_temporal.pdf"): if isinstance(adja_mat,np.ndarray): adja_mat=adja_mat.tolist() gr=igraph.Graph.Weighted_Adjacency(adja_mat, mode="directed", attr="weight", loops=False) coord_list=[0]*len(all_variable_names) for ell in range(len(feature_names)): coord_list[all_variable_names.index(full_feature_names[ell])]=(0.5*ell,0+0.06*(-1)**ell) gr.vs[all_variable_names.index(full_feature_names[ell])]["name"]=feature_names[ell] for mmm in range(len(lag_range)): coord_list[all_variable_names.index(full_feature_names[ell]+'-'+str(lag_range[mmm]))]=(0.5*ell+0.01*(-1)**mmm,0.5*(mmm+1)+0.06*(-1)**ell) gr.vs[all_variable_names.index(full_feature_names[ell]+'-'+str(lag_range[mmm]))]["name"]=feature_names[ell]+'_'+str(lag_range[mmm]) layout = igraph.Layout(coord_list) visual_style = {} visual_style["vertex_size"] = 20 visual_style["vertex_label_size"]=6 visual_style["vertex_color"] = [220,220,220] visual_style["vertex_shape"] = "rectangle" visual_style["vertex_label"] = gr.vs["name"] visual_style["edge_width"] = 1.2 visual_style["edge_arrow_size"]=0.8 visual_style["edge_arrow_width"]=0.8 visual_style["edge_label_size"]=8 visual_style["layout"] = layout visual_style["bbox"] = (800, 800) visual_style["margin"] = 40 igraph.plot(gr,plotname,**visual_style)
def clonotype_network_igraph(adata, neighbors_key="tcr_neighbors", basis="clonotype_network"): """ Get an `igraph` object representing the clonotype network. Parameters ---------- adata annotated data matrix neighbors_key key in `adata.uns` where tcr neighborhood information is located basis key in `adata.obsm` where the network layout is stored. Returns ------- graph igraph object layout corresponding igraph Layout object. """ import igraph as ig from .._util._graph import get_igraph_from_adjacency conn = adata.uns[neighbors_key]["connectivities"] idx = np.where(~np.any(np.isnan(adata.obsm["X_" + basis]), axis=1))[0] g = get_igraph_from_adjacency(conn).subgraph(idx) layout = ig.Layout(coords=adata.obsm["X_" + basis][idx, :].tolist()) return g, layout
def __call__(self, graph, length=None, add_loops=None): weight = None if self.weighted: weight = EDGE_WEIGHT_ATTR #TODO: manage loops weight ! graph.to_undirected() coords = [prox.prox_markov_list(graph, [vtx.index], weight=weight, length=length, add_loops=add_loops) \ for vtx in graph.vs] return ig.Layout(coords, dim=len(coords))
def __call__(self, layout): """ Process the random projection """ if len(layout) == 0: return layout mat = np.array(layout.coords) mat_r = sc.rand(layout.dim, self.out_dim) result = mat.dot(mat_r) return ig.Layout(result.tolist())
def get_coords(g0, g1): """ Keep the coordinates of graph g0 after certain nodes are deleted. G0: original graph G1: derived graph from G0 after certain nodes are deleted. """ import igraph coords0 = g0['layout'].coords coords0 = dict([el for el in zip(g0.vs['name'], coords0)]) coords1 = [coords0.get(v) for v in g1.vs['name']] return igraph.Layout(coords1)
def main(): #---------------------------------------------------------------------# # Layout for simulated EEG idx, x, y, label = np.loadtxt('acticap64xy.csv', dtype={ 'names': ('idx', 'x', 'y', 'label'), 'formats': ('i', 'f', 'f', 'U3') }, delimiter=' ', unpack=True) loc = np.stack([x, y], axis=-1).tolist() layout = ig.Layout(loc) layout.mirror(1) # simulated connection prefix = 'sim_chaos_colpitts_p64_' suffix = '.mat' filename = [ 'r6', 'r6_LF', 'r6_LF_RP_iid', 'r6_LF+RP', 'r4_3r_iid', 'r4_3r_2inter', 'r4_3r_3inter', 'r12' ] matname = 'conn_nt' for fname in filename: conn = comty.loadmat(os.path.join(prefix + fname + suffix), matname) conn_tmp = np.mean(conn, 2) g, w = comty.create_graph(conn_tmp, labels=label, rescale=False, lowbnd=0) comty.graph_plot(g, layout, clustering='fastgreedy', savename=fname + '.png') #---------------------------------------------------------------------# # Layout for minimal EEG loc_min = np.array([[-1, 1], [1, 1], [2, -1], [0, -1], [-2, -1]]).tolist() label_min = np.array(['x1', 'x2', 'x3', 'x4', 'x5']) layout_min = ig.Layout(loc_min)
def computeLayout(graph): was_directed = graph.is_directed() if not was_directed: graph.to_directed() sugi = [x[1] for x in graph.layout_sugiyama()[:len(graph.vs)]] if not was_directed: graph.to_undirected() rank_max = max(sugi) ranks = [(x / (rank_max / 2)) - 1 for x in sugi] prox_coords = ProxLayoutPCA(dim=dim - 1)(graph) return ig.Layout( [prox_coords[i] + [rank] for i, rank in enumerate(ranks)], dim=dim)
def shake(self, layout): from scipy.spatial.distance import pdist, squareform iter_max = 50 # try to keep low layout_mat = np.array(layout.coords, dtype=float) nbs, nbdim = layout_mat.shape # nb objets, nb dimension de l'espace deplacements = np.zeros( (nbs, nbdim)) # matrice des déplacement élémentaires # on calcul la taille des spheres, # l'heuristique c'est que l'on puisse mettre 10 spheres sur la largeur du layout # le layout fait 1 de large size_elem = 1. / 10. sizes = size_elem * np.ones((nbs)) # a pseudo sphere size # calcul la matrice des distances minimales entre sommets dists_min = (sizes[:, None] + sizes[None, :]) / 2 dists_min -= np.diag(dists_min.diagonal()) # diagonal = 0 chevauchement = True # est-ce qu'il y a chevauchement entre les spheres ? nb_iter = 0 while nb_iter < iter_max and chevauchement: nb_iter += 1 # calcul des distances entre les spheres dists = pdist(layout_mat, 'euclidean') dists = squareform(dists, force='tomatrix') # si tout les distances sont sup a distance min chevauchement = (dists < dists_min).any() if not chevauchement: break # calcul des vecteurs de deplacement de chaque sphere (= somme des forces qui s'exerce sur chaque sommet) deplacements[:, :] = 0 # raz for source in range(nbs): for dest in range(source + 1, nbs): if dists[source, dest] < dists_min[source, dest]: # vecteur de deplacement de source vers dest vect_depl = layout_mat[dest] - layout_mat[source] # deplacement aléatoire si chevauchement parfait vnorm = np.linalg.norm(vect_depl) if vnorm < 1e-10: vect_depl = np.random.random(nbdim) vnorm = np.linalg.norm(vect_depl) vect_depl /= vnorm # normalisation # force = prop a la difference entre dist min et dist réel force = self.kelastic * (dists_min[source, dest] - dists[source, dest]) deplacements[source, :] += -force * vect_depl deplacements[dest, :] -= -force * vect_depl # mise a jour des positions layout_mat += deplacements layout = ig.Layout(layout_mat.tolist()) layout = normalise(layout) return layout
def __call__(self, graph, length=None, add_loops=None): assert "type" in graph.vs.attributes() weight = None if self.weighted: weight = EDGE_WEIGHT_ATTR coords = [] for vtx in graph.vs: v_length = length - (length % 2) if vtx["type"] else length - ( length % 2) + 1 pline = prox.prox_markov_list(graph, [vtx.index], length=v_length, add_loops=False, weight=weight) coords.append(pline) return ig.Layout(coords)
def graphgen(N, directed=True, noigraph_gen=False, return_layout_as_object=True): """ This function creates a directed lattice in d=2 where edges go up or right. The ig.Graph.Lattice function does not appear to create directed graphs well. Use plot_graph to test with a small N. Returns: a tuple (g,l) where g is an igraph object, and l is an igraph layout igraph does not check for uniqueness when adding vertices by name. noigraph_gen does not generate the igraph object. This is mostly used for debugging. It works best if asgenerator is set to false so that you get a list of vertices and edges. Oct 25 2017 The for loop in this function is very slow. An iterator that yields is definitely better since the for loop is run by the igraph creation routine. Oct 24 2017 This is a fairly inefficient function. Probably easier to add vertices by generating a list of names first. noigraph_gen simply retuns edges and vertices """ if dbg >= 3: print('running graphgen as generator') verts = vertgen(N) edges = edgegen(N) # make a graph layout for plotting if not noigraph_gen: if dbg >= 3: print('generating new graph') try: g = ig.Graph(directed=directed) g.add_vertices(verts) g.add_edges(edges) except: print('Error in generating igraph') # make layout for plotting layoutlist = [(x, y) for x in range(N) for y in range(N)] if return_layout_as_object: return g, ig.Layout(layoutlist) else: return g, layoutlist #return g,ig.Layout(layoutlist) else: return ([x for x in verts], [x for x in edges])
def __call__(self, layout): """ Process a PCA """ if len(layout) > 0 and len(layout) != layout.dim: raise ValueError( 'The layout should have same number of vertices and dimensions' ) mat = np.array(layout.coords) if len(layout) == 0: result = [] else: if layout.dim <= self.out_dim: result = np.hstack( (mat, np.zeros( (len(layout), self.out_dim - layout.dim)))).tolist() else: result = self.robust_pca(mat).tolist() return ig.Layout(result, dim=self.out_dim)
def visualize_network(self): g = ig.Graph(self.mdp_dict['adjacency_list']) g.vs["name"] = self.mdp_dict['S'] g.vs["reward"] = self.mdp_dict['R'] g.vs["label"] = g.vs["name"] # vec=np.array(self.mdp_dict['U']) # p=np.var(vec) # if(p==0): # print('error') # exit() # color_dict = {0: "blue", 1: "green", 2: "cyan", 3: "yellow", 4: "pink", 5: "orange", 6: "red"} # try: # codebook, _ = kmeans(vec, len(color_dict)) # cluster_indices, _ = vq(vec, codebook) # except: # codebook # # sel=[] # am_max_cluster=np.max(cluster_indices) # for qrti in range(0, am_max_cluster+1): # tre=qrti==cluster_indices # new_candi=np.max(vec[tre]) # sel.append(new_candi) # sel=np.array(sel) # sort_idx=np.argsort(sel) # new_cluster_indices=[np.nan]*len(cluster_indices) # for count, qrt in enumerate(sort_idx): # act_idx_bool=sort_idx[count]==cluster_indices # act_idx=np.where(act_idx_bool) # act_idx=act_idx[0].tolist() # for t in act_idx: # new_cluster_indices[t]=count # # colors = [color_dict[index] for index in new_cluster_indices] # g.vs["color"] = colors g.vs["vertex_size"] = 20 visual_style = {} visual_style["edge_curved"] = False P_2D = [(wlt[0], wlt[1]) for wlt in self.mdp_dict['P']] layout = ig.Layout(P_2D) ig.plot(g)
def clonotype_network_igraph( adata: AnnData, basis="clonotype_network") -> Tuple[ig.Graph, ig.Layout]: """ Get an `igraph` object representing the clonotype network. Requires running :func:`scirpy.tl.clonotype_network` before, to compute the layout. Parameters ---------- adata Annotated data matrix. basis Key in `adata.obsm` where the network layout is stored. Returns ------- graph igraph object layout corresponding igraph Layout object. """ from ..util.graph import igraph_from_sparse_matrix try: clonotype_key = adata.uns[basis]["clonotype_key"] except KeyError: raise KeyError( f"{basis} not found in `adata.uns`. Did you run `tl.clonotype_network`?" ) if f"X_{basis}" not in adata.obsm_keys(): raise KeyError( f"X_{basis} not found in `adata.obsm`. Did you run `tl.clonotype_network`?" ) coords, adj_mat = _graph_from_coordinates(adata, clonotype_key) graph = igraph_from_sparse_matrix(adj_mat, matrix_type="distance") # flip y axis to be consistent with networkx coords["y"] = np.max(coords["y"]) - coords["y"] layout = ig.Layout(coords=coords.loc[:, ["x", "y"]].values.tolist()) return graph, layout
def __call__(self, layout): """ run a TSNE """ from sklearn import manifold if len(layout) > 0 and len(layout) != layout.dim: raise ValueError( 'The layout should have same number of vertices and dimensions' ) mat = np.array(layout.coords) if len(layout) == 0: result = [] else: if layout.dim <= self.out_dim: result = np.hstack( (mat, np.zeros( (len(layout), self.out_dim - layout.dim)))).tolist() else: tsne = manifold.TSNE(self.out_dim, n_iter_without_progress=50) result = tsne.fit_transform(mat).tolist() return ig.Layout(result, dim=self.out_dim)
def plot(self): states = [self.agents[i].feat[0] for i in range(self.n)] color_dict = {0: 'orange', 1: 'blue'} size_dict = {0: 8, 1: 2} positions = [(vs['pos_x'], vs['pos_y']) for vs in self.graph.vs] layout = igraph.Layout(positions) igraph.plot(self.graph, layout = layout, \ vertex_color = [color_dict[self.agents[i].feat[0]] \ if self.agents[i].zealot != 1 else 'red' \ for i in range(self.n)], vertex_size = [size_dict[self.agents[i].feat[0]] \ for i in range(self.n)], edge_width = [2.00 if es['t'] != 'v' and \ self.agents[es.target].feat[0] == 0 and \ self.agents[es.source].feat[0] == 0 else 0.00 for es in self.graph.es])
def build_layout(graph, options): coords = [] w = 0.6 * min(numpy.asarray(options.bbox)) r = 0.8 * w / 2 n = len(options.vertices) teta = numpy.linspace(-math.pi / 2, 2 * math.pi - math.pi / 2, num=n + 1) p = [numpy.asarray([r * math.cos(t), r * math.sin(t)]) for t in teta] for layer in range(n): p0 = p[layer] p1 = p[layer + 1] ni = options.vertices[layer] vec = p1 - p0 s = 0.4 / (ni - 1) ci = [p0 + (0.3 + s * i) * vec for i in range(ni)] coords += ci layout = igraph.Layout(coords) return layout
def __call__(self, graph, **kwargs): # split the graph in N connected components connected_components = graph.clusters() subgraphs = connected_components.subgraphs() # compute a list of vertex position (cc id, and id in subgraph) vertex_cc = [] next_by_cc = [0] * len(connected_components) for cc_num in connected_components.membership: v_num = next_by_cc[cc_num] next_by_cc[cc_num] += 1 vertex_cc.append((cc_num, v_num)) # compute layout for each cc layout_mth = self._layout_mth layouts = [layout_mth(cc, **kwargs) for cc in subgraphs] # move each layout nb_cc = len(connected_components) ## full graph of CC cc_graph = ig.Graph.Full(nb_cc) ## compute a weight for each CC, the more nodes the more weight #cc_weight = [np.log(len(cc) + 1) for cc in connected_components] cc_weight = [len(cc) for cc in connected_components] #print(cc_weight) ## weights for the edges between CC wmax = 1. * max(cc_weight) weights = [ 2. * wmax - (cc_weight[edg.source] + cc_weight[edg.target]) for edg in cc_graph.es ] ## Compute CC graph layout cc_layout = cc_graph.layout_fruchterman_reingold(weights=weights, dim=self._merge_dim) for cc_num, layout in enumerate(layouts): cc_position = cc_layout[cc_num] # resize each small layout layout.fit_into([cc_weight[cc_num] / wmax] * layout.dim) layout.center(cc_position) # merge layouts layout = [layouts[cc_num][v_num] for cc_num, v_num in vertex_cc] return ig.Layout(layout)
def compute_Layout(graph_object, layout_type): graph_name = graph_object["name"] layout_name = graph_name + ("." if layout_type != "fr" else ".kk.") + layout_type + ".layout" layout_file = Path(layout_name) if layout_file.is_file(): layout_file = open(layout_name, 'r') layout = ig.Layout(json.load(layout_file), 2) layout_file.close() return layout else: start = time.clock() print("Starting to compute " + LAYOUT_TYPE_NAMES[layout_type]) if layout_type == "fr": layout = graph_object.layout(layout_type, weights="weight", seed = compute_Layout(graph_object, "kk")) #Takes way more than awhile #PROPERLY DONE LIST FOR FR #Uses Kamada Kawai for rough initial placement, then sets using Fruchterman Reingold with proper edge weights elif layout_type == "sugi": layout = graph_object.layout_sugiyama(layers=graph_object.vs["var_type"], weights="weight", hgap = (4 + max(graph_object.vs["size"])) * 2) #Change the hard coding visual_style["bbox"][0] *= 4 elif layout_type == "fr_layer": #Not terribly useful considering the tendency to clump to the dividing line var_types = 1 + max(graph_object.vs["var_type"]) layer_size = visual_style["bbox"][1] / var_types minY, maxY = [], [] for i in range(var_types): minY.append(i * layer_size) maxY.append((i + 1) * layer_size) layout = graph_object.layout_fruchterman_reingold(weights="weight", miny=[minY[i] + visual_style["margin"][i % 2] for i in graph_object.vs["var_type"]], maxy=[maxY[i] + visual_style["margin"][(i + 1) % 2] for i in graph_object.vs["var_type"]]) else: layout = graph_object.layout(layout_type) #Takes awhile print("Layout computed in", time.clock() - start, "seconds") try: layout_file = open(layout_name, 'w') json.dump(layout.coords, layout_file, separators=(",",":")) except: print("Error saving " + layout_name) return layout
def update_layout(self, layout=None, param=None): g = self.graph if self.layout_update_needed(layout, param): start_time = time.time() self.layout_param = self.layout_param if self.layout_param is not None \ else self.layout_defaults[self.layout] if self.layout in self.layout_defaults \ else {} msg = """Calculating %s layout... (numof nodes/edges: %u/%u)""" % \ (self.layout, g.vcount(), g.ecount()) sys.stdout.write('\t::%s' % msg) sys.stdout.flush() self._log(msg) if self.grouping is not None: if self.layout in [ "intergroup", "modular_fr", "modular_circle" ]: f = getattr(gr_plot, "layout_%s" % self.layout) f(g, self.grouping, self.layout_param) else: if self.layout not in [ "fruchterman_reingold", "fr", "circle" ]: self.layout = "fr" g['layout_data'] = layout_intergroup( g, self.grouping, **self.layout_param) g['layout_type'] = "layout_intergroup" if self.vertex_color == "groups": self.colorize(what='vertex', coldef=self.grouping) self.layout = self.layout if layout is None else layout self.layout_param = self.layout_param if param is None else param self.layout_data = g.layout(self.layout, **self.layout_param) self.layout_data = igraph.Layout(self.layout_data) time_elapsed = time.time() - start_time m, s = divmod(time_elapsed, 60) time_elapsed_str = "%02d min %02d sec" % (m, s) sys.stdout.write(' Done in %s. \n' % time_elapsed_str) sys.stdout.flush()
def clonotype_network_igraph(adata, basis="clonotype_network" ) -> Tuple[ig.Graph, ig.Layout]: """ Get an `igraph` object representing the clonotype network. Requires running :func:`scirpy.tl.clonotype_network` before, to compute the layout. Parameters ---------- adata Annotated data matrix. basis Key in `adata.obsm` where the network layout is stored. Returns ------- graph igraph object layout corresponding igraph Layout object. """ from ..util.graph import _get_igraph_from_adjacency try: neighbors_key = adata.uns[basis]["neighbors_key"] except KeyError: raise KeyError( f"{basis} not found in `adata.uns`. Did you run `tl.clonotype_network`?" ) conn = adata.uns[neighbors_key]["connectivities"] idx = np.where(~np.any(np.isnan(adata.obsm["X_" + basis]), axis=1))[0] g = _get_igraph_from_adjacency(conn).subgraph(idx) layout = ig.Layout(coords=adata.obsm["X_" + basis][idx, :].tolist()) return g, layout
def animate(g, layout = None, filename = "frame" , height = 800, rendermovie = True, outfile = 'anim'): """ Rotate 3d layout of graph C{g} and export a C{.png} snapshot for each angle. If found, the graphs vertex attributes C{size} and C{color} will be use. C{color} should be an RGB tuple. If layout is None, a 3d C{FR} layout will be computed. @param g: an C{igraph.Graph} instance. @param layout: 3d igraph Layout. Optional. @param filename: filename prefix for C{.png} snapshots. @param height: height of output C{.png} files in pixels. @param rendermovie: whether or not to render a movie from the snapshots. Requires C{ffmpeg}. @param outfile: filename for output movie. """ if 'size' not in g.vs.attribute_names(): g.vs['size'] = g.degree() if 'color' not in g.vs.attribute_names(): g.vs['color'] = [(255,255,255)] * g.vcount() print "Framing the layout..." gg = frame_the_graph(g) if layout is None: print "computing 3d layout..." layout = g.layout_fruchterman_reingold_3d() #center the layout layout.center(layout.centroid()) y_max = max([item[1] for item in layout.coords]) x_max = max([item[0] for item in layout.coords]) y_min = min([item[1] for item in layout.coords]) x_min = min([item[0] for item in layout.coords]) k = 1.5 x_width = max([np.sqrt(point[0] ** 2 + point[2] ** 2) for point in layout.coords]) aspect = k*(x_max-x_min) / (y_max-y_min) fixed_coords = [[x_width*k,y_max],[x_width*k,y_min],[-x_width*k,y_min],[-x_width*k,y_max]] for i in range(360): rootpoint = layout.coords[0] rootpoint = (0,0,-10) layout.rotate(1, 0, 2, origin=rootpoint) coords2d = [point[:2] for point in layout.coords] new_layout = ig.Layout( coords2d + fixed_coords) update_depths(gg,layout) ig.plot(gg, filename + '-%s.png' % str(i).zfill(3), vertex_color = gg.vs['color-2'], vertex_size = gg.vs['size'], vertex_frame_color = gg.vs['color-1'], layout = new_layout, edge_color = gg.es['color-1'], background='black', bbox=(0,0,int(aspect*height),height) ) if rendermovie: result = os.system(' ffmpeg -y -r 60 -qscale 2 -i %s-%%03d.png %s.mp4' % (filename,outfile)) if result != 0: print "Eerror: could not render movie with ffmpeg."
def graphgen(N, directed=True, noigraph_gen=False, return_layout_as_object=True, graph_shape='rectangle'): """ This function creates a directed lattice in d=2 where edges go up or right. The ig.Graph.Lattice function does not appear to create directed graphs well. Use plot_graph to test with a small N. Returns: a tuple (g,l) where g is an igraph object, and l is an igraph layout directed=True produces a directed lattice with only up/right paths. Currently the other functions cannot handle the undirected lattice noigraph_gen=True does not generate the igraph object. This is mostly used for debugging. return_layout_as_object=True returns the second return value as an igraph object graph_shape='rectangle' or 'triangle' If chosen to be a triangle, helps cut down on computation time for limit shape computations. This is because you do not want to limit shape to be truncated. igraph does not check for uniqueness when adding vertices by name. Oct 25 2017 The for loop in this function is very slow. An iterator that yields is definitely better since the for loop is run by the igraph creation routine. Oct 24 2017 This is a fairly inefficient function. Probably easier to add vertices by generating a list of names first. noigraph_gen simply retuns edges and vertices """ if dbg >= 1: print('Start generating graph: ' + time.asctime()) verts = vertgen(N, graph_shape=graph_shape) edges = edgegen(N, graph_shape=graph_shape) if dbg >= 1: print('Done generating vertex and edge lists: ' + time.asctime()) # make a graph layout for plotting if not noigraph_gen: if dbg >= 3: print('generating new graph') try: g = ig.Graph(directed=directed) #import ipdb; ipdb.set_trace() g.add_vertices(verts) g.add_edges(edges) except: print('Error in generating igraph') # make layout for plotting if graph_shape == 'rectangle': layoutlist = [(x, y) for x in range(N) for y in range(N)] elif graph_shape == 'triangle': layoutlist = [(x, y) for x in range(N) for y in range(N - x)] if dbg >= 1: print('Done generating igraph object and layout: ' + time.asctime()) if return_layout_as_object: return g, ig.Layout(layoutlist) else: return g, layoutlist else: # if noigraph_gen == True return ([x for x in verts], [x for x in edges])
def get_location_plot(neurons, positions, connections, savefile=None): """Plots a location of neurons in Allen common framework, colorcoded by location, with connection edges neurons: list of indices of neurons, corresponding to the indices in the connection tuples positions: [(x,y,z,brain_location)] x,y,z are coordinates in the Allen common framework brain_location is a string describing the brain location of a neuron - position(neuron[i]) = positions[i] connections: [(source,target)] source/target is the index of the source/target neuron in the connection. The source/target index does not access the neurons array, rather, it corresponds to an index that is in the neurons array. """ ### GET EDGES xe = [] ye = [] ze = [] ws = [] for i, j, w in connections: xe += [positions[i][0], positions[j][0], None] ye += [positions[i][1], positions[j][1], None] ze += [positions[i][2], positions[j][2], None] ws += w ### GET POSITIONS, leaving out brain_location string positions_just3d = np.array([(x, y, z) for (x, y, z, _) in positions[neurons]]) xyz = [np.array(i) for i in zip(*positions_just3d)] ### GET BRAIN LOCATION labels locations = np.array([l for (_, _, _, l) in positions[neurons]]) ## GET COLORS TO MATCH BRAIN LOCATION ind_locations = list(set(locations)) colors = [] for loc in locations: colors.append((ind_locations.index(loc) + 1) * 1 / len(ind_locations)) ## PLOTTING layt = ig.Layout(coords=list(positions_just3d)) trace1 = go.Scatter3d(x=xe, y=ye, z=ze, mode='lines', line=dict(color='rgb(125,125,125)', width=1), text=ws, hoverinfo='text', name='functional connections') trace2 = go.Scatter3d(x=xyz[0], y=xyz[1], z=xyz[2], mode='markers', marker=dict(symbol='circle', size=6, color=colors, colorscale='Viridis', line=dict(color='rgb(50,50,50)', width=0.5)), text=locations, hoverinfo='text', name='neurons') data = [trace1, trace2] fig = go.Figure(data=data) iplot(fig, filename='Bi-directionally connected bursting neurons') if savefile is not None: fig.write_html(savefile)
# # To embed users, we do Uuser = user x (v2^-1)' x s2^-1 # # So lets save the right multiplier # user_embed = np.matmul(np.transpose(np.linalg.inv(v_t2)), np.linalg.inv(s_t2)) ### Embedding? # The L/R matrices above are the embeddings for our observed nodes ### Plotting? # Need an igraph, along with a layout num_users = B.shape[0] num_subs = B.shape[1] zero_u = np.zeros((num_users, num_users)) zero_s = np.zeros((num_subs, num_subs)) A = np.block([[zero_u, B], [np.transpose(B), zero_s]]) layout = np.block([[u_t2], [np.transpose(v_t2)]]) full_graph = ig.Graph.Adjacency(A.tolist(), mode=ig.ADJ_MAX) # Adding attributes to the nodes. for i in range(0, num_users): full_graph.vs[i]["color"] = "blue" for i in range(num_users, num_subs + num_users - 1): full_graph.vs[i]["color"] = "red" g_layout = ig.Layout(layout.tolist()) testplot(full_graph, g_layout, filename=PLOT_FN)
def graph_style(graph, visual_style=None): """ args: graph: graph return: visual_style: a dictionary containing the visualization style """ if visual_style is None: visual_style = dict() print("visual_style is None") # vertex color # if not 'vertex_color' in visual_style.keys(): # try: # "set vertex color based on vs attribute area" # # unique areas # uniqarea = list(set(graph.vs["area"])) # # set palette # palette = igcolors.ClusterColoringPalette(len(uniqarea)) # # set vertex color # visual_style['vertex_color'] = [palette[uniqarea.index(area)] for area in graph.vs["area"]] # except KeyError: # visual_style['vertex_color'] = 'black' # vertex size visual_style['vertex_size'] = 10 # outdegree = graph.outdegree() # if max(outdegree) > 0: # visual_style['vertex_size'] = [x/max(outdegree)*10+5 for x in outdegree] # vertex label size visual_style['vertex_label_size'] = 2 # vertex label distance visual_style['vertex_label_dist'] = 2 # vertex label color visual_style['vertex_label_color'] = 'black' # vertex label name try: visual_style["vertex_label"] = graph.vs['name'] except KeyError: print("No vertex name") # vertext label size visual_style["vertex_label_size"] = 20 visual_style["vertex_label_angle"] = 0 # the outdegree for each vertex outdegree = graph.outdegree() visual_style["margin"] = 100 visual_style['edge_width'] = 0.35 # set edge width if not exist if not 'edge_width' in visual_style.keys(): visual_style['edge_width'] = graph.es['weight'] * 10 # set edge color if not exist if not 'edge_color' in visual_style.keys(): print("Use default edge color") # layout try: "set vertex layout based on vs attribute coordinate coord" visual_style['layout'] = ig.Layout(graph.vs["coord"]) except KeyError: print("Does not have a user defined layout, use the default.") return visual_style
def layout(self, ly_alg = "Fruchterman-Reingold", directed_graph=True): if ly_alg not in SUPPORTED_LAYOUTS: return { "graph_ready": False, "errors": "Unsuspported layout algorithm" } print "VIZUALISATION TIMER: igraph layouting :",datetime.now() ly_start = datetime.now() #new layouting by rcattano dimension = 2 max_it = 500 temp = 1 nodes = len(self.igraph.vs) edges = np.array( [edge.tuple for edge in self.igraph.es], np.int32) _l = len(edges) pos = fl.layout_fr(nodes*dimension, edges, max_it, temp ) #get the Layout object here. #http://igraph.org/python/doc/igraph.layout.Layout-class.html scl = int( _l/ 100 ) #int( _l * _l / 10 ) if ly_alg == "Fruchterman-Reingold": ly = igraph.Layout(tuple(zip(pos[0:nodes], pos[nodes:2*nodes]))) scl = scl / 3 elif ly_alg == "LGL": ly = self.igraph.layout_lgl() elif ly_alg == "Kamada-Kawai": ly = self.igraph.layout_kamada_kawai() scl = scl / 10 elif ly_alg == "Star": ly = self.igraph.layout_star() scl = scl * 2 elif ly_alg == "Random": ly = self.igraph.layout_random() scl = scl * 2 else: #ly = igraph.Layout( tuple(map(tuple, pos )) ) #scl = scl / 3 ly = self.igraph.layout_fruchterman_reingold(dim=2,coolexp =1, area = int( _l * _l / 10 ) ) #ly_alg = "Fruchterman-Reingold" #OR standard fruchterman reingold ly_end = datetime.now() diff = ly_end - ly_start print "VIZUALISATION TIMER: returning coordinates :",ly_end print "Layouting took :", diff.seconds, "seconds using", ly_alg # TODO screws up positioning for graphs with few nodes #ly.scale( scl * 4) box = ly.bounding_box() width = abs(box.left) + abs(box.right) coords = ly.__dict__['_coords'] #numpy.float64 cannot be jsonified later, so we convert to standard float: coords = [ [ float( c[0] )* 1 , float( c[1] ) * 1 ] for c in coords ] #todo we have the node names somewhere already ... vertices = [] for i in self.igraph.vs: vertices.append( i['name'] ) all_coords = dict( zip( vertices, coords ) ) #add coords to each layer and get the nodes in each layer intersect with the nodes in the next layer layer_neighborhoods = [] for i,_l in enumerate(self.layer_names): _layer_data = self.data[_l] _layer_data['name'] = _l try: _layer_data_next = data[ self.layer_names[i+1] ] except: #last layer _layer_data_next = self.data[ self.layer_names[i-1] ] #possible with namedtuples #nodes1 = _layer_data.nodes #nodes2 = _layer_data_next.nodes #indegs = _layer_data.in_degrees max_in_deg = 0 max_out_deg = 0 max_total_deg = 0 nodes1 = _layer_data['nodes'] nodes2 = _layer_data_next['nodes'] indegs = _layer_data['in_degrees'] outdegs = _layer_data['out_degrees'] coords = {} common_nodes = list( set( nodes1 ).intersection( set( nodes2 ) ) ) for node_id in nodes1: _common = 1 if node_id in common_nodes else 0 try: indeg = indegs[ node_id ] outdeg = outdegs[ node_id ] except Exception,e: indeg = 0 outdeg = 0 coords[node_id] = [ all_coords[ node_id ], _common, indeg, outdeg, indeg + outdeg, self.custom_scale.get(node_id, 1)] max_out_deg = max(max_out_deg, outdeg) max_in_deg = max(max_in_deg, indeg) max_total_deg = max(max_total_deg, outdeg + indeg) #possible with namedtuples #_layer_data.coords = coords _layer_data['coords'] = coords # add dummy 0 values, so max_in_degree and max_out_degree have to # same offset as the node's degrees _layer_data['maxDeg'] = [0, 0, max_in_deg, max_out_deg, max_total_deg, 1.0] if directed_graph: get_key = lambda v1, v2: ''.join([v1, v2]) else: get_key = lambda v1, v2: ''.join(sorted([v1, v2])) edge_dict = { get_key(x[0], x[1]): x[2] for x in _layer_data['edges']} neighborhood = {} for i, nb in enumerate(self.igraph.neighborhood()): l = [] neighborhood[vertices[i]] = neighborhood.get(vertices[i], l) + [[vertices[j], edge_dict[get_key(vertices[i], vertices[j])]] for j in nb if get_key(vertices[i], vertices[j]) in edge_dict] _layer_data['neighborhood'] = neighborhood
graph = igraph.Graph.Read( tmp_name , directed=directed_graph,format="ncol",weights=False ) #new layouting by rcattano dimension = 2 max_it = 500 temp = 1 nodes = len(graph.vs) edges = np.array( [edge.tuple for edge in graph.es], np.int32) pos = fl.layout_fr(nodes*dimension, edges, max_it, temp ) #get the Layout object here. #http://igraph.org/python/doc/igraph.layout.Layout-class.html scl = int( _l/ 100 ) #int( _l * _l / 10 ) if ly_alg == "Fruchterman-Reingold": ly = igraph.Layout(tuple(zip(pos[0:nodes], pos[nodes:2*nodes]))) scl = scl / 3 elif ly_alg == "LGL": ly = graph.layout_lgl() elif ly_alg == "Kamada-Kawai": ly = graph.layout_kamada_kawai() scl = scl / 10 elif ly_alg == "Star": ly = graph.layout_star() scl = scl * 2 elif ly_alg == "Random": ly = graph.layout_random() scl = scl * 2 else: #ly = igraph.Layout( tuple(map(tuple, pos )) ) #scl = scl / 3