def group_people_js(request, mode="egograph", output="full"): """Return Belfast Group network graph data as JSON, for use with :meth:`group_people`. Optionally filter the data by minimum degree, if min_degree is specified as a url parameter. When generating the node and link data, nodes are annotated with degree, in degree, out degree, betweenness centrality, and eigenvector centrality if available. (In/out degree is only available for directed graphs.) :param mode: egograph: network information for a one- or two-degree egograph centered around the Belfast Group; groupsheet-model: alternate network graph based on the Group sheets themselves :param output: full: node and link data; adjacency: adjacency matrix, used for generating chord diagram """ if mode == "egograph": degree = request.GET.get("degree", 1) extra_opts = {} try: degree = int(degree) # currently only support 1 or 2 degree degree = max(1, min(degree, 2)) # NOTE: degree 2 graph is large enough that it *must* be filtered # to be sensible and usable on the webpage; # by trial & error, I found a minimum degree of 5 to be reasonable if degree == 2: extra_opts["min_degree"] = 5 except ValueError: # if a value is passed that can't be converted to int, fallback to 1 degree = 1 belfast_group = RdfOrganization(network_data().copy(), BELFAST_GROUP_URI) graph = belfast_group.ego_graph(radius=degree, types=["Person", "Organization"], **extra_opts) # annotate nodes in graph with degree # FIXME: not a directional graph; in/out degree not available graph = annotate_graph( graph, fields=["degree", "in_degree", "out_degree", "betweenness_centrality", "eigenvector_centrality"] ) elif mode == "groupsheet-model": graph = gexf.read_gexf(settings.GEXF_DATA["bg1"]) graph = annotate_graph( graph, fields=["degree", "betweenness_centrality", "eigenvector_centrality"] #'in_degree', 'out_degree', ) if output == "full": data = json_graph.node_link_data(graph) if output == "adjacency": # adjacency matrix for generating chord diagram matrix = nx.convert_matrix.to_numpy_matrix(graph) # NOTE: this also works, but as of networx 1.9 requires scipy # matrix = nx.linalg.graphmatrix.adjacency_matrix(graph) data = matrix.tolist() return HttpResponse(json.dumps(data), content_type="application/json")
def plot_decompose(r): ego_node = df_decompose.query( f'iteration == {r.iteration+1}')['tag'].iloc[0] print(r.iteration, ego_node, sp[ego_node]) g_node = gexf.read_gexf(r.filename) # sp1 = layout.kamada_kawai_layout(g_node) nx.draw(g_node, pos=sp, node_color='#0C84B6', node_size=5, with_labels=False) nx.draw_networkx_edges(g_node, pos=sp, alpha=0.04, edge_color='#D8E7F5') plt.text(sp[ego_node][0], sp[ego_node][1], r.tag, fontsize=8, bbox={ 'facecolor': 'white', 'edgecolor': 'none', 'alpha': 0.5 }) nx.draw_networkx_nodes(g_node, pos=sp, nodelist=[ego_node], node_size=10, node_color='r') plt.axis('off') # plt.show() plt.savefig('images/' + r.filename.replace('.gexf', '.png'), dpi=500) plt.show()
def gexf_content(request, mode): """Make network data available as GEXF files for download and use in tools like Gephi.""" if mode == "all": graph = network_data() elif mode == "group-people": # filtered graph of people/places/organizations used for # first BG network graph displayed on the site # - same data used in :meth:`full_js` graph = _network_graph() elif mode == "groupsheets": graph = gexf.read_gexf(settings.GEXF_DATA["bg1"]) buf = StringIO() gexf.write_gexf(graph, buf) response = HttpResponse(buf.getvalue(), content_type="application/gexf+xml") response["Content-Disposition"] = "attachment; filename=belfastgroup-%s.gexf" % mode return response
def egograph_node_info(request, id): """HTML snippet to provide information about a node in the egograph. Intended to be loaded and displayed via AJAX. Some overlap with :meth:`belfast.network.views.node_info`. """ # id is the person to whom this node is connected uri = local_uri(reverse("people:profile", args=[id]), request) g = rdf_data() ego_person = RdfPerson(g, rdflib.URIRef(uri)) # NOTE: some overlap here with networks node_info view # id param is the node we want information node_id = request.GET.get("id", None) if node_id is None: raise Http404 node_uri = rdflib.URIRef(node_id) # TODO: better to get relations from gexf or rdf ? graph = gexf.read_gexf(settings.GEXF_DATA["full"]) node = graph.node[node_id] context = {"node": node} if node.get("type", None) == "Person": # init rdf person person = RdfPerson(rdf_data(), rdflib.URIRef(node_id)) context["person"] = person # determine relation between node and ego-center rels = set(g.predicates(ego_person.identifier, node_uri)) # TODO: may want to display other relationships? # special case: if "mentions", should be a poem; find for display/link if rdfns.SCHEMA_ORG.mentions in rels: txts = set(g.subjects(rdfns.SCHEMA_ORG.mentions, node_uri)) - set([ego_person.identifier]) if txts: poems = [RdfPoem(g, p) for p in txts] # explicitly skip any non-poems, just in case context["poems"] = [p for p in poems if rdfns.FREEBASE["book/poem"] in p.rdf_types] return render(request, "network/node_info.html", context)
def node_info(request): """Return an HTML snippet with brief information about a node in the network (e.g., name, number of Group sheets, link to profile page if there is one). Intended to be called via AJAX and displayed with the network graphs. Expects a url parameter ``id`` with the node identifier. """ node_id = request.GET.get("id", None) # if no id is specified, 404 if node_id is None: raise Http404 # TODO: better to get from gexf or rdf ? graph = gexf.read_gexf(settings.GEXF_DATA["full"]) node = graph.node[node_id] context = {"node": node} if node.get("type", None) == "Person": # init rdf person person = RdfPerson(rdf_data(), rdflib.URIRef(node_id)) context["person"] = person # TODO: handle other types? location, organization return render(request, "network/node_info.html", context)
def load_graph(filepath): return gexf.read_gexf(filepath)
# %% import networkx as nx # from networkx.algorithms import centrality from networkx.readwrite import gexf import pandas as pd import matplotlib.pyplot as plt from networkx.drawing import layout ## https://networkx.github.io/documentation/networkx-1.10/reference/generated/networkx.drawing.nx_agraph.graphviz_layout.html # %% print('start') G = gexf.read_gexf('3mj/subgraph--1-start.gexf') print('generate layout') sp = layout.kamada_kawai_layout(G) degrees = pd.DataFrame(dict(G.degree).items(), columns=['tag', 'degree']) print(nx.__version__) print('before') print(nx.info(G)) nodes_zero_degree = (degrees.query('degree == 0')['tag'].to_list()) G.remove_nodes_from(nodes_zero_degree) print('after') print(nx.info(G)) # %% df_decompose = pd.read_csv('3mj/decomposed_3mj.csv')[[ 'iteration', 'tag', 'filename' ]]
# %% import networkx as nx from networkx.algorithms import centrality from networkx.algorithms import components from networkx.readwrite import gexf import pandas as pd import tqdm # import matplotlib.pyplot as plt # import scipy # %% G = gexf.read_gexf('data/outputs/tags-tags.gexf') print(nx.__version__) print(nx.info(G)) # %% def df_from_betweeness(inG): print(f'calculate betweenness, network of size {inG.order()}') temp_betweenness = centrality.betweenness_centrality(inG) return pd.DataFrame( temp_betweenness.items(), columns=['tag', 'betweenness']).sort_values('betweenness', ascending=False) # %% # calc betweenness for the first time and subgraph to remove nodes that have 0 betweeness df_betweenness = df_from_betweeness(G)
import networkx as nx from networkx.readwrite import gexf from networkx.readwrite import json_graph import json G = gexf.read_gexf("static/data/math3.gexf") # with open("static/data/middle_school_extend.json", "r") as read_file: # data = json.load(read_file) # G = json_graph.node_link_graph(data) print(nx.info(G)) # G.add_node('test1', modular=1, Degree=0, viz={'size': 50}, label='test1') # G.remove_node('test') print(G.nodes['Circle']) # print(G.nodes['test1']) print(nx.info(G)) # G = gexf.write_gexf(G, "static/data/middle_school_extend.gexf") data = json_graph.node_link_data(G) with open("static/data/middle_school_3.json", "w") as write_file: json.dump(data, write_file)
def network_data(): global _NX_GRAPH if _NX_GRAPH is None: _NX_GRAPH = gexf.read_gexf(settings.GEXF_DATA['full']) return _NX_GRAPH