From 23e5c27d83d545fb1155ae9c0d558abe9c828c91 Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Thu, 9 May 2019 15:47:10 -0500 Subject: links from nodes --- ratspub.py | 27 ++++++++++++++++----------- server.py | 43 +++++++++++++++++++++++++++++-------------- templates/cytoscape.html | 10 +++++++++- templates/index.html | 16 ++++------------ templates/layout.html | 4 +--- templates/sentences.html | 3 ++- 6 files changed, 61 insertions(+), 42 deletions(-) diff --git a/ratspub.py b/ratspub.py index 345146e..ea78d85 100755 --- a/ratspub.py +++ b/ratspub.py @@ -3,6 +3,8 @@ from nltk.tokenize import sent_tokenize import os import re +global function_d, brain_d, drug_d, addiction_d + ## turn dictionary (synonyms) to regular expression def undic(dic): return "|".join(dic.values()) @@ -67,27 +69,28 @@ def gene_functional(gene): out+=gene+"\t"+"function\t"+bio0+"\t"+sent+"\n" return(out) -def generate_nodes(nodes_d, nodecolor): +def generate_nodes(nodes_d, nodetype): + nodecolor={'function':"#A9CCE3", 'addiction': "#D7BDE2", 'drug': "#F9E79F", 'brain':"#A3E4D7"} # include all search terms even if there are no edges, just to show negative result - json0 =str() #"{ data: { id: '" + gene + "'} },\n" + json0 =str() for node in nodes_d: - json0 += "{ data: { id: '" + node + "', nodecolor: '" + nodecolor + "' } },\n" + json0 += "{ data: { id: '" + node + "', nodecolor: '" + nodecolor[nodetype] + "', nodetype: '"+nodetype + "', url:'/shownode?nodetype=" + nodetype + "&node="+node+"' } },\n" return(json0) -def generate_edges(data): +def generate_edges(data, filename): json0=str() edgeCnts={} for line in data.split("\n"): if len(line.strip())!=0: (source, cat, target, pmid, sent) = line.split("\t") - edgeID=source+"|"+target + edgeID=filename+"|"+source+"|"+target if edgeID in edgeCnts: edgeCnts[edgeID]+=1 else: edgeCnts[edgeID]=1 for edgeID in edgeCnts: - (source,target)=edgeID.split("|") - json0+="{ data: { id: \'" + edgeID + "\', source: \'" + source + "\', target: '" + target + "\', sentCnt: '" + str(edgeCnts[edgeID]) + "', url:'/sentences?edgeID=" + edgeID + "' } },\n" + (filename, source,target)=edgeID.split("|") + json0+="{ data: { id: '" + edgeID + "', source: '" + source + "', target: '" + target + "', sentCnt: '" + str(edgeCnts[edgeID]) + "', url:'/sentences?edgeID=" + edgeID + "' } },\n" return(json0) addiction_d = {"reward":"reward|hedonic|incentive|intracranial self stimulation|ICSS|reinforcement|conditioned place preference|CPP|self administration|self administered|drug reinforced|operant|instrumental response", @@ -126,9 +129,11 @@ function_d={"neuroplasticity":"neuroplasticity|plasticity|long term potentiation } function=undic(function_d) + + #https://htmlcolorcodes.com/ -n0=generate_nodes(function_d, "#D7BDE2") -n1=generate_nodes(addiction_d,"#A9CCE3") -n2=generate_nodes(drug_d, "#A3E4D7") -n3=generate_nodes(brain_d, "#F9E79F") +n0=generate_nodes(function_d, 'function') +n1=generate_nodes(addiction_d, 'addiction') +n2=generate_nodes(drug_d, 'drug') +n3=generate_nodes(brain_d, 'brain') default_nodes=n0+n1+n2+n3 diff --git a/server.py b/server.py index 0f3d94b..804e0fc 100755 --- a/server.py +++ b/server.py @@ -1,5 +1,8 @@ #!/bin/env python3 from flask import Flask, render_template, request, redirect +import tempfile +import random +import string from ratspub import * app=Flask(__name__) @@ -11,43 +14,55 @@ def root(): @app.route("/search") def search(): - global all_sentences + tf_path=tempfile.gettempdir() + tf_name=tf_path+"/tmp"+''.join(random.choice(string.ascii_letters) for x in range(6)) all_sentences=str() genes=request.args.get('query') genes=genes.replace(",", " ") genes=genes.replace(";", " ") genes=genes.split() - if len(genes)>=6: + if len(genes)>=6: return render_template('index.html') nodes=default_nodes edges=str() for gene in genes: - nodes+="{ data: { id: '" + gene + "', nodecolor:'#FADBD8', fontweight:700} },\n" + nodes+="{ data: { id: '" + gene + "', nodecolor:'#FADBD8', fontweight:700, url:'https://www.ncbi.nlm.nih.gov/gene/?term="+gene+"'} },\n" sent0=gene_addiction(gene) - e0=generate_edges(sent0) + e0=generate_edges(sent0, tf_name) sent1=gene_functional(gene) - e1=generate_edges(sent1) + e1=generate_edges(sent1, tf_name) sent2=gene_anatomical(gene) - e2=generate_edges(sent2) + e2=generate_edges(sent2, tf_name) edges+=e0+e1+e2 all_sentences+=sent0+sent1+sent2 - #f=open("all_sentences.tab","w") - #f.write(all_sentences) - #f.close() + #session['tmpfile']={'filename':tf_name} + with open(tf_name,"w") as f: + f.write(all_sentences) + f.close() return render_template('cytoscape.html', elements=nodes+edges) @app.route("/sentences") def sentences(): edge=request.args.get('edgeID') - (gene0, cat0)=edge.split("|") - print (gene0 + cat0) - out="

"+gene0 + " and " + cat0 + "

\n" - for sent in all_sentences.split("\n"): + (tf_name, gene0, cat0)=edge.split("|") + out="

"+gene0 + " and " + cat0 + "


\n" + print(tf_name) + with open(tf_name, "r") as df: + all_sents=df.read() + for sent in all_sents.split("\n"): if len(sent.strip())!=0: - (gene,nouse,cat, pmid, text)=sent.split("\t") + (gene,nouse,cat, pmid, text)=sent.split("\t") if (gene == gene0 and cat == cat0) : out+= "
  • "+ text + " PMID:"+pmid+"
    " return render_template('sentences.html', sentences="
      "+out+"

    ") +@app.route("/shownode") +def shownode(): + node=request.args.get('node') + allnodes={**brain_d, **drug_d, **function_d, **addiction_d} + out="

    "+node.upper()+"


  • "+ allnodes[node].replace("|", "
  • ") + return render_template('sentences.html', sentences=out+"

    ") + + if __name__ == '__main__': app.run(debug=True) diff --git a/templates/cytoscape.html b/templates/cytoscape.html index fd2000e..c0c6bf6 100644 --- a/templates/cytoscape.html +++ b/templates/cytoscape.html @@ -22,7 +22,7 @@ css: { 'content': 'data(sentCnt)', 'curve-style': 'bezier', - 'opacity': '0.3' + 'opacity': 'mapData(sentCnt, 1, 50, 0.2, 0.3)', } }, { selector: 'node.highlight', @@ -50,6 +50,7 @@ name: 'circle' } }); + cy.on('tap', 'edge', function(){ try { // your browser may block popups window.open( this.data('url') ); @@ -57,6 +58,13 @@ window.location.href = this.data('url'); } }); + cy.on('tap', 'node', function(){ + try { // your browser may block popups + window.open( this.data('url') ); + } catch(e){ // fall back on url change + window.location.href = this.data('url'); + } + }); cy.on('mouseover', 'node', function(e){ var sel = e.target; cy.elements().difference(sel.outgoers()).not(sel).addClass('semitransp'); diff --git a/templates/index.html b/templates/index.html index ba18e0c..011aa6f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,22 +3,14 @@

    - +

    - This app searches PubMed to find sentences that contain the query terms (e.g., gene symbols) and a drug addiction related keyword. These keywords belong to the following categories: - - + This app searches PubMed to find sentences that contain the query terms (e.g., gene symbols, up to five are allowed per search) and keywords related to drug addiction. +


    -Live searches are conducted through PubMed to get relevant PMIDs, which are then used to retrieve the abstracts from a local archive. The relationships are presented as an interactive cytoscape graph. The nodes can be moved around to better reveal the connections. Clicking on the links will bring up the corresponding sentences in a new browser window. +Searches are conducted through PubMed to get relevant PMIDs, which are then used to retrieve the abstracts from a local archive. The relationships are presented as an interactive cytoscape graph. The nodes can be moved around to better reveal the connections. Clicking on the links will bring up the corresponding sentences in a new browser window.


    Source code diff --git a/templates/layout.html b/templates/layout.html index d64b331..cf8e8ed 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -13,7 +13,7 @@ -