def load_graph(self, G, pos=[]): """ load the network """ self.G = G self.n = len(G.nodes) self.m = len(G.edges) #if no positions given, use force atlas if len(pos) == 0: forceatlas2 = ForceAtlas2( # Tuning scalingRatio=2, strongGravityMode=False, gravity=1, outboundAttractionDistribution=False, # Dissuade hubs # Log verbose=False) self.pos = forceatlas2.forceatlas2_networkx_layout(self.G, pos=None, iterations=2000) else: #else use positions self.pos = pos
def run_force_layout(links, n_cells, n_iter=100, edgeWeightInfluence=1, barnesHutTheta=2, scalingRatio=1, gravity=0.05, jitterTolerance=1, verbose=False): from fa2 import ForceAtlas2 import networkx as nx G = nx.Graph() G.add_nodes_from(range(n_cells)) G.add_edges_from(list(links)) forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=False, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=edgeWeightInfluence, # Performance jitterTolerance=jitterTolerance, # Tolerance barnesHutOptimize=True, barnesHutTheta=barnesHutTheta, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=scalingRatio, strongGravityMode=False, gravity=gravity, # Log verbose=verbose) positions = forceatlas2.forceatlas2_networkx_layout(G, pos=None, iterations=n_iter) positions = np.array([positions[i] for i in sorted(positions.keys())]) return positions
def __init__(self, window: QMainWindow, nodes=None, edges=None, **kwargs): """Конструктор класса :param window: Окно-родитель для GraphWidget :type window: QMainWindow :param nodes: Список вида { id: Id Вершины, args: Список аргументов для конструктора Node } :param edges: Список вида { id: Id Ребра, args: Список аргументов для конструктора Edge } :param kwargs: Аргументы для GraphWidget """ self.window = window self.widget = GraphWidget(self.window, **kwargs) self.fa2 = ForceAtlas2( outboundAttractionDistribution=False, scalingRatio=100.0, verbose=False, gravity=10.0 ) self._nodes = {} # Хранилище вершин self._edges = {} # Хранилище связей self._texts = {} # Хранилище текстов self.get_relation_text = lambda item: str(item) self.matrix = None self.positions = None self.gravity_timer = None # Таймер для работы с гравитацией self.widget.item_right_clicked.connect(self._on_item_clicked)
def compute_embeddings(G): print('Computting embeddings...') forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=False, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=7.0, strongGravityMode=False, gravity=.2, # Log verbose=True) positions = forceatlas2.forceatlas2_networkx_layout(G, pos=None, iterations=100) return positions
def _forceAtlas2Layout_1(self, G: nx.Graph, iterations: int): """ Uses this implementation: https://github.com/bhargavchippada/forceatlas2 """ forceatlas2 = ForceAtlas2( outboundAttractionDistribution=True, # Distributes attraction along outbound edges. Hubs attract less and thus are pushed to the borders edgeWeightInfluence=0, # How much influence you give to the edges weight. 0 is "no influence" and 1 is "normal" # Performance jitterTolerance=0.8, # How much swinging you allow. Above 1 discouraged. Lower gives less speed and more precision barnesHutOptimize=True, # Barnes Hut optimization, n2 complexity to n.ln(n) barnesHutTheta=1, # Tuning scalingRatio=0.6, # How much repulsion you want. More makes a more sparse graph (spärlich) strongGravityMode=False, # A stronger gravity view gravity=1.0, # Attracts nodes to the center. Prevents islands from drifting away # Log verbose=True ) return forceatlas2.forceatlas2_networkx_layout(G, iterations=iterations)
def get_atlas(graph): from fa2 import ForceAtlas2 forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=True) G = igraph.Graph.TupleList(ccn_graph.edges(), directed=False) layout = forceatlas2.forceatlas2_igraph_layout(G, pos=None, iterations=1000) return layout
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 force_directed_layout(G, pdf_name='Layout.network.pdf', cell_names=None, verbose=True, iterations=2000): """" Function to compute force directed layout from the G :param G: networkx graph object converted from sparse matrix representing affinities between cells :param cell_names: pandas Series object with cell names :param verbose: Verbosity for force directed layout computation :param iterations: Number of iterations used by ForceAtlas :return: Pandas data frame representing the force directed layout """ forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=False, linLogMode=False, adjustSizes=False, edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=verbose) ## use affinity construct KNN graph positions = forceatlas2.forceatlas2_networkx_layout(G, pos=None, iterations=iterations) positions = np.array([list(positions[i]) for i in range(len(positions))]) ## plot KNN graph f = plt.figure(figsize=(15, 15)) nx.draw_networkx_nodes(G, positions, node_size=20, with_labels=False, node_color="blue", alpha=0.4) nx.draw_networkx_edges(G, positions, edge_color="green", alpha=0.5) plt.axis('off') plt.show() f.savefig(pdf_name, bbox_inches='tight') ## Convert to dataframe if cell_names is None: cell_names = np.arange(affinity_matrix.shape[0]) positions = pd.DataFrame(positions, index=cell_names, columns=['x', 'y']) positions.loc[:, 'tp'] = pd.Series(cell_names).apply( lambda x: x.split('_')[0]).tolist() return positions
def _coordinates(self, iterations=100, force=False, ignore_orphans=True): from fa2 import ForceAtlas2 forceatlas2 = ForceAtlas2( outboundAttractionDistribution=False, linLogMode=False, adjustSizes=False, edgeWeightInfluence=1.0, jitterTolerance=1.0, barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, scalingRatio=2.0, strongGravityMode=False, gravity=1.0, verbose=True, ) pos = self._bcolz("coordinates") if pos is None or force == True: import scipy.sparse.csgraph as csgraph import networkx A, i = self.to_sparse_matrix() # generate a reverse lookup for index to label rev_i = {v: k for k, v in i.items()} num, ccindex = csgraph.connected_components(A, directed=False) # convert to csc self.log(f"Converting to compressed sparse column") L = A.tocsc() connected_components = Counter(ccindex) component_coordinates = [] offset = None for index, csize in sorted(connected_components.items(), key=lambda x: x[1], reverse=True): if csize == 1 and ignore_orphans: continue C = L[ccindex == index, :][:, ccindex == index] (c_indices, ) = np.where(ccindex == index) labels = [rev_i[x] for x in c_indices] self.log( f"Calculating positions for component {index} (n={csize})") coordinates = positions = forceatlas2.forceatlas2( C, pos=None, iterations=iterations) coordinates = pd.DataFrame(coordinates, index=labels, columns=["x", "y"]) if offset is not None: # shift the x coordinates to 0 coordinates.x = coordinates.x + abs( coordinates.x.min()) + offset offset = coordinates.x.max() component_coordinates.append(coordinates) pos = pd.concat(component_coordinates) self._bcolz("coordinates", df=pos) return pos
def get_fa(std_n=3): G = nx.read_gml('graph_%dstd.gml' % std_n) fa2 = ForceAtlas2() positions = fa2.forceatlas2_networkx_layout(G, pos=None, iterations=2000) nx.draw_networkx(G, positions, cmap=plt.get_cmap('jet'), node_size=50, with_labels=False, width=1, arrows=False) plt.show()
def create_force_cloud(self): G = nx.Graph() for w, info in self.words_info.items(): for w1, info1 in self.words_info.items(): if w != w1: if not G.has_edge(w, w1): if info["cluster"] == info1["cluster"]: weight = 5 - spatial.distance.cosine(info["vector"], info1["vector"]) + 5 if weight == weight: G.add_edge(w, w1, weight=weight) else: G.add_edge(w, w1, weight=0.1) else: weight = 5 - spatial.distance.cosine(info["vector"], info1["vector"]) if weight == weight: G.add_edge(w, w1, weight=weight) else: G.add_edge(w, w1, weight=0.1) forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=True) positions = {} for p, pos in forceatlas2.forceatlas2_networkx_layout(G, pos=None, iterations=100).items(): positions[p] = (min(pos[0], 10000), min(pos[1], 10000) ) print(pos) edgelist=[] nx.draw_networkx(G, positions, edgelist=edgelist, cmap=plt.get_cmap('jet'), node_size=50, with_labels=True, vmin=0.,vmax=0.6) plt.show()
def get_nice_pos(G, k=0.01, iterations=500, layout=None, flatten=False): import networkx as nx if layout is None: try: from fa2 import ForceAtlas2 pos = ForceAtlas2(verbose=False).forceatlas2_networkx_layout( G, iterations=iterations) return massage_pos(pos, flatten=flatten) except ImportError: layout = 'kamada_kawai' pos = getattr(nx.layout, layout + '_layout')(G) pos = nx.spring_layout(G, k=k, iterations=0, pos=pos) return massage_pos(pos, flatten=flatten)
def _networkx(components): G = nx.DiGraph() node_labels = {} node_sizes = [] for c in components: G.add_node(c.name) node_labels[c.name] = str(c.name) node_sizes.append(0.1 + c.revenue) edge_labels = {} for parent in components: for child in components: G.add_edge(parent.name, child.name) edge_labels[(parent.name, child.name)] = "%.3f" % parent.weights[child.name] forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=False) positions = nx.layout.circular_layout(G) pos_higher = {} y_off = 0.2 for k, v in positions.items(): pos_higher[k] = (v[0], v[1]+y_off) nx.draw_networkx_nodes(G, positions, with_labels=True, node_size=node_sizes, node_color="blue", alpha=0.4) nx.draw_networkx_edges(G, positions, arrowstyle='->', arrowsize=15, edge_color="green", edge_labels=edge_labels, alpha=0.05, label_pos=0.3) nx.draw_networkx_labels(G, pos_higher, node_labels) nx.draw_networkx_edge_labels(G, pos_higher, edge_labels=edge_labels, with_labels=True, label_pos=0.3)
def __apply_layout(self, graph, g_status, options): if options["positions"] == 'kk': if options["density"] == "normal": c = 70 elif options["density"] == "dense": c = 30 else: c = 140 positions = graph.layout_kamada_kawai() positions = np.array(positions) * c return positions else: ratio = graph.vcount() / 100.0 if options["density"] == "normal": c = 4 elif options["density"] == "dense": c = 1 else: c = 16 # add position forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=math.sqrt(ratio) * c, strongGravityMode=False, gravity=ratio * 25, # Log verbose=True) graph.es['weights'] = [ 0 if i == -1 else math.sqrt(ratio) * 15 for i in g_status.e_community ] positions = forceatlas2.forceatlas2_igraph_layout( graph, pos=None, iterations=2000, weight_attr='weights') return positions
def plot_graph(fname, iters=500, lbl=False, show=True): nx_graph = nx.Graph() graph = utils.load_graph(fname, weighted=True) for prime in graph.keys(): for target, weight in graph[prime]: nx_graph.add_edge(prime, target, weight=weight) forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=0.1, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=True) positions = forceatlas2.forceatlas2_networkx_layout(nx_graph, pos=None, iterations=iters) if (lbl): nx.draw_networkx_labels(nx_graph, positions, labels=dict([(n, n) for n in nx_graph.nodes()])) nx.draw_networkx_nodes(nx_graph, positions, node_size=5, with_labels=False, node_color="blue", alpha=0.4) nx.draw_networkx_edges(nx_graph, positions, edge_color="green", alpha=0.05) plt.axis('off') plt.savefig(f"{fname.split('.')[-2]}_graph.png") if (show): plt.show() plt.clf()
def calculate_layout(g, iterations=1000, gravity=1): try: from fa2 import ForceAtlas2 model = ForceAtlas2( verbose=True, scalingRatio=1, gravity=gravity, ) matrix = nx.to_scipy_sparse_matrix(g, dtype='f', format='lil', weight='weight') pos = model.forceatlas2(matrix, iterations=iterations) return dict(zip(g.nodes(), pos)) except ImportError: return nx.drawing.layout.spring_layout(g)
def plot_fa(embedding): import networkx as nx from fa2 import ForceAtlas2 fa2 = ForceAtlas2() G = nx.DiGraph() weights = [(i, j, np.linalg.norm(embedding[i] - embedding[j])) for i in range(len(embedding)) for j in range(i)] G.add_weighted_edges_from(weights) positions = fa2.forceatlas2_networkx_layout(G, pos=None, iterations=2000) nx.draw_networkx(G, positions, cmap=plt.get_cmap('jet'), node_size=50, with_labels=False, width=1, arrows=False) plt.show()
def force_directed_layout(affinity_matrix, cell_names=None, verbose=True, iterations=500): """" Function to compute force directed layout from the affinity_matrix :param affinity_matrix: Sparse matrix representing affinities between cells :param cell_names: pandas Series object with cell names :param verbose: Verbosity for force directed layout computation :param iterations: Number of iterations used by ForceAtlas :return: Pandas data frame representing the force directed layout """ init_coords = np.random.random((affinity_matrix.shape[0], 2)) forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=False, linLogMode=False, adjustSizes=False, edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=verbose) positions = forceatlas2.forceatlas2(affinity_matrix, pos=init_coords, iterations=iterations) positions = np.array(positions) # Convert to dataframe if cell_names is None: cell_names = np.arange(affinity_matrix.shape[0]) positions = pd.DataFrame(positions, index=cell_names, columns=['x', 'y']) return positions
def get_symbol_position( number_of_symbols: int, diagram_size: Tuple[int, int]) -> List[Tuple[int, int]]: if number_of_symbols == 1: positions = [ (randint(0, diagram_size[0]), randint(0, diagram_size[1])), ] else: forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=0.1, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=0.5, # Log verbose=False, ) G = np.identity(number_of_symbols) positions = forceatlas2.forceatlas2(G, pos=None, iterations=50) x, y = zip(*positions) x_range = max(x) - min(x) or 1 y_range = max(y) - min(y) or 1 dx, dy = (diagram_size[0], diagram_size[1]) x_ratio = dx / x_range y_ratio = dy / y_range xnp = (np.array(x) + np.abs(min(x))) * x_ratio ynp = (np.array(y) + np.abs(min(y))) * y_ratio positions = list(zip(xnp.astype(int), ynp.astype(int))) return positions
def get_graph_coordinates(self): """ Gets the graph coordinates, which can be: (1) set in the graph itself with the 'pos' tag on the vertices, (2) positioned according to the force atlas2 algorithm, (3) positioned using a spectral layout. Then lays out the edges, can be curved, bundled, or straight :return: Tuple containing node and edge positions """ edge_pos = None node_pos = { idx: v['pos'] for idx, (k, v) in enumerate(dict(self.graph.nodes).items()) if 'pos' in v } # check graph for coords node_pos = node_pos if len(node_pos) == len(self.graph) else None # node positions if self.prm['node_style'] == 'force_atlas' and node_pos is None: force = ForceAtlas2(outboundAttractionDistribution=True, edgeWeightInfluence=0, scalingRatio=6.0, verbose=False) node_pos = force.forceatlas2_networkx_layout( self.graph, pos=None, iterations=self.prm['fa_iter']) elif node_pos is None: node_pos = nx.spectral_layout(self.graph) # edge positions if self.prm['edge_style'] == 'bundled': pos = pd.DataFrame.from_dict( node_pos, orient='index', columns=['x', 'y']).rename_axis('name').reset_index() edge_pos = hammer_bundle(pos, nx.to_pandas_edgelist(self.graph)) return node_pos, edge_pos
def main(args): G = network_from_simulations(args.folders, save=True) frc = ForceAtlas2( outboundAttractionDistribution=True, gravity=1, ) positions = frc.forceatlas2_networkx_layout(G) degree = nx.degree(G) nodes = G.nodes() base_size = 100 sizes = [(degree[node] + 1) * base_size for node in nodes] groups = set(nx.get_node_attributes(G, 'epoch').values()) mapping = dict(zip(sorted(groups), count())) colors = [mapping[G.node[n]['epoch']] for n in nodes] cmap = plt.cm.get_cmap('tab20c', len(groups)) f, ax = plt.subplots(figsize=figure_dims(600, 0.9)) ec = nx.draw_networkx_edges(G, positions, alpha=0.2, ax=ax) nc = nx.draw_networkx_nodes(G, positions, nodelist=nodes, node_color=colors, cmap=cmap, ax=ax, node_size=sizes) if args.labels: nx.draw_networkx_labels(G, positions, font_size=10, ax=ax) cbar = plt.colorbar(nc) if args.title is not None: ax.set_title(args.title) cbar.ax.set_ylabel('Epoch') plt.axis('off') if not args.outputfile.endswith('.pdf'): args.outputfile += '.pdf' f.savefig(args.outputfile)
def layout_graph_force(g, pos=None, iterations=10000, **attrs): from fa2 import ForceAtlas2 defaults = dict( # Behavior alternatives outboundAttractionDistribution=False, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=1.0, strongGravityMode=False, gravity=1.0, # Log verbose=False) newattrs = { **defaults, **dict((k, v) for k, v in attrs.items() if k in defaults) } # if pos is None: pos={} # print(pos.keys()) # print(pos,'!!') # print(g.nodes()) forceatlas2 = ForceAtlas2(**newattrs) # print('inp',pos,'?!?!?') pos = dict( forceatlas2.forceatlas2_networkx_layout(g, pos=pos, iterations=iterations).items()) # print('\nres',pos,'\n') return pos
def force_atlas_2_orderings(g, coefficients_list): ''' Returns orderings based on force atlas 2. coefficients_list is a list of coefficients for the mapping. Each entry must contain two coefficients. The length of coefficients_list is the amount of orderings returned. ''' forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=False) sparse_g = nk.algebraic.adjacencyMatrix(g) positions = forceatlas2.forceatlas2(sparse_g, pos=None, iterations=config.FORCEATLAS2_ITER) ret = list() for coef in coefficients_list: ret.append( sort_nodes( map_to_line( [pos for coordinate in positions for pos in coordinate], coef))) return ret
def pos_fa_layout(network_union): """ ForceAtlas2 to get the layout of the network (the positions) Parameters ---------- network_union : networkx.classes.graph.Graph The union of network1 and network1 Copyright (C) 2017 Bhargav Chippada [email protected]. Licensed under the GNU GPLv3. """ forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=True) pos = forceatlas2.forceatlas2_networkx_layout(network_union, pos=None, iterations=3000) return pos
def fa2_layout(nx_graph, iters=500): if (not os.path.exists(CACHE_FOLDER)): os.makedirs(CACHE_FOLDER) g_hash = nx.weisfeiler_lehman_graph_hash(nx_graph) fa2_cached_layout = f"{CACHE_FOLDER}/{g_hash}.fa2" if (os.path.isfile(fa2_cached_layout)): with open(fa2_cached_layout, 'rb') as fin: return pickle.load(fin) forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=True) positions = forceatlas2.forceatlas2_networkx_layout(nx_graph, pos=None, iterations=iters) with open(fa2_cached_layout, 'wb+') as fout: pickle.dump(positions, fout) return positions
def _paga_graph(adata, ax, layout=None, layout_kwds={}, init_pos=None, solid_edges=None, dashed_edges=None, transitions=None, threshold=None, root=0, colors=None, labels=None, fontsize=None, fontweight=None, text_kwds=None, node_size_scale=1, node_size_power=0.5, edge_width_scale=1, title=None, pos=None, cmap=None, frameon=True, min_edge_width=None, max_edge_width=None, export_to_gexf=False, cax=None, colorbar=None, use_raw=True, cb_kwds={}, single_component=False, arrowsize=30, random_state=0): node_labels = labels # rename for clarity if (node_labels is not None and isinstance(node_labels, str) and node_labels != adata.uns['paga']['groups']): raise ValueError( 'Provide a list of group labels for the PAGA groups {}, not {}.'. format(adata.uns['paga']['groups'], node_labels)) groups_key = adata.uns['paga']['groups'] if node_labels is None: node_labels = adata.obs[groups_key].cat.categories if (colors is None or colors == groups_key) and groups_key is not None: if (groups_key + '_colors' not in adata.uns or len(adata.obs[groups_key].cat.categories) != len( adata.uns[groups_key + '_colors'])): utils.add_colors_for_categorical_sample_annotation( adata, groups_key) colors = adata.uns[groups_key + '_colors'] for iname, name in enumerate(adata.obs[groups_key].cat.categories): if name in settings.categories_to_ignore: colors[iname] = 'grey' if isinstance(root, str): if root in node_labels: root = list(node_labels).index(root) else: raise ValueError( 'If `root` is a string, it needs to be one of {} not \'{}\'.'. format(node_labels.tolist(), root)) if isinstance(root, list) and root[0] in node_labels: root = [list(node_labels).index(r) for r in root] # define the adjacency matrices adjacency_solid = adata.uns['paga'][solid_edges].copy() if threshold is None: threshold = 0.01 # default threshold if threshold > 0: adjacency_solid.data[adjacency_solid.data < threshold] = 0 adjacency_solid.eliminate_zeros() nx_g_solid = nx.Graph(adjacency_solid) if dashed_edges is not None: adjacency_dashed = adata.uns['paga'][dashed_edges].copy() if threshold > 0: adjacency_dashed.data[adjacency_dashed.data < threshold] = 0 adjacency_dashed.eliminate_zeros() nx_g_dashed = nx.Graph(adjacency_dashed) # uniform color if isinstance(colors, str) and is_color_like(colors): colors = [colors for c in range(len(node_labels))] # color degree of the graph if isinstance(colors, str) and colors.startswith('degree'): # see also tools.paga.paga_degrees if colors == 'degree_dashed': colors = [d for _, d in nx_g_dashed.degree(weight='weight')] elif colors == 'degree_solid': colors = [d for _, d in nx_g_solid.degree(weight='weight')] else: raise ValueError( '`degree` either "degree_dashed" or "degree_solid".') colors = (np.array(colors) - np.min(colors)) / (np.max(colors) - np.min(colors)) # plot gene expression var_names = adata.var_names if adata.raw is None else adata.raw.var_names if isinstance(colors, str) and colors in var_names: x_color = [] cats = adata.obs[groups_key].cat.categories for icat, cat in enumerate(cats): subset = (cat == adata.obs[groups_key]).values if adata.raw is not None and use_raw: adata_gene = adata.raw[:, colors] else: adata_gene = adata[:, colors] x_color.append(np.mean(adata_gene.X[subset])) colors = x_color # plot continuous annotation if (isinstance(colors, str) and colors in adata.obs and not is_categorical_dtype(adata.obs[colors])): x_color = [] cats = adata.obs[groups_key].cat.categories for icat, cat in enumerate(cats): subset = (cat == adata.obs[groups_key]).values x_color.append(adata.obs.loc[subset, colors].mean()) colors = x_color # plot categorical annotation if (isinstance(colors, str) and colors in adata.obs and is_categorical_dtype(adata.obs[colors])): from ... import utils as sc_utils asso_names, asso_matrix = sc_utils.compute_association_matrix_of_groups( adata, prediction=groups_key, reference=colors, normalization='reference') utils.add_colors_for_categorical_sample_annotation(adata, colors) asso_colors = sc_utils.get_associated_colors_of_groups( adata.uns[colors + '_colors'], asso_matrix) colors = asso_colors if len(colors) < len(node_labels): print(node_labels, colors) raise ValueError( '`color` list need to be at least as long as `groups`/`node_labels` list.' ) # count number of connected components n_components, labels = scipy.sparse.csgraph.connected_components( adjacency_solid) if n_components > 1 and not single_component: logg.msg( 'Graph has more than a single connected component. ' 'To restrict to this component, pass `single_component=True`.') if n_components > 1 and single_component: component_sizes = np.bincount(labels) largest_component = np.where( component_sizes == component_sizes.max())[0][0] adjacency_solid = adjacency_solid.tocsr()[labels == largest_component, :] adjacency_solid = adjacency_solid.tocsc()[:, labels == largest_component] colors = np.array(colors)[labels == largest_component] node_labels = np.array(node_labels)[labels == largest_component] logg.info( 'Restricting graph to largest connected component by dropping categories\n' '{}'.format(adata.obs[groups_key].cat.categories[ labels != largest_component].tolist())) nx_g_solid = nx.Graph(adjacency_solid) if dashed_edges is not None: raise ValueError( '`single_component` only if `dashed_edges` is `None`.') # node positions from adjacency_solid if pos is None: if layout is None: layout = 'fr' if layout == 'fa': try: from fa2 import ForceAtlas2 except: logg.warn( 'Package \'fa2\' is not installed, falling back to layout \'fr\'.' 'To use the faster and better ForceAtlas2 layout, ' 'install package \'fa2\' (`pip install fa2`).') layout = 'fr' if layout == 'fa': np.random.seed(random_state) if init_pos is None: init_coords = np.random.random((adjacency_solid.shape[0], 2)) else: init_coords = init_pos.copy() forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=False, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=False) if 'maxiter' in layout_kwds: iterations = layout_kwds['maxiter'] elif 'iterations' in layout_kwds: iterations = layout_kwds['iterations'] else: iterations = 500 pos_list = forceatlas2.forceatlas2(adjacency_solid, pos=init_coords, iterations=iterations) pos = {n: [p[0], -p[1]] for n, p in enumerate(pos_list)} elif layout == 'eq_tree': nx_g_tree = nx_g_solid if solid_edges == 'connectivities': adj_tree = adata.uns['paga']['connectivities_tree'] nx_g_tree = nx.Graph(adj_tree) pos = utils.hierarchy_pos(nx_g_tree, root) if len(pos) < adjacency_solid.shape[0]: raise ValueError('This is a forest and not a single tree. ' 'Try another `layout`, e.g., {\'fr\'}.') else: # igraph layouts from ... import utils as sc_utils g = sc_utils.get_igraph_from_adjacency(adjacency_solid) if 'rt' in layout: g_tree = g if solid_edges == 'connectivities': adj_tree = adata.uns['paga']['connectivities_tree'] g_tree = sc_utils.get_igraph_from_adjacency(adj_tree) pos_list = g_tree.layout( layout, root=root if isinstance(root, list) else [root]).coords elif layout == 'circle': pos_list = g.layout(layout).coords else: # I don't know why this is necessary np.random.seed(random_state) if init_pos is None: init_coords = np.random.random( (adjacency_solid.shape[0], 2)).tolist() else: init_pos = init_pos.copy() # this is a super-weird hack that is necessary as igraphs layout function # seems to do some strange stuff, here init_pos[:, 1] *= -1 init_coords = init_pos.tolist() try: pos_list = g.layout(layout, seed=init_coords, weights='weight', **layout_kwds).coords except: # hack for excepting attribute error for empty graphs... pos_list = g.layout(layout, seed=init_coords, **layout_kwds).coords pos = {n: [p[0], -p[1]] for n, p in enumerate(pos_list)} pos_array = np.array([pos[n] for count, n in enumerate(nx_g_solid)]) else: if isinstance(pos, str): if not pos.endswith('.gdf'): raise ValueError( 'Currently only supporting reading positions from .gdf files.' 'Consider generating them using, for instance, Gephi.') s = '' # read the node definition from the file with open(pos) as f: f.readline() for line in f: if line.startswith('edgedef>'): break s += line from io import StringIO df = pd.read_csv(StringIO(s), header=-1) pos = df[[4, 5]].values pos_array = pos # convert to dictionary pos = {n: [p[0], p[1]] for n, p in enumerate(pos)} if len(pos) == 1: pos[0] = (0.5, 0.5) # edge widths base_edge_width = edge_width_scale * 5 * rcParams['lines.linewidth'] # draw dashed edges if dashed_edges is not None: widths = [x[-1]['weight'] for x in nx_g_dashed.edges(data=True)] widths = base_edge_width * np.array(widths) if max_edge_width is not None: widths = np.clip(widths, None, max_edge_width) nx.draw_networkx_edges(nx_g_dashed, pos, ax=ax, width=widths, edge_color='grey', style='dashed', alpha=0.5) # draw solid edges if transitions is None: widths = [x[-1]['weight'] for x in nx_g_solid.edges(data=True)] widths = base_edge_width * np.array(widths) if min_edge_width is not None or max_edge_width is not None: widths = np.clip(widths, min_edge_width, max_edge_width) nx.draw_networkx_edges(nx_g_solid, pos, ax=ax, width=widths, edge_color='black') # draw directed edges else: adjacency_transitions = adata.uns['paga'][transitions].copy() if threshold is None: threshold = 0.005 adjacency_transitions.data[adjacency_transitions.data < threshold] = 0 adjacency_transitions.eliminate_zeros() g_dir = nx.DiGraph(adjacency_transitions.T) widths = [x[-1]['weight'] for x in g_dir.edges(data=True)] widths = 100 * base_edge_width * np.array(widths) if min_edge_width is not None or max_edge_width is not None: widths = np.clip(widths, min_edge_width, max_edge_width) nx.draw_networkx_edges(g_dir, pos, ax=ax, width=widths, edge_color='black', arrowsize=arrowsize) if export_to_gexf: if isinstance(colors[0], tuple): from matplotlib.colors import rgb2hex colors = [rgb2hex(c) for c in colors] for count, n in enumerate(nx_g_solid.nodes()): nx_g_solid.node[count]['label'] = str(node_labels[count]) nx_g_solid.node[count]['color'] = str(colors[count]) nx_g_solid.node[count]['viz'] = { 'position': { 'x': 1000 * pos[count][0], 'y': 1000 * pos[count][1], 'z': 0 } } filename = settings.writedir + 'paga_graph.gexf' logg.msg('exporting to {}'.format(filename), v=1) if settings.writedir != '' and not os.path.exists(settings.writedir): os.makedirs(settings.writedir) nx.write_gexf(nx_g_solid, settings.writedir + 'paga_graph.gexf') ax.set_frame_on(frameon) ax.set_xticks([]) ax.set_yticks([]) # groups sizes if (groups_key is not None and groups_key + '_sizes' in adata.uns): groups_sizes = adata.uns[groups_key + '_sizes'] else: groups_sizes = np.ones(len(node_labels)) base_scale_scatter = 2000 base_pie_size = (base_scale_scatter / (np.sqrt(adjacency_solid.shape[0]) + 10) * node_size_scale) median_group_size = np.median(groups_sizes) groups_sizes = base_pie_size * np.power(groups_sizes / median_group_size, node_size_power) # usual scatter plot if not isinstance(colors[0], dict): sct = ax.scatter(pos_array[:, 0], pos_array[:, 1], c=colors, edgecolors='face', s=groups_sizes, cmap=cmap) if fontsize is None: fontsize = rcParams['legend.fontsize'] for count, group in enumerate(node_labels): ax.text(pos_array[count, 0], pos_array[count, 1], group, verticalalignment='center', horizontalalignment='center', size=fontsize, fontweight=fontweight, **text_kwds) # else pie chart plot else: # start with this dummy plot... otherwise strange behavior sct = ax.scatter(pos_array[:, 0], pos_array[:, 1], c='white', edgecolors='face', s=groups_sizes, cmap=cmap) trans = ax.transData.transform bbox = ax.get_position().get_points() ax_x_min = bbox[0, 0] ax_x_max = bbox[1, 0] ax_y_min = bbox[0, 1] ax_y_max = bbox[1, 1] ax_len_x = ax_x_max - ax_x_min ax_len_y = ax_y_max - ax_y_min trans2 = ax.transAxes.inverted().transform pie_axs = [] for count, n in enumerate(nx_g_solid.nodes()): pie_size = groups_sizes[count] / base_scale_scatter x1, y1 = trans(pos[n]) # data coordinates xa, ya = trans2((x1, y1)) # axis coordinates xa = ax_x_min + (xa - pie_size / 2) * ax_len_x ya = ax_y_min + (ya - pie_size / 2) * ax_len_y # clip, the fruchterman layout sometimes places below figure if ya < 0: ya = 0 if xa < 0: xa = 0 pie_axs.append( pl.axes([xa, ya, pie_size * ax_len_x, pie_size * ax_len_y], frameon=False)) pie_axs[count].set_xticks([]) pie_axs[count].set_yticks([]) if not isinstance(colors[count], dict): raise ValueError( '{} is neither a dict of valid matplotlib colors ' 'nor a valid matplotlib color.'.format(colors[count])) color_single = colors[count].keys() fracs = [colors[count][c] for c in color_single] if sum(fracs) < 1: color_single = list(color_single) color_single.append('grey') fracs.append(1 - sum(fracs)) pie_axs[count].pie(fracs, colors=color_single) if node_labels is not None: for ia, a in enumerate(pie_axs): a.text(0.5, 0.5, node_labels[ia], verticalalignment='center', horizontalalignment='center', transform=a.transAxes, size=fontsize) return pos_array, sct
import os import matplotlib as mpl import matplotlib.pyplot as plt from matplotlib.collections import LineCollection import matplotlib.patches as mpatches from fa2 import ForceAtlas2 from curved_edges import curved_edges from collections import defaultdict import json import networkx as nx import sys from tqdm import tqdm import pickle from matplotlib.axes._subplots import Axes forceatlas2 = ForceAtlas2(gravity=5) def get_wallet_balances(blockchain): balances = defaultdict(float) for block in blockchain['blocks']: for transaction in block['transactions']: for i in transaction['inputs']: balances[i['address']] -= i['amount'] for o in transaction['outputs']: balances[o['address']] += o['amount'] return balances def get_user_user_transactions(blockchain, wallet_agent_map):
def _compute_pos( adjacency_solid, layout=None, random_state=0, init_pos=None, adj_tree=None, root=0, layout_kwds: Mapping[str, Any] = {}, ): import networkx as nx nx_g_solid = nx.Graph(adjacency_solid) if layout is None: layout = 'fr' if layout == 'fa': try: from fa2 import ForceAtlas2 except: logg.warning( "Package 'fa2' is not installed, falling back to layout 'fr'." 'To use the faster and better ForceAtlas2 layout, ' "install package 'fa2' (`pip install fa2`)." ) layout = 'fr' if layout == 'fa': np.random.seed(random_state) if init_pos is None: init_coords = np.random.random((adjacency_solid.shape[0], 2)) else: init_coords = init_pos.copy() forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=False, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.0, strongGravityMode=False, gravity=1.0, # Log verbose=False) if 'maxiter' in layout_kwds: iterations = layout_kwds['maxiter'] elif 'iterations' in layout_kwds: iterations = layout_kwds['iterations'] else: iterations = 500 pos_list = forceatlas2.forceatlas2( adjacency_solid, pos=init_coords, iterations=iterations) pos = {n: [p[0], -p[1]] for n, p in enumerate(pos_list)} elif layout == 'eq_tree': nx_g_tree = nx.Graph(adj_tree) pos = _utils.hierarchy_pos(nx_g_tree, root) if len(pos) < adjacency_solid.shape[0]: raise ValueError('This is a forest and not a single tree. ' 'Try another `layout`, e.g., {\'fr\'}.') else: # igraph layouts g = _sc_utils.get_igraph_from_adjacency(adjacency_solid) if 'rt' in layout: g_tree = _sc_utils.get_igraph_from_adjacency(adj_tree) pos_list = g_tree.layout( layout, root=root if isinstance(root, list) else [root]).coords elif layout == 'circle': pos_list = g.layout(layout).coords else: # I don't know why this is necessary np.random.seed(random_state) if init_pos is None: init_coords = np.random.random((adjacency_solid.shape[0], 2)).tolist() else: init_pos = init_pos.copy() # this is a super-weird hack that is necessary as igraphs layout function # seems to do some strange stuff, here init_pos[:, 1] *= -1 init_coords = init_pos.tolist() try: pos_list = g.layout( layout, seed=init_coords, weights='weight', **layout_kwds).coords except: # hack for excepting attribute error for empty graphs... pos_list = g.layout( layout, seed=init_coords, **layout_kwds).coords pos = {n: [p[0], -p[1]] for n, p in enumerate(pos_list)} if len(pos) == 1: pos[0] = (0.5, 0.5) pos_array = np.array([pos[n] for count, n in enumerate(nx_g_solid)]) return pos_array
from library_functions.config import Config except ModuleNotFoundError: from project.library_functions.config import Config # %% forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=0.5, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=5, strongGravityMode=False, gravity=1, # Log verbose=True, ) def get_fa2_layout( graph: nx.Graph, edge_weight_attribute: str = None, saved: str = None, save: str = None,
def forceatlas_graph(GU): # Color nodes according to party colors = [] for n in list(GU.nodes(data="Party")): if 'Republican' in n: colors.append('red') else: colors.append('blue') # Scale node-size according to degree d = nx.degree(GU) sizes = [(d[node] + 1) * 5 for node in GU.nodes()] # Color edges according to between-party or not edge_colors = [] for edge in GU.edges: if GU.nodes[edge[0]]['Party'] != GU.nodes[edge[1]]['Party']: edge_colors.append('grey') else: if GU.nodes[edge[0]]['Party'] == 'Republican': edge_colors.append('red') else: edge_colors.append('blue') # Specify the settings for the Force Atlas 2 algorithm forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=7.0, # Performance jitterTolerance=0.5, # Tolerance barnesHutOptimize=True, barnesHutTheta=40, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=0.5, strongGravityMode=False, gravity=0, # Log verbose=True) positions = forceatlas2.forceatlas2_networkx_layout(GU, pos=None, iterations=4000) plt.figure(num=None, figsize=(18, 9), dpi=85, facecolor='w', edgecolor='k') sns.set_style('whitegrid') sns.set_context('talk') # create legend plt.scatter([], [], c='red', alpha=0.7, s=100, label='Republican party') plt.scatter([], [], c='blue', alpha=0.7, s=100, label='Democrat party') plt.legend(scatterpoints=1, frameon=False, labelspacing=1) nx.draw_networkx_nodes(GU, positions, node_size=sizes, node_color=colors, alpha=0.5) nx.draw_networkx_edges(GU, positions, edge_color=edge_colors, alpha=0.08) ax = plt.gca() ax.collections[0].set_linewidth(0.1) ax.set_title('US House Representatives of 2020 network', fontsize=16) plt.axis('off') plt.savefig("./images/ForceAtlas_Graph.png", format="PNG") # plt.show() return GU