diff options
author | root | 2012-05-08 18:39:56 -0500 |
---|---|---|
committer | root | 2012-05-08 18:39:56 -0500 |
commit | ea46f42ee640928b92947bfb204c41a482d80937 (patch) | |
tree | 9b27a4eb852d12539b543c3efee9d2a47ef470f3 /web/webqtl/networkGraph | |
parent | 056b5253fc3857b0444382aa39944f6344dc1ceb (diff) | |
download | genenetwork2-ea46f42ee640928b92947bfb204c41a482d80937.tar.gz |
Add all the source codes into the github.
Diffstat (limited to 'web/webqtl/networkGraph')
-rwxr-xr-x | web/webqtl/networkGraph/GraphPage.py | 46 | ||||
-rwxr-xr-x | web/webqtl/networkGraph/ProcessedPoint.py | 49 | ||||
-rwxr-xr-x | web/webqtl/networkGraph/__init__.py | 0 | ||||
-rwxr-xr-x | web/webqtl/networkGraph/nGraphException.py | 33 | ||||
-rwxr-xr-x | web/webqtl/networkGraph/networkGraphPage.py | 335 | ||||
-rw-r--r-- | web/webqtl/networkGraph/networkGraphPageBody.py | 697 | ||||
-rw-r--r-- | web/webqtl/networkGraph/networkGraphUtils.py | 750 |
7 files changed, 1910 insertions, 0 deletions
diff --git a/web/webqtl/networkGraph/GraphPage.py b/web/webqtl/networkGraph/GraphPage.py new file mode 100755 index 00000000..b0d4063d --- /dev/null +++ b/web/webqtl/networkGraph/GraphPage.py @@ -0,0 +1,46 @@ +# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) +# at rwilliams@uthsc.edu and xzhou15@uthsc.edu +# +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) +# +# Created by GeneNetwork Core Team 2010/08/10 +# +# Last updated by GeneNetwork Core Team 2010/10/20 + +class GraphPage: + + def __init__(self, imagefile, mapfile): + # open and read the image map file + try: + mapData = open(mapfile).read() + except: + mapData = "<p><b>Unable to load image map with trait links</b></p>" + + self.content = '''%s + <img border="0" alt="the graph" src="%s" usemap="#webqtlGraph" /> + ''' % (mapData, imagefile) + + def writeToFile(self, filename): + """ + Output the contents of this HTML page to a file + """ + handle = open(filename, "w") + handle.write(self.content) + handle.close() diff --git a/web/webqtl/networkGraph/ProcessedPoint.py b/web/webqtl/networkGraph/ProcessedPoint.py new file mode 100755 index 00000000..6eb855e3 --- /dev/null +++ b/web/webqtl/networkGraph/ProcessedPoint.py @@ -0,0 +1,49 @@ +# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) +# at rwilliams@uthsc.edu and xzhou15@uthsc.edu +# +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) +# +# Created by GeneNetwork Core Team 2010/08/10 +# +# Last updated by GeneNetwork Core Team 2010/10/20 + +# ProcessedPoint: to store information about the relationship between +# two particular traits +# ProcessedPoint represents the calculations made by the program + +class ProcessedPoint: + + def __init__(self, i, j): + self.i = i + self.j = j + + def __eq__(self, other): + # print "ProcessedPoint: comparing %s and %s" % (self, other) + return (self.i == other.i and + self.j == other.j and + self.value == other.value and + self.color == other.color) + + def __str__(self): + return "(%s,%s,%s,%s,%s)" % (self.i, + self.j, + self.value, + self.length, + self.color) diff --git a/web/webqtl/networkGraph/__init__.py b/web/webqtl/networkGraph/__init__.py new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/web/webqtl/networkGraph/__init__.py diff --git a/web/webqtl/networkGraph/nGraphException.py b/web/webqtl/networkGraph/nGraphException.py new file mode 100755 index 00000000..d492fca9 --- /dev/null +++ b/web/webqtl/networkGraph/nGraphException.py @@ -0,0 +1,33 @@ +# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) +# at rwilliams@uthsc.edu and xzhou15@uthsc.edu +# +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) +# +# Created by GeneNetwork Core Team 2010/08/10 +# +# Last updated by GeneNetwork Core Team 2010/10/20 + +class nGraphException(Exception): + def __init__(self, message): + self.message = message + + def __str__(self): + return "Network Graph Exception: %s" % self.message + diff --git a/web/webqtl/networkGraph/networkGraphPage.py b/web/webqtl/networkGraph/networkGraphPage.py new file mode 100755 index 00000000..fb4021f0 --- /dev/null +++ b/web/webqtl/networkGraph/networkGraphPage.py @@ -0,0 +1,335 @@ +# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) +# at rwilliams@uthsc.edu and xzhou15@uthsc.edu +# +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) +# +# Created by GeneNetwork Core Team 2010/08/10 +# +# Last updated by NL 2010/02/11 + +#!/usr/bin/python +# networkGraph.py +# Author: Stephen Pitts +# 6/2/2004 +# +# a script to take a matrix of data from a WebQTL job and generate a +# graph using the neato package from GraphViz +# +# See graphviz for documentation of the parameters +# + + +#from mod_python import apache, util, Cookie +#import cgi +import tempfile +import os +import time +import sys +import cgitb +import string + +from htmlgen import HTMLgen2 as HT + +from base.templatePage import templatePage +import networkGraphUtils +from base import webqtlConfig +from utility import webqtlUtil +from base.webqtlTrait import webqtlTrait +import compareCorrelates.trait as smpTrait +from GraphPage import GraphPage +from networkGraphPageBody import networkGraphPageBody +from correlationMatrix.tissueCorrelationMatrix import tissueCorrelationMatrix + +cgitb.enable() + + +class networkGraphPage(templatePage): + + def __init__(self,fd,InputData=None): + + templatePage.__init__(self, fd) + + if not self.openMysql(): + return + + if not fd.genotype: + fd.readGenotype() + + self.searchResult = fd.formdata.getvalue('searchResult') + + self.tissueProbeSetFeezeId = "1" #XZ, Jan 03, 2010: currently, this dataset is "UTHSC Illumina V6.2 RankInv B6 D2 average CNS GI average (May 08)" + TissueCorrMatrixObject = tissueCorrelationMatrix(tissueProbeSetFreezeId=self.tissueProbeSetFeezeId) + + if type("1") == type(self.searchResult): + self.searchResult = string.split(self.searchResult, '\t') + + if (not self.searchResult or (len(self.searchResult) < 2)): + heading = 'Network Graph' + detail = ['You need to select at least two traits in order to generate Network Graph.'] + self.error(heading=heading,detail=detail) + print 'Content-type: text/html\n' + self.write() + return + + if self.searchResult: + if len(self.searchResult) > webqtlConfig.MAXCORR: + heading = 'Network Graph' + detail = ['In order to display Network Graph properly, Do not select more than %d traits for Network Graph.' % webqtlConfig.MAXCORR] + self.error(heading=heading,detail=detail) + print 'Content-type: text/html\n' + self.write() + return + else: + pass + + traitList = [] + traitDataList = [] + + for item in self.searchResult: + thisTrait = webqtlTrait(fullname=item, cursor=self.cursor) + thisTrait.retrieveInfo() + thisTrait.retrieveData(fd.strainlist) + traitList.append(thisTrait) + traitDataList.append(thisTrait.exportData(fd.strainlist)) + + else: + heading = 'Network Graph' + detail = [HT.Font('Error : ',color='red'),HT.Font('Error occurs while retrieving data from database.',color='black')] + self.error(heading=heading,detail=detail) + print 'Content-type: text/html\n' + self.write() + return + + NNN = len(traitList) + + if NNN < 2: + templatePage.__init__(self, fd) + heading = 'Network Graph' + detail = ['You need to select at least two traits in order to generate a Network Graph'] + print 'Content-type: text/html\n' + self.write() + return + else: + pearsonArray = [([0] * (NNN))[:] for i in range(NNN)] + spearmanArray = [([0] * (NNN))[:] for i in range(NNN)] + GeneIdArray = [] + GeneSymbolList = [] #XZ, Jan 03, 2011: holds gene symbols for calculating tissue correlation + traitInfoArray = [] + + i = 0 + nnCorr = len(fd.strainlist) + for i, thisTrait in enumerate(traitList): + names1 = [thisTrait.db.name, thisTrait.name, thisTrait.cellid] + for j, thisTrait2 in enumerate(traitList): + names2 = [thisTrait2.db.name, thisTrait2.name, thisTrait2.cellid] + if j < i: + corr,nOverlap = webqtlUtil.calCorrelation(traitDataList[i],traitDataList[j],nnCorr) + pearsonArray[i][j] = corr + pearsonArray[j][i] = corr + elif j == i: + pearsonArray[i][j] = 1.0 + spearmanArray[i][j] = 1.0 + else: + corr,nOverlap = webqtlUtil.calCorrelationRank(traitDataList[i],traitDataList[j],nnCorr) + spearmanArray[i][j] = corr + spearmanArray[j][i] = corr + + GeneId1 = None + tmpSymbol = None + if thisTrait.db.type == 'ProbeSet': + try: + GeneId1 = int(thisTrait.geneid) + except: + GeneId1 = 0 + if thisTrait.symbol: + tmpSymbol = thisTrait.symbol.lower() + GeneIdArray.append(GeneId1) + GeneSymbolList.append(tmpSymbol) + + _traits = [] + _matrix = [] + + for i in range(NNN): + turl = webqtlConfig.CGIDIR + webqtlConfig.SCRIPTFILE + '?FormID=showDatabase&database=%s&ProbeSetID=%s' % (traitList[i].db.name, traitList[i].name) + if traitList[i].cellid: + turl += "&CellID=%s" % traitList[i].cellid + + if traitList[i].db.type == 'ProbeSet': + if traitList[i].symbol: + _symbol = traitList[i].symbol + else: + _symbol = 'unknown' + elif traitList[i].db.type == 'Publish': + _symbol = traitList[i].name + if traitList[i].confidential: + if webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=traitList[i].authorized_users): + if traitList[i].post_publication_abbreviation: + _symbol = traitList[i].post_publication_abbreviation + else: + if traitList[i].pre_publication_abbreviation: + _symbol = traitList[i].pre_publication_abbreviation + else: + if traitList[i].post_publication_abbreviation: + _symbol = traitList[i].post_publication_abbreviation + + #XZ, 05/26/2009: Xiaodong add code for Geno data + elif traitList[i].db.type == 'Geno': + _symbol = traitList[i].name + else: + _symbol = traitList[i].description + #####if this trait entered by user + if _symbol.__contains__('entered'): + _symbol = _symbol[:_symbol.index('entered')] + #####if this trait generaged by genenetwork + elif _symbol.__contains__('generated'): + _symbol = _symbol[_symbol.rindex(':')+1:] + + newTrait = smpTrait.Trait(name=str(traitList[i]), href=turl, symbol=_symbol) + newTrait.color = "black" + _traits.append(newTrait) + + for j in range(i+1, NNN): + dataPoint = smpTrait.RawPoint(i, j) + dataPoint.spearman = spearmanArray[i][j] + dataPoint.pearson = pearsonArray[i][j] + + #XZ: get literature correlation info. + if GeneIdArray[i] and GeneIdArray[j]: + if GeneIdArray[i] == GeneIdArray[j]: + dataPoint.literature = 1 + else: + self.cursor.execute("SELECT Value from LCorrRamin3 WHERE (GeneId1 = %d and GeneId2 = %d) or (GeneId1 = %d and GeneId2 = %d)" % (GeneIdArray[i], GeneIdArray[j], GeneIdArray[j], GeneIdArray[i])) + try: + dataPoint.literature = self.cursor.fetchone()[0] + except: + dataPoint.literature = 0 + else: + dataPoint.literature = 0 + + #XZ: get tissue correlation info + if GeneSymbolList[i] and GeneSymbolList[j]: + dataPoint.tissue = 0 + geneSymbolPair = [] + geneSymbolPair.append(GeneSymbolList[i]) + geneSymbolPair.append(GeneSymbolList[j]) + corrArray,pvArray = TissueCorrMatrixObject.getCorrPvArrayForGeneSymbolPair(geneNameLst=geneSymbolPair) + if corrArray[1][0]: + dataPoint.tissue = corrArray[1][0] + else: + dataPoint.tissue = 0 + + _matrix.append(dataPoint) + + OrigDir = os.getcwd() + + sessionfile = fd.formdata.getvalue('session') + + inputFilename = fd.formdata.getvalue('inputFile') + + #If there is no sessionfile generate one and dump all matrix/trait values + if not sessionfile: + filename = webqtlUtil.generate_session() + webqtlUtil.dump_session([_matrix, _traits], os.path.join(webqtlConfig.TMPDIR, filename + '.session')) + sessionfile = filename + + startTime = time.time() + + #Build parameter dictionary used by networkGraphPage class using buildParamDict function + params = networkGraphUtils.buildParamDict(fd, sessionfile) + + nodes = len(_traits) + rawEdges = len(_matrix) + + if params["tune"] == "yes": + params = networkGraphUtils.tuneParamDict(params, nodes, rawEdges) + + matrix = networkGraphUtils.filterDataMatrix(_matrix, params) + + optimalNode = networkGraphUtils.optimalRadialNode(matrix) + + if not inputFilename: + inputFilename = tempfile.mktemp() + + inputFilename = webqtlConfig.IMGDIR + inputFilename.split("/")[2] + + #writes out 4 graph files for exporting + graphFile = "/image/" + networkGraphUtils.writeGraphFile(matrix, _traits, inputFilename, params) + + networkGraphUtils.processDataMatrix(matrix, params) + + edges = 0 + + for edge in matrix: + if edge.value != 0: + edges +=1 + + for trait in _traits: + trait.name = networkGraphUtils.fixLabel(trait.name) + + RootDir = webqtlConfig.IMGDIR + RootDirURL = "/image/" + + + + #This code writes the datafile that the graphviz function runNeato uses to generate the + #"digraph" file that defines the graphs parameters + datafile = networkGraphUtils.writeNeatoFile(matrix=matrix, traits=_traits, filename=inputFilename, GeneIdArray=GeneIdArray, p=params) + + #Generate graph in various file types + layoutfile = networkGraphUtils.runNeato(datafile, "dot", "dot", params["gType"]) # XZ, 09/11/2008: add module name + # ZS 03/04/2010 This second output file (layoutfile_pdf) is rotated by 90 degrees to prevent an issue with pdf output being cut off at the edges + layoutfile_pdf = networkGraphUtils.runNeato(datafile + "_pdf", "dot", "dot", params["gType"]) # ZS 03/04/2010 + pngfile = networkGraphUtils.runNeato(layoutfile, "png", "png", params["gType"]) + mapfile = networkGraphUtils.runNeato(layoutfile, "cmapx", "cmapx", params["gType"])# XZ, 09/11/2008: add module name + giffile = networkGraphUtils.runNeato(layoutfile, "gif", "gif", params["gType"])# XZ, 09/11/2008:add module name + psfile = networkGraphUtils.runNeato(layoutfile_pdf, "ps", "ps", params["gType"])# XZ, 09/11/2008: add module name + pdffile = networkGraphUtils.runPsToPdf(psfile, params["width"], params["height"])# XZ, 09/11/2008: add module name + + #This generates text files in XGGML (standardized graphing language) and plain text + #so the user can create his/her own graphs in a program like Cytoscape + + htmlfile1 = datafile + ".html" + htmlfile2 = datafile + ".graph.html" + + os.chdir(OrigDir) + + #This generates the graph in various image formats + giffile = RootDirURL + giffile + pngfile = RootDirURL + pngfile + pdffile = RootDirURL + pdffile + endTime = time.time() + totalTime = endTime - startTime + + os.chdir(RootDir) + + page2 = GraphPage(giffile, mapfile) + page2.writeToFile(htmlfile2) + + #This generates the HTML for the body of the Network Graph page + page1 = networkGraphPageBody(fd, matrix, _traits, htmlfile2, giffile, pdffile, nodes, edges, rawEdges, totalTime, params, page2.content, graphFile, optimalNode) + + #Adds the javascript colorSel to the body to allow line color selection + self.dict["js1"] = '<SCRIPT SRC="/javascript/colorSel.js"></SCRIPT><BR>' + #self.dict["js1"] += '<SCRIPT SRC="/javascript/networkGraph.js"></SCRIPT>' + + #Set body of current templatePage to body of the templatePage networkGraphPage + self.dict['body'] = page1.dict['body'] + + diff --git a/web/webqtl/networkGraph/networkGraphPageBody.py b/web/webqtl/networkGraph/networkGraphPageBody.py new file mode 100644 index 00000000..22b49ccd --- /dev/null +++ b/web/webqtl/networkGraph/networkGraphPageBody.py @@ -0,0 +1,697 @@ +# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) +# at rwilliams@uthsc.edu and xzhou15@uthsc.edu +# +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) +# +# Created by GeneNetwork Core Team 2010/08/10 +# +# Last updated by GeneNetwork Core Team 2010/10/20 + +from base.templatePage import templatePage +import networkGraphUtils +from base import webqtlConfig + + +# our output representation is fairly complicated +# because we use an iframe to represent the image and the image has +# an associated image map, our output is actually three files +# 1) a networkGraphPage instance -- the URL we pass to the user +# 2) a GraphPage with the image map and the graph -- this page has to be +# there to pass the imagemap data to the browser +# 3) a PNG graph file itself + +class networkGraphPageBody(templatePage): + """ + Using the templatePage class, we build an HTML shell for the graph + that displays the parameters used to generate it and allows the + user to redraw the graph with different parameters. + + The way templatePage works, we build the page in pieces in the __init__ + method and later on use the inherited write method to render the page. + """ + + def __init__(self, fd, matrix, traits, imageHtmlName, imageName, pdfName, nodes, + edges, rawEdges, totalTime, p, graphcode, graphName, optimalNode): + + templatePage.__init__(self, fd) + + if p["printIslands"] == 0: + island = "Only nodes with edges" + else: + island = "All nodes" + + body = """ <td><P class='title'>Network Graph</P> + <Blockquote><p>The %s nodes in the + graph below show the selected traits. %s are displayed. The + %s edges between the nodes, filtered from the %s total edges and + drawn as %s, show <b>%s</b> correlation + coefficients greater than %s or less than -%s. The graph\'s + canvas is %s by %s cm, and the node + labels are drawn with a %s point font, and the edge + labels are drawn with a %s point font. Right-click or control-click + on the graph to save it to disk for further manipulation. See + below for the trait key, and graph options.</p> + """ % (nodes, island, edges, rawEdges, + p["splineName"], p["correlationName"], + p["kValue"], + p["kValue"], + p["width"], + p["height"], + p["nfontsize"], + p["cfontsize"]) + + #Generate a list of symbols for the central node selection drop-down menu + + symbolList = networkGraphUtils.generateSymbolList(traits) + + #Some of these hidden variables (CellID, CellID2, ProbesetID2, etc) exist + #to be used by the javascript functions called when a user clicks on an edge or node + + formParams = ''' + + <form name="showDatabase" action="%s%s" METHOD="POST" enctype="multipart/form-data"> + + <input type="hidden" name="filename" value="%s" /> + <input type="hidden" name="exportFilename" value="%s" /> + <input type="hidden" name="progress" value="1" /> + <input type="hidden" name="database" value="_" /> + <input type="hidden" name="database2" value="_" /> + <input type="hidden" name="ProbeSetID" value="_" /> + <input type="hidden" name="ProbeSetID2" value="_" /> + <input type="hidden" name="CellID" value="_" /> + <input type="hidden" name="CellID2" value="_" /> + <input type="hidden" name="tune" value="no" /> + <input type="hidden" name="ShowLine" value="ON"> + <input type="hidden" name="ShowStrains" value="ON"> + <input type="hidden" name="FormID" value="showDatabase" /> + <input type="hidden" name="RISet" value="%s" /> + <input type="hidden" name="incparentsf1" value="ON" /> + <input type="hidden" name="session" value="%s" /> + <input type="hidden" name="searchResult" id="searchResult" value="%s" /> + <input type="hidden" name="symbolList" id="symbolList" value="%s" /> + <input type="hidden" name="optimalNode" id="optimalNode" value="%s" /> + <input type="hidden" name="rankOrder" id="rankOrder" value="_" /> + <input type="hidden" name="X_geneID" id="X_geneID" value="_" /> + <input type="hidden" name="Y_geneID" id="Y_geneID" value="_" /> + <input type="hidden" name="X_geneSymbol" id="X_geneSymbol" value="_" /> + <input type="hidden" name="Y_geneSymbol" id="Y_geneSymbol" value="_" /> + <input type="hidden" name="TissueProbeSetFreezeId" id="TissueProbeSetFreezeId" value="1" /> + ''' % (webqtlConfig.CGIDIR, + webqtlConfig.SCRIPTFILE, + p["filename"], + graphName, + p["riset"], + p["session"], + p["searchResult"], + symbolList, + optimalNode) + + body += formParams + + #Adds the html generated by graphviz that displays the graph itself + body += graphcode + + #Initializes all form values + + selected = ["","","",""] + selected[p["whichValue"]] = "CHECKED" + + selected3 = ["",""] + if p["splines"] == "yes": + selected3[0] = "CHECKED" + else: + selected3[1] = "CHECKED" + + selected5 = ["",""] + if p["nodeshape"] == "yes": + selected5[0] = "CHECKED" + else: + selected5[1] = "CHECKED" + + selected7 = ["",""] + if p["nodelabel"] == "yes": + selected7[0] = "CHECKED" + else: + selected7[1] = "CHECKED" + + selected6 = ["",""] + if p["dispcorr"] == "yes": + selected6[0] = "CHECKED" + else: + selected6[1] = "CHECKED" + + selected4 = ["", ""] + selected4[p["printIslands"]] = "CHECKED" + + selectedExportFormat = ["",""] + if p["exportFormat"] == "xgmml": + selectedExportFormat[0] = "selected='selected'" + elif p["exportFormat"] == "plain": + selectedExportFormat[1] = "selected='selected'" + + selectedTraitType = ["",""] + if p["traitType"] == "symbol": + selectedTraitType[0] = "selected='selected'" + elif p["traitType"] == "name": + selectedTraitType[1] = "selected='selected'" + + selectedgType = ["","","","",""] + if p["gType"] == "none": + selectedgType[0] = "selected='selected'" + elif p["gType"] == "neato": + selectedgType[1] = "selected='selected'" + elif p["gType"] == "fdp": + selectedgType[2] = "selected='selected'" + elif p["gType"] == "circular": + selectedgType[3] = "selected='selected'" + elif p["gType"] == "radial": + selectedgType[4] = "selected='selected'" + + + selectedLock = ["",""] + if p["lock"] == "no": + selectedLock[0] = "selected='selected'" + elif p["lock"] == "yes": + selectedLock[1] = "selected='selected'" + + # line 1~6 + + selectedL1style = ["","","","",""] + if p["L1style"] == "": + selectedL1style[0] = "selected='selected'" + elif p["L1style"] == "bold": + selectedL1style[1] = "selected='selected'" + elif p["L1style"] == "dotted": + selectedL1style[2] = "selected='selected'" + elif p["L1style"] == "dashed": + selectedL1style[3] = "selected='selected'" + else: + selectedL1style[4] = "selected='selected'" + + selectedL2style = ["","","","",""] + if p["L2style"] == "": + selectedL2style[0] = "selected='selected'" + elif p["L2style"] == "bold": + selectedL2style[1] = "selected='selected'" + elif p["L2style"] == "dotted": + selectedL2style[2] = "selected='selected'" + elif p["L2style"] == "dashed": + selectedL2style[3] = "selected='selected'" + else: + selectedL2style[4] = "selected='selected'" + + selectedL3style = ["","","","",""] + if p["L3style"] == "": + selectedL3style[0] = "selected='selected'" + elif p["L3style"] == "bold": + selectedL3style[1] = "selected='selected'" + elif p["L3style"] == "dotted": + selectedL3style[2] = "selected='selected'" + elif p["L3style"] == "dashed": + selectedL3style[3] = "selected='selected'" + else: + selectedL3style[4] = "selected='selected'" + + selectedL4style = ["","","","",""] + if p["L4style"] == "": + selectedL4style[0] = "selected='selected'" + elif p["L4style"] == "bold": + selectedL4style[1] = "selected='selected'" + elif p["L4style"] == "dotted": + selectedL4style[2] = "selected='selected'" + elif p["L4style"] == "dashed": + selectedL4style[3] = "selected='selected'" + else: + selectedL4style[4] = "selected='selected'" + + selectedL5style = ["","","","",""] + if p["L5style"] == "": + selectedL5style[0] = "selected='selected'" + elif p["L5style"] == "bold": + selectedL5style[1] = "selected='selected'" + elif p["L5style"] == "dotted": + selectedL5style[2] = "selected='selected'" + elif p["L5style"] == "dashed": + selectedL5style[3] = "selected='selected'" + else: + selectedL5style[4] = "selected='selected'" + + selectedL6style = ["","","","",""] + if p["L6style"] == "": + selectedL6style[0] = "selected='selected'" + elif p["L6style"] == "bold": + selectedL6style[1] = "selected='selected'" + elif p["L6style"] == "dotted": + selectedL6style[2] = "selected='selected'" + elif p["L6style"] == "dashed": + selectedL6style[3] = "selected='selected'" + else: + selectedL6style[4] = "selected='selected'" + + nfontSelected = ["", "", ""] + if p["nfont"] == "arial": + nfontSelected[0] = "selected='selected'" + elif p["nfont"] == "verdana": + nfontSelected[1] = "selected='selected'" + elif p["nfont"] == "times": + nfontSelected[2] = "selected='selected'" + + cfontSelected = ["", "", ""] + if p["cfont"] == "arial": + cfontSelected[0] = "selected='selected'" + elif p["cfont"] == "verdana": + cfontSelected[1] = "selected='selected'" + elif p["cfont"] == "times": + cfontSelected[2] = "selected='selected'" + + #Writes the form part of the body + + body += ''' <br><br> + <TABLE cellspacing=0 Cellpadding=0> + <TR> + <TD class="doubleBorder"> + + <Table Cellpadding=3> + + <tr><td align="left"> + <dd> + + + + <input type="submit" name="mintmap" value=" Redraw " class="button" onClick="return sortSearchResults(this.form);" /> + + + <input TYPE="Button" class="button" value=" Info " onclick="javascript:window.open('/networkGraphInfo.html', '_blank');"> + </dd> + </td></tr> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + <tr> + <tr align='left' valign='top'> + <td align='left'> + <select align='left' name='gType' id='gType' onchange='addTraitSelection();'> + <option value='none' %s>Select Graph Method</option> + <option value='neato' %s>Spring Model Layout (energy reduction)</option> + <option value='fdp' %s>Spring Model Layout (force reduction)</option> + <option value='circular' %s>Circular Layout</option> + <option value='radial' %s>Radial Layout</option> + </select> + <div align="left" id='nodeSelect'> </div> + </td> + </tr> + </tr> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <tr><td align='center' colspan='2'> + + <table width='100%%'> + + <tr align='left'> + <td>Lock Graph Structure</td> + <td align='left'><select name='lock' id='lock' onChange="changeThreshold();"> + <option value='no' %s>No</option> + <option value='yes' %s>Yes</option> + </select></td> + </tr> + <tr><td align='left' colspan='2' nowrap='nowrap'> + Locking the graph structure allows the user to hold the position of<br> + all nodes and the length of all edges constant, letting him/her easily<br> + compare between different correlation types. Changing the value to "yes"<br> + requires the line threshold to be set to 0 in order to lock the structure.<br> + </td></tr> + </td> + </tr> + + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <tr><td align='center' colspan='2'> + + <table width='100%%'> + + <tr align='center'> + <td>Line Type 1:</td> + <td>-1</td> + <td>to</td> + <td>-0.7</td> + <td><Input type=radio name=colorS value="cL1" checked></TD> + <td bgcolor="%s" ID="cL1" width=20></td> + <td><select name='L1style'> + <option value='' %s>normal</option> + <option value='bold' %s>bold</option> + <option value='dotted' %s>dotted</option> + <option value='dashed' %s>dashed</option> + <option value='invis' %s>invisible</option> + </select></td> + </tr> + + <tr align='center'> + <td>Line Type 2:</td> + <td>-0.7</td> + <td>to</td> + <td>-0.5</td> + <td><Input type=radio name=colorS value="cL2"></TD> + <Td bgcolor="%s" ID="cL2" width=20></td> + <td><select name='L2style'> + <option value='' %s>normal</option> + <option value='bold' %s>bold</option> + <option value='dotted' %s>dotted</option> + <option value='dashed' %s>dashed</option> + <option value='invis' %s>invisible</option> + </select></td> + </tr> + + <tr align='center'> + <td>Line Type 3:</td> + <td>-0.5</td> + <td>to</td> + <td>0</td> + <td><Input type=radio name=colorS value="cL3"></TD> + <Td bgcolor="%s" ID="cL3" width=20></td> + <td><select name='L3style'> + <option value='' %s>normal</option> + <option value='bold' %s>bold</option> + <option value='dotted' %s>dotted</option> + <option value='dashed' %s>dashed</option> + <option value='invis' %s>invisible</option> + </select></td> + </tr> + + <tr align='center'> + <td>Line Type 4:</td> + <td>0</td> + <td>to</td> + <td>0.5</td> + <td><Input type=radio name=colorS value="cL4"></TD> + <Td bgcolor="%s" ID="cL4" width=20></td> + <td><select name='L4style'> + <option value='' %s>normal</option> + <option value='bold' %s>bold</option> + <option value='dotted' %s>dotted</option> + <option value='dashed' %s>dashed</option> + <option value='invis' %s>invisible</option> + </select></td> + </tr> + + <tr align='center'> + <td>Line Type 5:</td> + <td>0.5</td> + <td>to</td> + <td>0.7</td> + <td><Input type=radio name=colorS value="cL5"></TD> + <Td bgcolor="%s" ID="cL5" width=20></td> + <td><select name='L5style'> + <option value='' %s>normal</option> + <option value='bold' %s>bold</option> + <option value='dotted' %s>dotted</option> + <option value='dashed' %s>dashed</option> + <option value='invis' %s>invisible</option> + </select></td> + </tr> + + <tr align='center'> + <td>Line Type 6:</td> + <td>0.7</td> + <td>to</td> + <td>1</td> + <td><Input type=radio name=colorS value="cL6"></TD> + <Td bgcolor="%s" ID="cL6" width=20></td> + <td><select name='L6style'> + <option value='' %s>normal</option> + <option value='bold' %s>bold</option> + <option value='dotted' %s>dotted</option> + <option value='dashed' %s>dashed</option> + <option value='invis' %s>invisible</option> + </select></td> + </tr> + + </table> + </td> + </tr> + + <tr><td align='center' colspan='2' nowrap='nowrap'>To change colors, select Line Type then select Color below.</td></tr> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <tr> + <TD align="right">Correlation Type:</TD> + <TD> + <table border='0' cellspacing='0' cellpadding='0' width='100%%'> + <tr> + <td><Input type="radio" name="whichValue" value="0" %s>Pearson</td> + <td><Input type="radio" name="whichValue" value="1" %s>Spearman</td> + <td rowspan=2 align="center"><input TYPE="Button" class="button" value="Info" onclick="javascript:window.open('/correlationAnnotation.html', '_blank');"></td> + </tr> + <tr> + <td><Input type="radio" name="whichValue" value="2" %s>Literature</td> + <td><Input type="radio" name="whichValue" value="3" %s>Tissue</td> + </tr> + </table> + </TD> + </TR> + + <TR> + <TD align="right" NOWRAP>Line Threshold:</TD> + <TD NOWRAP>Absolute values greater than <input size="5" name="kValue" id="kValue" value="%s"></TD> + </TR> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <TR> + <TD align="right">Draw Nodes :</TD> + <TD NOWRAP> + <Input type="radio" name="printIslands" value="1" %s>all + <Input type="radio" name="printIslands" value="0" %s>connected only + </TD> + </TR> + + <TR> + <TD align="right">Node Shape:</TD> + <TD> + <Input type="radio" name="nodeshape" value="yes" %s>rectangle + <Input type="radio" name="nodeshape" value="no" %s>ellipse + </TD> + </TR> + + <TR> + <TD align="right">Node Label:</TD> + <TD> + <Input type="radio" name="nodelabel" value="yes" %s>trait name<br> + <Input type="radio" name="nodelabel" value="no" %s>gene symbol / marker name + </TD> + </TR> + + <tr> + <td align="right">Node Font:</td> + <TD> + <select name='nfont'> + <option value='Arial' %s>Arial</option> + <option value='Verdana' %s>Verdana</option> + <option value='Times' %s>Times</option> + </select> + </TD> + </TR> + + <tr> + <td align="right">Node Font Size:</td> + <TD><input size="5" name="nfontsize" value="%s"> point</TD> + </TR> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <TR> + <TD align="right">Draw Lines:</TD> + <TD> + <Input type="radio" name="splines" value="yes" %s>curved + <Input type="radio" name="splines" value="no" %s>straight + </TD> + </TR> + + <TR> + <TD align="right">Display Correlations:</TD> + <TD> + <Input type="radio" name="dispcorr" value="no" %s>no + <Input type="radio" name="dispcorr" value="yes" %s>yes + </TD> + </tr> + + <tr> + <td align="right">Line Font:</td> + <TD> + <select name='cfont'> + <option value='Arial' %s>Arial</option> + <option value='Verdana' %s>Verdana</option> + <option value='Times' %s>Times</option> + </select> + </TD> + </TR> + + <TR> + <TD align="right" nowrap="nowrap">Line Font Size:</TD> + <TD><input size="5" name="cfontsize" value="%s"> point</TD> + </TR> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <TR><TD colspan = 2> + + <Input type=hidden name=cPubName value="%s"> + <Input type=hidden name=cMicName value="%s"> + <Input type=hidden name=cGenName value="%s"> + + <Input type=hidden name=cPubColor value="%s"> + <Input type=hidden name=cMicColor value="%s"> + <Input type=hidden name=cGenColor value="%s"> + + <Input type=hidden name=cL1Name value="%s"> + <Input type=hidden name=cL2Name value="%s"> + <Input type=hidden name=cL3Name value="%s"> + <Input type=hidden name=cL4Name value="%s"> + <Input type=hidden name=cL5Name value="%s"> + <Input type=hidden name=cL6Name value="%s"> + + <Input type=hidden name=cL1Color value="%s"> + <Input type=hidden name=cL2Color value="%s"> + <Input type=hidden name=cL3Color value="%s"> + <Input type=hidden name=cL4Color value="%s"> + <Input type=hidden name=cL5Color value="%s"> + <Input type=hidden name=cL6Color value="%s"> + + <Input type=hidden id=initThreshold value="0.5"> + + <Table CellSpacing = 3> + <tr> + <TD><Input type=radio name=colorS value="cPub"> Publish </TD> + <Td bgcolor="%s" ID="cPub" width=20 height=10></td> + <TD><Input type=radio name=colorS value="cMic"> Microarray </TD> + <Td bgcolor="%s" ID="cMic" width=20 height=10></td> + <TD><Input type=radio name=colorS value="cGen"> Genotype </TD> + <Td bgcolor="%s" ID="cGen" width=20 height=10></td> + </tr> + </table> + + </td></tr> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <tr> + <td colspan='2' align='center'> + <img NAME="colorPanel" src="/images/colorPanel.png" alt="colorPanel" onClick="clickHandler(event, this);"> + </TD> + </TR> + + <tr><td align='center' colspan='2'><hr size='1'></td></tr> + + <tr><td align='center' colspan='2'><input type="submit" name="mintmap" value=" Redraw Graph " class="button" onClick="return sortSearchResults(this.form);"/></td></tr> + + </TABLE> + </form></TD> + <SCRIPT type="text/javascript" SRC="/javascript/networkGraph.js"></SCRIPT> + ''' % (selectedgType[0], selectedgType[1], selectedgType[2], selectedgType[3], selectedgType[4], + selectedLock[0], selectedLock[1], + p["cL1Color"], + selectedL1style[0], selectedL1style[1], selectedL1style[2], selectedL1style[3], selectedL1style[4], + p["cL2Color"], + selectedL2style[0], selectedL2style[1], selectedL2style[2], selectedL2style[3], selectedL2style[4], + p["cL3Color"], + selectedL3style[0], selectedL3style[1], selectedL3style[2], selectedL3style[3], selectedL3style[4], + p["cL4Color"], + selectedL4style[0], selectedL4style[1], selectedL4style[2], selectedL4style[3], selectedL4style[4], + p["cL5Color"], + selectedL5style[0], selectedL5style[1], selectedL5style[2], selectedL5style[3], selectedL5style[4], + p["cL6Color"], + selectedL6style[0], selectedL6style[1], selectedL6style[2], selectedL6style[3], selectedL6style[4], + selected[0], selected[1], selected[2], selected[3], + p["kValue"], + selected4[1], selected4[0], + selected5[0], selected5[1], + selected7[0], selected7[1], + nfontSelected[0], nfontSelected[1], nfontSelected[2], + p["nfontsize"], + selected3[0], selected3[1], + selected6[1], selected6[0], + cfontSelected[0], cfontSelected[1], cfontSelected[2], + p["cfontsize"], + p["cPubName"], p["cMicName"], p["cGenName"], + p["cPubColor"], p["cMicColor"], p["cGenColor"], + p["cL1Name"], p["cL2Name"], p["cL3Name"], p["cL4Name"], p["cL5Name"], p["cL6Name"], + p["cL1Color"], p["cL2Color"], p["cL3Color"], p["cL4Color"], p["cL5Color"], p["cL6Color"], + p["cPubColor"], p["cMicColor"], p["cGenColor"]) + + #updated by NL 09-03-2010 function changeFormat() has been moved to webqtl.js and be changed to changeFormat(graphName) + #Javascript that selects the correct graph export file given what the user selects + #from the two drop-down menus + + body += ''' <td width='10'> </td> + <TD valign="top"><p>Right-click or control-click on the following + links to download this graph as a <a href="%s" class="normalsize" target="_blank">GIF file</a> or + a <a href="%s" class="normalsize" target="_blank">PDF file</a>.</p> ''' % (imageName, pdfName) + + body += ''' <p>Initial edge lengths were computed by applying an r-to-Z transform to the correlation coefficents + and then inverting the results. The graph drawing algorithm + found a configuration that minimizes the total stretching of the edges.</p> ''' + + body += ''' <p>This graph took %s seconds to generate with the <a href="http://www.research.att.com/sw/tools/graphviz/" class="normalsize" target="_blank"> + GraphViz</a> visualization toolkit from <a href="http://www.research.att.com" class="normalsize" target="_blank">AT&T Research</a>.</p>''' % (round(totalTime, 2)) + + #Form to export graph file as either XGMML (standardized graphing format) or a + #plain text file with trait names/symbols and correlations + + body += ''' + <form name="graphExport"> + <p>Export Graph File:</p> + <p><select name='exportFormat' id='exportFormat' onchange='changeFormat("%s")'> + <option value='plain' %s>Plain Text Format</option> + <option value='xgmml' %s>XGMML Format</option> + </select> +       + <select name='traitType' id='traitType' onchange='changeFormat("%s")'> + <option value='symbol' %s>Trait Symbol</option> + <option value='name' %s>Full Trait Name</option> + </select></p> + + <p> + <input type="button" class="button" name="exportGraphFile" value=" Export Graph File "/> + </p> + </form> + ''' % (graphName, selectedExportFormat[0], selectedExportFormat[1], + graphName, selectedTraitType[0], selectedTraitType[1]) + + body += '''</Blockquote></td> + </TR></TABLE> + <form method="get" action="http://www.google.com/search"> + <input type="text" name="q" size="31" maxlength="255" value="" /> + <input type="submit" value="Google Search" /> + <input type="radio" name="sitesearch" value="" /> The Web + <input type="radio" name="sitesearch" value="genenetwork.org" checked /> GeneNetwork <br /> + </form> + ''' + + + self.dict["body"] = body + + def writeToFile(self, filename): + """ + Output the contents of this HTML page to a file. + """ + handle = open(filename, "w") + handle.write(str(self)) + handle.close() diff --git a/web/webqtl/networkGraph/networkGraphUtils.py b/web/webqtl/networkGraph/networkGraphUtils.py new file mode 100644 index 00000000..fd0e7484 --- /dev/null +++ b/web/webqtl/networkGraph/networkGraphUtils.py @@ -0,0 +1,750 @@ +# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) +# at rwilliams@uthsc.edu and xzhou15@uthsc.edu +# +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) +# +# Created by GeneNetwork Core Team 2010/08/10 +# +# Last updated by GeneNetwork Core Team 2010/10/20 + +# graphviz: +# a library for sending trait data to the graphviz utilities to get +# graphed + +# ParamDict: a dictionary of strings that map to strings where the keys are +# valid parameters and the values are validated versions of those parameters +# +# The list below also works for visualize.py; different parameters apply to different +# functions in the pipeline. See visualize.py for more details. +# +# parameters: +# filename: an input file with comma-delimited data to visualize +# kValue: +# how to filter the edges; edges with correlation coefficents in +# [-k, k] are not drawn +# whichValue: which of the two correlation coefficents are used; +# 0 means the top half (pearson) and +# 1 means the bottom half (spearman) +# width: the width of the graph in inches +# height: the height of the graph in inches +# --scale: an amount to multiply the length factors by to space out the nodes +# spline: whether to use splines instead of straight lines to draw graphs +# tune: whether to automatically pick intelligent default values for +# kValue and spline based on the number of edges in the input data +# whichVersion: whether to display the graph zoomed or fullscreen +# 0 means zoom +# 1 means fullscreen +# printIslands: whether to display nodes with no visible edges +# + +# DataMatrix: a one-dimensional array of DataPoints in sorted order by i first + + + +import copy +import os +#import os.path +import math +import string + +from base import webqtlConfig +from utility import webqtlUtil +#import trait +from nGraphException import nGraphException +from ProcessedPoint import ProcessedPoint + + +# processDataMatrix: DataMatrix -> ParamDict -> void +# this is the second part after filterDataMatrix +# To process the set of points in a DataMatrix as follows +# 1) choose an appropriate color for the data point +# 2) filter those between k values +# 3) to use an r-to-Z transform to spread out the correlation +# values from [-1,1] to (-inf, inf) +# 4) to invert the values so that higher correlations result in +# shorter edges +# +# Note: this function modifies the matrix in-place. My functional +# programming instincts tell me that this is a bad idea. +def processDataMatrix(matrix, p): + for pt2 in matrix: + # filter using k + if (-p["kValue"] <= pt2.value) and (pt2.value <= p["kValue"]): + pt2.value = 0.00 + + # Lei Yan + # 05/28/2009 + # fix color + + # pick a color + if pt2.value >= 0.7: + pt2.color = p["cL6Name"] + pt2.style = p["L6style"] + elif pt2.value >= 0.5: + pt2.color = p["cL5Name"] + pt2.style = p["L5style"] + elif pt2.value >= 0.0: + pt2.color = p["cL4Name"] + pt2.style = p["L4style"] + elif pt2.value >= -0.5: + pt2.color = p["cL3Name"] + pt2.style = p["L3style"] + elif pt2.value >= -0.7: + pt2.color = p["cL2Name"] + pt2.style = p["L2style"] + else: + pt2.color = p["cL1Name"] + pt2.style = p["L1style"] + + # r to Z transform to generate the length + # 0 gets transformed to infinity, which we can't + # represent here, and 1 gets transformed to 0 + if p["lock"] == "no": + if -0.01 < pt2.value and pt2.value < 0.01: + pt2.length = 1000 + elif pt2.value > 0.99 or pt2.value < -0.99: + pt2.length = 0 + else: + pt2.length = pt2.value + pt2.length = 0.5 * math.log((1 + pt2.length)/(1 - pt2.length)) + + # invert so higher correlations mean closer edges + #pt2.length = abs(p["scale"] * 1/pt2.length) + pt2.length = abs(1/pt2.length) + else: + pt2.length = 2 + + +# tuneParamDict: ParamDict -> Int -> Int -> ParamDict +# to adjust the parameter dictionary for a first-time run +# so that the graphing doesn't take so long, especially since +# small parameter changes can make a big performance difference +# note: you can pass this function an empty dictionary and +# get back a good set of default parameters for your +# particular graph +def tuneParamDict(p, nodes, edges): + newp = copy.deepcopy(p) + + if nodes > 50: + newp["splines"] = "no" + else: + newp["splines"] = "yes" + + if edges > 1000: + newp["printIslands"] = 0 + else: + newp["printIslands"] = 1 + + if edges > 1000: + newp["kValue"] = 0.8 + elif edges > 500: + newp["kValue"] = 0.7 + elif edges > 250: + newp["kValue"] = 0.6 + + if nodes > 50: + # there's no magic here; this formula + # just seems to work + dim = 3*math.sqrt(nodes) + newp["width"] = round(dim,2) + newp["height"] = round(dim,2) + + # the two values below shouldn't change + # newp["scale"] = round(dim/10.0,2) + # newp["fontsize"] = round(14*newp["scale"],0) + + else: + newp["width"] = 40.0 + newp["height"] = 40.0 + + return newp + +# fixLabel : string -> string +def fixLabel(lbl): + """ + To split a label with newlines so it looks a bit better + Note: we send the graphing program literal '\n' strings and + it converts these into newlines + """ + lblparts = lbl.split(" ") + newlbl = "" + i = 0 + for part in lblparts: + if 10*(i+1) < len(newlbl): + i += 1 + newlbl = newlbl + r"\n" + part + else: + newlbl = newlbl + " " + part + return newlbl + #return "\N" + +def writeGraphFile(matrix, traits, filename, p): + """ + Expresses the same information as the neato file, only in + eXtensible Graph Markup and Modeling Language (XGMML) so the user can develop his/her + own graph in a program such as Cytoscape + """ + inputFile1 = open(filename + "_xgmml_symbol.txt", "w") + inputFile2 = open(filename + "_xgmml_name.txt", "w") + inputFile3 = open(filename + "_plain_symbol.txt", "w") + inputFile4 = open(filename + "_plain_name.txt", "w") + + inputFile1.write("<graph directed=\"1\" label=\"Network Graph\">\n") + inputFile2.write("<graph directed=\"1\" label=\"Network Graph\">\n") + + #Write out nodes + traitEdges = [] + for i in range(0, len(traits)): + traitEdges.append(0) + + for i in range(0, len(traits)): + + labelName = traits[i].symbol + inputFile1.write("\t<node id=\"%s\" label=\"%s\"></node>\n" % (i, labelName)) + + for i in range(0, len(traits)): + + labelName = traits[i].name + inputFile2.write("\t<node id=\"%s\" label=\"%s\"></node>\n" % (i, labelName)) + + #Write out edges + for point in matrix: + + traitEdges[point.i] = 1 + traitEdges[point.j] = 1 + if p["edges"] == "complex": + _traitValue = "%.3f" % point.value + inputFile1.write("\t<edge source=\"%s\" target=\"%s\" label=\"%s\"></edge>\n" + % (point.i, + point.j, + _traitValue)) + inputFile2.write("\t<edge source=\"%s\" target=\"%s\" label=\"%s\"></edge>\n" + % (point.i, + point.j, + _traitValue)) + + inputFile1.write("</graph>") + inputFile2.write("</graph>") + + for edge in matrix: + inputFile3.write("%s\t%s\t%s\n" % (traits[edge.i].symbol, edge.value, traits[edge.j].symbol)) + + + for edge in matrix: + inputFile4.write("%s\t%s\t%s\n" % (traits[edge.i].name, edge.value, traits[edge.j].name)) + + inputFile1.close() + inputFile2.close() + inputFile3.close() + inputFile4.close() + + return (os.path.split(filename))[1] + +# writeNeatoFile : DataMatrix -> arrayof Traits -> String -> ParamDict -> String +def writeNeatoFile(matrix, traits, filename, GeneIdArray, p): + """ + Given input data, to write a valid input file for neato, optionally + writing entries for nodes that have no edges. + + NOTE: There is a big difference between removing an edge and zeroing + its value. Because writeNeatoFile is edge-driven, zeroing an edge's value + will still result in its node being written. + """ + inputFile = open(filename, "w") + + """ + This file (inputFile_pdf) is rotated 90 degrees. This is because of a bug in graphviz + that causes pdf output onto a non-landscape layout to often be cut off at the edge + of the page. This second filename (which is just the first + "_pdf" is then read + in the "visualizePage" class in networkGraph.py and used to generate the postscript + file that is converted to pdf. + """ + inputFile_pdf = open(filename + "_pdf", "w") + + + if p["splines"] == "yes": + splines = "true" + else: + splines = "false" + + # header + inputFile.write('''graph webqtlGraph { + overlap="false"; + start="regular"; + splines="%s"; + ratio="auto"; + fontpath = "%s"; + node [fontname="%s", fontsize=%s, shape="%s"]; + edge [fontname="%s", fontsize=%s]; + ''' % (splines, webqtlConfig.PIDDLE_FONT_PATH, + p["nfont"], p["nfontsize"], p["nodeshapeType"], + p["cfont"], p["cfontsize"])) + + inputFile_pdf.write('''graph webqtlGraph { + overlap="false"; + start="regular"; + splines="%s"; + rotate="90"; + center="true"; + size="11,8.5"; + margin="0"; + ratio="fill"; + fontpath = "%s"; + node [fontname="%s", fontsize=%s, shape="%s"]; + edge [fontname="%s", fontsize=%s]; + ''' % (splines, webqtlConfig.PIDDLE_FONT_PATH, + p["nfont"], p["nfontsize"], p["nodeshapeType"], + p["cfont"], p["cfontsize"])) + + # traitEdges stores whether a particular trait has edges + traitEdges = [] + for i in range(0, len(traits)): + traitEdges.append(0) + + if p["dispcorr"] == "yes": + _dispCorr = 1 + else: + _dispCorr = 0 + # print edges first while keeping track of nodes + for point in matrix: + if point.value != 0: + traitEdges[point.i] = 1 + traitEdges[point.j] = 1 + if p["edges"] == "complex": + if _dispCorr: + _traitValue = "%.3f" % point.value + else: + _traitValue = "" + if p["correlationName"] == "Pearson": + inputFile.write('%s -- %s [len=%s, weight=%s, label=\"%s\", color=\"%s\", style=\"%s\", edgeURL=\"javascript:showCorrelationPlot2(db=\'%s\',ProbeSetID=\'%s\',CellID=\'\',db2=\'%s\',ProbeSetID2=\'%s\',CellID2=\'\',rank=\'%s\');\", edgetooltip="%s"];\n' + % (point.i, + point.j, + point.length, + point.length, + _traitValue, + point.color, + point.style, + str(traits[point.i].datasetName()), + str(traits[point.i].nameNoDB()), + str(traits[point.j].datasetName()), + str(traits[point.j].nameNoDB()), + "0", + "Pearson Correlation Plot between " + str(traits[point.i].symbol) + " and " + str(traits[point.j].symbol))) + elif p["correlationName"] == "Spearman": + inputFile.write('%s -- %s [len=%s, weight=%s, label=\"%s\", color=\"%s\", style=\"%s\", edgeURL=\"javascript:showCorrelationPlot2(db=\'%s\',ProbeSetID=\'%s\',CellID=\'\',db2=\'%s\',ProbeSetID2=\'%s\',CellID2=\'\',rank=\'%s\');\", edgetooltip="%s"];\n' + % (point.i, + point.j, + point.length, + point.length, + _traitValue, + point.color, + point.style, + str(traits[point.j].datasetName()), + str(traits[point.j].nameNoDB()), + str(traits[point.i].datasetName()), + str(traits[point.i].nameNoDB()), + "1", + "Spearman Correlation Plot between " + str(traits[point.i].symbol) + " and " + str(traits[point.j].symbol))) + elif p["correlationName"] == "Tissue": + inputFile.write('%s -- %s [len=%s, weight=%s, label=\"%s\", color=\"%s\", style=\"%s\", edgeURL=\"javascript:showTissueCorrPlot(fmName=\'showDatabase\', X_geneSymbol=\'%s\', Y_geneSymbol=\'%s\', rank=\'0\');\", edgetooltip="%s"];\n' + % (point.i, + point.j, + point.length, + point.length, + _traitValue, + point.color, + point.style, + str(traits[point.i].symbol), + str(traits[point.j].symbol), + "Tissue Correlation Plot between " + str(traits[point.i].symbol) + " and " + str(traits[point.j].symbol))) + else: + inputFile.write('%s -- %s [len=%s, weight=%s, label=\"%s\", color=\"%s\", style=\"%s\", edgeURL=\"javascript:showCorrelationPlot2(db=\'%s\',ProbeSetID=\'%s\',CellID=\'\',db2=\'%s\',ProbeSetID2=\'%s\',CellID2=\'\',rank=\'%s\');\", edgetooltip="%s"];\n' + % (point.i, + point.j, + point.length, + point.length, + _traitValue, + point.color, + point.style, + str(traits[point.i].datasetName()), + str(traits[point.i].nameNoDB()), + str(traits[point.j].datasetName()), + str(traits[point.j].nameNoDB()), + "0", + "Correlation Plot between " + str(traits[point.i].symbol) + " and " + str(traits[point.j].symbol))) + inputFile_pdf.write('%s -- %s [len=%s, weight=%s, label=\"%s\", color=\"%s\", style=\"%s\", edgetooltip="%s"];\n' + % (point.i, + point.j, + point.length, + point.length, + _traitValue, + point.color, + point.style, + "Correlation Plot between " + str(traits[point.i].symbol) + " and " + str(traits[point.j].symbol))) + + else: + inputFile.write('%s -- %s [color="%s", style="%s"];\n' + % (point.i, + point.j, + point.color, + point.style)) + inputFile_pdf.write('%s -- %s [color="%s", style="%s"];\n' + % (point.i, + point.j, + point.color, + point.style)) + + # now print nodes + # the target attribute below is undocumented; I found it by looking + # in the neato code + for i in range(0, len(traits)): + if traitEdges[i] == 1 or p["printIslands"] == 1: + _tname = str(traits[i]) + if _tname.find("Publish") > 0: + plotColor = p["cPubName"] + elif _tname.find("Geno") > 0: + plotColor = p["cGenName"] + else: + plotColor = p["cMicName"] + if p['nodelabel'] == 'yes': + labelName = _tname + else: + labelName = traits[i].symbol + + inputFile.write('%s [label="%s", href="javascript:showDatabase2(\'%s\',\'%s\',\'\');", color="%s", style = "filled"];\n' + % (i, labelName, traits[i].datasetName(), traits[i].nameNoDB(), plotColor))# traits[i].color + inputFile_pdf.write('%s [label="%s", href="javascript:showDatabase2(\'%s\',\'%s\',\'\');", color="%s", style = "filled"];\n' + % (i, labelName, traits[i].datasetName(), traits[i].nameNoDB(), plotColor))# traits[i].color + + # footer + inputFile.write("}\n") + inputFile_pdf.write("]\n") + inputFile.close() + inputFile_pdf.close() + + # return only the filename portion, omitting the directory + return (os.path.split(filename))[1] + +# runNeato : string -> string -> string +def runNeato(filename, extension, format, gType): + """ + to run neato on the dataset in the given filename and produce an image file + in the given format whose name we will return. Right now we assume + that format is a valid neato output (see graphviz docs) and a valid extension + for the source datafile. For example, + runNeato('input1', 'png') will produce a file called 'input1.png' + by invoking 'neato input1 -Tpng -o input1.png' + """ + # trim extension off of filename before adding output extension + if filename.find(".") > 0: + filenameBase = filename[:filename.find(".")] + else: + filenameBase = filename + + imageFilename = filenameBase + "." + extension + + #choose which algorithm to run depended upon parameter gType + #neato: energy based algorithm + #circular: nodes given circular structure determined by which nodes are most closely correlated + #radial: first node listed (when you search) is center of the graph, all other nodes are in a circular structure around it + #fdp: force based algorithm + + if gType == "none": + # to keep the output of neato from going to stdout, we open a pipe + # and then wait for it to terminate + + if format in ('gif', 'cmapx', 'ps'): + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/neato", "/usr/local/bin/neato", "-s", "-T", format, webqtlConfig.IMGDIR + filename, "-o", webqtlConfig.IMGDIR + imageFilename) + + else: + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/neato", "/usr/local/bin/neato", webqtlConfig.IMGDIR + filename, "-T", format, "-o", webqtlConfig.IMGDIR + imageFilename) + + if neatoExit == 0: + return imageFilename + + return imageFilename + + + elif gType == "neato": + # to keep the output of neato from going to stdout, we open a pipe + # and then wait for it to terminate + if format in ('gif', 'cmapx', 'ps'): + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/neato", "/usr/local/bin/neato", "-s", "-T", format, webqtlConfig.IMGDIR + filename, "-o", webqtlConfig.IMGDIR + imageFilename) + + else: + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/neato", "/usr/local/bin/neato", webqtlConfig.IMGDIR + filename, "-T", format, "-o", webqtlConfig.IMGDIR + imageFilename) + + if neatoExit == 0: + return imageFilename + + return imageFilename + + elif gType == "circular": + + if format in ('gif', 'cmapx', 'ps'): + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/circo", "/usr/local/bin/circo", "-s", "-T", format, webqtlConfig.IMGDIR + filename, "-o", webqtlConfig.IMGDIR + imageFilename) + + else: + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/circo", "/usr/local/bin/circo", webqtlConfig.IMGDIR + filename, "-T", format, "-o", webqtlConfig.IMGDIR + imageFilename) + + if neatoExit == 0: + return imageFilename + + return imageFilename + + elif gType == "radial": + + if format in ('gif', 'cmapx', 'ps'): + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/twopi", "/usr/local/bin/twopi", "-s", "-T", format, webqtlConfig.IMGDIR + filename, "-o", webqtlConfig.IMGDIR + imageFilename) + + else: + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/twopi", "/usr/local/bin/twopi", webqtlConfig.IMGDIR + filename, "-T", format, "-o", webqtlConfig.IMGDIR + imageFilename) + + if neatoExit == 0: + return imageFilename + + return imageFilename + + elif gType == "fdp": + + if format in ('gif', 'cmapx', 'ps'): + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/fdp", "/usr/local/bin/fdp", "-s", "-T", format, webqtlConfig.IMGDIR + filename, "-o", webqtlConfig.IMGDIR + imageFilename) + + else: + neatoExit = os.spawnlp(os.P_WAIT, "/usr/local/bin/fdp", "/usr/local/bin/fdp", webqtlConfig.IMGDIR + filename, "-T", format, "-o", webqtlConfig.IMGDIR + imageFilename) + + if neatoExit == 0: + return imageFilename + + return imageFilename + + + return imageFilename +# runPsToPdf: string -> int -> intstring +# to run Ps2Pdf to convert the given input postscript file to an 8.5 by 11 +# pdf file The width and height should be specified in inches. We assume +# that the PS files output by GraphViz are 72 dpi. +def runPsToPdf(psfile, width, height): + # we add 1 for padding b/c sometimes a small part of the graph gets + # cut off + newwidth = int((width + 1) * 720) + newheight = int((height + 1) * 720) + + # replace the ps extension with a pdf one + pdffile = psfile[:-2] + "pdf" + + os.spawnlp(os.P_WAIT, "ps2pdf", + "-g%sx%s" % (newwidth, newheight), + webqtlConfig.IMGDIR + psfile, webqtlConfig.IMGDIR + pdffile) + + return pdffile + +# buildParamDict: void -> ParamDict +# to process and validate CGI arguments, +# looking up human-readable names where necessary +# see the comment at the top of the file for valid cgi parameters +def buildParamDict(fs, sessionfile): + params = {} + + params["inputFile"] = fs.formdata.getvalue("inputFile", "") + params["progress"] = fs.formdata.getvalue("progress", "1") + params["filename"] = fs.formdata.getvalue("filename", "") + params["session"] = sessionfile + + if type("1") != type(fs.formdata.getvalue("searchResult")): + params["searchResult"] = string.join(fs.formdata.getvalue("searchResult"),'\t') + else: + params["searchResult"] = fs.formdata.getvalue("searchResult") + + params["riset"] = fs.formdata.getvalue("RISet", "") + #if params["filename"] == "": + # raise nGraphException("Required parameter filename missing") + + #parameter determining whether export button returns an xgmml graph file or plain text file + params["exportFormat"] = fs.formdata.getvalue("exportFormat", "xgmml") + + #parameter determining whether or not traits in the graph file are listed by their symbol or name + params["traitType"] = fs.formdata.getvalue("traitType", "symbol") + + #parameter saying whether or not graph structure should be locked when you redraw the graph + params["lock"] = fs.formdata.getvalue("lock", "no") + + #parameter saying what algorithm should be used to draw the graph + params["gType"] = fs.formdata.getvalue("gType", "none") + + params["kValue"] = webqtlUtil.safeFloat(fs.formdata.getvalue("kValue", "0.5"), 0.5) + params["whichValue"] = webqtlUtil.safeInt(fs.formdata.getvalue("whichValue","0"),0) + + # 1 inch = 2.54 cm + # 1 cm = 0.3937 inch + + params["width"] = webqtlUtil.safeFloat(fs.formdata.getvalue("width", "40.0"), 40.0) + params["height"] = webqtlUtil.safeFloat(fs.formdata.getvalue("height", "40.0"), 40.0) + + yesno = ["yes", "no"] + + params["tune"] = webqtlUtil.safeString(fs.formdata.getvalue("tune", "yes"), yesno, "yes") + + params["printIslands"] = webqtlUtil.safeInt(fs.formdata.getvalue("printIslands", "1"),1) + params["nodeshape"] = webqtlUtil.safeString(fs.formdata.getvalue("nodeshape","yes"), yesno, "yes") + params["nodelabel"] = webqtlUtil.safeString(fs.formdata.getvalue("nodelabel","no"), yesno, "no") + params["nfont"] = fs.formdata.getvalue("nfont","Arial") + params["nfontsize"] = webqtlUtil.safeFloat(fs.formdata.getvalue("nfontsize", "10.0"), 10.0) + + params["splines"] = webqtlUtil.safeString(fs.formdata.getvalue("splines","yes"), yesno, "yes") + params["dispcorr"] = webqtlUtil.safeString(fs.formdata.getvalue("dispcorr","no"), yesno, "no") + params["cfont"] = fs.formdata.getvalue("cfont","Arial") + params["cfontsize"] = webqtlUtil.safeFloat(fs.formdata.getvalue("cfontsize", "10.0"), 10.0) + + params["cPubName"] = fs.formdata.getvalue("cPubName","palegreen") + params["cMicName"] = fs.formdata.getvalue("cMicName","lightblue") + params["cGenName"] = fs.formdata.getvalue("cGenName","lightcoral") + + params["cPubColor"] = fs.formdata.getvalue("cPubColor","98fb98") + params["cMicColor"] = fs.formdata.getvalue("cMicColor","add8e6") + params["cGenColor"] = fs.formdata.getvalue("cGenColor","f08080") + + params["cL1Name"] = fs.formdata.getvalue("cL1Name","blue") + params["cL2Name"] = fs.formdata.getvalue("cL2Name","green") + params["cL3Name"] = fs.formdata.getvalue("cL3Name","black") + params["cL4Name"] = fs.formdata.getvalue("cL4Name","pink") + params["cL5Name"] = fs.formdata.getvalue("cL5Name","orange") + params["cL6Name"] = fs.formdata.getvalue("cL6Name","red") + + params["cL1Color"] = fs.formdata.getvalue("cL1Color","0000ff") + params["cL2Color"] = fs.formdata.getvalue("cL2Color","00ff00") + params["cL3Color"] = fs.formdata.getvalue("cL3Color","000000") + params["cL4Color"] = fs.formdata.getvalue("cL4Color","ffc0cb") + params["cL5Color"] = fs.formdata.getvalue("cL5Color","ffa500") + params["cL6Color"] = fs.formdata.getvalue("cL6Color","ff0000") + + params["L1style"] = fs.formdata.getvalue("L1style","bold") + params["L2style"] = fs.formdata.getvalue("L2style","") + params["L3style"] = fs.formdata.getvalue("L3style","dashed") + params["L4style"] = fs.formdata.getvalue("L4style","dashed") + params["L5style"] = fs.formdata.getvalue("L5style","") + params["L6style"] = fs.formdata.getvalue("L6style","bold") + + if params["splines"] == "yes": + params["splineName"] = "curves" + else: + params["splineName"] = "lines" + + if params["nodeshape"] == "yes": + params["nodeshapeType"] = "box" + else: + params["nodeshapeType"] = "ellipse" + + if params["whichValue"] == 0: + params["correlationName"] = "Pearson" + elif params["whichValue"] == 1: + params["correlationName"] = "Spearman" + elif params["whichValue"] == 2: + params["correlationName"] = "Literature" + else: + params["correlationName"] = "Tissue" + + # see graphviz::writeNeatoFile to find out what this done + params["edges"] = "complex" + + return params + +def optimalRadialNode(matrix): + """ + Automatically determines the node with the most/strongest correlations with + other nodes. If the user selects "radial" for Graph Type and then "Auto" for the + central node then this node is used as the central node. The algorithm is simply a sum of + each node's correlations that fall above the threshold set by the user. + """ + + optMatrix = [0]*(len(matrix)+1) + + for pt in matrix: + if abs(pt.value) > 0.5: + optMatrix[pt.i] += abs(pt.value) + optMatrix[pt.j] += abs(pt.value) + + optPoint = 0 + optCorrTotal = 0 + + j = 0 + + for point in optMatrix: + if (float(point) > float(optCorrTotal)): + optPoint = j + optCorrTotal = point + j += 1 + + + return optPoint + +# filterDataMatrix : DataMatrix -> ParamDict -> DataMatrix +def filterDataMatrix(matrix, p): + """ + To convert a set of input RawPoints to a set of + ProcessedPoints and to choose the appropriate + correlation coefficent. + """ + newmatrix = [] + for pt in matrix: + pt2 = ProcessedPoint(pt.i, pt.j) # XZ, 09/11/2008: add module name + + # pick right value + if p["whichValue"] == 0: + pt2.value = pt.pearson + elif p["whichValue"] == 1: + pt2.value = pt.spearman + elif p["whichValue"] == 2: + pt2.value = pt.literature + elif p["whichValue"] == 3: + pt2.value = pt.tissue + else: + raise nGraphException("whichValue should be either 0, 1, 2 or 3") + + try: + pt2.value = float(pt2.value) + except: + pt2.value = 0.00 + + newmatrix.append(pt2) + + + + return newmatrix + +def generateSymbolList(traits): + """ + Generates a list of trait symbols to be displayed in the central node + selection drop-down menu when plotting a radial graph + """ + + traitList = traits + + symbolList = [None]*len(traitList) + + i=0 + for trait in traitList: + symbolList[i] = str(trait.symbol) + i = i+1 + + symbolListString = "\t".join(symbolList) + + return symbolListString + |