fded6ce46cb167faaae559ff93b050c2b7d18ff1 max Mon Jun 26 08:59:00 2023 -0700 Porting hgGeneGraph to python3. refs #31563 diff --git src/hg/hgGeneGraph/hgGeneGraph src/hg/hgGeneGraph/hgGeneGraph index 96bd4bc..b5df5d0 100755 --- src/hg/hgGeneGraph/hgGeneGraph +++ src/hg/hgGeneGraph/hgGeneGraph @@ -1,16 +1,16 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Gene Interaction Viewer for the Genome Browser # query tables with prefix "gg" in hgFixed, writes the results to a dot file, # runs graphviz's "dot" program to create a pathway map from it and write html # and mapfiles to the trash directory. # CGI params: gene=(HGNCsymbol) or link=sym1:sym2 # optional params: addNeighbors # colors: # grey+thickness = only text mining data # light blue, dashed = only high-throughput data @@ -18,59 +18,59 @@ # dark blue, dashed = only low-throughput data # dark blue, thickness = low-throughput data + text # dark blue + dashed = only pathway data # code review # - os.system is not a security risk here, no variables go into the cmd line # - mysql statements are not escaped, instead all CGI vars are checked for non-alpha letters # hgFixed tables required for this script: ggLink (main table with gene-gene links), # ggLinkEvent (details about link), ggEventDb (details about links from databases), # ggEventText (details about links from text mining), ggDoc (details about documents for ggEventText) # ggGeneName (symbols), ggGeneClass (HPRD/Panther class) # these are default python modules on python 2.7, no errors expected here -import sys, cgi, os, string, urllib, operator, hashlib +import sys, cgi, os, string, urllib.request, urllib.parse, urllib.error, operator, hashlib from sys import exit from collections import defaultdict, namedtuple from os.path import * import cgitb cgitb.enable() # import the UCSC-specific library sys.path.append(join(dirname(__file__), "pyLib")) try: - from hgLib import cgiArgs, cgiSetup, cgiString, printContentType, printMenuBar, \ + from hgLib3 import cgiArgs, cgiSetup, cgiString, printContentType, printMenuBar, \ sqlConnect, sqlQuery, errAbort, cfgOption, runCmd, cgiGetAll, printHgcHeader, \ printHgcSection, getNonce, getCspMetaHeader, jsOnEventById, \ jsInlineFinish, webStartGbNoBanner, htmlPageEnd, hConnectCentral, \ sqlTableExists, readSmallFile except: print("Content-type: text/html\n") print("Cannot find the directory cgi-bin/pyLib in Apache. This is an installation error.") print("All all parts of cgi-bin installed? Did you do 'make' in kent/src/hg/pyLib?") -import MySQLdb +import pymysql.cursors # not using feedback button for now. Fan would have liked it, but not sure how we can write # to any form of database. # the list of allowed chars in cgi args: digits, letters and dashes legalChars = set(string.digits) -legalChars.update(set(string.letters)) +legalChars.update(set(string.ascii_letters)) legalChars.update("_-./: ") # number of genes to show on graph by default DEFGENECOUNT="25" # ignore all text mining data with less than X abstracts MINSUPP=2 # minResCount is used throughout the code. For a given interaction, it is the minimal # number of interactions from all documents linked to this interaction. # E.g. minResCount of 5 means that the interaction is based on at least one document # that contained not more than 5 interactions. # Cutoff on minResCount: # maximum number of pairs a study can have to be considered "low-throughput" # only interactions with at least one low-throughput study are colord in dark @@ -137,31 +137,31 @@ #<script src="//code.jquery.com/jquery-1.10.2.js"></script> #<script src="//code.jquery.com/ui/1.11.0/jquery-ui.js"></script> #<script src="../js/readmore.min.js"></script> #<link rel="stylesheet" href="//code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css"> #<link rel="stylesheet" href="../style/HGStyle.css" type="text/css" /> #<link rel='stylesheet' href='../style/nice_menu.css' type='text/css' /> def printInlineAndStyles(): #print('<script src="//code.jquery.com/ui/1.11.0/jquery-ui.js"></script>') print('<script src="//cdn.rawgit.com/jedfoster/Readmore.js/master/readmore.min.js"></script>') - print(""" + print((""" <script type="text/javascript" nonce='%s'> $(function() { //$( document ).uitooltip(); //$( document ).uitooltip(); $('[data-toggle="tooltip"]').bsTooltip(); // bootstrap does not really allow HTML in the title attribute // use jquery ui tooltips for the graph var opt = { items: "area", track : true, content: function() {return $(this).prop('title')} }; $("area").uitooltip(opt); // when user opens annotate genes menu, close the tooltip @@ -208,248 +208,249 @@ } .ui-tooltip { font-size:10pt; font-family:Helvetica; padding: 3px; } ul { padding-left: 15px; margin: 0px; padding-top:3px;} .tooltip.right { margin-left: 20px; } .tooltip.left { margin-left: -20px; } </style> - """ % getNonce()) + """ % getNonce())) def htmlHeader(): " print start of page " webStartGbNoBanner(getCspMetaHeader(), "Genome Browser Gene Interaction Graph") print('<body class="hgc cgi">') printMenuBar() db = getCgiVar("db") printHgcHeader(db, "Gene Interactions Track", "Gene interactions and pathways from curated databases and text-mining", addGoButton=False, infoUrl=MANUALURL, infoMouseOver="Open help page") def mustBeClean(str): """ make sure a string contains only letters and digits """ if str==None: return str - str = urllib.unquote(str) + str = urllib.parse.unquote(str) str = str.strip() for s in str: if s not in legalChars: errAbort("illegal character in CGI parameter") return str def getCgiVar(name, default=None, allowAnyChar=False, maxLen=30): " get named cgi variable as a string " val = cgiString(name, default=default) if not allowAnyChar: mustBeClean(val) if val != None and len(val) > maxLen: errAbort("CGI arg %s cannot be longer than %d characters" % (name, maxLen)) return val def mergeCgiParamDicts(data, changes, reset=False): """ given a data dict and a 2nd one with key=val changes, return a new dict with changes merged into data. If changes has key=None, remove the key from data. Skips some typical hgTracks-specific settings, like hgt.*, l, r or pix. """ cgiArgs = cgiGetAll() newArgs = {} # copy all existing CGI vars into new dict if not reset: - for key in data.keys(): + for key in list(data.keys()): if key.startswith("hgt") or key.startswith("dink") or key=="c" or key=="l" or key=="r" or key=="pix" or key=="position": continue val = cgiArgs.getfirst(key) newArgs[key] = val # remove or add the changes - for key, val in changes.iteritems(): + for key, val in changes.items(): if val==None: if key in newArgs: del newArgs[key] else: newArgs[key] = str(val) return newArgs def makeSelfUrl(changes, clear=False): " return a url to myself, keep all CGI vars, but change/append addParam=addValue " # construct the new link newArgs = mergeCgiParamDicts(cgiGetAll(), changes, clear) - paramStr = urllib.urlencode(newArgs) + paramStr = urllib.parse.urlencode(newArgs) myName = basename(__file__) url = "%s?%s" % (myName, paramStr) return url def printSelfHiddenVars(paramDict, clear=False, skipList=[]): " like makeSelfUrl, but write out all current CGI vars as hidden form fields " newArgs = mergeCgiParamDicts(cgiGetAll(), paramDict, clear) - for key, val in newArgs.iteritems(): + for key, val in newArgs.items(): if key not in skipList and not key=="submit": - print '<input type="HIDDEN" name="%s" value="%s">' % (key, val) + print('<input type="HIDDEN" name="%s" value="%s">' % (key, val)) def makeSelfLink(linkName, paramDict, clear=False, anchor=None, className=None, title=None, style=None, dataToggle=None): """ make a href link to myself, keep all CGI vars, but change/append addParam=addValue styleDict is a list of css styles """ url = makeSelfUrl(paramDict, clear=clear) if anchor!=None: url += "#"+anchor classStr = "" if className!=None: classStr='class="%s" ' % className dataToggleStr = "" if dataToggle!=None: dataToggleStr='data-toggle="%s" data-placement="right"' % dataToggle styleStr = "" if style!=None: styleStr='style="%s" ' % style titleStr = "" if title!=None: titleStr = ' title="%s"' % title.replace('"', ' ') return '<a %s%s%shref="%s"%s>%s</a>' % (titleStr, classStr, dataToggleStr, url, styleStr, linkName) def saltedHash(word, length=5): " return first 5 chars of salted hash " # pretty simple salt: PITX2, salting is just for the captcha - hashStr = "".join(hashlib.sha1(word+"PITX2").hexdigest()[:length]).lower() + inStr = word+"PITX2" + hashStr = "".join(hashlib.sha1(inStr.encode("utf8")).hexdigest()[:length]).lower() return hashStr def reqMinSupp(links, minArtSupp, maxResCount, targetGene): """ remove all 'text mining only' links with less than minArtSupp supporting documents The only exception is targetGene which we always want to stay connected Also remove links that are PPI-only and have a high minResCount. """ newLinks = defaultdict(set) genes = set() targetConns = {} - for genePair, linkData in links.iteritems(): + for genePair, linkData in links.items(): docCount, dbCount, tagSet, pairMinResCount = linkData[:4] if targetGene in genePair: targetConns[genePair] = linkData # remove text-mining links with only one article if "text" in tagSet and docCount < minArtSupp: continue # remove noisy PPI links if len(tagSet)==1 and "ppi" in tagSet and pairMinResCount > maxResCount: continue genes.update(genePair) newLinks[genePair] = linkData # is the target gene still connected to something? If not add it back and # accept that these links are less than minSupp if targetGene not in genes: - for genePair, linkData in targetConns.iteritems(): + for genePair, linkData in targetConns.items(): newLinks[genePair] = linkData return newLinks def scorePair(docCount, tagSet): " return the score for a gene pair " # pairs that have no text mining results get assigned artifical # article counts, based on this query: # hgsql publications -e "select * from ggLink where linkTypes like '%ppi%'" -NB | tawk '($4!=0 && $5!=0) { print $4+$5}' | avg # the avg for PPI was 14 and the one for pwy 22 # but PPI scores were mostly 0, so I lower it manually geneScore = docCount if geneScore==0 and "ppi" in tagSet: geneScore = 2 if geneScore==0 and "pwy" in tagSet: geneScore = 4 return geneScore def iterLinkScores(links): """ given a dict (gene1, gene2) -> [score1, score2, ...] yield tuples (gene1, gene2), totalScore """ - for genes, linkData in links.iteritems(): + for genes, linkData in links.items(): docCount, dbCount, tagSet = linkData[:3] geneScore = scorePair(docCount, tagSet) yield genes, geneScore def limitGenes(links, maxRank, targetGene, lowLinks=None): """ get the links for the top X genes and return two lists of links, highLinks and lowLinks The targetGene is always in the high list. """ # create a list of genes sorted by article count in links geneScores = defaultdict(int) for genes, geneScore in iterLinkScores(links): for g in genes: geneScores[g] += geneScore - geneScores = geneScores.items() + geneScores = list(geneScores.items()) geneScores.sort(key=operator.itemgetter(1), reverse=True) # keep only the best genes sortedGenes = [x for x,y in geneScores] highGenes = set(sortedGenes[:maxRank]) lowGenes = set(sortedGenes[maxRank:]) # the target gene itself always has to be in the top list if targetGene not in highGenes: highGenes.add(targetGene) if targetGene in lowGenes: lowGenes.remove(targetGene) # filter the links into high and low highLinks = defaultdict(set) if lowLinks==None: lowLinks = defaultdict(set) - for genes, linkData in links.iteritems(): + for genes, linkData in links.items(): g1, g2 = genes if g1 in highGenes and g2 in highGenes: highLinks[genes] = linkData else: lowLinks[genes] = linkData return highLinks, lowLinks def limitLinks(graphLinks, lowLinks, maxRank, targetGene): """ filter the high links to keep only the best X and return them, move the others into the lowLinks dict. Always keep all links to/from targetGene. """ # ignoring link direction, get all PMIDs per link linkScores = {} for genes, geneScore in iterLinkScores(graphLinks): linkScores[genes] = geneScore - linkScores= linkScores.items() # convert to list + linkScores= list(linkScores.items()) # convert to list linkScores.sort(key=operator.itemgetter(1), reverse=True) # sort linkScores = [x for x,y in linkScores] # keep only the gene pairs highPairs = set(linkScores[:maxRank]) # keep only the best pairs lowPairs = set(linkScores[maxRank:]) # now filter all links and keep only the those of the pairs highLinksFiltered = defaultdict(set) - for pair, linkData in graphLinks.iteritems(): + for pair, linkData in graphLinks.items(): g1, g2 = pair if pair in highPairs or g1==targetGene or g2==targetGene: #print "high", pair highLinksFiltered[pair] = linkData else: #print "low" lowLinks[pair] = linkData return highLinksFiltered, lowLinks def splitHighLowLinks(links, gene, minSupp, lowLinks, geneCount): """ split into two sets of links: high = best geneCount genes and best 2*geneCount links between them, low = all the others""" links = reqMinSupp(links, minSupp, 999999999, gene) @@ -491,72 +492,72 @@ dbList = row.dbList.split("|") links[pair] = (int(row.docCount), dbList, \ row.linkTypes.split(","), int(row.minResCount), row.snippet) return links def filterLinks(links): " remove links depending on the CGI param 'supportLevel'. Can show all, only with PPI/pathway or only with pathway " showTags = getFilterStatus() if len(showTags)==3: # no filtering return links # filter links filtLinks = {} - for pair, pairData in links.iteritems(): + for pair, pairData in links.items(): docCount, dbList, tagSet = pairData[:3] if len(showTags.intersection(tagSet))!=0: filtLinks[pair] = pairData return filtLinks def buildGraph(conn, gene, geneCount, minSupp, addNeighbors): """ get (gene,gene) links from database and annotate with weights and tags only get links with minSupp articles for each link """ if geneCount <= 1: errAbort("Sorry, you have to show at least two genes.") try: links = queryLinks(conn, gene=gene) - except MySQLdb.Error: + except pymysql.Error: errAbort("Cannot find the gg* tables in hgFixed. This mirror's database may need updating.") if len(links)==0: errAbort("Sorry, the gene %s is not a valid gene symbol or is not present in any gene interaction database." % cgi.escape(gene)) links = filterLinks(links) lowLinks = defaultdict(set) graphLinks, lowLinks = splitHighLowLinks(links, gene, minSupp, lowLinks, geneCount) if addNeighbors: # create the links between all other genes, be less stringent about these otherGenes = set() - for genes, pmids in graphLinks.iteritems(): + for genes, pmids in graphLinks.items(): otherGenes.update(genes) if gene in otherGenes: otherGenes.remove(gene) if len(otherGenes)!=0: # get links between all other genes but keep the limit on the graphed links otherLinks = queryLinks(conn, genes=otherGenes) otherLinks = filterLinks(otherLinks) otherLinks = reqMinSupp(otherLinks, 2, 999999999, gene) # we still require two text mining abstracts otherLinks, lowLinks = limitLinks(otherLinks, lowLinks, 35, gene) # add the high links back to the graph - for pair, linkData in otherLinks.iteritems(): + for pair, linkData in otherLinks.items(): assert(pair not in graphLinks) graphLinks[pair] = linkData return graphLinks, lowLinks #def queryLinkColors(conn, links): #" figure out if links have annotations in pathway commons " #colors = {} #for gene1, gene2 in links: #if sqlQueryExists(conn, "SELECT causeGene, themeGene FROM pathCommons where causeGene='%s' and themeGene='%s'" % (gene1,gene2)): #colors[(gene1, gene2)] = "blue" #return colors def pmidCountToThick(pmidCount): " convert pmid count to line thickness " @@ -640,53 +641,53 @@ outMap = splitext(fname)[0]+".map" binPath = findDot() if which(binPath) is None: print("Could not find the command dot or cgi-bin/loader/dot_static<p>") printDotErrorHelpAndExit() cmd = [binPath, "-Gdpi=96", "-Gsize=12,5", "-Gratio=fill", "-K"+alg, "-T"+format, fname, "-o",outFname, "-q 2"] # create a html map for png format if format=="png": cmd.extend(["-Tcmapx", "-o", outMap]) ret = runCmd(cmd, mustRun=False) if ret!=0: - print("Could not run the command '%s'. <p>" % " ".join(cmd)) + print(("Could not run the command '%s'. <p>" % " ".join(cmd))) printDotErrorHelpAndExit() return outFname, outMap def dictToDot(d): """ reformat a dictionary to a string like [key1="value1"; key2="value2"] """ if len(d)==0: return "" strList = [] - for key, val in d.iteritems(): + for key, val in d.items(): strList.append('%s="%s"' % (key, val.replace('"', ''))) return "[%s]" % (";".join(strList)) def writeDot(allGenes, links, fname, targetGene, geneDescs, annotLabel, geneAnnots, linkSnips): """ write a description of the graph to fname in dot format. targetGene is highlighted, geneDescs are on mouseovers, geneAnnots are used to color the genes. geneSnips are added to mouseovers. """ try: - ofh = open(fname, "w") + ofh = open(fname, "w", encoding="utf8") except: errAbort("Error writing %s, this is an installation error. Please make sure that the trash directory has the correct permissions." % fname) ofh.write("digraph test {\n") ofh.write("graph [bgcolor=transparent; esep=0.4];\n") #ofh.write("rankdir=LR;\n") ofh.write("overlap=voronoi;\n") ofh.write('size="7,7";\n') #ofh.write('splines=polyline;\n') ofh.write('splines=true;\n') #ofh.write('nodesep=2.0;\n') #ofh.write('pack=true;\n') #ofh.write('edge [arrowhead=vee, color=grey];\n') #ofh.write('node [color=none; shape=plaintext; fixedsize=true,width=0.9,fontname="Helvetica"];\n') ofh.write('edge [color="%s"; weight=0.2; arrowsize=0.7];\n' % (TEXTCOLOR+TRANSPARENCY)) ofh.write('node [penwidth=0; style=filled; fontcolor="#ffffff"; fillcolor="#111177"; shape=ellipse; fontsize=11; fixedsize=true; width=0.8; height=0.3; fontname="Helvetica"];\n') @@ -803,78 +804,78 @@ if len(rows)==0: # "INS" is not in kgXref??? rows = sqlQuery(conn, 'select chrom, txStart, txEnd from refGene where name2="%s" limit 1;' % gene) if len(rows)==0: return "", "", "" return rows[0] def flattenLink(links): """ given a dict with a directed graph geneA, geneB -> linkData return a undirected graph in the form of a list (geneA, geneB), totalCount, docCount, tags """ counts = [] minAbsCount = 99999999 - for genes, linkData in links.iteritems(): + for genes, linkData in links.items(): docCount, dbList, tagSet, minResCount, snippet = linkData geneScore = scorePair(docCount, tagSet) counts.append( (genes[0], genes[1], geneScore, docCount, dbList, tagSet, minResCount, snippet) ) if docCount!=0: minAbsCount = min(minAbsCount, docCount) return counts, minAbsCount def countTargetLinks(links, targetGene): """ given a dict with (gene1, gene2) => docCount, dbCount, tags create a list of (gene, count) for all genes connected to target gene """ # count the in+outgoing links for each gene in 'links', the DB evidence # and the union of the tags allGenes = set() txtCounts = defaultdict(int) pairDbs = defaultdict(set) tags = defaultdict(set) - for genePair, pairData in links.iteritems(): + for genePair, pairData in links.items(): g1, g2 = genePair docCount, dbs, tagSet = pairData[:3] if g1==targetGene: gene = g2 elif g2==targetGene: gene = g1 else: continue allGenes.add(gene) pairDbs[gene].update(dbs) txtCounts[gene] += docCount tags[gene].update(tagSet) # create a list (gene, txtCount, dbCount) linkList = [] for g in allGenes: dbs = pairDbs.get(g, []) dbCount = len(dbs) linkList.append( (g, txtCounts.get(g, 0), dbCount, tags.get(g, [])) ) return linkList def makeUniDir(links): " for bidirectional links: keep only strongest direction and return new links dict " newLinks = defaultdict(set) - for pair, pmids in links.iteritems(): + for pair, pmids in links.items(): if not pair in newLinks: cause, theme = pair revPair = (theme, cause) score = len(pmids) revPmids = links.get( revPair, set()) revScore = len(revPmids) allPmids = pmids.union(revPmids) if score > revScore: newLinks[pair] = allPmids elif revScore > score: newLinks[revPair] = allPmids else: newLinks[pair] = allPmids newLinks[revPair] = allPmids return newLinks @@ -888,165 +889,166 @@ q = 'SELECT text from ggGeneName where gene="%s"' % gene rows = sqlQuery(conn, q) if len(rows)!=0: geneDescs[gene].append("<b>%s</b>" % rows[0].text) #q = 'SELECT text from geneDescRefSeq where gene="%s"' % gene q = 'SELECT text from ggGeneClass where gene="%s"' % gene rows = sqlQuery(conn, q) if len(rows)!=0: geneDescs[gene].append(rows[0].text) return geneDescs def printHttpHead(format): " print content type header " mimeType = mimeTypes[format] - print "Content-Type: %s" % mimeType + print("Content-Type: %s" % mimeType) if format in ["pdf", "svg", "sif"]: fname = "graph."+format - print "Content-Disposition: attachment; filename=%s" % fname - print + print("Content-Disposition: attachment; filename=%s" % fname) + print() + #sys.stdout.flush() def printCheckbox(name, isChecked, event, codeStr): " print a html checkbox " addStr = "" if isChecked: addStr = 'checked="true" ' - print '<input type="checkbox" id="%s" name="%s" value="on" %s />' % (name, name, addStr) + print('<input type="checkbox" id="%s" name="%s" value="on" %s />' % (name, name, addStr)) if event != "": jsOnEventById(event, name, codeStr) def getFilterStatus(): """ return a set of the support tags that should be shown, based on the CGI var 'supportLevel'. """ supportLevel = getCgiVar("supportLevel", "text") tagSet = set(["pwy"]) if supportLevel=="ppi" or supportLevel=="text": tagSet.add("ppi") if supportLevel=="text": tagSet.add("text") return tagSet def printDropdown(cgiArgName, selectedName, options, event="", codeStr=""): " print a html dropdown <select> box. " - print("<select id='%s' name='%s'>" % (cgiArgName, cgiArgName)) + print(("<select id='%s' name='%s'>" % (cgiArgName, cgiArgName))) for name, label in options: addStr = "" if name==selectedName: addStr = " selected" - print('<option value="%s"%s>%s</option>' % (name, addStr, label)) + print(('<option value="%s"%s>%s</option>' % (name, addStr, label))) print("</select>") if event != "": jsOnEventById(event, cgiArgName, codeStr) def printFilterMenu(targetGene, addNeighbors): # form to filter by type - print "<small>" - print '<form name="filterForm" action="%s" method="GET">' % makeSelfUrl({}, True) - print """<b>Gene:</b>""" - print '<input type="text" size="10" name="gene" value="%s" />' % targetGene - print " " - print '<input type="submit" name="1" value="OK">' - print " " + print("<small>") + print('<form name="filterForm" action="%s" method="GET">' % makeSelfUrl({}, True)) + print("""<b>Gene:</b>""") + print('<input type="text" size="10" name="gene" value="%s" />' % targetGene) + print(" ") + print('<input type="submit" name="1" value="OK">') + print(" ") supportLevel = getCgiVar("supportLevel", "text") if supportLevel not in ["text", "pwy", "ppi"]: errAbort("Illegal value for the supportLevel argument. Can only be text,pwy or ppi.") event = "change" codeStr = "document.forms['filterForm'].submit();" printDropdown("supportLevel", supportLevel, [("text", "Show all interactions, even only text-mining support"), ("ppi", "Show only interactions with some database support"), ("pwy", "Show only interactions with pathway database support")], event, codeStr ) #filterTags = getFilterStatus() #printCheckbox("pwy", "pwy" in filterTags, onChangeAttr) #print '<span style="background:%s;color:white" title="Show interactions manually curated by a pathway database, like WikiPathways, KEGG or Reactome, in dark-blue" onclick="">Pathways</span>' % LTCOLOR #printCheckbox("ppi", "ppi" in filterTags, onChangeAttr) #print '<span style="background:%s;color:white" title="Show interactions manually curated by a protein interaction database, like IntAct or BioGrid, in light-blue">Protein Interaction</span>' % HTCOLOR #printCheckbox("text", "text" in filterTags, onChangeAttr) #print '<span style="background:%s;color:white" title="Show interactions automatically extracted from PubMed abstracts with text-mining software in grey." onclick="">Text-Mining</span>' % TEXTCOLOR - print " " + print(" ") #if addNeighbors: #addNeighborLink = makeSelfLink("Show only %s links" % targetGene, {"onlyDirect":"1"}) #print("Only %s-interacting genes and only the most-mentioned interactions are shown. (%s)<br>" % (targetGene, noNeighborLink)) #else: #addNeighborLink = makeSelfLink("Show links between neighbors", {"onlyDirect":None}) #print("Only %s interactions are shown (%s)<br>" % (targetGene, addNeighborLink)) #print(addNeighborLink) hideIndirectStatus = (getCgiVar("hideIndirect")=="on") printCheckbox("hideIndirect", hideIndirectStatus, event, codeStr) - print '<span style="font-weight:bold">Hide non-%s interactions</span>' % targetGene - print " " + print('<span style="font-weight:bold">Hide non-%s interactions</span>' % targetGene) + print(" ") geneCount = getCgiVar("geneCount", DEFGENECOUNT) - print "<b>Show top" - print '<input name="geneCount" type="text" size="3" value="%s">' % geneCount - print "Genes on graph</b>" - print " " + print("<b>Show top") + print('<input name="geneCount" type="text" size="3" value="%s">' % geneCount) + print("Genes on graph</b>") + print(" ") printSelfHiddenVars({}, skipList=["supportLevel", "hideIndirect", "gene"]) - print "</form>" - print "</small>" + print("</form>") + print("</small>") def printDropDownMenu(label, entries, tooltip, selectedLabel=None): " output bootstrap dropdown menu of links " - print + print() print('<span class="dropdown">') if tooltip is not None: - print('<button class="btn btn-default btn-sm dropdown-toggle dropdown-toggle-split" type="button" id="dropdownMenu1" data-toggle="dropdown" title="%s" aria-haspopup="true" aria-expanded="false">' % tooltip) + print(('<button class="btn btn-default btn-sm dropdown-toggle dropdown-toggle-split" type="button" id="dropdownMenu1" data-toggle="dropdown" title="%s" aria-haspopup="true" aria-expanded="false">' % tooltip)) else: print('<button class="btn btn-default btn-sm dropdown-toggle dropdown-toggle-split" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">') print(label) print('<span class="caret"></span>') print('</button>') print('<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">') for row in entries: if len(row)==2: label, url = row link = '<a class="dropdown-item" href="%s">%s</a></li>' % (url, label) else: label, url, title = row link = '<a data-placement="left" data-toggle="tooltip" title="%s" class="dropdown-item" href="%s">%s</a></li>' % (title, url, label) if label==selectedLabel: print("<li class='active'>") else: print("<li>") - print link + print(link) print('</ul>') print('</span>') - print + print() def printGraphMenu(conn, targetGene, addNeighbors): " print the menu above the graph " - print '<div style="layout: inline-block; background: white"> <!-- whole menu -->' + print('<div style="layout: inline-block; background: white"> <!-- whole menu -->') - print '<div style="layout: inline; float: left;"> <!-- left part of menu -->' + print('<div style="layout: inline; float: left;"> <!-- left part of menu -->') printFilterMenu(targetGene, addNeighbors) - print '</div> <!-- left part of menu -->' + print('</div> <!-- left part of menu -->') - print '<div style="layout: inline; float: right"> <!-- right part of menu -->' - print "<small>" + print('<div style="layout: inline; float: right"> <!-- right part of menu -->') + print("<small>") #print """ #<style> #.smallDropDownMenu { #border: 1px solid #ccc; #margin: 0px; #padding: 3px; #display: none; #position:absolute; #z-index: 10; #width: 140px; #background:white #} #</style> #""" @@ -1095,34 +1097,34 @@ #// when user clicks the dropdown link, hide all other menus and toggle the menu of this link #$('.smallDropDownLink').click(function(event) { #var menuId = "#smallDropDown_"+event.target.id; #$(".smallDropDownMenu"+":not("+menuId+")").hide(); #$(menuId).toggle(); #}); #// when user clicks any link in the menu, hide all menus #$('.closeMenu').click(function() { #$('.smallDropDownMenu').hide(); #}); #}); #''' #print '</script>' - print '</div> <!-- right part of menu -->' + print('</div> <!-- right part of menu -->') - print "</small>" - print '</div> <!-- whole menu -->' + print("</small>") + print('</div> <!-- whole menu -->') #print '</div>' def openGeneAnnotFile(dataName): " return name and lines in gbdb tab sep file " annotData = None for annotTuple in geneAnnotFiles: if dataName==annotTuple[0]: annotData = annotTuple break if annotData==None: errAbort("Could not find annotations with name %s" % dataName) _, annotFname, annotName, annotLongName = annotData inPath = join("/gbdb", "hgFixed", "geneGraph", annotFname) ifh = readSmallFile(inPath) @@ -1181,125 +1183,128 @@ selfLink = makeSelfLink("Remove all filters", {"supportLevel": None}) errAbort("Sorry, there are no direct interactions with %s that fulfill your " "filter criteria. %s" % (geneName, selfLink)) allGenes = set() sifLines = [] for linkRow in weightedLinks: gene1, gene2 = linkRow[:2] allGenes.add(gene1) allGenes.add(gene2) if format=="sif": sifLines.append("%s pp %s" % (gene1, gene2)) if format in ["sif", "json"]: printHttpHead(format) if format=="sif": - print "\n".join(sifLines) + print("\n".join(sifLines)) else: - print jsonStr + print(jsonStr) return geneDescs = queryGeneDescs(conn, allGenes) linkSnips = querySnippets(conn, weightedLinks) annotLabel, geneAnnots = getGeneAnnots() writeDot(allGenes, weightedLinks, tmpName, targetGene, geneDescs, annotLabel, geneAnnots, linkSnips) if len(allGenes)>=100: alg = "fdp" picName, mapName = runDot(tmpName, alg, format) if format!="png": printHttpHead(format) - sys.stdout.write(open(picName,"rb").read()) + sys.stdout.flush() + sys.stdout.buffer.write(open(picName,"rb").read()) # binary data must use sys.stdout.buffer sys.stdout.flush() return # text above graph print("Mouse over or click genes or lines for details. Dashed lines indicate interactions without text mining support. ") print("Click any gene to make it the new center. Click any line to show details about the interaction. ") - print("Only %s-interacting genes and only the most-mentioned/most-curated interactions are shown in the graph. " % (targetGene)) + print(("Only %s-interacting genes and only the most-mentioned/most-curated interactions are shown in the graph. " % (targetGene))) print("See the <a href='../../goldenPath/help/hgGeneGraph.html'>Help Page</a> for details.<br>") # menu above graph # background #fffef5 would be an alternive - print '<div style="display:inline-block"> <!-- graph -->' + print('<div style="display:inline-block"> <!-- graph -->') printGraphMenu(conn, targetGene, addNeighbors) - print "<p>" + print("<p>") # graph itself - print '<img src="%s" usemap="#test">' % picName - map = open(mapName).read() - print map + print('<img src="%s" usemap="#test">' % picName) + mapData = open(mapName, "rb").read() + sys.stdout.flush() + sys.stdout.buffer.write(mapData) # only way to get binary data to stdout. Problem may be that data is mixed latin1/utf8 in tables from Stanford + sys.stdout.flush() - print '</div> <!-- graph -->' - print "<p>" + print('</div> <!-- graph -->') + print("<p>") def printPmidSearchForm(): " print a little form that allows to search for a PMID " - print "<hr>" - print "Search for a PMID: " - print '<form action="hgGeneGraph" method="get">' - print ' <input type="text" name="search">' - print ' <input type="submit" name="Search">' - print '</form><p>' + print("<hr>") + print("Search for a PMID: ") + print('<form action="hgGeneGraph" method="get">') + print(' <input type="text" name="search">') + print(' <input type="submit" name="Search">') + print('</form><p>') def printDisclaimer(): - print ''' + print(''' <div class="warn-note" style="width:800px;border: 2px solid #9e5900; padding: 5px 20px; background-color: #ffe9cc;"> <P><span style="font-weight: bold; color: #c70000;">NOTE:</span><br> Gene interactions that are not highlighted in blue were obtained with text mining software. They include errors. Please read the original source text before relying on an interaction. </P> </div> - ''' + ''') def printInfo(): - print """Please see the <a href='%s'>Gene Interactions Track Manual</a>.""" % MANUALURL - print "<div style='height:20px'> </div>" + print("""Please see the <a href='%s'>Gene Interactions Track Manual</a>.""" % MANUALURL) + print("<div style='height:20px'> </div>") def printLowLinksTable(gene, lowLinks, sortByCount): " print the other links as a table " if len(lowLinks)==0: return lowGeneList = countTargetLinks(lowLinks, gene) if len(lowGeneList)==0: return # sort lowGenes by either count or name if sortByCount: lowGeneList.sort(key=operator.itemgetter(1), reverse=True) selfLink = makeSelfLink("sort alphabetically", {"sortByCount": None}, anchor="table") currentSortDesc = "Sorted by article count" else: lowGeneList.sort(key=operator.itemgetter(0)) selfLink = makeSelfLink("sort by article count", {"sortByCount": "1"}, anchor="table") currentSortDesc = "Sorted alphabetically" geneCount = int(getCgiVar("geneCount", DEFGENECOUNT)) title = 'Less-frequently mentioned interactions with %s, not among the Top %d' % (gene, geneCount) printHgcSection(title, "", id='table') - print "Other genes interacting with %s. Mouse-over to show number of abstracts or databases. %s (%s).<br>" % \ - (gene, currentSortDesc, selfLink) + print("Other genes interacting with %s. Mouse-over to show number of abstracts or databases. %s (%s).<br>" % \ + (gene, currentSortDesc, selfLink)) print("Like above, interactions are colored by support. Grey:only text mining, light-blue:interaction database, blue:pathway database<p>") #print("Click any gene to make it the new center. Click number of articles to show sentences.<p>") - print '<table class="hgcCcds" style="table-layout:fixed">' - print '<tr>' + print('<table class="hgcCcds" style="table-layout:fixed">') + print('<tr>') i = 0 rowSize = 7 # columns per row for g, artCount, dbCount, tags in lowGeneList: # to set the cell width, browsers use only the first row cellStyle = "" if i <= rowSize: cellStyle=' style="width:140px"' color = None if "low" in tags or "pwy" in tags: color = LTCOLOR elif "ppi" in tags: color = HTCOLOR elif "text" in tags: @@ -1311,67 +1316,67 @@ newGeneLink = makeSelfLink("▸", {"gene": g}, title="Center graph on %s" % g, style='text-decoration:none', dataToggle="tooltip") if dbCount == 1 and artCount != 0: detailsText = "interaction %s-%s mentioned by %d articles and %d database" % (gene, g, artCount, dbCount) elif dbCount != 0 and artCount != 0: detailsText = "interaction %s-%s mentioned by %d articles and %d databases" % (gene, g, artCount, dbCount) elif artCount != 0: detailsText = "interaction %s-%s mentioned by %d articles" % (gene, g, artCount) elif dbCount != 0: detailsText = "interaction %s-%s mentioned by %d databases" % (gene, g, dbCount) detailsLink = makeSelfLink(g, {"gene": None, "lastGene": gene,"link":"%s:%s" % (g, gene)}, style=linkStyle, title=detailsText, dataToggle="tooltip") - print( '<td%s>%s %s</td>' % (cellStyle, detailsLink, newGeneLink)) + print(( '<td%s>%s %s</td>' % (cellStyle, detailsLink, newGeneLink))) i += 1 if i % rowSize == 0: - print "</tr><tr>" + print("</tr><tr>") - print "</tr>" - print "</table>" + print("</tr>") + print("</table>") def listToMysqlList(l): " convert a python list of strings to a mysql list, like ('a', 'b') " newList = [] for s in l: s = s.replace("'", "") newList.append("'"+s+"'") return "(%s)" % ",".join(newList) def querySnippets(conn, pairs): """ get the little text snippets from the ggLink table for a list of pairs return as a dict (gene1, gene2) -> snippet """ # convert list of pairs to mysql quoted string list newList = [] for pairData in pairs: g1, g2 = pairData[:2] pairQuote = "('%s', '%s')" % (g1, g2) newList.append(pairQuote) listStr = "(%s)" % ",".join(newList) query = "SELECT gene1, gene2, snippet FROM ggLink "\ "WHERE (gene1, gene2) in %s" % listStr rows = sqlQuery(conn, query) pairSnips = {} for g1, g2, snip in rows: - pairSnips[(g1,g2)]=snip + pairSnips[(g1,g2)]=snip.decode("utf8") return pairSnips def makeHgGeneLink(sym, db): return "<a title='Link to Gene Details page' href='hgGene?db=%s&hgg_gene=%s'>%s</a>" % (db, sym, sym) def showGraphBrowser(): " run graphviz on gene graph around gene, print html img and html map " gene, alg, addNeighbors, sortByCount, geneCount = parseGraphArgs() conn = sqlConnect(GGDB) graphLinks, lowLinks = buildGraph(conn, gene, geneCount, MINSUPP, addNeighbors) weightedLinks, minAbsCount = flattenLink(graphLinks) humanDb = getCgiVar("db", "hg19") @@ -1453,116 +1458,116 @@ geneStr = ", ".join(eGenes) if eName=="": return "%s" % geneStr else: return "%s (%s)" % (eName, geneStr) if eType == "family": geneStr = "/".join(eGenes) if eName=="": return "%s" % geneStr else: return "%s (%s)" % (eName, geneStr) def printDbRows(conn, rows, onlyDoc=None): " print a row from the ggEventDb table as html " - print '<ul class="more">' + print('<ul class="more">') # sort by database name for row in sorted(rows, key=operator.itemgetter(9)): eventId, causeType, causeName, causeGenes, themeType, themeName, themeGenes, \ relType, relSubtype, sourceDb, sourceId, sourceDesc, docIds, evidence = row if eventId.startswith("ppi_"): isPpi = True else: isPpi = False docSet = set(docIds.split("|")) if eventId.startswith("ppi_iref"): dbName, dbUrlPat = dbData["iref"] dbName = "IRef %s" % sourceDb.capitalize() else: dbName, dbUrlPat = dbData[sourceDb] url = dbUrlPat % sourceId - print "<li>" + print("<li>") if sourceDesc=="": if isPpi: sourceDesc = "Interaction" else: sourceDesc = "Reaction" - print '%s <a href="%s" target="_BLANK">%s</a>: ' % (dbName, url, sourceDesc) + print('%s <a href="%s" target="_BLANK">%s</a>: ' % (dbName, url, sourceDesc)) - print entToDesc(causeType, causeName, causeGenes) + print(entToDesc(causeType, causeName, causeGenes)) desc = "" if themeGenes!="": if isPpi: - print "—" # unicode long dash + print("—") # unicode long dash else: - print "→" # Unicode Arrow + print("→") # Unicode Arrow desc = entToDesc(themeType, themeName, themeGenes) - print desc + print(desc) if relType!="" or relSubtype!="": if relType!="" and relSubtype!="": - print "(%s, %s)" % (relType, relSubtype) + print("(%s, %s)" % (relType, relSubtype)) elif relType!="": - print "(%s)" % (relType) + print("(%s)" % (relType)) elif relSubtype!="": - print "(%s)" % (relSubtype) + print("(%s)" % (relSubtype)) if onlyDoc==None and len(docSet)!=0: if desc is not None and len(desc)>25: - print "<br>" - print prettyDocLinks(conn, sorted(docSet)) + print("<br>") + print(prettyDocLinks(conn, sorted(docSet))) if evidence!="" and evidence!="unknown": - print "<br>Evidence: <i>", evidence.replace("|", ", ").replace("_", " "), "</i>" + print("<br>Evidence: <i>", evidence.replace("|", ", ").replace("_", " "), "</i>") - print "</li>" - print "</ul>" + print("</li>") + print("</ul>") def showPwyPpiInfo(conn, gene1, gene2): " print pathway and PPI info about link " gene1, gene2 = sorted([gene1, gene2]) q = "SELECT ggEventDb.* FROM ggLinkEvent, ggEventDb " \ "WHERE gene1='%s' and gene2='%s' AND ggEventDb.eventId=ggLinkEvent.eventId" % (gene1,gene2) rows = sqlQuery(conn, q) # split db rows into ppi and pathway rows pwyRows, ppiRows = [], [] for r in rows: if r[0].startswith("ppi_"): ppiRows.append(r) else: pwyRows.append(r) if len(pwyRows)!=0: - print "<h3>Pathways - manually collected, often from reviews:</h3>" + print("<h3>Pathways - manually collected, often from reviews:</h3>") printDbRows(conn, pwyRows) if len(ppiRows)!=0: - print "<h3>Protein-Protein interactions - manually collected from original source literature:</h3>" - print '<p>Studies that report less than %d interactions are marked with *</p>' % LTCUTOFF + print("<h3>Protein-Protein interactions - manually collected from original source literature:</h3>") + print('<p>Studies that report less than %d interactions are marked with *</p>' % LTCUTOFF) printDbRows(conn, ppiRows) def markupSentence(row): " given a MSR-textmining row, print a sentence with the various detected words marked up in bold " sent = row.sentence tStart, tEnd = int(row.themeTokenStart), int(row.themeTokenEnd) cStart, cEnd = int(row.causeTokenStart), int(row.causeTokenEnd) trigToken = int(row.triggerTokenId) sentId = int(row.sentenceId) # put into temporary var to be able to replace " , " later parts = [] for i, word in enumerate(sent.split()): if i==tStart or i==cStart: if i==cStart: @@ -1597,45 +1602,45 @@ doneDocs.add(docInfo) yield row def printDocNlpResults(rows): " print text mining results for document-centered view " for row in iterUniqueInteractions(rows): causeGene, themeGene = row.causeGenes, row.themeGenes if "Negative" in row.relType: sym = "8867" # unicode right-tack elif "Positive" in row.relType: sym = "8594" # unicode right arrow else: sym = "8212" # unicode long dash - print '%s &#%s; %s: "' % (row.causeName, sym, row.themeName), - print markupSentence(row), - print '"<p>' + print('%s &#%s; %s: "' % (row.causeName, sym, row.themeName)) + print(markupSentence(row)) + print('"<p>') def printMsrNlpRows(rows): " print msrNlp table rows with marked-up snippets " phrases = [] for row in iterUniqueInteractions(rows): causeGene, themeGene = row.causeGenes, row.themeGenes #if addGenes: #print "%s → %s :" % (causeGene, themeGene) line = markupSentence(row) phrases.append(line) - print " ... ".join(phrases) + print(" ... ".join(phrases)) # the blacklist ist not used right now, as we cannot write to the database. # pending further discussions with senior engineers #def readBlackList(conn): #""" return flagged interactions as a set of (cause, theme, pmid (as str)) """ #centralDb = cfgOption("central.db") #blackList = set() #rows = sqlQuery(conn, "SELECT causeGene, themeGene, pmid from %s.ggFeedback" % centralDb) #for row in rows: #blackList.add( (row.causeGene, row.themeGene, str(row.pmid)) ) #return blackList def queryEventText(conn, gene1, gene2): " return rows from the ggEventText table " @@ -1682,114 +1687,114 @@ if showStar and int(row.resCount)<=LTCUTOFF: note = '<a href="#" title="Low-throughput publication">*</a>' #note = "*" text = "%s %s, %s %s" % (fAu, suffix, row.journal, row.year) mouseOver = None if row.title!="": mouseOver = row.title.replace('"', "") return docLink(row.docId, text=text, mouseOver=mouseOver)+note def showSnipsLink(conn, gene1, gene2): " show snippets for a gene pair " rows = queryEventText(conn, gene1, gene2) if len(rows)!=0: - print '<h3>Text-mined interactions from <A HREF="http://literome.azurewebsites.net/Network?gene1=%s&gene2=%s">Literome</A></h3>' % (gene1, gene2) + print('<h3>Text-mined interactions from <A HREF="http://literome.azurewebsites.net/Network?gene1=%s&gene2=%s">Literome</A></h3>' % (gene1, gene2)) byDoc = defaultdict(list) for row in rows: byDoc[row.docId].append(row) - for docId, rows in byDoc.iteritems(): - print prettyDocLink(rows[0], showStar=False), + for docId, rows in byDoc.items(): + print(prettyDocLink(rows[0], showStar=False)) disSuffix = "" if rows[0].context!="": contexts = rows[0].context.split("|") if len(contexts)>1: suffix = "..." else: suffix = "" disSuffix = "(%s%s)" % (contexts[0], suffix) - print "%s :" % disSuffix + print("%s :" % disSuffix) printMsrNlpRows(rows) - print "<br>" + print("<br>") def showLink(link): " print details page with db info and snippets for a gene interaction " if ":" not in link: errAbort("'link' CGI parameter has to contain a colon-separated pair of genes, like PITX2:TBX5") gene1, gene2 = link.split(":") gene1, gene2 = sorted([gene1, gene2]) gene1 = gene1.upper() gene2 = gene2.upper() lastGene = getCgiVar("lastGene") if lastGene is not None: backUrl = makeSelfUrl({"gene":lastGene, "link":None}) - print "<p><a href='%s'>◀ Back to %s</a></p>" % (backUrl, lastGene) + print("<p><a href='%s'>◀ Back to %s</a></p>" % (backUrl, lastGene)) - print "<h3>%s — %s</h3>" % (gene1, gene2)# unicode long dash + print("<h3>%s — %s</h3>" % (gene1, gene2))# unicode long dash conn = sqlConnect(GGDB) #flagLink = makeSelfLink("Report data error", {"flag":"%s:%s" % (gene1, gene2)}, clear=True) #print ('%s<p>' % flagLink) showPwyPpiInfo(conn, gene1, gene2) showSnipsLink(conn, gene1, gene2) def makeRefString(articleData): """ prepare a string that describes the citation: vol, issue, page, etc of journal """ refParts = [articleData.journal] if articleData.year!="": refParts[0] += (" "+articleData.year) #if articleData.vol!="": #refParts.append("Vol "+articleData.vol) #if articleData.issue!="": #refParts.append("Issue "+articleData.issue) #if articleData.page!="": #refParts.append("Page "+articleData.page) return ", ".join(refParts) def showArtInfo(conn, pmid): " show basic pubmed metadata for article " q = "SELECT * from ggDoc where docId='%s'" % (str(pmid)) rows = sqlQuery(conn, q) if len(rows)==0: - print "No metadata for docId PMID %s" % str(pmid) + print("No metadata for docId PMID %s" % str(pmid)) return p = rows[0] - print "<small>%s, " % makeRefString(p) - print pubmedLink(p.docId) - print "</small><p>" - print '<h4 style="width:900px">%s</h4>' % (pubmedLink(pmid, p.title)) - print "%s<p>" % p.authors - print '<div style="width: 900px">' - print p.abstract - print '</div><br>' + print("<small>%s, " % makeRefString(p)) + print(pubmedLink(p.docId)) + print("</small><p>") + print('<h4 style="width:900px">%s</h4>' % (pubmedLink(pmid, p.title))) + print("%s<p>" % p.authors) + print('<div style="width: 900px">') + print(p.abstract) + print('</div><br>') if p.context!="": - print "<b>Diseases/Pathways annotated by Medline MESH: </b>", p.context.replace("|", ", "), "<br>" + print("<b>Diseases/Pathways annotated by Medline MESH: </b>", p.context.replace("|", ", "), "<br>") - print "<small>Document information provided by NCBI PubMed<p></small>" + print("<small>Document information provided by NCBI PubMed<p></small>") return p.resCount #def printPwyRows(rows, showPmids=True): #dbToTypePmids = defaultdict(dict) # db -> intType -> list of pmid #for row in rows: #dbToTypePmids[row.db].setdefault(row.intType, []).append( (row.pmid, row.causeGene, row.themeGene )) # print "<ul>" # for db, typePmids in dbToTypePmids.iteritems(): # for intType, pmids in typePmids.iteritems(): # # print "<li>" # print "%s (%s): " % (db, intType.lower().replace("_", " ")) # links = [] @@ -1827,60 +1832,60 @@ print("Dashed line = No text mining data") else: printDocNlpResults(rows) print("<h3>Manually curated Databases</h3>") query = "SELECT ggEventDb.* FROM ggDocEvent, ggEventDb " \ "WHERE ggDocEvent.docId='%s' AND ggEventDb.eventId=ggDocEvent.eventId " % pmid rows = sqlQuery(conn, query) if len(rows)==0: print("No curated data.") else: printDbRows(conn, rows, onlyDoc=pmid) if resCount!=0: - print "In total, %d gene pairs are associated to this article in curated databases" % resCount + print("In total, %d gene pairs are associated to this article in curated databases" % resCount) #if len(rows)==0: #rint("No data in pathway databases for PMID %d" % pmid) #else# #printPwyRow(row) def flagInteraction(param): " show flag interaction dialog with comment box " fields = param.split(":") if len(fields)!=2: errAbort( "illegal CGI parameter") causeGene, themeGene = fields - print "<h3>Interaction %s - %s</h3>" % (causeGene, themeGene) + print("<h3>Interaction %s - %s</h3>" % (causeGene, themeGene)) conn = sqlConnect(GGDB) rows = queryEventText(conn, causeGene, themeGene) print ("<p>") print ("Thank you for reporting errors, e.g.") print("<ul><li>not true (e.g. the authors state that the interaction does not happen )</li>") print("<li>text mining errors (the authors did not say anything about this particular interaction)</li>") print("</ul>") print("This makes it easier for us to improve the text mining system or database imports.<br>") print("You can leave your email address in the comment if you want to give us the possibility to comment.<P>") print ("Optional comment: <br>") - print ('<FORM method="GET" action="%s">' % basename(__file__)) - print ('<INPUT TYPE="HIDDEN" NAME="remove" VALUE="%s"></INPUT>' % param) + print(('<FORM method="GET" action="%s">' % basename(__file__))) + print(('<INPUT TYPE="HIDDEN" NAME="remove" VALUE="%s"></INPUT>' % param)) print ('<TEXTAREA rows="6" cols="50" name="comment"></TEXTAREA>') print ("<P>") print ('<INPUT TYPE="SUBMIT" name="submit" value="Report Interaction as inaccurate"></INPUT>') print ('</FORM>') #printMsrNlpRows(rows) showSnipsLink(conn, causeGene, themeGene) #def namedtuple_factory(cursor, row): #""" #used as a function pointer to sqlite to have it return structs with names and not just arrays #""" #fields = [col[0] for col in cursor.description] #Row = collections.namedtuple("Row", fields) #return Row(*row) @@ -1902,31 +1907,31 @@ ip = cgi.escape(os.environ["REMOTE_ADDR"]) conn = hConnectCentral() if not sqlTableExists(conn, "ggFeedback"): sqlQuery(conn, "CREATE TABLE ggFeedback (causeGene varchar(255), themeGene varchar(255), pmid varchar(255), " \ "comment varchar(10000), time TIMESTAMP, ip varchar(255), INDEX allIdx (causeGene, themeGene, pmid));") cur = conn.cursor() cur.execute("INSERT INTO ggFeedback VALUES (%s, %s, %s, NOW(), %s, %s)", (causeGene, themeGene, 0, comment, ip)) cur.close() conn.close() print ("Interaction successfully removed.<p>") lastGene = getCgiVar("lastGene") linkUrl = makeSelfUrl({"gene":None, "link":"%s:%s" % (causeGene, themeGene), "lastGene":lastGene}) - print ('Return to the <a href="%s">Interaction page</a></p>' % linkUrl) + print(('Return to the <a href="%s">Interaction page</a></p>' % linkUrl)) def parseGraphArgs(): " get the arguments to build a graph from the CGI parameters " gene = getCgiVar("gene") if gene is None: gene = "MTOR" gene = gene.rstrip(":") gene = gene.split()[0] gene = gene.upper() alg = getCgiVar("alg") if alg==None: alg= "neato" @@ -1949,45 +1954,45 @@ for row in sqlQuery(conn, q): for g1 in row.causeGenes.split("|"): for g2 in row.themeGenes.split("|"): pair = tuple(sorted([g1, g2])) pairs[row.sourceDb].add(pair) q = "SELECT docId, causeGenes, themeGenes from ggEventText" pairToPmids = defaultdict(set) for row in sqlQuery(conn, q): for g1 in row.causeGenes.split("|"): for g2 in row.themeGenes.split("|"): pair = tuple(sorted([g1, g2])) pairToPmids[pair].add(row.docId) pairs["literome"].add(pair) - for pair, pmids in pairToPmids.iteritems(): + for pair, pmids in pairToPmids.items(): if len(pmids)>1: pairs["literome (>= 2 PMIDs)"].add(pair) return pairs def showStats(): " " - print "<h3>Databases - number of unique pairs</h3>" - print "<ul>" + print("<h3>Databases - number of unique pairs</h3>") + print("<ul>") conn = sqlConnect(GGDB) pairs = uniquePairs(conn) for db, pairSet in sorted(pairs.items()): - print "<li>%s: %d" % (db, len(pairSet)) - print "</ul>" + print("<li>%s: %d" % (db, len(pairSet))) + print("</ul>") def htmlMiddle(): " print html middle part " sys.stdout.flush() flag = getCgiVar("flag") if flag!=None: flagInteraction(flag) exit(0) remove = getCgiVar("remove") if remove!=None: captcha = getCgiVar("captcha") comment = getCgiVar("comment", allowAnyChar=True, maxLen=10000) removeInteraction(remove, captcha, comment)