def relayout_graph(self, name: str): """Расположить вершины графа по какому-то алгоритму. Алгоритмы: * circular - по кругу * kamada_kawai - Kamada-Kawai Algorithm * planar - без пересечений ребер * random - рандом * shell - пока то же, что circular * spring - Fruchterman-Reingold Algorithm :param name: :type name: str """ def kamada_kawai(G): return nx.kamada_kawai_layout(G, weight=1) # def spectral(G): # return nx.spectral_layout(G, scale=20) func_dict = { 'circular': nx.circular_layout, 'kamada_kawai': kamada_kawai, 'planar': nx.planar_layout, 'random': nx.random_layout, 'shell': nx.shell_layout, # TODO 'spring': nx.spring_layout, # 'spectral': spectral } scale_dict = { 'circular': 0.5, 'random': 0.3 } self.calculate_matrix() matrix = np.array(self.matrix) G = nx.from_numpy_matrix(matrix) # Получить networkx-граф из матрицы try: pos = func_dict[name](G) except nx.exception.NetworkXException: self.box = QMessageBox.critical(self.widget, 'Ошибка', 'Граф не планарен') return # Расчехлить позиции pos = np.array([pos[i] for i in range(len(pos))]) # Масштабировать scale = SupremeSettings()['graphmodule_graph_scale'] try: pos = nx.rescale_layout(pos, scale=scale * scale_dict[name]) except KeyError: pos = nx.rescale_layout(pos, scale=scale) # Применить позиции for index, position in enumerate(pos): x, y = position node = self._nodes[self.head[index]] if node != self.widget.scene().mouseGrabberItem(): node.setX(x) node.setY(y) self._adjust_scene()
def rescale_coords(pos, scale=1, center=0): node_list = pos.keys() # dict to array npos = np.row_stack((pos[x] for x in node_list)) npos = npos.astype(np.float64) npos = nx.rescale_layout(npos, scale=scale) + center # array to dict return dict(zip(node_list, npos))
def show(G: nx.DiGraph): scale = 1000 pos = graphviz_layout(G, prog='dot') new_pos = nx.rescale_layout(pos=np.array(list(pos.values())), scale=scale).tolist() for idx,key in enumerate(pos.keys()): pos[key] = new_pos[idx] nx.set_edge_attributes(G, 'color', 'r') labels = nx.get_node_attributes(G, 'fancy_label') nx.draw_networkx(G, pos=pos, arrows=True, labels=labels, edge_color='r' ) # plt.savefig(f"plot_{uuid.uuid4()}.png", dpi=1000) plt.show()
def layout(self): """Initialize the CausalModel object by reading the information from the dot file with the passed path. The file should be a `dot` file and if it contains multiple graphs, only the first such graph is returned. All graphs _except_ the first are silently ignored. Parameters ---------- path : str or file Filename or file handle. Returns ------- None Examples -------- >>> G = CausalModel() >>> G.load_model('temp.dot') Notes ----- The heavy lifting is done by `networkx.drawing.nx_pydot.read_dot` """ pos = graphviz_layout(self.dag, 'dot') keys = list(pos.keys()) coords = np.array([pos[key] for key in keys]) coords = nx.rescale_layout(coords, 1) pos = dict(zip(keys, coords)) xs = [] ys = [] for key, value in pos.items(): xs.append(value[0]) ys.append(value[1]) # All xx coordinates are the same, switch x and y # To make it horizontal instead of vertical if len(set(xs)) == 1: pos = {key: [-value[1], value[0]] for key, value in pos.items()} return pos
def rescaleCoordinate(self, X, Y, scale): coordinates = np.array([[X, Y]]) return (nx.rescale_layout(coordinates, scale))
degrees = dict() for node, val in g.degree(): degrees[node] = val ids = list(g.nodes()) x = [] y = [] degree = [] for elem in ids: degree.append(degrees[elem]) x.append(pos[elem][0]) y.append(pos[elem][1]) p = empty(shape=(len(x), 2)) p[:, 0] = asarray(x) p[:, 1] = asarray(y) scale = canvas_size // 2 - padding pos_new = nx.rescale_layout(p, scale=scale) pos = dict() for i in range(len(ids)): pos[ids[i]] = (pos_new[i][0], pos_new[i][1]) x[i] = pos_new[i][0] + scale + padding y[i] = pos_new[i][1] + scale + padding conf_list_n = {Id: (X, Y, Degree) for Id, X, Y, Degree in zip(ids, x, y, degree)} max_weight = 4 time_desease = dict() for i in ids: time_desease[i] = 2
def fruchterman_reingold_layout( G, k=None, pos=None, fixed=None, iterations=50, threshold=1e-4, weight="weight", scale=1, center=None, dim=2, seed=None, min_dist=0.01, ): """Position nodes using Fruchterman-Reingold force-directed algorithm. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. k : float (default=None) Optimal distance between nodes. If None the distance is set to 1/sqrt(n) where n is the number of nodes. Increase this value to move nodes farther apart. pos : dict or None optional (default=None) Initial positions for nodes as a dictionary with node as keys and values as a coordinate list or tuple. If None, then use random initial positions. fixed : list or None optional (default=None) Nodes to keep fixed at initial position. iterations : int optional (default=50) Maximum number of iterations taken threshold: float optional (default = 1e-4) Threshold for relative error in node position changes. The iteration stops if the error is below this threshold. weight : string or None optional (default='weight') The edge attribute that holds the numerical value used for the edge weight. If None, then all edge weights are 1. scale : number (default: 1) Scale factor for positions. Not used unless `fixed is None`. center : array-like or None Coordinate pair around which to center the layout. Not used unless `fixed is None`. dim : int Dimension of layout. seed : int, RandomState instance or None optional (default=None) Set the random state for deterministic node layouts. If int, `seed` is the seed used by the random number generator, if numpy.random.RandomState instance, `seed` is the random number generator, if None, the random number generator is the RandomState instance used by numpy.random. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> G = nx.path_graph(4) >>> pos = nx.spring_layout(G) # The same using longer but equivalent function name >>> pos = nx.fruchterman_reingold_layout(G) """ if center is None: center = np.zeros(dim) lg = len(G) if not lg: return {} if lg == 1: return {nx.utils.arbitrary_element(G.nodes()): center} nfixed = dict(zip(G, range(len(G)))) if fixed is not None: fixed = np.asarray([nfixed[v] for v in fixed]) if pos is not None: # Determine size of existing domain to adjust initial positions dom_size = max(coord for pos_tup in pos.values() for coord in pos_tup) if dom_size == 0: dom_size = 1 pos_arr = seed.rand(len(G), dim) * dom_size + center for i, n in enumerate(G): if n in pos: pos_arr[i] = np.asarray(pos[n]) else: pos_arr = None A = nx.to_numpy_array(G, weight=weight) if k is None and fixed is not None: # We must adjust k by domain size for layouts not near 1x1 nnodes, _ = A.shape k = dom_size / np.sqrt(nnodes) # Cycles cycles = [[nfixed[x] for x in c] for c in nx.cycle_basis(G)] # pos = _fruchterman_reingold( A, k, pos_arr, fixed, iterations, threshold, dim, seed, min_dist, cycles ) if fixed is None: pos = nx.rescale_layout(pos, scale=scale) + center pos = dict(zip(G, pos)) return pos
def rescale_nx_pos(self): """Devuelve una nueva escala para las coordenadas de los nodos en el dibujo del grafo""" self.pos = nx.rescale_layout(g, pos = self.pos)
def draw_graph(graph, labels=None, graph_layout='reingold', #please don't change this node_size=500, #size of data dots node_color='#2c8ca4', #hex code or word like 'yellow' node_alpha=0.5, #opacity of dots node_text_size=5, #size of text. edge_color='#fcd454', edge_alpha=0.2, edge_tickness=1, edge_text_pos=0.3, text_font='sans-serif'): # create networkx graph G=nx.Graph() # add edges for edge in graph: G.add_edge(edge[0], edge[1]) #takes edge from edge list G (see below) # these are different layouts for the network you may try # use reingold!! if graph_layout == 'spring': graph_pos=nx.spring_layout(G) elif graph_layout == 'spectral': graph_pos=nx.spectral_layout(G) elif graph_layout == 'random': graph_pos=nx.random_layout(G) elif graph_layout == 'bipartite': graph_pos = nx.bipartite_layout(G, nodes=effortlist, align='vertical') elif graph_layout == 'circular': graph_pos=nx.circular_layout(G) elif graph_layout == 'kawai': graph_pos=nx.kamada_kawai_layout(G) elif graph_layout == 'rescale': graph_pos=nx.rescale_layout(G) elif graph_layout == 'reingold': #USE THIS ONE graph_pos=nx.fruchterman_reingold_layout(G, pos=GraphPositions, fixed=all_node_list) else: graph_pos=nx.shell_layout(G) # draw graph #modified to assigned colors/sizes on nodes of each information category (bias, effort, tech) nx.draw_networkx_nodes(G,graph_pos,nodelist=effortlist,node_size=node_size, alpha=node_alpha, node_color='black') #assign color/size/opacity to 'effort' nodes nx.draw_networkx_nodes(G, graph_pos, nodelist=techlist, node_size=300, alpha=node_alpha, node_color='#545454') #assign color/size/opacity to 'tech' nodes nx.draw_networkx_nodes(G, graph_pos, nodelist=biaslist, node_size=200, alpha=node_alpha, node_color=node_color) #assign color/size/opacity to 'bias' nodes nx.draw_networkx_edges(G,graph_pos,width=edge_tickness, alpha=edge_alpha,edge_color=edge_color) nx.draw_networkx_labels(G, graph_pos,font_size=node_text_size, font_family=text_font) #below is for edge labels, which I removed from the edges #if labels is None: # labels = range(len(graph)) #edge_labels = dict(zip(graph, labels)) #nx.draw_networkx_edge_labels(G, graph_pos, edge_labels=edge_labels, # label_pos=edge_text_pos) # show graph plt.show()