33d37d6a60180fdc11fbdd59641c822579f85995
max
  Wed May 24 15:04:20 2017 -0700
adding help page for mirrors where graphviz may not work, refs #13634

diff --git src/hg/hgGeneGraph/hgGeneGraph src/hg/hgGeneGraph/hgGeneGraph
index f8cb051..56493a6 100755
--- src/hg/hgGeneGraph/hgGeneGraph
+++ src/hg/hgGeneGraph/hgGeneGraph
@@ -578,65 +578,97 @@
     if count > 100:
         thick = 1
     elif count > 50:
         thick = 2
     elif count > 10:
         thick = 3.5
     else:
         thick = 2
     return thick
 
 def which(binPath):
     " find full path of binary "
     import distutils.spawn
     return distutils.spawn.find_executable(binPath)
 
-def runDot(fname, alg, format="png"):
-    " run dot and return tuple outFname, outMapFname "
-    outFname = splitext(fname)[0]+"."+format
-    outMap = splitext(fname)[0]+".map"
-    binPath = cfgOption("graphvizPath", "dot")
+def findDot():
+    """ this would never be run on the RR but only on mirrors, because we specify it in hg.conf.
+    It will try to find 'dot' and if it cannot find it, will fall back to cgi-bin/loader/dot_static:
 
-    if which(binPath) is None:
-        print("Could not find the command %s<p>" % binPath)
-        print("This usually means that on this UCSC Genome Browser, GraphViz is not installed.")
-        print("To install GraphViz, ask the Administrator of this server to run one of the following commands:<br>")
+        - if anything is specified in hg.conf, it will use that
+        - if it can find "dot" in the PATH, it will use that next (dot
+          installed from the repos will always work)
+        - if that doesn't work either, we run cgi-bin/loader/dot_static (our
+          static version may fail due to wrong glibc version) """
+    binPath = cfgOption("graphvizPath")
+
+    if binPath is not None and binPath.strip()!="":
+        return binPath
+
+    installedBin = which("dot")
+
+    if installedBin is None:
+        staticPath = join("loader", "dot_static")
+        if not isfile(staticPath):
+            return None
+        else:
+            return staticPath
+    else:
+        sys.stderr.write("Using graphviz binary %s\n" % installedBin)
+        return installedBin
+
+def printDotErrorHelpAndExit():
+    print("This often means that on this UCSC Genome Browser, GraphViz is not installed or is too old and ")
+    print("that the supplied program dot_static also did not work. It can also mean that the configuration option")
+    print("graphvizPath in hg.conf specifies a program that does not work.<p>")
+    print("To resolve any of these problems, you will have to contact the system administrator of this Genome Browser server.<p>")
+    print("To install GraphViz, ask the administrator of this server to run one of the following commands:<br>")
     print("<tt>sudo apt-get install graphviz</tt><br>")
     print("<tt>sudo wget http://www.graphviz.org/graphviz-rhel.repo -o /etc/yum/repos.d/graphviz.rhel.repo; sudo yum install graphviz*</tt><br>")
     print("<p>")
-        print("Alternatively, you can compile GraphViz from source and specify the full path to 'dot' with the option 'graphvizPath' in cgi-bin/hg.conf.")
+    print("If you have graphviz installed but this error message still appears, then the ")
+    print("graphviz version may be too old.<p>")
+    print("Also, the Genome Browser ships with a statically compiled version of")
+    print("dot, cgi-bin/loader/dot_static. This version should work with a")
+    print("64bit linux, unless the installed glibc is too different from the one compiled into dot_static.<p>")
+    print("As a last resort, you can compile GraphViz from source and specify the full path to 'dot'")
+    print("with the option 'graphvizPath' in cgi-bin/hg.conf.<br>")
+    print("If you see this message on a website managed by UCSC, please contact genome-www@soe.ucsc.edu immediately.<p>")
     exit(0)
 
+def runDot(fname, alg, format="png"):
+    """ run dot and return tuple outFname, outMapFname. Makes a real effort to find a working version of dot,
+        see findDot()
+    """
+    outFname = splitext(fname)[0]+"."+format
+    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]
     # 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'. <br>" % "".join(cmd))
-        print("This means that on this UCSC Genome Browser Installation too old.")
-        print("To update GraphViz to a more recent version, ask the Administrator of this ")
-        print("server to try running one of these commands:<br>")
-        print("<tt>sudo apt-get install graphviz</tt><br>")
-        print("<tt>sudo wget http://www.graphviz.org/graphviz-rhel.repo -o ")
-        print("/etc/yum/repos.d/graphviz.rhel.repo;")
-        print("sudo yum install graphviz*</tt><br>")
-        print("<p>")
-        print("If this does not work, you may have to compile GraphViz from source and")
-        print("specify the 'dot' binary with the option graphvizPath cgi-bin/hg.conf.")
-        exit(0)
+        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():
         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.
@@ -665,35 +697,39 @@
         d = {}
         ttLines = geneDescs[g]
         if g in geneAnnots:
             #d["color"]="#3636E2"
             geneAnnotVal, geneAnnotGrey = geneAnnots[g]
             transVal = 200 - (geneAnnotGrey*25) # scale to 55-255
             transHex = "%0.2X" % transVal # convert to hex
             d["fillcolor"]="#"+"".join([transHex]*3) # concat three times, creates a grey-value
             d["fontcolor"] = "white"
             ttLines.append("<b>%s</b>: %s" % (annotLabel, geneAnnotVal))
         d["tooltip"] = " &lt;br&gt; ".join(ttLines) # separate with encoded html linebreaks
         url = makeSelfUrl({"gene":g})
         url = url.replace("&", "&amp;") # otherwise invalid SVG will result
         d["URL"] = url
         if g==targetGene:
+            if g not in geneAnnots:
                 d["penwidth"] = "1"
                 d["fontcolor"] = "black"
                 d["fillcolor"] = "yellow"
-            #d["style"] = "bold"
                 d["color"] = "blue"
+            else:
+                d["penwidth"] = "3"
+                d["color"] = "yellow"
+
         ofh.write('"%s" %s;\n' % (g, dictToDot(d)))
 
     # write the links between genes
     for gene1, gene2, score, docCount, dbs, tags, minResCount, snippet in links:
         dbs = [x.upper() for x in dbs if x!='']
 
         addStr = ""
 
         # based on http://www.w3schools.com/tags/ref_colorpicker.asp?colorhex=F0F8FF
         color = None
         if "pwy" in tags or ("ppi" in tags and minResCount<=LTCUTOFF):
             color = LTCOLOR+TRANSPARENCY #"#000099A0"
         elif "ppi" in tags:
             color = HTCOLOR+TRANSPARENCY # "#8080CCA0"
 
@@ -1260,31 +1296,31 @@
         linkStyle = None
         if color != None:
             linkStyle = 'color:%s' % color
 
         newGeneLink = makeSelfLink("&#9656;", {"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, "link":"%s:%s" % (g, gene)},
+        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))
 
         i += 1
         if i % rowSize == 0:
             print "</tr><tr>"
 
     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: