def make_graph(interaction, score): G_flat = G_to_flat(G, score) if interaction == "all": # if no interaction is selected, use full graph G_cyto = nx.cytoscape_data(G_flat) weights = [d["weight"] for u, v, d in G_flat.edges(data=True)] # prepare data for network graph nodes = G_cyto["elements"]["nodes"] edges = G_cyto["elements"]["edges"] elements = nodes + edges return elements, min(weights), max(weights), np.mean(weights) else: # an interaction is selected, select only that interaction G_split = cn.graph.split_graph(G) G_split_flat = G_to_flat(G_split[interaction], score) G_cyto = nx.cytoscape_data(G_split_flat) weights = [ d["weight"] for u, v, d in G_split_flat.edges(data=True) ] # prepare data for network graph nodes = G_cyto["elements"]["nodes"] edges = G_cyto["elements"]["edges"] elements = nodes + edges return elements, min(weights), max(weights), np.mean(weights)
def create_elements_from_graph(G): cytoscape_data_format = nx.cytoscape_data(G) nodes = cytoscape_data_format["elements"]["nodes"] edges = cytoscape_data_format["elements"]["edges"] elements = nodes + edges return elements
async def respond_cytoscape( gen: AsyncIterator[JsonElement]) -> AsyncGenerator[str, None]: # Note: this is a very inefficient way of creating a response, since it creates the graph in memory # on the server side, so we can reuse the networkx code. # This functionality can be reimplemented is a streaming way. graph = await result_to_graph( gen, lambda js: value_in_path_get(js, NodePath.reported, {})) yield json.dumps(cytoscape_data(graph))
def graph_to_cyto(G: nx.DiGraph) -> dict: """Returns data in Cytoscape JSON format (cyjs), according to nx.cytoscape_data(G) Returns ------- data: dict A dictionary with cyjs formatted data. Raises ------ NetworkXError If values in attrs are not unique. """ return nx.cytoscape_data(G)
def export(self, root=None): if self.graph_type is 'node_link': graph_json = nx.node_link_data(self.graph) elif self.graph_type is 'cytoscape': graph_json = nx.cytoscape_data(self.graph) elif self.graph_type is 'tree': if nx.is_directed(self.graph): graph_json = nx.tree_data(self.graph, root) else: print('Graph passed into export data is not directed') return 0 return graph_json
def from_graph(self, graph_obj): """Initialize from a networkx graph object. Args: graph_obj (nx.Graph): a graph object. """ if not graph_obj.size(): logger.warning("Unable to load graph from an empty graph object.") return self.resource_data = nx.cytoscape_data(graph_obj) self._graph = graph_obj self._name = "" self._description = "From a graph object." time = datetime.datetime.now(datetime.timezone.utc) self._created_at = time self._updated_at = time
def create_graph(G): cytoscape_data_format = nx.cytoscape_data(G) nodes = cytoscape_data_format["elements"]["nodes"] edges = cytoscape_data_format["elements"]["edges"] app = dash.Dash(__name__) app.layout = html.Div([ cyto.Cytoscape(id='cytoscape-two-nodes', layout={'name': 'circle'}, style={ 'width': '100%', 'height': '1400px' }, elements=nodes + edges) ]) app.run_server(debug=True)
def build_g(original_G_path, list_of_hosts, list_of_viruses): # -------------------------------------------------------- # --------------------Build the network--------------------- # -------------------------------------------------------- # Initialize directed network G = nx.Graph() # initialize a dict {virus: virus proteins} dict_of_belong_relations = {host: [] for host in list_of_hosts} dict_of_belong_relations.update({host: [] for host in list_of_viruses}) # initialize list of nodes groups and edge groups dict_of_nodes_groups, dict_of_edges_groups = {'virus': {}, 'host protein': {}, 'virus protein': {}, 'host': {}}, \ {'virus': {}, 'host protein': {}, 'virus protein': {}, 'host': {}} # fill in these two nested dictionaries by building h**o graphs bd.build_home_graph(G, dict_of_nodes_groups=dict_of_nodes_groups, dict_of_edges_groups=dict_of_edges_groups, file_dir=file_dir, belong_relation_dict=dict_of_belong_relations) # heterogeneous edges hetero_edges = [] bd.build_original_hetero_edges(G, hetero_edges, dict_of_belong_relations, dict_of_nodes_groups, list_of_viruses) # convert to and store cytoscape needed format # print("Saving to cytoscape required json\n") json_cyto = nx.cytoscape_data(G) with open('data/cytoscape/cytoscape_undirected_original.json', 'w') as json_file: json.dump(json_cyto, json_file) nx.write_gml(G, original_G_path) print('original network saved!') print("network building finished!")
def save_graph(self, is_needed, df, graph, name): if is_needed: if not os.path.isdir("data/graphs/" + name): os.mkdir("data/graphs/" + name) df.to_csv("data/graphs/%s/%s.tsv" % (name, name), sep="\t") nx.write_gpickle(graph, "data/graphs/%s/%s.gpickle" % (name, name)) nx.write_adjlist(graph, "data/graphs/%s/%s.adjlist" % (name, name), delimiter="\t") nx.write_multiline_adjlist( graph, "data/graphs/%s/%s.multiline_adjlist" % (name, name), delimiter="\t", ) nx.write_edgelist(graph, "data/graphs/%s/%s.edgelist" % (name, name), delimiter="\t") with open("data/graphs/%s/%s.cyjs" % (name, name), "w") as outfile: outfile.write(json.dumps(nx.cytoscape_data(graph), indent=2)) graph = stringify_list_attributes(graph) nx.write_gexf(graph, "data/graphs/%s/%s.gexf" % (name, name)) nx.write_graphml(graph, "data/graphs/%s/%s.graphml" % (name, name))
def visualize_in_cytoscape(): full_G = nx.read_gml(os.path.abspath('./data/classifier/original_G.txt')) with open( os.path.abspath('./data/prediction/prediction_IMSP_interacts.csv'), 'r') as int_pred: PPI_csv = csv.reader(int_pred, delimiter=',') for row in PPI_csv: if row[7] == 'likely': if full_G.has_edge(str(row[0]), str(row[1])): print(row[0], row[1]) full_G.add_edge(str(row[0]), str(row[1]), etype='predicted', relation='interacts', probability_estimate=row[4], connection=row[5]) int_pred.close() with open(os.path.abspath('./data/prediction/prediction_IMSP_infects.csv'), 'r') as inf_pred: inf_csv = csv.reader(inf_pred, delimiter=',') for row in inf_csv: if row[6] == 'likely': if full_G.has_edge(str(row[0]), str(row[1])): print(row[0], row[1]) full_G.add_edge(str(row[0]), str(row[1]), etype='predicted', relation='infects', probability_estimate=row[4], connection=row[5]) inf_pred.close() json_cyto = nx.cytoscape_data(full_G) with open('data/cytoscape/cytoscape_with_prediction.json', 'w') as json_file: json.dump(json_cyto, json_file)
ResultSet = connection.execute(base).fetchall() base_db = pd.DataFrame(ResultSet) base_db.columns = ResultSet[0].keys() #base usada para o grafo f = lambda x: pd.DataFrame(list(combinations(x.values, 2)), columns=['ingredientA', 'ingredientB']) edges = (base_db[['recipe_id', 'ingredient' ]].groupby('recipe_id')['ingredient'].apply(f).reset_index( level=1, drop=True).reset_index()) edges2 = edges.groupby(['ingredientA', 'ingredientB' ]).size().reset_index().rename(columns={0: 'count'}) edges3 = edges2.loc[edges2['count'] > 200].reset_index() edges4 = pd.concat([ edges3, edges3.loc[edges3['ingredientA'] == edges3['ingredientB']] ]).drop_duplicates(keep=False) #selecionamos apenas as conexões que ocorrem mais de duzentas vezes, para garantir que o grafo seja leve e facilmente #visualizável G = nx.Graph() G = nx.from_pandas_edgelist(edges4, 'ingredientA', 'ingredientB', ['count']) with open('../food.json', 'w') as f: f.write(json.dumps(nx.cytoscape_data(G))) #geração do grafo a partir dos dados
for d in docs: human_gene_lookup[d['subject_label']] = d['subject'] retval = symbol if symbol in human_gene_lookup: retval = human_gene_lookup[symbol] return retval table = pd.read_csv(sys.argv[1], sep='\t') graph = nx.MultiDiGraph() for index, row in table.iterrows(): n1 = row['gene1'] n1_curie = map_symbol_to_gene(n1) n2 = row['gene2'] n2_curie = map_symbol_to_gene(n2) n1_props = {'gene1 perturbation': row['gene1 perturbation']} n2_props = {'gene2 perturbation': row['gene2 perturbation']} publication = f'PMID:{row["PMID"]}' edge_props = {'edge_label': 'regulates', 'relation': 'RO:0002211', 'publications': [publication], 'cancer_type_tested': row['cancer type tested'], 'synthetic_lethality': bool(row['SL'])} graph.add_node(n1_curie, **n1_props) graph.add_node(n2_curie, **n2_props) graph.add_edge(n1_curie, n2_curie, **edge_props) OUTSTREAM = open('output.cytoscape.json', 'w') nx_data = nx.cytoscape_data(graph) nx_data_json = json.dumps(nx_data) OUTSTREAM.write(nx_data_json)
def _export_to_cyjs(self, filename: str): """Save the network in cyjs format.""" graph = nx.cytoscape_data(self.graph) return self._write_to_json(graph, filename)
def Graph2CYJS(G, ofile): cyjs = nx.cytoscape_data(G) fout.write(json.dumps(cyjs, indent=2))
def network_save(gg, ppath): # nx.write_gpickle(gg, ppath) cyjs = nx.cytoscape_data(gg) with open(ppath, 'w') as fds: json.dump(cyjs, fds)
is_largest = edge_record['properties']['properties']['islargest'] overlap_ratio = edge_record['properties']['properties']['ratio'] G[source_node][target_node]['unique_label'] = unique_label G[source_node][target_node]['is_largest'] = is_largest G[source_node][target_node]['overlap_ratio'] = overlap_ratio #G[source_node][target_node]['modulation_type'] = 'NA' elif edge_type == 'POTENT_PATTERN_OF': unique_label = edge_record['properties']['properties']['unique_label'] G[source_node][target_node]['unique_label'] = unique_label #G[source_node][target_node]['modulation_type'] = 'NA' else: print('[ERROR] Invalid edge type detected: %s' % (edge_type)) sys.exit(-1) #G.add_node(uuid) #print (node_record) #print (G) j = nx.cytoscape_data(G, attrs=None) with open(fname_out, 'w+') as outfile: json.dump(j, outfile) print('[Done.]')
def Visualize(importance, graph, disease, resultDir, dbAdapter=None): #print(resultDir) #exit() #get shortest paths # make the graph, dump it to JSON, save that in an HTML template with our formatting #firstFeature = importance.most_common()[4] #print(firstFeature[0]) firstFeature = importance # this parameter will change based on the features ... we will need the name saving ability here... # maybe we can test the disease list feature as well nodesInGraph = set() #cutoff = 3 #print(firstFeature) middleNode = firstFeature[0] if ProteinInteractionNode.isThisNode(firstFeature[0]): #print("THIS IS INT",firstFeature[0]) middleNode = int(middleNode) #cutoff = 2 cutoff = FindCutoff(graph, disease, middleNode) print("here is the cuttoffe", cutoff) for path in nx.all_simple_paths(graph, source=disease, target=middleNode, cutoff=cutoff): #print(path) nodesInGraph |= set(path) #print('hehe',list(nx.all_simple_paths(graph, source=disease, target=firstFeature[0], cutoff=4))) #if len(list(nx.all_simple_paths(graph, source=disease, target=middleNode, cutoff=cutoff))) == 0: # raise Exception('WARNING- {0} cannot be visualized to {1}, no paths'.format(middleNode,disease)) #print("ALL",nodesInGraph) if dbAdapter is None: dbAdapter = OlegDB() niceLabels = convertLabels(list(nodesInGraph), dbAdapter, selectAsDF, type='graph') #print(11268 in list(nodesInGraph)) #print('11268' in list(nodesInGraph)) finalGraph = graph.subgraph(list(nodesInGraph)) #print(type(nx.cytoscape_data(finalGraph)),nx.cytoscape_data(finalGraph) #print(niceLabels[11268]) cytoscapeDump = nx.cytoscape_data(finalGraph) #print("this is data",cytoscapeDump['data']) #print("this is E",cytoscapeDump['elements']) #print(len(cytoscapeDump['elements']['nodes'])) #print(len(cytoscapeDump['elements']['edges'])) #cytoscapeDump['elements']['edges'] = cytoscapeDump['elements']['edges'][:10] for k, n in enumerate(cytoscapeDump['elements']['nodes']): cytoscapeDump['elements']['nodes'][k]['data']['name'] = niceLabels[ n['data']['value']] if ProteinInteractionNode.isThisNode( n['data']['value']): #isinstance(n['data']['value'],int): cytoscapeDump['elements']['nodes'][k]['data']['value'] = str( n['data']['value']) dataOut = str(cytoscapeDump).replace("True", "true").replace("False", "false")[:-1] #for key in niceLabels.keys(): #print(key,niceLabels[key]) #dataOut = dataOut.replace(str(key),str(niceLabels[key])) header = """ <style type="text/css"> .disease { background-color: blue; color: blue; } </style> <!--cy.getElementById("GO:0016323").addClass()--> <script type="text/javascript" src=https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.7.3/cytoscape.min.js></script> <script src="https://unpkg.com/layout-base/layout-base.js"></script> <script src="https://unpkg.com/avsdf-base/avsdf-base.js"></script> <script type="text/javascript" src="https://ivis-at-bilkent.github.io/cytoscape.js-avsdf/cytoscape-avsdf.js"></script> <div id="cy" style="width:900px; height:750px; border-style: solid"> </div> """ + firstFeature[0] + """ <script type="text/javascript"> data = """ #, # 'style': [{ # selector: "node", # css: { # label: "data(name)" # } #}] #}; footer = """ ,'container':document.getElementById('cy') , 'style': [{ selector: "node", css: { label: "data(name)" } }] }; var cy = cytoscape(data); let options = { name: 'avsdf', //'breadthfirst', fit: false, // whether to fit the viewport to the graph directed: false, // whether the tree is directed downwards (or edges can point in any direction if false) padding: 30, // padding on fit nodeSep: 40, circle: false, // put depths in concentric circles if true, put depths top down if false grid: false, // whether to create an even grid into which the DAG is placed (circle:false only) spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap) boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm roots: undefined, // the roots of the trees maximal: false, // whether to shift nodes down their natural BFS depths in order to avoid upwards edges (DAGS only) animate: false, // whether to transition the node positions animationDuration: 500, // duration of animation in ms if enabled animationEasing: undefined, // easing of animation if enabled, animateFilter: function ( node, i ){ return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts ready: undefined, // callback on layoutready stop: undefined, // callback on layoutstop transform: function (node, position ){ return position; } // transform a given node position. Useful for changing flow direction in discrete layouts }; cy.layout(options).run(); //cy.$('#j, #e').addClass('foo'); ## ADD A CLASS TO THE MP nodes, and their label // * // here we can build a harness that will color the nodes, and set edge weights? // the more this map is annotated, tbe better function isMPNode(input) { if(input[0]+input[1] == "MP") { return true; } return false; } function isGoNode(input) { if(input[0]+input[1] == "GO") { return true; } return false; } function isNotProteinOrMP(input) { if(input.length > 5) { return true && !isMPNode(input); } return false; } function edgeHasNode(inputEdge,nodeCheck) { if(nodeCheck(inputEdge.source) || nodeCheck(inputEdge.target)) { return true } else { return false } } for(var node of Object.values(cy.nodes())) { //console.log(node) if(node.id) { //cy.getElementById(id).style('label',id) var id = node.id() //console.log(id); if(isMPNode(id)) { cy.getElementById(id).style('background-color','#0081CF') } else if(id.length > 5) { cy.getElementById(id).style('background-color','lightgreen') } else { cy.getElementById(id).style('background-color','rgb(0, 149, 149)') } } //node.addClass("disease") } // for each edge in the graph, if its got an association, color that, if its got a combined score, color that for(var edge of Object.values(cy.edges())) { if(edge.data && edge.data().association != undefined) { console.log(edge.data().association) if(edge.data().association) { edge.style('line-color','#00C9A7'); edge.style('width','12px'); edge.style('label','KNOWN POSITIVE ASSOCIATION'); edge.style('text-rotation','autorotate') } else { //edge.style('line-color','#FF6F91'); //edge.style('width','3px'); var data = edge.data(); var noderemove = null; if(isMPNode(data.source)) { noderemove = data.target; } else { noderemove = data.source; } cy.remove(edge) cy.remove(cy.getElementById(noderemove)) } } else { if(edge.data) { if(edgeHasNode(edge.data(),isNotProteinOrMP)){ edge.style('line-color','lightgreen') edge.style('width','6px'); } else if(edgeHasNode(edge.data(),isMPNode)){ edge.style('line-color','lightblue') edge.style('label','') edge.style('width','6px'); } else { var score = parseFloat(edge.data().combined_score)/1000.0 edge.style('line-color','#444') console.log(parseFloat(edge.data().combined_score)/1000.0,score) edge.style('opacity',score.toString()) edge.style('width','5%'); edge.style('line-style','dotted') } } //console.log("NO!",edge) } } cy.layout(options).run(); //for(var edge in nod) </script> """ #outDir = "results/graphs" #if not os.path.exists(outDir): # os.mkdir(outDir) filePath = resultDir + "/{0}{1}{2}.html".format(str( firstFeature[0]), str(int(time.time())), disease) text_file = open(filePath, "w") text_file.write(header + dataOut + footer) text_file.close() print("Output visualization file: {0}".format(filePath))
from flask import Flask, render_template, json, jsonify, request, redirect, url_for import networkx as nx from json import dumps # first convert graph into cytoscape graph, with node weights = sum of all outgoing edge weights file = "NELA_FullNetwork_2019.gexf" #file = "InDegreeWeightedNormalizedFullNetwork.gexf" #file = "RawWeightsJulyNetwork.gexf" G = nx.read_gexf(file) for node in G.nodes(): G.nodes[node]['weight'] = G.out_degree(node, 'weight') graph = nx.cytoscape_data(G) graph = dumps(graph) print(graph) # Initialize Flask app = Flask(__name__) @app.route("/") def index(): global graph return render_template("index.html", graph=graph) if __name__ == "__main__": app.run() # uncomment lines below to write graph with node weights = sum of all outgoing edge weights as json file # use this file with cytoscape desktop
def write_cytoscape(G, filename): cs = nx.cytoscape_data(G) with open(filename, 'w') as fo: fo.write(json.dumps(cs))
def graph(G, mode="external", **kwargs): """ G: a multidirectional graph kwargs are passed to the Jupyter_Dash.run_server() function. Some usefull arguments are: mode: "inline" to run app inside the jupyter nodebook, default is external debug: True or False, Usefull to catch errors during development. """ import dash from jupyter_dash import JupyterDash import dash_cytoscape as cyto from dash.dependencies import Output, Input import dash_html_components as html import dash_core_components as dcc import dash_table import networkx as nx import scConnect as cn import plotly.graph_objs as go import plotly.io as pio import pandas as pd import numpy as np import json import matplotlib import matplotlib.pyplot as plt pio.templates.default = "plotly_white" cyto.load_extra_layouts() JupyterDash.infer_jupyter_proxy_config() app = JupyterDash(__name__) server = app.server # Add a modified index string to change the title to scConnect app.index_string = ''' <!DOCTYPE html> <html> <head> {%metas%} <title>scConnect</title> {%favicon%} {%css%} </head> <body> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </body> </html> ''' # Add colors to each node nodes = pd.Categorical(G.nodes()) # make a list of RGBA tuples, one for each node colors = plt.cm.tab20c(nodes.codes / len(nodes.codes), bytes=True) # zip node to color color_map_nodes = dict(zip(nodes, colors)) # add these colors to original graph for node, color in color_map_nodes.items(): G.nodes[node]["color"] = color[0:3] # Save only RGB # Add colors to edges(source node color) for G for u, v, k in G.edges(keys=True): G.edges[u, v, k]["color"] = color_map_nodes[u][0:3] # load graph into used formes def G_to_flat(G, weight): G_flat = cn.graph.flatten_graph(G, weight=weight, log=True) # Add colors to edges(source node color) for G_flat for u, v, in G_flat.edges(): G_flat.edges[u, v]["color"] = color_map_nodes[u][0:3] return G_flat # produce full graph variante to extract metadata G_flat = G_to_flat(G, weight="score") G_split = cn.graph.split_graph(G) # find and sort all found interactions interactions = list(G_split.keys()) interactions.sort() G_cyto = nx.cytoscape_data(G_flat) # get min and max weight for all edges for flat and normal graph #weights = [d["weight"] for u, v, d in G_flat.edges(data=True)] scores = [d["score"] for u, v, d in G.edges(data=True)] cent = [d["centrality"] for n, d in G.nodes(data=True)] # prepare data for network graph nodes = G_cyto["elements"]["nodes"] elements = [] # collect all available genes genes = list(nodes[0]["data"]["genes"].keys()) # Styling parameters font_size = 20 # Style for network graph default_stylesheet = [{ 'selector': 'node', 'style': { 'background-color': 'data(color)', 'label': 'data(id)', 'shape': 'ellipse', 'opacity': 1, 'font-size': f'{font_size}', 'font-weight': 'bold', 'text-wrap': 'wrap', 'text-max-width': "100px", 'text-opacity': 1, 'text-outline-color': "white", 'text-outline-opacity': 1, 'text-outline-width': 2 } }, { 'selector': 'node:selected', 'style': { 'background-color': 'data(color)', 'label': 'data(id)', 'shape': 'ellipse', 'opacity': 1, 'border-color': "black", 'border-width': "5" } }, { 'selector': 'edge', 'style': { 'line-color': 'data(color)', "opacity": 0.7, "curve-style": "unbundled-bezier", "width": "data(weight)", "target-arrow-shape": "vee", "target-arrow-color": "black", 'z-index': 1, 'font-size': f'{font_size}' } }, { 'selector': 'edge:selected', 'style': { 'line-color': 'red', 'line-style': "dashed", 'opacity': 1, 'z-index': 10, } }] app.layout = html.Div( className="wrapper", children=[ # wrapper html.Div( className="header", children=[ # header html.Img(src="assets/logo.png", alt="scConnect logo"), html.Div( className="graph-info", id="graph-stat", children=[ html. H3(f'Loaded graph with {len(G.nodes())} nodes and {len(G.edges())} edges' ) ]) ]), html.Div( className="network-settings", children=[ # network settings html.H2("Network settings", style={"text-align": "center"}), html.Label("Interactions"), dcc.Dropdown(id="network-interaction", options=[{ 'label': "all interactions", 'value': "all" }] + [{ 'label': interaction, 'value': interaction } for interaction in interactions], value="all"), # select if only significant ligands and receptors should be shown html.Label("Graph weight:"), dcc.RadioItems(id="weight-select", options=[{ "label": "Score", "value": "score" }, { "label": "Log score", "value": "log_score" }, { "label": "Specificity", "value": "specificity" }, { "label": "Importance", "value": "importance" }], value="importance", labelStyle={ 'display': 'block', "margin-left": "50px" }, style={ "padding": "10px", "margin": "auto" }), html.Label("Graph Layout"), dcc.Dropdown( id="network-layout", options=[{ 'label': name.capitalize(), 'value': name } for name in [ 'grid', 'random', 'circle', 'cose', 'concentric', 'breadthfirst', 'cose-bilkent', 'cola', 'euler', 'spread', 'dagre', 'klay' ]], value="circle", clearable=False), html.Label("Weight Filter", style={ "paddingBottom": 500, "paddingTop": 500 }), dcc. Slider( # min, max and value are set dynamically via a callback id="network-filter", step=0.001, updatemode="drag", tooltip={ "always_visible": True, "placement": "right" }, ), html.Label("Node size"), dcc.RangeSlider(id="node-size", value=[10, 50], min=0, max=100, updatemode="drag"), html.Label("Select gene"), dcc.Dropdown( id="gene_dropdown", options=[{ "label": gene, "value": gene } for gene in genes], clearable=True, placeholder="Color by gene expression", ), # Store node colors "hidden" for gene expresison html.Div(id="node-colors", style={"display": "none"}, children=[""]), html.Div(id="min-max", children=[]), # Click to download image of network graph html.Button(children="Download current view", id="download-network-graph", style={"margin": "10px"}) ]), # end network settings html.Div( id="network-graph", className="network-graph", children=[ # network graph html.H2("Network graph", style={"text-align": "center"}), cyto.Cytoscape(id="cyto-graph", style={ 'width': '100%', 'height': '80vh' }, stylesheet=default_stylesheet, elements=elements, autoRefreshLayout=True, zoomingEnabled=False) ]), # end network graph html.Div( className="sankey-settings", children=[ # network settings html.H2("Sankey Settings", style={"text-align": "center"}), html.Label("Weight Filter"), dcc.Slider(id="sankey-filter", min=min(scores), max=max(scores), value=0.75, step=0.001, updatemode="drag", tooltip={ "always_visible": True, "placement": "right" }), html.Label("Toggle weighted"), dcc.RadioItems(id="sankey-toggle", options=[{ "label": "Score", "value": "score" }, { "label": "Log score", "value": "log_score" }, { "label": "Specificity", "value": "specificity" }, { "label": "Importance", "value": "importance" }], value="importance", labelStyle={"display": "block"}) ]), # end network settings html.Div( className="sankey", id="sankey", children=[ # sankey graph html.H2("Sankey graph", style={"text-align": "center"}), dcc.Graph(id="sankey-graph") ]), # end sankey graph html.Div( className="interaction-list", children=[ # interaction list html.Div(id="selection", children=[ html.H2("Interactions", style={"text-align": "center"}), html.H3(id="edge-info", style={"text-align": "center"}), dcc.Graph(id="interaction-scatter"), html.Div(id="interaction-selection", style={"display": "none"}, children=[""]) ]), html.Div(children=[ dash_table.DataTable( id="edge-selection", page_size=20, style_table={ "overflowX": "scroll", "overflowY": "scroll", "height": "50vh", "width": "95%" }, style_cell_conditional=[{ "if": { "column_id": "interaction" }, "textAlign": "left" }, { "if": { "column_id": "receptorfamily" }, "textAlign": "left" }, { "if": { "column_id": "pubmedid" }, "textAlign": "left" }], style_header={ "fontWeight": "bold", "maxWidth": "200px", "minWidth": "70px" }, style_data={ "maxWidth": "200px", "minWidth": "70px", "textOverflow": "ellipsis" }, sort_action="native", fixed_rows={ 'headers': True, 'data': 0 }) ]) ]), # end interaction list html.Div( className="L-R-scores", children=[ # ligand and receptor lists html.H2("Ligand and receptors", style={"text-align": "center"}), html.Div(children=[ html.H3( id="selected-node", style={"text-align": "center"}, children=["Select a node in the notwork graph"]), html.Label("Search for ligands and receptors:", style={"margin-right": "10px"}), dcc.Input(id="filter_l_r", type="search", value="", placeholder="Search") ]), dcc.Tabs([ dcc.Tab(label="Ligands", children=[ dcc.Graph(id="ligand-graph", config=dict(autosizable=True, responsive=True)), dash_table.DataTable( id="ligand-table", page_size=20, style_table={ "overflowX": "scroll", "overflowY": "scroll", "height": "50vh", "width": "95%" }, style_cell_conditional=[{ "if": { "column_id": "Ligand" }, "textAlign": "left" }], style_header={ "fontWeight": "bold", "maxWidth": "200px", "minWidth": "70px" }, style_data={ "maxWidth": "200px", "minWidth": "70px", "textOverflow": "ellipsis" }, sort_action="native", fixed_rows={ 'headers': True, 'data': 0 }) ]), dcc.Tab(label="Receptors", children=[ dcc.Graph(id="receptor-graph", config=dict(autosizable=True, responsive=True)), dash_table.DataTable( id="receptor-table", page_size=20, style_table={ "overflowX": "scroll", "overflowY": "scroll", "height": "50vh", "width": "95%" }, style_cell_conditional=[{ "if": { "column_id": "Receptor" }, "textAlign": "left" }], style_header={ "fontWeight": "bold", "maxWidth": "200px", "minWidth": "70px" }, style_data={ "maxWidth": "200px", "minWidth": "70px", "textOverflow": "ellipsis" }, sort_action="native", fixed_rows={ 'headers': True, 'data': 0 }) ]) ]) ]) # end ligand receptor list ]) # end wrapper # Instantiate the graph and produce the bounderies for filters @app.callback([ Output("cyto-graph", "elements"), Output("network-filter", "min"), Output("network-filter", "max"), Output("network-filter", "value") ], [ Input("network-interaction", "value"), Input("weight-select", "value") ]) def make_graph(interaction, score): G_flat = G_to_flat(G, score) if interaction == "all": # if no interaction is selected, use full graph G_cyto = nx.cytoscape_data(G_flat) weights = [d["weight"] for u, v, d in G_flat.edges(data=True)] # prepare data for network graph nodes = G_cyto["elements"]["nodes"] edges = G_cyto["elements"]["edges"] elements = nodes + edges return elements, min(weights), max(weights), np.mean(weights) else: # an interaction is selected, select only that interaction G_split = cn.graph.split_graph(G) G_split_flat = G_to_flat(G_split[interaction], score) G_cyto = nx.cytoscape_data(G_split_flat) weights = [ d["weight"] for u, v, d in G_split_flat.edges(data=True) ] # prepare data for network graph nodes = G_cyto["elements"]["nodes"] edges = G_cyto["elements"]["edges"] elements = nodes + edges return elements, min(weights), max(weights), np.mean(weights) # Change layout of network graph @app.callback(Output("cyto-graph", "layout"), [Input("network-layout", "value")]) def update_network_layout(layout): return {"name": layout, "automate": True, "fit": True} # Choose gene to color nodes by @app.callback( [Output("node-colors", "children"), Output("min-max", "children")], [Input("gene_dropdown", "value")]) def calculate_colors(gene): if gene is None: return [None, ""] # get all gene expression values for selected gene gene_data = { celltype["data"]["id"]: celltype["data"]["genes"][gene] for celltype in nodes } min_value = min(gene_data.values()) max_value = max(gene_data.values()) # package min max expression information to a list that will be returned expression = html.Ul(children=[ html.Li(f"minimum gene expression: {min_value}"), html.Li(f"maximum gene expression: {max_value}") ]) cmap = matplotlib.cm.get_cmap("coolwarm") color_dict = dict() for k, v in gene_data.items(): color_dict[k] = {"rgb": cmap(v, bytes=True)[0:3], "expression": v} color = pd.Series(color_dict) return color.to_json(), expression # Select visible edges of network graph depending on filter value # node color depending on selected gene # width of edges @app.callback(Output("cyto-graph", "stylesheet"), [ Input("network-filter", "value"), Input("network-filter", "min"), Input("network-filter", "max"), Input("node-size", "value"), Input("node-colors", "children") ]) def style_network_graph(th, min_weight, max_weight, size, colors): # create a filter for edges filter_style = [{ "selector": f"edge[weight < {th}]", "style": { "display": "none" } }, { "selector": "node", "style": { 'height': f'mapData(centrality, {min(cent)}, {max(cent)}, {size[0]}, {size[1]})', 'width': f'mapData(centrality, {min(cent)}, {max(cent)}, {size[0]}, {size[1]})' } }] # create a color style for nodes based on gene expression if isinstance(colors, str): colors = pd.read_json(colors, typ="series", convert_dates=False) color_style = [{ 'selector': f'node[id = "{str(index)}"]', 'style': { 'background-color': f'rgb{tuple(colors[index]["rgb"])}' } } for index in colors.index] filter_style += color_style else: color_style = { "selector": "node", "style": { 'background-color': 'BFD7B5' } } # Map edges width to a set min and max value (scale for visibility) edge_style = [{ "selector": "edge", "style": { "width": f"mapData(weight, {min_weight}, {max_weight}, 1, 10)" } }] return default_stylesheet + filter_style + edge_style # download an image of current network graph view @app.callback(Output("cyto-graph", "generateImage"), Input("download-network-graph", "n_clicks")) def download_networkgraph_image(get_request): if get_request == None: return dict() return {"type": "svg", "action": "download"} # Produce a table of all edge data from tapped edge @app.callback([ Output("edge-info", "children"), Output("edge-selection", "columns"), Output("edge-selection", "data") ], [ Input("cyto-graph", "tapEdgeData"), Input("interaction-selection", "children") ]) def update_data(edge, selection): import pandas as pd import json # check if an edge has really been clicked, return default otherwise if edge is None: return ["", None, None] info = f"Interactions from {edge['source']} to {edge['target']}." # map visible names for columns with columns in edge[interaction] columns = [{ "name": "Interaction", "id": "interaction" }, { "name": "Receptor Family", "id": "receptorfamily" }, { "name": "Score", "id": "score" }, { "name": "Log10(score)", "id": "log_score" }, { "name": "Specificity", "id": "specificity" }, { "name": "Importance", "id": "importance" }, { "name": "Ligand z-score", "id": "ligand_zscore" }, { "name": "Ligand p-value", "id": "ligand_pval" }, { "name": "Receptor z-score", "id": "receptor_zscore" }, { "name": "Receptor p-value", "id": "receptor_pval" }, { "name": "PubMed ID", "id": "pubmedid" }] interactions = pd.DataFrame(edge["interactions"])[[ "interaction", "receptorfamily", "score", "log_score", "specificity", "importance", "ligand_zscore", "ligand_pval", "receptor_zscore", "receptor_pval", "pubmedid" ]] # Sort values based on score interactions.sort_values(by="score", ascending=False, inplace=True) # round values for scores to two decimals interactions[[ "score", "log_score", "specificity", "importance", "ligand_zscore", "receptor_zscore" ]] = interactions[[ "score", "log_score", "specificity", "importance", "ligand_zscore", "receptor_zscore" ]].round(decimals=2) interactions[["ligand_pval", "receptor_pval" ]] = interactions[["ligand_pval", "receptor_pval"]].round(decimals=4) # if selection from interaction graph, filter dataframe if selection != "": selection = json.loads(selection) interactions = interactions.loc[interactions["interaction"].isin( selection)] records = interactions.to_dict("records") return [info, columns, records] @app.callback([Output("interaction-scatter", "figure")], [Input("cyto-graph", "tapEdgeData")]) def interaction_scatter_plot(edge): import plotly.express as px fig = go.Figure() if not isinstance(edge, dict): return [ fig, ] interactions = pd.DataFrame(edge["interactions"])[[ "interaction", "receptorfamily", "score", "log_score", "ligand_zscore", "ligand_pval", "receptor_zscore", "receptor_pval", "specificity", "importance", "pubmedid" ]] # add 10% to the min and max value to not clip the datapoint range_x = (-max(interactions["log_score"]) * 0.1, max(interactions["log_score"]) * 1.1) range_y = (-max(interactions["specificity"]) * 0.1, max(interactions["specificity"]) * 1.1) #interactions["specificity"] = np.log10( interactions["specificity"]) fig = px.scatter(interactions, x="log_score", range_x=range_x, y="specificity", range_y=range_y, color="importance", hover_name="interaction", hover_data=[ "ligand_pval", "receptor_pval", "score", "specificity", "receptorfamily" ], color_continuous_scale=px.colors.sequential.Viridis_r, labels={ "ligand_zscore": "Ligand Z-score", "receptor_zscore": "Receptor Z-score", "log_score": "log(Interaction score)", "score": "Interaction score", "specificity": "Specificity", "importance": "Importance", "receptorfamily": "Receptor family", "pubmedid": "PubMed ID", "ligand_pval": "Ligand p-value", "receptor_pval": "Receptor p-value" }) return [ fig, ] @app.callback(Output("interaction-selection", "children"), [Input("interaction-scatter", "selectedData")]) def interaction_select(selected_data): import json if isinstance(selected_data, dict): interactions = [ point["hovertext"] for point in selected_data["points"] ] else: return "" return json.dumps(interactions) # Produce ligand and receptor graphs based on tapped node @app.callback([ Output("ligand-graph", "figure"), Output("receptor-graph", "figure"), Output("selected-node", "children") ], [Input("cyto-graph", "tapNodeData"), Input("filter_l_r", "value")]) def plot_l_r_expression(node, filter_text): # set output variables to empty figures ligand_fig = go.Figure() receptor_fig = go.Figure() node_id = "Select a node in the network graph" if isinstance(node, dict): import plotly.express as px node_id = node["id"] ligands_score = pd.DataFrame.from_dict(node["ligands_score"], orient="index", columns=["Score"]) ligands_zscore = np.log2( pd.DataFrame.from_dict(node["ligands_zscore"], orient="index", columns=["Z-score"])) ligands_corr_pval = pd.DataFrame.from_dict( node["ligands_corr_pval"], orient="index", columns=["p-value"]) ligands_merge = ligands_score.merge(ligands_zscore, how="left", left_index=True, right_index=True) ligands_merge = ligands_merge.merge(ligands_corr_pval, how="left", left_index=True, right_index=True) ligands_merge["log(score + 1)"] = np.log10(ligands_merge["Score"] + 1) ligands_merge["Significant"] = [ True if p_val < 0.05 else False for p_val in ligands_merge["p-value"] ] ligands_merge["-log(p-value)"] = -np.log10( ligands_merge["p-value"]) if filter_text != "": ligands_merge = ligands_merge.filter(like=filter_text, axis=0) ligand_fig = px.scatter(ligands_merge, x="log(score + 1)", y="-log(p-value)", color="Significant", hover_name=ligands_merge.index, hover_data=["Score", "Z-score", "p-value"]) receptors_score = pd.DataFrame.from_dict(node["receptors_score"], orient="index", columns=["Score"]) receptors_zscore = np.log2( pd.DataFrame.from_dict(node["receptors_zscore"], orient="index", columns=["Z-score"])) receptors_corr_pval = pd.DataFrame.from_dict( node["receptors_corr_pval"], orient="index", columns=["p-value"]) receptors_merge = receptors_score.merge(receptors_zscore, how="left", left_index=True, right_index=True) receptors_merge = receptors_merge.merge(receptors_corr_pval, how="left", left_index=True, right_index=True) receptors_merge["log(score + 1)"] = np.log10( receptors_merge["Score"] + 1) receptors_merge["Significant"] = [ True if p_val < 0.05 else False for p_val in receptors_merge["p-value"] ] receptors_merge["-log(p-value)"] = -np.log10( receptors_merge["p-value"]) if filter_text != "": receptors_merge = receptors_merge.filter(like=filter_text, axis=0) receptor_fig = px.scatter( receptors_merge, x="log(score + 1)", y="-log(p-value)", color="Significant", hover_name=receptors_merge.index, hover_data=["Score", "Z-score", "p-value"]) return [ligand_fig, receptor_fig, node_id] # Builds a sankey graph based on the tapped node (store in global G_s) G_s = nx.MultiDiGraph() #variable holding sankey graph @app.callback([ Output("sankey-filter", "min"), Output("sankey-filter", "max"), Output("sankey-filter", "value") ], [Input("cyto-graph", "tapNodeData"), Input("sankey-toggle", "value")]) def build_sankey_graph(node, score): import numpy as np # If no node has been selected, dont try to build graph if node is None: return (0, 0, 0) node = node["id"] # Find all interactions where node is target or source node nonlocal G_s G_s = nx.MultiDiGraph() # reset content weight = list( ) # list to store all weights (used to set min and max for the filter) for n, nbrs in G.adj.items( ): # graph has been modified by network graph before for nbr, edict in nbrs.items(): if n == node: for e, d in edict.items(): G_s.add_edge(n, " Post " + nbr, **d) weight.append(d[score]) if nbr == node: for e, d in edict.items(): G_s.add_edge("Pre " + n, nbr, **d) weight.append(d[score]) if len(weight) == 0: weight = [0, 1] if score == "specificity": # set default start value to specificity value for ligand and receptor # p-value of (0.05 and 0.05)/2 = 1.3 return (min(weight), max(weight), 1.3) return (min(weight), max(weight), np.mean(weight)) @app.callback(Output("sankey-graph", "figure"), [ Input("sankey-filter", "value"), Input("sankey-toggle", "value"), Input("cyto-graph", "tapNodeData") ]) def filter_sankey_graph(th, score, node): if node: node = node["id"] _G_s = nx.MultiDiGraph() for u, v, n, d in G_s.edges(data=True, keys=True): if d[score] > th: _G_s.add_edge(u, v, n, **d) _G_s.add_nodes_from(G_s.nodes(data=True)) edges = nx.to_pandas_edgelist(_G_s) if len(edges) < 1: fig = dict() return fig # add same color scheme as network graph for node_s in _G_s.nodes(): if " Post" in node_s: original_node = str(node_s).split(sep=" Post")[1] elif "Pre " in node_s: original_node = str(node_s).split(sep="Pre ")[1] else: original_node = str(node_s) new_color = color_map_nodes[original_node.strip()] G_s.nodes[node_s]["color"] = new_color nodes = G_s.nodes() node_map = {cluster: id for id, cluster in enumerate(list(nodes))} sankey = go.Sankey(node=dict(pad=15, thickness=20, line=dict(color="black", width=0.5), label=list(nodes), color=[ f'rgb{tuple(d["color"][0:3])}' for n, d in G_s.nodes(data=True) ]), link=dict( source=list(edges["source"].map(node_map)), target=list(edges["target"].map(node_map)), value=list(edges[score]), label=edges["interaction"])) data = [sankey] layout = go.Layout(autosize=True, title=f"Interactions: {node}", font=dict(size=font_size)) fig = go.Figure(data=data, layout=layout) return fig @app.callback( [Output("ligand-table", "columns"), Output("ligand-table", "data")], [ Input("ligand-graph", "figure"), Input("ligand-graph", "selectedData") ]) def select_ligands(figure, selected): import json ligands = [] score = [] zscore = [] pval = [] for group in figure["data"]: for ligand in group["hovertext"]: ligands.append(ligand) for data in group["customdata"]: score.append(data[0]) zscore.append(data[1]) pval.append(data[2]) df = pd.DataFrame({ "Ligand": ligands, "Score": score, "Z-score": zscore, "P-value": pval }) df.index = df["Ligand"] df.sort_values(by="Score", ascending=False, inplace=True) if isinstance(selected, dict): filt = [] for point in selected["points"]: filt.append(point["hovertext"]) df = df.loc[filt] columns = [{ "name": "Ligand", "id": "Ligand" }, { "name": "Score", "id": "Score" }, { "name": "Z-score", "id": "Z-score" }, { "name": "P-value", "id": "P-value" }] data = df.to_dict("records") return columns, data @app.callback([ Output("receptor-table", "columns"), Output("receptor-table", "data") ], [ Input("receptor-graph", "figure"), Input("receptor-graph", "selectedData") ]) def select_ligands(figure, selected): import json receptors = [] score = [] zscore = [] pval = [] for group in figure["data"]: for receptor in group["hovertext"]: receptors.append(receptor) for data in group["customdata"]: score.append(data[0]) zscore.append(data[1]) pval.append(data[2]) df = pd.DataFrame({ "Receptor": receptors, "Score": score, "Z-score": zscore, "P-value": pval }) df.index = df["Receptor"] df.sort_values(by="Score", ascending=False, inplace=True) if isinstance(selected, dict): filt = [] for point in selected["points"]: filt.append(point["hovertext"]) df = df.loc[filt] columns = [{ "name": "Receptor", "id": "Receptor" }, { "name": "Score", "id": "Score" }, { "name": "Z-score", "id": "Z-score" }, { "name": "P-value", "id": "P-value" }] data = df.to_dict("records") return columns, data # Run server app.run_server(**kwargs)
def main(): """ 関数の実行を行う関数。 Return: """ import random def shuffle_dict(d): """ 辞書(のキー)の順番をランダムにする Args: d: 順番をランダムにしたい辞書。 Return: dの順番をランダムにしたもの """ keys = list(d.keys()) random.shuffle(keys) return dict([(key, d[key]) for key in keys]) """ input_node_dict: 全ノードについての情報を辞書にまとめたもの。dict() key: ノードの名前。 value: リスト 第1要素: keyのノードが指すノードの集合。set() 第2要素: keyのノードのリンク先URL。str() """ input_node_dict = {"a": [set(), "example.html"], "b": [{"a"}, "example.html"], "c": [{"b", "e"}, "example.html"], "d": [{"c", "a"}, "example.html"], "e": [{"a"}, "example.html"], "f": [{"e", "b", "a"}, "example.html"], "g": [{"e"}, "example.html"], "h": [{"g", "f"}, "example.html"], "i": [{"a"}, "example.html"], "j": [{"i"}, "example.html"], "k": [{"j", "m"}, "example.html"], "l": [{"i", "a"}, "example.html"], "m": [{"i"}, "example.html"], "n": [{"j", "m"}, "example.html"], "o": [{"m", "l"}, "example.html"], "p": [{"n", "k"}, "example.html"], "q": [{"k", "o", "i"}, "example.html"], } node_list = create_node_list(shuffle_dict(input_node_dict)) # 間引き remove_waste_edges(node_list) # 階層割り当て assign_level(node_list) cut_edges_higher_than_1(node_list) assign_x_sequentially(node_list) sort_nodes_by_xcenter(node_list, downward=True) sort_nodes_by_xcenter(node_list, downward=False) node_attributes = node_list2node_dict(node_list) # 有向グラフGraphの作成 graph = nx.DiGraph() create_dependency_graph(node_list, graph) # nodes_attrsを用いて各ノードの属性値を設定 nx.set_node_attributes(graph, node_attributes) # グラフの描画 nx.draw_networkx(graph) # cytoscape.jsの記述形式(JSON)でグラフを記述 graph_json = nx.cytoscape_data(graph, attrs=None) with open('demo_sample.json', 'w') as f: f.write(json.dumps(graph_json))
import json import matplotlib.pyplot as plt import networkx as nx G = nx.read_gpickle("data/mab.pickle") # Restrict the graph to roads that connect to the A1 paths = nx.shortest_path_length(G, source="A1") closest_nodes = [k for k, v in paths.items() if v <= 1] G = G.subgraph(closest_nodes) # Write out this subgraph in cytoscape format for the dataviz cyjs = nx.cytoscape_data(G) with open("data/a1.cyjs", "w") as outfile: json.dump(cyjs, outfile, indent=2) # Use graphviz's neato algorithm to layout the subgraph pos = nx.drawing.nx_pydot.pydot_layout(G, prog="neato") # Use the positions to fix the layout in cytoscape, by pasting the dict into a1.html print("pos", {k: dict(x=v[0] * 5, y=v[1] * 5) for k, v in pos.items()}) # Preview the dataviz using matplotlib nx.draw_networkx(G, pos=pos) plt.show()