aboutsummaryrefslogtreecommitdiff
path: root/web/webqtl
diff options
context:
space:
mode:
authorroot2012-05-08 18:39:56 -0500
committerroot2012-05-08 18:39:56 -0500
commitea46f42ee640928b92947bfb204c41a482d80937 (patch)
tree9b27a4eb852d12539b543c3efee9d2a47ef470f3 /web/webqtl
parent056b5253fc3857b0444382aa39944f6344dc1ceb (diff)
downloadgenenetwork2-ea46f42ee640928b92947bfb204c41a482d80937.tar.gz
Add all the source codes into the github.
Diffstat (limited to 'web/webqtl')
-rwxr-xr-xweb/webqtl/.htaccess5
-rwxr-xr-xweb/webqtl/__init__.py0
-rwxr-xr-xweb/webqtl/annotation/AnnotationPage.py39
-rwxr-xr-xweb/webqtl/annotation/HTMLBody.py32
-rwxr-xr-xweb/webqtl/annotation/__init__.py0
-rwxr-xr-xweb/webqtl/base/GeneralObject.py71
-rwxr-xr-xweb/webqtl/base/__init__.py0
-rwxr-xr-xweb/webqtl/base/admin.py88
-rwxr-xr-xweb/webqtl/base/cgiData.py70
-rwxr-xr-xweb/webqtl/base/cookieData.py52
-rwxr-xr-xweb/webqtl/base/footer.py6
-rwxr-xr-xweb/webqtl/base/header.py6
-rwxr-xr-xweb/webqtl/base/indexBody.py290
-rwxr-xr-xweb/webqtl/base/myCookie.py55
-rwxr-xr-xweb/webqtl/base/sessionData.py53
-rw-r--r--web/webqtl/base/template.py123
-rw-r--r--web/webqtl/base/templatePage.py222
-rwxr-xr-xweb/webqtl/base/webqtlCaseData.py54
-rwxr-xr-xweb/webqtl/base/webqtlConfig.py73
-rwxr-xr-xweb/webqtl/base/webqtlConfigLocal.py19
-rwxr-xr-xweb/webqtl/base/webqtlDataset.py160
-rwxr-xr-xweb/webqtl/base/webqtlFormData.py289
-rw-r--r--web/webqtl/base/webqtlTrait.py581
-rwxr-xr-xweb/webqtl/basicStatistics/BasicStatisticsFunctions.py174
-rwxr-xr-xweb/webqtl/basicStatistics/BasicStatisticsPage_alpha.py348
-rwxr-xr-xweb/webqtl/basicStatistics/__init__.py0
-rwxr-xr-xweb/webqtl/basicStatistics/updatedBasicStatisticsPage.py150
-rwxr-xr-xweb/webqtl/cmdLine/__init__.py0
-rwxr-xr-xweb/webqtl/cmdLine/cmdCompCorrPage.py49
-rwxr-xr-xweb/webqtl/cmdLine/cmdCorrelationPage.py53
-rwxr-xr-xweb/webqtl/cmdLine/cmdDirectPlotPage.py49
-rwxr-xr-xweb/webqtl/cmdLine/cmdHeatmapPage.py52
-rwxr-xr-xweb/webqtl/cmdLine/cmdIntervalMappingPage.py75
-rwxr-xr-xweb/webqtl/cmdLine/cmdMarkerRegressionPage.py47
-rwxr-xr-xweb/webqtl/cmdLine/cmdNetworkGraphPage.py49
-rwxr-xr-xweb/webqtl/cmdLine/cmdPartialCorrelationPage.py50
-rwxr-xr-xweb/webqtl/cmdLine/cmdQTLminerPage.py47
-rwxr-xr-xweb/webqtl/cmdLine/cmdShowAllPage.py50
-rwxr-xr-xweb/webqtl/cmdLine/cmdShowAllPage2.py55
-rwxr-xr-xweb/webqtl/cmdLine/cmdSnpBrowserResultPage.py47
-rwxr-xr-xweb/webqtl/cmdLine/cmdTissueCorrelationResultPage.py47
-rwxr-xr-xweb/webqtl/cmdLine/procPage.py46
-rwxr-xr-xweb/webqtl/cmdLine/webqtlCmdLine.py176
-rw-r--r--web/webqtl/collection/AddToSelectionPage.py695
-rwxr-xr-xweb/webqtl/collection/AddUserInputToSelectionPage.py97
-rwxr-xr-xweb/webqtl/collection/BatchSubmitSelectionPage.py225
-rwxr-xr-xweb/webqtl/collection/DisplaySelectionPage.py51
-rwxr-xr-xweb/webqtl/collection/ExportSelectionDetailInfoPage.py197
-rwxr-xr-xweb/webqtl/collection/ExportSelectionPage.py67
-rwxr-xr-xweb/webqtl/collection/ImportSelectionPage.py92
-rwxr-xr-xweb/webqtl/collection/RemoveSelectionPage.py108
-rwxr-xr-xweb/webqtl/collection/__init__.py0
-rwxr-xr-xweb/webqtl/compareCorrelates/MultipleCorrelationPage.py108
-rwxr-xr-xweb/webqtl/compareCorrelates/__init__.py0
-rwxr-xr-xweb/webqtl/compareCorrelates/correlation.py359
-rwxr-xr-xweb/webqtl/compareCorrelates/htmlModule.py279
-rwxr-xr-xweb/webqtl/compareCorrelates/multitrait.py1121
-rwxr-xr-xweb/webqtl/compareCorrelates/trait.py1074
-rwxr-xr-xweb/webqtl/correlation/CorrelationPage.py1958
-rwxr-xr-xweb/webqtl/correlation/PartialCorrDBPage.py1359
-rwxr-xr-xweb/webqtl/correlation/PartialCorrInputPage.py484
-rwxr-xr-xweb/webqtl/correlation/PartialCorrTraitPage.py310
-rwxr-xr-xweb/webqtl/correlation/PlotCorrelationPage.py683
-rwxr-xr-xweb/webqtl/correlation/__init__.py0
-rwxr-xr-xweb/webqtl/correlation/correlationFunction.py923
-rwxr-xr-xweb/webqtl/correlationMatrix/CorrelationMatrixPage.py595
-rwxr-xr-xweb/webqtl/correlationMatrix/TissueAbbreviationPage.py79
-rwxr-xr-xweb/webqtl/correlationMatrix/TissueCorrelationPage.py673
-rwxr-xr-xweb/webqtl/correlationMatrix/__init__.py0
-rwxr-xr-xweb/webqtl/correlationMatrix/tissueCorrelationMatrix.py132
-rwxr-xr-xweb/webqtl/dataSharing/SharingBody.py290
-rwxr-xr-xweb/webqtl/dataSharing/SharingInfo.py98
-rwxr-xr-xweb/webqtl/dataSharing/SharingInfoAddPage.py47
-rwxr-xr-xweb/webqtl/dataSharing/SharingInfoDeletePage.py55
-rwxr-xr-xweb/webqtl/dataSharing/SharingInfoEditPage.py51
-rwxr-xr-xweb/webqtl/dataSharing/SharingInfoPage.py52
-rwxr-xr-xweb/webqtl/dataSharing/SharingInfoUpdatePage.py109
-rwxr-xr-xweb/webqtl/dataSharing/SharingListDataSetPage.py99
-rwxr-xr-xweb/webqtl/dataSharing/SharingPage.py40
-rwxr-xr-xweb/webqtl/dataSharing/__init__.py0
-rwxr-xr-xweb/webqtl/dbFunction/__init__.py0
-rwxr-xr-xweb/webqtl/dbFunction/webqtlDatabaseFunction.py265
-rwxr-xr-xweb/webqtl/externalResource/GCATPage.py101
-rwxr-xr-xweb/webqtl/externalResource/GoTreePage.py154
-rwxr-xr-xweb/webqtl/externalResource/ODEPage.py143
-rwxr-xr-xweb/webqtl/externalResource/__init__.py0
-rwxr-xr-xweb/webqtl/geneWiki/AddGeneRIFPage.py635
-rwxr-xr-xweb/webqtl/geneWiki/__init__.py0
-rwxr-xr-xweb/webqtl/genomeGraph/__init__.py0
-rwxr-xr-xweb/webqtl/genomeGraph/cmdGenomeScanPage.py532
-rwxr-xr-xweb/webqtl/genomeGraph/genAllDbResultPage.py309
-rwxr-xr-xweb/webqtl/heatmap/Heatmap.py437
-rwxr-xr-xweb/webqtl/heatmap/__init__.py0
-rwxr-xr-xweb/webqtl/heatmap/heatmapPage.py116
-rwxr-xr-xweb/webqtl/heatmap/heatmapPage_GN.py522
-rwxr-xr-xweb/webqtl/heatmap/slink.py141
-rwxr-xr-xweb/webqtl/intervalAnalyst/GeneUtil.py124
-rwxr-xr-xweb/webqtl/intervalAnalyst/IntervalAnalystPage.py405
-rwxr-xr-xweb/webqtl/intervalAnalyst/__init__.py0
-rw-r--r--web/webqtl/intervalMapping/IntervalMappingPage.py2454
-rwxr-xr-xweb/webqtl/intervalMapping/__init__.py0
-rw-r--r--web/webqtl/main.py699
-rwxr-xr-xweb/webqtl/maintainance/__init__.py0
-rwxr-xr-xweb/webqtl/maintainance/addRif.py107
-rwxr-xr-xweb/webqtl/maintainance/checkInfoFile.py102
-rwxr-xr-xweb/webqtl/maintainance/genSelectDatasetJS.py637
-rwxr-xr-xweb/webqtl/maintainance/updateMenuJS.py127
-rwxr-xr-xweb/webqtl/management/GenoUpdate.py1279
-rwxr-xr-xweb/webqtl/management/__init__.py0
-rwxr-xr-xweb/webqtl/management/assignUserToDatasetPage.py159
-rwxr-xr-xweb/webqtl/management/createUserAccountPage.py161
-rwxr-xr-xweb/webqtl/management/deletePhenotypeTraitPage.py196
-rwxr-xr-xweb/webqtl/management/editHeaderFooter.py200
-rwxr-xr-xweb/webqtl/management/exportPhenotypeDatasetPage.py228
-rwxr-xr-xweb/webqtl/management/managerMainPage.py130
-rwxr-xr-xweb/webqtl/markerRegression/CompositeMarkerRegressionPage.py211
-rwxr-xr-xweb/webqtl/markerRegression/MarkerRegressionPage.py1626
-rwxr-xr-xweb/webqtl/markerRegression/__init__.py0
-rwxr-xr-xweb/webqtl/misc/__init__.py0
-rwxr-xr-xweb/webqtl/misc/editHtmlPage.py129
-rwxr-xr-xweb/webqtl/misc/uploadFilePage.py137
-rwxr-xr-xweb/webqtl/networkGraph/GraphPage.py46
-rwxr-xr-xweb/webqtl/networkGraph/ProcessedPoint.py49
-rwxr-xr-xweb/webqtl/networkGraph/__init__.py0
-rwxr-xr-xweb/webqtl/networkGraph/nGraphException.py33
-rwxr-xr-xweb/webqtl/networkGraph/networkGraphPage.py335
-rw-r--r--web/webqtl/networkGraph/networkGraphPageBody.py697
-rw-r--r--web/webqtl/networkGraph/networkGraphUtils.py750
-rwxr-xr-xweb/webqtl/pairScan/CategoryGraphPage.py199
-rwxr-xr-xweb/webqtl/pairScan/DirectPlotPage.py430
-rwxr-xr-xweb/webqtl/pairScan/PairPlotPage.py314
-rwxr-xr-xweb/webqtl/pairScan/__init__.py0
-rwxr-xr-xweb/webqtl/pubmedsearch/PubmedSearch.py58
-rwxr-xr-xweb/webqtl/pubmedsearch/PubmedSearchRe.py57
-rwxr-xr-xweb/webqtl/pubmedsearch/__init__.py0
-rwxr-xr-xweb/webqtl/qtlminer/GeneUtil.py658
-rwxr-xr-xweb/webqtl/qtlminer/QTLminer.py1237
-rwxr-xr-xweb/webqtl/qtlminer/__init__.py0
-rwxr-xr-xweb/webqtl/schema/ShowCommentPage.py123
-rwxr-xr-xweb/webqtl/schema/ShowSchemaPage.py194
-rwxr-xr-xweb/webqtl/schema/UpdateCommentPage.py101
-rwxr-xr-xweb/webqtl/schema/__init__.py0
-rwxr-xr-xweb/webqtl/search/IndexPage.py41
-rw-r--r--web/webqtl/search/SearchResultPage.py1237
-rwxr-xr-xweb/webqtl/search/TextSearchPage.py536
-rwxr-xr-xweb/webqtl/search/__init__.py0
-rwxr-xr-xweb/webqtl/search/pubmedsearch.py12
-rw-r--r--web/webqtl/showTrait/DataEditingPage.py1883
-rwxr-xr-xweb/webqtl/showTrait/ShowBestTrait.py195
-rwxr-xr-xweb/webqtl/showTrait/ShowProbeInfoPage.py486
-rwxr-xr-xweb/webqtl/showTrait/ShowTraitPage.py170
-rwxr-xr-xweb/webqtl/showTrait/__init__.py0
-rwxr-xr-xweb/webqtl/showTrait/exportPage.py141
-rwxr-xr-xweb/webqtl/showTrait/testTraitPage.py36
-rwxr-xr-xweb/webqtl/snpBrowser/GeneAnnot.py124
-rwxr-xr-xweb/webqtl/snpBrowser/GeneListAnnot.py90
-rwxr-xr-xweb/webqtl/snpBrowser/__init__.py0
-rwxr-xr-xweb/webqtl/snpBrowser/snpBrowserPage.py1259
-rwxr-xr-xweb/webqtl/snpBrowser/snpBrowserUtils.py71
-rwxr-xr-xweb/webqtl/snpBrowser/snpDetails.py101
-rwxr-xr-xweb/webqtl/submitTrait/AddUserInputToPublishPage.py523
-rwxr-xr-xweb/webqtl/submitTrait/BatchSubmitPage.py142
-rwxr-xr-xweb/webqtl/submitTrait/CrossChoicePage.py233
-rwxr-xr-xweb/webqtl/submitTrait/VarianceChoicePage.py174
-rwxr-xr-xweb/webqtl/submitTrait/__init__.py0
-rwxr-xr-xweb/webqtl/textUI/__init__.py0
-rwxr-xr-xweb/webqtl/textUI/cmdClass.py224
-rwxr-xr-xweb/webqtl/textUI/cmdCorrelation.py325
-rwxr-xr-xweb/webqtl/textUI/cmdGeno.py118
-rwxr-xr-xweb/webqtl/textUI/cmdGet.py86
-rwxr-xr-xweb/webqtl/textUI/cmdHelp.py105
-rwxr-xr-xweb/webqtl/textUI/cmdInterval.py174
-rwxr-xr-xweb/webqtl/textUI/cmdMap.py144
-rwxr-xr-xweb/webqtl/textUI/cmdSearchGene.py70
-rwxr-xr-xweb/webqtl/textUI/cmdShowEditing.py50
-rwxr-xr-xweb/webqtl/updateTrait/DataUpdatePage.py738
-rwxr-xr-xweb/webqtl/updateTrait/__init__.py0
-rwxr-xr-xweb/webqtl/user/__init__.py0
-rwxr-xr-xweb/webqtl/user/userLogin.py84
-rwxr-xr-xweb/webqtl/user/userLogoff.py54
-rwxr-xr-xweb/webqtl/user/userPasswd.py73
-rwxr-xr-xweb/webqtl/user/userPasswdPage.py70
-rwxr-xr-xweb/webqtl/utility/AJAX_table.py153
-rwxr-xr-xweb/webqtl/utility/Plot.py1283
-rwxr-xr-xweb/webqtl/utility/TDCell.py42
-rwxr-xr-xweb/webqtl/utility/THCell.py44
-rwxr-xr-xweb/webqtl/utility/__init__.py0
-rwxr-xr-xweb/webqtl/utility/svg.py1069
-rwxr-xr-xweb/webqtl/utility/webqtlUtil.py977
189 files changed, 47446 insertions, 0 deletions
diff --git a/web/webqtl/.htaccess b/web/webqtl/.htaccess
new file mode 100755
index 00000000..d5e1aa95
--- /dev/null
+++ b/web/webqtl/.htaccess
@@ -0,0 +1,5 @@
+AddHandler python-program .py
+PythonHandler main
+PythonInterpreter GeneNetwork
+PythonOption session FileSession
+PythonDebug On
diff --git a/web/webqtl/__init__.py b/web/webqtl/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/__init__.py
diff --git a/web/webqtl/annotation/AnnotationPage.py b/web/webqtl/annotation/AnnotationPage.py
new file mode 100755
index 00000000..ab3f7095
--- /dev/null
+++ b/web/webqtl/annotation/AnnotationPage.py
@@ -0,0 +1,39 @@
+# 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 HTMLBody
+
+#########################################
+# AnnotationPage
+#########################################
+
+class AnnotationPage(templatePage):
+
+ def __init__(self, fd):
+ templatePage.__init__(self, fd)
+ self.dict['title'] = 'GeneNetwork Data Sharing Zone'
+ self.dict['body'] = HTMLBody.body_string
diff --git a/web/webqtl/annotation/HTMLBody.py b/web/webqtl/annotation/HTMLBody.py
new file mode 100755
index 00000000..39e012a8
--- /dev/null
+++ b/web/webqtl/annotation/HTMLBody.py
@@ -0,0 +1,32 @@
+# 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
+
+body_string = """
+<TD vAlign=top width="100%" align="left" bgColor=#eeeeee>
+<p style="font-size:18px;font-family:verdana;color:black"><B> Annotation Database for Microarray</B></p>
+<iframe src="http://lily.uthsc.edu:8080/20090504_UTHSC_dbDownload/download.jsp" frameborder="0" scrolling="no" width="100%" height="1250"></iframe>
+</td>
+"""
diff --git a/web/webqtl/annotation/__init__.py b/web/webqtl/annotation/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/annotation/__init__.py
diff --git a/web/webqtl/base/GeneralObject.py b/web/webqtl/base/GeneralObject.py
new file mode 100755
index 00000000..311c9e22
--- /dev/null
+++ b/web/webqtl/base/GeneralObject.py
@@ -0,0 +1,71 @@
+# 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 GeneralObject:
+ """
+ Base class to define an Object.
+ a = [Spam(1, 4), Spam(9, 3), Spam(4,6)]
+ a.sort(lambda x, y: cmp(x.eggs, y.eggs))
+ """
+
+ def __init__(self, *args, **kw):
+ self.contents = list(args)
+ for name, value in kw.items():
+ setattr(self, name, value)
+
+ def __setitem__(self, key, value):
+ setattr(self, key, value)
+
+ def __getitem__(self, key):
+ return getattr(self, key)
+
+ def __getattr__(self, key):
+ if key in self.__dict__.keys():
+ return self.__dict__[key]
+ else:
+ return eval("self.__dict__.%s" % key)
+
+ def __len__(self):
+ return len(self.__dict__) - 1
+
+ def __str__(self):
+ s = ''
+ for key in self.__dict__.keys():
+ if key != 'contents':
+ s += '%s = %s\n' % (key,self.__dict__[key])
+ return s
+
+ def __repr__(self):
+ s = ''
+ for key in self.__dict__.keys():
+ s += '%s = %s\n' % (key,self.__dict__[key])
+ return s
+
+ def __cmp__(self,other):
+ return len(self.__dict__.keys()).__cmp__(len(other.__dict__.keys()))
+
+
+
diff --git a/web/webqtl/base/__init__.py b/web/webqtl/base/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/base/__init__.py
diff --git a/web/webqtl/base/admin.py b/web/webqtl/base/admin.py
new file mode 100755
index 00000000..a04df2da
--- /dev/null
+++ b/web/webqtl/base/admin.py
@@ -0,0 +1,88 @@
+# 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
+
+
+
+
+
+#XZ, 04/02/2009: we should put this into database.
+
+
+###LIST of databases used into gene name query
+
+
+ADMIN_search_dbs = {
+ 'rat': {'PERITONEAL FAT': ['FT_2A_0605_Rz'],
+ 'KIDNEY': ['KI_2A_0405_Rz'],
+ 'ADRENAL GLAND': ['HXB_Adrenal_1208'],
+ 'HEART': ['HXB_Heart_1208']
+ },
+ 'mouse': {'CEREBELLUM': ['CB_M_0305_R'],
+ 'STRIATUM': ['SA_M2_0905_R', 'SA_M2_0405_RC', 'UTHSC_1107_RankInv', 'Striatum_Exon_0209'],
+ 'HIPPOCAMPUS': ['HC_M2_0606_R', 'UMUTAffyExon_0209_RMA'],
+ 'WHOLE BRAIN': ['BR_M2_1106_R', 'IBR_M_0106_R', 'BRF2_M_0805_R', 'UCLA_BHF2_BRAIN_0605'],
+ 'LIVER': ['LV_G_0106_B', 'UCLA_BHF2_LIVER_0605'],
+ 'EYE': ['Eye_M2_0908_R'],
+ 'HEMATOPOIETIC STEM CELLS': ['HC_U_0304_R'],
+ 'KIDNEY': ['MA_M2_0806_R'],
+ 'MAMMARY TUMORS': ['MA_M_0704_R', 'NCI_Agil_Mam_Tum_RMA_0409'],
+ 'PREFRONTAL CORTEX': ['VCUSal_1206_R'],
+ 'SPLEEN': ['IoP_SPL_RMA_0509'],
+ 'NUCLEUS ACCUMBENS': ['VCUSalo_1007_R'],
+ 'NEOCORTEX': ['HQFNeoc_0208_RankInv'],
+ 'ADIPOSE': ['UCLA_BHF2_ADIPOSE_0605'],
+ 'RETINA': ['Illum_Retina_BXD_RankInv0410']
+ },
+ 'human': {
+ 'LYMPHOBLAST B CELL': ['Human_1008', 'UT_CEPH_RankInv0909'],
+ 'WHOLE BRAIN': ['GSE5281_F_RMA0709', 'GSE15222_F_RI_0409']
+ }
+ }
+
+
+###LIST of tissue alias
+
+ADMIN_tissue_alias = {'CEREBELLUM': ['Cb'],
+ 'STRIATUM': ['Str'],
+ 'HIPPOCAMPUS': ['Hip'],
+ 'WHOLE BRAIN': ['Brn'],
+ 'LIVER': ['Liv'],
+ 'EYE': ['Eye'],
+ 'PERITONEAL FAT': ['Fat'],
+ 'HEMATOPOIETIC STEM CELLS': ['Hsc'],
+ 'KIDNEY': ['Kid'],
+ 'ADRENAL GLAND': ['Adr'],
+ 'HEART': ['Hea'],
+ 'MAMMARY TUMORS': ['Mam'],
+ 'PREFRONTAL CORTEX': ['Pfc'],
+ 'SPLEEN': ['Spl'],
+ 'NUCLEUS ACCUMBENS': ['Nac'],
+ 'NEOCORTEX': ['Ctx'],
+ 'ADIPOSE': ['Wfat'],
+ 'RETINA': ['Ret']
+ }
+
+
diff --git a/web/webqtl/base/cgiData.py b/web/webqtl/base/cgiData.py
new file mode 100755
index 00000000..57416060
--- /dev/null
+++ b/web/webqtl/base/cgiData.py
@@ -0,0 +1,70 @@
+# 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
+
+#########################################
+#convert Field storage object to Dict object
+#in order to be able to saved into a session file
+#########################################
+
+class cgiData(dict):
+ '''convert Field storage object to Dict object
+ Filed storage object cannot be properly dumped
+ '''
+
+ def __init__(self, field_storage=None):
+
+ if not field_storage:
+ field_storage={}
+
+ for key in field_storage.keys():
+ temp = field_storage.getlist(key)
+ if len(temp) > 1:
+ temp = map(self.toValue, temp)
+ elif len(temp) == 1:
+ temp = self.toValue(temp[0])
+ else:
+ temp = None
+ self[key]= temp
+
+ def toValue(self, obj):
+ '''fieldstorge returns different type of objects, \
+ need to convert to string or None'''
+ try:
+ return obj.value
+ except:
+ return ""
+
+ def getvalue(self, k, default= None):
+ try:
+ return self[k]
+ except:
+ return default
+
+ getfirst = getvalue
+
+
+
+
diff --git a/web/webqtl/base/cookieData.py b/web/webqtl/base/cookieData.py
new file mode 100755
index 00000000..4b7c9046
--- /dev/null
+++ b/web/webqtl/base/cookieData.py
@@ -0,0 +1,52 @@
+# 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
+
+#########################################
+#convert mod_python object to Dict object
+#in order to be able to be pickled
+#########################################
+
+class cookieData(dict):
+ 'convert mod python Cookie object to Dict object'
+
+ def __init__(self, cookies=None):
+
+ if not cookies:
+ cookies={}
+
+ for key in cookies.keys():
+ self[key.lower()]= cookies[key].value
+
+ def getvalue(self, k, default= None):
+ try:
+ return self[k.lower()]
+ except:
+ return default
+
+ getfirst = getvalue
+
+
+
diff --git a/web/webqtl/base/footer.py b/web/webqtl/base/footer.py
new file mode 100755
index 00000000..6f92fdf8
--- /dev/null
+++ b/web/webqtl/base/footer.py
@@ -0,0 +1,6 @@
+import webqtlConfig
+
+footer_html = open(webqtlConfig.HTMLPATH + 'footer.html', 'r').read()
+footer = footer_html.replace('%"','%%"')
+
+footer_string = footer.replace('<!-- %s -->', '%s')
diff --git a/web/webqtl/base/header.py b/web/webqtl/base/header.py
new file mode 100755
index 00000000..b6136b51
--- /dev/null
+++ b/web/webqtl/base/header.py
@@ -0,0 +1,6 @@
+import webqtlConfig
+
+header_string = open(webqtlConfig.HTMLPATH + 'header.html', 'r').read()
+header_string = header_string.replace("\\'", "'")
+header_string = header_string.replace('%"','%%"')
+header_string = header_string.replace('<!-- %s -->', '%s') \ No newline at end of file
diff --git a/web/webqtl/base/indexBody.py b/web/webqtl/base/indexBody.py
new file mode 100755
index 00000000..aa67dffa
--- /dev/null
+++ b/web/webqtl/base/indexBody.py
@@ -0,0 +1,290 @@
+index_body_string = """
+<TD vAlign=top width="40%" align="left" height=10 bgColor=#eeeeee>
+ <p style="font-size:18px;font-family:verdana;color:black"><B> Select and Search</B>
+ <Form METHOD="POST" ACTION="/webqtl/main.py" ENCTYPE="multipart/form-data" NAME="SEARCHFORM">
+
+ <TABLE width="100%">
+
+ <!-- SPECIES SELECTION -->
+ <TR>
+ <TD align=right height="35" style="font-size:14px;font-family:verdana;color:black" width="16%">
+ <B>Species:</B>
+ </TD>
+
+ <TD width="3%">
+ </TD>
+
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu0">
+ <Select NAME="species" size=1 id="species" onchange="fillOptions('species');">
+ </Select>
+ </DIV>
+ </TD>
+ </TR>
+
+ <!-- GROUP SELECTION -->
+
+ <TR>
+
+ <TD align="right" height="35" style="font-size:14px;font-family:verdana;color:black">
+ <B>Group:</B>
+ </TD>
+
+ <TD width="3%">
+ </TD>
+
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu1">
+
+ <Select NAME="cross" size=1 id="cross" onchange="fillOptions('cross');">
+ </Select>
+ <input type="button" class="button" value=" Info " onCLick="javascript:crossinfo();">
+ </DIV>
+ </TD>
+ </TR>
+
+
+ <!-- TYPE SELECTION -->
+
+ <TR>
+
+ <TD align=right height=35 style="font-size:14px;font-family:verdana;color:black">
+ <B>Type:</B>
+ </TD>
+
+ <TD width="3%">
+ </TD>
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu2">
+ <Select NAME="tissue" size=1 id="tissue" onchange="fillOptions('tissue');">
+
+ </Select>
+ </DIV>
+ </TD>
+ </TR>
+
+
+ <!-- DATABASE SELECTION -->
+ <TR>
+ <TD align=right height=35 style="font-size:14px;font-family:verdana;color:black">
+ <B>Database:</B>
+ </TD>
+
+ <TD width="3%">
+ </TD>
+
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu3">
+ <Select NAME="database" size=1 id="database">
+ </Select>
+ <input type="button" class="button" value=" Info " onCLick="javascript:databaseinfo();">
+ </DIV>
+
+ </TD>
+ </TR>
+
+ <!-- USER HELP -->
+ <TR>
+ <TD align=right height=20 width="10%">
+ </TD>
+ <TD width="3%">
+ </TD>
+
+ <TD align="left" width="85%">
+ <P class="fs12">&nbsp;&nbsp;&nbsp;&nbsp;Databases marked with <B>**</B> suffix are not public yet.
+ <BR>&nbsp;&nbsp;&nbsp;&nbsp;Access requires <A HREF="/account.html" target="_blank" class="fs14"><small>user login</small></A>.</P>
+ </TD>
+ </TR>
+
+
+<!-- GET ANY SEARCH -->
+ <TR>
+ <TD align=right height=35 NOWRAP="on" style="font-size:14px;font-family:verdana;color:black" width="10%">
+ <B>Get Any:</B>
+ </TD>
+
+ <TD width="3%">
+ </TD>
+
+ <TD NOWRAP width="85%" align="left">
+
+ <input id="tfor" name="ORkeyword" style="width:420px; background-color:white; font-family:verdana; font-size:14px" type="text" maxlength="500">
+ </TD>
+ </TR>
+
+
+
+<!-- GET ANY HELP -->
+ <TR>
+ <TD align=right height=20 width="10%">
+ </TD>
+ <TD width="3%">
+
+ </TD>
+ <TD width="85%" align="left">
+ <P class="fs12">&nbsp;&nbsp;&nbsp;&nbsp;Enter terms, genes, ID numbers in the <B>Get Any</B> field.
+ <BR>&nbsp;&nbsp;&nbsp;&nbsp;Use <B>*</B> or <B>?</B> wildcards (Cyp*a?, synap*).
+ <BR>&nbsp;&nbsp;&nbsp;&nbsp;Use <B>Combined</B> for terms such as <I>tyrosine kinase</I>.</P>
+
+ </TD>
+ </TR>
+
+
+
+<!-- COMBINED SEARCH -->
+
+ <TR>
+ <TD align=right height=35 NOWRAP="on" STYLE="font-size:14px;font-family:verdana;color:black" width="10%">
+ <B>Combined:</B>
+ </TD>
+
+ <TD width="3%">
+ </TD>
+
+ <TD NOWRAP width="85%" align="left">
+ <input id="tfand" NAME="ANDkeyword" STYLE="width:420px; background-color:white; font-family:verdana; font-size:14px" type="text" maxlength="500">
+ <input name="matchwhole" type="hidden" value="ON">
+ </TD>
+ </TR>
+
+
+
+<!-- SEARCH, MAKE DEFAULT, ADVANCED SEARCH -->
+
+ <TR ALIGN="center">
+ <TD width="3%">
+ </TD>
+ <TD width="3%">
+ </TD>
+ <TD ALIGN="left" HEIGHT="40" COLSPAN=3>
+ <INPUT id="btsearch" TYPE="Submit" CLASS="button" STYLE="font-size:12px" VALUE=" Search ">&nbsp;&nbsp;&nbsp;&nbsp;
+ <INPUT TYPE="button" CLASS="button" STYLE="font-size:12px" VALUE=" Make Default " onClick = "setDefault(this.form);">&nbsp;&nbsp;&nbsp;&nbsp;
+ <INPUT TYPE="button" CLASS="button" STYLE="font-size:12px" VALUE=" Advanced Search " onClick="javascript:window.open('/index3.html', '_self');">
+
+ </TD>
+ </TR>
+ </TABLE>
+ <INPUT TYPE="hidden" NAME="FormID" VALUE="searchResult">
+ <INPUT TYPE="hidden" NAME="RISet" VALUE="BXD">
+ <SCRIPT SRC="/javascript/selectDatasetMenu.js"></SCRIPT>
+ </FORM>
+ </CENTER>
+
+
+
+
+
+<!-- QUICK HELP -->
+
+<P><LEFT>&nbsp;______________________________________________________
+
+<P STYLE="font-size:13px;font-family:verdana;color:black"><B>&nbsp;
+
+Quick HELP Examples and </B>
+<A HREF="http://www.genenetwork.org/index4.html" target="_blank" class="fs14"><B>
+ User's Guide</B></A></P>
+
+</CENTER style="font-size:12px;font-family:verdana;color:black">
+&nbsp;&nbsp;You can also use advanced commands. Copy these simple examples
+<BR>&nbsp;&nbsp;into the <B>Get Any</B> or <B>Combined</B> search fields:
+<UL style="font-size:12px;font-family:verdana;color:black">
+
+<LI><B><I>POSITION=(chr1 25 30)</I></B> finds genes, markers, or transcripts on chromosome 1 between 25 and 30 Mb.
+
+<LI><B><I>MEAN=(15 16) LRS=(23 46)</I></B> in the <B>Combined</B> field finds highly expressed genes (15 to 16 log2 units) AND with peak <A HREF="http://www.genenetwork.org/glossary.html#L" target="_blank" class="fs14"><small>LRS</small></A> linkage between 23 and 46.
+
+
+<LI><B><I>RIF=mitochondrial</I></B> searches RNA databases for <A HREF="http://www.ncbi.nlm.nih.gov/projects/GeneRIF/GeneRIFhelp.html" target="_blank" class="fs14"><small>GeneRIF</small></A> links.
+
+<LI><B><I>WIKI=nicotine</I></B> searches <A HREF="http://www.genenetwork.org/webqtl/main.py?FormID=geneWiki" target="_blank" class="fs14"><small>GeneWiki</small></A> for genes that you or other users have annotated with the word <I>nicotine</I>.
+
+<LI><B><I>GO:0045202</I></B> searches for synapse-associated genes listed in the <A HREF="http://www.godatabase.org/cgi-bin/amigo/go.cgi" target="_blank" class="fs14"><small>Gene Ontology</small></A>.
+
+
+<LI><B><I>GO:0045202 LRS=(9 99 Chr4 122 155) cisLRS=(9 999 10)</I> </B><BR> in <B>Combined</B> finds synapse-associated genes with <A HREF="http://www.genenetwork.org/glossary.html#E" target="_blank" class="fs14"><small>cis eQTL</small></A> on Chr 4 from 122 and 155 Mb with LRS scores between 9 and 999.
+
+<LI><B><I>RIF=diabetes LRS=(9 999 Chr2 100 105) transLRS=(9 999 10)</I> </B><BR> in <B>Combined</B> finds diabetes-associated transcripts with peak <A HREF="http://www.genenetwork.org/glossary.html#E" target="_blank" class="fs14"><small>trans eQTLs</small></A> on Chr 2 between 100 and 105 Mb with LRS scores between 9 and 999.
+
+
+</UL>
+</DIR>
+ </TD>
+<!-- END OF FIND SELECTOR PULL-DOWN PANEL (LEFT SIDE) -->
+
+<!-- START OF TOP RIGHT PANEL -->
+
+<TD vAlign=top width="40%" bgColor=#FFFFFF>
+ <p style="font-size:15px;font-family:verdana;color:black"><B>Websites Affiliated with GeneNetwork</B></p>
+ <p style="font-size:12px;font-family:verdana;color:black">
+ <ul>
+ <li><a href="http://ucscbrowser.genenetwork.org/" target="_blank">Genome Browser</a> at UTHSC</li>
+ <li><a href="http://galaxy.genenetwork.org/" target="_blank">Galaxy</a> at UTHSC</li>
+ <li>GeneNetwork at <a href="http://ec2.genenetwork.org/" target="_blank">Amazon Cloud (EC2)</a></li>
+ <li>GeneNetwork Source Codes at <a href="http://sourceforge.net/projects/genenetwork/" target="_blank">SourceForge</a></li>
+ </ul>
+ </p>
+ <P>____________________________
+
+ <p style="font-size:15px;font-family:verdana;color:black"><B>Getting Started</B> &nbsp;&nbsp; </p>
+ <OL style="font-size:12px;font-family:verdana;color:black">
+ <LI>Select <B>Species</B> (or select All)
+ <LI>Select <B>Group</B> (a specific sample)
+ <LI>Select <B>Type</B> of data:
+ <UL>
+ <LI>Phenotype (traits)
+ <LI>Genotype (markers)
+ <LI>Expression (mRNAs)
+ </UL>
+ <LI>Select a <B>Database</B>
+ <LI>Enter search terms in the <B>Get Any</B> or <B>Combined</B> field: words, genes, ID numbers, probes, advanced search commands
+ <LI>Click on the <B>Search</B> button
+ <LI>Optional: Use the <B>Make Default</B> button to save your preferences
+ </OL>
+
+ <P>____________________________
+
+<p style="font-size:14px;font-family:verdana;color:black"><B>How to Use GeneNetwork</B>
+
+ <BLOCKQUOTE>
+ <p style="font-size:12px;font-family:verdana;color:black">Take a 20-40 minute GeneNetwork <A HREF="http://www.genenetwork.org/tutorial/WebQTLTour/" target="_blank" class="fs14"><small>Tour</small></A> that includes screen shots and typical steps in the analysis.</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <p style="font-size:12px;font-family:verdana;color:black">For information about resources and methods, select the <img src="http://www.genenetwork.org/images/upload/Info.png" alt="INFO" border= 0 valign="middle"> buttons.</P>
+
+
+
+<p style="font-size:12px;font-family:verdana;color:black">Try the <A HREF="http://alexandria.uthsc.edu/" target="_blank" class="fs14"><small>Workstation</small></A> site to explore data and features that are being implemented.</P>
+
+
+<p style="font-size:12px;font-family:verdana;color:black">Review the <A HREF="/conditionsofUse.html" target="_blank" class="fs14"><small>Conditions</small></A> and <A HREF="/statusandContact.html" target="_blank" class="fs14"><small>Contacts</small></A> pages for information on the status of data sets and advice on their use and citation.</P>
+
+
+ </BLOCKQUOTE>
+
+
+
+ <p style="font-size:14px;font-family:verdana;color:black"><B>Mirror and Development Sites</B></P>
+
+ <UL>
+ <LI><A HREF="http://www.genenetwork.org/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Main GN site at UTHSC</A> (main site)
+ <LI><A HREF="http://www.genenetwork.waimr.uwa.edu.au/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Australia at the UWA</A>
+ <LI><A HREF="http://gn.genetics.ucla.edu/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">California at UCLA</A>
+ <LI><A HREF="http://genenetwork.helmholtz-hzi.de/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Germany at the HZI</A>
+ <LI><A HREF="https://genenetwork.hubrecht.eu/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Netherlands at the Hubrecht</A> (Development)
+ <LI><A HREF="http://xzhou3.memphis.edu/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Memphis at the U of M</A>
+ <LI><A HREF="http://webqtl.bic.nus.edu.sg/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Singapore at the NUS</A>
+ <LI><A HREF="http://genenetwork.epfl.ch/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Switzerland at the EPFL</A>
+ </UL>
+
+
+ <p style="font-size:14px;font-family:verdana;color:black"><B>History and Archive</B>
+
+ <BLOCKQUOTE>
+ <p style="font-size:12px;font-family:verdana;color:black">GeneNetwork's <A HREF="http://artemis.uthsc.edu" target="_blank" class="fs14"><small>Time Machine</small></A> links to earlier versions that correspond to specific publication dates.</P>
+
+ </BLOCKQUOTE>
+
+
+</P>
+ </TD>
+"""
diff --git a/web/webqtl/base/myCookie.py b/web/webqtl/base/myCookie.py
new file mode 100755
index 00000000..db5320df
--- /dev/null
+++ b/web/webqtl/base/myCookie.py
@@ -0,0 +1,55 @@
+# 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
+
+#########################################
+## python cookie and mod python cookie are
+## not compatible
+#########################################
+
+class myCookie(dict):
+ 'define my own cookie'
+
+ def __init__(self, name="", value="", expire = None, path="/"):
+ self['name']= name
+ self['value']= value
+ self['expire']= expire
+ self['path']= path
+
+ def __getattr__(self, key):
+ if key in self.keys():
+ return self[key]
+ else:
+ return None
+
+ def __nonzero__ (self):
+ if self['name']:
+ return 1
+ else:
+ return 0
+
+
+
+
diff --git a/web/webqtl/base/sessionData.py b/web/webqtl/base/sessionData.py
new file mode 100755
index 00000000..01555f87
--- /dev/null
+++ b/web/webqtl/base/sessionData.py
@@ -0,0 +1,53 @@
+# 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
+
+#########################################
+#convert mod_python object to Dict object
+#in order to be able to be pickled
+#########################################
+
+class sessionData(dict):
+ 'convert mod python Session object to Dict object'
+
+ def __init__(self, mod_python_session=None):
+
+ if not mod_python_session:
+ mod_python_session = {}
+
+ for key in mod_python_session.keys():
+ self[key]= mod_python_session[key]
+
+
+ def getvalue(self, k, default= None):
+ try:
+ return self[k]
+ except:
+ return default
+
+ getfirst = getvalue
+
+
+
diff --git a/web/webqtl/base/template.py b/web/webqtl/base/template.py
new file mode 100644
index 00000000..85bd86df
--- /dev/null
+++ b/web/webqtl/base/template.py
@@ -0,0 +1,123 @@
+# 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
+
+template = """
+<?XML VERSION="1.0" ENCODING="UTF-8">
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<TITLE>%s</TITLE>
+
+<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<META NAME="keywords" CONTENT="genetics, bioinformatics, genome, phenome, gene expression, complex trait analysis, gene mapping, SNP, quantitative trait locus QTL, expression eQTL, WebQTL, Traitnet, Traitnetwork, personalized medicine">
+<META NAME="description" CONTENT ="GeneNetwork is a free scientific web resource used to study relationships between differences in genes, environmental factors, phenotypes, and disease risk." >
+<META NAME="author" CONTENT ="GeneNetwork developers" >
+<META NAME="geo.placename" CONTENT ="Memphis, TN" >
+<META NAME="geo.region" CONTENT="US-TN">
+%s
+<LINK REL="stylesheet" TYPE="text/css" HREF='/css/general.css'>
+<LINK REL="stylesheet" TYPE="text/css" HREF='/css/menu.css'>
+<link rel="stylesheet" media="all" type="text/css" href="/css/tabbed_pages.css" />
+<LINK REL="apple-touch-icon" href="/images/ipad_icon3.png" />
+<link type="text/css" href='/css/custom-theme/jquery-ui-1.8.12.custom.css' rel='Stylesheet' />
+<link type="text/css" href='/css/tab_style.css' rel='Stylesheet' />
+
+<script type="text/javascript" src="/javascript/jquery-1.5.2.min.js"></script>
+<SCRIPT SRC="/javascript/webqtl.js"></SCRIPT>
+<SCRIPT SRC="/javascript/dhtml.js"></SCRIPT>
+<SCRIPT SRC="/javascript/tablesorter.js"></SCRIPT>
+<SCRIPT SRC="/javascript/jqueryFunction.js"></SCRIPT>
+<script src="/javascript/tabbed_pages.js" type="text/javascript"></script>
+<script src="/javascript/jquery-ui-1.8.12.custom.min.js" type="text/javascript"></script>
+%s
+
+<script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-3782271-1']);
+ _gaq.push(['_trackPageview']);
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+</script>
+</HEAD>
+<BODY bottommargin="2" leftmargin="2" rightmargin="2" topmargin="2" text=#000000 bgColor=#ffffff %s>
+%s
+<TABLE cellSpacing=5 cellPadding=4 width="100%%" border=0>
+ <TBODY>
+ <!-- Start of header -->
+ <TR>
+ %s
+ </TR>
+ <!-- End of header -->
+
+ <!-- Start of body -->
+ <TR>
+ <TD bgColor=#eeeeee class="solidBorder">
+ <Table width= "100%%" cellSpacing=0 cellPadding=5>
+ <TR>
+ %s
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <!-- End of body -->
+
+ <!-- Start of footer -->
+ <TR>
+ <TD align=center bgColor=#ddddff class="solidBorder">
+ <TABLE width="90%%">%s</table>
+ </td>
+ </TR>
+ <!-- End of footer -->
+</TABLE>
+
+<!-- menu script itself. you should not modify this file -->
+<script language="JavaScript" src="/javascript/menu_new.js"></script>
+<!-- items structure. menu hierarchy and links are stored there -->
+<script language="JavaScript" src="/javascript/menu_items.js"></script>
+<!-- files with geometry and styles structures -->
+<script language="JavaScript" src="/javascript/menu_tpl.js"></script>
+<script language="JavaScript">
+ <!--//
+ // Note where menu initialization block is located in HTML document.
+ // Don't try to position menu locating menu initialization block in
+ // some table cell or other HTML element. Always put it before </body>
+ // each menu gets two parameters (see demo files)
+ // 1. items structure
+ // 2. geometry structure
+ new menu (MENU_ITEMS, MENU_POS);
+ // make sure files containing definitions for these variables are linked to the document
+ // if you got some javascript error like "MENU_POS is not defined", then you've made syntax
+ // error in menu_tpl.js file or that file isn't linked properly.
+
+ // also take a look at stylesheets loaded in header in order to set styles
+ //-->
+</script>
+</BODY>
+</HTML>
+"""
diff --git a/web/webqtl/base/templatePage.py b/web/webqtl/base/templatePage.py
new file mode 100644
index 00000000..4dece24a
--- /dev/null
+++ b/web/webqtl/base/templatePage.py
@@ -0,0 +1,222 @@
+# 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
+
+#templatePage.py
+#
+#--Genenetwork generates a lot of pages; this file is the generic version of them, defining routines they all use.
+#
+#Classes:
+#templatePage
+#
+#Functions (of templatePage):
+#__init__(...) -- class constructor, allows a more specific template to be used in addition to templatePage
+#__str__(self) -- returns the object's elements as a tuple
+#__del__(self) -- closes the current connection to MySQL, if there is one
+#write -- explained below
+#writefile -- explained below
+#openMysql(self) -- opens a MySQL connection and stores the resulting cursor in the object's cursor variable
+#updMysql(self) -- same as openMysql
+#error -- explained below
+#session -- explained below
+
+
+import socket
+import time
+import shutil
+import MySQLdb
+import os
+
+from htmlgen import HTMLgen2 as HT
+
+import template
+import webqtlConfig
+import header
+import footer
+from utility import webqtlUtil
+
+
+
+class templatePage:
+
+ contents = ['title','basehref','js1','js2', 'layer', 'header', 'body', 'footer']
+
+ # you can pass in another template here if you want
+ def __init__(self, fd=None, template=template.template):
+
+ # initiate dictionary
+ self.starttime = time.time()
+ self.dict = {}
+ self.template = template
+
+ for item in self.contents:
+ self.dict[item] = ""
+
+ self.dict['basehref'] = "" #webqtlConfig.BASEHREF
+ self.cursor = None
+
+ self.cookie = [] #XZ: list to hold cookies (myCookie object) being changed
+ self.content_type = 'text/html'
+ self.content_disposition = ''
+ self.redirection = ''
+ self.debug = ''
+ self.attachment = ''
+
+ #XZ: Holding data (new data or existing data being changed) that should be saved to session. The data must be picklable!!!
+ self.session_data_changed = {}
+
+ self.userName = 'Guest'
+ self.privilege = 'guest'
+ if fd.input_session_data.has_key('user'):
+ self.userName = fd.input_session_data['user']
+ if fd.input_session_data.has_key('privilege'):
+ self.privilege = fd.input_session_data['privilege']
+
+ def __str__(self):
+
+ #XZ: default setting
+ thisUserName = self.userName
+ thisPrivilege = self.privilege
+ #XZ: user may just go through login or logoff page
+ if self.session_data_changed.has_key('user'):
+ thisUserName = self.session_data_changed['user']
+ if self.session_data_changed.has_key('privilege'):
+ thisPrivilege = self.session_data_changed['privilege']
+
+ if thisUserName == 'Guest':
+ userInfo = 'Welcome! <a href=/account.html><U>Login</U></a>'
+ else:
+ userInfo = 'Hi, %s! <a href=/webqtl/main.py?FormID=userLogoff><U>Logout</U></a>' % thisUserName
+
+ reload(header)
+ self.dict['header'] = header.header_string % userInfo
+
+ serverInfo = "It took %2.3f second(s) for %s to generate this page" % (time.time()-self.starttime, socket.getfqdn())
+ reload(footer)
+ self.dict['footer'] = footer.footer_string % serverInfo
+
+ slist = []
+ for item in self.contents:
+ slist.append(self.dict[item])
+ return self.template % tuple(slist)
+
+
+ def __del__(self):
+ if self.cursor:
+ self.cursor.close()
+
+ def write(self):
+ 'return string representation of this object'
+
+ if self.cursor:
+ self.cursor.close()
+
+ return str(self)
+
+ def writeFile(self, filename):
+ 'save string representation of this object into a file'
+ if self.cursor:
+ self.cursor.close()
+
+ try:
+ 'it could take a long time to generate the file, save to .tmp first'
+ fp = open(os.path.join(webqtlConfig.TMPDIR, filename+'.tmp'), 'wb')
+ fp.write(str(self))
+ fp.close()
+ path_tmp = os.path.join(webqtlConfig.TMPDIR, filename+'.tmp')
+ path_html = os.path.join(webqtlConfig.TMPDIR, filename)
+ shutil.move(path_tmp,path_html)
+ except:
+ pass
+
+ def openMysql(self):
+ try:
+ self.con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, \
+ user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+ self.cursor = self.con.cursor()
+ return 1
+ except:
+ heading = "Connect MySQL Server"
+ detail = ["Can't connect to MySQL server on '"+ webqtlConfig.MYSQL_SERVER+"':100061. \
+ The server may be down at this time"]
+ self.error(heading=heading,detail=detail,error="Error 2003")
+ return 0
+
+ def updMysql(self):
+ try:
+ self.con = MySQLdb.Connect(db=webqtlConfig.DB_UPDNAME,host=webqtlConfig.MYSQL_UPDSERVER, \
+ user=webqtlConfig.DB_UPDUSER,passwd=webqtlConfig.DB_UPDPASSWD)
+ self.cursor = self.con.cursor()
+ return 1
+ except:
+ heading = "Connect MySQL Server"
+ detail = ["update: Can't connect to MySQL server on '"+ webqtlConfig.MYSQL_UPDSERVER+"':100061. \
+ The server may be down at this time "]
+ self.error(heading=heading,detail=detail,error="Error 2003")
+ return 0
+
+ def error(self,heading="",intro=[],detail=[],title="Error",error="Error"):
+ 'generating a WebQTL style error page'
+ Heading = HT.Paragraph(heading)
+ Heading.__setattr__("class","title")
+
+ Intro = HT.Blockquote()
+ if intro:
+ for item in intro:
+ Intro.append(item)
+ else:
+ Intro.append(HT.Strong('Sorry!'),' Error occurred while processing\
+ your request.', HT.P(),'The nature of the error generated is as\
+ follows:')
+
+ Detail = HT.Blockquote()
+ Detail.append(HT.Span("%s : " % error,Class="fwb cr"))
+ if detail:
+ Detail2 = HT.Blockquote()
+ for item in detail:
+ Detail2.append(item)
+ Detail.append(HT.Italic(Detail2))
+
+ #Detail.__setattr__("class","subtitle")
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
+ TD_LR.append(Heading,Intro,Detail)
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = title
+
+ def session(self,mytitle="",myHeading=""):
+ 'generate a auto-refreshing temporary html file(waiting page)'
+ self.filename = webqtlUtil.generate_session()
+ self.dict['title'] = mytitle
+ self.dict['basehref'] = webqtlConfig.REFRESHSTR % (webqtlConfig.CGIDIR, self.filename) + "" #webqtlConfig.BASEHREF
+
+ TD_LR = HT.TD(align="center", valign="middle", height=200,width="100%", bgColor='#eeeeee')
+ Heading = HT.Paragraph(myHeading, Class="fwb fs16 cr")
+ # NL, 07/27/2010. variable 'PROGRESSBAR' has been moved from templatePage.py to webqtlUtil.py;
+ TD_LR.append(Heading, HT.BR(), webqtlUtil.PROGRESSBAR)
+ self.dict['body'] = TD_LR
+ self.writeFile(self.filename + '.html')
+ return self.filename
+
+
diff --git a/web/webqtl/base/webqtlCaseData.py b/web/webqtl/base/webqtlCaseData.py
new file mode 100755
index 00000000..4df32ca4
--- /dev/null
+++ b/web/webqtl/base/webqtlCaseData.py
@@ -0,0 +1,54 @@
+# 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 webqtlCaseData:
+ """
+ one case data in one trait
+ """
+
+ val = None #Trait Value
+ var = None #Trait Variance
+ N = None #Number of individuals
+
+ def __init__(self, val=val, var=var, N=N):
+ self.val = val
+ self.var = var
+ self.N = N
+
+ def __str__(self):
+ str = ""
+ if self.val != None:
+ str += "value=%2.3f" % self.val
+ if self.var != None:
+ str += " variance=%2.3f" % self.var
+ if self.N != None:
+ str += " ndata=%d" % self.N
+ return str
+
+ __repr__ = __str__
+
+
+
diff --git a/web/webqtl/base/webqtlConfig.py b/web/webqtl/base/webqtlConfig.py
new file mode 100755
index 00000000..87e2f3d0
--- /dev/null
+++ b/web/webqtl/base/webqtlConfig.py
@@ -0,0 +1,73 @@
+from webqtlConfigLocal import *
+#########################################'
+# Environment Variables - public
+#########################################
+
+#Debug Level
+#1 for debug, mod python will reload import each time
+DEBUG = 1
+
+#USER privilege
+USERDICT = {'guest':1,'user':2, 'admin':3, 'root':4}
+
+#minimum number of informative strains
+KMININFORMATIVE = 5
+
+#maximum number of traits for interval mapping
+MULTIPLEMAPPINGLIMIT = 11
+
+#maximum number of traits for correlation
+MAXCORR = 100
+
+#Daily download limit from one IP
+DAILYMAXIMUM = 1000
+
+#maximum LRS value
+MAXLRS = 460.0
+
+#temporary data life span
+MAXLIFE = 86400
+
+#MINIMUM Database public value
+PUBLICTHRESH = 0
+
+#NBCI address
+NCBI_LOCUSID = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s"
+UCSC_REFSEQ = "http://genome.cse.ucsc.edu/cgi-bin/hgGene?db=%s&hgg_gene=%s&hgg_chrom=chr%s&hgg_start=%s&hgg_end=%s"
+GENBANK_ID = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=Nucleotide&cmd=search&doptcmdl=DocSum&term=%s"
+OMIM_ID = "http://www.ncbi.nlm.nih.gov/omim/%s"
+UNIGEN_ID = "http://www.ncbi.nlm.nih.gov/UniGene/clust.cgi?ORG=%s&CID=%s"
+HOMOLOGENE_ID = "http://www.ncbi.nlm.nih.gov/sites/entrez?Db=homologene&Cmd=DetailsSearch&Term=%s"
+PUBMEDLINK_URL = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=PubMed&list_uids=%s&dopt=Abstract"
+UCSC_POS = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=mammal&org=%s&db=%s&position=chr%s:%s-%s&pix=800&Submit=submit"
+UCSC_BLAT = 'http://genome.ucsc.edu/cgi-bin/hgBlat?org=%s&db=%s&type=0&sort=0&output=0&userSeq=%s'
+UTHSC_BLAT = 'http://ucscbrowser.genenetwork.org/cgi-bin/hgBlat?org=%s&db=%s&type=0&sort=0&output=0&userSeq=%s'
+UCSC_GENOME = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d&hgt.customText=http://web2qtl.utmem.edu:88/snp/chr%s"
+ENSEMBLE_BLAT = 'http://www.ensembl.org/Mus_musculus/featureview?type=AffyProbe&id=%s'
+DBSNP = 'http://www.ncbi.nlm.nih.gov/SNP/snp_ref.cgi?type=rs&rs=%s'
+UCSC_RUDI_TRACK_URL = " http://genome.cse.ucsc.edu/cgi-bin/hgTracks?org=%s&db=%s&hgt.customText=http://gbic.biol.rug.nl/~ralberts/tracks/%s/%s"
+GENOMEBROWSER_URL="http://ucscbrowser.genenetwork.org/cgi-bin/hgTracks?clade=mammal&org=Mouse&db=mm9&position=%s&hgt.suggest=&pix=800&Submit=submit"
+ENSEMBLETRANSCRIPT_URL="http://useast.ensembl.org/Mus_musculus/Lucene/Details?species=Mus_musculus;idx=Transcript;end=1;q=%s"
+
+SECUREDIR = GNROOT + 'secure/'
+COMMON_LIB = GNROOT + 'support/admin'
+HTMLPATH = GNROOT + 'web/'
+IMGDIR = HTMLPATH +'image/'
+IMAGESPATH = HTMLPATH + 'images/'
+UPLOADPATH = IMAGESPATH + 'upload/'
+TMPDIR = HTMLPATH +'tmp/'
+GENODIR = HTMLPATH + 'genotypes/'
+GENO_ARCHIVE_DIR = GENODIR + 'archive/'
+TEXTDIR = HTMLPATH + 'ProbeSetFreeze_DataMatrix/'
+CMDLINEDIR = HTMLPATH + 'webqtl/cmdLine/'
+ChangableHtmlPath = GNROOT + 'web/'
+
+SITENAME = 'GN'
+PORTADDR = "http://132.192.47.32"
+BASEHREF = '<base href="http://132.192.47.32/">'
+INFOPAGEHREF = '/dbdoc/%s.html'
+GLOSSARYFILE = "/glossary.html"
+CGIDIR = '/webqtl/' #XZ: The variable name 'CGIDIR' should be changed to 'PYTHONDIR'
+SCRIPTFILE = 'main.py'
+REFRESHSTR = '<meta http-equiv="refresh" content="5;url=%s' + SCRIPTFILE +'?sid=%s">'
+REFRESHDIR = '%s' + SCRIPTFILE +'?sid=%s'
diff --git a/web/webqtl/base/webqtlConfigLocal.py b/web/webqtl/base/webqtlConfigLocal.py
new file mode 100755
index 00000000..0c95fe7b
--- /dev/null
+++ b/web/webqtl/base/webqtlConfigLocal.py
@@ -0,0 +1,19 @@
+#########################################'
+# Environment Variables - private
+#########################################
+
+MYSQL_SERVER = 'localhost'
+DB_NAME = 'db_webqtl'
+DB_USER = 'webqtlupd'
+DB_PASSWD = 'webqtl'
+
+MYSQL_UPDSERVER = 'localhost'
+DB_UPDNAME = 'db_webqtl'
+DB_UPDUSER = 'webqtlupd'
+DB_UPDPASSWD = 'webqtl'
+
+GNROOT = '/gnshare/gn/'
+PythonPath = '/usr/bin/python'
+PIDDLE_FONT_PATH = '/usr/lib/python2.4/site-packages/piddle/truetypefonts/'
+
+TEXTUI=0 # This is to protect GN production server. If set to 0, no text UI is allowed.
diff --git a/web/webqtl/base/webqtlDataset.py b/web/webqtl/base/webqtlDataset.py
new file mode 100755
index 00000000..da1b8601
--- /dev/null
+++ b/web/webqtl/base/webqtlDataset.py
@@ -0,0 +1,160 @@
+# 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 htmlgen import HTMLgen2 as HT
+
+import webqtlConfig
+
+
+
+class webqtlDataset:
+ """
+ Database class defines a database in webqtl, can be either Microarray,
+ Published phenotype, genotype, or user input database(temp)
+ """
+
+ def __init__(self, dbName, cursor=None):
+
+ assert dbName
+ self.id = 0
+ self.name = ''
+ self.type = ''
+ self.riset = ''
+ self.cursor = cursor
+
+ #temporary storage
+ if dbName.find('Temp') >= 0:
+ self.searchfield = ['name','description']
+ self.disfield = ['name','description']
+ self.type = 'Temp'
+ self.id = 1
+ self.fullname = 'Temporary Storage'
+ self.shortname = 'Temp'
+ elif dbName.find('Publish') >= 0:
+ self.searchfield = ['name','post_publication_description','abstract','title','authors']
+ self.disfield = ['name','pubmed_id',
+ 'pre_publication_description', 'post_publication_description', 'original_description',
+ 'pre_publication_abbreviation', 'post_publication_abbreviation',
+ 'lab_code', 'submitter', 'owner', 'authorized_users',
+ 'authors','title','abstract', 'journal','volume','pages','month',
+ 'year','sequence', 'units', 'comments']
+ self.type = 'Publish'
+ elif dbName.find('Geno') >= 0:
+ self.searchfield = ['name','chr']
+ self.disfield = ['name','chr','mb', 'source2', 'sequence']
+ self.type = 'Geno'
+ else: #ProbeSet
+ self.searchfield = ['name','description','probe_target_description',
+ 'symbol','alias','genbankid','unigeneid','omim',
+ 'refseq_transcriptid','probe_set_specificity', 'probe_set_blat_score']
+ self.disfield = ['name','symbol','description','probe_target_description',
+ 'chr','mb','alias','geneid','genbankid', 'unigeneid', 'omim',
+ 'refseq_transcriptid','blatseq','targetseq','chipid', 'comments',
+ 'strand_probe','strand_gene','probe_set_target_region',
+ 'probe_set_specificity', 'probe_set_blat_score','probe_set_blat_mb_start',
+ 'probe_set_blat_mb_end', 'probe_set_strand',
+ 'probe_set_note_by_rw', 'flag']
+ self.type = 'ProbeSet'
+ self.name = dbName
+ if self.cursor and self.id == 0:
+ self.retrieveName()
+
+ def __str__(self):
+ return self.name
+
+ __repr__ = __str__
+
+
+ def getRISet(self):
+ assert self.cursor
+ if self.type == 'Publish':
+ query = '''
+ SELECT
+ InbredSet.Name, InbredSet.Id
+ FROM
+ InbredSet, PublishFreeze
+ WHERE
+ PublishFreeze.InbredSetId = InbredSet.Id AND
+ PublishFreeze.Name = "%s"
+ ''' % self.name
+ elif self.type == 'Geno':
+ query = '''
+ SELECT
+ InbredSet.Name, InbredSet.Id
+ FROM
+ InbredSet, GenoFreeze
+ WHERE
+ GenoFreeze.InbredSetId = InbredSet.Id AND
+ GenoFreeze.Name = "%s"
+ ''' % self.name
+ elif self.type == 'ProbeSet':
+ query = '''
+ SELECT
+ InbredSet.Name, InbredSet.Id
+ FROM
+ InbredSet, ProbeSetFreeze, ProbeFreeze
+ WHERE
+ ProbeFreeze.InbredSetId = InbredSet.Id AND
+ ProbeFreeze.Id = ProbeSetFreeze.ProbeFreezeId AND
+ ProbeSetFreeze.Name = "%s"
+ ''' % self.name
+ else:
+ return ""
+ self.cursor.execute(query)
+ RISet, RIID = self.cursor.fetchone()
+ if RISet == 'BXD300':
+ RISet = "BXD"
+ self.riset = RISet
+ self.risetid = RIID
+ return RISet
+
+
+ def retrieveName(self):
+ assert self.id == 0 and self.cursor
+ query = '''
+ SELECT
+ Id, Name, FullName, ShortName
+ FROM
+ %sFreeze
+ WHERE
+ public > %d AND
+ (Name = "%s" OR FullName = "%s" OR ShortName = "%s")
+ '''% (self.type, webqtlConfig.PUBLICTHRESH, self.name, self.name, self.name)
+ try:
+ self.cursor.execute(query)
+ self.id,self.name,self.fullname,self.shortname=self.cursor.fetchone()
+ except:
+ raise KeyError, `self.name`+' doesn\'t exist.'
+
+
+ def genHTML(self, Class='c0dd'):
+ return HT.Href(text = HT.Span('%s Database' % self.fullname, Class= "fwb " + Class),
+ url= webqtlConfig.INFOPAGEHREF % self.name,target="_blank")
+
+
+
+
+
diff --git a/web/webqtl/base/webqtlFormData.py b/web/webqtl/base/webqtlFormData.py
new file mode 100755
index 00000000..84e41cae
--- /dev/null
+++ b/web/webqtl/base/webqtlFormData.py
@@ -0,0 +1,289 @@
+# 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 mod_python import Cookie
+import string
+import os
+
+import reaper
+
+import webqtlConfig
+import cookieData
+import sessionData
+from cgiData import cgiData
+from webqtlCaseData import webqtlCaseData
+from utility import webqtlUtil
+
+
+
+class webqtlFormData:
+ 'Represents data from a WebQTL form page, needed to generate the next page'
+ attrs = ('formID','RISet','genotype','strainlist','allstrainlist',
+ 'suggestive','significance','submitID','identification', 'enablevariance',
+ 'nperm','nboot','email','incparentsf1','genotype_1','genotype_2','traitInfo')
+
+ #XZ: Attention! All attribute values must be picklable!
+
+ def __init__(self, req = None, mod_python_session=None, FieldStorage_formdata=None):
+
+ for item in self.attrs:
+ setattr(self,item, None)
+
+ try:
+ self.remote_ip = req.connection.remote_ip
+ except:
+ self.remote_ip = '1.2.3.4'
+
+ if req and req.headers_in.has_key('referer'):
+ self.refURL = req.headers_in['referer']
+ else:
+ self.refURL = None
+
+
+ self.cookies = cookieData.cookieData(Cookie.get_cookies(req)) #XZ: dictionary type. To hold values transfered from mod_python Cookie.
+
+ #XZ: dictionary type. To hold values transfered from mod_python Session object. We assume that it is always picklable.
+ self.input_session_data = sessionData.sessionData( mod_python_session )
+
+ #XZ: FieldStorage_formdata may contain item that can't be pickled. Must convert to picklable data.
+ self.formdata = cgiData( FieldStorage_formdata )
+
+ #get Form ID
+ self.formID = self.formdata.getfirst('FormID')
+
+ #get rest of the attributes
+ if self.formID:
+ for item in self.attrs:
+ value = self.formdata.getfirst(item)
+ if value != None:
+ setattr(self,item,string.strip(value))
+
+ self.ppolar = ""
+ self.mpolar = ""
+ if self.RISet:
+ try:
+ # NL, 07/27/2010. ParInfo has been moved from webqtlForm.py to webqtlUtil.py;
+ f1, f12, self.mpolar, self.ppolar = webqtlUtil.ParInfo[self.RISet]
+ except:
+ f1 = f12 = self.mpolar = self.ppolar = None
+
+ try:
+ self.nperm = int(self.nperm)
+ self.nboot = int(self.nboot)
+ except:
+ self.nperm = 2000 #XZ: Rob asked to change the default value to 2000
+ self.nboot = 2000 #XZ: Rob asked to change the default value to 2000
+
+ if self.allstrainlist:
+ self.allstrainlist = map(string.strip, string.split(self.allstrainlist))
+ #self.readGenotype()
+ #self.readData()
+
+ if self.RISet == 'BXD300':
+ self.RISet = 'BXD'
+ else:
+ pass
+
+ def __str__(self):
+ rstr = ''
+ for item in self.attrs:
+ if item != 'genotype':
+ rstr += '%s:%s\n' % (item,str(getattr(self,item)))
+ return rstr
+
+
+ def readGenotype(self):
+ 'read genotype from .geno file'
+ if self.RISet == 'BXD300':
+ self.RISet = 'BXD'
+ else:
+ pass
+ assert self.RISet
+ #genotype_1 is Dataset Object without parents and f1
+ #genotype_2 is Dataset Object with parents and f1 (not for intercross)
+ self.genotype_1 = reaper.Dataset()
+ self.genotype_1.read(os.path.join(webqtlConfig.GENODIR, self.RISet + '.geno'))
+ try:
+ # NL, 07/27/2010. ParInfo has been moved from webqtlForm.py to webqtlUtil.py;
+ _f1, _f12, _mat, _pat = webqtlUtil.ParInfo[self.RISet]
+ except:
+ _f1 = _f12 = _mat = _pat = None
+
+ self.genotype_2 =self.genotype_1
+ if self.genotype_1.type == "riset" and _mat and _pat:
+ self.genotype_2 = self.genotype_1.add(Mat=_mat, Pat=_pat) #, F1=_f1)
+
+ #determine default genotype object
+ if self.incparentsf1 and self.genotype_1.type != "intercross":
+ self.genotype = self.genotype_2
+ else:
+ self.incparentsf1 = 0
+ self.genotype = self.genotype_1
+ self.strainlist = list(self.genotype.prgy)
+ self.f1list = self.parlist = []
+ if _f1 and _f12:
+ self.f1list = [_f1, _f12]
+ if _mat and _pat:
+ self.parlist = [_mat, _pat]
+
+ def readData(self, strainlst=[], incf1=[]):
+ 'read user input data or from trait data and analysis form'
+
+ if not self.genotype:
+ self.readGenotype()
+ if not strainlst:
+ if incf1:
+ strainlst = self.f1list + self.strainlist
+ else:
+ strainlst = self.strainlist
+
+
+ traitfiledata = self.formdata.getfirst('traitfile')
+ traitpastedata = self.formdata.getfirst('traitpaste')
+ variancefiledata = self.formdata.getfirst('variancefile')
+ variancepastedata = self.formdata.getfirst('variancepaste')
+ Nfiledata = self.formdata.getfirst('Nfile')
+
+
+ if traitfiledata:
+ tt = string.split(traitfiledata)
+ vals = map(webqtlUtil.StringAsFloat, tt)
+ elif traitpastedata:
+ tt = string.split(traitpastedata)
+ vals = map(webqtlUtil.StringAsFloat, tt)
+ else:
+ vals = map(self.FormDataAsFloat, strainlst)
+
+ if len(vals) < len(strainlst):
+ vals += [None]*(len(strainlst) - len(vals))
+ elif len(vals) > len(strainlst):
+ vals = vals[:len(strainlst)]
+ else:
+ pass
+
+
+ if variancefiledata:
+ tt = string.split(variancefiledata)
+ vars = map(webqtlUtil.StringAsFloat, tt)
+ elif variancepastedata:
+ tt = string.split(variancepastedata)
+ vars = map(webqtlUtil.StringAsFloat, tt)
+ else:
+ vars = map(self.FormVarianceAsFloat, strainlst)
+
+ if len(vars) < len(strainlst):
+ vars += [None]*(len(strainlst) - len(vars))
+ elif len(vars) > len(strainlst):
+ vars = vars[:len(strainlst)]
+ else:
+ pass
+
+ if Nfiledata:
+ tt = string.split(Nfiledata)
+ nstrains = map(webqtlUtil.IntAsFloat, tt)
+ if len(nstrains) < len(strainlst):
+ nstrains += [None]*(len(strainlst) - len(nstrains))
+ else:
+ nstrains = map(self.FormNAsFloat, strainlst)
+
+ ##vals, vars, nstrains is obsolete
+ self.allTraitData = {}
+ for i, _strain in enumerate(strainlst):
+ if vals[i] != None:
+ self.allTraitData[_strain] = webqtlCaseData(vals[i], vars[i], nstrains[i])
+
+
+
+ def informativeStrains(self, strainlst=[], incVars = 0):
+ '''if readData was called, use this to output the informative strains
+ (strain with values)'''
+ if not strainlst:
+ strainlst = self.strainlist
+ strains = []
+ vals = []
+ vars = []
+ for _strain in strainlst:
+ if self.allTraitData.has_key(_strain):
+ _val, _var = self.allTraitData[_strain].val, self.allTraitData[_strain].var
+ if _val != None:
+ if incVars:
+ if _var != None:
+ strains.append(_strain)
+ vals.append(_val)
+ vars.append(_var)
+ else:
+ strains.append(_strain)
+ vals.append(_val)
+ vars.append(None)
+ return strains, vals, vars, len(strains)
+
+
+
+ def FormDataAsFloat(self, key):
+ try:
+ return float(self.formdata.getfirst(key))
+ except:
+ return None
+
+
+ def FormVarianceAsFloat(self, key):
+ try:
+ return float(self.formdata.getfirst('V' + key))
+ except:
+ return None
+
+ def FormNAsFloat(self, key):
+ try:
+ return int(self.formdata.getfirst('N' + key))
+ except:
+ return None
+
+ def Sample(self):
+ 'Create some dummy data for testing'
+ self.RISet = 'BXD'
+ self.incparentsf1 = 'on'
+ #self.display = 9.2
+ #self.significance = 16.1
+ self.readGenotype()
+ self.identification = 'BXD : Coat color example by Lu Lu, et al'
+ #self.readGenotype()
+ #self.genotype.ReadMM('AXBXAforQTL')
+ #self.strainlist = map((lambda x, y='': '%s%s' % (y,x)), self.genotype.prgy)
+ #self.strainlist.sort()
+ self.allTraitData = {'BXD29': webqtlCaseData(3), 'BXD28': webqtlCaseData(2),
+ 'BXD25': webqtlCaseData(2), 'BXD24': webqtlCaseData(2), 'BXD27': webqtlCaseData(2),
+ 'BXD21': webqtlCaseData(1), 'BXD20': webqtlCaseData(4), 'BXD23': webqtlCaseData(4),
+ 'BXD22': webqtlCaseData(3), 'BXD14': webqtlCaseData(4), 'BXD15': webqtlCaseData(2),
+ 'BXD16': webqtlCaseData(3), 'BXD11': webqtlCaseData(4), 'BXD12': webqtlCaseData(3),
+ 'BXD13': webqtlCaseData(2), 'BXD18': webqtlCaseData(3), 'BXD19': webqtlCaseData(3),
+ 'BXD38': webqtlCaseData(3), 'BXD39': webqtlCaseData(3), 'BXD36': webqtlCaseData(2),
+ 'BXD34': webqtlCaseData(4), 'BXD35': webqtlCaseData(4), 'BXD32': webqtlCaseData(4),
+ 'BXD33': webqtlCaseData(3), 'BXD30': webqtlCaseData(1), 'BXD31': webqtlCaseData(4),
+ 'DBA/2J': webqtlCaseData(1), 'BXD8': webqtlCaseData(3), 'BXD9': webqtlCaseData(1),
+ 'BXD6': webqtlCaseData(3), 'BXD5': webqtlCaseData(3), 'BXD2': webqtlCaseData(4),
+ 'BXD1': webqtlCaseData(1), 'C57BL/6J': webqtlCaseData(4), 'B6D2F1': webqtlCaseData(4),
+ 'BXD42': webqtlCaseData(4), 'BXD40': webqtlCaseData(3)}
+
diff --git a/web/webqtl/base/webqtlTrait.py b/web/webqtl/base/webqtlTrait.py
new file mode 100644
index 00000000..f5051e45
--- /dev/null
+++ b/web/webqtl/base/webqtlTrait.py
@@ -0,0 +1,581 @@
+import string
+
+from htmlgen import HTMLgen2 as HT
+
+import webqtlConfig
+from webqtlCaseData import webqtlCaseData
+from webqtlDataset import webqtlDataset
+from dbFunction import webqtlDatabaseFunction
+from utility import webqtlUtil
+
+
+class webqtlTrait:
+ """
+ Trait class defines a trait in webqtl, can be either Microarray,
+ Published phenotype, genotype, or user input trait
+ """
+
+ def __init__(self, cursor = None, **kw):
+ self.cursor = cursor
+ self.db = None # database object
+ self.name = '' # Trait ID, ProbeSet ID, Published ID, etc.
+ self.cellid = ''
+ self.identification = 'un-named trait'
+ self.riset = ''
+ self.haveinfo = 0
+ self.sequence = '' # Blat sequence, available for ProbeSet
+ self.data = {}
+ for name, value in kw.items():
+ if self.__dict__.has_key(name):
+ setattr(self, name, value)
+ elif name == 'fullname':
+ name2 = value.split("::")
+ if len(name2) == 2:
+ self.db, self.name = name2
+ elif len(name2) == 3:
+ self.db, self.name, self.cellid = name2
+ else:
+ raise KeyError, `value` + ' parameter format error.'
+ else:
+ raise KeyError, `name`+' not a valid parameter for this class.'
+
+ if self.db and type(self.db) == type("1"):
+ assert self.cursor
+ self.db = webqtlDataset(self.db, self.cursor)
+
+ #if self.db == None, not from a database
+ if self.db:
+ if self.db.type == "Temp":
+ self.cursor.execute('''
+ SELECT
+ InbredSet.Name
+ FROM
+ InbredSet, Temp
+ WHERE
+ Temp.InbredSetId = InbredSet.Id AND
+ Temp.Name = "%s"
+ ''' % self.name)
+ self.riset = self.cursor.fetchone()[0]
+ else:
+ self.riset = self.db.getRISet()
+
+ #
+ # In ProbeSet, there are maybe several annotations match one sequence
+ # so we need use sequence(BlatSeq) as the identification, when we update
+ # one annotation, we update the others who match the sequence also.
+ #
+ # Hongqiang Li, 3/3/2008
+ #
+
+ #XZ, 05/08/2009: This block is not neccessary. We can add 'BlatSeq' into disfield.
+ # The variable self.sequence should be changed to self.BlatSeq
+ # It also should be changed in other places where it are used.
+
+ if self.db:
+ if self.db.type == 'ProbeSet':
+ query = '''
+ SELECT
+ ProbeSet.BlatSeq
+ FROM
+ ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSet.Id=ProbeSetXRef.ProbeSetId and
+ ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId and
+ ProbeSet.Name = "%s" and
+ ProbeSetFreeze.Name = "%s"
+ ''' % (self.name, self.db.name)
+ self.cursor.execute(query)
+ self.sequence = self.cursor.fetchone()[0]
+
+
+ def getName(self):
+ str = ""
+ if self.db and self.name:
+ str = "%s::%s" % (self.db, self.name)
+ if self.cellid:
+ str += "::" + self.cellid
+ else:
+ str = self.description
+ return str
+
+ #
+ # when user enter a trait or GN generate a trait, user want show the name
+ # not the name that generated by GN randomly, the two follow function are
+ # used to give the real name and the database. displayName() will show the
+ # database also, getGivenName() just show the name.
+ # For other trait, displayName() as same as getName(), getGivenName() as
+ # same as self.name
+ #
+ # Hongqiang 11/29/07
+ #
+ def getGivenName(self):
+ str = self.name
+ if self.db and self.name:
+ if self.db.type=='Temp':
+ self.cursor.execute('SELECT description FROM Temp WHERE Name=%s',self.name)
+ desc = self.cursor.fetchone()[0]
+ if desc.__contains__('PCA'):
+ desc = desc[desc.rindex(':')+1:].strip()
+ else:
+ desc = desc[:desc.index('entered')].strip()
+ str = desc
+ return str
+
+ def displayName(self):
+ str = ""
+ if self.db and self.name:
+ if self.db.type=='Temp':
+ desc = self.description
+ if desc.__contains__('PCA'):
+ desc = desc[desc.rindex(':')+1:].strip()
+ else:
+ desc = desc[:desc.index('entered')].strip()
+ str = "%s::%s" % (self.db, desc)
+ else:
+ str = "%s::%s" % (self.db, self.name)
+ if self.cellid:
+ str += "::" + self.cellid
+ else:
+ str = self.description
+
+ return str
+
+
+ #def __str__(self):
+ # #return "%s %s" % (self.getName(), self.riset)
+ # return self.getName()
+ __str__ = getName
+ __repr__ = __str__
+
+ def exportData(self, strainlist, type="val"):
+ """
+ export data according to strainlist
+ mostly used in calculating correlation
+ """
+ result = []
+ for strain in strainlist:
+ if self.data.has_key(strain):
+ if type=='val':
+ result.append(self.data[strain].val)
+ elif type=='var':
+ result.append(self.data[strain].var)
+ elif type=='N':
+ result.append(self.data[strain].N)
+ else:
+ raise KeyError, `type`+' type is incorrect.'
+ else:
+ result.append(None)
+ return result
+
+ def exportInformative(self, incVar=0):
+ """
+ export informative strain
+ mostly used in qtl regression
+ """
+ strains = []
+ vals = []
+ vars = []
+ for strain, value in self.data.items():
+ if value.val != None:
+ if not incVar or value.var != None:
+ strains.append(strain)
+ vals.append(value.val)
+ vars.append(value.var)
+ return strains, vals, vars
+
+
+ #
+ # In ProbeSet, there are maybe several annotations match one sequence
+ # so we need use sequence(BlatSeq) as the identification, when we update
+ # one annotation, we update the others who match the sequence also.
+ #
+ # Hongqiang Li, 3/3/2008
+ #
+ def getSequence(self):
+ assert self.cursor
+ if self.db.type == 'ProbeSet':
+ query = '''
+ SELECT
+ ProbeSet.BlatSeq
+ FROM
+ ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSet.Id=ProbeSetXRef.ProbeSetId and
+ ProbeSetFreeze.Id = ProbeSetXRef.ProbSetFreezeId and
+ ProbeSet.Name = %s
+ ProbeSetFreeze.Name = %s
+ ''' , (self.name, self.db.name)
+ self.cursor.execute(query)
+ results = self.fetchone()
+
+ return results[0]
+
+
+
+ def retrieveData(self, strainlist=[]):
+ assert self.db and self.cursor
+
+ if self.db.type == 'Temp':
+ query = '''
+ SELECT
+ Strain.Name, TempData.value, TempData.SE, TempData.NStrain, TempData.Id
+ FROM
+ TempData, Temp, Strain
+ WHERE
+ TempData.StrainId = Strain.Id AND
+ TempData.Id = Temp.DataId AND
+ Temp.name = '%s'
+ Order BY
+ Strain.Name
+ ''' % self.name
+ #XZ, 03/02/2009: Xiaodong changed Data to PublishData, SE to PublishSE
+ elif self.db.type == 'Publish':
+ query = '''
+ SELECT
+ Strain.Name, PublishData.value, PublishSE.error, NStrain.count, PublishData.Id
+ FROM
+ (PublishData, Strain, PublishXRef, PublishFreeze)
+ left join PublishSE on
+ (PublishSE.DataId = PublishData.Id AND PublishSE.StrainId = PublishData.StrainId)
+ left join NStrain on
+ (NStrain.DataId = PublishData.Id AND
+ NStrain.StrainId = PublishData.StrainId)
+ WHERE
+ PublishXRef.InbredSetId = PublishFreeze.InbredSetId AND
+ PublishData.Id = PublishXRef.DataId AND PublishXRef.Id = %s AND
+ PublishFreeze.Id = %d AND PublishData.StrainId = Strain.Id
+ Order BY
+ Strain.Name
+ ''' % (self.name, self.db.id)
+
+ #XZ, 03/02/2009: Xiaodong changed Data to ProbeData, SE to ProbeSE
+ elif self.cellid:
+ #Probe Data
+ query = '''
+ SELECT
+ Strain.Name, ProbeData.value, ProbeSE.error, ProbeData.Id
+ FROM
+ (ProbeData, ProbeFreeze, ProbeSetFreeze, ProbeXRef,
+ Strain, Probe, ProbeSet)
+ left join ProbeSE on
+ (ProbeSE.DataId = ProbeData.Id AND ProbeSE.StrainId = ProbeData.StrainId)
+ WHERE
+ Probe.Name = '%s' AND ProbeSet.Name = '%s' AND
+ Probe.ProbeSetId = ProbeSet.Id AND
+ ProbeXRef.ProbeId = Probe.Id AND
+ ProbeXRef.ProbeFreezeId = ProbeFreeze.Id AND
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id AND
+ ProbeSetFreeze.Name = '%s' AND
+ ProbeXRef.DataId = ProbeData.Id AND
+ ProbeData.StrainId = Strain.Id
+ Order BY
+ Strain.Name
+ ''' % (self.cellid, self.name, self.db.name)
+ #XZ, 03/02/2009: Xiaodong added this block for ProbeSetData and ProbeSetSE
+ elif self.db.type == 'ProbeSet':
+ #ProbeSet Data
+ query = '''
+ SELECT
+ Strain.Name, ProbeSetData.value, ProbeSetSE.error, ProbeSetData.Id
+ FROM
+ (ProbeSetData, ProbeSetFreeze, Strain, ProbeSet, ProbeSetXRef)
+ left join ProbeSetSE on
+ (ProbeSetSE.DataId = ProbeSetData.Id AND ProbeSetSE.StrainId = ProbeSetData.StrainId)
+ WHERE
+ ProbeSet.Name = '%s' AND ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id AND
+ ProbeSetFreeze.Name = '%s' AND
+ ProbeSetXRef.DataId = ProbeSetData.Id AND
+ ProbeSetData.StrainId = Strain.Id
+ Order BY
+ Strain.Name
+ ''' % (self.name, self.db.name)
+ #XZ, 03/02/2009: Xiaodong changeded Data to GenoData, SE to GenoSE
+ else:
+ #Geno Data
+ #XZ: The SpeciesId is not necessary, but it's nice to keep it to speed up database search.
+ query = '''
+ SELECT
+ Strain.Name, GenoData.value, GenoSE.error, GenoData.Id
+ FROM
+ (GenoData, GenoFreeze, Strain, Geno, GenoXRef)
+ left join GenoSE on
+ (GenoSE.DataId = GenoData.Id AND GenoSE.StrainId = GenoData.StrainId)
+ WHERE
+ Geno.SpeciesId = %s AND Geno.Name = '%s' AND GenoXRef.GenoId = Geno.Id AND
+ GenoXRef.GenoFreezeId = GenoFreeze.Id AND
+ GenoFreeze.Name = '%s' AND
+ GenoXRef.DataId = GenoData.Id AND
+ GenoData.StrainId = Strain.Id
+ Order BY
+ Strain.Name
+ ''' % (webqtlDatabaseFunction.retrieveSpeciesId(self.cursor, self.db.riset), self.name, self.db.name)
+
+
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+ self.data.clear()
+ if results:
+ self.mysqlid = results[0][-1]
+ if strainlist:
+ for item in results:
+ if item[0] in strainlist:
+ val = item[1]
+ if val != None:
+ var = item[2]
+ ndata = None
+ if self.db.type in ('Publish', 'Temp'):
+ ndata = item[3]
+ self.data[item[0]] = webqtlCaseData(val, var, ndata)
+ #end for
+ else:
+ for item in results:
+ val = item[1]
+ if val != None:
+ var = item[2]
+ ndata = None
+ if self.db.type in ('Publish', 'Temp'):
+ ndata = item[3]
+ self.data[item[0]] = webqtlCaseData(val, var, ndata)
+ #end for
+ #end if
+ else:
+ pass
+
+ def keys(self):
+ return self.__dict__.keys()
+
+ def has_key(self, key):
+ return self.__dict__.has_key(key)
+
+ def items(self):
+ return self.__dict__.items()
+
+ def retrieveInfo(self, QTL = None):
+ assert self.db and self.cursor
+ if self.db.type == 'Publish':
+ #self.db.DisField = ['Name','PubMed_ID','Phenotype','Abbreviation','Authors','Title',\
+ # 'Abstract', 'Journal','Volume','Pages','Month','Year','Sequence',\
+ # 'Units', 'comments']
+ query = '''
+ SELECT
+ PublishXRef.Id, Publication.PubMed_ID,
+ Phenotype.Pre_publication_description, Phenotype.Post_publication_description, Phenotype.Original_description,
+ Phenotype.Pre_publication_abbreviation, Phenotype.Post_publication_abbreviation,
+ Phenotype.Lab_code, Phenotype.Submitter, Phenotype.Owner, Phenotype.Authorized_Users,
+ Publication.Authors, Publication.Title, Publication.Abstract,
+ Publication.Journal, Publication.Volume, Publication.Pages,
+ Publication.Month, Publication.Year, PublishXRef.Sequence,
+ Phenotype.Units, PublishXRef.comments
+ FROM
+ PublishXRef, Publication, Phenotype, PublishFreeze
+ WHERE
+ PublishXRef.Id = %s AND
+ Phenotype.Id = PublishXRef.PhenotypeId AND
+ Publication.Id = PublishXRef.PublicationId AND
+ PublishXRef.InbredSetId = PublishFreeze.InbredSetId AND
+ PublishFreeze.Id =%s
+ ''' % (self.name, self.db.id)
+ #XZ, 05/08/2009: Xiaodong add this block to use ProbeSet.Id to find the probeset instead of just using ProbeSet.Name
+ #XZ, 05/08/2009: to avoid the problem of same probeset name from different platforms.
+ elif self.db.type == 'ProbeSet':
+ disfieldString = string.join(self.db.disfield,',ProbeSet.')
+ disfieldString = 'ProbeSet.' + disfieldString
+ query = """
+ SELECT %s
+ FROM ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetFreeze.Name = '%s' AND
+ ProbeSet.Name = '%s'
+ """ % (disfieldString, self.db.name, self.name)
+ #XZ, 05/08/2009: We also should use Geno.Id to find marker instead of just using Geno.Name
+ # to avoid the problem of same marker name from different species.
+ elif self.db.type == 'Geno':
+ disfieldString = string.join(self.db.disfield,',Geno.')
+ disfieldString = 'Geno.' + disfieldString
+ query = """
+ SELECT %s
+ FROM Geno, GenoFreeze, GenoXRef
+ WHERE
+ GenoXRef.GenoFreezeId = GenoFreeze.Id AND
+ GenoXRef.GenoId = Geno.Id AND
+ GenoFreeze.Name = '%s' AND
+ Geno.Name = '%s'
+ """ % (disfieldString, self.db.name, self.name)
+ else: #Temp type
+ query = 'SELECT %s FROM %s WHERE Name = "%s"' % \
+ (string.join(self.db.disfield,','), self.db.type, self.name)
+
+
+ self.cursor.execute(query)
+ traitInfo = self.cursor.fetchone()
+ if traitInfo:
+ self.haveinfo = 1
+
+ #XZ: assign SQL query result to trait attributes.
+ for i, field in enumerate(self.db.disfield):
+ setattr(self, field, traitInfo[i])
+
+ if self.db.type == 'Publish':
+ self.confidential = 0
+ if self.pre_publication_description and not self.pubmed_id:
+ self.confidential = 1
+
+ self.homologeneid = None
+ if self.db.type == 'ProbeSet' and self.riset and self.geneid:
+ #XZ, 05/26/2010: From time to time, this query get error message because some geneid values in database are not number.
+ #XZ: So I have to test if geneid is number before execute the query.
+ #XZ: The geneid values in database should be cleaned up.
+ try:
+ junk = float(self.geneid)
+ geneidIsNumber = 1
+ except:
+ geneidIsNumber = 0
+
+ if geneidIsNumber:
+ query = """
+ SELECT
+ HomologeneId
+ FROM
+ Homologene, Species, InbredSet
+ WHERE
+ Homologene.GeneId =%s AND
+ InbredSet.Name = '%s' AND
+ InbredSet.SpeciesId = Species.Id AND
+ Species.TaxonomyId = Homologene.TaxonomyId
+ """ % (self.geneid, self.riset)
+ self.cursor.execute(query)
+ result = self.cursor.fetchone()
+ else:
+ result = None
+
+ if result:
+ self.homologeneid = result[0]
+
+ if QTL:
+ if self.db.type == 'ProbeSet' and not self.cellid:
+ query = '''
+ SELECT
+ ProbeSetXRef.Locus, ProbeSetXRef.LRS, ProbeSetXRef.pValue, ProbeSetXRef.mean
+ FROM
+ ProbeSetXRef, ProbeSet
+ WHERE
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSet.Name = "%s" AND
+ ProbeSetXRef.ProbeSetFreezeId =%s
+ ''' % (self.name, self.db.id)
+ self.cursor.execute(query)
+ traitQTL = self.cursor.fetchone()
+ if traitQTL:
+ self.locus, self.lrs, self.pvalue, self.mean = traitQTL
+ else:
+ self.locus = self.lrs = self.pvalue = self.mean = ""
+ if self.db.type == 'Publish':
+ query = '''
+ SELECT
+ PublishXRef.Locus, PublishXRef.LRS
+ FROM
+ PublishXRef, PublishFreeze
+ WHERE
+ PublishXRef.Id = %s AND
+ PublishXRef.InbredSetId = PublishFreeze.InbredSetId AND
+ PublishFreeze.Id =%s
+ ''' % (self.name, self.db.id)
+ self.cursor.execute(query)
+ traitQTL = self.cursor.fetchone()
+ if traitQTL:
+ self.locus, self.lrs = traitQTL
+ else:
+ self.locus = self.lrs = ""
+ else:
+ raise KeyError, `self.name`+' information is not found in the database.'
+
+ def genHTML(self, formName = "", dispFromDatabase=0, privilege="guest", userName="Guest", authorized_users=""):
+ if not self.haveinfo:
+ self.retrieveInfo()
+
+ if self.db.type == 'Publish':
+ PubMedLink = ""
+ if self.pubmed_id:
+ PubMedLink = HT.Href(text="PubMed %d : " % self.pubmed_id,
+ target = "_blank", url = webqtlConfig.PUBMEDLINK_URL % self.pubmed_id)
+ else:
+ PubMedLink = HT.Span("Unpublished : ", Class="fs15")
+
+ if formName:
+ setDescription2 = HT.Href(url="javascript:showDatabase3('%s','%s','%s','')" %
+ (formName, self.db.name, self.name), Class = "fs14")
+ else:
+ setDescription2 = HT.Href(url="javascript:showDatabase2('%s','%s','')" %
+ (self.db.name,self.name), Class = "fs14")
+
+ if self.confidential and not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=privilege, userName=userName, authorized_users=authorized_users):
+ setDescription2.append('RecordID/%s - %s' % (self.name, self.pre_publication_description))
+ else:
+ setDescription2.append('RecordID/%s - %s' % (self.name, self.post_publication_description))
+
+ #XZ 03/26/2011: Xiaodong comment out the following two lins as Rob asked. Need to check with Rob why in PublishXRef table, there are few row whose Sequence > 1.
+ #if self.sequence > 1:
+ # setDescription2.append(' btach %d' % self.sequence)
+ if self.authors:
+ a1 = string.split(self.authors,',')[0]
+ while a1[0] == '"' or a1[0] == "'" :
+ a1 = a1[1:]
+ setDescription2.append(' by ')
+ setDescription2.append(HT.Italic('%s, and colleagues' % a1))
+ setDescription = HT.Span(PubMedLink, setDescription2)
+
+ elif self.db.type == 'Temp':
+ setDescription = HT.Href(text="%s" % (self.description),url="javascript:showDatabase2\
+ ('%s','%s','')" % (self.db.name,self.name), Class = "fs14")
+ setDescription = HT.Span(setDescription)
+
+ elif self.db.type == 'Geno': # Genome DB only available for single search
+ if formName:
+ setDescription = HT.Href(text="Locus %s [Chr %s @ %s Mb]" % (self.name,self.chr,\
+ '%2.3f' % self.mb),url="javascript:showDatabase3('%s','%s','%s','')" % \
+ (formName, self.db.name, self.name), Class = "fs14")
+ else:
+ setDescription = HT.Href(text="Locus %s [Chr %s @ %s Mb]" % (self.name,self.chr,\
+ '%2.3f' % self.mb),url="javascript:showDatabase2('%s','%s','')" % \
+ (self.db.name,self.name), Class = "fs14")
+
+ setDescription = HT.Span(setDescription)
+
+ else:
+ if self.cellid:
+ if formName:
+ setDescription = HT.Href(text="ProbeSet/%s/%s" % (self.name, self.cellid),url=\
+ "javascript:showDatabase3('%s','%s','%s','%s')" % (formName, self.db.name,self.name,self.cellid), \
+ Class = "fs14")
+ else:
+ setDescription = HT.Href(text="ProbeSet/%s/%s" % (self.name,self.cellid),url=\
+ "javascript:showDatabase2('%s','%s','%s')" % (self.db.name,self.name,self.cellid), \
+ Class = "fs14")
+ else:
+ if formName:
+ setDescription = HT.Href(text="ProbeSet/%s" % self.name, url=\
+ "javascript:showDatabase3('%s','%s','%s','')" % (formName, self.db.name,self.name), \
+ Class = "fs14")
+ else:
+ setDescription = HT.Href(text="ProbeSet/%s" % self.name, url=\
+ "javascript:showDatabase2('%s','%s','')" % (self.db.name,self.name), \
+ Class = "fs14")
+ if self.symbol and self.chr and self.mb:
+ setDescription.append(' [')
+ setDescription.append(HT.Italic('%s' % self.symbol,Class="cdg fwb"))
+ setDescription.append(' on Chr %s @ %s Mb]' % (self.chr,self.mb))
+ if self.description:
+ setDescription.append(': %s' % self.description)
+ if self.probe_target_description:
+ setDescription.append('; %s' % self.probe_target_description)
+ setDescription = HT.Span(setDescription)
+
+ if self.db.type != 'Temp' and dispFromDatabase:
+ setDescription.append( ' --- FROM : ')
+ setDescription.append(self.db.genHTML(Class='cori'))
+ return setDescription
+
+
diff --git a/web/webqtl/basicStatistics/BasicStatisticsFunctions.py b/web/webqtl/basicStatistics/BasicStatisticsFunctions.py
new file mode 100755
index 00000000..a22b50a2
--- /dev/null
+++ b/web/webqtl/basicStatistics/BasicStatisticsFunctions.py
@@ -0,0 +1,174 @@
+#import string
+from math import *
+import piddle as pid
+#import os
+
+import reaper
+from htmlgen import HTMLgen2 as HT
+
+from utility import Plot
+from utility import webqtlUtil
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+
+def basicStatsTable(vals, trait_type=None, cellid=None, heritability=None):
+
+ valsOnly = []
+ dataXZ = vals[:]
+ for i in range(len(dataXZ)):
+ valsOnly.append(dataXZ[i][1])
+
+ traitmean, traitmedian, traitvar, traitstdev, traitsem, N = reaper.anova(valsOnly) #ZS: Should convert this from reaper to R in the future
+
+ tbl = HT.TableLite(cellpadding=20, cellspacing=0)
+ dataXZ = vals[:]
+ dataXZ.sort(webqtlUtil.cmpOrder)
+ tbl.append(HT.TR(HT.TD("Statistic",align="left", Class="fs14 fwb ffl b1 cw cbrb", width = 180),
+ HT.TD("Value", align="right", Class="fs14 fwb ffl b1 cw cbrb", width = 60)))
+ tbl.append(HT.TR(HT.TD("N of Samples",align="left", Class="fs13 b1 cbw c222"),
+ HT.TD(N,nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ tbl.append(HT.TR(HT.TD("Mean",align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitmean,nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ tbl.append(HT.TR(HT.TD("Median",align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitmedian,nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ #tbl.append(HT.TR(HT.TD("Variance",align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ # HT.TD("%2.3f" % traitvar,nowrap="yes",align="left", Class="fs13 b1 cbw c222")))
+ tbl.append(HT.TR(HT.TD("Standard Error (SE)",align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitsem,nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ tbl.append(HT.TR(HT.TD("Standard Deviation (SD)", align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitstdev,nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ tbl.append(HT.TR(HT.TD("Minimum", align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%s" % dataXZ[0][1],nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ tbl.append(HT.TR(HT.TD("Maximum", align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%s" % dataXZ[-1][1],nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ if (trait_type != None and trait_type == 'ProbeSet'):
+ #IRQuest = HT.Href(text="Interquartile Range", url=webqtlConfig.glossaryfile +"#Interquartile",target="_blank", Class="fs14")
+ #IRQuest.append(HT.BR())
+ #IRQuest.append(" (fold difference)")
+ tbl.append(HT.TR(HT.TD("Range (log2)",align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % (dataXZ[-1][1]-dataXZ[0][1]),nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ tbl.append(HT.TR(HT.TD(HT.Span("Range (fold)"),align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.2f" % pow(2.0,(dataXZ[-1][1]-dataXZ[0][1])), nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+ tbl.append(HT.TR(HT.TD(HT.Span(HT.Href(url="/glossary.html#Interquartile", target="_blank", text="Interquartile Range", Class="non_bold")), align="left", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.2f" % pow(2.0,(dataXZ[int((N-1)*3.0/4.0)][1]-dataXZ[int((N-1)/4.0)][1])), nowrap="yes", Class="fs13 b1 cbw c222"), align="right"))
+
+ #XZ, 04/01/2009: don't try to get H2 value for probe.
+ if cellid:
+ pass
+ else:
+ if heritability:
+ tbl.append(HT.TR(HT.TD(HT.Span("Heritability"),align="center", Class="fs13 b1 cbw c222",nowrap="yes"),HT.TD("%s" % heritability, nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ else:
+ pass
+ # Lei Yan
+ # 2008/12/19
+
+ return tbl
+
+def plotNormalProbability(vals=None, RISet='', title=None, showstrains=0, specialStrains=[None], size=(750,500)):
+
+ dataXZ = vals[:]
+ dataXZ.sort(webqtlUtil.cmpOrder)
+ dataLabel = []
+ dataX = map(lambda X: X[1], dataXZ)
+
+ showLabel = showstrains
+ if len(dataXZ) > 50:
+ showLabel = 0
+ for item in dataXZ:
+ strainName = webqtlUtil.genShortStrainName(RISet=RISet, input_strainName=item[0])
+ dataLabel.append(strainName)
+
+ dataY=Plot.U(len(dataX))
+ dataZ=map(Plot.inverseCumul,dataY)
+ c = pid.PILCanvas(size=(750,500))
+ Plot.plotXY(c, dataZ, dataX, dataLabel = dataLabel, XLabel='Expected Z score', connectdot=0, YLabel='Trait value', title=title, specialCases=specialStrains, showLabel = showLabel)
+
+ filename= webqtlUtil.genRandStr("nP_")
+ c.save(webqtlConfig.IMGDIR+filename, format='gif')
+
+ img=HT.Image('/image/'+filename+'.gif',border=0)
+
+ return img
+
+def plotBoxPlot(vals):
+
+ valsOnly = []
+ dataXZ = vals[:]
+ for i in range(len(dataXZ)):
+ valsOnly.append(dataXZ[i][1])
+
+ plotHeight = 320
+ plotWidth = 220
+ xLeftOffset = 60
+ xRightOffset = 40
+ yTopOffset = 40
+ yBottomOffset = 60
+
+ canvasHeight = plotHeight + yTopOffset + yBottomOffset
+ canvasWidth = plotWidth + xLeftOffset + xRightOffset
+ canvas = pid.PILCanvas(size=(canvasWidth,canvasHeight))
+ XXX = [('', valsOnly[:])]
+
+ Plot.plotBoxPlot(canvas, XXX, offset=(xLeftOffset, xRightOffset, yTopOffset, yBottomOffset), XLabel= "Trait")
+ filename= webqtlUtil.genRandStr("Box_")
+ canvas.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img=HT.Image('/image/'+filename+'.gif',border=0)
+
+ plotLink = HT.Span("More about ", HT.Href(text="Box Plots", url="http://davidmlane.com/hyperstat/A37797.html", target="_blank", Class="fs13"))
+
+ return img, plotLink
+
+def plotBarGraph(identification='', RISet='', vals=None, type="name"):
+
+ this_identification = "unnamed trait"
+ if identification:
+ this_identification = identification
+
+ if type=="rank":
+ dataXZ = vals[:]
+ dataXZ.sort(webqtlUtil.cmpOrder)
+ title='%s' % this_identification
+ else:
+ dataXZ = vals[:]
+ title='%s' % this_identification
+
+ tvals = []
+ tnames = []
+ tvars = []
+ for i in range(len(dataXZ)):
+ tvals.append(dataXZ[i][1])
+ tnames.append(webqtlUtil.genShortStrainName(RISet=RISet, input_strainName=dataXZ[i][0]))
+ tvars.append(dataXZ[i][2])
+ nnStrain = len(tnames)
+
+ sLabel = 1
+
+ ###determine bar width and space width
+ if nnStrain < 20:
+ sw = 4
+ elif nnStrain < 40:
+ sw = 3
+ else:
+ sw = 2
+
+ ### 700 is the default plot width minus Xoffsets for 40 strains
+ defaultWidth = 650
+ if nnStrain > 40:
+ defaultWidth += (nnStrain-40)*10
+ defaultOffset = 100
+ bw = int(0.5+(defaultWidth - (nnStrain-1.0)*sw)/nnStrain)
+ if bw < 10:
+ bw = 10
+
+ plotWidth = (nnStrain-1)*sw + nnStrain*bw + defaultOffset
+ plotHeight = 500
+ #print [plotWidth, plotHeight, bw, sw, nnStrain]
+ c = pid.PILCanvas(size=(plotWidth,plotHeight))
+ Plot.plotBarText(c, tvals, tnames, variance=tvars, YLabel='Value', title=title, sLabel = sLabel, barSpace = sw)
+
+ filename= webqtlUtil.genRandStr("Bar_")
+ c.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img=HT.Image('/image/'+filename+'.gif',border=0)
+
+ return img
diff --git a/web/webqtl/basicStatistics/BasicStatisticsPage_alpha.py b/web/webqtl/basicStatistics/BasicStatisticsPage_alpha.py
new file mode 100755
index 00000000..4ba9d54a
--- /dev/null
+++ b/web/webqtl/basicStatistics/BasicStatisticsPage_alpha.py
@@ -0,0 +1,348 @@
+# 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
+
+import string
+from math import *
+import piddle as pid
+import os
+
+from htmlgen import HTMLgen2 as HT
+import reaper
+
+from utility import Plot
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+
+
+
+class BasicStatisticsPage_alpha(templatePage):
+
+ plotMinInformative = 4
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not fd.genotype:
+ fd.readGenotype()
+ strainlist2 = fd.strainlist
+
+ if fd.allstrainlist:
+ strainlist2 = fd.allstrainlist
+
+ fd.readData(strainlist2)
+
+ specialStrains = []
+ setStrains = []
+ for item in strainlist2:
+ if item not in fd.strainlist and item.find('F1') < 0:
+ specialStrains.append(item)
+ else:
+ setStrains.append(item)
+ specialStrains.sort()
+ #So called MDP Panel
+ if specialStrains:
+ specialStrains = fd.f1list+fd.parlist+specialStrains
+
+ self.plotType = fd.formdata.getvalue('ptype', '0')
+ plotStrains = strainlist2
+ if specialStrains:
+ if self.plotType == '1':
+ plotStrains = setStrains
+ if self.plotType == '2':
+ plotStrains = specialStrains
+
+ self.dict['title'] = 'Basic Statistics'
+ if not self.openMysql():
+ return
+
+ self.showstrains = 1
+ self.identification = "unnamed trait"
+
+ self.fullname = fd.formdata.getvalue('fullname', '')
+ if self.fullname:
+ self.Trait = webqtlTrait(fullname=self.fullname, cursor=self.cursor)
+ self.Trait.retrieveInfo()
+ else:
+ self.Trait = None
+
+ if fd.identification:
+ self.identification = fd.identification
+ self.dict['title'] = self.identification + ' / '+self.dict['title']
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ ##should not display Variance, but cannot convert Variance to SE
+ #print plotStrains, fd.allTraitData.keys()
+ if len(fd.allTraitData) > 0:
+ vals=[]
+ InformData = []
+ for _strain in plotStrains:
+ if fd.allTraitData.has_key(_strain):
+ _val, _var = fd.allTraitData[_strain].val, fd.allTraitData[_strain].var
+ if _val != None:
+ vals.append([_strain, _val, _var])
+ InformData.append(_val)
+
+ if len(vals) >= self.plotMinInformative:
+ supertable2 = HT.TableLite(border=0, cellspacing=0, cellpadding=5,width="800")
+
+ staIntro1 = HT.Paragraph("The table and plots below list the basic statistical analysis result of trait",HT.Strong(" %s" % self.identification))
+
+ #####
+ #anova
+ #####
+ traitmean, traitmedian, traitvar, traitstdev, traitsem, N = reaper.anova(InformData)
+ TDStatis = HT.TD(width="360", valign="top")
+ tbl2 = HT.TableLite(cellpadding=5, cellspacing=0, Class="collap")
+ dataXZ = vals[:]
+ dataXZ.sort(self.cmpValue)
+ tbl2.append(HT.TR(HT.TD("Statistic",align="center", Class="fs14 fwb ffl b1 cw cbrb", width = 200),
+ HT.TD("Value", align="center", Class="fs14 fwb ffl b1 cw cbrb", width = 140)))
+ tbl2.append(HT.TR(HT.TD("N of Cases",align="center", Class="fs13 b1 cbw c222"),
+ HT.TD(N,nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD("Mean",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitmean,nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD("Median",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitmedian,nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ #tbl2.append(HT.TR(HT.TD("Variance",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ # HT.TD("%2.3f" % traitvar,nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD("SEM",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitsem,nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD("SD",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % traitstdev,nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD("Minimum",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%s" % dataXZ[0][1],nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD("Maximum",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%s" % dataXZ[-1][1],nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ if self.Trait and self.Trait.db.type == 'ProbeSet':
+ #IRQuest = HT.Href(text="Interquartile Range", url=webqtlConfig.glossaryfile +"#Interquartile",target="_blank", Class="fs14")
+ #IRQuest.append(HT.BR())
+ #IRQuest.append(" (fold difference)")
+ tbl2.append(HT.TR(HT.TD("Range (log2)",align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.3f" % (dataXZ[-1][1]-dataXZ[0][1]),nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD(HT.Span("Range (fold)"),align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.2f" % pow(2.0,(dataXZ[-1][1]-dataXZ[0][1])), nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ tbl2.append(HT.TR(HT.TD(HT.Span("Quartile Range",HT.BR()," (fold difference)"),align="center", Class="fs13 b1 cbw c222",nowrap="yes"),
+ HT.TD("%2.2f" % pow(2.0,(dataXZ[int((N-1)*3.0/4.0)][1]-dataXZ[int((N-1)/4.0)][1])), nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+
+ # (Lei Yan)
+ # 2008/12/19
+ self.Trait.retrieveData()
+ #XZ, 04/01/2009: don't try to get H2 value for probe.
+ if self.Trait.cellid:
+ pass
+ else:
+ self.cursor.execute("SELECT DataId, h2 from ProbeSetXRef WHERE DataId = %d" % self.Trait.mysqlid)
+ dataid, heritability = self.cursor.fetchone()
+ if heritability:
+ tbl2.append(HT.TR(HT.TD(HT.Span("Heritability"),align="center", Class="fs13 b1 cbw c222",nowrap="yes"),HT.TD("%s" % heritability, nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+ else:
+ tbl2.append(HT.TR(HT.TD(HT.Span("Heritability"),align="center", Class="fs13 b1 cbw c222",nowrap="yes"),HT.TD("NaN", nowrap="yes",align="center", Class="fs13 b1 cbw c222")))
+
+ # Lei Yan
+ # 2008/12/19
+
+ TDStatis.append(tbl2)
+
+ plotHeight = 220
+ plotWidth = 120
+ xLeftOffset = 60
+ xRightOffset = 25
+ yTopOffset = 20
+ yBottomOffset = 53
+
+ canvasHeight = plotHeight + yTopOffset + yBottomOffset
+ canvasWidth = plotWidth + xLeftOffset + xRightOffset
+ canvas = pid.PILCanvas(size=(canvasWidth,canvasHeight))
+ XXX = [('', InformData[:])]
+
+ Plot.plotBoxPlot(canvas, XXX, offset=(xLeftOffset, xRightOffset, yTopOffset, yBottomOffset), XLabel= "Trait")
+ filename= webqtlUtil.genRandStr("Box_")
+ canvas.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img=HT.Image('/image/'+filename+'.gif',border=0)
+
+ #supertable2.append(HT.TR(HT.TD(staIntro1, colspan=3 )))
+ tb = HT.TableLite(border=0, cellspacing=0, cellpadding=0)
+ tb.append(HT.TR(HT.TD(img, align="left", style="border: 1px solid #999999; padding:0px;")))
+ supertable2.append(HT.TR(TDStatis, HT.TD(tb)))
+
+ dataXZ = vals[:]
+ tvals = []
+ tnames = []
+ tvars = []
+ for i in range(len(dataXZ)):
+ tvals.append(dataXZ[i][1])
+ tnames.append(webqtlUtil.genShortStrainName(fd, dataXZ[i][0]))
+ tvars.append(dataXZ[i][2])
+ nnStrain = len(tnames)
+
+ sLabel = 1
+
+ ###determine bar width and space width
+ if nnStrain < 20:
+ sw = 4
+ elif nnStrain < 40:
+ sw = 3
+ else:
+ sw = 2
+
+ ### 700 is the default plot width minus Xoffsets for 40 strains
+ defaultWidth = 650
+ if nnStrain > 40:
+ defaultWidth += (nnStrain-40)*10
+ defaultOffset = 100
+ bw = int(0.5+(defaultWidth - (nnStrain-1.0)*sw)/nnStrain)
+ if bw < 10:
+ bw = 10
+
+ plotWidth = (nnStrain-1)*sw + nnStrain*bw + defaultOffset
+ plotHeight = 500
+ #print [plotWidth, plotHeight, bw, sw, nnStrain]
+ c = pid.PILCanvas(size=(plotWidth,plotHeight))
+ Plot.plotBarText(c, tvals, tnames, variance=tvars, YLabel='Value', title='%s by Case (sorted by name)' % self.identification, sLabel = sLabel, barSpace = sw)
+
+ filename= webqtlUtil.genRandStr("Bar_")
+ c.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img0=HT.Image('/image/'+filename+'.gif',border=0)
+
+ dataXZ = vals[:]
+ dataXZ.sort(self.cmpValue)
+ tvals = []
+ tnames = []
+ tvars = []
+ for i in range(len(dataXZ)):
+ tvals.append(dataXZ[i][1])
+ tnames.append(webqtlUtil.genShortStrainName(fd, dataXZ[i][0]))
+ tvars.append(dataXZ[i][2])
+
+ c = pid.PILCanvas(size=(plotWidth,plotHeight))
+ Plot.plotBarText(c, tvals, tnames, variance=tvars, YLabel='Value', title='%s by Case (ranked)' % self.identification, sLabel = sLabel, barSpace = sw)
+
+ filename= webqtlUtil.genRandStr("Bar_")
+ c.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img1=HT.Image('/image/'+filename+'.gif',border=0)
+
+ # Lei Yan
+ # 05/18/2009
+ # report
+
+ title = HT.Paragraph('REPORT on the variation of Shh (or PCA Composite Trait XXXX) (sonic hedgehog) in the (insert Data set name) of (insert Species informal name, e.g., Mouse, Rat, Human, Barley, Arabidopsis)', Class="title")
+ header = HT.Paragraph('''This report was generated by GeneNetwork on May 11, 2009, at 11.20 AM using the Basic Statistics module (v 1.0) and data from the Hippocampus Consortium M430v2 (Jun06) PDNN data set. For more details and updates on this data set please link to URL:get Basic Statistics''')
+ hr = HT.HR()
+ p1 = HT.Paragraph('''Trait values for Shh were taken from the (insert Database name, Hippocampus Consortium M430v2 (Jun06) PDNN). GeneNetwork contains data for NN (e.g., 99) cases. In general, data are averages for each case. A summary of mean, median, and the range of these data are provided in Table 1 and in the box plot (Figure 1). Data for individual cases are provided in Figure 2A and 2B, often with error bars (SEM). ''')
+ p2 = HT.Paragraph('''Trait values for Shh range 5.1-fold: from a low of 8.2 (please round value) in 129S1/SvImJ to a high of 10.6 (please round value) in BXD9. The interquartile range (the difference between values closest to the 25% and 75% levels) is a more modest 1.8-fold. The mean value is XX. ''')
+ t1 = HT.Paragraph('''Table 1. Summary of Shh data from the Hippocampus Consortium M430v2 (june06) PDNN data set''')
+ f1 = HT.Paragraph('''Figure 1. ''')
+ f1.append(HT.Href(text="Box plot", url="http://davidmlane.com/hyperstat/A37797.html", target="_blank", Class="fs14"))
+ f1.append(HT.Text(''' of Shh data from the Hippocampus Consortium M430v2 (june06) PDNN data set'''))
+ f2A = HT.Paragraph('''Figure 2A: Bar chart of Shh data ordered by case from the Hippocampus Consortium M430v2 (june06) PDNN data set''')
+ f2B = HT.Paragraph('''Figure 2B: Bar chart of Shh values ordered by from the Hippocampus Consortium M430v2 (june06) PDNN data set''')
+ TD_LR.append(HT.Blockquote(title, HT.P(), header, hr, p1, HT.P(), p2, HT.P(), supertable2, t1, f1, HT.P(), img0, f2A, HT.P(), img1, f2B))
+ self.dict['body'] = str(TD_LR)
+ else:
+ heading = "Basic Statistics"
+ detail = ['Fewer than %d case data were entered for %s data set. No statitical analysis has been attempted.' % (self.plotMinInformative, fd.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = "Basic Statistics"
+ detail = ['Empty data set, please check your data.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ def traitInfo(self, fd, specialStrains = None):
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+ heading2 = HT.Paragraph(HT.Strong('Population: '), "%s %s" % (species.title(), fd.RISet) , HT.BR())
+ if self.Trait:
+ trait_url = HT.Href(text=self.Trait.name, url = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE) + \
+ "?FormID=showDatabase&incparentsf1=1&database=%s&ProbeSetID=%s" % (self.Trait.db.name, self.Trait.name), \
+ target='_blank', Class="fs13 fwn")
+ heading2.append(HT.Strong("Database: "),
+ HT.Href(text=self.Trait.db.fullname, url = webqtlConfig.INFOPAGEHREF % self.Trait.db.name ,
+ target='_blank',Class="fs13 fwn"),HT.BR())
+ if self.Trait.db.type == 'ProbeSet':
+ heading2.append(HT.Strong('Trait ID: '), trait_url, HT.BR(),
+ HT.Strong("Gene Symbol: "), HT.Italic('%s' % self.Trait.symbol,id="green"),HT.BR())
+ if self.Trait.chr and self.Trait.mb:
+ heading2.append(HT.Strong("Location: "), 'Chr %s @ %s Mb' % (self.Trait.chr, self.Trait.mb))
+ elif self.Trait.db.type == 'Geno':
+ heading2.append(HT.Strong('Locus : '), trait_url, HT.BR())
+ #heading2.append(HT.Strong("Gene Symbol: "), HT.Italic('%s' % self.Trait.Symbol,id="green"),HT.BR())
+ if self.Trait.chr and self.Trait.mb:
+ heading2.append(HT.Strong("Location: "), 'Chr %s @ %s Mb' % (self.Trait.chr, self.Trait.mb))
+ elif self.Trait.db.type == 'Publish':
+ heading2.append(HT.Strong('Record ID: '), trait_url, HT.BR())
+ heading2.append(HT.Strong('Phenotype: '), self.Trait.phenotype, HT.BR())
+ heading2.append(HT.Strong('Author: '), self.Trait.authors, HT.BR())
+ elif self.Trait.db.type == 'Temp':
+ heading2.append(HT.Strong('Description: '), self.Trait.description, HT.BR())
+ #heading2.append(HT.Strong('Author: '), self.Trait.authors, HT.BR())
+ else:
+ pass
+ else:
+ heading2.append(HT.Strong("Trait Name: "), fd.identification)
+
+ if specialStrains:
+ mdpform = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='MDP_Form',submit=HT.Input(type='hidden'))
+ mdphddn = {'FormID':'dataEditing', 'submitID':'basicStatistics','RISet':fd.RISet, "allstrainlist":string.join(fd.allstrainlist, " "), "ptype":self.plotType, 'identification':fd.identification, "incparentsf1":1}
+ if self.fullname: mdphddn['fullname'] = self.fullname
+ webqtlUtil.exportData(mdphddn, fd.allTraitData)
+ for key in mdphddn.keys():
+ mdpform.append(HT.Input(name=key, value=mdphddn[key], type='hidden'))
+ btn0 = HT.Input(type='button' ,name='',value='All Cases',onClick="this.form.ptype.value=0;submit();", Class="button")
+ btn1 = HT.Input(type='button' ,name='',value='%s Only' % fd.RISet,onClick="this.form.ptype.value=1;submit();", Class="button")
+ btn2 = HT.Input(type='button' ,name='',value='MDP Only', onClick="this.form.ptype.value=2;submit();", Class="button")
+ mdpform.append(btn0)
+ mdpform.append(btn1)
+ mdpform.append(btn2)
+ heading2.append(HT.P(), mdpform)
+
+ return HT.Span(heading2)
+
+ def calSD(self,var):
+ try:
+ return sqrt(abs(var))
+ except:
+ return None
+
+
+ def cmpValue(self,A,B):
+ try:
+ if A[1] < B[1]:
+ return -1
+ elif A[1] == B[1]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+
+
+
diff --git a/web/webqtl/basicStatistics/__init__.py b/web/webqtl/basicStatistics/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/basicStatistics/__init__.py
diff --git a/web/webqtl/basicStatistics/updatedBasicStatisticsPage.py b/web/webqtl/basicStatistics/updatedBasicStatisticsPage.py
new file mode 100755
index 00000000..156dafe7
--- /dev/null
+++ b/web/webqtl/basicStatistics/updatedBasicStatisticsPage.py
@@ -0,0 +1,150 @@
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from dbFunction import webqtlDatabaseFunction
+import BasicStatisticsFunctions
+
+#Window generated from the Trait Data and Analysis page (DataEditingPage.py) with updated stats figures; takes the page's values that can bed edited by the user
+class updatedBasicStatisticsPage(templatePage):
+
+ plotMinInformative = 4
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not fd.genotype:
+ fd.readGenotype()
+ this_strainlist = fd.strainlist
+
+ if fd.allstrainlist:
+ this_strainlist = fd.allstrainlist
+
+ fd.readData(this_strainlist)
+
+ specialStrains = [] #This appears to be the "other/non-RISet strainlist" without parents/f1 strains; not sure what to name it
+ setStrains = []
+ for item in this_strainlist:
+ if item not in fd.strainlist and item.find('F1') < 0:
+ specialStrains.append(item)
+ else:
+ continue
+
+ specialStrains.sort()
+ if specialStrains:
+ specialStrains = fd.f1list+fd.parlist+specialStrains
+
+ self.dict['title'] = 'Basic Statistics'
+ TD_LR = HT.TD(valign="top",width="100%",bgcolor="#fafafa")
+
+ stats_row = HT.TR()
+ stats_cell = HT.TD()
+ stats_script = HT.Script(language="Javascript")
+
+ #Get strain names, values, and variances
+ strain_names = fd.formdata.getvalue('strainNames').split(',')
+ strain_vals = fd.formdata.getvalue('strainVals').split(',')
+ strain_vars = fd.formdata.getvalue('strainVars').split(',')
+
+ vals = []
+ if (len(strain_names) > 0):
+ if (len(strain_names) > 3):
+ #Need to create "vals" object
+ for i in range(len(strain_names)):
+ try:
+ this_strain_val = float(strain_vals[i])
+ except:
+ continue
+ try:
+ this_strain_var = float(strain_vars[i])
+ except:
+ this_strain_var = None
+
+ thisValFull = [strain_names[i], this_strain_val, this_strain_var]
+ vals.append(thisValFull)
+
+ stats_tab_list = [HT.Href(text="Basic Table", url="#statstabs-1", Class="stats_tab"),HT.Href(text="Probability Plot", url="#statstabs-5", Class="stats_tab"),
+ HT.Href(text="Bar Graph (by name)", url="#statstabs-3", Class="stats_tab"), HT.Href(text="Bar Graph (by rank)", url="#statstabs-4", Class="stats_tab"),
+ HT.Href(text="Box Plot", url="#statstabs-2", Class="stats_tab")]
+ stats_tabs = HT.List(stats_tab_list)
+
+ stats_container = HT.Div(id="stats_tabs", Class="ui-tabs")
+ stats_container.append(stats_tabs)
+
+ stats_script_text = """$(function() { $("#stats_tabs").tabs();});""" #Javascript enabling tabs
+
+ table_div = HT.Div(id="statstabs-1")
+ table_container = HT.Paragraph()
+
+ statsTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ this_trait_type = fd.formdata.getvalue('trait_type', None)
+ this_cellid = fd.formdata.getvalue('cellid', None)
+ statsTableCell = BasicStatisticsFunctions.basicStatsTable(vals=vals, trait_type=this_trait_type, cellid=this_cellid)
+ statsTable.append(HT.TR(HT.TD(statsTableCell)))
+
+ table_container.append(statsTable)
+ table_div.append(table_container)
+ stats_container.append(table_div)
+
+ boxplot_div = HT.Div(id="statstabs-2")
+ boxplot_container = HT.Paragraph()
+ boxplot = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ boxplot_img, boxplot_link = BasicStatisticsFunctions.plotBoxPlot(vals)
+ boxplot.append(HT.TR(HT.TD(boxplot_img, HT.P(), boxplot_link, align="left")))
+ boxplot_container.append(boxplot)
+ boxplot_div.append(boxplot_container)
+ stats_container.append(boxplot_div)
+
+ barName_div = HT.Div(id="statstabs-3")
+ barName_container = HT.Paragraph()
+ barName = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ barName_img = BasicStatisticsFunctions.plotBarGraph(identification=fd.identification, RISet=fd.RISet, vals=vals, type="name")
+ barName.append(HT.TR(HT.TD(barName_img)))
+ barName_container.append(barName)
+ barName_div.append(barName_container)
+ stats_container.append(barName_div)
+
+ barRank_div = HT.Div(id="statstabs-4")
+ barRank_container = HT.Paragraph()
+ barRank = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ barRank_img = BasicStatisticsFunctions.plotBarGraph(identification=fd.identification, RISet=fd.RISet, vals=vals, type="rank")
+ barRank.append(HT.TR(HT.TD(barRank_img)))
+ barRank_container.append(barRank)
+ barRank_div.append(barRank_container)
+ stats_container.append(barRank_div)
+
+ normalplot_div = HT.Div(id="statstabs-5")
+ normalplot_container = HT.Paragraph()
+ normalplot = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ plotTitle = fd.formdata.getvalue("normalPlotTitle","")
+ normalplot_img = BasicStatisticsFunctions.plotNormalProbability(vals=vals, RISet=fd.RISet, title=plotTitle, specialStrains=specialStrains)
+ normalplot.append(HT.TR(HT.TD(normalplot_img)))
+ normalplot.append(HT.TR(HT.TD(HT.BR(),HT.BR(),"This plot evaluates whether data are \
+ normally distributed. Different symbols represent different groups.",HT.BR(),HT.BR(),
+ "More about ", HT.Href(url="http://en.wikipedia.org/wiki/Normal_probability_plot",
+ target="_blank", text="Normal Probability Plots"), " and more about interpreting these plots from the ", HT.Href(url="/glossary.html#normal_probability", target="_blank", text="glossary"))))
+ normalplot_container.append(normalplot)
+ normalplot_div.append(normalplot_container)
+ stats_container.append(normalplot_div)
+
+ stats_cell.append(stats_container)
+ stats_script.append(stats_script_text)
+
+ submitTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ stats_row.append(stats_cell)
+
+ submitTable.append(stats_row)
+ submitTable.append(stats_script)
+
+ TD_LR.append(submitTable)
+ self.dict['body'] = str(TD_LR)
+ else:
+ heading = "Basic Statistics"
+ detail = ['Fewer than %d case data were entered for %s data set. No statitical analysis has been attempted.' % (self.plotMinInformative, fd.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = "Basic Statistics"
+ detail = ['Empty data set, please check your data.']
+ self.error(heading=heading,detail=detail)
+ return \ No newline at end of file
diff --git a/web/webqtl/cmdLine/__init__.py b/web/webqtl/cmdLine/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/cmdLine/__init__.py
diff --git a/web/webqtl/cmdLine/cmdCompCorrPage.py b/web/webqtl/cmdLine/cmdCompCorrPage.py
new file mode 100755
index 00000000..f53e1bce
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdCompCorrPage.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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+
+class cmdCompCorrPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Correlation Comparison", "Correlation Comparison in progress")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py correlationComparison %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdCorrelationPage.py b/web/webqtl/cmdLine/cmdCorrelationPage.py
new file mode 100755
index 00000000..4c76dc0b
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdCorrelationPage.py
@@ -0,0 +1,53 @@
+# 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
+
+import os
+
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# Correlation Page
+#########################################
+class cmdCorrelationPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Correlation", "Correlation Computation in Progress")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py correlation %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
+
diff --git a/web/webqtl/cmdLine/cmdDirectPlotPage.py b/web/webqtl/cmdLine/cmdDirectPlotPage.py
new file mode 100755
index 00000000..21e936dc
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdDirectPlotPage.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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+
+class cmdDirectPlotPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Pair Scan", "Pair Scan Computation in Progress")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py directplot %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdHeatmapPage.py b/web/webqtl/cmdLine/cmdHeatmapPage.py
new file mode 100755
index 00000000..e96f3449
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdHeatmapPage.py
@@ -0,0 +1,52 @@
+# 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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# QTL Heatmap Page
+#########################################
+
+class cmdHeatmapPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("QTL Heatmap", "Computing QTL Heatmap")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py heatmap %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdIntervalMappingPage.py b/web/webqtl/cmdLine/cmdIntervalMappingPage.py
new file mode 100755
index 00000000..8e0a3d92
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdIntervalMappingPage.py
@@ -0,0 +1,75 @@
+# 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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+#########################################
+# Interval Mapping Page
+#########################################
+
+class cmdIntervalMappingPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ wtext = "Mapping "
+ try:
+ selectedChr = int(fd.formdata.getvalue('chromosomes')) + 1
+ if selectedChr < 1:
+ raise "ValueError"
+ if selectedChr == 21 or (selectedChr == 20 and fd.RISet != 'HXBBXH'):
+ selectedChr = 'X'
+ wtext += 'chromosome %s ' % selectedChr
+ except:
+ wtext += 'whole genome '
+
+ perm = 0
+ if fd.formdata.getvalue('permCheck'):
+ perm = 1
+ wtext += 'with %d permutation tests ' % fd.nperm
+
+ boot = 0
+ if fd.formdata.getvalue('bootCheck'):
+ boot = 1
+ if perm:
+ wtext += 'and %d bootstrap tests ' % fd.nboot
+ else:
+ wtext += 'with %d bootstrap tests ' % fd.nboot
+
+ if boot == 0 and perm == 0:
+ wtext += "without permutation or bootstrap tests"
+
+ filename = self.session("Interval Mapping", wtext)
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+ os.system("%s %swebqtlCmdLine.py interval %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+ self.redirection = url
+
diff --git a/web/webqtl/cmdLine/cmdMarkerRegressionPage.py b/web/webqtl/cmdLine/cmdMarkerRegressionPage.py
new file mode 100755
index 00000000..fb974e33
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdMarkerRegressionPage.py
@@ -0,0 +1,47 @@
+# 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 NL 2011/03/15
+#
+# Last updated by NL 2011/03/15
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# Marker RegressionPage Page
+#########################################
+
+class cmdMarkerRegressionPage(templatePage):
+
+ def __init__(self,fd):
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Genome Association Result", "Computing Genome Association Results")
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+ os.system("%s %swebqtlCmdLine.py markerRegression %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdNetworkGraphPage.py b/web/webqtl/cmdLine/cmdNetworkGraphPage.py
new file mode 100755
index 00000000..a16fcbaf
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdNetworkGraphPage.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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+
+class cmdNetworkGraphPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Network Graph", "Computing Network Graph")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename + '.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py networkGraph %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdPartialCorrelationPage.py b/web/webqtl/cmdLine/cmdPartialCorrelationPage.py
new file mode 100755
index 00000000..fb5324c6
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdPartialCorrelationPage.py
@@ -0,0 +1,50 @@
+# 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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+########################################
+# Partial Correlation Page
+########################################
+class cmdPartialCorrelationPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Partial Correlation", "Partial Correlation in Progress")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py partialCorrelation %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdQTLminerPage.py b/web/webqtl/cmdLine/cmdQTLminerPage.py
new file mode 100755
index 00000000..2197d3ce
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdQTLminerPage.py
@@ -0,0 +1,47 @@
+# 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 NL 2011/03/15
+#
+# Last updated by NL 2011/03/15
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# QTLminer Page
+#########################################
+
+class cmdQTLminerPage(templatePage):
+
+ def __init__(self,fd):
+ templatePage.__init__(self, fd)
+
+ filename = self.session("QTLminer Result", "Computing QTLminer Results")
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+ os.system("%s %swebqtlCmdLine.py QTLminer %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdShowAllPage.py b/web/webqtl/cmdLine/cmdShowAllPage.py
new file mode 100755
index 00000000..37e159e9
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdShowAllPage.py
@@ -0,0 +1,50 @@
+# 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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+
+class cmdShowAllPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Generate Report", "Generating Report. Please be Patient")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py genreport %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
+
diff --git a/web/webqtl/cmdLine/cmdShowAllPage2.py b/web/webqtl/cmdLine/cmdShowAllPage2.py
new file mode 100755
index 00000000..a1ac172f
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdShowAllPage2.py
@@ -0,0 +1,55 @@
+# 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
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+
+#########################################
+# Generate Report Page
+#########################################
+
+class cmdShowAllPage2(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Generate Report v2", "Generating Report v2. Please be Patient")
+
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+
+ os.system("%s %swebqtlCmdLine.py genreport2 %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+
+ self.redirection = url
+
+
diff --git a/web/webqtl/cmdLine/cmdSnpBrowserResultPage.py b/web/webqtl/cmdLine/cmdSnpBrowserResultPage.py
new file mode 100755
index 00000000..54cb1181
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdSnpBrowserResultPage.py
@@ -0,0 +1,47 @@
+# 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 NL 2011/03/15
+#
+# Last updated by NL 2011/03/15
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# SnpBrowser Page
+#########################################
+
+class cmdSnpBrowserResultPage(templatePage):
+
+ def __init__(self,fd):
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Variant Browser Result", "Computing Variant Browser Results")
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+ os.system("%s %swebqtlCmdLine.py snpbrowser %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/cmdTissueCorrelationResultPage.py b/web/webqtl/cmdLine/cmdTissueCorrelationResultPage.py
new file mode 100755
index 00000000..1f28953c
--- /dev/null
+++ b/web/webqtl/cmdLine/cmdTissueCorrelationResultPage.py
@@ -0,0 +1,47 @@
+# 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 NL 2011/03/15
+#
+# Last updated by NL 2011/03/15
+
+import os
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# SnpBrowser Page
+#########################################
+
+class cmdTissueCorrelationResultPage(templatePage):
+
+ def __init__(self,fd):
+ templatePage.__init__(self, fd)
+
+ filename = self.session("Tissue Correlation Result Page", "Computing Tissue Correlation Result")
+ webqtlUtil.dump_session(fd, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+ url = webqtlConfig.REFRESHDIR % (webqtlConfig.CGIDIR, self.filename)
+ os.system("%s %swebqtlCmdLine.py tissueCorrelation %s >/dev/null 2>&1 &" % (webqtlConfig.PythonPath, webqtlConfig.CMDLINEDIR, filename))
+ self.redirection = url
diff --git a/web/webqtl/cmdLine/procPage.py b/web/webqtl/cmdLine/procPage.py
new file mode 100755
index 00000000..03ce242c
--- /dev/null
+++ b/web/webqtl/cmdLine/procPage.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
+
+#--Only imported by WebQTL.py -KA
+
+#Xiaodong changed the dependancy structure
+
+import os
+
+from base import webqtlConfig
+
+
+class procPage:
+ def __init__(self, myID, req):
+ try:
+ fp = open(os.path.join(webqtlConfig.TMPDIR, myID + '.html'), 'rb')
+ except:
+ fp = open(os.path.join(webqtlConfig.ChangableHtmlPath, 'missing.html'), 'rb')
+
+ content = fp.read()
+ fp.close()
+ req.write(content)
+
diff --git a/web/webqtl/cmdLine/webqtlCmdLine.py b/web/webqtl/cmdLine/webqtlCmdLine.py
new file mode 100755
index 00000000..ebc10e1c
--- /dev/null
+++ b/web/webqtl/cmdLine/webqtlCmdLine.py
@@ -0,0 +1,176 @@
+# 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
+
+
+
+########################################################
+#XZ, Aug 10, 2010
+#This part is the temporary solution to make python be able to find other subpackages.
+#We can't set global environment because there are many branches on the development machine.
+
+import sys, os
+
+current_file_name = __file__
+pathname = os.path.dirname( current_file_name )
+abs_path = os.path.abspath(pathname)
+sys.path.insert(0, abs_path + '/..')
+
+########################################################
+
+
+
+import traceback
+import string
+import cPickle
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+if __name__ == "__main__":
+ try:
+ if len(sys.argv) > 2:
+ getID = string.lower(sys.argv[1])
+ else:
+ raise ValueError
+
+ cmdtype = sys.argv[1]
+ sessionfile = sys.argv[2]
+
+ fd = None
+
+ fp = open(os.path.join(webqtlConfig.TMPDIR, sessionfile + '.session'), 'rb')
+ fd = cPickle.load(fp)
+ fp.close()
+
+ if cmdtype == "heatmap":
+ from heatmap import heatmapPage
+ reload(heatmapPage)
+ page = heatmapPage.heatmapPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "directplot":
+ from pairScan import DirectPlotPage
+ reload(DirectPlotPage)
+ page = DirectPlotPage.DirectPlotPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "networkGraph":
+ from networkGraph import networkGraphPage
+ reload(networkGraphPage)
+ page = networkGraphPage.networkGraphPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "interval":
+ from intervalMapping import IntervalMappingPage
+ reload(IntervalMappingPage)
+ page = IntervalMappingPage.IntervalMappingPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "correlation":
+ from correlation import CorrelationPage
+ reload (CorrelationPage)
+ page = CorrelationPage.CorrelationPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "partialCorrelation":
+ from correlation import PartialCorrDBPage
+ reload(PartialCorrDBPage)
+ page = PartialCorrDBPage.PartialCorrDBPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "correlationComparison":
+ from compareCorrelates import multitrait
+ reload(multitrait)
+ page = multitrait.compCorrPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "genreport": # Generate Report Page
+ spacer = '</TR></Table><Table width=900 cellSpacing=0 cellPadding=5><TR>'
+
+ from basicStatistics import BasicStatisticsPage
+ reload(BasicStatisticsPage)
+ page1 = BasicStatisticsPage.BasicStatisticsPage(fd)
+
+ if not fd.formdata.getvalue('bsCheck'):
+ page1.dict['body'] = ""
+
+ if fd.formdata.getvalue('tcCheck'):
+ from correlation import CorrelationPage
+ reload(CorrelationPage)
+ page2 = CorrelationPage.CorrelationPage(fd)
+ page1.dict['body'] += spacer + str(page2.dict['body'])
+ page1.dict['js1'] += page2.dict['js1']
+
+ if fd.formdata.getvalue('imCheck'):
+ from intervalMapping import IntervalMappingPage
+ reload(IntervalMappingPage)
+ page3 = IntervalMappingPage.IntervalMappingPage(fd)
+ page1.dict['body'] += spacer + str(page3.dict['body'])
+
+ if fd.formdata.getvalue('mrCheck'):
+ from markerRegression import MarkerRegressionPage
+ reload(MarkerRegressionPage)
+ page4 = MarkerRegressionPage.MarkerRegressionPage(fd)
+ page1.dict['body'] += spacer + str(page4.dict['body'])
+
+ if fd.formdata.getvalue('psCheck'):
+ from pairScan import DirectPlotPage
+ reload(DirectPlotPage)
+ page5 = DirectPlotPage.DirectPlotPage(fd)
+ page1.dict['body'] += spacer + str(page5.dict['body'])
+
+ page1.writeFile(sessionfile+'.html')
+
+ elif cmdtype == "genreport2": # Generate Report Page v2
+ spacer = '</TR></Table><Table width=900 cellSpacing=0 cellPadding=5><TR>'
+
+ from basicStatistics import BasicStatisticsPage_alpha
+ reload(BasicStatisticsPage_alpha)
+ page1 = BasicStatisticsPage_alpha.BasicStatisticsPage_alpha(fd)
+ page1.writeFile(sessionfile+'.html')
+ elif cmdtype == "snpbrowser":
+ from snpBrowser import snpBrowserPage
+ reload(snpBrowserPage)
+ page = snpBrowserPage.snpBrowserPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "QTLminer":
+ from qtlminer import QTLminer
+ reload(QTLminer)
+ page = QTLminer.QTLminer(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "tissueCorrelation":
+ from correlationMatrix import TissueCorrelationPage
+ reload(TissueCorrelationPage)
+ page = TissueCorrelationPage.TissueCorrelationPage(fd)
+ page.writeFile(sessionfile+'.html')
+ elif cmdtype == "markerRegression":
+ from markerRegression import MarkerRegressionPage
+ reload(MarkerRegressionPage)
+ page = MarkerRegressionPage.MarkerRegressionPage(fd)
+ page.writeFile(sessionfile+'.html')
+ else:
+ raise ValueError
+ except:
+ fp = open(os.path.join(webqtlConfig.TMPDIR, sessionfile +'.html'), 'wb')
+ fp.write('\n\n<pre>')
+ traceback.print_exc(file=fp)
+ fp.write('\n</pre>')
+ fp.close()
diff --git a/web/webqtl/collection/AddToSelectionPage.py b/web/webqtl/collection/AddToSelectionPage.py
new file mode 100644
index 00000000..2a99e8c1
--- /dev/null
+++ b/web/webqtl/collection/AddToSelectionPage.py
@@ -0,0 +1,695 @@
+#AddToSelectionPage.py
+
+import string
+from htmlgen import HTMLgen2 as HT
+import os
+import cPickle
+import reaper
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+from utility import webqtlUtil
+from showTrait import ShowProbeInfoPage
+# NL, 07/27/2010: add 'import webqtlDatabaseFunction' for retrieveSpecies function
+from dbFunction import webqtlDatabaseFunction
+from base.webqtlTrait import webqtlTrait
+
+
+#########################################
+# Add to Selection Page
+#########################################
+class AddToSelectionPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if not fd.genotype:
+ fd.readGenotype()
+
+ self.searchResult = fd.formdata.getvalue('searchResult', [])
+ if type("1") == type(self.searchResult):
+ self.searchResult = [self.searchResult]
+ if fd.formdata.getvalue('fromDataEditingPage'):
+ searchResult2 = fd.formdata.getvalue('fullname')
+ if searchResult2:
+ self.searchResult.append(searchResult2)
+
+ if self.searchResult:
+ pass
+ else:
+ templatePage.__init__(self, fd)
+ heading = 'Add Collections'
+ detail = ['You need to select at least one trait to add to your selection.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ if self.genSelection(fd=fd):
+ self.writeHTML(fd)
+
+
+
+ def genSelection(self, fd=None, checkPreSelection = 1):
+ collectionName = '%s_Select' % fd.RISet
+
+ if checkPreSelection:
+ try:
+ preSelection = fd.input_session_data[collectionName]
+ preSelection = list(string.split(preSelection,','))
+ except:
+ preSelection = []
+ else:
+ preSelection = []
+
+ if preSelection:
+ for item in preSelection:
+ if item not in self.searchResult:
+ self.searchResult.append(item)
+
+ self.searchResult = map(self.transfer2NewName, self.searchResult)
+
+ for item in self.searchResult:
+ if not item:
+ self.searchResult.remove(item)
+
+ if len(self.searchResult) > 3000:
+ heading = 'Add Collections'
+ detail = ['You are adding over 3000 traits to selections, please reduce your number of traits.']
+ self.error(heading=heading,detail=detail)
+ return 0
+
+ searchResult2 = []
+ self.theseTraits = []
+ for item in self.searchResult:
+ try:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo(QTL=1)
+ self.theseTraits.append(thisTrait)
+ searchResult2.append(item)
+ except:
+ pass
+
+ allTraitStr = string.join(searchResult2,',')
+
+ self.session_data_changed[collectionName] = allTraitStr
+
+ return 1
+
+
+
+ def writeHTML(self,fd):
+ TD_LR = HT.TD(height=100,width="100%",bgColor='#eeeeee',valign="top")
+ pageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%",border=0, align="Left")
+ tbl = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0, align="Left")
+ seq = 1
+ SelectionHeading = HT.Paragraph('%s Trait Collection' % fd.RISet, Class="title")
+
+ mintmap = HT.Href(url="#redirect", onClick="if(validateTraitNumber()){databaseFunc(document.getElementsByName('showDatabase')[0], 'showIntMap');}")
+ mintmap_img = HT.Image("/images/multiple_interval_mapping1_final.jpg", name='mintmap', alt="Multiple Interval Mapping", title="Multiple Interval Mapping", style="border:none;")
+ mintmap.append(mintmap_img)
+ mcorr = HT.Href(url="#redirect", onClick="if(validateTraitNumber()){databaseFunc(document.getElementsByName('showDatabase')[0], 'compCorr');}")
+ mcorr_img = HT.Image("/images/compare_correlates2_final.jpg", name='comparecorr', alt="Compare Correlates", title="Compare Correlates", style="border:none;")
+ mcorr.append(mcorr_img)
+ cormatrix = HT.Href(url="#redirect", onClick="if(validateTraitNumber()){databaseFunc(document.getElementsByName('showDatabase')[0], 'corMatrix');}")
+ cormatrix_img = HT.Image("/images/correlation_matrix1_final.jpg", name='corrmatrix', alt="Correlation Matrix and PCA", title="Correlation Matrix and PCA", style="border:none;")
+ cormatrix.append(cormatrix_img)
+ networkGraph = HT.Href(url="#redirect", onClick="if(validateTraitNumber()){databaseFunc(document.getElementsByName('showDatabase')[0], 'networkGraph');}")
+ networkGraph_img = HT.Image("/images/network_graph1_final.jpg", name='networkgraph', alt="Network Graphs", title="Network Graphs", style="border:none;")
+ networkGraph.append(networkGraph_img)
+ heatmap = HT.Href(url="#redirect", onClick="if(validateTraitNumber()){databaseFunc(document.getElementsByName('showDatabase')[0], 'heatmap');}")
+ heatmap_img = HT.Image("/images/heatmap2_final.jpg", name='heatmap', alt="QTL Heat Map and Clustering", title="QTL Heatmap and Clustering", style="border:none;")
+ heatmap.append(heatmap_img)
+ partialCorr = HT.Href(url="#redirect", onClick="if(validateTraitNumber()){databaseFunc(document.getElementsByName('showDatabase')[0], 'partialCorrInput');}")
+ partialCorr_img = HT.Image("/images/partial_correlation_final.jpg", name='partialCorr', alt="Partial Correlation", title="Partial Correlation", style="border:none;")
+ partialCorr.append(partialCorr_img)
+
+ BN = HT.Href(url="#redirect", onClick="if(validateTraitNumber()){databaseFunc(document.getElementsByName('showDatabase')[0], 'BNInput');}")
+ networkGraph_img = HT.Image("/images/network_graph1_final.jpg", name='BayesianNetwork', alt="Bayesian Network", title="Bayesian Network", style="border:none;")
+ BN.append(networkGraph_img)
+
+ removeselect = HT.Href(url="#redirect", onClick="addRmvSelection('%s', document.getElementsByName('showDatabase')[0], 'removeSelection');" % fd.RISet)
+ removeselect_img = HT.Image("/images/remove_selection1_final.jpg", name="removeselect", alt="Remove Selection", title="Remove Selection", style="border:none;")
+ removeselect.append(removeselect_img)
+ selectall = HT.Href(url="#redirect", onClick="$('.checkallbox').attr('checked', true);")
+ selectall_img = HT.Image("/images/select_all2_final.jpg", name="selectall", alt="Select All", title="Select All", style="border:none;")
+ selectall.append(selectall_img)
+ reset = HT.Href(url="#redirect", onClick="$('.checkallbox').attr('checked', false);")
+ reset_img = HT.Image("/images/select_none2_final.jpg", alt="Select None", title="Select None", style="border:none;")
+ reset.append(reset_img)
+ exportSelect = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('showDatabase')[0], 'exportSelectionDetailInfo');")
+ exportSelect_img = HT.Image("/images/export2_final.jpg", name="exportSelection", alt="Export Selection", title="Export Selection", style="border:none;")
+ exportSelect.append(exportSelect_img)
+ selectinvert = HT.Href(url="#redirect", onClick = "checkInvert(document.getElementsByName('showDatabase')[0]);")
+ selectinvert_img = HT.Image("/images/invert_selection2_final.jpg", name="selectinvert", alt="Invert Selection", title="Invert Selection", style="border:none;")
+ selectinvert.append(selectinvert_img)
+
+ chrMenu = HT.Input(type='hidden',name='chromosomes',value='all')
+
+ importFile = HT.Input(type='file', name='importfile', size=15)
+ importButton = HT.Input(type='button',name='importSelection',value='Load Collection', onClick="addRmvSelection('%s', this.form, 'importSelect');" % fd.RISet,Class="button")
+ exportButton = HT.Input(type='button' ,name='exportSelection',value='Save Collection', onClick="databaseFunc(this.form,'exportSelect');", Class="button")
+ importMenu = HT.Select(name='importmethod')
+ importMenu.append(('append','append'))
+ importMenu.append(('replace','replace'))
+
+ ODE = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('showDatabase')[0], 'ODE');")
+ ODE_img = HT.Image("/images/ODE_logo_final.jpg", name="ode", alt="ODE", title="ODE", style="border:none")
+ ODE.append(ODE_img)
+
+ GCATButton = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('showDatabase')[0], 'GCAT');")
+ GCATButton_img = HT.Image("/images/GCAT_logo_final.jpg", name="GCAT", alt="GCAT", title="GCAT", style="border:none")
+ GCATButton.append(GCATButton_img)
+
+ GeneSet = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('showDatabase')[0],'GOTree');")
+ GeneSet_img = HT.Image("/images/webgestalt_icon_final.jpg", name="webgestalt", alt="Gene Set Analysis Toolkit", title="Gene Set Analysis Toolkit", style="border:none")
+ GeneSet.append(GeneSet_img)
+
+ #need to be refined
+ if fd.genotype.Mbmap:
+ scale = HT.Input(name="scale", value="physic", type="hidden")
+ else:
+ scale = ""
+
+ formMain = HT.Form(cgi=os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+
+ #XZ, July 22, 2011: I add parameters for interval mapping
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':'_','CellID':'_','RISet':fd.RISet,'incparentsf1':'ON','showHideOptions':'more','scale':'physic','additiveCheck':'ON', 'showSNP':'ON', 'showGenes':'ON', 'intervalAnalystCheck':'ON','bootCheck':None, 'permCheck':None, 'applyVarianceSE':None}
+ for key in hddn.keys():
+ formMain.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ if not self.searchResult:
+ SelectionHeading = HT.Paragraph('%s Trait Collection' % fd.RISet, Class="title")
+ formMain.append(HT.HR(width="70%", color = "blue"),importFile, ' ', importMenu, ' ', importButton)
+ TD_LR.append(SelectionHeading,HT.Blockquote('No trait has been added to this selection.'), HT.Center(HT.BR(), HT.BR(), HT.BR(), HT.BR(), formMain))
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = "%s Trait Collection" % fd.RISet
+ return
+
+ #########################################
+ # Creating table object for AJAX table #
+ #########################################
+ tblobj = {}
+ mainfmName = 'showDatabase'
+ # NL, 07/27/2010. retrieveSpecies function has been moved from webqtlTrait.py to webqtlDatabaseFunction.py;
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+ if species == 'human':
+ chrMenu = scale = mintmap = heatmap = ""
+
+ tblobj['header'] = self.getCollectionTableHeader()
+
+ sortby = self.getSortByValue()
+
+ thisRISet = fd.RISet
+ tblobj['body'] = self.getCollectionTableBody(RISet=thisRISet, traitList=self.theseTraits, formName=mainfmName, species=species)
+
+ filename= webqtlUtil.genRandStr("Search_")
+
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), Id="sortable")
+
+
+ containerTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0,align="Left")
+ postContainerTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0,align="Left")
+
+ optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="400", border=0, align="Left")
+ optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(removeselect), HT.TD(exportSelect)))
+ optionsTable.append(HT.TR(HT.TD("&nbsp;"*1,"Select"), HT.TD("Deselect"), HT.TD("&nbsp;"*1,"Invert"), HT.TD("&nbsp;"*1,"Remove"), HT.TD("&nbsp;"*1,"Export")))
+ postContainerTable.append(HT.TR(HT.TD(optionsTable)))
+ containerTable.append(HT.TR(HT.TD(optionsTable)))
+
+ functionTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="480",border=0, align="Left")
+ functionRow = HT.TR(HT.TD(networkGraph, width="16.7%"), HT.TD(cormatrix, width="16.7%"), HT.TD(partialCorr, width="16.7%"), HT.TD(mcorr, width="16.7%"), HT.TD(mintmap, width="16.7%"), HT.TD(heatmap))
+ if species == "human":
+ labelRow = HT.TR(HT.TD("&nbsp;"*2,HT.Text("Graph")), HT.TD("&nbsp;"*2,HT.Text("Matrix")), HT.TD("&nbsp;"*2, HT.Text("Partial")), HT.TD(HT.Text("Compare")))
+ else:
+ labelRow = HT.TR(HT.TD("&nbsp;"*2,HT.Text("Graph")), HT.TD("&nbsp;"*2,HT.Text("Matrix")), HT.TD("&nbsp;"*2, HT.Text("Partial")), HT.TD(HT.Text("Compare")), HT.TD(HT.Text("QTL Map")), HT.TD(HT.Text(text="Heat Map")))
+ functionTable.append(functionRow, labelRow)
+ postContainerTable.append(HT.TR(HT.TD(functionTable)))
+ containerTable.append(HT.TR(HT.TD(functionTable)))
+
+ moreOptions = HT.Input(type='button',name='options',value='More Options', onClick="",Class="toggle")
+ fewerOptions = HT.Input(type='button',name='options',value='Fewer Options', onClick="",Class="toggle")
+
+
+
+ if (fd.formdata.getvalue('showHideOptions') == 'less'):
+ postContainerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
+ else:
+ postContainerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
+
+
+ LinkOutTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="320",border=0, align="Left")
+ LinkOutRow = HT.TR(HT.TD(GeneSet, width="33%"), HT.TD(GCATButton, width="33%"), HT.TD(ODE, width="33%"), style="display:none;", Class="extra_options")
+ LinkOutLabels = HT.TR(HT.TD(HT.Text("Gene Set")), HT.TD("&nbsp;"*2, HT.Text("GCAT")), HT.TD("&nbsp;"*3, HT.Text("ODE")), style="display:none;", Class="extra_options")
+ LinkOutTable.append(LinkOutRow,LinkOutLabels)
+ postContainerTable.append(HT.TR(HT.TD("&nbsp;"), height=10), HT.TR(HT.TD(LinkOutTable)))
+ containerTable.append(HT.TR(HT.TD("&nbsp;"), height=10), HT.TR(HT.TD(LinkOutTable)))
+
+ pageTable.append(HT.TR(HT.TD(containerTable)))
+ chrMenu = scale = ""
+
+ pageTable.append(HT.TR(HT.TD(div)))
+ pageTable.append(HT.TR(HT.TD("&nbsp;")))
+ if len(self.theseTraits) > 20:
+ pageTable.append(HT.TR(HT.TD(postContainerTable)))
+ pageTable.append(HT.TR(HT.TD(importFile, ' ', importMenu, ' ', importButton, '&nbsp;'*10, exportButton)))
+ #Took out scaleMenu since it will be replaced with a jquery popup in the future - Zach 5/10/2010
+ formMain.append(chrMenu,scale,pageTable)
+
+ #Updated by NL, deleted showHideJS, moved jquery to jqueryFunction.js
+ self.dict['js1'] = ''
+ TD_LR.append(SelectionHeading,formMain)
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['js2'] = 'onLoad="pageOffset()"'
+ self.dict['layer'] = self.generateWarningLayer()
+ self.dict['title'] = "%s Trait Collection" % thisRISet
+
+ def transfer2NewName(self, str):
+ "this is temporary"
+ if str.find("::") < 0:
+ return str.replace(":", "::")
+ else:
+ return str
+
+ def generateWarningLayer(self):
+
+ layerString = """
+ <!-- BEGIN FLOATING LAYER CODE //-->
+ <div id="warningLayer" style="padding:3px; border: 1px solid #222;
+ background-color: #fff; position:absolute;width:250px;left:100;top:100;visibility:hidden">
+ <table border="0" width="250" class="cbrb" cellspacing="0" cellpadding="5">
+ <tr>
+ <td width="100%">
+ <table border="0" width="100%" cellspacing="0" cellpadding="0" height="36">
+ <tr>
+ <td class="cbrb cw ff15 fwb" align="Center" width="100%" style="padding:4px">
+ Sort Table
+ </td>
+ </tr>
+ <tr>
+ <td width="100%" bgcolor="#eeeeee" align="Center" style="padding:4px">
+ <!-- PLACE YOUR CONTENT HERE //-->
+ Resorting this table <br>
+ <!-- END OF CONTENT AREA //-->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <!-- END FLOATING LAYER CODE //-->
+
+ """
+
+ return layerString
+
+ def getCollectionTableHeader(self):
+
+ tblobj_header = []
+
+ className = "fs13 fwb ffl b1 cw cbrb"
+
+ tblobj_header = [[THCell(HT.TD(' ', Class=className, nowrap="on"), sort=0),
+ THCell(HT.TD('Dataset', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="dataset", idx=1),
+ THCell(HT.TD('Trait', HT.BR(), 'ID', HT.BR(), valign="top", Class=className, nowrap="on"), text="name", idx=2),
+ THCell(HT.TD('Symbol', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="symbol", idx=3),
+ THCell(HT.TD('Description', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="desc", idx=4),
+ THCell(HT.TD('Location', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="location", idx=5),
+ THCell(HT.TD('Mean', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="mean", idx=6),
+ THCell(HT.TD('N', HT.BR(), 'Cases', HT.BR(), valign="top", Class=className, nowrap="on"), text="samples", idx=7),
+ THCell(HT.TD('Max LRS', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="lrs", idx=8),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb', HT.BR(), valign="top", Class=className, nowrap="on"), text="lrs_location", idx=9)]]
+
+ return tblobj_header
+
+ def getCollectionTableBody(self, RISet=None, traitList=None, formName=None, species=''):
+
+ tblobj_body = []
+
+ className = "fs12 fwn b1 c222"
+
+ for thisTrait in traitList:
+ tr = []
+
+ if not thisTrait.haveinfo:
+ thisTrait.retrieveInfo(QTL=1)
+
+ if thisTrait.riset != RISet:
+ continue
+
+ trId = str(thisTrait)
+
+ #XZ: check box column
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkallbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class=className)))
+
+ #XZ: Dataset column
+ tr.append(TDCell(HT.TD(thisTrait.db.name, Class="fs12 fwn b1 c222"), thisTrait.db.name, thisTrait.db.name.upper()))
+
+ #XZ: Trait ID column
+ if thisTrait.cellid:
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.cellid,url="javascript:showDatabase3('%s','%s','%s','%s')" % (formName, thisTrait.db.name, thisTrait.name, thisTrait.cellid), Class="fs12 fwn"), nowrap="yes",align="left", Class=className),str(thisTrait.cellid), thisTrait.cellid))
+ else:
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.getGivenName(),url="javascript:showDatabase3('%s','%s','%s','')" % (formName, thisTrait.db.name, thisTrait.name), Class="fs12 fwn"), nowrap="yes",align="left", Class=className),str(thisTrait.name), thisTrait.name))
+
+ #XZ: Symbol column and Description column
+ if (thisTrait.db.type == "Publish"):
+ AbbreviationString = "--"
+ if (thisTrait.post_publication_abbreviation != None):
+ AbbreviationString = thisTrait.post_publication_abbreviation
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ if thisTrait.pre_publication_abbreviation:
+ AbbreviationString = thisTrait.pre_publication_abbreviation
+ else:
+ AbbreviationString = "--"
+ PhenotypeString = thisTrait.pre_publication_description
+
+ if AbbreviationString == "--":
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+ else:
+ tr.append(TDCell(HT.TD(AbbreviationString, Class=className), AbbreviationString, AbbreviationString.upper()))
+
+ tr.append(TDCell(HT.TD(PhenotypeString, Class=className), PhenotypeString, PhenotypeString.upper()))
+
+
+ elif (thisTrait.db.type == "ProbeSet" or thisTrait.db.type == "Temp"):
+ description_string = str(thisTrait.description).strip()
+ if (thisTrait.db.type == "ProbeSet"):
+ if (thisTrait.symbol != None):
+ if thisTrait.geneid:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % thisTrait.geneid, Class="font_black fs12 fwn")
+ else:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % thisTrait.symbol, Class="font_black fs12 fwn")
+ tr.append(TDCell(HT.TD(symbolurl, align="left", Class="fs12 fwn b1 c222 fsI"), thisTrait.symbol, thisTrait.symbol))
+ else:
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+ target_string = str(thisTrait.probe_target_description).strip()
+
+ description_display = ''
+
+ if len(description_string) > 1 and description_string != 'None':
+ description_display = description_string
+ else:
+ description_display = thisTrait.symbol
+
+ if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ description_display = description_display + '; ' + target_string.strip()
+
+ description_string = description_display
+ else:
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+ tr.append(TDCell(HT.TD(description_string, Class=className), description_string, description_string))
+ else:
+ if (thisTrait.name != None):
+ tr.append(TDCell(HT.TD(thisTrait.name, Class="fs12 fwn b1 c222"), thisTrait.name, thisTrait.name))
+ else:
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+
+ #XZ: Location column
+ if (thisTrait.db.type == "Publish"):
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+ else:
+ if thisTrait.db.type == "ProbeSet" and thisTrait.cellid:
+ EnsemblProbeSetID = thisTrait.name
+ if '_at' in thisTrait.name:
+ EnsemblProbeSetID = thisTrait.name[0:thisTrait.name.index('_at')+3]
+
+ #These tables (Ensembl) were created by Xusheng Wang in 2010 and are mm9 (so they'll need to be changed at some point to be mm10.
+ self.cursor.execute('''
+ SELECT EnsemblProbeLocation.*
+ FROM EnsemblProbeLocation, EnsemblProbe, EnsemblChip, GeneChipEnsemblXRef, ProbeFreeze, ProbeSetFreeze
+ WHERE EnsemblProbeLocation.ProbeId=EnsemblProbe.Id and EnsemblProbe.ChipId=GeneChipEnsemblXRef.EnsemblChipId and
+ GeneChipEnsemblXRef.GeneChipId=ProbeFreeze.ChipId and EnsemblProbe.Name=%s and EnsemblProbe.ProbeSet=%s and
+ ProbeSetFreeze.Id=%s and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id group by Chr, Start, End'''
+ ,(thisTrait.cellid, EnsemblProbeSetID, thisTrait.db.id))
+ LocationFields = self.cursor.fetchall()
+
+ Chr=''
+ Mb=''
+ Start=''
+ End=''
+ if (len(LocationFields)>=1):
+ Chr,Start,End,Strand,MisMatch,ProbeId = map(self.nullRecord,LocationFields[0])
+ Start /= 1000000.0
+ End /= 1000000.0
+ Mb = Start
+ if (len(LocationFields)>1):
+ self.cursor.execute('''
+ SELECT ProbeSet.Chr, ProbeSet.Mb FROM ProbeSet, ProbeFreeze, ProbeSetFreeze
+ WHERE ProbeSet.ChipId=ProbeFreeze.ChipId and ProbeSet.Name=%s and ProbeSetFreeze.Id=%s and
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id'''
+ ,(thisTrait.name, thisTrait.db.id))
+ ProbeSetChr, ProbeSetMb = map(self.nullRecord,self.cursor.fetchall()[0])
+
+ self.cursor.execute('''
+ SELECT EnsemblProbeLocation.*, ABS(EnsemblProbeLocation.Start/1000000-%s) as Mb
+ FROM EnsemblProbeLocation, EnsemblProbe, EnsemblChip, GeneChipEnsemblXRef, ProbeFreeze
+ WHERE EnsemblProbeLocation.ProbeId=EnsemblProbe.Id and EnsemblProbe.ChipId=GeneChipEnsemblXRef.EnsemblChipId and
+ GeneChipEnsemblXRef.GeneChipId=ProbeFreeze.ChipId and EnsemblProbe.Name=%s and EnsemblProbe.ProbeSet=%s and
+ EnsemblProbeLocation.Chr=%s and ProbeSetFreezeId=%s and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id order by Mb limit 1'''
+ ,(ProbeSetMb, thisTrait.cellid, EnsemblProbeSetID, ProbeSetChr, thisTrait.db.id))
+ NewLocationFields = self.cursor.fetchall()
+ if (len(NewLocationFields)>0):
+ Chr,Start,End,Strand,MisMatch,ProbeId,Mb = map(self.nullRecord,NewLocationFields[0])
+ Start /= 1000000.0
+ End /= 1000000.0
+ Mb = Start
+
+ #ZS: trait_location_value is used for sorting
+ trait_location_repr = "--"
+ trait_location_value = 1000000
+
+ if Chr and Mb:
+ try:
+ trait_location_value = int(Chr)*1000 + Mb
+ except:
+ if Chr.upper() == "X":
+ trait_location_value = 20*1000 + Mb
+ else:
+ trait_location_value = ord(str(Chr).upper()[0])*1000 + Mb
+
+ trait_location_repr = "Chr%s: %.6f" % (Chr, float(Mb) )
+
+ tr.append(TDCell(HT.TD(trait_location_repr, nowrap='ON', Class=className), trait_location_repr, trait_location_value))
+
+ else:
+
+ #ZS: trait_location_value is used for sorting
+ trait_location_repr = "--"
+ trait_location_value = 1000000
+
+ if hasattr(thisTrait, 'chr') and hasattr(thisTrait, 'mb') and thisTrait.chr and thisTrait.mb:
+ try:
+ trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if thisTrait.chr.upper() == "X":
+ trait_location_value = 20*1000 + thisTrait.mb
+ else:
+ trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ trait_location_repr = "Chr%s: %.6f" % (thisTrait.chr, float(thisTrait.mb) )
+
+ tr.append(TDCell(HT.TD(trait_location_repr, nowrap='ON', Class=className), trait_location_repr, trait_location_value))
+
+ #XZ: Mean column
+ if (thisTrait.db.type == "ProbeSet"):
+ if thisTrait.cellid:
+ mean = -10000.0
+ try:
+ thisTrait.retrieveData()
+ mean, median, var, stdev, sem, N = reaper.anova(thisTrait.exportInformative()[1])
+ except:
+ pass
+ repr = '%2.3f' % mean
+ mean = '%2.2f' % mean
+ tr.append(TDCell(HT.TD(repr, Class=className, align='right', nowrap='ON'),repr, mean))
+ else:
+ self.cursor.execute("""
+ select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %d and
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId and
+ ProbeSet.Name = '%s'
+ """ % (thisTrait.db.id, thisTrait.name))
+ result = self.cursor.fetchone()
+ if result:
+ if result[0]:
+ mean = result[0]
+ else:
+ mean=0
+ else:
+ mean = 0
+
+ #XZ, 06/05/2009: It is neccessary to turn on nowrap
+ repr = "%2.3f" % mean
+ tr.append(TDCell(HT.TD(repr, Class=className, align='right', nowrap='ON'),repr, mean))
+
+ elif (thisTrait.db.type == "Publish"):
+ self.cursor.execute("""
+ select count(PublishData.value), sum(PublishData.value) from PublishData, PublishXRef, PublishFreeze
+ where PublishData.Id = PublishXRef.DataId and
+ PublishXRef.Id = %s and
+ PublishXRef.InbredSetId = PublishFreeze.InbredSetId and
+ PublishFreeze.Id = %d
+ """ % (thisTrait.name, thisTrait.db.id))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ mean = result[1]/result[0]
+ else:
+ mean = 0
+ else:
+ mean = 0
+
+ repr = "%2.3f" % mean
+ tr.append(TDCell(HT.TD(repr, Class=className, align='right', nowrap='ON'),repr, mean))
+ else:
+ tr.append(TDCell(HT.TD("--", Class=className, align='left', nowrap='ON'),"--", 0))
+
+ #Number of cases
+ n_cases_value = 0
+ n_cases_repr = "--"
+ if (thisTrait.db.type == "Publish"):
+ self.cursor.execute("""
+ select count(PublishData.value) from PublishData, PublishXRef, PublishFreeze
+ where PublishData.Id = PublishXRef.DataId and
+ PublishXRef.Id = %s and
+ PublishXRef.InbredSetId = PublishFreeze.InbredSetId and
+ PublishFreeze.Id = %d
+ """ % (thisTrait.name, thisTrait.db.id))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0]:
+ n_cases_value = result[0]
+ n_cases_repr = result[0]
+
+ if (n_cases_value == "--"):
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='right', nowrap="on"), n_cases_repr, n_cases_value))
+
+ elif (thisTrait.db.type == "ProbeSet"):
+ self.cursor.execute("""
+ select count(ProbeSetData.value) from ProbeSet, ProbeSetXRef, ProbeSetData, ProbeSetFreeze
+ where ProbeSet.Name='%s' and
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id and
+ ProbeSetXRef.DataId = ProbeSetData.Id and
+ ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id and
+ ProbeSetFreeze.Name = '%s'
+ """ % (thisTrait.name, thisTrait.db.name))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0]:
+ n_cases_value = result[0]
+ n_cases_repr = result[0]
+ if (n_cases_value == "--"):
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='right', nowrap="on"), n_cases_repr, n_cases_value))
+
+ elif (thisTrait.db.type == "Geno"):
+ self.cursor.execute("""
+ select count(GenoData.value) from GenoData, GenoXRef, GenoFreeze, Geno, Strain
+ where Geno.SpeciesId = %s and Geno.Name='%s' and
+ GenoXRef.GenoId = Geno.Id and
+ GenoXRef.DataId = GenoData.Id and
+ GenoXRef.GenoFreezeId = GenoFreeze.Id and
+ GenoData.StrainId = Strain.Id and
+ GenoFreeze.Name = '%s'
+ """ % (webqtlDatabaseFunction.retrieveSpeciesId(self.cursor, thisTrait.db.riset), thisTrait.name, thisTrait.db.name))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0]:
+ n_cases_value = result[0]
+ n_cases_repr = result[0]
+ if (n_cases_value == "--"):
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='right', nowrap="on"), n_cases_repr, n_cases_value))
+
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+
+ #XZ: Max LRS column and Max LRS Location column
+ if (thisTrait.db.type != "Geno"):
+ #LRS and its location
+ LRS_score_repr = '--'
+ LRS_score_value = 0
+ LRS_location_repr = '--'
+ LRS_location_value = 1000000
+ LRS_flag = 1
+
+ #Max LRS and its Locus location
+ if hasattr(thisTrait, 'lrs') and hasattr(thisTrait, 'locus') and thisTrait.lrs and thisTrait.locus:
+ self.cursor.execute("""
+ select Geno.Chr, Geno.Mb from Geno, Species
+ where Species.Name = '%s' and
+ Geno.Name = '%s' and
+ Geno.SpeciesId = Species.Id
+ """ % (species, thisTrait.locus))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ LRS_Chr = result[0]
+ LRS_Mb = result[1]
+
+ #XZ: LRS_location_value is used for sorting
+ try:
+ LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
+ except:
+ if LRS_Chr.upper() == 'X':
+ LRS_location_value = 20*1000 + float(LRS_Mb)
+ else:
+ LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
+
+
+ LRS_score_repr = '%3.1f' % thisTrait.lrs
+ LRS_score_value = thisTrait.lrs
+ LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
+ LRS_flag = 0
+
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class=className, align='right', nowrap="on"), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class=className), LRS_location_repr, LRS_location_value))
+
+ if LRS_flag:
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class=className), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class=className), LRS_location_repr, LRS_location_value))
+ else:
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", 0))
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", 1000000))
+
+ tblobj_body.append(tr)
+
+ return tblobj_body
+
+ def getSortByValue(self):
+
+ sortby = ("pv", "up")
+
+ return sortby
+
+ def nullRecord(self,x):
+ if x or x == 0:
+ return x
+ else:
+ return ""
+
diff --git a/web/webqtl/collection/AddUserInputToSelectionPage.py b/web/webqtl/collection/AddUserInputToSelectionPage.py
new file mode 100755
index 00000000..2c69a047
--- /dev/null
+++ b/web/webqtl/collection/AddUserInputToSelectionPage.py
@@ -0,0 +1,97 @@
+# 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
+
+#AddUserInputToSelectionPage.py
+
+import time
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from AddToSelectionPage import AddToSelectionPage
+
+#########################################
+# Add UserInput to Selection Page
+#########################################
+class AddUserInputToSelectionPage(AddToSelectionPage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if not fd.genotype:
+ fd.readData(incf1 = 1)
+
+ self.strainlist = []
+ self.vals = []
+ for i, strain in enumerate(fd.f1list + fd.strainlist):
+ if fd.allTraitData.has_key(strain) and fd.allTraitData[strain].val != None:
+ self.strainlist.append(strain)
+ self.vals.append([fd.allTraitData[strain].val, fd.allTraitData[strain].var])
+
+ if len(self.strainlist) > webqtlConfig.KMININFORMATIVE:
+ pass
+ else:
+ templatePage.__init__(self, fd)
+ heading = 'Add to Collection'
+ detail = ['The number of informative strains in your trait is less than %d, this trait can not be added to the selection' % webqtlConfig.KMININFORMATIVE]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.cursor.execute('delete Temp, TempData from Temp, TempData where Temp.DataId = TempData.Id and UNIX_TIMESTAMP()-UNIX_TIMESTAMP(CreateTime)>%d;' % webqtlConfig.MAXLIFE)
+ ct0 = time.localtime(time.time())
+ ct = time.strftime("%B/%d %H:%M:%S",ct0)
+ if not fd.identification:
+ fd.identification = "Unnamed Trait"
+ user_ip = fd.remote_ip
+ newDescription = '%s entered at %s from IP %s' % (fd.identification,ct,user_ip)
+ newProbeSetID = webqtlUtil.genRandStr("USER_Tmp_")
+ self.cursor.execute('SelecT max(id) from TempData')
+ try:
+ DataId = self.cursor.fetchall()[0][0] + 1
+ except:
+ DataId = 1
+ self.cursor.execute('SelecT Id from InbredSet where Name = "%s"' % fd.RISet)
+ InbredSetId = self.cursor.fetchall()[0][0]
+
+ self.cursor.execute('insert into Temp(Name,description, createtime,DataId,InbredSetId,IP) values(%s,%s,Now(),%s,%s,%s)' ,(newProbeSetID, newDescription, DataId,InbredSetId,user_ip))
+
+ k = 0
+ for Strain in self.strainlist:
+ self.cursor.execute('SelecT Strain.Id from Strain,StrainXRef where Strain.Name = "%s" and Strain.Id = StrainXRef.StrainId and StrainXRef.InbredSetId=%d' % (Strain, InbredSetId))
+ StrainId = self.cursor.fetchall()[0][0]
+ self.cursor.execute('insert into TempData(Id, StrainId, value, SE) values(%s,%s,%s,%s)' , (DataId, StrainId, self.vals[k][0], self.vals[k][1]))
+ k += 1
+
+ self.searchResult = ['Temp::%s' % newProbeSetID]
+
+ if self.genSelection(fd=fd):
+ self.writeHTML(fd)
+
+
diff --git a/web/webqtl/collection/BatchSubmitSelectionPage.py b/web/webqtl/collection/BatchSubmitSelectionPage.py
new file mode 100755
index 00000000..743606b2
--- /dev/null
+++ b/web/webqtl/collection/BatchSubmitSelectionPage.py
@@ -0,0 +1,225 @@
+# 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
+
+#BatchSubmitSelectionPage.py
+
+import string
+import time
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from AddToSelectionPage import AddToSelectionPage
+
+
+#########################################
+# batch submission result Page
+#########################################
+class BatchSubmitSelectionPage(AddToSelectionPage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+ if not fd.genotype:
+ fd.readGenotype()
+
+ heading = 'Batch Submission'
+
+ self.batchDataFile = fd.formdata.getvalue('batchdatafile')
+ if not self.batchDataFile:
+ templatePage.__init__(self, fd)
+ detail = ['The file you choose to import from doesn\'t exist.']
+ self.error(heading=heading,detail=detail)
+ return
+ self.batchDataFile = string.replace(self.batchDataFile, '\r', '\n')
+ self.batchDataFile = string.replace(self.batchDataFile, '\n\n', '\n')
+ self.batchDataFile = string.split(self.batchDataFile, '\n')
+ self.batchDataFile = map(string.strip, self.batchDataFile)
+
+ traitNames, strainNames, traitValues, SE, NStrain = self.parseDataFile()
+ strainIds = []
+
+ #print 'Content-type: text/html\n'
+ #print len(traitNames), len(strainNames) , len(strainIds), len(traitValues) , len(SE), "<BR><BR>", len(NStrain)
+ #return
+
+ try:
+
+ if not traitNames or not strainNames or not traitValues or len(traitNames) != len(traitValues) or len(traitNames) != len(SE) or len(traitNames) != len(NStrain):
+ raise 'ValueError'
+ for item in traitValues:
+ if len(strainNames) != len(item):
+ raise 'ValueError'
+ for item in SE:
+ if len(strainNames) != len(item):
+ raise 'ValueError'
+ for item in NStrain:
+ if len(strainNames) != len(item):
+ raise 'ValueError'
+ for item in strainNames:
+ self.cursor.execute('''Select
+ Strain.Id
+ from Strain, StrainXRef,InbredSet
+ where
+ Strain.Name = "%s" AND
+ StrainXRef.StrainId = Strain.Id AND
+ StrainXRef.InbredSetId = InbredSet.Id AND
+ InbredSet.Name = "%s"
+ ''' % (item, fd.RISet))
+ strainId = self.cursor.fetchone()[0]
+ strainIds.append(strainId)
+ except:
+ templatePage.__init__(self, fd)
+ detail = ['The format of the file is incorrect, or it contains unknown strains.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.searchResult = []
+ self.addToTable(traitNames, strainNames,strainIds, traitValues,SE, NStrain, fd)
+
+ if self.genSelection(fd=fd):
+ self.writeHTML(fd)
+
+ def parseDataFile(self):
+ rchSartPos = 0
+ header = []
+ traits = []
+ data = []
+ se = []
+ nstrain = []
+ strains = []
+
+ if 1:
+ for line in self.batchDataFile:
+ line = line.strip()
+ if line == '' or line[0] == '#':
+ continue
+
+ columns = string.split(line, '\t')
+ columns = map(string.strip, columns)
+
+ if rchSartPos == 'column':
+ strains.append(columns[0])
+ tdata = map(webqtlUtil.StringAsFloat,columns[1:])
+ for j, item in enumerate(tdata):
+ if posIdx[j][0] == 'data':
+ data[posIdx[j][1]].append(item)
+ elif posIdx[j][0] == 'n':
+ if item != None:
+ nstrain[posIdx[j][1]].append(int(item))
+ else:
+ nstrain[posIdx[j][1]].append(item)
+ else:
+ se[posIdx[j][1]].append(item)
+
+ elif rchSartPos == 'row':
+ if columns[0].lower() == 'se':
+ se.append(map(webqtlUtil.StringAsFloat,columns[1:]))
+ elif columns[0].lower() == 'n':
+ nstrain.append(map(webqtlUtil.IntAsFloat,columns[1:]))
+ else:
+ while (len(data) > len(se)):
+ se.append([None] * len(data[-1]))
+ while (len(data) > len(nstrain)):
+ nstrain.append([None] * len(data[-1]))
+ header.append(columns[0])
+ data.append(map(webqtlUtil.StringAsFloat,columns[1:]))
+ elif columns[0] == '@format=column':
+ rchSartPos = 'column'
+ posIdx = []
+ j = 0
+ for item in columns[1:]:
+ #assign column type
+ if string.lower(item) == 'se':
+ posIdx.append(('se',j-1))
+ elif string.lower(item) == 'n':
+ posIdx.append(('n',j-1))
+ else:
+ header.append(item)
+ posIdx.append(('data',j))
+ j += 1
+
+ for i in range(len(header)):
+ data.append([])
+ se.append([])
+ nstrain.append([])
+ elif columns[0] == '@format=row':
+ rchSartPos = 'row'
+ strains = columns[1:]
+ else:
+ pass
+ #modify
+ for i in range(len(se)):
+ if se[i] == []:
+ se[i] = [None] * len(data[-1])
+ for i in range(len(nstrain)):
+ if nstrain[i] == []:
+ nstrain[i] = [None] * len(data[-1])
+ if len(data) > len(se):
+ se.append([None] * len(data[-1]))
+ if len(data) > len(nstrain):
+ nstrain.append([None] * len(data[-1]))
+
+ return header,strains,data,se, nstrain
+ else:
+ return [],[],[],[], []
+
+
+ #XZ, add items to self.searchResult
+ def addToTable(self, traitNames, strainNames,strainIds, traitValues, SE, NStrain, fd):
+ self.cursor.execute('delete Temp, TempData from Temp, TempData where Temp.DataId = TempData.Id and UNIX_TIMESTAMP()-UNIX_TIMESTAMP(CreateTime)>%d;' % webqtlConfig.MAXLIFE)
+
+ i = 0
+ for trait in traitNames:
+ ct0 = time.localtime(time.time())
+ ct = time.strftime("%B/%d %H:%M:%S",ct0)
+ if trait == '':
+ trait = "Unnamed Trait"
+ user_ip = fd.remote_ip
+ newDescription = '%s entered at %s from IP %s' % (trait,ct,user_ip)
+ newProbeSetID = webqtlUtil.genRandStr('Usr_TMP_')
+
+ self.cursor.execute('SelecT max(id) from TempData')
+ try:
+ DataId = self.cursor.fetchall()[0][0] + 1
+ except:
+ DataId = 1
+
+ self.cursor.execute('Select Id from InbredSet where Name = "%s"' % fd.RISet)
+ InbredSetId = self.cursor.fetchall()[0][0]
+
+ self.cursor.execute('insert into Temp(Name,description, createtime,DataId,InbredSetId,IP) values(%s,%s,Now(),%s,%s,%s)' ,(newProbeSetID, newDescription, DataId,InbredSetId,user_ip))
+
+ for k in range(len(traitValues[i])):
+ if traitValues[i][k] != None:
+ self.cursor.execute('insert into TempData(Id, StrainId, value, SE, NStrain) values(%s, %s, %s, %s, %s)' , (DataId, strainIds[k], traitValues[i][k],SE[i][k],NStrain[i][k]))
+
+ self.searchResult.append('Temp::%s' % newProbeSetID)
+ i += 1
+
diff --git a/web/webqtl/collection/DisplaySelectionPage.py b/web/webqtl/collection/DisplaySelectionPage.py
new file mode 100755
index 00000000..02d4d4b8
--- /dev/null
+++ b/web/webqtl/collection/DisplaySelectionPage.py
@@ -0,0 +1,51 @@
+# 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
+
+#DisplaySelectionPage.py
+
+from base.templatePage import templatePage
+from AddToSelectionPage import AddToSelectionPage
+
+#########################################
+# Display Selection Page
+#########################################
+class DisplaySelectionPage(AddToSelectionPage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if not fd.genotype:
+ fd.readGenotype()
+
+ self.searchResult = []
+
+ self.genSelection(fd=fd)
+
+ self.writeHTML(fd)
diff --git a/web/webqtl/collection/ExportSelectionDetailInfoPage.py b/web/webqtl/collection/ExportSelectionDetailInfoPage.py
new file mode 100755
index 00000000..69f293b2
--- /dev/null
+++ b/web/webqtl/collection/ExportSelectionDetailInfoPage.py
@@ -0,0 +1,197 @@
+# 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
+
+#ExportSelectionDetailInfoPage.py
+
+import string
+from htmlgen import HTMLgen2 as HT
+import os
+import time
+import pyXLWriter as xl
+
+import reaper
+
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base.webqtlTrait import webqtlTrait
+
+
+#########################################
+# Export Selection DetailInfo Page
+#########################################
+class ExportSelectionDetailInfoPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ fd.incparentsf1 = 1
+ if not fd.genotype:
+ fd.readGenotype()
+
+ locusChr = {}
+ locusMb = {}
+ for chr in fd.genotype:
+ for locus in chr:
+ locusChr[locus.name] = locus.chr
+ locusMb[locus.name] = locus.Mb
+
+ self.searchResult = fd.formdata.getvalue('searchResult')
+
+ if not self.searchResult:
+ templatePage.__init__(self, fd)
+ heading = 'Export Collection'
+ detail = ['You need to select at least one trait to export.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.RISet = fd.formdata.getvalue("RISet")
+ self.cursor.execute("Select Species.Name from Species, InbredSet where InbredSet.SpeciesId = Species.Id and InbredSet.Name = '%s'" % self.RISet)
+ self.Species = self.cursor.fetchone()[0]
+
+ if type("1") == type(self.searchResult):
+ self.searchResult = string.split(self.searchResult,'\t')
+ strainlist = fd.f1list + fd.strainlist
+ fields = ["ID", "Species", "Cross", "Database", "ProbeSetID / RecordID", "Symbol", "Description", "ProbeTarget", "PubMed_ID", "Phenotype", "Chr", "Mb", "Alias", "Gene_ID", "HomoloGene_ID", "UniGene_ID", "Strand_Probe ", "Strand_Gene ", "Probe_set_specificity", "Probe_set_BLAT_score", "Probe_set_BLAT_Mb_start", "Probe_set_BLAT_Mb_end ", "QTL_Chr", "QTL_Mb", "Locus_at_Peak", "Max_LRS", "P_value_of_MAX", "Mean_Expression"] + strainlist
+
+ if self.searchResult:
+ traitList = []
+ for item in self.searchResult:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo(QTL=1)
+ thisTrait.retrieveData(strainlist=strainlist)
+ traitList.append(thisTrait)
+
+ text = [fields]
+ for i, thisTrait in enumerate(traitList):
+ if thisTrait.db.type == 'ProbeSet':
+ if not thisTrait.cellid: #ProbeSet
+ #12/22/2009, XZ: We calculated LRS for each marker(locus) in geno file and record the max LRS and its corresponding marker in MySQL database. But after the calculation, Rob deleted several markers. If one of the deleted markers happen to be the one recorded in database, error will occur. So we have to deal with this situation.
+ if locusChr.has_key(thisTrait.locus) and locusMb.has_key(thisTrait.locus):
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, thisTrait.symbol, thisTrait.description, thisTrait.probe_target_description,"", "", thisTrait.chr, thisTrait.mb, thisTrait.alias, thisTrait.geneid, thisTrait.homologeneid, thisTrait.unigeneid, thisTrait.strand_probe, thisTrait.strand_gene, thisTrait.probe_set_specificity, thisTrait.probe_set_blat_score, thisTrait.probe_set_blat_mb_start, thisTrait.probe_set_blat_mb_end, locusChr[thisTrait.locus], locusMb[thisTrait.locus], thisTrait.locus, thisTrait.lrs, thisTrait.pvalue])
+ else:
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, thisTrait.symbol, thisTrait.description, thisTrait.probe_target_description,"", "", thisTrait.chr, thisTrait.mb, thisTrait.alias, thisTrait.geneid, thisTrait.homologeneid, thisTrait.unigeneid, thisTrait.strand_probe, thisTrait.strand_gene, thisTrait.probe_set_specificity, thisTrait.probe_set_blat_score, thisTrait.probe_set_blat_mb_start, thisTrait.probe_set_blat_mb_end, "", "", "", "", ""])
+ else: #Probe
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name + " : " + thisTrait.cellid, thisTrait.symbol, thisTrait.description, thisTrait.probe_target_description,"", "", thisTrait.chr, thisTrait.mb, thisTrait.alias, thisTrait.geneid, thisTrait.homologeneid, thisTrait.unigeneid, "", "", "", "", "", "", "", "", "", "", ""])
+
+ elif thisTrait.db.type == 'Publish':
+ #XZ: need to consider confidential phenotype
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ PhenotypeString = thisTrait.pre_publication_description
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", "", "", thisTrait.pubmed_id, PhenotypeString, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""])
+ elif thisTrait.db.type == 'Temp':
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", thisTrait.description, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "","", ""])
+ elif thisTrait.db.type == 'Geno':
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", thisTrait.name,"", "", "", thisTrait.chr, thisTrait.mb, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""])
+ else:
+ continue
+
+ testval = thisTrait.exportData(strainlist)
+ try:
+ mean = reaper.anova(testval)[0]
+ except:
+ count = 0
+ sum = 0
+ for oneValue in testval:
+ try:
+ oneValue = float(oneValue)
+ sum = sum + oneValue
+ count = count + 1
+ except:
+ pass
+ mean = sum/count
+ text[-1].append(mean)
+ text[-1] += testval
+ if len(text[0]) < 255 or len(text) < 255:
+ transpose = 0
+ if len(text[0]) >= 255:
+ text = webqtlUtil.transpose(text)
+ transpose = 1
+ filename = os.path.join(webqtlConfig.TMPDIR, webqtlUtil.generate_session() +'.xls')
+
+ # Create a new Excel workbook
+ workbook = xl.Writer(filename)
+ worksheet = workbook.add_worksheet()
+ headingStyle = workbook.add_format(align = 'center', bold = 1, size=13, color = 'green')
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=13, border = 1, border_color="gray")
+
+ ##Write title Info
+ # Modified by Hongqiang Li
+ # worksheet.write([0, 0], "Data source: The GeneNetwork at web2qtl.utmem.edu:88", titleStyle)
+ # worksheet.write([1, 0], "Citations: Please see web2qtl.utmem.edu:88/reference.html", titleStyle)
+ worksheet.write([0, 0], "Data source: The GeneNetwork at %s" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ #
+ worksheet.write([2, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([3, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+
+ # Modified by Hongqiang Li
+ # worksheet.write([4, 0], "Status of data ownership: Possibly unpublished data; please see web2qtl.utmem.edu:88/statusandContact.html for details on sources, ownership, and usage of these data.", titleStyle)
+ worksheet.write([4, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+ #
+ worksheet.write([6, 0], "This output file contains data from %d GeneNetwork databases listed below" % len(traitList), titleStyle)
+
+ # Row and column are zero indexed
+ nrow = startRow = 8
+ for row in text:
+ for ncol, cell in enumerate(row):
+ if nrow == startRow:
+ worksheet.write([nrow, ncol], cell.strip(), headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(cell))
+ else:
+ worksheet.write([nrow, ncol], cell)
+ nrow += 1
+
+ worksheet.write([nrow+1, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA 21131), NCI MMHCC (U01CA105417), and NCRR (U24 RR021760)", titleStyle)
+ worksheet.write([nrow+2, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+ workbook.close()
+
+ fp = open(filename, 'rb')
+ text = fp.read()
+ fp.close()
+
+ self.content_type = 'application/xls'
+ self.content_disposition = 'attachment; filename=%s' % ('export-%s.xls' % time.strftime("%y-%m-%d-%H-%M"))
+ self.attachment = text
+ else:
+ self.content_type = 'application/xls'
+ self.content_disposition = 'attachment; filename=%s' % ('export-%s.txt' % time.strftime("%y-%m-%d-%H-%M"))
+ for item in text:
+ self.attachment += string.join(map(str, item), '\t')+ "\n"
+ self.cursor.close()
+ else:
+ fd.req.content_type = 'text/html'
+ heading = 'Export Collection'
+ detail = [HT.Font('Error : ',color='red'),HT.Font('Error occurs while retrieving data from database.',color='black')]
+ self.error(heading=heading,detail=detail)
+
+
diff --git a/web/webqtl/collection/ExportSelectionPage.py b/web/webqtl/collection/ExportSelectionPage.py
new file mode 100755
index 00000000..df401e9e
--- /dev/null
+++ b/web/webqtl/collection/ExportSelectionPage.py
@@ -0,0 +1,67 @@
+# 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
+
+#ExportSelectionPage.py
+
+import string
+import time
+
+from base.templatePage import templatePage
+
+
+#########################################
+# Export Selection Page
+#########################################
+class ExportSelectionPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ collectionName = '%s_Select' % fd.RISet
+
+ try:
+ preSelection = fd.input_session_data[collectionName]
+ preSelection = list(string.split(preSelection,','))
+ except:
+ preSelection = []
+
+ for item in preSelection:
+ if not item:
+ preSelection.remove(item)
+
+ if preSelection:
+ self.content_type = 'application/txt'
+ self.content_disposition = 'attachment; filename=%s' % (fd.RISet+'_export-%s.txt' % time.strftime("%y-%m-%d-%H-%M"))
+ self.attachment += fd.RISet+"\n"
+ for item in preSelection:
+ self.attachment += item+"\n"
+ else:
+ heading = 'Export Collection'
+ detail = ['This collection is empty. No trait could be exported.']
+ self.error(heading=heading,detail=detail)
+
+
diff --git a/web/webqtl/collection/ImportSelectionPage.py b/web/webqtl/collection/ImportSelectionPage.py
new file mode 100755
index 00000000..0702509b
--- /dev/null
+++ b/web/webqtl/collection/ImportSelectionPage.py
@@ -0,0 +1,92 @@
+# 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
+
+#ImportSelectionPage.py
+
+import string
+
+from base.templatePage import templatePage
+from AddToSelectionPage import AddToSelectionPage
+
+
+#########################################
+# Import Selection Page
+#########################################
+class ImportSelectionPage(AddToSelectionPage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if not fd.genotype:
+ fd.readGenotype()
+
+ self.importFile = fd.formdata.getvalue('importfile')
+ if not self.importFile:
+ templatePage.__init__(self, fd)
+ heading = 'Import Collection'
+ detail = ['The file you choose to import from doesn\'t exist.']
+ self.error(heading=heading,detail=detail)
+ return
+ self.importFile = string.split(self.importFile, '\n')
+
+ RISetLocate = 0
+ self.searchResult = []
+ for line in self.importFile:
+ if line and line[0] != '#':
+ if not RISetLocate:
+ RISetLocate = line
+ if RISetLocate != fd.RISet:
+ templatePage.__init__(self, fd)
+ heading = 'Import Collection'
+ detail = ['The file you choose to import from doesn\'t contain %s selection.' % fd.RISet]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ self.searchResult.append(line)
+
+ if not self.searchResult:
+ templatePage.__init__(self, fd)
+ heading = 'Import Collection'
+ detail = ['The file you choose to import from is empty.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.importMethod = fd.formdata.getvalue('importmethod')
+
+ if self.importMethod == 'replace':
+ checkPreSelection = 0
+ else:
+ checkPreSelection = 1
+
+ if self.genSelection(fd=fd, checkPreSelection = checkPreSelection):
+ self.writeHTML(fd)
+
+
+
diff --git a/web/webqtl/collection/RemoveSelectionPage.py b/web/webqtl/collection/RemoveSelectionPage.py
new file mode 100755
index 00000000..b9560c6b
--- /dev/null
+++ b/web/webqtl/collection/RemoveSelectionPage.py
@@ -0,0 +1,108 @@
+# 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
+
+
+
+import string
+
+from base.templatePage import templatePage
+from base.webqtlTrait import webqtlTrait
+from AddToSelectionPage import AddToSelectionPage
+
+#########################################
+# Remove Selection Page
+#########################################
+class RemoveSelectionPage(AddToSelectionPage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if not fd.genotype:
+ fd.readGenotype()
+
+ self.searchResult = fd.formdata.getvalue('searchResult')
+ if self.searchResult:
+ pass
+ else:
+ templatePage.__init__(self, fd)
+ heading = 'Remove Selections'
+ detail = ['You need to select at least one trait to remove from your selection.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.genSelection(fd=fd)
+ self.writeHTML(fd)
+
+
+
+ def genSelection(self, fd=None):
+ collectionName = '%s_Select' % fd.RISet
+
+ try:
+ preSelection = fd.input_session_data[collectionName]
+ preSelection = list(string.split(preSelection,','))
+ except:
+ preSelection = []
+
+ if type("1") == type(self.searchResult):
+ self.searchResult = [self.searchResult]
+
+ if preSelection:
+ for item in self.searchResult:
+ try:
+ preSelection.remove(item)
+ except:
+ pass
+ self.searchResult = preSelection[:]
+
+ if not self.searchResult:
+ self.session_data_changed[collectionName] = ""
+ return
+
+ #self.searchResult.sort()
+ for item in self.searchResult:
+ if not item:
+ self.searchResult.remove(item)
+
+ searchResult2 = []
+ self.theseTraits = []
+ for item in self.searchResult:
+ try:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo(QTL=1)
+ self.theseTraits.append(thisTrait)
+ searchResult2.append(item)
+ except:
+ pass
+
+ allTraitStr = string.join(searchResult2,',')
+
+ self.session_data_changed[collectionName] = allTraitStr
+
diff --git a/web/webqtl/collection/__init__.py b/web/webqtl/collection/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/collection/__init__.py
diff --git a/web/webqtl/compareCorrelates/MultipleCorrelationPage.py b/web/webqtl/compareCorrelates/MultipleCorrelationPage.py
new file mode 100755
index 00000000..6a464ab6
--- /dev/null
+++ b/web/webqtl/compareCorrelates/MultipleCorrelationPage.py
@@ -0,0 +1,108 @@
+# 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
+from utility import webqtlUtil
+from base.webqtlTrait import webqtlTrait
+from base import webqtlConfig
+import multitrait
+
+# XZ, 09/09/2008: After adding several traits to collection, click "Compare Correlates" button,
+# XZ, 09/09/2008: This class will generate what you see.
+# XZ, 09/09/2008: This class just collect the input, then pass them to multitrait.py
+#########################################
+# Multiple Correlation Page
+#########################################
+class MultipleCorrelationPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+ if not fd.genotype:
+ fd.readData()
+
+ self.searchResult = fd.formdata.getvalue('searchResult')
+ if not self.searchResult:
+ heading = 'Compare Correlates'
+ detail = ['You need to select at least two traits in order to generate correlation matrix.']
+ self.error(heading=heading,detail=detail)
+ print 'Content-type: text/html\n'
+ self.write()
+ return
+ if type("1") == type(self.searchResult):
+ self.searchResult = [self.searchResult]
+
+ if self.searchResult:
+ if len(self.searchResult) > 100:
+ heading = 'Compare Correlates'
+ detail = ['In order to display Compare Correlates properly, Do not select more than %d traits for Compare Correlates.' % 100]
+ self.error(heading=heading,detail=detail)
+ print 'Content-type: text/html\n'
+ self.write()
+ return
+ else:
+ pass
+
+ traitList = []
+ for item in self.searchResult:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo()
+ traitList.append(thisTrait)
+ else:
+ heading = 'Compare Correlates'
+ 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
+
+
+ ##########
+ filename= webqtlUtil.genRandStr("mult_")
+ fp = open(webqtlConfig.IMGDIR+filename, 'wb')
+ fp.write('%s\n' % fd.RISet)
+ for thisTrait in traitList:
+ fp.write("%s,%s,%s\n" % (thisTrait.db.type,thisTrait.db.id,thisTrait.name))
+ fp.close()
+ fd.formdata["filename"] = filename
+
+ params = {"filename":filename, "targetDatabase":"",
+ "threshold":0.5, "subsetSize":10,
+ "correlation":"pearson", "subsetCount":10,
+ "firstRun":"1"}
+ results = []
+ txtOutputFileName = ""
+
+ self.dict['body'] = multitrait.TraitCorrelationPage(fd, params, self.cursor, traitList, results,
+ fd.RISet,txtOutputFileName).dict['body']
+ self.dict['title'] = 'Compare Correlates'
+
+
+
+
diff --git a/web/webqtl/compareCorrelates/__init__.py b/web/webqtl/compareCorrelates/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/compareCorrelates/__init__.py
diff --git a/web/webqtl/compareCorrelates/correlation.py b/web/webqtl/compareCorrelates/correlation.py
new file mode 100755
index 00000000..f2ea55b3
--- /dev/null
+++ b/web/webqtl/compareCorrelates/correlation.py
@@ -0,0 +1,359 @@
+# 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
+
+# correlation.py
+# functions for computing correlations for traits
+#
+# Originally, this code was designed to compute Pearson product-moment
+# coefficents. The basic function calcPearson scans the strain data
+# for the two traits and drops data for a strain unless both traits have it.
+# If there are less than six strains left, we conclude that there's
+# insufficent data and drop the correlation.
+#
+# In addition, this code can compute Spearman rank-order coefficents using
+# the calcSpearman function.
+
+#Xiaodong changed the dependancy structure
+import numarray
+import numarray.ma as MA
+import time
+
+import trait
+
+# strainDataUnion : StrainData -> StrainData -> array, array
+def strainDataUnion(s1, s2):
+ # build lists of values that both have
+ # and make sure that both sets of values are in the same order
+ s1p = []
+ s2p = []
+ sortedKeys = s1.keys()
+ sortedKeys.sort()
+ for s in sortedKeys:
+ if s2.has_key(s):
+ s1p.append(s1[s])
+ s2p.append(s2[s])
+
+ return (numarray.array(s1p, numarray.Float64),
+ numarray.array(s2p, numarray.Float64))
+
+# calcCorrelationHelper : array -> array -> float
+def calcCorrelationHelper(s1p, s2p):
+ # if the traits share less than six strains, then we don't
+ # bother with the correlations
+ if len(s1p) < 6:
+ return 0.0
+
+ # subtract by x-bar and y-bar elementwise
+ #oldS1P = s1p.copy()
+ #oldS2P = s2p.copy()
+
+ s1p = (s1p - numarray.average(s1p)).astype(numarray.Float64)
+ s2p = (s2p - numarray.average(s2p)).astype(numarray.Float64)
+
+ # square for the variances
+ s1p_2 = numarray.sum(s1p**2)
+ s2p_2 = numarray.sum(s2p**2)
+
+ try:
+ corr = (numarray.sum(s1p*s2p)/
+ numarray.sqrt(s1p_2 * s2p_2))
+ except ZeroDivisionError:
+ corr = 0.0
+
+ return corr
+
+# calcSpearman : Trait -> Trait -> float
+def calcSpearman(trait1, trait2):
+ s1p, s2p = strainDataUnion(trait1.strainData,
+ trait2.strainData)
+ s1p = rankArray(s1p)
+ s2p = rankArray(s2p)
+ return calcCorrelationHelper(s1p, s2p)
+
+# calcPearson : Trait -> Trait -> float
+def calcPearson(trait1, trait2):
+ # build lists of values that both have
+ # and make sure that both sets of values are in the same order
+ s1p, s2p = strainDataUnion(trait1.strainData,
+ trait2.strainData)
+
+ return calcCorrelationHelper(s1p, s2p)
+
+# buildPearsonCorrelationMatrix: (listof n traits) -> int s -> n x s matrix, n x s matrix
+#def buildPearsonCorrelationMatrix(traits, sc):
+# dim = (len(traits), sc)
+# matrix = numarray.zeros(dim, MA.Float64)
+# testMatrix = numarray.zeros(dim, MA.Float64)
+
+# for i in range(len(traits)):
+# sd = traits[i].strainData
+# for key in sd.keys():
+# matrix[i,int(key) - 1] = sd[key]
+# testMatrix[i,int(key) - 1] = 1
+
+def buildPearsonCorrelationMatrix(traits, commonStrains):
+ dim = (len(traits), len(commonStrains))
+ matrix = numarray.zeros(dim, MA.Float64)
+ testMatrix = numarray.zeros(dim, MA.Float64)
+
+ for i in range(len(traits)):
+ sd = traits[i].strainData
+ keys = sd.keys()
+ for j in range(0, len(commonStrains)):
+ if keys.__contains__(commonStrains[j]):
+ matrix[i,j] = sd[commonStrains[j]]
+ testMatrix[i,j] = 1
+
+ return matrix, testMatrix
+
+# buildSpearmanCorrelationMatrix: (listof n traits) -> int s -> n x s matrix, n x s matrix
+def buildSpearmanCorrelationMatrix(traits, sc):
+ dim = (len(traits), sc)
+ matrix = numarray.zeros(dim, MA.Float64)
+ testMatrix = numarray.zeros(dim, MA.Float64)
+
+ def customCmp(a, b):
+ return cmp(a[1], b[1])
+
+ for i in range(len(traits)):
+ # copy strain data to a temporary list and turn it into
+ # (strain, expression) pairs
+ sd = traits[i].strainData
+ tempList = []
+ for key in sd.keys():
+ tempList.append((key, sd[key]))
+
+ # sort the temporary list by expression
+ tempList.sort(customCmp)
+
+ for j in range(len(tempList)):
+ # k is the strain id minus 1
+ # 1-based strain id -> 0-based column index
+ k = int(tempList[j][0]) - 1
+
+ # j is the rank of the particular strain
+ matrix[i,k] = j
+
+ testMatrix[i,k] = 1
+
+ return matrix, testMatrix
+
+def findLargestStrain(traits, sc):
+ strainMaxes = []
+ for i in range(len(traits)):
+ keys = traits[i].strainData.keys()
+ strainMaxes.append(max(keys))
+
+ return max(strainMaxes)
+
+def findCommonStrains(traits1, traits2):
+ commonStrains = []
+ strains1 = []
+ strains2 = []
+
+ for trait in traits1:
+ keys = trait.strainData.keys()
+ for key in keys:
+ if not strains1.__contains__(key):
+ strains1.append(key)
+
+ for trait in traits2:
+ keys = trait.strainData.keys()
+ for key in keys:
+ if not strains2.__contains__(key):
+ strains2.append(key)
+
+ for strain in strains1:
+ if strains2.__contains__(strain):
+ commonStrains.append(strain)
+
+ return commonStrains
+
+def calcPearsonMatrix(traits1, traits2, sc, strainThreshold=6,
+ verbose = 0):
+ return calcMatrixHelper(buildPearsonCorrelationMatrix,
+ traits1, traits2, sc, strainThreshold,
+ verbose)
+
+def calcProbeSetPearsonMatrix(cursor, freezeId, traits2, strainThreshold=6,
+ verbose = 0):
+
+ cursor.execute('select ProbeSetId from ProbeSetXRef where ProbeSetFreezeId = %s order by ProbeSetId' % freezeId)
+ ProbeSetIds = cursor.fetchall()
+
+ results = []
+ i=0
+ while i<len(ProbeSetIds):
+ ProbeSetId1 = ProbeSetIds[i][0]
+ if (i+4999) < len(ProbeSetIds):
+ ProbeSetId2 = ProbeSetIds[i+4999][0]
+ else:
+ ProbeSetId2 = ProbeSetIds[len(ProbeSetIds)-1][0]
+
+ traits1 = trait.queryPopulatedProbeSetTraits2(cursor, freezeId, ProbeSetId1, ProbeSetId2) # XZ,09/10/2008: add module name 'trait.'
+ SubMatrix = calcMatrixHelper(buildPearsonCorrelationMatrix,
+ traits1, traits2, 1000, strainThreshold,
+ verbose)
+ results.append(SubMatrix)
+ i += 5000
+
+ returnValue = numarray.zeros((len(ProbeSetIds), len(traits2)), MA.Float64)
+ row = 0
+ col = 0
+ for SubMatrix in results:
+ for i in range(0, len(SubMatrix)):
+ for j in range(0, len(traits2)):
+ returnValue[row,col] = SubMatrix[i,j]
+ col += 1
+ col = 0
+ row +=1
+
+ return returnValue
+
+
+
+# note: this code DOES NOT WORK, especially in cases where
+# there are missing observations (e.g. when comparing traits
+# from different probesetfreezes)
+def calcSpearmanMatrix(traits1, traits2, sc, strainThreshold=6,
+ verbose=0):
+ return calcMatrixHelper(buildSpearmanCorrelationMatrix,
+ traits1, traits2, sc, strainThreshold,
+ verbose)
+
+def calcMatrixHelper(builder, traits1, traits2, sc, strainThreshold,
+ verbose):
+
+ # intelligently figure out strain count
+ step0 = time.time()
+ #localSC = max(findLargestStrain(traits1, sc),
+ # findLargestStrain(traits2, sc))
+
+ commonStrains = findCommonStrains(traits1, traits2)
+
+ buildStart = time.time()
+ matrix1, test1 = builder(traits1, commonStrains)
+ matrix2, test2 = builder(traits2, commonStrains)
+ buildTime = time.time() - buildStart
+
+ step1 = time.time()
+
+ ns = numarray.innerproduct(test1, test2)
+
+ # mask all ns less than strainThreshold so the correlation values
+ # end up masked
+ # ns is now a MaskedArray and so all ops involving ns will be
+ # MaskedArrays
+ ns = MA.masked_less(ns, strainThreshold, copy=0)
+
+ # divide-by-zero errors are automatically masked
+ #ns = -1.0/ns
+
+ step2 = time.time()
+
+ # see comment above to find out where this ridiculously cool
+ # matrix algebra comes from
+ xs = numarray.innerproduct(matrix1, test2)
+ ys = numarray.innerproduct(test1, matrix2)
+ xys = numarray.innerproduct(matrix1, matrix2)
+
+ # use in-place operations to try to speed things up
+ numarray.power(matrix1, 2, matrix1)
+ numarray.power(matrix2, 2, matrix2)
+
+ x2s = numarray.innerproduct(matrix1, test2)
+ y2s = numarray.innerproduct(test1, matrix2)
+
+ step3 = time.time()
+
+ # parens below are very important
+ # the instant we touch ns, arrays become masked and
+ # computation is much, much slower
+ top = ns*xys - (xs*ys)
+ bottom1 = ns*x2s - (xs*xs)
+ bottom2 = ns*y2s - (ys*ys)
+ bottom = MA.sqrt(bottom1*bottom2)
+
+ # mask catches floating point divide-by-zero problems here
+ corrs = top / bottom
+
+ step4 = time.time()
+
+ # we define undefined correlations as zero even though there
+ # is a mathematical distinction
+ returnValue = MA.filled(corrs, 0.0)
+
+ step5 = time.time()
+
+ #print ("calcMatrixHelper: %.2f s, %.2f s, %.2f s, %.2f s, %.2f s, %.2f s, total: %.2f s"
+ # %(buildTime,
+ # buildStart - step0,
+ # step2 - step1,
+ # step3 - step2,
+ # step4 - step3,
+ # step5 - step4,
+ # step5 - step0))
+
+ if verbose:
+ print "Matrix 1:", matrix1
+ print "Matrix 2:", matrix2
+ print "Ns:", ns
+ print "Xs", xs
+ print "Ys", ys
+ print "XYs:", xys
+ print "Top:", top
+ print "Bottom 1:", bottom1
+ print "Bottom 2:", bottom2
+ print "Bottom:", bottom
+ print "Corrs:", corrsa
+
+
+ return returnValue
+
+
+
+# rankArray: listof float -> listof float
+# to generate a companion list to alof with
+# the actual value of each element replaced by the
+# value's rank
+def rankArray(floatArray):
+ # first we save the original index of each element
+ tmpAlof = []
+ returnArray = numarray.zeros(len(floatArray), numarray.Float64)
+ i = 0
+ for i in range(len(floatArray)):
+ tmpAlof.append((i,floatArray[i]))
+
+ # now we sort by the data value
+ def customCmp(a,b): return cmp(a[1],b[1])
+ tmpAlof.sort(customCmp)
+
+ # finally we use the new rank data to populate the
+ # return array
+ for i in range(len(floatArray)):
+ returnArray[tmpAlof[i][0]] = i+1
+
+ return returnArray
diff --git a/web/webqtl/compareCorrelates/htmlModule.py b/web/webqtl/compareCorrelates/htmlModule.py
new file mode 100755
index 00000000..ebba3b86
--- /dev/null
+++ b/web/webqtl/compareCorrelates/htmlModule.py
@@ -0,0 +1,279 @@
+# 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
+
+import sys
+import string
+import os
+import MySQLdb
+import cgi
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+
+
+# XZ 08/14/2008: When I tried to replace 'from webqtlConfig import *' with 'import webqtlConfig'
+# XZ 08/14/2008: I found some problems. I discussed with Hongqiang and the below is conclusion.
+# XZ 08/14/2008: The program uses webqtlConfig.DB_NAME, webqtlConfig.MYSQL_SERVER and so on
+# XZ 08/14/2008: without 'import webqtlConfig'. This program will not work.
+# XZ 08/14/2008: CONFIG_htmlpath doesn't exist in webqtlConfig.py
+# XZ 08/14/2008: Hongqian said this was done by Fan Zhang, and this program was not tested.
+# XZ 08/14/2008: So nobody realize these bugs.
+
+# XZ, 09/09/2008: This function is not called any where.
+# XZ, 09/09/2008: Actually, I don't think this function works.
+def genHeaderFooter(i=1,title='',basehref='',js1='',js2='',layer='',body=''):
+ """
+ generate footer and header HTML code
+ default is header
+ i = 0 is footer+header
+ i = 1 is header
+ i = 2 is footer
+ """
+ try:
+ temp_file = CONFIG_htmlpath + 'beta-template.html'
+ fp = open(temp_file, 'rb')
+ template = fp.read()
+ fp.close()
+ template = template % (title,basehref,js1,js2,layer,body, "")
+ header,footer = string.split(template,'<!-- split from Here -->')
+ if i == 0:
+ return header + footer
+ elif i == 1:
+ return header
+ elif i == 2:
+ return footer
+ else:
+ return ""
+ except:
+ if i == 0:
+ return "header + footer"
+ elif i == 1:
+ return "header"
+ elif i == 2:
+ return "footer"
+ else:
+ return ""
+
+# XZ, 09/09/2008: This function is only used in multitrait.py where it is called with value assigned to db.
+# XZ, 09/09/2008: So the try-except block is not executed.
+# XZ, 09/09/2008: This explains why no error was generated even without 'import webqtlConfig'
+def genDatabaseMenu(db = None, public =1, RISetgp = 'BXD', selectname = 'database', selected = ""):
+ """
+ generate database Menu
+ public = 0 : search3.html databases Menu
+ public = 1 : search.html databases Menu
+ """
+ if not db:
+ try:
+ # import MySQLdb
+ # con = MySQLdb.Connect(db='db_webqtl')
+ # Modified by Fan Zhang
+ con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+ db = con.cursor()
+ except:
+ return "Connect MySQL Server Error"
+ else:
+ pass
+
+ databaseMenu = HT.Select(name=selectname)
+ nmenu = 0
+
+ # here's a hack: bxd and bxd300 can be correlated against each other
+ # if either of those are the group, we put in special SQL that pulls both
+ if RISetgp in ("BXD", "BXD300"):
+ ibsNameQry = '(InbredSet.Name = "BXD" OR InbredSet.Name = "BXD300")'
+ else:
+ ibsNameQry = 'InbredSet.Name = "%s"' % RISetgp
+
+ #Publish Database
+ db.execute('''
+ SelecT
+ PublishFreeze.FullName,
+ PublishFreeze.Name
+ from
+ PublishFreeze,
+ InbredSet
+ where
+ PublishFreeze.InbredSetId = InbredSet.Id and
+ %s
+ ''' % ibsNameQry)
+ for item in db.fetchall():
+ databaseMenu.append(item)
+ nmenu += 1
+
+ #Genome Database
+ db.execute('''
+ SelecT
+ GenoFreeze.FullName,
+ GenoFreeze.Name
+ from
+ GenoFreeze,InbredSet
+ where
+ GenoFreeze.InbredSetId = InbredSet.Id and
+ %s
+ ''' % ibsNameQry)
+ for item in db.fetchall():
+ databaseMenu.append(item)
+ nmenu += 1
+
+ #Microarray Database
+ db.execute('SelecT Id, Name from Tissue')
+ for item in db.fetchall():
+ TId, TName = item
+ databaseMenuSub = HT.Optgroup(label = '%s ------' % TName)
+ db.execute('''
+ SelecT
+ ProbeSetFreeze.FullName,
+ ProbeSetFreeze.Name
+ from
+ ProbeSetFreeze,
+ ProbeFreeze,
+ InbredSet
+ where
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and
+ ProbeFreeze.TissueId = %d and
+ ProbeSetFreeze.public > %d and
+ ProbeFreeze.InbredSetId = InbredSet.Id and
+ %s
+ order by
+ ProbeSetFreeze.CreateTime desc,
+ ProbeSetFreeze.AvgId
+ ''' % (TId,public,ibsNameQry))
+ for item2 in db.fetchall():
+ databaseMenuSub.append(item2)
+ nmenu += 1
+ databaseMenu.append(databaseMenuSub)
+
+ if nmenu:
+ if selected:
+ databaseMenu.selected.append(selected)
+ return str(databaseMenu)
+ else:
+ return ''
+
+
+# XZ, 09/09/2008: This function is not called any where.
+# XZ, 09/09/2008: Actually, I don't think this function works.
+# XZ, 09/09/2008: There is no 'DataForm' file now. It should be webqtlForm.py
+def genRISample():
+ import glob
+ import reaper
+ import random
+ import math
+ import webqtlUtil
+ risets = filter(lambda X:X.find('F2')<0, map(os.path.basename, glob.glob(os.path.join(CONFIG_genodir, "*.geno"))))
+ risets = map(lambda X:X.split('.')[0], risets)
+ risets.remove("BayXSha")
+ risets.sort()
+ body = HT.Blockquote()
+ NPerRow = 6
+ for item in risets:
+ values = []
+ if item == 'AXBXA': item2='AXB/BXA'
+ elif item == 'HXBBXH': item2='HXB/BXH'
+ else: item2=item
+ body.append(HT.Paragraph(item2, Class='subtitle'))
+ tbl = HT.TableLite(Class="collap")
+ dataset = reaper.Dataset()
+ dataset.read(os.path.join(CONFIG_genodir, "%s.geno"%item))
+ prgy = webqtlUtil.ParInfo[item] + list(dataset.prgy)
+
+ mean = random.random()*100
+ variance = random.random()*500
+ variables = []
+ while len(variables) < len(prgy):
+ S = 2
+ while (S>=1):
+ U1= random.random()
+ U2= random.random()
+ V1= 2*U1-1.0
+ V2= 2*U2-1.0
+ S=V1*V1+V2*V2
+ X= math.sqrt(-2 * math.log(S) / S) * V1
+ Y= math.sqrt(-2 * math.log(S) / S) * V2
+ variables.append(mean + math.sqrt(variance) * X)
+ variables.append(mean + math.sqrt(variance) * Y)
+
+ tempTR = HT.TR()
+ for i, strain in enumerate(prgy):
+ if i and i%NPerRow==0:
+ tbl.append(tempTR)
+ tempTR = HT.TR()
+ if random.random() < 0.2:
+ variable = 'X'
+ else:
+ variable = "%2.3f" % variables[i]
+
+ tempTR.append(HT.TD(strain, Class="strains", width=80))
+ tempTR.append(HT.TD(variable, Class="values", width=60))
+ values.append(variable)
+
+ for j in range(NPerRow-i%NPerRow-1):
+ tempTR.append(HT.TD())
+ tbl.append(tempTR)
+ body.append(tbl)
+ body.append(HT.Paragraph("Copy the following line to paste into the GeneNetwork entry box:"))
+ body.append(HT.Code(string.join(values, " ")))
+ body.append(HT.HR(width="90%"))
+ return body
+
+if __name__ == "__main__":
+ if os.environ.has_key('SCRIPT_FILENAME'):
+ script_filename = os.environ['SCRIPT_FILENAME']
+ else:
+ script_filename = ''
+ #Used as cgi script
+ if script_filename and script_filename[-2:] == 'py':
+ print 'Content-type: text/html\n'
+ formdata = cgi.FieldStorage()
+ sys.stderr = sys.stdout
+ try:
+ getID = string.lower(formdata.getvalue('get'))
+ except:
+ getID = ''
+ #Used as command
+ else:
+ if len(sys.argv) >= 2:
+ getID = string.lower(sys.argv[1])
+ else:
+ getID = ''
+
+ if getID == 'headerfooter':
+ print genHeaderFooter(0)
+ elif getID == 'header':
+ print genHeaderFooter(1)
+ elif getID == 'footer':
+ print genHeaderFooter(2)
+ elif getID == 'databasemenu':
+ print genDatabaseMenu(public=0)
+ elif getID == 'datasample':
+ print genRISample()
+ else:
+ print genHeaderFooter(0)
+else:
+ pass
+
diff --git a/web/webqtl/compareCorrelates/multitrait.py b/web/webqtl/compareCorrelates/multitrait.py
new file mode 100755
index 00000000..047620af
--- /dev/null
+++ b/web/webqtl/compareCorrelates/multitrait.py
@@ -0,0 +1,1121 @@
+# multitrait.py
+# a tool to analyze the correlations between several different traits and the traits
+# in a given dataset
+#
+# Parameters:
+# correlation -- either "pearson" or "spearman" depending on which ones we want to use
+#
+# filename -- an input file containing the traits to analyze
+#
+# progress -- if set, this parameter outputs a static progress page
+# and uses a META redirect to trigger the real computation
+#
+# targetDatabaseType:
+# one of "ProbeSet", "Publish", "Genotype" depending on the type of database
+# we will use for the analysis
+#
+# targetDatabaseId:
+# the id (*Freeze.Id in the database) of the particular database we will analyze
+#
+# threshold -- a float between 0 and 1 to determine which coefficents we wil l consider
+#
+# firstRun -- either 0 or 1
+# whether to automatically pick reasonable defaults for the other three parameters
+#
+# outputType -- either "html" or "text"
+#
+# Author: Stephen Pitts
+# June 15, 2004
+
+#Xiaodong changed the dependancy structure
+
+import copy
+import sys
+import cgi
+import os
+import os.path
+import math
+import time
+import numarray
+import tempfile
+import string
+import cgitb #all tracebacks come out as HTMLified CGI,useful when we have a random crash in the middle
+
+from base import templatePage
+from base.webqtlTrait import webqtlTrait
+from utility import webqtlUtil
+from base import webqtlConfig
+import trait
+import correlation
+import htmlModule
+
+cgitb.enable()
+
+
+# where this program's data files are
+RootDir = webqtlConfig.IMGDIR # XZ, 09/10/2008: add module name 'webqtlConfig.'
+RootDirURL = "/image/" # XZ, 09/10/2008: This parameter is not used in this module
+
+tempfile.tempdir = RootDir
+tempfile.template = "multitrait"
+
+# MultitraitException: used if something goes wrong
+# maybe in the future we should make exceptions more granular
+class MultitraitException(Exception):
+ def __init__(self, message):
+ self.message = message
+
+ def __repr__(self):
+ return "MultitraitException: %s" % self.message
+
+# buildParamDict: Cursor -> ParamDict
+# to process and validate CGI arguments
+# see the comment at the top of this file for valid cgi
+# parameters
+def buildParamDict(cursor, fd):
+ params = {}
+ fs = fd.formdata #cgi.FieldStorage()
+ params["progress"] = fs.getfirst("progress", "0")
+ params["filename"] = fs.getfirst("filename", "")
+ if params["filename"] == "":
+ raise MultitraitException("Required parameter filename missing.")
+
+ params["targetDatabase"] = fs.getfirst("targetDatabase", "U74Av2RMA_Raw_ProbeSet_March04")
+ params["firstRun"] = webqtlUtil.safeInt(fs.getfirst("firstRun", "0"),0)
+ params["threshold"] = webqtlUtil.safeFloat(fs.getfirst("threshold", "0.5"), 0.5)
+ params["subsetSize"] = webqtlUtil.safeInt(fs.getfirst("subsetSize", "10"), 10)
+
+ if params["subsetSize"] < -1:
+ params["subsetSize"] = -1
+
+ params["correlation"] = fs.getfirst("correlation", "pearson")
+ params["subsetCount"] = webqtlUtil.safeInt(fs.getfirst("subsetCount", 10), 10)
+
+ if params["subsetCount"] < -1:
+ params["subsetCount"] = -1
+
+ #params["outputType"] = fs.getfirst("outputType", "html")
+
+ #if params["outputType"] not in ("html", "text"):
+ # params["outputType"] = "html"
+
+ if params["correlation"] not in ("pearson", "spearman"):
+ params["correlation"] = "pearson"
+
+ params["correlationName"] = params["correlation"].capitalize()
+
+ # one of two cases:
+ # 1) We have just come from a submit, so there are a bunch of display*
+ # but no displaySets. Thus, the code down there converts the display*
+ # to displaySets so the GET request doesn't get too long
+ # 2) We have just been redirected from a progress page which already has
+ # a converted displaySets for us.
+
+ displaySets = webqtlUtil.safeInt(fs.getfirst("displaySets","0"), 0)
+
+ if displaySets == 0:
+ for key in fs.keys():
+ if key[:7] == "display":
+ #print "Hit display key %s<br>" % key
+ try:
+ whichSet = int(key[7:])
+
+ # prevent malicious attacks
+ whichSet = min(whichSet, 512)
+ displaySets += pow(2, whichSet)
+
+ except ValueError: pass
+
+ params["displaySets"] = displaySets
+ #print "In the beginning, display sets was %s: %s<br>" % (displaySets,
+ # str(binaryDecompose(displaySets)))
+
+ # if we are just gonna display a progress page, then there's no
+ # reason to look up detailed database information
+ #if params["progress"] == "1":
+ # return params
+
+ a,b = trait.dbNameToTypeId(cursor, params["targetDatabase"]) # XZ, 09/10/2008: add module name
+ params["targetDatabaseType"] = a
+ params["targetDatabaseId"] = b
+ params["targetDatabaseName"] = params["targetDatabase"]
+
+ return params
+
+# readInputFile: DB cursor -> string -> string, (arrayof Trait)
+def readInputFile(cursor, filename):
+ """
+ To read an input file with n lines in the following format
+ <databasetype>,<databaseid>,<traitname>
+ and retrieve and populate traits with appropriate data
+ from the database
+
+ Also, for our purposes. we store the database type and
+ database id in fields attached to the trait instances. We use
+ this information to generate Javascript popups with trait
+ information.
+
+ In addition, we read the strain of mice that the traits are
+ from so we can only show those databases to correlate against.
+ """
+ handle = open(filename)
+ line = handle.readline()
+ inbredSetName = line.strip()
+ line = handle.readline()
+ traits = []
+
+# XZ, 09/10/2008: In this while loop block, I changed the original variable name 'trait' to 'oneTrait'
+ while line != "":
+ line = line.strip()
+ dbType, dbId, tName = line.split(",")
+
+ if dbType == "ProbeSet":
+ oneTrait = trait.queryProbeSetTraitByName(cursor, tName) # XZ, 09/10/2008: add module name
+ oneTrait.populateDataId(cursor, dbId)
+ oneTrait.dbName = trait.dbTypeIdToName(cursor, dbType, dbId) # XZ, 09/10/2008: add module name
+ elif dbType == "Geno":
+ speciesId = trait.getSpeciesIdByDbTypeId(cursor, dbType, dbId)
+ oneTrait = trait.queryGenotypeTraitByName(cursor, speciesId, tName) # XZ, 09/10/2008: add module name
+ oneTrait.populateDataId(cursor, dbId)
+ oneTrait.dbName = trait.dbTypeIdToName(cursor, dbType, dbId) # XZ, 09/10/2008: add module name
+ elif dbType == "Publish":
+ oneTrait = trait.queryPublishTraitByName(cursor, dbId, tName) # XZ, 09/10/2008: add module name
+ oneTrait.populateDataId(cursor, dbId)
+ oneTrait.dbName = trait.dbTypeIdToName(cursor, dbType, dbId) # XZ, 09/10/2008: add module name
+ elif dbType == "Temp":
+ oneTrait = trait.queryTempTraitByName(cursor, tName) # XZ, 09/10/2008: add module name
+ oneTrait.populateDataId(cursor, dbId)
+ oneTrait.dbName = "Temp"
+
+ oneTrait.populateStrainData(cursor)
+ traits.append(oneTrait)
+
+ line = handle.readline()
+
+ return inbredSetName, traits
+
+# loadDatabase: Cursor -> ParamDict -> arrayof Trait
+def loadDatabase(cursor, p):
+ """
+ To load a set of traits as specified by the
+ targetDatabaseId
+ and targetDatabaseType parameters
+
+ Cursor should be a fastCursor from the webqtl library (i.e.
+ a MySQLdb SSCursor).
+
+ Calling populateStrainData 20,000 or so times on a ProbeSet
+ is really inefficent, so I wrote an optimized queryPopulatedProbeSetTraits
+ in the trait module that uses a join to get all of the rows in
+ bulk, store the resultset on the server, and do all sorts of nice buffering.
+ It's about two or three times faster.
+ """
+ if p["targetDatabaseType"] == "ProbeSet": # XZ, 09/10/2008: add module name
+ dbTraits = trait.queryPopulatedProbeSetTraits(cursor,
+ p["targetDatabaseId"])
+ elif p["targetDatabaseType"] == "Publish": # XZ, 09/10/2008: add module name
+ dbTraits = trait.queryPublishTraits(cursor,
+ p["targetDatabaseId"])
+ psd = trait.PublishTrait.populateStrainData
+ elif p["targetDatabaseType"] == "Geno": # XZ, 09/10/2008: add module name
+ dbTraits = trait.queryGenotypeTraits(cursor,
+ p["targetDatabaseId"])
+ psd = trait.GenotypeTrait.populateStrainData
+ else:
+ print "Unknown target database type %s" % p["targetDatabaseType"]
+
+ if p["targetDatabaseType"] != "ProbeSet":
+ map(psd, dbTraits, [cursor]*len(dbTraits))
+
+ return dbTraits
+
+def runProbeSetCorrelations(cursor, p, traits):
+ """
+ To run the correlations between the traits and the database.
+ This function computes a correlation coefficent between each
+ trait and every entry in the database, and partitions the database
+ into a disjoint array of arrays which it returns.
+
+ The length of the return array is 2^n, where n is the length of
+ the trait array. Which constitutent element a of the return array
+ a given trait ends up in is determined by the following formula
+ i = i_02^0 + ... + i_(n-1)2^(n-1)
+ where i_0 is 1 if corr(a,trait 0) >= threshold and 0 otherwise
+
+ Since most of the several thousand database traits will end up
+ with i=0, we don't return them, so the first element of the
+ return array will be empty.
+
+ A particular element of subarray j of the return array contains
+ a 2-tuple (trait,kvalues). The variable trait is obviously the
+ particular database trait that matches the user traits l_1, ..., l_m
+ to which subarray j corresponds. kvalues is a list of the correlation
+ values linking trait to l_1, ..., l_m, so the length of kvalues is
+ the number of 1s in the binary representation of j (there must be
+ a better way to describe this length).
+
+ The return array is an array of 2-tuples. The first element of
+ each tuple is the index of the particular subarray, and the second
+ element is the subarray itself. The array is sorted in descending
+ order by the number of 1's in the binary representation of the
+ index so the first few subarrays are the ones that correspond to
+ the largest sets. Each subarray is then sorted by the average of
+ the magnitude of the individual correlation values.
+ """
+
+ kMin = p["threshold"]
+ traitArrays = {}
+
+ # TODO: Add Spearman support
+ freezeId = p["targetDatabaseId"]
+ if p["correlation"] == "pearson":
+ correlations = correlation.calcProbeSetPearsonMatrix(cursor, freezeId, traits) #XZ, 09/10/2008: add module name
+ else:
+ correlations = correlation.calcProbeSetSpearmanMatrix(freezeId, traits) #XZ, 09/10/2008: add module name
+
+ # now we test all of the correlations in bulk
+ test = numarray.absolute(correlations)
+ test = numarray.greater_equal(test, kMin)
+ test = test.astype(numarray.Int8)
+ #print test
+
+ db = trait.queryProbeSetTraits(cursor, freezeId) #XZ, 09/10/2008: add module name
+ for i in range(len(db)):
+ cIndex = 0
+ prods = []
+ for j in range(len(traits)):
+ if test[i,j] == 1:
+ cIndex += pow(2, j)
+ prods.append(correlations[i,j])
+ if cIndex != 0:
+ if not traitArrays.has_key(cIndex):
+ traitArrays[cIndex] = []
+
+ traitArrays[cIndex].append((db[i], prods))
+
+
+ # sort each inner list of traitArrays
+ # so the matched traits appear in descending order by the
+ # average magnitude of the correlation
+ def customCmp(traitPair, traitPair2):
+ magAvg1 = numarray.average(map(abs, traitPair[1]))
+ magAvg2 = numarray.average(map(abs, traitPair2[1]))
+
+ # invert the sign to get descending order
+ return -cmp(magAvg1, magAvg2)
+
+ for traitArray in traitArrays.values():
+ traitArray.sort(customCmp)
+
+ # sort the outer list of traitArrays
+ traitArrays2 = []
+ i = 0
+ for key in traitArrays.keys():
+ a = traitArrays[key]
+ if len(a) > 0:
+ traitArrays2.append((key,a,len(binaryDecompose(key)),
+ len(a)))
+
+ # we sort by the number of 1's in the binary output
+ # and then by the size of the list, both in descending order
+ def customCmp2(aL,bL):
+ a = -cmp(aL[2], bL[2])
+ if a == 0:
+ return -cmp(aL[3], bL[3])
+ else:
+ return a
+
+ traitArrays2.sort(customCmp2)
+
+ return traitArrays2
+
+def runCorrelations(p, strainCount, traits, db):
+ """
+ To run the correlations between the traits and the database.
+ This function computes a correlation coefficent between each
+ trait and every entry in the database, and partitions the database
+ into a disjoint array of arrays which it returns.
+
+ The length of the return array is 2^n, where n is the length of
+ the trait array. Which constitutent element a of the return array
+ a given trait ends up in is determined by the following formula
+ i = i_02^0 + ... + i_(n-1)2^(n-1)
+ where i_0 is 1 if corr(a,trait 0) >= threshold and 0 otherwise
+
+ Since most of the several thousand database traits will end up
+ with i=0, we don't return them, so the first element of the
+ return array will be empty.
+
+ A particular element of subarray j of the return array contains
+ a 2-tuple (trait,kvalues). The variable trait is obviously the
+ particular database trait that matches the user traits l_1, ..., l_m
+ to which subarray j corresponds. kvalues is a list of the correlation
+ values linking trait to l_1, ..., l_m, so the length of kvalues is
+ the number of 1s in the binary representation of j (there must be
+ a better way to describe this length).
+
+ The return array is an array of 2-tuples. The first element of
+ each tuple is the index of the particular subarray, and the second
+ element is the subarray itself. The array is sorted in descending
+ order by the number of 1's in the binary representation of the
+ index so the first few subarrays are the ones that correspond to
+ the largest sets. Each subarray is then sorted by the average of
+ the magnitude of the individual correlation values.
+ """
+ kMin = p["threshold"]
+ traitArrays = {}
+
+ # TODO: Add Spearman support
+ if p["correlation"] == "pearson":
+ correlations = correlation.calcPearsonMatrix(db, traits, strainCount) #XZ, 09/10/2008: add module name
+ else:
+ correlations = correlation.calcSpearmanMatrix(db, traits, strainCount) #XZ, 09/10/2008: add module name
+
+ # now we test all of the correlations in bulk
+ test = numarray.absolute(correlations)
+ test = numarray.greater_equal(test, kMin)
+ test = test.astype(numarray.Int8)
+ #print test
+
+
+ for i in range(len(db)):
+ cIndex = 0
+ prods = []
+ for j in range(len(traits)):
+ if test[i,j] == 1:
+ cIndex += pow(2, j)
+ prods.append(correlations[i,j])
+ if cIndex != 0:
+ if not traitArrays.has_key(cIndex):
+ traitArrays[cIndex] = []
+
+ traitArrays[cIndex].append((db[i], prods))
+
+ # sort each inner list of traitArrays
+ # so the matched traits appear in descending order by the
+ # average magnitude of the correlation
+ def customCmp(traitPair, traitPair2):
+ magAvg1 = numarray.average(map(abs, traitPair[1]))
+ magAvg2 = numarray.average(map(abs, traitPair2[1]))
+
+ # invert the sign to get descending order
+ return -cmp(magAvg1, magAvg2)
+
+ for traitArray in traitArrays.values():
+ traitArray.sort(customCmp)
+
+ # sort the outer list of traitArrays
+ traitArrays2 = []
+ i = 0
+ for key in traitArrays.keys():
+ a = traitArrays[key]
+ if len(a) > 0:
+ traitArrays2.append((key,a,len(binaryDecompose(key)),
+ len(a)))
+
+ # we sort by the number of 1's in the binary output
+ # and then by the size of the list, both in descending order
+ def customCmp2(aL,bL):
+ a = -cmp(aL[2], bL[2])
+ if a == 0:
+ return -cmp(aL[3], bL[3])
+ else:
+ return a
+
+ traitArrays2.sort(customCmp2)
+
+ return traitArrays2
+
+
+# XZ, 09/09/2008: In multiple trait correlation result page,
+# XZ, 09/09/2008: click "Download a text version of the above results in CSV format"
+
+# TraitCorrelationText: a class to display trait correlations
+# as textual output
+class TraitCorrelationText:
+ # build a text shell to describe the given trait correlations
+ # this method sets self.output; use str(self) to actually
+ # get the text page
+ #
+ # traits is a list of traits and traitArray is a
+ # list of 3-tuples: index, traits', garbage
+ # where index is a binary-encoded description of which subset of
+ # traits the list traits' matches
+ #
+ # traits' is a list of 3-tuples as well: trait, correlations, garbage
+ # where trait is a particular trait and correlations is a list of float
+ # correlations (matching traits above)
+ def __init__(self, p, traits, traitArray):
+ output = "Correlation Comparison\n"
+ output += "from WebQTL and the University of Tennessee Health Science Center\n"
+ output += "initiated at " + time.asctime(time.gmtime()) + " UTC\n\n"
+
+ output += self.showOptionPanel(p)
+ output += self.showSelectedTraits(traits)
+ output += self.showSummaryCorrelationResults(p, traits, traitArray)
+ output += self.showDetailedCorrelationResults(p, traits, traitArray)
+
+ self.output = output
+
+ # showOptionPanel: ParamDict -> string
+ # to display the options used to run this correlation
+ def showOptionPanel(self, params):
+ output = "Correlation Comparison Options:\n"
+ output += "Target database,%s\n" % params["targetDatabase"]
+ output += "Correlation type,%s\n" % params["correlationName"]
+ output += "Threshold,%f\n" % params["threshold"]
+ #output += "Subsets to Show,%d\n" % params["subsetCount"]
+ #output += "Traits to Show Per Subset,%d\n\n" % params["subsetSize"]
+ return output
+
+ # showSelectedTraits: (listof Trait) -> string
+ # to display the traits compared with the database
+ # note: we can't use tabular output because the traits could be of
+ # different types and produce different fields
+ def showSelectedTraits(self, traits):
+ output = "Selected Traits:\n"
+ for trait in traits:
+ output += '"' + trait.longName() + '"' + "\n"
+ output += "\n"
+ return output
+
+ # showSummaryCorrelationResults: ParamDict -> (listof Trait) ->
+ # TraitArray -> string
+ # see comment for __init__ for a description of TraitArray
+ #
+ # to show a summary (sets and sizes) of the correlation results
+ # as well as an X to indicate whether they will be included
+ # in the detailed output
+ def showSummaryCorrelationResults(self, p, traits, traitArray):
+ output = "Correlation Comparison Summary:\n"
+
+ #if p["subsetCount"] != -1:
+ # ourSubsetCount = min(p["subsetCount"], len(traitArray))
+ #else:
+
+ ourSubsetCount = len(traitArray)
+
+ displayDecomposition = binaryDecompose(p["displaySets"])
+ for j in range(ourSubsetCount):
+ i = traitArray[j][0]
+ traitSubarray = traitArray[j][1]
+ if len(traitSubarray) == 0:
+ continue
+
+ targetTraits = decomposeIndex(traits, i)
+ traitDesc = string.join(map(trait.Trait.shortName, targetTraits), # XZ, 09/10/2008: add module name
+ ", ")
+ if j in displayDecomposition:
+ checked = "X"
+ else:
+ checked = ""
+
+ output += '"%s","%s","%d"\n' % (checked, traitDesc, len(traitSubarray))
+
+ output += "\n"
+ return output
+
+ # showDetailedCorrelationResults: ParamDict -> (listof Trait) ->
+ # TraitArray -> string
+ #
+ # to show a detailed list of the correlation results; that is,
+ # to completely enumerate each subset of traitArray using the
+ # filtering parameters in p
+ def showDetailedCorrelationResults(self, p, traits, traitArray):
+ output = "Correlation Comparison Details:\n"
+ displayDecomposition = binaryDecompose(p["displaySets"])
+ displayDecomposition.sort()
+
+ def formatCorr(c):
+ return "%.4f" % c
+
+ for j in displayDecomposition:
+ i = traitArray[j][0]
+ traitSubarray = traitArray[j][1]
+
+ if len(traitSubarray) == 0:
+ continue
+
+ targetTraits = decomposeIndex(traits, i)
+ extraColumnHeaders = map(trait.Trait.shortName, targetTraits) # XZ, 09/10/2008: add module name
+ traitDesc = string.join(extraColumnHeaders, ", ")
+
+ #if(p["subsetSize"] != -1 and len(traitSubarray) > p["subsetSize"]):
+ # traitDesc += ",(showing top %s of %s)" % (p["subsetSize"],
+ # len(traitSubarray))
+ # traitSubarray = traitSubarray[0:p["subsetSize"]]
+
+ output += "%s\n" % traitDesc
+ output += traitSubarray[0][0].csvHeader([], extraColumnHeaders)
+ output += "\n"
+ for oneTrait, corr in traitSubarray:#XZ, 09/10/2008: change original variable name 'trait' to 'oneTrait'
+ corr = map(formatCorr, corr)
+ output += oneTrait.csvRow([], corr) + "\n"
+
+ output += "\n"
+
+ return output
+
+ # __str__ : string
+ # to return self.output as the string representation of this page
+ # self.output is built in __init__
+ def __str__(self):
+ return self.output
+
+# TraitCorrelationPage: a class to display trait correlations
+# for now this is just one HTML file, so we don't even write it
+# to a temporary file somewhere
+class TraitCorrelationPage(templatePage.templatePage):
+ """
+ Using the templatePage class, we build an HTML shell for
+ the core data here: the trait correlation lists.
+
+ 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, p, cursor, traits, traitArray, inbredSetName, txtFilename):
+
+ templatePage.templatePage.__init__(self, fd)
+
+ self.dict["title"] = "Correlation Comparison"
+ self.dict["basehref"] = ""
+ # NL: deleted js1 content part, since it has not been used in this project
+ self.dict["js1"] = ""
+ self.dict["js2"] = ""
+
+ body = "<td><h1>Correlation Comparison</h1>"
+ body += "<p>Run at %s UTC</p>" % time.asctime(time.gmtime())
+ body += """
+ <p>The correlation comparison tool identifies intersecting sets of traits that are
+correlated with your selections at a specified threshold. A correlation comparison
+involves the following steps:</p>
+<ol>
+<li><p>
+<b>Correlate:</b>
+Choose a <i>Target Database</i>, a <i>Correlation Type</i>, and a <i>Correlation
+Threshold</i>. For your initial correlation, leave <i>Number of Subsets to Show</i> and
+<i>Traits to Show per Subset</i> at their default values of 10. Using the Correlation
+Options panel, you can adjust the <i>Correlation Threshold</i>, <i>Number of Subsets to
+Show</i>, and <i>Traits to Show per Subset</i>.
+</p></li>
+
+<li><p>
+<b>Add to Collection:</b>
+You can use the check boxes in the <i>Correlation
+Comparison Details</i> panel and the buttons at the bottom of the page to add these
+results to your selections page for further analysis in WebQTL.
+</p></li>
+
+<li><p>
+<b>Filter:</b>
+Using the <i>Correlation Comparison Summary</i> panel, choose which
+subsets you would like to display for export. Note that if you change the
+parameters in the <i>Correlation Options</i> panel, you will need to re-apply your filter.
+</p></li>
+
+<li><p>
+<b>Export:</b>
+Once you are satisfied with your report, use the export link at
+the bottom of the page to save the report as a comma-separated (CSV) text file
+which you can then import into Excel or another tool. Note: the exported report
+will list all subsets in the summary view and only those traits in the subsets
+you have selected in the Filter step.
+</p></li>
+</ol>
+"""
+
+# body += """
+# <p>The correlation
+# comparison tool identifies the intersecting sets of traits that are
+# correlated with your selections. A correlation comparison involves
+# the following steps:</p>
+# <ol>
+# <li><p><b>Correlate:</b> Choose a <i>Target Database</i>, a <i>Correlation Type</i>, and a <i>Correlation Threshold</i>.
+# For the initial correlation, leave <i>Subsets to Show</i> and <i>Traits to Show per Subset</i>
+# at their default values of 10.</p></li>
+# <li><p><b>Refine Correlation:</b> Using the <i>Correlation Options</i> panel,
+# adjust the <i>Correlation Threshold</i>, <i>Subsets to Show</i>, and <i>Traits to
+# Show per Subset</i> until you have a reasonable number of traits.</p></li>
+# <li><p><b>Filter:</b> Using the <i>Correlation Comparison Summary</i> panel, choose which subsets you would
+# like to see. Note that if you change the parameters in the <i>Correlation Options</i> panel, you will
+# loose the filter you have selected.</p></li>
+# <li><p><b>Export:</b> Once you are satisfied with your report, use the export
+# link at the bottom of the page to save the report as a comma-separated (CSV) text file which
+# you can then import into Excel or another tool. Note: the exported report
+# will show all subsets in the summary view and all traits in each subset you have
+# selected in the Filter step.
+# <li><p><b>Shopping Cart:</b> In addition, you can use the
+# check boxes in the <i>Correlation Comparison Details</i> panel and the
+# buttons at the bottom of the page to add the traits you have found to the shopping cart.</p>
+# </li>
+# </ol>
+# """
+
+ body += self.showOptionPanel(p, cursor, inbredSetName)
+ body += self.showSelectedTraits(traits, p, inbredSetName)
+
+ if p["firstRun"] == 0:
+ body += self.showCorrelationResults(p, inbredSetName, traits, traitArray)
+
+ exportParams = copy.copy(p)
+ exportParams["outputType"] = "text"
+
+ body += ('''
+ <h2>Export these results</h2>
+ <p>
+ <a href="/image/%s">Download a text version of the above results in CSV format</a>. This text version differs from
+ the version you see on this page in two ways. First, the summary view shows all subsets. Second, the details
+ view shows all traits in the subsets that you have selected.
+ </p>
+ '''
+ % txtFilename)
+
+
+
+ body += "</td>"
+ self.dict["body"] = body
+
+
+ # showOptionPanel: ParamDict -> Cursor -> String -> String
+ # to build an option panel for the multitrait correlation
+ # we expect the database list to be a list of 2-tuples
+ # the first element of each tuple is the short name
+ # and the second element of the tuple is the long name
+ def showOptionPanel(self, params, cursor, inbredSetName):
+ output = '''
+ <h2>Correlation Options</h2>
+ <FORM METHOD="POST" ACTION="%s%s" ENCTYPE="multipart/form-data">
+ <INPUT TYPE="hidden" NAME="FormID" VALUE="compCorr2">
+ <input type="hidden" name="filename" value="%s">
+ <input type="hidden" name="firstRun" value="0">
+ <input type="hidden" name="progress" value="1">
+ <table>
+ <tr>
+ <td>Target Database:</td><td>
+ ''' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, params["filename"])
+
+ output += htmlModule.genDatabaseMenu(db = cursor,
+ public=0,
+ RISetgp = inbredSetName,
+ selectname="targetDatabase",
+ selected=params["targetDatabase"])
+ output += "</td></tr>"
+
+ corrSelected = ["",""]
+
+ if params["correlation"] == "pearson":
+ corrSelected[0] = "SELECTED"
+ else:
+ corrSelected[1] = "SELECTED"
+
+ output += ('''
+ <tr>
+ <td>Correlation Method:</td>
+ <td><select name="correlation">
+ <option value="pearson" %s>Pearson</option>
+ <!--<option value="spearman" %s>Spearman</option>-->
+ </select></td></tr>
+ ''' % (corrSelected[0], corrSelected[1]))
+ output += ('<tr><td>Correlation Threshold:</td><td><input name="threshold" value="%s" /></td></tr>'
+ % params["threshold"])
+ output += ('<tr><td>Subsets to Show (-1 to show all subsets):</td><td><input name="subsetCount" value="%s" /></td></tr>'
+ % params["subsetCount"])
+ output += ('<tr><td>Traits to Show per Subset (-1 to show all traits):</td><td><input name="subsetSize" value="%s" /></td></tr>'
+ % params["subsetSize"])
+
+ # a cosmetic change to hopefully make this form a bit easier to use
+# if params["firstRun"] == 1:
+# applyName = "Correlate"
+# else:
+# applyName = "Refine Correlation"
+
+ output += '''
+ <tr>
+ <td colspan="2"><input class="button" type="submit" value="Correlate" /></td>
+ </tr>
+ </table>
+ </form>
+ '''
+
+ return output
+
+ # showSelectedTraits: listof Trait -> string
+ # to show a list of the selected traits
+ def showSelectedTraits(self, traits, p, inbredSetName):
+ output = '''
+ <form action="%s%s" method="post" name="showDatabase">
+ <INPUT TYPE="hidden" NAME="FormID" VALUE="showDatabase">
+
+ <input type="hidden" name="incparentsf1" value="ON">
+ <input type="hidden" name="ShowStrains" value="ON">
+ <input type="hidden" name="ShowLine" value="ON">
+ <input type="hidden" name="database" value="">
+ <input type="hidden" name="ProbeSetID" value="">
+ <input type="hidden" name="RISet" value="%s">
+ <input type="hidden" name="CellID" value="">
+ <input type="hidden" name="database2" value="">
+ <input type="hidden" name="rankOrder" value="">
+ <input type="hidden" name="ProbeSetID2" value="">
+ <input type="hidden" name="CellID2" value="">
+ ''' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, inbredSetName)
+
+ output += "<h2>Selected Traits</h2>"
+ output += '<table cellpadding="2" cellspacing="0"><tr bgcolor="FFFFFF"><th>Database</th><th>Trait</th></tr>'
+ flip = 1
+ colors = ["FFFFFF", "cccccc"]
+
+ for trait in traits:
+ # we take advantage of the secret dbName attribute that
+ # loadDatabase fills in
+ descriptionString = trait.genHTML()
+ if trait.db.type == 'Publish' and trait.confidential:
+ descriptionString = trait.genHTML(privilege=self.privilege, userName=self.userName, authorized_users=trait.authorized_users)
+ output += '''
+ <tr bgcolor="%s"><td><a href="/dbdoc/%s.html">%s</a></td>
+ <td><a href="javascript:showDatabase2('%s', '%s', '')">%s</a></td>
+ </tr>
+ ''' % (colors[flip], trait.db.name, trait.db.name, trait.db.name, trait.name, descriptionString)
+ flip = not flip
+
+ output += "</table></form>"
+ return output
+
+
+ # showSummaryCorrelationResults
+ # show just the number of traits in each subarray
+ def showSummaryCorrelationResults(self, p, traits, traitArray):
+ output = '''
+ <form action="%s%s" method="post">
+ <INPUT TYPE="hidden" NAME="FormID" VALUE="compCorr2">
+ <input type="hidden" name="filename" value="%s">
+ <input type="hidden" name="firstRun" value="0">
+ <input type="hidden" name="progress" value="1">
+ <input type="hidden" name="correlation" value="%s">
+ <input type="hidden" name="threshold" value="%s">
+ <input type="hidden" name="rankOrder" value="">
+ <input type="hidden" name="subsetCount" value="%s">
+ <input type="hidden" name="subsetSize" value="%s">
+ <input type="hidden" name="targetDatabase" value="%s">
+ ''' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, p["filename"], p["correlation"], p["threshold"],
+ p["subsetCount"], p["subsetSize"], p["targetDatabase"])
+
+ output += '''
+ <table cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Trait Subsets</th>
+ <th colspan="2">Intersecting Set Size</th>
+ </tr>
+ '''
+ # figure out a scale for the summary graph
+ # for now we set max = 300 pixels wide
+ if p["subsetCount"] != -1:
+ ourSubsetCount = min(p["subsetCount"], len(traitArray))
+ else:
+ ourSubsetCount = len(traitArray)
+
+ screenWidth = 600
+ lengths = []
+ for j in range(ourSubsetCount):
+ lengths.append(len(traitArray[j][1]))
+ maxLength = max(lengths)
+
+ displayDecomposition = binaryDecompose(p["displaySets"])
+ flip = 0
+ colors = ["FFFFFF", "cccccc"]
+
+ for j in range(ourSubsetCount):
+ i = traitArray[j][0]
+ traitSubarray = traitArray[j][1]
+
+ if len(traitSubarray) == 0:
+ continue
+
+ targetTraits = decomposeIndex(traits, i)
+ traitDesc = string.join(map(webqtlTrait.displayName, targetTraits),
+ ", ")
+
+ if j in displayDecomposition:
+ checked = "CHECKED"
+ else:
+ checked = ""
+
+ barWidth = (len(traitSubarray) * screenWidth) / maxLength
+ output += ('''<tr bgcolor="%s">
+ <td><input type="checkbox" name="display%d" value="1" %s>%s</input></td>
+ <td>%s</td>
+ <td><img src="/images/blue.png" width="%d" height="25"></td></tr>'''
+ % (colors[flip], j, checked, traitDesc, len(traitSubarray), barWidth))
+ flip = not flip
+
+ output += '''
+ <tr>
+ <td colspan="3">
+ <input class="button" type="submit" value="Filter" /></td>
+ </tr>
+ </table></form>
+ '''
+ return output
+
+ # showDetailedCorrelationResults
+ # actually show the traits in each subarray
+ def showDetailedCorrelationResults(self, p, inbredSetName, traits,
+ traitArray):
+ output = "<h2>Correlation Comparison Details</h2>"
+
+ # the hidden form below powers all of the JavaScript links,
+ # the shopping cart links, and the correlation plot links
+
+ output += '''
+ <form action="%s%s" method="post">
+ <input type="hidden" name="database" value="%s">
+ <input type="hidden" name="FormID" value="showDatabase">
+ <input type="hidden" name="traitfile" value="">
+ <input type="hidden" name="incparentsf1" value="ON">
+ <input type="hidden" name="ShowStrains" value="ON">
+ <input type="hidden" name="ProbeSetID" value="">
+ <input type="hidden" name="ShowLine" value="ON">
+ <input type="hidden" name="RISet" value="%s">
+ <input type="hidden" name="CellID" value="">
+ <input type="hidden" name="database2" value="">
+ <input type="hidden" name="rankOrder" value="">
+ <input type="hidden" name="ProbeSetID2" value="">
+ <input type="hidden" name="CellID2" value="">
+ ''' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, p["targetDatabase"], inbredSetName)
+
+
+ displayDecomposition = binaryDecompose(p["displaySets"])
+
+ # necessary to ensure that subset order is the same in the
+ # summary and the detailed view
+ displayDecomposition.sort()
+
+ # here's a trick: the first trait we show must have the widest row because it correlates
+ # with the largest set of input traits
+ firstSubset = traitArray[displayDecomposition[0]]
+ firstTrait = firstSubset[1][0][0]
+ extraColumnCount = firstSubset[2]
+ totalColumnCount = 1 + len(firstTrait.row()) + extraColumnCount
+
+ output += "<table cellpadding=2 cellspacing=0>\n"
+ for j in displayDecomposition:
+ i = traitArray[j][0]
+ traitSubarray = traitArray[j][1]
+
+ # we don't display trait combinations for which there are
+ # no correlations
+ if len(traitSubarray) == 0:
+ continue
+
+ # generate a description of the traits that this particular array
+ # matches highly
+ targetTraits = decomposeIndex(traits, i)
+ extraColumnHeaders = map(webqtlTrait.displayName, targetTraits)
+ traitDesc = string.join(extraColumnHeaders, ", ")
+
+ # massage extraColumnHeaders so that they can be wrapped
+ for i in range(len(extraColumnHeaders)):
+ ech = extraColumnHeaders[i]
+ ech = ech.replace("-", " ")
+ ech = ech.replace("_", " ")
+ extraColumnHeaders[i] = ech
+
+ # pad extraColumnHeaders if we have less columns than the max
+ paddingNeeded = extraColumnCount - len(extraColumnHeaders)
+ if paddingNeeded > 0:
+ extraColumnHeaders.extend(paddingNeeded * ["&nbsp;"])
+
+ # we limit the output to the top ones
+ if(p["subsetSize"] != -1 and len(traitSubarray) > p["subsetSize"]):
+ traitDesc += " (showing top %s of %s)" % (p["subsetSize"], len(traitSubarray))
+ traitSubarray = traitSubarray[0:p["subsetSize"]]
+
+ # combine that description with actual database traits themselves
+ # and the correlation values
+ output += '<tr><td colspan="%d"><h3>%s</h3></td></tr>' % (totalColumnCount, traitDesc)
+ #output += '<h3>%s</h3>\n<table cellpadding=2 cellspacing=0>\n'% traitDesc
+
+ # we assume that every trait in traitSubarray is the same type
+ # of trait
+ flip = 0
+ colors = ["FFFFFF", "cccccc"]
+
+ output += traitSubarray[0][0].tableRowHeader(["&nbsp;"], extraColumnHeaders, colors[0])
+
+ for traitPair in traitSubarray:
+ corr = []
+ traitPair[0].dbName = p['targetDatabase']
+ trait = traitPair[0]
+
+ for i in range(len(traitPair[1])):
+ corrValue = traitPair[1][i]
+ corrPlotLink = ('''
+ <a href="javascript:showCorrelationPlot2(db='%s',ProbeSetID='%s',CellID='',db2='%s',ProbeSetID2='%s',CellID2='',rank='%s')">%.2f</a>
+ ''' % (p["targetDatabaseName"], trait.name, targetTraits[i].db.name, targetTraits[i].name, "0", corrValue))
+ corr.append(corrPlotLink)
+
+ corr.extend(paddingNeeded * ["&nbsp;"])
+
+ checkbox = ('<INPUT TYPE="checkbox" NAME="searchResult" VALUE="%s:%s" />'
+ % (p["targetDatabaseName"], trait.name))
+ flip = not flip
+ output += traitPair[0].tableRow([checkbox], corr, colors[flip])
+
+ #output += "</table>"
+ i += 1
+ output += '<tr><td colspan="%d">&nbsp;</td></tr>' % totalColumnCount
+
+ output += "</table>"
+
+ # print form buttons if there were checkboxes above
+ output += '''
+ <div align="left">
+ <INPUT TYPE="button" NAME="addselect" CLASS="button" VALUE="Add to Collection"
+ onClick="addRmvSelection('%s',this.form, 'addToSelection');">
+ <INPUT TYPE="button" NAME="selectall" CLASS="button" VALUE="Select All" onClick="checkAll(this.form);">
+ <INPUT TYPE="reset" CLASS="button" VALUE="Select None">
+ </div>
+ </form>
+ ''' % inbredSetName
+
+ return output
+
+ # showCorrelationResults: ParamDict -> listof Trait -> tupleof (int,arrayof trait) -> String
+ # to build an output display for the multitrait correlation results
+ def showCorrelationResults(self, p, inbredSetName, traits, traitArray):
+ output = '''
+ <h2>Correlation Comparison Summary</h2>
+ <p>
+ %s correlations were computed for each of the selected traits with each trait in
+ the <a href="/dbdoc/%s.html">%s</a> database.
+ Subsets of database traits for which correlations were higher than %s
+ or lower than -%s are shown below based on which traits
+ they correlated highly with. The top %s subsets, ranked by the number of input traits that
+ they correspond with, are shown, and at most %s traits in each subset are shown. </p>
+ ''' % (p["correlationName"],
+ p["targetDatabase"], p["targetDatabaseName"],
+ p["threshold"], p["threshold"], p["subsetCount"],
+ p["subsetSize"])
+
+
+ totalTraits = 0
+ for j in range(len(traitArray)):
+ totalTraits += len(traitArray[j][1])
+
+ if totalTraits == 0:
+ output += """
+ <p>
+ No shared corrrelates were found with your given traits at this
+ threshold. You may wish to lower the correlation threshold or choose different traits.
+ </p>
+ """
+ else:
+ output += self.showSummaryCorrelationResults(p, traits, traitArray)
+ output += self.showDetailedCorrelationResults(p, inbredSetName,
+ traits, traitArray)
+
+ return output
+
+# decomposeIndex: (listof Trait) -> Int ->
+# (listof Trait)
+# to use i to partition T into a sublist
+# each bit in i controls the inclusion or exclusion of a trait
+def decomposeIndex(traits, i):
+ targetTraits = []
+
+ for j in range(len(traits)):
+ # look, mom, a bitwise and!
+ # expression below tests whether the jth bit is
+ # set in i
+ # see runCorrelation for how we decompose the
+ # array index
+ if (i & pow(2,j)) == pow(2,j):
+ targetTraits.append(traits[j])
+
+ return targetTraits
+
+# binaryDecompose: int -> (listof int)
+# to decompose a number into its constituent powers of 2
+# returns a list of the exponents a_1...a_n such that the input m
+# is m = 2^a_1 + ... + 2^a_n
+def binaryDecompose(n):
+ if n == 0:
+ return []
+
+ # we start with the highest power of 2 <= this number
+ # and work our way down, subtracting powers of 2
+ start = long(math.floor(math.log(n)/math.log(2)))
+
+ exponents = []
+ while start >= 0:
+ if n >= long(math.pow(2, start)):
+ n -= math.pow(2,start)
+ exponents.append(start)
+ start -= 1
+ return exponents
+
+# powerOf : int -> int -> boolean
+# to determine whether m is a power of n;
+# more precisely, whether there exists z in Z s.t.
+# n^z = m
+def powerOf(m, n):
+ trialZ = math.floor(math.log(m)/math.log(n))
+ return pow(n,trialZ) == m
+
+
+class compCorrPage(templatePage.templatePage):
+ def __init__(self,fd):
+ templatePage.templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ cursor = self.cursor
+ params = buildParamDict(cursor, fd)
+
+ # get the input data
+ inbredSetName, traits = readInputFile(cursor, RootDir + params["filename"])
+
+ # and what we are comparing the data to
+ dbTraits = []
+ if params["targetDatabaseType"] != "ProbeSet":
+ dbTraits = loadDatabase(cursor, params)
+
+
+ # run the comparison itself
+ strainCount = trait.queryStrainCount(cursor) # XZ, 09/10/2008: add module name
+ if params["targetDatabaseType"] == "ProbeSet":
+ results = runProbeSetCorrelations(cursor, params, traits)
+ else:
+ results = runCorrelations(params, strainCount, traits, dbTraits)
+
+ # try to be smart about what to output:
+ # we want to limit the number of traits shown, at least initially
+ # and since traitArray is already sorted with most interesting
+ # subsets first, we simply pick up the first 500 or so traits
+ # that we find
+ if params["displaySets"] == 0:
+ selectedTraits = 0
+ for j in range(len(results)):
+ #print "Scanning subarray %d" % j
+ if selectedTraits <= 200:
+ params["displaySets"] += pow(2, j)
+ selectedTraits += len(results[j][1])
+
+ traitList = []
+ for oneTrait in traits: # XZ, 09/10/2008: change the original variable name 'trait' to 'oneTrait'
+ traitName = oneTrait.dbName+'::'+oneTrait.name # XZ, 09/10/2008: change the original variable name 'trait' to 'oneTrait'
+ aTrait = webqtlTrait(cursor=self.cursor, fullname=traitName)
+ traitList.append(aTrait)
+
+ # and generate some output
+ txtOutputFilename = tempfile.mktemp()
+ txtOutputHandle = open(txtOutputFilename, "w")
+ txtOutput = TraitCorrelationText(params, traits, results)
+ txtOutputHandle.write(str(txtOutput))
+ txtOutputHandle.close()
+ txtOutputFilename = os.path.split(txtOutputFilename)[1]
+
+ self.dict['body'] = TraitCorrelationPage(fd, params, cursor, traitList,
+ results, inbredSetName,
+ txtOutputFilename).dict['body']
diff --git a/web/webqtl/compareCorrelates/trait.py b/web/webqtl/compareCorrelates/trait.py
new file mode 100755
index 00000000..ff1f8119
--- /dev/null
+++ b/web/webqtl/compareCorrelates/trait.py
@@ -0,0 +1,1074 @@
+#Trait.py
+#
+#--Individual functions are already annotated, more or less.
+#
+#Classes:
+#RawPoint
+#Trait
+#ProbeSetTrait
+#GenotypeTrait
+#PublishTrait
+#TempTrait
+#-KA
+
+# trait.py: a data structure to represent a trait
+import time
+import string
+
+CONFIG_pubMedLinkURL = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=PubMed&list_uids=%s&dopt=Abstract"
+
+# RawPoint: to store information about the relationship between two particular
+# traits
+# RawPoint represents directly the input file
+class RawPoint:
+ def __init__(self, i, j):
+ self.i = i
+ self.j = j
+
+ def __eq__(self, other):
+ return (self.i == other.i and
+ self.j == other.j and
+ self.spearman == other.spearman and
+ self.pearson == other.pearson)
+
+ def __str__(self):
+ return "(%s,%s,%s,%s)" % (self.i, self.j, self.spearman, self.pearson)
+
+def tdEscapeList(cols, align="left"):
+ """
+ A helper function used by tableRow
+ in Trait that will convert a list of strings into a set of
+ table cells enclosed by <td>%s</td> tags
+ """
+ html = ""
+ for col in cols:
+ html += '<td style="text-align: %s">%s</td>' % (align, col)
+ return html
+
+def thEscapeList(cols):
+ """
+ A helper function used by tableRowHeader
+ in Trait that will convert a list of strings into a set of
+ table cells enclosed by <td>%s</td> tags
+ """
+ html = ""
+ for col in cols:
+ html += "<th>%s</th>" % col
+ return html
+
+def commaEscapeList(cols):
+ """
+ A helper function used by csvHeader and csvRow.
+ Really it's just a wrapper for string.join
+ """
+ return '"' + string.join(cols, '","') + '"'
+
+
+class Trait:
+ """
+ A trait represents an attribute of an object. In the WebQTL database, traits are stored
+ as ProbeSets; that is, the average values of a set of probes are stored.
+ """
+ def __init__(self, id="", name="", description="", symbol="", href=""):
+ self.id = id
+ self.name = name
+ self.dbName = ""
+ self.symbol = symbol
+ self.href = href
+ self.strainData = {}
+
+ def populateDataId(self, cursor, freezeId):
+ """
+ Retrieve the dataId for trait data corresponding to the given database
+ The way to do this depends on the particular type of trait, so we leave implementation
+ to subclasses.
+ """
+ raise NotImplementedError
+
+ def populateStrainData(self, cursor):
+ """
+ Load this trait full of train data corresponding to the data id
+ The data id can either come from populateDataId
+ or can be set manually by the user of this class.
+ Xiaodong added: The way to do this depends on the particular type of trait,
+ so we leave implementation to subclasses.
+
+ """
+ raise NotImplementedError
+
+ def shortName(self):
+ """
+ To return a short name for this trait; this name should be
+ appropriate for a row or column title
+ """
+ return self.name
+
+ def nameNoDB(self):
+ """
+ To return only the short name without the database attached
+ """
+ strArray = self.shortName().split('::')
+
+ return strArray[1]
+
+ def datasetName(self):
+ """
+ To return only the name of the dataset
+ """
+ strArray = self.shortName().split('::')
+
+ return strArray[0].strip()
+
+ def longName(self):
+ """
+ To return a long name for this trait; this name should be
+ appropriate for a key to a table
+ """
+ return self.shortName()
+
+ def __str__(self):
+ return self.shortName()
+
+ def tableRowHelper(self, beforeCols, afterCols, color, thisRow):
+ """
+ tableRowHelper: (arrayof String) -. String
+ To generate a table row to represent this object, appending
+ the additional information in beforeCols and afterCols
+ to the beginning and the end
+ """
+ thisRow[0] = '<a href="%s">%s</a>' % (self.traitInfoLink(),
+ self.name)
+ html = '<tr bgcolor="%s">' % color
+ html += tdEscapeList(beforeCols + thisRow)
+ html += tdEscapeList(afterCols, align="right")
+ html += "</tr>"
+
+ return html
+
+
+ def header(self):
+ """
+ header: (listof String)
+ To generate a list of strings describing each piece of data
+ returned by row
+ """
+ raise NotImplementedError
+
+ def row(self):
+ """
+ row: (listof String)
+ To generate a list of strings describing this object. The
+ elements of this list should be described by header()
+ """
+ raise NotImplementedError
+
+ def tableRowHeader(self, beforeCols, afterCols, color):
+ """
+ tableRowHeader: (arrayof String) -> (arrayof String) -> String
+ To generate a table row header to represent this object,
+ appending the additional information in beforeCols and
+ afterCols to the beginning and end
+ """
+ html = '<tr bgcolor="%s">' % color
+ html += thEscapeList(beforeCols + self.header() +
+ afterCols)
+ html += "</tr>"
+ return html
+
+ def csvHeader(self, beforeCols, afterCols):
+ return commaEscapeList(beforeCols + self.header() + afterCols)
+
+ def csvRow(self, beforeCols, afterCols):
+ return commaEscapeList(beforeCols + self.row() + afterCols)
+
+
+ def traitInfoLink(self):
+ """
+ To build a trait info link to show information about this
+ trait. We assume that the database attribute is properly set
+ on the hidden form on the page where this link will go.
+ """
+ return "javascript:showDatabase2('%s','%s','')" % (self.dbName, self.name)
+
+# ProbeSetTrait: a trait with data from a probeset
+class ProbeSetTrait(Trait):
+ def __init__(self, id="", name="", description="", symbol="", href="",
+ chromosome="", MB="", GeneId=""):
+ Trait.__init__(self, id=id, name=name, href=href)
+ self.description = description
+ self.symbol = symbol
+ self.chromosome = chromosome
+ self.MB = MB
+ self.GeneId = GeneId
+
+ def populateDataId(self, cursor, freezeId):
+ """
+ Look up the data id for this trait given which
+ freeze it came from.
+ """
+ cursor.execute('''
+ SELECT
+ ProbeSetXRef.DataId
+ FROM
+ ProbeSetXRef
+ WHERE
+ ProbeSetId = %s AND
+ ProbeSetFreezeId = %s
+ ''' % (self.id, freezeId))
+
+ # we hope that there's only one record here
+ row = cursor.fetchone()
+ self.dataId = row[0]
+
+ #XZ, 03/03/2009: Xiaodong implemented this fuction
+ def populateStrainData(self, cursor):
+ cursor.execute('''
+ SELECT
+ ProbeSetData.StrainId,
+ ProbeSetData.value
+ FROM
+ ProbeSetData
+ WHERE
+ ProbeSetData.Id = %s''' % self.dataId)
+ for row in cursor.fetchall():
+ self.strainData[int(row[0])] = float(row[1])
+
+
+ def shortName(self):
+ """
+ An improved string method that uses the gene symbol where
+ we have it
+ """
+ if self.symbol != "":
+ return self.symbol
+ else:
+ return Trait.shortName(self)
+
+ def longName(self):
+ """
+ We use several bits of genetic information to give
+ useful information about this trait and where it is
+ """
+ if self.chromosome != "":
+ chrPart = " (%s on Chr %s @ %s Mb)" % (self.symbol,
+ self.chromosome,
+ self.MB)
+ else:
+ chrPart = ""
+
+ return "%s%s: %s" % (self.name, chrPart, self.description)
+
+ def header(self):
+ return ["Name", "Symbol", "Description",
+ "Chr", "Position (Mb)"]
+
+ def row(self):
+ if type(self.MB) is float:
+ MB = "%.2f" % self.MB
+ else:
+ MB = ""
+
+ return [self.name, self.symbol, self.description,
+ self.chromosome, MB]
+
+ def tableRow(self, beforeCols, afterCols, color):
+ """
+ tableRow: (arrayof String) -> (arrayof String) -> String
+ To generate a table row to represent this object, appending
+ the additional information in beforeCols and afterCols to the
+ beginning and end
+ """
+ thisRow = self.row()
+
+ # trim description
+ if len(thisRow[2]) > 20:
+ thisRow[2] = thisRow[2][:20] + "..."
+
+ # add NCBI info link
+ thisRow[1] = self.ncbiInfoLink()
+
+ return self.tableRowHelper(beforeCols, afterCols, color,
+ thisRow)
+
+
+ def ncbiInfoLink(self):
+ """
+ ncbiInfoLink :: String
+ To generate an NCBI info link for this trait. If we have a GeneId,
+ then we can go straight to the gene. If not, then we generate a search
+ link based on the gene symbol. If we have none of them, then we don't
+ generate a link at all.
+ """
+ if self.GeneId != "":
+ cmd = "cmd=Retrieve&dopt=Graphics&list_uids=%s" % self.GeneId
+ elif self.symbol != "":
+ cmd = "cmd=Search&term=%s" % self.symbol
+ else:
+ return ""
+
+ return '''
+ <a target="_new"
+ href="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&%s">
+ %s</a> ''' % (cmd, self.symbol)
+
+
+# GenotypeTrait: a trait with data from the genotype
+class GenotypeTrait(Trait):
+ def __init__(self, id="", name="", href="", chromosome="", MB=""):
+ Trait.__init__(self, id=id, name=name, href=href)
+ self.chromosome = chromosome
+ self.MB = MB
+
+ def populateDataId(self, cursor, freezeId):
+ """
+ Look up the data id for this trait from the
+ genotype.
+ """
+ cursor.execute('''
+ SELECT
+ GenoXRef.DataId
+ FROM
+ GenoXRef
+ WHERE
+ GenoId = %s AND
+ GenoFreezeId = %s
+ ''' % (self.id, freezeId))
+
+ # we hope that there's only one record here
+ row = cursor.fetchone()
+ self.dataId = row[0]
+
+ #XZ, 03/03/2009: Xiaodong implemented this fuction
+ def populateStrainData(self, cursor):
+ cursor.execute('''
+ SELECT
+ GenoData.StrainId,
+ GenoData.value
+ FROM
+ GenoData
+ WHERE
+ GenoData.Id = %s''' % self.dataId)
+ for row in cursor.fetchall():
+ self.strainData[int(row[0])] = float(row[1])
+
+ def header(self):
+ return ["Locus", "Chr", "Position (Mb)"]
+
+ def row(self):
+ return [self.name, self.chromosome, "%.3f" % self.MB]
+
+ def tableRow(self, beforeCols, afterCols, color):
+ return self.tableRowHelper(beforeCols, afterCols, color, self.row())
+
+# PublishTrait: a trait with data from publications
+class PublishTrait(Trait):
+ def __init__(self, id="", name="", href="", authors="", title="",
+ phenotype="", year=""):
+ Trait.__init__(self, id=id, name=name, href=href)
+ self.authors = authors
+ self.title = title
+ self.phenotype = phenotype
+ self.year = year
+
+ def populateDataId(self, cursor, freezeId):
+ """
+ Look up the data id for this trait from the
+ published set. For the moment, we assume that there's
+ only one publish freeze.
+ """
+ cursor.execute('''
+ SELECT
+ PublishXRef.DataId
+ FROM
+ PublishXRef, PublishFreeze
+ WHERE
+ PublishFreeze.Id = %s AND
+ PublishFreeze.InbredSetId = PublishXRef.InbredSetId AND
+ PublishXRef.Id = %s
+ ''' % (freezeId, self.id))
+
+ # we hope that there's only one record here
+ row = cursor.fetchone()
+ self.dataId = row[0]
+
+ #XZ, 03/03/2009: Xiaodong implemented this fuction
+ def populateStrainData(self, cursor):
+ cursor.execute('''
+ SELECT
+ PublishData.StrainId,
+ PublishData.value
+ FROM
+ PublishData
+ WHERE
+ PublishData.Id = %s''' % self.dataId)
+ for row in cursor.fetchall():
+ self.strainData[int(row[0])] = float(row[1])
+
+
+ def longName(self):
+ """
+ A more intelligent string function that uses
+ information about the publication from which this trait came
+ """
+ return "%s: %s by %s" % (self.name, self.title, self.authors)
+
+ def header(self):
+ return ["Record", "Phenotype", "Authors", "Year", "URL"]
+
+ def row(self):
+ return [self.name,
+ self.phenotype,
+ self.authors,
+ str(self.year),
+ ""]
+
+ def tableRow(self, beforeCols, afterCols, color):
+ """
+ tableRow: (arrayof String) -> (arrayof String) -> String
+ To generate a table row to represent this object, appending
+ the additional information in beforeCols and afterCols to the
+ beginning and end
+ """
+ thisRow = self.row()
+
+ # for multiple authors, use "et. al" after first two
+ authors = thisRow[2].split(",")
+ if len(authors) > 2:
+ thisRow[2] = string.join(authors[:2], ",") + ", et al"
+
+ # clip phenotype to 20 chars
+ if len(thisRow[1]) > 20:
+ thisRow[1] = thisRow[1][:20] + "..."
+
+ # add Pub Med URL
+ thisRow[4] = '<a href="%s" target="_new">Pub Med</a>' % (CONFIG_pubMedLinkURL % self.href)
+
+ return self.tableRowHelper(beforeCols, afterCols, color,
+ thisRow)
+
+
+# TempTrait: a trait with data generate by user and stored in temp table
+class TempTrait(Trait):
+ def __init__(self, id="", name="", href="", description=""):
+ Trait.__init__(self, id=id, name=name, href=href)
+ self.description = description
+
+ def populateDataId(self, cursor, freeezeId):
+ """
+ Look up the data id for this trait from the Temp table, freezeId isn't used,
+ it just for fixing the inherit
+ """
+ cursor.execute('''
+ SELECT
+ DataId
+ FROM
+ Temp
+ WHERE
+ Id=%s
+ ''' % (self.id))
+
+ # we hope that there's only one record here
+ row = cursor.fetchone()
+ self.dataId = row[0]
+
+ #XZ, 03/03/2009: Xiaodong implemented this fuction
+ def populateStrainData(self, cursor):
+ cursor.execute('''
+ SELECT
+ TempData.StrainId,
+ TempData.value
+ FROM
+ TempData
+ WHERE
+ TempData.Id = %s''' % self.dataId)
+ for row in cursor.fetchall():
+ self.strainData[int(row[0])] = float(row[1])
+
+
+ def row(self):
+ return [self.id,
+ self.name,
+ self.description,
+ ""]
+
+
+ def longName(self):
+ """
+ For temp trait, the description always contents whole useful information
+ """
+ return self.description
+
+
+# queryGenotypeTraitByName : Cursor -> string -> GenotypeTrait
+def queryGenotypeTraitByName(cursor, speciesId, name):
+ qry = '''
+ SELECT
+ Geno.Id,
+ Geno.Name,
+ Geno.Chr,
+ Geno.Mb
+ FROM
+ Geno
+ WHERE
+ Geno.SpeciesId = %s and Geno.Name = "%s" ''' % (speciesId, name)
+
+ cursor.execute(qry)
+ row = cursor.fetchone()
+ return GenotypeTrait(id=row[0], name=row[1],
+ chromosome=row[2], MB=row[3])
+
+# queryPublishTraitByName : Cursor -> string -> PublishTrait
+def queryPublishTraitByName(cursor, freezeId, name):
+ qry = '''
+ SELECT
+ PublishXRef.Id,
+ Phenotype.Id,
+ Publication.Authors,
+ Publication.Title,
+ Publication.Year,
+ Publication.PubMed_ID
+ FROM
+ Publication, PublishXRef, Phenotype, PublishFreeze
+ WHERE
+ PublishFreeze.Id = %s AND
+ PublishFreeze.InbredSetId = PublishXRef.InbredSetId AND
+ PublishXRef.Id = %s AND
+ PublishXRef.PublicationId = Publication.Id AND
+ PublishXRef.PhenotypeId = Phenotype.Id
+ ''' % (freezeId, name)
+
+ cursor.execute(qry)
+ if cursor.rowcount == 0:
+ return None
+ else:
+ row = cursor.fetchone()
+
+ return PublishTrait(id=row[0], name='%s'%row[0],
+ authors=row[2], title=row[3],
+ year=row[4], href=row[5])
+
+
+def queryTempTraitByName(cursor, name):
+ name=name.strip()
+ qry = '''
+ SELECT
+ Temp.Id,
+ Temp.Name,
+ Temp.description
+ FROM
+ Temp
+ WHERE
+ Temp.Name= "%s"
+ ''' % (name)
+
+ cursor.execute(qry)
+ if cursor.rowcount == 0:
+ return None
+ else:
+ row = cursor.fetchone()
+ return TempTrait(id=row[0], name=row[1], description=row[2], href='')
+
+# queryPopulatedProbeSetTraits: Cursor -> Integer -> dictof Trait
+# to retrieve an entire probeset fully populated with data
+# this query can take 15+ sec the old way (22,000 traits * 35 strains = half
+# a million records)
+# so we ask for the data in bulk
+#
+# cursor should be SSCursor for MySQL so rows are stored on the server side
+# and tuples are used
+# we explicitly close the cursor here as well
+#XZ, 03/04/2009: It seems to me that this function is never be executed.
+#XZ: Although it can be called from multitrait.loadDatabase,
+#XZ: but the loadDatabase function will not be called
+#XZ: if the targetDatabaseType is probeset.
+#XZ: The probeset traits of target database are retrieved by execute
+#XZ: queryPopulatedProbeSetTraits2 from correlation.calcProbeSetPearsonMatrix
+def queryPopulatedProbeSetTraits(cursor, freezeId):
+ step1 = time.time()
+ traits = queryProbeSetTraits(cursor, freezeId)
+ traitDict = {}
+ for trait in traits:
+ traitDict[trait.id] = trait
+
+ step2 = time.time()
+ print
+ #XZ, 03/04/2009: Xiaodong changed Data to ProbeSetData
+ cursor.execute('''
+ SELECT
+ ProbeSetXRef.ProbeSetId,
+ ProbeSetData.StrainId,
+ ProbeSetData.value
+ FROM
+ ProbeSetXRef
+ Left Join ProbeSetData ON
+ ProbeSetXRef.DataId = ProbeSetData.Id
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = %s
+ ''' % freezeId)
+
+ step3 = time.time()
+ totalrows = 0
+ somerows = cursor.fetchmany(1000)
+ while len(somerows) > 0:
+ totalrows += len(somerows)
+ for row in somerows:
+ # this line of code can execute more than one million times
+ traitDict[row[0]].strainData[int(row[1])] = row[2]
+ somerows = cursor.fetchmany(1000)
+
+ #cursor.close()
+ step4 = time.time()
+
+ time1 = step2 - step1
+ time2 = step3 - step2
+ time3 = step4 - step3
+ time4 = step4 - step1
+ #print "%f %f %f %f %d rows" % (round(time1, 2),
+ # round(time2, 2),
+ # round(time3, 2),
+ # round(time4, 2),
+ # totalrows)
+ #print "Fetched %d traits" % len(traits)
+ return traits
+
+
+# queryPopulatedProbeSetTraits2: Cursor -> Integer -> dictof Trait
+# to retrieve probeset fully populated whose ProbeSetId in a range
+# a special ProbeSetId with data
+# this query can take 15+ sec the old way (22,000 traits * 35 strains = half
+# a million records)
+# so we ask for the data in bulk
+#
+# cursor should be SSCursor for MySQL so rows are stored on the server side
+# and tuples are used
+# we explicitly close the cursor here as well
+def queryPopulatedProbeSetTraits2(cursor, freezeId, ProbeSetId1, ProbeSetId2):
+ step1 = time.time()
+ traits = queryProbeSetTraits2(cursor, freezeId, ProbeSetId1, ProbeSetId2)
+ traitDict = {}
+ for trait in traits:
+ traitDict[trait.id] = trait
+
+ step2 = time.time()
+ print
+ #XZ, 03/04/2009: Xiaodong changed Data to ProbeSetData
+ cursor.execute('''
+ SELECT
+ ProbeSetXRef.ProbeSetId,
+ ProbeSetData.StrainId,
+ ProbeSetData.value
+ FROM
+ ProbeSetXRef
+ Left Join ProbeSetData ON
+ ProbeSetXRef.DataId = ProbeSetData.Id
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = %s AND
+ ProbeSetXRef.ProbeSetId >= %s AND
+ ProbeSetXRef.ProbeSetId <= %s
+ ''' % (freezeId, ProbeSetId1, ProbeSetId2))
+
+ step3 = time.time()
+ totalrows = 0
+ somerows = cursor.fetchmany(1000)
+ while len(somerows) > 0:
+ totalrows += len(somerows)
+ for row in somerows:
+ # this line of code can execute more than one million times
+ traitDict[row[0]].strainData[int(row[1])] = row[2]
+ somerows = cursor.fetchmany(1000)
+
+ #cursor.close()
+ step4 = time.time()
+
+ time1 = step2 - step1
+ time2 = step3 - step2
+ time3 = step4 - step3
+ time4 = step4 - step1
+ #print "%f %f %f %f %d rows" % (round(time1, 2),
+ # round(time2, 2),
+ # round(time3, 2),
+ # round(time4, 2),
+ # totalrows)
+ #print "Fetched %d traits" % len(traits)
+ return traits
+
+
+# def noneFilter : string or none -> string
+# to replace a possible None by an empty string
+def noneFilter(x):
+ if x is None:
+ return ""
+ else:
+ return x
+
+# queryProbeSetTraits: Cursor -> Integer -> dictof Trait
+def queryProbeSetTraits(cursor, freezeId):
+ """
+ To locate all of the traits in a particular probeset
+ """
+ qry = '''
+ SELECT
+ ProbeSet.Id,
+ ProbeSet.Name,
+ ProbeSet.description,
+ ProbeSet.symbol,
+ ProbeSet.Chr,
+ ProbeSet.Mb,
+ ProbeSet.GeneId,
+ ProbeSetXRef.DataId
+ FROM
+ ProbeSet,
+ ProbeSetXRef
+ WHERE
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetXRef.ProbeSetFreezeId = %s
+ ORDER BY ProbeSet.Id
+ ''' % freezeId
+
+ cursor.execute(qry)
+ rows = cursor.fetchall()
+ traits = []
+
+ for row in rows:
+ row = map(noneFilter, row)
+ trait = ProbeSetTrait(id=row[0], name=row[1],
+ description=row[2],
+ chromosome=row[4],
+ MB=row[5],
+ symbol=row[3],
+ GeneId=row[6])
+ trait.dataId = row[7]
+ traits.append(trait)
+
+ return traits
+
+
+# queryProbeSetTraits2: Cursor -> Integer -> dictof Trait
+def queryProbeSetTraits2(cursor, freezeId, ProbeSetId1, ProbeSetId2):
+ """
+ To locate all of the traits in a particular probeset
+ """
+ qry = '''
+ SELECT
+ ProbeSet.Id,
+ ProbeSet.Name,
+ ProbeSet.description,
+ ProbeSet.symbol,
+ ProbeSet.Chr,
+ ProbeSet.Mb,
+ ProbeSet.GeneId,
+ ProbeSetXRef.DataId
+ FROM
+ ProbeSet,
+ ProbeSetXRef
+ WHERE
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetXRef.ProbeSetFreezeId = %s AND
+ ProbeSet.Id >= %s AND
+ ProbeSet.Id <= %s
+ ORDER BY ProbeSet.Id
+ ''' % (freezeId, ProbeSetId1, ProbeSetId2)
+
+ cursor.execute(qry)
+ rows = cursor.fetchall()
+ traits = []
+
+ for row in rows:
+ row = map(noneFilter, row)
+ trait = ProbeSetTrait(id=row[0], name=row[1],
+ description=row[2],
+ chromosome=row[4],
+ MB=row[5],
+ symbol=row[3],
+ GeneId=row[6])
+ trait.dataId = row[7]
+ traits.append(trait)
+
+ return traits
+
+
+# queryPublishTraits : Cursor -> arrayof Trait
+def queryPublishTraits(cursor, freezeId):
+ """
+ To locate all published traits
+ """
+ qry = '''
+ SELECT
+ Publication.Id,
+ Publication.Name,
+ Publication.PhenoType,
+ Publication.Authors,
+ Publication.Title,
+ Publication.Year,
+ Publication.PubMed_ID,
+ PublishXRef.DataId
+ FROM
+ Publication,
+ PublishXRef
+ WHERE
+ PublishXRef.PublishFreezeId = %s AND
+ PublishXRef.PublishId = Publication.Id
+ ''' % freezeId
+
+ qry = '''
+ SELECT
+ Publication.Id,
+ PublishXRef.Id,
+ Phenotype.Pre_publication_description,
+ Phenotype.Post_publication_description,
+ Publication.Authors,
+ Publication.Title,
+ Publication.Year,
+ Publication.PubMed_ID,
+ PublishXRef.DataId
+ FROM
+ Publication, PublishXRef, Phenotype, PublishFreeze
+ WHERE
+ PublishFreeze.Id = %s AND
+ PublishFreeze.InbredSetId = PublishXRef.InbredSetId AND
+ PublishXRef.PublicationId = Publication.Id AND
+ PublishXRef.PhenotypeId = Phenotype.Id
+ ''' % freezeId
+ cursor.execute(qry)
+ rows = cursor.fetchall()
+ traits = []
+ for row in rows:
+ PhenotypeString = row[3]
+ if not row[7] and row[2]:
+ PhenotypeString = row[2]
+ trait = PublishTrait(id=row[0], name= '%s' %row[1],
+ phenotype=PhenotypeString,
+ authors=row[4],
+ title=row[5],
+ year=row[6],
+ href=row[7])
+ trait.dataId = row[8]
+ traits.append(trait)
+
+ return traits
+
+# queryGenotypeTraits : Cursor -> arrayof Trait
+def queryGenotypeTraits(cursor, freezeId):
+ """
+ To locate all traits in the genotype
+ """
+ qry = '''
+ SELECT
+ Geno.Id,
+ Geno.Name,
+ Geno.Chr,
+ GenoXRef.DataId,
+ Geno.Mb
+ FROM
+ Geno,
+ GenoXRef
+ WHERE
+ GenoXRef.GenoId = Geno.Id
+ AND GenoXRef.GenoFreezeId = %s
+ ''' % freezeId
+ cursor.execute(qry)
+ rows = cursor.fetchall()
+ traits = []
+
+ for row in rows:
+ trait = GenotypeTrait(id=row[0], name=row[1],
+ chromosome=row[2], MB=row[4])
+ trait.dataId = row[3]
+ traits.append(trait)
+
+ return traits
+
+# queryProbeSetTraitByName : Cursor -> string -> Trait
+# to find a particular trait given its name
+def queryProbeSetTraitByName(cursor, name):
+ qry = '''
+ SELECT
+ ProbeSet.Id,
+ ProbeSet.Name,
+ ProbeSet.description,
+ ProbeSet.symbol,
+ ProbeSet.Chr,
+ ProbeSet.Mb,
+ ProbeSet.GeneId
+ FROM
+ ProbeSet
+ WHERE
+ ProbeSet.Name = "%s"
+ ''' % name
+ #print qry
+ cursor.execute(qry)
+ row = cursor.fetchone()
+
+ # convert a MySQL NULL value to an empty string
+ # for gene symbol
+ if row[3] is None:
+ sym = ""
+ else:
+ sym = row[3]
+
+ return ProbeSetTrait(id=row[0], name=row[1], description=row[2],
+ symbol=sym, chromosome=row[4], MB=row[5],
+ GeneId=row[6])
+
+
+# queryTraits : Cursor -> string -> string -> arrayof Traits
+# to find all of the traits whose descriptions match a certain string in a
+# particular database
+def queryTraits(cursor, dbId, queryString):
+ # we do this in two steps:
+ # first we get the data id for the matching traits
+ qry = '''
+ SELECT
+ ProbeSet.Id,
+ ProbeSet.Name,
+ ProbeSet.description,
+ ProbeSetXRef.DataId
+ FROM
+ ProbeSet,
+ ProbeSetXRef
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = %s AND
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId AND
+ ProbeSet.description LIKE "%%%s%%"
+ ''' % (dbId, queryString)
+ # print qry
+ cursor.execute(qry)
+
+ if cursor.rowcount == 0:
+ print "No traits found"
+ return []
+ else:
+ print "%s traits found" % (cursor.rowcount)
+
+ # maybe fetchall is bad; we will see
+ traits = []
+ for row in cursor.fetchall():
+ myTrait = Trait(row[0], row[1], row[2])
+ myTrait.dataId = row[3]
+ traits.append(myTrait)
+
+ # second we pull all of the strain data for each trait
+ print "Retrieving individual trait data..."
+ for trait in traits:
+ trait.populateStrainData(cursor, trait.dataId)
+ print "%s (%s) -- %s" % (trait.name, trait.id, trait.description)
+
+ print "done"
+ return traits
+
+# queryProbeSetFreezes : Cursor -> arrayof String,String tuples
+# to return the short and long name for each ProbeSetFreeze
+# this function is designed specifically for building
+# a database selector
+def queryProbeSetFreezes(cursor):
+ cursor.execute("""
+ SELECT
+ ProbeSetFreeze.Name,
+ ProbeSetFreeze.FullName
+ FROM
+ ProbeSetFreeze
+ ORDER BY
+ ProbeSetFreeze.Name
+ """)
+
+ # for now, fetchall returns the data as a list of tuples
+ # which is what we want
+ return list(cursor.fetchall())
+
+# queryProbeSetFreezeIdName: Cursor -> String -> String, String
+# this function returns the
+# id and the long name of a probesetfreeze given its name
+# once again, it's designed specifically for building
+# the database selector
+def queryProbeSetFreezeIdName(cursor, name):
+ qry = ('''
+ SELECT
+ ProbeSetFreeze.Id,
+ ProbeSetFreeze.FullName
+ FROM
+ ProbeSetFreeze
+ WHERE
+ ProbeSetFreeze.Name = "%s"
+ ''' % name)
+ #print qry
+ cursor.execute(qry)
+
+ row = cursor.fetchone()
+ return row
+
+# queryProbeSetFreezeName: Cursor -> String -> String
+# to return the name of a probe set freeze given its id
+def queryProbeSetFreezeName(cursor, id):
+ cursor.execute('''
+ SELECT
+ ProbeSetFreeze.FullName
+ FROM
+ ProbeSetFreeze
+ WHERE
+ ProbeSetFreeze.Id = %s
+ ''' % id)
+
+ row = cursor.fetchone()
+ return row[0]
+
+# dbNameToTypeId : Cursor -> String -> (String, String)
+# to convert a database name to a (type, id) pair
+def dbNameToTypeId(cursor, name):
+ types = ["ProbeSet", "Geno", "Publish"]
+ for type_ in types:
+ count = cursor.execute('''
+ SELECT
+ %sFreeze.Id
+ FROM
+ %sFreeze
+ WHERE
+ Name = "%s"
+ ''' % (type_, type_, name))
+
+ if count != 0:
+ id = cursor.fetchone()[0]
+ return type_, id
+
+ return None, None
+
+# dbTypeIdToName : Cursor -> String -> String -> String
+# to convert a database (type,id) pair into a name
+def dbTypeIdToName(cursor, dbType, dbId):
+ cursor.execute('''
+ SELECT
+ %sFreeze.Name
+ FROM
+ %sFreeze
+ WHERE
+ Id = %s
+ ''' % (dbType, dbType, dbId))
+
+ row = cursor.fetchone()
+ return row[0]
+
+#XZ, July 21, 2010: I add this function
+def getSpeciesIdByDbTypeId (cursor, dbType, dbId):
+ cursor.execute('''
+ SELECT
+ SpeciesId
+ FROM
+ InbredSet, %sFreeze
+ WHERE
+ %sFreeze.Id = %s
+ and InbredSetId = InbredSet.Id
+ ''' % (dbType, dbType, dbId))
+
+ row = cursor.fetchone()
+ return row[0]
+
+
+# queryStrainCount : Cursor -> int
+# return the number of strains in the database
+def queryStrainCount(cursor):
+ cursor.execute('''
+ SELECT
+ Max(Strain.Id)
+ FROM
+ Strain
+ ''')
+ return (cursor.fetchone())[0]
diff --git a/web/webqtl/correlation/CorrelationPage.py b/web/webqtl/correlation/CorrelationPage.py
new file mode 100755
index 00000000..8ce669cb
--- /dev/null
+++ b/web/webqtl/correlation/CorrelationPage.py
@@ -0,0 +1,1958 @@
+# 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 2011/02/11
+
+import string
+from math import *
+import cPickle
+import os
+import time
+import pyXLWriter as xl
+import pp
+import math
+
+from htmlgen import HTMLgen2 as HT
+import reaper
+
+from base import webqtlConfig
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+from base.webqtlTrait import webqtlTrait
+from base.webqtlDataset import webqtlDataset
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from dbFunction import webqtlDatabaseFunction
+import utility.webqtlUtil #this is for parallel computing only.
+from correlation import correlationFunction
+
+
+class CorrelationPage(templatePage):
+
+ corrMinInformative = 4
+
+ def __init__(self, fd):
+
+ #XZ, 01/14/2009: This method is for parallel computing only.
+ #XZ: It is supposed to be called when "Genetic Correlation, Pearson's r" (method 1)
+ #XZ: or "Genetic Correlation, Spearman's rho" (method 2) is selected
+ def compute_corr( input_nnCorr, input_trait, input_list, computing_method):
+
+ allcorrelations = []
+
+ for line in input_list:
+ tokens = line.split('","')
+ tokens[-1] = tokens[-1][:-2] #remove the last "
+ tokens[0] = tokens[0][1:] #remove the first "
+
+ traitdataName = tokens[0]
+ database_trait = tokens[1:]
+
+ if computing_method == "1": #XZ: Pearson's r
+ corr,nOverlap = utility.webqtlUtil.calCorrelationText(input_trait, database_trait, input_nnCorr)
+ else: #XZ: Spearman's rho
+ corr,nOverlap = utility.webqtlUtil.calCorrelationRankText(input_trait, database_trait, input_nnCorr)
+ traitinfo = [traitdataName,corr,nOverlap]
+ allcorrelations.append(traitinfo)
+
+ return allcorrelations
+
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if not fd.genotype:
+ fd.readGenotype()
+
+ #XZ, 09/18/2008: get the information such as value, variance of the input strain names from the form.
+ if fd.allstrainlist:
+ mdpchoice = fd.formdata.getvalue('MDPChoice')
+ #XZ, in HTML source code, it is "BXD Only" or "BXH only", and so on
+ if mdpchoice == "1":
+ strainlist = fd.f1list + fd.strainlist
+ #XZ, in HTML source code, it is "MDP Only"
+ elif mdpchoice == "2":
+ strainlist = []
+ strainlist2 = fd.f1list + fd.strainlist
+ for strain in fd.allstrainlist:
+ if strain not in strainlist2:
+ strainlist.append(strain)
+ #So called MDP Panel
+ if strainlist:
+ strainlist = fd.f1list+fd.parlist+strainlist
+ #XZ, in HTML source code, it is "All Cases"
+ else:
+ strainlist = fd.allstrainlist
+ #XZ, 09/18/2008: put the trait data into dictionary fd.allTraitData
+ fd.readData(fd.allstrainlist)
+ else:
+ mdpchoice = None
+ strainlist = fd.strainlist
+ #XZ, 09/18/2008: put the trait data into dictionary fd.allTraitData
+ fd.readData()
+
+ #XZ, 3/16/2010: variable RISet must be pass by the form
+ RISet = fd.RISet
+ #XZ, 12/12/2008: get species infomation
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=RISet)
+
+ #XZ, 09/18/2008: get all information about the user selected database.
+ self.target_db_name = fd.formdata.getvalue('database')
+
+ try:
+ self.db = webqtlDataset(self.target_db_name, self.cursor)
+ except:
+ heading = "Correlation Table"
+ detail = ["The database you just requested has not been established yet."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ, 09/18/2008: check if user has the authority to get access to the database.
+ if self.db.type == 'ProbeSet':
+ self.cursor.execute('SELECT Id, Name, FullName, confidentiality, AuthorisedUsers FROM ProbeSetFreeze WHERE Name = "%s"' % self.target_db_name)
+ indId, indName, indFullName, confidential, AuthorisedUsers = self.cursor.fetchall()[0]
+
+ if confidential == 1:
+ access_to_confidential_dataset = 0
+
+ #for the dataset that confidentiality is 1
+ #1. 'admin' and 'root' can see all of the dataset
+ #2. 'user' can see the dataset that AuthorisedUsers contains his id(stored in the Id field of User table)
+ if webqtlConfig.USERDICT[self.privilege] > webqtlConfig.USERDICT['user']:
+ access_to_confidential_dataset = 1
+ else:
+ AuthorisedUsersList=AuthorisedUsers.split(',')
+ if AuthorisedUsersList.__contains__(self.userName):
+ access_to_confidential_dataset = 1
+
+ if not access_to_confidential_dataset:
+ #Error, Confidential Database
+ heading = "Correlation Table"
+ detail = ["The %s database you selected is not open to the public at this time, please go back and select other database." % indFullName]
+ self.error(heading=heading,detail=detail,error="Confidential Database")
+ return
+
+ #XZ, 09/18/2008: filter out the strains that have no value.
+ _strains, _vals, _vars, N = fd.informativeStrains(strainlist)
+
+ N = len(_strains)
+
+ if N < self.corrMinInformative:
+ heading = "Correlation Table"
+ detail = ['Fewer than %d strain data were entered for %s data set. No calculation of correlation has been attempted.' % (self.corrMinInformative, RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ, 09/28/2008: if user select "1", then display 1, 3 and 4.
+ #XZ, 09/28/2008: if user select "2", then display 2, 3 and 5.
+ #XZ, 09/28/2008: if user select "3", then display 1, 3 and 4.
+ #XZ, 09/28/2008: if user select "4", then display 1, 3 and 4.
+ #XZ, 09/28/2008: if user select "5", then display 2, 3 and 5.
+ methodDict = {"1":"Genetic Correlation (Pearson's r)","2":"Genetic Correlation (Spearman's rho)","3":"SGO Literature Correlation","4":"Tissue Correlation (Pearson's r)", "5":"Tissue Correlation (Spearman's rho)"}
+ self.method = fd.formdata.getvalue('method')
+ if self.method not in ("1","2","3","4","5"):
+ self.method = "1"
+
+ self.returnNumber = int(fd.formdata.getvalue('criteria'))
+
+ myTrait = fd.formdata.getvalue('fullname')
+ if myTrait:
+ myTrait = webqtlTrait(fullname=myTrait, cursor=self.cursor)
+ myTrait.retrieveInfo()
+
+ # We will not get Literature Correlations if there is no GeneId because there is nothing to look against
+ try:
+ input_trait_GeneId = int(fd.formdata.getvalue('GeneId'))
+ except:
+ input_trait_GeneId = None
+
+ # We will not get Tissue Correlations if there is no gene symbol because there is nothing to look against
+ try:
+ input_trait_symbol = myTrait.symbol
+ except:
+ input_trait_symbol = None
+
+
+ #XZ, 12/12/2008: if the species is rat or human, translate the geneid to mouse geneid
+ input_trait_mouse_geneid = self.translateToMouseGeneID(species, input_trait_GeneId)
+
+
+ #XZ: As of Nov/13/2010, this dataset is 'UTHSC Illumina V6.2 RankInv B6 D2 average CNS GI average (May 08)'
+ TissueProbeSetFreezeId = 1
+
+ #XZ, 09/22/2008: If we need search by GeneId,
+ #XZ, 09/22/2008: we have to check if this GeneId is in the literature or tissue correlation table.
+ #XZ, 10/15/2008: We also to check if the selected database is probeset type.
+ if self.method == "3" or self.method == "4" or self.method == "5":
+ if self.db.type != "ProbeSet":
+ self.error(heading="Wrong correlation type",detail="It is not possible to compute the %s between your trait and data in this %s database. Please try again after selecting another type of correlation." % (methodDict[self.method],self.db.name),error="Correlation Type Error")
+ return
+
+ """
+ if not input_trait_GeneId:
+ self.error(heading="No Associated GeneId",detail="This trait has no associated GeneId, so we are not able to show any literature or tissue related information.",error="No GeneId Error")
+ return
+ """
+
+ #XZ: We have checked geneid did exist
+
+ if self.method == "3":
+ if not input_trait_GeneId or not self.checkForLitInfo(input_trait_mouse_geneid):
+ self.error(heading="No Literature Info",detail="This gene does not have any associated Literature Information.",error="Literature Correlation Error")
+ return
+
+ if self.method == "4" or self.method == "5":
+ if not input_trait_symbol:
+ self.error(heading="No Tissue Correlation Information",detail="This gene does not have any associated Tissue Correlation Information.",error="Tissue Correlation Error")
+ return
+
+ if not self.checkSymbolForTissueCorr(TissueProbeSetFreezeId, myTrait.symbol):
+ self.error(heading="No Tissue Correlation Information",detail="This gene does not have any associated Tissue Correlation Information.",error="Tissue Correlation Error")
+ return
+
+############################################################################################################################################
+
+ allcorrelations = []
+ nnCorr = len(_vals)
+
+ #XZ: Use the fast method only for probeset dataset, and this dataset must have been created.
+ #XZ: Otherwise, use original method
+
+ useFastMethod = False
+
+ if self.db.type == "ProbeSet":
+
+ DatabaseFileName = self.getFileName( target_db_name=self.target_db_name )
+ DirectoryList = os.listdir(webqtlConfig.TEXTDIR) ### List of existing text files. Used to check if a text file already exists
+
+ if DatabaseFileName in DirectoryList:
+ useFastMethod = True
+
+ if useFastMethod:
+ if 1:
+ #try:
+ useLit = False
+ if self.method == "3":
+ litCorrs = self.fetchLitCorrelations(species=species, GeneId=input_trait_GeneId, db=self.db, returnNumber=self.returnNumber)
+ useLit = True
+
+ useTissueCorr = False
+ if self.method == "4" or self.method == "5":
+ tissueCorrs = self.fetchTissueCorrelations(db=self.db, primaryTraitSymbol=input_trait_symbol, TissueProbeSetFreezeId=TissueProbeSetFreezeId, method=self.method, returnNumber = self.returnNumber)
+ useTissueCorr = True
+
+ datasetFile = open(webqtlConfig.TEXTDIR+DatabaseFileName,'r')
+
+ #XZ, 01/08/2009: read the first line
+ line = datasetFile.readline()
+ dataset_strains = webqtlUtil.readLineCSV(line)[1:]
+
+ #XZ, 01/08/2009: This step is critical. It is necessary for this new method.
+ #XZ: The original function fetchAllDatabaseData uses all strains stored in variable _strains to
+ #XZ: retrieve the values of each strain from database in real time.
+ #XZ: The new method uses all strains stored in variable dataset_strains to create a new variable
+ #XZ: _newvals. _newvals has the same length as dataset_strains. The items in _newvals is in
+ #XZ: the same order of items in dataset_strains. The value of each item in _newvals is either
+ #XZ: the value of correspinding strain in _vals or 'None'.
+ _newvals = []
+ for item in dataset_strains:
+ if item in _strains:
+ _newvals.append(_vals[_strains.index(item)])
+ else:
+ _newvals.append('None')
+
+ nnCorr = len(_newvals)
+
+ #XZ, 01/14/2009: If literature corr or tissue corr is selected,
+ #XZ: there is no need to use parallel computing.
+ if useLit or useTissueCorr:
+ for line in datasetFile:
+ traitdata=webqtlUtil.readLineCSV(line)
+ traitdataName = traitdata[0]
+ traitvals = traitdata[1:]
+
+ if useLit:
+ if not litCorrs.has_key( traitdataName ):
+ continue
+
+ if useTissueCorr:
+ if not tissueCorrs.has_key( traitdataName ):
+ continue
+
+ if self.method == "3" or self.method == "4":
+ corr,nOverlap = webqtlUtil.calCorrelationText(traitvals,_newvals,nnCorr)
+ else:
+ corr,nOverlap = webqtlUtil.calCorrelationRankText(traitvals,_newvals,nnCorr)
+
+ traitinfo = [traitdataName,corr,nOverlap]
+
+ if useLit:
+ traitinfo.append(litCorrs[traitdataName])
+
+ if useTissueCorr:
+ tempCorr, tempPValue = tissueCorrs[traitdataName]
+ traitinfo.append(tempCorr)
+ traitinfo.append(tempPValue)
+
+ allcorrelations.append(traitinfo)
+ #XZ, 01/14/2009: If genetic corr is selected, use parallel computing
+ else:
+ input_line_list = datasetFile.readlines()
+ all_line_number = len(input_line_list)
+
+ step = 1000
+ job_number = math.ceil( float(all_line_number)/step )
+
+ job_input_lists = []
+
+ for job_index in range( int(job_number) ):
+ starti = job_index*step
+ endi = min((job_index+1)*step, all_line_number)
+
+ one_job_input_list = []
+
+ for i in range( starti, endi ):
+ one_job_input_list.append( input_line_list[i] )
+
+ job_input_lists.append( one_job_input_list )
+
+ ppservers = ()
+ # Creates jobserver with automatically detected number of workers
+ job_server = pp.Server(ppservers=ppservers)
+
+ jobs = []
+ results = []
+
+ for one_job_input_list in job_input_lists: #pay attention to modules from outside
+ jobs.append( job_server.submit(func=compute_corr, args=(nnCorr, _newvals, one_job_input_list, self.method), depfuncs=(), modules=("utility.webqtlUtil",)) )
+
+ for one_job in jobs:
+ one_result = one_job()
+ results.append( one_result )
+
+ for one_result in results:
+ for one_traitinfo in one_result:
+ allcorrelations.append( one_traitinfo )
+
+ datasetFile.close()
+ totalTraits = len(allcorrelations)
+ #except:
+ # useFastMethod = False
+ # self.error(heading="No computation method",detail="Something is wrong within the try except block in CorrelationPage python module.",error="Computation Error")
+ # return
+
+ #XZ, 01/08/2009: use the original method to retrieve from database and compute.
+ if not useFastMethod:
+
+ traitdatabase, dataStartPos = self.fetchAllDatabaseData(species=species, GeneId=input_trait_GeneId, GeneSymbol=input_trait_symbol, strains=_strains, db=self.db, method=self.method, returnNumber=self.returnNumber, tissueProbeSetFreezeId=TissueProbeSetFreezeId)
+
+ totalTraits = len(traitdatabase) #XZ, 09/18/2008: total trait number
+
+ for traitdata in traitdatabase:
+ traitdataName = traitdata[0]
+ traitvals = traitdata[dataStartPos:]
+ if self.method == "1" or self.method == "3" or self.method == "4":
+ corr,nOverlap = webqtlUtil.calCorrelation(traitvals,_vals,nnCorr)
+ else:
+ corr,nOverlap = webqtlUtil.calCorrelationRank(traitvals,_vals,nnCorr)
+
+ traitinfo = [traitdataName,corr,nOverlap]
+
+ #XZ, 09/28/2008: if user select '3', then fetchAllDatabaseData would give us LitCorr in the [1] position
+ #XZ, 09/28/2008: if user select '4' or '5', then fetchAllDatabaseData would give us Tissue Corr in the [1] position
+ #XZ, 09/28/2008: and Tissue Corr P Value in the [2] position
+ if input_trait_GeneId and self.db.type == "ProbeSet":
+ if self.method == "3":
+ traitinfo.append( traitdata[1] )
+ if self.method == "4" or self.method == "5":
+ traitinfo.append( traitdata[1] )
+ traitinfo.append( traitdata[2] )
+
+ allcorrelations.append(traitinfo)
+
+
+#############################################################
+
+ if self.method == "3" and input_trait_GeneId:
+ allcorrelations.sort(webqtlUtil.cmpLitCorr)
+ #XZ, 3/31/2010: Theoretically, we should create one function 'comTissueCorr'
+ #to compare each trait by their tissue corr p values.
+ #But because the tissue corr p values are generated by permutation test,
+ #the top ones always have p value 0. So comparing p values actually does nothing.
+ #In addition, for the tissue data in our database, the N is always the same.
+ #So it's safe to compare with tissue corr statistic value.
+ #That's the same as literature corr.
+ elif self.method in ["4","5"] and input_trait_GeneId:
+ allcorrelations.sort(webqtlUtil.cmpLitCorr)
+ else:
+ allcorrelations.sort(webqtlUtil.cmpCorr)
+
+
+ #XZ, 09/20/2008: we only need the top ones.
+ self.returnNumber = min(self.returnNumber,len(allcorrelations))
+ allcorrelations = allcorrelations[:self.returnNumber]
+
+ addLiteratureCorr = False
+ addTissueCorr = False
+
+ traitList = []
+ for item in allcorrelations:
+ thisTrait = webqtlTrait(db=self.db, name=item[0], cursor=self.cursor)
+ thisTrait.retrieveInfo( QTL='Yes' )
+
+ nOverlap = item[2]
+ corr = item[1]
+
+ #XZ: calculate corrPValue
+ if nOverlap < 3:
+ corrPValue = 1.0
+ else:
+ if abs(corr) >= 1.0:
+ corrPValue = 0.0
+ else:
+ ZValue = 0.5*log((1.0+corr)/(1.0-corr))
+ ZValue = ZValue*sqrt(nOverlap-3)
+ corrPValue = 2.0*(1.0 - reaper.normp(abs(ZValue)))
+
+ thisTrait.Name = item[0]
+ thisTrait.corr = corr
+ thisTrait.nOverlap = nOverlap
+ thisTrait.corrPValue = corrPValue
+ # NL, 07/19/2010
+ # js function changed, add a new parameter rankOrder for js function 'showTissueCorrPlot'
+ rankOrder = 0;
+ if self.method in ["2","5"]:
+ rankOrder = 1;
+ thisTrait.rankOrder =rankOrder
+
+ #XZ, 26/09/2008: Method is 4 or 5. Have fetched tissue corr, but no literature correlation yet.
+ if len(item) == 5:
+ thisTrait.tissueCorr = item[3]
+ thisTrait.tissuePValue = item[4]
+ addLiteratureCorr = True
+
+ #XZ, 26/09/2008: Method is 3, Have fetched literature corr, but no tissue corr yet.
+ elif len(item) == 4:
+ thisTrait.LCorr = item[3]
+ thisTrait.mouse_geneid = self.translateToMouseGeneID(species, thisTrait.geneid)
+ addTissueCorr = True
+
+ #XZ, 26/09/2008: Method is 1 or 2. Have NOT fetched literature corr and tissue corr yet.
+ # Phenotype data will not have geneid, and neither will some probes
+ # we need to handle this because we will get an attribute error
+ else:
+ if input_trait_mouse_geneid and self.db.type=="ProbeSet":
+ addLiteratureCorr = True
+ if input_trait_symbol and self.db.type=="ProbeSet":
+ addTissueCorr = True
+
+ traitList.append(thisTrait)
+
+ if addLiteratureCorr:
+ traitList = self.getLiteratureCorrelationByList(input_trait_mouse_geneid, species, traitList)
+ if addTissueCorr:
+ traitList = self.getTissueCorrelationByList( primaryTraitSymbol=input_trait_symbol, traitList=traitList,TissueProbeSetFreezeId =TissueProbeSetFreezeId, method=self.method)
+
+########################################################
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ mainfmName = webqtlUtil.genRandStr("fm_")
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name= mainfmName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase', 'ProbeSetID':'_','database':self.target_db_name, 'databaseFull':self.db.fullname, 'CellID':'_', 'RISet':RISet, 'identification':fd.identification}
+
+ if myTrait:
+ hddn['fullname']=fd.formdata.getvalue('fullname')
+ if mdpchoice:
+ hddn['MDPChoice']=mdpchoice
+
+
+ #XZ, 09/18/2008: pass the trait data to next page by hidden parameters.
+ webqtlUtil.exportData(hddn, fd.allTraitData)
+
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+
+ if fd.allstrainlist:
+ hddn['allstrainlist'] = string.join(fd.allstrainlist, ' ')
+
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ #XZ, 11/21/2008: add two parameters to form
+ form.append(HT.Input(name="X_geneSymbol", value="", type='hidden'))
+ form.append(HT.Input(name="Y_geneSymbol", value="", type='hidden'))
+
+ #XZ, 3/11/2010: add one parameter to record if the method is rank order.
+ form.append(HT.Input(name="rankOrder", value="%s" % rankOrder, type='hidden'))
+
+ form.append(HT.Input(name="TissueProbeSetFreezeId", value="%s" % TissueProbeSetFreezeId, type='hidden'))
+
+ ####################################
+ # generate the info on top of page #
+ ####################################
+
+ info = self.getTopInfo(myTrait=myTrait, method=self.method, db=self.db, target_db_name=self.target_db_name, returnNumber=self.returnNumber, methodDict=methodDict, totalTraits=totalTraits, identification=fd.identification )
+
+ ##############
+ # Excel file #
+ ##############
+ filename= webqtlUtil.genRandStr("Corr_")
+ xlsUrl = HT.Input(type='button', value = 'Download Table', onClick= "location.href='/tmp/%s.xls'" % filename, Class='button')
+ # Create a new Excel workbook
+ workbook = xl.Writer('%s.xls' % (webqtlConfig.TMPDIR+filename))
+ headingStyle = workbook.add_format(align = 'center', bold = 1, border = 1, size=13, fg_color = 0x1E, color="white")
+
+ #XZ, 3/18/2010: pay attention to the line number of header in this file. As of today, there are 7 lines.
+ worksheet = self.createExcelFileWithTitleAndFooter(workbook=workbook, identification=fd.identification, db=self.db, returnNumber=self.returnNumber)
+
+ newrow = 7
+
+
+#####################################################################
+
+
+
+ mintmap = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'showIntMap');" % mainfmName)
+ mintmap_img = HT.Image("/images/multiple_interval_mapping1_final.jpg", name='mintmap', alt="Multiple Interval Mapping", title="Multiple Interval Mapping", style="border:none;")
+ mintmap.append(mintmap_img)
+ mcorr = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'compCorr');" % mainfmName)
+ mcorr_img = HT.Image("/images/compare_correlates2_final.jpg", alt="Compare Correlates", title="Compare Correlates", style="border:none;")
+ mcorr.append(mcorr_img)
+ cormatrix = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'corMatrix');" % mainfmName)
+ cormatrix_img = HT.Image("/images/correlation_matrix1_final.jpg", alt="Correlation Matrix and PCA", title="Correlation Matrix and PCA", style="border:none;")
+ cormatrix.append(cormatrix_img)
+ networkGraph = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'networkGraph');" % mainfmName)
+ networkGraph_img = HT.Image("/images/network_graph1_final.jpg", name='mintmap', alt="Network Graphs", title="Network Graphs", style="border:none;")
+ networkGraph.append(networkGraph_img)
+ heatmap = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'heatmap');" % mainfmName)
+ heatmap_img = HT.Image("/images/heatmap2_final.jpg", name='mintmap', alt="QTL Heat Map and Clustering", title="QTL Heatmap and Clustering", style="border:none;")
+ heatmap.append(heatmap_img)
+ partialCorr = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'partialCorrInput');" % mainfmName)
+ partialCorr_img = HT.Image("/images/partial_correlation_final.jpg", name='partialCorr', alt="Partial Correlation", title="Partial Correlation", style="border:none;")
+ partialCorr.append(partialCorr_img)
+ addselect = HT.Href(url="#redirect", onClick="addRmvSelection('%s', document.getElementsByName('%s')[0], 'addToSelection');" % (RISet, mainfmName))
+ addselect_img = HT.Image("/images/add_collection1_final.jpg", name="addselect", alt="Add To Collection", title="Add To Collection", style="border:none;")
+ addselect.append(addselect_img)
+ selectall = HT.Href(url="#redirect", onClick="checkAll(document.getElementsByName('%s')[0]);" % mainfmName)
+ selectall_img = HT.Image("/images/select_all2_final.jpg", name="selectall", alt="Select All", title="Select All", style="border:none;")
+ selectall.append(selectall_img)
+ selectinvert = HT.Href(url="#redirect", onClick = "checkInvert(document.getElementsByName('%s')[0]);" % mainfmName)
+ selectinvert_img = HT.Image("/images/invert_selection2_final.jpg", name="selectinvert", alt="Invert Selection", title="Invert Selection", style="border:none;")
+ selectinvert.append(selectinvert_img)
+ reset = HT.Href(url="#redirect", onClick="checkNone(document.getElementsByName('%s')[0]); return false;" % mainfmName)
+ reset_img = HT.Image("/images/select_none2_final.jpg", alt="Select None", title="Select None", style="border:none;")
+ reset.append(reset_img)
+ selecttraits = HT.Input(type='button' ,name='selecttraits',value='Select Traits', onClick="checkTraits(this.form);",Class="button")
+ selectgt = HT.Input(type='text' ,name='selectgt',value='-1.0', size=6,maxlength=10,onChange="checkNumeric(this,1.0,'-1.0','gthan','greater than filed')")
+ selectlt = HT.Input(type='text' ,name='selectlt',value='1.0', size=6,maxlength=10,onChange="checkNumeric(this,-1.0,'1.0','lthan','less than field')")
+ selectandor = HT.Select(name='selectandor')
+ selectandor.append(('AND','and'))
+ selectandor.append(('OR','or'))
+ selectandor.selected.append('AND')
+
+ pageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%", border=0, align="Left")
+
+ containerTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="90%",border=0, align="Left")
+
+ optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="320", height="80", border=0, align="Left")
+ optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), align="left"))
+ optionsTable.append(HT.TR(HT.TD("&nbsp;"*1,"Select"), HT.TD("Deselect"), HT.TD("&nbsp;"*1,"Invert"), HT.TD("&nbsp;"*3,"Add")))
+ containerTable.append(HT.TR(HT.TD(optionsTable)))
+
+ functionTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="480",height="80", border=0, align="Left")
+ functionRow = HT.TR(HT.TD(networkGraph, width="16.7%"), HT.TD(cormatrix, width="16.7%"), HT.TD(partialCorr, width="16.7%"), HT.TD(mcorr, width="16.7%"), HT.TD(mintmap, width="16.7%"), HT.TD(heatmap), align="left")
+ labelRow = HT.TR(HT.TD("&nbsp;"*1,HT.Text("Graph")), HT.TD("&nbsp;"*1,HT.Text("Matrix")), HT.TD("&nbsp;"*1,HT.Text("Partial")), HT.TD(HT.Text("Compare")), HT.TD(HT.Text("QTL Map")), HT.TD(HT.Text(text="Heat Map")))
+ functionTable.append(functionRow, labelRow)
+ containerTable.append(HT.TR(HT.TD(functionTable), HT.BR()))
+
+ #more_options = HT.Image("/images/more_options1_final.jpg", name='more_options', alt="Expand Options", title="Expand Options", style="border:none;", Class="toggleShowHide")
+
+ #containerTable.append(HT.TR(HT.TD(more_options, HT.BR(), HT.BR())))
+
+ moreOptions = HT.Input(type='button',name='options',value='More Options', onClick="",Class="toggle")
+ fewerOptions = HT.Input(type='button',name='options',value='Fewer Options', onClick="",Class="toggle")
+
+ if (fd.formdata.getvalue('showHideOptions') == 'less'):
+ containerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD("&nbsp;")))
+ else:
+ containerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD("&nbsp;")))
+
+ containerTable.append(HT.TR(HT.TD(HT.Span(selecttraits,' with r > ',selectgt, ' ',selectandor, ' r < ',selectlt,Class="bd1 cbddf fs11")), style="display:none;", Class="extra_options"))
+
+ chrMenu = HT.Input(type='hidden',name='chromosomes',value='all')
+
+ corrHeading = HT.Paragraph('Correlation Table', Class="title")
+
+
+ tblobj = {}
+
+ if self.db.type=="Geno":
+
+ containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
+
+ pageTable.append(HT.TR(HT.TD(containerTable)))
+
+ tblobj['header'], worksheet = self.getTableHeaderForGeno( method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+ newrow += 1
+
+ sortby = self.getSortByValue( calculationMethod = self.method )
+
+ corrScript = HT.Script(language="Javascript")
+ corrScript.append("var corrArray = new Array();")
+
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForGeno(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript)
+
+ workbook.close()
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), corrScript, Id="sortable")
+
+ pageTable.append(HT.TR(HT.TD(div)))
+
+ form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
+ HT.Input(name='ShowLine',type='hidden', value =1),
+ HT.P(), HT.P(), pageTable)
+ TD_LR.append(corrHeading, info, form, HT.P())
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['js1'] = ''
+ self.dict['title'] = 'Correlation'
+
+ elif self.db.type=="Publish":
+
+ containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
+
+ pageTable.append(HT.TR(HT.TD(containerTable)))
+
+ tblobj['header'], worksheet = self.getTableHeaderForPublish(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+ newrow += 1
+
+ sortby = self.getSortByValue( calculationMethod = self.method )
+
+ corrScript = HT.Script(language="Javascript")
+ corrScript.append("var corrArray = new Array();")
+
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForPublish(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript, species=species)
+
+ workbook.close()
+
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+ # NL, 07/27/2010. genTableObj function has been moved from templatePage.py to webqtlUtil.py;
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), corrScript, Id="sortable")
+
+ pageTable.append(HT.TR(HT.TD(div)))
+
+ form.append(
+ HT.Input(name='ShowStrains',type='hidden', value =1),
+ HT.Input(name='ShowLine',type='hidden', value =1),
+ HT.P(), pageTable)
+ TD_LR.append(corrHeading, info, form, HT.P())
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['js1'] = ''
+ self.dict['title'] = 'Correlation'
+
+
+ elif self.db.type=="ProbeSet":
+
+ tblobj['header'], worksheet = self.getTableHeaderForProbeSet(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+ newrow += 1
+
+ sortby = self.getSortByValue( calculationMethod = self.method )
+
+ corrScript = HT.Script(language="Javascript")
+ corrScript.append("var corrArray = new Array();")
+
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForProbeSet(traitList=traitList, primaryTrait=myTrait, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript, species=species)
+
+ workbook.close()
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ #XZ: here is the table of traits
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1", hiddenColumns=["Gene ID","Homologene ID"]), corrScript, Id="sortable")
+
+
+ #XZ, 01/12/2009: create database menu for 'Add Correlation'
+ self.cursor.execute("""
+ select
+ ProbeSetFreeze.FullName, ProbeSetFreeze.Id, Tissue.name
+ from
+ ProbeSetFreeze, ProbeFreeze, ProbeSetFreeze as ps2, ProbeFreeze as p2, Tissue
+ where
+ ps2.Id = %d
+ and ps2.ProbeFreezeId = p2.Id
+ and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id
+ and (ProbeFreeze.InbredSetId = p2.InbredSetId or (ProbeFreeze.InbredSetId in (1, 3) and p2.InbredSetId in (1, 3)))
+ and p2.ChipId = ProbeFreeze.ChipId
+ and ps2.Id != ProbeSetFreeze.Id
+ and ProbeFreeze.TissueId = Tissue.Id
+ and ProbeSetFreeze.public > %d
+ order by
+ ProbeFreeze.TissueId, ProbeSetFreeze.CreateTime desc
+ """ % (self.db.id, webqtlConfig.PUBLICTHRESH))
+
+ results = self.cursor.fetchall()
+ dbCustomizer = HT.Select(results, name = "customizer")
+ databaseMenuSub = preTissue = ""
+ for item in results:
+ TName, TId, TTissue = item
+ if TTissue != preTissue:
+ if databaseMenuSub:
+ dbCustomizer.append(databaseMenuSub)
+ databaseMenuSub = HT.Optgroup(label = '%s mRNA ------' % TTissue)
+ preTissue = TTissue
+
+ databaseMenuSub.append(item[:2])
+ if databaseMenuSub:
+ dbCustomizer.append(databaseMenuSub)
+
+ #updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
+ #variables: filename, strainIds and vals are required by getquerystring function
+ strainIds=self.getStrainIds(species=species, strains=_strains)
+ var1 = HT.Input(name="filename", value=filename, type='hidden')
+ var2 = HT.Input(name="strainIds", value=strainIds, type='hidden')
+ var3 = HT.Input(name="vals", value=_vals, type='hidden')
+ customizerButton = HT.Input(type="button", Class="button", value="Add Correlation", onClick = "xmlhttpPost('%smain.py?FormID=AJAX_table', 'sortable', (getquerystring(this.form)))" % webqtlConfig.CGIDIR)
+
+ containerTable.append(HT.TR(HT.TD(HT.Span(var1,var2,var3,customizerButton, "with", dbCustomizer, Class="bd1 cbddf fs11"), HT.BR(), HT.BR()), style="display:none;", Class="extra_options"))
+
+ #outside analysis part
+ GCATButton = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'GCAT');" % mainfmName)
+ GCATButton_img = HT.Image("/images/GCAT_logo_final.jpg", name="GCAT", alt="GCAT", title="GCAT", style="border:none")
+ GCATButton.append(GCATButton_img)
+
+ ODE = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'ODE');" % mainfmName)
+ ODE_img = HT.Image("/images/ODE_logo_final.jpg", name="ode", alt="ODE", title="ODE", style="border:none")
+ ODE.append(ODE_img)
+
+ '''
+ #XZ, 07/07/2010: I comment out this block of code.
+ WebGestaltScript = HT.Script(language="Javascript")
+ WebGestaltScript.append("""
+setTimeout('openWebGestalt()', 2000);
+function openWebGestalt(){
+ var thisForm = document['WebGestalt'];
+ makeWebGestaltTree(thisForm, '%s', %d, 'edag_only.php');
+}
+ """ % (mainfmName, len(traitList)))
+ '''
+
+ self.cursor.execute('SELECT GeneChip.GO_tree_value FROM GeneChip, ProbeFreeze, ProbeSetFreeze WHERE GeneChip.Id = ProbeFreeze.ChipId and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Name = "%s"' % self.db.name)
+ result = self.cursor.fetchone()
+
+ if result:
+ GO_tree_value = result[0]
+
+ if GO_tree_value:
+
+ WebGestalt = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'GOTree');" % mainfmName)
+ WebGestalt_img = HT.Image("/images/webgestalt_icon_final.jpg", name="webgestalt", alt="Gene Set Analysis Toolkit", title="Gene Set Analysis Toolkit", style="border:none")
+ WebGestalt.append(WebGestalt_img)
+
+ hddnWebGestalt = {
+ 'id_list':'',
+ 'correlation':'',
+ 'id_value':'',
+ 'llid_list':'',
+ 'id_type':GO_tree_value,
+ 'idtype':'',
+ 'species':'',
+ 'list':'',
+ 'client':''}
+
+ hddnWebGestalt['ref_type'] = hddnWebGestalt['id_type']
+ hddnWebGestalt['cat_type'] = 'GO'
+ hddnWebGestalt['significancelevel'] = 'Top10'
+
+ if species == 'rat':
+ hddnWebGestalt['org'] = 'Rattus norvegicus'
+ elif species == 'human':
+ hddnWebGestalt['org'] = 'Homo sapiens'
+ elif species == 'mouse':
+ hddnWebGestalt['org'] = 'Mus musculus'
+ else:
+ hddnWebGestalt['org'] = ''
+
+ for key in hddnWebGestalt.keys():
+ form.append(HT.Input(name=key, value=hddnWebGestalt[key], type='hidden'))
+
+
+ LinkOutTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="320",height="80", border=0, align="Left")
+
+ if not GO_tree_value:
+ LinkOutRow = HT.TR(HT.TD(GCATButton, width="50%"), HT.TD(ODE, width="50%"), align="left")
+ LinkOutLabels = HT.TR(HT.TD("&nbsp;", HT.Text("GCAT"), width="50%"), HT.TD("&nbsp;",HT.Text("ODE"), width="50%"), align="left")
+ else:
+ LinkOutRow = HT.TR(HT.TD(WebGestalt, width="25%"), HT.TD(GCATButton, width="25%"), HT.TD(ODE, width="25%"), align="left")
+ LinkOutLabels = HT.TR(HT.TD(HT.Text("Gene Set")), HT.TD("&nbsp;"*2, HT.Text("GCAT")), HT.TD("&nbsp;"*3, HT.Text("ODE")), style="display:none;", Class="extra_options")
+
+ LinkOutTable.append(LinkOutRow,LinkOutLabels)
+
+ containerTable.append(HT.TR(HT.TD(LinkOutTable), Class="extra_options", style="display:none;"))
+
+ containerTable.append(HT.TR(HT.TD(xlsUrl, HT.BR(), HT.BR())))
+
+ pageTable.append(HT.TR(HT.TD(containerTable)))
+
+ pageTable.append(HT.TR(HT.TD(div)))
+
+ if species == 'human':
+ heatmap = ""
+
+ form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
+ HT.Input(name='ShowLine',type='hidden', value =1),
+ info, HT.BR(), pageTable, HT.BR())
+
+ TD_LR.append(corrHeading, form, HT.P())
+
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = 'Correlation'
+ # updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
+ self.dict['js1'] = ''
+ self.dict['js2'] = 'onLoad="pageOffset()"'
+ self.dict['layer'] = self.generateWarningLayer()
+ else:
+ self.dict['body'] = ""
+
+
+#############################
+# #
+# CorrelationPage Functions #
+# #
+#############################
+
+
+ def getSortByValue(self, calculationMethod):
+
+ if calculationMethod == "1":
+ sortby = ("Sample p(r)", "up")
+ elif calculationMethod == "2":
+ sortby = ("Sample p(rho)", "up")
+ elif calculationMethod == "3": #XZ: literature correlation
+ sortby = ("Lit Corr","down")
+ elif calculationMethod == "4": #XZ: tissue correlation
+ sortby = ("Tissue r", "down")
+ elif calculationMethod == "5":
+ sortby = ("Tissue rho", "down")
+
+ return sortby
+
+
+
+ def generateWarningLayer(self):
+
+ layerString = """
+<!-- BEGIN FLOATING LAYER CODE //-->
+<div id="warningLayer" style="padding:3px; border: 1px solid #222;
+ background-color: #fff; position:absolute;width:250px;left:100;top:100;visibility:hidden">
+<table border="0" width="250" class="cbrb" cellspacing="0" cellpadding="5">
+<tr>
+<td width="100%">
+ <table border="0" width="100%" cellspacing="0" cellpadding="0" height="36">
+ <tr>
+ <td class="cbrb cw ff15 fwb" align="Center" width="100%" style="padding:4px">
+ Sort Table
+ </td>
+ </tr>
+ <tr>
+ <td width="100%" bgcolor="#eeeeee" align="Center" style="padding:4px">
+<!-- PLACE YOUR CONTENT HERE //-->
+Resorting this table <br>
+<!-- END OF CONTENT AREA //-->
+ </td>
+ </tr>
+ </table>
+</td>
+</tr>
+</table>
+</div>
+<!-- END FLOATING LAYER CODE //-->
+
+ """
+
+ return layerString
+
+
+ #XZ, 01/07/2009: In HTML code, the variable 'database' corresponds to the column 'Name' in database table.
+ def getFileName(self, target_db_name): ### dcrowell August 2008
+ """Returns the name of the reference database file with which correlations are calculated.
+ Takes argument cursor which is a cursor object of any instance of a subclass of templatePage
+ Used by correlationPage"""
+
+ query = 'SELECT Id, FullName FROM ProbeSetFreeze WHERE Name = "%s"' % target_db_name
+ self.cursor.execute(query)
+ result = self.cursor.fetchone()
+ Id = result[0]
+ FullName = result[1]
+ FullName = FullName.replace(' ','_')
+ FullName = FullName.replace('/','_')
+
+ FileName = 'ProbeSetFreezeId_' + str(Id) + '_FullName_' + FullName + '.txt'
+
+ return FileName
+
+
+ #XZ, 01/29/2009: I modified this function.
+ #XZ: Note that the type of StrainIds must be number, not string.
+ def getStrainIds(self, species=None, strains=[]):
+ StrainIds = []
+ for item in strains:
+ self.cursor.execute('''SELECT Strain.Id FROM Strain, Species WHERE
+ Strain.Name="%s" and Strain.SpeciesId=Species.Id and Species.name = "%s" ''' % (item, species))
+ Id = self.cursor.fetchone()[0]
+ StrainIds.append(Id)
+
+ return StrainIds
+
+
+ #XZ, 12/12/2008: if the species is rat or human, translate the geneid to mouse geneid
+ #XZ, 12/12/2008: if the input geneid is 'None', return 0
+ #XZ, 12/12/2008: if the input geneid has no corresponding mouse geneid, return 0
+ def translateToMouseGeneID (self, species, geneid):
+ mouse_geneid = 0;
+
+ #if input geneid is None, return 0.
+ if not geneid:
+ return mouse_geneid
+
+ if species == 'mouse':
+ mouse_geneid = geneid
+ elif species == 'rat':
+ self.cursor.execute( "SELECT mouse FROM GeneIDXRef WHERE rat=%d" % int(geneid) )
+ record = self.cursor.fetchone()
+ if record:
+ mouse_geneid = record[0]
+ elif species == 'human':
+ self.cursor.execute( "SELECT mouse FROM GeneIDXRef WHERE human=%d" % int(geneid) )
+ record = self.cursor.fetchone()
+ if record:
+ mouse_geneid = record[0]
+
+ return mouse_geneid
+
+
+ #XZ, 12/16/2008: the input geneid is of mouse type
+ def checkForLitInfo(self,geneId):
+ q = 'SELECT 1 FROM LCorrRamin3 WHERE GeneId1=%s LIMIT 1' % geneId
+ self.cursor.execute(q)
+ try:
+ x = self.cursor.fetchone()
+ if x: return True
+ else: raise
+ except: return False
+
+
+ #XZ, 12/16/2008: the input geneid is of mouse type
+ def checkSymbolForTissueCorr(self, tissueProbeSetFreezeId=0, symbol=""):
+ q = "SELECT 1 FROM TissueProbeSetXRef WHERE TissueProbeSetFreezeId=%s and Symbol='%s' LIMIT 1" % (tissueProbeSetFreezeId,symbol)
+ self.cursor.execute(q)
+ try:
+ x = self.cursor.fetchone()
+ if x: return True
+ else: raise
+ except: return False
+
+
+
+ def fetchAllDatabaseData(self, species, GeneId, GeneSymbol, strains, db, method, returnNumber, tissueProbeSetFreezeId):
+
+ StrainIds = []
+ for item in strains:
+ self.cursor.execute('''SELECT Strain.Id FROM Strain, Species WHERE Strain.Name="%s" and Strain.SpeciesId=Species.Id and Species.name = "%s" ''' % (item, species))
+ Id = self.cursor.fetchone()[0]
+ StrainIds.append('%d' % Id)
+
+ # break it into smaller chunks so we don't overload the MySql server
+ nnn = len(StrainIds) / 25
+ if len(StrainIds) % 25:
+ nnn += 1
+ oridata = []
+
+ #XZ, 09/24/2008: build one temporary table that only contains the records associated with the input GeneId
+ tempTable = None
+ if GeneId and db.type == "ProbeSet":
+ if method == "3":
+ tempTable = self.getTempLiteratureTable(species=species, input_species_geneid=GeneId, returnNumber=returnNumber)
+
+ if method == "4" or method == "5":
+ tempTable = self.getTempTissueCorrTable(primaryTraitSymbol=GeneSymbol, TissueProbeSetFreezeId=tissueProbeSetFreezeId, method=method, returnNumber=returnNumber)
+
+ for step in range(nnn):
+ temp = []
+ StrainIdstep = StrainIds[step*25:min(len(StrainIds), (step+1)*25)]
+ for item in StrainIdstep: temp.append('T%s.value' % item)
+
+ if db.type == "Publish":
+ query = "SELECT PublishXRef.Id, "
+ dataStartPos = 1
+ query += string.join(temp,', ')
+ query += ' FROM (PublishXRef, PublishFreeze)'
+ #XZ, 03/04/2009: Xiaodong changed Data to PublishData
+ for item in StrainIdstep:
+ query += 'left join PublishData as T%s on T%s.Id = PublishXRef.DataId and T%s.StrainId=%s\n' %(item,item,item,item)
+ query += "WHERE PublishXRef.InbredSetId = PublishFreeze.InbredSetId and PublishFreeze.Name = '%s'" % (db.name, )
+ #XZ, 09/20/2008: extract literature correlation value together with gene expression values.
+ #XZ, 09/20/2008: notice the difference between the code in next block.
+ elif tempTable:
+ # we can get a little performance out of selecting our LitCorr here
+ # but also we need to do this because we are unconcerned with probes that have no geneId associated with them
+ # as we would not have litCorr data.
+
+ if method == "3":
+ query = "SELECT %s.Name, %s.value," % (db.type,tempTable)
+ dataStartPos = 2
+ if method == "4" or method == "5":
+ query = "SELECT %s.Name, %s.Correlation, %s.PValue," % (db.type,tempTable, tempTable)
+ dataStartPos = 3
+
+ query += string.join(temp,', ')
+ query += ' FROM (%s, %sXRef, %sFreeze)' % (db.type, db.type, db.type)
+ if method == "3":
+ query += ' LEFT JOIN %s ON %s.GeneId2=ProbeSet.GeneId ' % (tempTable,tempTable)
+ if method == "4" or method == "5":
+ query += ' LEFT JOIN %s ON %s.Symbol=ProbeSet.Symbol ' % (tempTable,tempTable)
+ #XZ, 03/04/2009: Xiaodong changed Data to %sData and changed parameters from %(item,item, db.type,item,item) to %(db.type, item,item, db.type,item,item)
+ for item in StrainIdstep:
+ query += 'left join %sData as T%s on T%s.Id = %sXRef.DataId and T%s.StrainId=%s\n' %(db.type, item,item, db.type,item,item)
+
+ if method == "3":
+ query += "WHERE ProbeSet.GeneId IS NOT NULL AND %s.value IS NOT NULL AND %sXRef.%sFreezeId = %sFreeze.Id and %sFreeze.Name = '%s' and %s.Id = %sXRef.%sId order by %s.Id" % (tempTable,db.type, db.type, db.type, db.type, db.name, db.type, db.type, db.type, db.type)
+ if method == "4" or method == "5":
+ query += "WHERE ProbeSet.Symbol IS NOT NULL AND %s.Correlation IS NOT NULL AND %sXRef.%sFreezeId = %sFreeze.Id and %sFreeze.Name = '%s' and %s.Id = %sXRef.%sId order by %s.Id" % (tempTable,db.type, db.type, db.type, db.type, db.name, db.type, db.type, db.type, db.type)
+ else:
+ query = "SELECT %s.Name," % db.type
+ dataStartPos = 1
+ query += string.join(temp,', ')
+ query += ' FROM (%s, %sXRef, %sFreeze)' % (db.type, db.type, db.type)
+ #XZ, 03/04/2009: Xiaodong changed Data to %sData and changed parameters from %(item,item, db.type,item,item) to %(db.type, item,item, db.type,item,item)
+ for item in StrainIdstep:
+ query += 'left join %sData as T%s on T%s.Id = %sXRef.DataId and T%s.StrainId=%s\n' %(db.type, item,item, db.type,item,item)
+ query += "WHERE %sXRef.%sFreezeId = %sFreeze.Id and %sFreeze.Name = '%s' and %s.Id = %sXRef.%sId order by %s.Id" % (db.type, db.type, db.type, db.type, db.name, db.type, db.type, db.type, db.type)
+
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+ oridata.append(results)
+
+ datasize = len(oridata[0])
+ traitdatabase = []
+ # put all of the seperate data together into a huge list of lists
+ for j in range(datasize):
+ traitdata = list(oridata[0][j])
+ for i in range(1,nnn):
+ traitdata += list(oridata[i][j][dataStartPos:])
+ traitdatabase.append(traitdata)
+
+ if tempTable:
+ self.cursor.execute( 'DROP TEMPORARY TABLE %s' % tempTable )
+
+ return traitdatabase, dataStartPos
+
+
+ # XZ, 09/20/2008: This function creates TEMPORARY TABLE tmpTableName_2 and return its name.
+ # XZ, 09/20/2008: It stores top literature correlation values associated with the input geneId.
+ # XZ, 09/20/2008: Attention: In each row, the input geneId is always in column GeneId1.
+ #XZ, 12/16/2008: the input geneid can be of mouse, rat or human type
+ def getTempLiteratureTable(self, species, input_species_geneid, returnNumber):
+ # according to mysql the TEMPORARY TABLE name should not have to be unique because
+ # it is only available to the current connection. This program will be invoked via command line, but if it
+ # were to be invoked over mod_python this could cuase problems. mod_python will keep the connection alive
+ # in its executing threads ( i think) so there is a potential for the table not being dropped between users.
+ #XZ, 01/29/2009: To prevent the potential risk, I generate random table names and drop the tables after use them.
+
+
+ # the 'input_species_geneid' could be rat or human geneid, need to translate it to mouse geneid
+ translated_mouse_geneid = self.translateToMouseGeneID (species, input_species_geneid)
+
+ tmpTableName_1 = webqtlUtil.genRandStr(prefix="LITERATURE")
+
+ q1 = 'CREATE TEMPORARY TABLE %s (GeneId1 int(12) unsigned, GeneId2 int(12) unsigned PRIMARY KEY, value double)' % tmpTableName_1
+ q2 = 'INSERT INTO %s (GeneId1, GeneId2, value) SELECT GeneId1,GeneId2,value FROM LCorrRamin3 WHERE GeneId1=%s' % (tmpTableName_1, translated_mouse_geneid)
+ q3 = 'INSERT INTO %s (GeneId1, GeneId2, value) SELECT GeneId2,GeneId1,value FROM LCorrRamin3 WHERE GeneId2=%s AND GeneId1!=%s' % (tmpTableName_1, translated_mouse_geneid,translated_mouse_geneid)
+ for x in [q1,q2,q3]: self.cursor.execute(x)
+
+ #XZ, 09/23/2008: Just use the top records insteard of using all records
+ tmpTableName_2 = webqtlUtil.genRandStr(prefix="TOPLITERATURE")
+
+ q1 = 'CREATE TEMPORARY TABLE %s (GeneId1 int(12) unsigned, GeneId2 int(12) unsigned PRIMARY KEY, value double)' % tmpTableName_2
+ self.cursor.execute(q1)
+ q2 = 'SELECT GeneId1, GeneId2, value FROM %s ORDER BY value DESC' % tmpTableName_1
+ self.cursor.execute(q2)
+ result = self.cursor.fetchall()
+
+ counter = 0 #this is to count how many records being inserted into table
+ for one_row in result:
+ mouse_geneid1, mouse_geneid2, lit_corr_alue = one_row
+
+ #mouse_geneid1 has been tested before, now should test if mouse_geneid2 has corresponding geneid in other species
+ translated_species_geneid = 0
+ if species == 'mouse':
+ translated_species_geneid = mouse_geneid2
+ elif species == 'rat':
+ self.cursor.execute( "SELECT rat FROM GeneIDXRef WHERE mouse=%d" % int(mouse_geneid2) )
+ record = self.cursor.fetchone()
+ if record:
+ translated_species_geneid = record[0]
+ elif species == 'human':
+ self.cursor.execute( "SELECT human FROM GeneIDXRef WHERE mouse=%d" % int(mouse_geneid2) )
+ record = self.cursor.fetchone()
+ if record:
+ translated_species_geneid = record[0]
+
+ if translated_species_geneid:
+ self.cursor.execute( 'INSERT INTO %s (GeneId1, GeneId2, value) VALUES (%d,%d,%f)' % (tmpTableName_2, int(input_species_geneid),int(translated_species_geneid), float(lit_corr_alue)) )
+ counter = counter + 1
+
+ #pay attention to the number
+ if (counter > 2*returnNumber):
+ break
+
+ self.cursor.execute('DROP TEMPORARY TABLE %s' % tmpTableName_1)
+
+ return tmpTableName_2
+
+
+
+ #XZ, 09/23/2008: In tissue correlation tables, there is no record of GeneId1 == GeneId2
+ #XZ, 09/24/2008: Note that the correlation value can be negative.
+ def getTempTissueCorrTable(self, primaryTraitSymbol="", TissueProbeSetFreezeId=0, method="", returnNumber=0):
+
+ def cmpTissCorrAbsoluteValue(A, B):
+ try:
+ if abs(A[1]) < abs(B[1]): return 1
+ elif abs(A[1]) == abs(B[1]):
+ return 0
+ else: return -1
+ except:
+ return 0
+
+ symbolCorrDict, symbolPvalueDict = self.calculateCorrOfAllTissueTrait(primaryTraitSymbol=primaryTraitSymbol, TissueProbeSetFreezeId=TissueProbeSetFreezeId, method=method)
+
+ symbolCorrList = symbolCorrDict.items()
+
+ symbolCorrList.sort(cmpTissCorrAbsoluteValue)
+ symbolCorrList = symbolCorrList[0 : 2*returnNumber]
+
+ tmpTableName = webqtlUtil.genRandStr(prefix="TOPTISSUE")
+
+ q1 = 'CREATE TEMPORARY TABLE %s (Symbol varchar(100) PRIMARY KEY, Correlation float, PValue float)' % tmpTableName
+ self.cursor.execute(q1)
+
+ for one_pair in symbolCorrList:
+ one_symbol = one_pair[0]
+ one_corr = one_pair[1]
+ one_p_value = symbolPvalueDict[one_symbol]
+
+ self.cursor.execute( "INSERT INTO %s (Symbol, Correlation, PValue) VALUES ('%s',%f,%f)" % (tmpTableName, one_symbol, float(one_corr), float(one_p_value)) )
+
+ return tmpTableName
+
+
+ #XZ, 01/09/2009: This function was created by David Crowell. Xiaodong cleaned up and modified it.
+ def fetchLitCorrelations(self, species, GeneId, db, returnNumber): ### Used to generate Lit Correlations when calculations are done from text file. dcrowell August 2008
+ """Uses getTempLiteratureTable to generate table of literatire correlations. This function then gathers that data and
+ pairs it with the TraitID string. Takes as its arguments a formdata instance, and a database instance.
+ Returns a dictionary of 'TraitID':'LitCorr' for the requested correlation"""
+
+ tempTable = self.getTempLiteratureTable(species=species, input_species_geneid=GeneId, returnNumber=returnNumber)
+
+ query = "SELECT %s.Name, %s.value" % (db.type,tempTable)
+ query += ' FROM (%s, %sXRef, %sFreeze)' % (db.type, db.type, db.type)
+ query += ' LEFT JOIN %s ON %s.GeneId2=ProbeSet.GeneId ' % (tempTable,tempTable)
+ query += "WHERE ProbeSet.GeneId IS NOT NULL AND %s.value IS NOT NULL AND %sXRef.%sFreezeId = %sFreeze.Id and %sFreeze.Name = '%s' and %s.Id = %sXRef.%sId order by %s.Id" % (tempTable, db.type, db.type, db.type, db.type, db.name, db.type, db.type, db.type, db.type)
+
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+
+ litCorrDict = {}
+
+ for entry in results:
+ traitName,litcorr = entry
+ litCorrDict[traitName] = litcorr
+
+ self.cursor.execute('DROP TEMPORARY TABLE %s' % tempTable)
+
+ return litCorrDict
+
+
+
+ #XZ, 01/09/2009: Xiaodong created this function.
+ def fetchTissueCorrelations(self, db, primaryTraitSymbol="", TissueProbeSetFreezeId=0, method="", returnNumber = 0):
+ """Uses getTempTissueCorrTable to generate table of tissue correlations. This function then gathers that data and
+ pairs it with the TraitID string. Takes as its arguments a formdata instance, and a database instance.
+ Returns a dictionary of 'TraitID':(tissueCorr, tissuePValue) for the requested correlation"""
+
+
+ tempTable = self.getTempTissueCorrTable(primaryTraitSymbol=primaryTraitSymbol, TissueProbeSetFreezeId=TissueProbeSetFreezeId, method=method, returnNumber=returnNumber)
+
+ query = "SELECT ProbeSet.Name, %s.Correlation, %s.PValue" % (tempTable, tempTable)
+ query += ' FROM (ProbeSet, ProbeSetXRef, ProbeSetFreeze)'
+ query += ' LEFT JOIN %s ON %s.Symbol=ProbeSet.Symbol ' % (tempTable,tempTable)
+ query += "WHERE ProbeSetFreeze.Name = '%s' and ProbeSetFreeze.Id=ProbeSetXRef.ProbeSetFreezeId and ProbeSet.Id = ProbeSetXRef.ProbeSetId and ProbeSet.Symbol IS NOT NULL AND %s.Correlation IS NOT NULL" % (db.name, tempTable)
+
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+
+ tissueCorrDict = {}
+
+ for entry in results:
+ traitName, tissueCorr, tissuePValue = entry
+ tissueCorrDict[traitName] = (tissueCorr, tissuePValue)
+
+ self.cursor.execute('DROP TEMPORARY TABLE %s' % tempTable)
+
+ return tissueCorrDict
+
+
+
+ #XZ, 01/13/2008
+ def getLiteratureCorrelationByList(self, input_trait_mouse_geneid=None, species=None, traitList=None):
+
+ tmpTableName = webqtlUtil.genRandStr(prefix="LITERATURE")
+
+ q1 = 'CREATE TEMPORARY TABLE %s (GeneId1 int(12) unsigned, GeneId2 int(12) unsigned PRIMARY KEY, value double)' % tmpTableName
+ q2 = 'INSERT INTO %s (GeneId1, GeneId2, value) SELECT GeneId1,GeneId2,value FROM LCorrRamin3 WHERE GeneId1=%s' % (tmpTableName, input_trait_mouse_geneid)
+ q3 = 'INSERT INTO %s (GeneId1, GeneId2, value) SELECT GeneId2,GeneId1,value FROM LCorrRamin3 WHERE GeneId2=%s AND GeneId1!=%s' % (tmpTableName, input_trait_mouse_geneid, input_trait_mouse_geneid)
+
+ for x in [q1,q2,q3]:
+ self.cursor.execute(x)
+
+ for thisTrait in traitList:
+ try:
+ if thisTrait.geneid:
+ thisTrait.mouse_geneid = self.translateToMouseGeneID(species, thisTrait.geneid)
+ else:
+ thisTrait.mouse_geneid = 0
+ except:
+ thisTrait.mouse_geneid = 0
+
+ if thisTrait.mouse_geneid and str(thisTrait.mouse_geneid).find(";") == -1:
+ try:
+ self.cursor.execute("SELECT value FROM %s WHERE GeneId2 = %s" % (tmpTableName, thisTrait.mouse_geneid))
+ result = self.cursor.fetchone()
+ if result:
+ thisTrait.LCorr = result[0]
+ else:
+ thisTrait.LCorr = None
+ except:
+ thisTrait.LCorr = None
+ else:
+ thisTrait.LCorr = None
+
+ self.cursor.execute("DROP TEMPORARY TABLE %s" % tmpTableName)
+
+ return traitList
+
+
+
+ def calculateCorrOfAllTissueTrait(self, primaryTraitSymbol=None, TissueProbeSetFreezeId=None, method=None):
+
+ symbolCorrDict = {}
+ symbolPvalueDict = {}
+
+ primaryTraitSymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[primaryTraitSymbol], TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ primaryTraitValue = primaryTraitSymbolValueDict.values()[0]
+
+ SymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[], TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+
+ if method in ["2","5"]:
+ symbolCorrDict, symbolPvalueDict = correlationFunction.batchCalTissueCorr(primaryTraitValue,SymbolValueDict,method='spearman')
+ else:
+ symbolCorrDict, symbolPvalueDict = correlationFunction.batchCalTissueCorr(primaryTraitValue,SymbolValueDict)
+
+
+ return (symbolCorrDict, symbolPvalueDict)
+
+
+
+ #XZ, 10/13/2010
+ def getTissueCorrelationByList(self, primaryTraitSymbol=None, traitList=None, TissueProbeSetFreezeId=None, method=None):
+
+ primaryTraitSymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[primaryTraitSymbol], TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+
+ if primaryTraitSymbol.lower() in primaryTraitSymbolValueDict:
+ primaryTraitValue = primaryTraitSymbolValueDict[primaryTraitSymbol.lower()]
+
+ geneSymbolList = []
+
+ for thisTrait in traitList:
+ if hasattr(thisTrait, 'symbol'):
+ geneSymbolList.append(thisTrait.symbol)
+
+ SymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=geneSymbolList, TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+
+ for thisTrait in traitList:
+ if hasattr(thisTrait, 'symbol') and thisTrait.symbol and thisTrait.symbol.lower() in SymbolValueDict:
+ oneTraitValue = SymbolValueDict[thisTrait.symbol.lower()]
+ if method in ["2","5"]:
+ result = correlationFunction.calZeroOrderCorrForTiss( primaryTraitValue, oneTraitValue, method='spearman' )
+ else:
+ result = correlationFunction.calZeroOrderCorrForTiss( primaryTraitValue, oneTraitValue)
+ thisTrait.tissueCorr = result[0]
+ thisTrait.tissuePValue = result[2]
+ else:
+ thisTrait.tissueCorr = None
+ thisTrait.tissuePValue = None
+ else:
+ for thisTrait in traitList:
+ thisTrait.tissueCorr = None
+ thisTrait.tissuePValue = None
+
+ return traitList
+
+
+ def getTopInfo(self, myTrait=None, method=None, db=None, target_db_name=None, returnNumber=None, methodDict=None, totalTraits=None, identification=None ):
+
+ if myTrait:
+ if method in ["1","2"]: #genetic correlation
+ info = HT.Paragraph("Values of Record %s in the " % myTrait.getGivenName(), HT.Href(text=myTrait.db.fullname,url=webqtlConfig.INFOPAGEHREF % myTrait.db.name,target="_blank", Class="fwn"),
+ " database were compared to all %d records in the " % totalTraits, HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank", Class="fwn"),
+ ' database. The top %d correlations ranked by the %s are displayed.' % (returnNumber,methodDict[method]),
+ ' You can resort this list using the small arrowheads in the top row.')
+ else:
+ #myTrait.retrieveInfo()#need to know geneid and symbol
+ if method == "3":#literature correlation
+ searchDBName = "Literature Correlation"
+ searchDBLink = "/correlationAnnotation.html#literatureCorr"
+ else: #tissue correlation
+ searchDBName = "Tissue Correlation"
+ searchDBLink = "/correlationAnnotation.html#tissueCorr"
+ info = HT.Paragraph("Your input record %s in the " % myTrait.getGivenName(), HT.Href(text=myTrait.db.fullname,url=webqtlConfig.INFOPAGEHREF % myTrait.db.name,target="_blank", Class="fwn"),
+ " database corresponds to ",
+ HT.Href(text='gene Id %s, and gene symbol %s' % (myTrait.geneid, myTrait.symbol), target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % myTrait.geneid, Class="fs12 fwn"),
+ '. GN ranked all genes in the ', HT.Href(text=searchDBName,url=searchDBLink,target="_blank", Class="fwn"),' database by the %s.' % methodDict[method],
+ ' The top %d probes or probesets in the ' % returnNumber, HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank", Class="fwn"),
+ ' database corresponding to the top genes ranked by the %s are displayed.' %( methodDict[method]),
+ ' You can resort this list using the small arrowheads in the top row.' )
+
+ elif identification:
+ info = HT.Paragraph('Values of %s were compared to all %d traits in ' % (identification, totalTraits),
+ HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank",Class="fwn"),
+ ' database. The TOP %d correlations ranked by the %s are displayed.' % (returnNumber,methodDict[method]),
+ ' You can resort this list using the small arrowheads in the top row.')
+
+ else:
+ info = HT.Paragraph('Trait values were compared to all values in ',
+ HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank",Class="fwn"),
+ ' database. The TOP %d correlations ranked by the %s are displayed.' % (returnNumber,methodDict[method]),
+ ' You can resort this list using the small arrowheads in the top row.')
+
+ if db.type=="Geno":
+ info.append(HT.BR(),HT.BR(),'Clicking on the Locus will open the genotypes data for that locus. Click on the correlation to see a scatter plot of the trait data.')
+ elif db.type=="Publish":
+ info.append(HT.BR(),HT.BR(),'Clicking on the record ID will open the published phenotype data for that publication. Click on the correlation to see a scatter plot of the trait data. ')
+ elif db.type=="ProbeSet":
+ info.append(HT.BR(),'Click the correlation values to generate scatter plots. Select the Record ID to open the Trait Data and Analysis form. Select the symbol to open NCBI Entrez.')
+ else:
+ pass
+
+
+ return info
+
+
+ def createExcelFileWithTitleAndFooter(self, workbook=None, identification=None, db=None, returnNumber=None):
+
+ worksheet = workbook.add_worksheet()
+
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=14, border = 1, border_color="gray")
+
+ ##Write title Info
+ # Modified by Hongqiang Li
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([2, 0], "Trait : %s" % identification, titleStyle)
+ worksheet.write([3, 0], "Database : %s" % db.fullname, titleStyle)
+ worksheet.write([4, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([5, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+ worksheet.write([6, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+ #Write footer info
+ worksheet.write([9 + returnNumber, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA21131), NCI MMHCC (U01CA105417), and NCRR (U01NR 105417)", titleStyle)
+ worksheet.write([10 + returnNumber, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+
+ return worksheet
+
+
+ def getTableHeaderForGeno(self, method=None, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ if method in ["1","3","4"]:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb"), sort=0),
+ THCell(HT.TD('Record', HT.BR(), 'ID', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text='Record ID', idx=1),
+ THCell(HT.TD('Location', HT.BR(), 'Chr and Mb', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text='Location (Chr and Mb)', idx=2),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample r", idx=3),
+ THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=4),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(r)", idx=5)]]
+
+ for ncol, item in enumerate(['Record ID', 'Location (Chr, Mb)', 'Sample r', 'N Cases', 'Sample p(r)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+ else:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb"), sort=0),
+ THCell(HT.TD('Record', HT.BR(), 'ID', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text='Record ID', idx=1),
+ THCell(HT.TD('Location', HT.BR(), 'Chr and Mb', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text='Location (Chr and Mb)', idx=2),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample rho", idx=3),
+ THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=4),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(rho)", idx=5)]]
+
+ for ncol, item in enumerate(['Record ID', 'Location (Chr, Mb)', 'Sample rho', 'N Cases', 'Sample p(rho)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+
+ return tblobj_header, worksheet
+
+
+ def getTableBodyForGeno(self, traitList, formName=None, worksheet=None, newrow=None, corrScript=None):
+
+ tblobj_body = []
+
+ for thisTrait in traitList:
+ tr = []
+
+ trId = str(thisTrait)
+
+ corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.corr))
+
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn ffl"),align="left", Class="fs12 fwn ffl b1 c222"), text=thisTrait.name, val=thisTrait.name.upper()))
+
+ #XZ: trait_location_value is used for sorting
+ trait_location_repr = '--'
+ trait_location_value = 1000000
+
+ if thisTrait.chr and thisTrait.mb:
+ try:
+ trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if thisTrait.chr.upper() == 'X':
+ trait_location_value = 20*1000 + thisTrait.mb
+ else:
+ trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ trait_location_repr = 'Chr%s: %.6f' % (thisTrait.chr, float(thisTrait.mb) )
+
+ tr.append(TDCell(HT.TD(trait_location_repr, Class="fs12 fwn b1 c222", nowrap="on"), trait_location_repr, trait_location_value))
+
+
+ repr='%3.3f' % thisTrait.corr
+ tr.append(TDCell(HT.TD(HT.Href(text=repr, url="javascript:showCorrPlot('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn ffl"), Class="fs12 fwn ffl b1 c222", nowrap='ON', align='right'),repr,abs(thisTrait.corr)))
+
+ repr = '%d' % thisTrait.nOverlap
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222",align='right'),repr,thisTrait.nOverlap))
+
+ repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, trait_location_repr, thisTrait.corr, thisTrait.nOverlap, thisTrait.corrPValue]):
+ worksheet.write([newrow, ncol], item)
+ newrow += 1
+
+ return tblobj_body, worksheet, corrScript
+
+
+ def getTableHeaderForPublish(self, method=None, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ if method in ["1","3","4"]:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), sort=0),
+ THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Record ID", idx=1),
+ THCell(HT.TD('Phenotype', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Phenotype", idx=2),
+ THCell(HT.TD('Authors', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Authors", idx=3),
+ THCell(HT.TD('Year', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Year", idx=4),
+ THCell(HT.TD('Max',HT.BR(), 'LRS', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS", idx=5),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS Location", idx=6),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample r", idx=7),
+ THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=8),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(r)", idx=9)]]
+
+ for ncol, item in enumerate(["Record", "Phenotype", "Authors", "Year", "Pubmed Id", "Max LRS", "Max LRS Location (Chr: Mb)", "Sample r", "N Cases", "Sample p(r)"]):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+ else:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), sort=0),
+ THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Record ID", idx=1),
+ THCell(HT.TD('Phenotype', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Phenotype", idx=2),
+ THCell(HT.TD('Authors', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Authors", idx=3),
+ THCell(HT.TD('Year', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Year", idx=4),
+ THCell(HT.TD('Max',HT.BR(), 'LRS', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS", idx=5),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS Location", idx=6),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample rho", idx=7),
+ THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=8),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(rho)", idx=9)]]
+
+ for ncol, item in enumerate(["Record", "Phenotype", "Authors", "Year", "Pubmed Id", "Max LRS", "Max LRS Location (Chr: Mb)", "Sample rho", "N Cases", "Sample p(rho)"]):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+
+ return tblobj_header, worksheet
+
+
+ def getTableBodyForPublish(self, traitList, formName=None, worksheet=None, newrow=None, corrScript=None, species=''):
+
+ tblobj_body = []
+
+ for thisTrait in traitList:
+ tr = []
+
+ trId = str(thisTrait)
+
+ corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.corr))
+
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn"), nowrap="yes",align="center", Class="fs12 fwn b1 c222"),str(thisTrait.name), thisTrait.name))
+
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ PhenotypeString = thisTrait.pre_publication_description
+
+ tr.append(TDCell(HT.TD(PhenotypeString, Class="fs12 fwn b1 c222"), PhenotypeString, PhenotypeString.upper()))
+
+ tr.append(TDCell(HT.TD(thisTrait.authors, Class="fs12 fwn b1 c222 fsI"),thisTrait.authors, thisTrait.authors.strip().upper()))
+
+ try:
+ PubMedLinkText = myear = repr = int(thisTrait.year)
+ except:
+ PubMedLinkText = repr = "--"
+ myear = 0
+ if thisTrait.pubmed_id:
+ PubMedLink = HT.Href(text= repr,url= webqtlConfig.PUBMEDLINK_URL % thisTrait.pubmed_id,target='_blank', Class="fs12 fwn")
+ else:
+ PubMedLink = repr
+
+ tr.append(TDCell(HT.TD(PubMedLink, Class="fs12 fwn b1 c222", align='center'), repr, myear))
+
+ #LRS and its location
+ LRS_score_repr = '--'
+ LRS_score_value = 0
+ LRS_location_repr = '--'
+ LRS_location_value = 1000000
+ LRS_flag = 1
+
+ #Max LRS and its Locus location
+ if thisTrait.lrs and thisTrait.locus:
+ self.cursor.execute("""
+ select Geno.Chr, Geno.Mb from Geno, Species
+ where Species.Name = '%s' and
+ Geno.Name = '%s' and
+ Geno.SpeciesId = Species.Id
+ """ % (species, thisTrait.locus))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ LRS_Chr = result[0]
+ LRS_Mb = result[1]
+
+ #XZ: LRS_location_value is used for sorting
+ try:
+ LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
+ except:
+ if LRS_Chr.upper() == 'X':
+ LRS_location_value = 20*1000 + float(LRS_Mb)
+ else:
+ LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
+
+
+ LRS_score_repr = '%3.1f' % thisTrait.lrs
+ LRS_score_value = thisTrait.lrs
+ LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
+ LRS_flag = 0
+
+ #tr.append(TDCell(HT.TD(HT.Href(text=LRS_score_repr,url="javascript:showIntervalMapping('%s', '%s : %s')" % (formName, thisTrait.db.shortname, thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn ffl b1 c222", align='right', nowrap="on"),LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222", align='right', nowrap="on"), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222"), LRS_location_repr, LRS_location_value))
+
+ if LRS_flag:
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222"), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222"), LRS_location_repr, LRS_location_value))
+
+ repr = '%3.4f' % thisTrait.corr
+ tr.append(TDCell(HT.TD(HT.Href(text=repr,url="javascript:showCorrPlot('%s', '%s')" % (formName,thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn b1 c222", align='right',nowrap="on"), repr, abs(thisTrait.corr)))
+
+ repr = '%d' % thisTrait.nOverlap
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.nOverlap))
+
+ repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, PhenotypeString, thisTrait.authors, thisTrait.year, thisTrait.pubmed_id, LRS_score_repr, LRS_location_repr, thisTrait.corr, thisTrait.nOverlap, thisTrait.corrPValue]):
+ worksheet.write([newrow, ncol], item)
+ newrow += 1
+
+ return tblobj_body, worksheet, corrScript
+
+
+ def getTableHeaderForProbeSet(self, method=None, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ if method in ["1","3","4"]:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
+ THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Record ID", idx=1),
+ THCell(HT.TD('Gene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Gene ID", idx=2),
+ THCell(HT.TD('Homologene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Homologene ID", idx=3),
+ THCell(HT.TD('Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Symbol", idx=4),
+ THCell(HT.TD('Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Description", idx=5),
+ THCell(HT.TD('Location',HT.BR(), 'Chr and Mb', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Location (Chr: Mb)", idx=6),
+ THCell(HT.TD('Mean',HT.BR(),'Expr',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Mean Expr", idx=7),
+ THCell(HT.TD('Max',HT.BR(),'LRS',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS", idx=8),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS Location (Chr: Mb)", idx=9),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample r", idx=10),
+ THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=11),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(r)", idx=12),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Lit',HT.BR(), 'Corr', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#literatureCorr"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Lit Corr", idx=13),
+ #XZ, 09/22/2008: tissue correlation
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue r", idx=14),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue p(r)", idx=15)]]
+
+ for ncol, item in enumerate(['Record', 'Gene ID', 'Homologene ID', 'Symbol', 'Description', 'Location (Chr: Mb)', 'Mean Expr', 'Max LRS', 'Max LRS Location (Chr: Mb)', 'Sample r', 'N Cases', 'Sample p(r)', 'Lit Corr', 'Tissue r', 'Tissue p(r)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+ else:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
+ THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Record ID", idx=1),
+ THCell(HT.TD('Gene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Gene ID", idx=2),
+ THCell(HT.TD('Homologene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Homologene ID", idx=3),
+ THCell(HT.TD('Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Symbol", idx=4),
+ THCell(HT.TD('Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Description", idx=5),
+ THCell(HT.TD('Location',HT.BR(), 'Chr and Mb', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Location (Chr: Mb)", idx=6),
+ THCell(HT.TD('Mean',HT.BR(),'Expr',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Mean Expr", idx=7),
+ THCell(HT.TD('Max',HT.BR(),'LRS',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS", idx=8),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS Location (Chr: Mb)", idx=9),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample rho", idx=10),
+ THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=11),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(rho)", idx=12),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Lit',HT.BR(), 'Corr', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#literatureCorr"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Lit Corr", idx=13),
+ #XZ, 09/22/2008: tissue correlation
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue rho", idx=14),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue p(rho)", idx=15)]]
+
+ for ncol, item in enumerate(['Record ID', 'Gene ID', 'Homologene ID', 'Symbol', 'Description', 'Location (Chr: Mb)', 'Mean Expr', 'Max LRS', 'Max LRS Location (Chr: Mb)', 'Sample rho', 'N Cases', 'Sample p(rho)', 'Lit Corr', 'Tissue rho', 'Tissue p(rho)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ return tblobj_header, worksheet
+
+
+ def getTableBodyForProbeSet(self, traitList=[], primaryTrait=None, formName=None, worksheet=None, newrow=None, corrScript=None, species=''):
+
+ tblobj_body = []
+
+ for thisTrait in traitList:
+
+ if thisTrait.symbol:
+ pass
+ else:
+ thisTrait.symbol = "--"
+
+ if thisTrait.geneid:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % thisTrait.geneid, Class="fs12 fwn")
+ else:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % thisTrait.symbol, Class="fs12 fwn")
+
+ tr = []
+
+ trId = str(thisTrait)
+
+ corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.corr))
+
+ #XZ, 12/08/2008: checkbox
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+
+ #XZ, 12/08/2008: probeset name
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName,thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn b1 c222"), thisTrait.name, thisTrait.name.upper()))
+
+ #XZ, 12/08/2008: gene id
+ if thisTrait.geneid:
+ tr.append(TDCell(None, thisTrait.geneid, val=999))
+ else:
+ tr.append(TDCell(None, thisTrait.geneid, val=999))
+
+ #XZ, 12/08/2008: homologene id
+ if thisTrait.homologeneid:
+ tr.append(TDCell("", thisTrait.homologeneid, val=999))
+ else:
+ tr.append(TDCell("", thisTrait.homologeneid, val=999))
+
+ #XZ, 12/08/2008: gene symbol
+ tr.append(TDCell(HT.TD(symbolurl, Class="fs12 fwn b1 c222 fsI"),thisTrait.symbol, thisTrait.symbol.upper()))
+
+ #XZ, 12/08/2008: description
+ #XZ, 06/05/2009: Rob asked to add probe target description
+ description_string = str(thisTrait.description).strip()
+ target_string = str(thisTrait.probe_target_description).strip()
+
+ description_display = ''
+
+ if len(description_string) > 1 and description_string != 'None':
+ description_display = description_string
+ else:
+ description_display = thisTrait.symbol
+
+ if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ description_display = description_display + '; ' + target_string.strip()
+
+ tr.append(TDCell(HT.TD(description_display, Class="fs12 fwn b1 c222"), description_display, description_display))
+
+ #XZ: trait_location_value is used for sorting
+ trait_location_repr = '--'
+ trait_location_value = 1000000
+
+ if thisTrait.chr and thisTrait.mb:
+ try:
+ trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if thisTrait.chr.upper() == 'X':
+ trait_location_value = 20*1000 + thisTrait.mb
+ else:
+ trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ trait_location_repr = 'Chr%s: %.6f' % (thisTrait.chr, float(thisTrait.mb) )
+
+ tr.append(TDCell(HT.TD(trait_location_repr, Class="fs12 fwn b1 c222", nowrap="on"), trait_location_repr, trait_location_value))
+
+ """
+ #XZ, 12/08/2008: chromosome number
+ #XZ, 12/10/2008: use Mbvalue to sort chromosome
+ tr.append(TDCell( HT.TD(thisTrait.chr, Class="fs12 fwn b1 c222", align='right'), thisTrait.chr, Mbvalue) )
+
+ #XZ, 12/08/2008: Rob wants 6 digit precision, and we have to deal with that the mb could be None
+ if not thisTrait.mb:
+ tr.append(TDCell(HT.TD(thisTrait.mb, Class="fs12 fwn b1 c222",align='right'), thisTrait.mb, Mbvalue))
+ else:
+ tr.append(TDCell(HT.TD('%.6f' % thisTrait.mb, Class="fs12 fwn b1 c222", align='right'), thisTrait.mb, Mbvalue))
+ """
+
+
+
+ #XZ, 01/12/08: This SQL query is much faster.
+ self.cursor.execute("""
+ select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %d and
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId and
+ ProbeSet.Name = '%s'
+ """ % (thisTrait.db.id, thisTrait.name))
+ result = self.cursor.fetchone()
+ if result:
+ if result[0]:
+ mean = result[0]
+ else:
+ mean=0
+ else:
+ mean = 0
+
+ #XZ, 06/05/2009: It is neccessary to turn on nowrap
+ repr = "%2.3f" % mean
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right', nowrap='ON'),repr, mean))
+
+ #LRS and its location
+ LRS_score_repr = '--'
+ LRS_score_value = 0
+ LRS_location_repr = '--'
+ LRS_location_value = 1000000
+ LRS_flag = 1
+
+ #Max LRS and its Locus location
+ if thisTrait.lrs and thisTrait.locus:
+ self.cursor.execute("""
+ select Geno.Chr, Geno.Mb from Geno, Species
+ where Species.Name = '%s' and
+ Geno.Name = '%s' and
+ Geno.SpeciesId = Species.Id
+ """ % (species, thisTrait.locus))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ LRS_Chr = result[0]
+ LRS_Mb = result[1]
+
+ #XZ: LRS_location_value is used for sorting
+ try:
+ LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
+ except:
+ if LRS_Chr.upper() == 'X':
+ LRS_location_value = 20*1000 + float(LRS_Mb)
+ else:
+ LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
+
+
+ LRS_score_repr = '%3.1f' % thisTrait.lrs
+ LRS_score_value = thisTrait.lrs
+ LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
+ LRS_flag = 0
+
+ #tr.append(TDCell(HT.TD(HT.Href(text=LRS_score_repr,url="javascript:showIntervalMapping('%s', '%s : %s')" % (formName, thisTrait.db.shortname, thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn ffl b1 c222", align='right', nowrap="on"),LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222", align='right', nowrap="on"), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222", nowrap="on"), LRS_location_repr, LRS_location_value))
+
+ if LRS_flag:
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222"), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222"), LRS_location_repr, LRS_location_value))
+
+
+ #XZ, 12/08/2008: generic correlation
+ repr='%3.3f' % thisTrait.corr
+ tr.append(TDCell(HT.TD(HT.Href(text=repr, url="javascript:showCorrPlot('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn ffl"), Class="fs12 fwn ffl b1 c222", align='right'),repr,abs(thisTrait.corr)))
+
+ #XZ, 12/08/2008: number of overlaped cases
+ repr = '%d' % thisTrait.nOverlap
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.nOverlap))
+
+ #XZ, 12/08/2008: p value of genetic correlation
+ repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
+
+ #XZ, 12/08/2008: literature correlation
+ LCorr = 0.0
+ LCorrStr = "--"
+ if hasattr(thisTrait, 'LCorr') and thisTrait.LCorr:
+ LCorr = thisTrait.LCorr
+ LCorrStr = "%2.3f" % thisTrait.LCorr
+ tr.append(TDCell(HT.TD(LCorrStr, Class="fs12 fwn b1 c222", align='right'), LCorrStr, abs(LCorr)))
+
+ #XZ, 09/22/2008: tissue correlation.
+ TCorr = 0.0
+ TCorrStr = "--"
+ #XZ, 11/20/2008: need to pass two geneids: input_trait_mouse_geneid and thisTrait.mouse_geneid
+ if hasattr(thisTrait, 'tissueCorr') and thisTrait.tissueCorr:
+ TCorr = thisTrait.tissueCorr
+ TCorrStr = "%2.3f" % thisTrait.tissueCorr
+ # NL, 07/19/2010: add a new parameter rankOrder for js function 'showTissueCorrPlot'
+ rankOrder = thisTrait.rankOrder
+ TCorrPlotURL = "javascript:showTissueCorrPlot('%s','%s','%s',%d)" %(formName, primaryTrait.symbol, thisTrait.symbol,rankOrder)
+ tr.append(TDCell(HT.TD(HT.Href(text=TCorrStr, url=TCorrPlotURL, Class="fs12 fwn ff1"), Class="fs12 fwn ff1 b1 c222", align='right'), TCorrStr, abs(TCorr)))
+ else:
+ tr.append(TDCell(HT.TD(TCorrStr, Class="fs12 fwn b1 c222", align='right'), TCorrStr, abs(TCorr)))
+
+ #XZ, 12/08/2008: p value of tissue correlation
+ TPValue = 1.0
+ TPValueStr = "--"
+ if hasattr(thisTrait, 'tissueCorr') and thisTrait.tissuePValue: #XZ, 09/22/2008: thisTrait.tissuePValue can't be used here because it could be 0
+ TPValue = thisTrait.tissuePValue
+ TPValueStr = "%2.3f" % thisTrait.tissuePValue
+ tr.append(TDCell(HT.TD(TPValueStr, Class="fs12 fwn b1 c222", align='right'), TPValueStr, TPValue))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, thisTrait.geneid, thisTrait.homologeneid, thisTrait.symbol, thisTrait.description, trait_location_repr, mean, LRS_score_repr, LRS_location_repr, thisTrait.corr, thisTrait.nOverlap, thisTrait.corrPValue, LCorr, TCorr, TPValue]):
+ worksheet.write([newrow, ncol], item)
+
+ newrow += 1
+
+ return tblobj_body, worksheet, corrScript
diff --git a/web/webqtl/correlation/PartialCorrDBPage.py b/web/webqtl/correlation/PartialCorrDBPage.py
new file mode 100755
index 00000000..ecd1e623
--- /dev/null
+++ b/web/webqtl/correlation/PartialCorrDBPage.py
@@ -0,0 +1,1359 @@
+import string
+import cPickle
+import os
+import pyXLWriter as xl
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+#import webqtlData
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+from base.webqtlTrait import webqtlTrait
+from base.webqtlDataset import webqtlDataset
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from CorrelationPage import CorrelationPage
+import correlationFunction
+from dbFunction import webqtlDatabaseFunction
+
+
+#########################################
+# Partial Correlation Dataset Page
+#########################################
+
+
+class PartialCorrDBPage(CorrelationPage):
+
+ corrMinInformative = 4
+
+ def __init__(self, fd):
+
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+
+ primaryTraitString = fd.formdata.getvalue('primaryTrait')
+ primaryTrait = (webqtlTrait(fullname=primaryTraitString, cursor=self.cursor))
+
+ controlTraitsString = fd.formdata.getvalue('controlTraits')
+ controlTraitsList = list(string.split(controlTraitsString,','))
+ controlTraits = []
+ for item in controlTraitsList:
+ controlTraits.append(webqtlTrait(fullname=item, cursor=self.cursor))
+
+ #XZ, 3/16/2010: variable RISet must be pass by the form
+ RISet = fd.RISet
+ #XZ, 12/12/2008: get species infomation
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=RISet)
+
+ #XZ, 09/18/2008: get all information about the user selected database.
+ self.target_db_name = fd.formdata.getvalue('database2')
+
+ try:
+ self.db = webqtlDataset(self.target_db_name, self.cursor)
+ except:
+ heading = "Partial Correlation Table"
+ detail = ["The database you just requested has not been established yet."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ, 09/18/2008: check if user has the authority to get access to the database.
+ if self.db.type == 'ProbeSet':
+ self.cursor.execute('SELECT Id, Name, FullName, confidentiality, AuthorisedUsers FROM ProbeSetFreeze WHERE Name = "%s"' % self.target_db_name)
+ indId, indName, indFullName, confidential, AuthorisedUsers = self.cursor.fetchall()[0]
+
+ if confidential == 1:
+ access_to_confidential_dataset = 0
+
+ #for the dataset that confidentiality is 1
+ #1. 'admin' and 'root' can see all of the dataset
+ #2. 'user' can see the dataset that AuthorisedUsers contains his id(stored in the Id field of User table)
+ if webqtlConfig.USERDICT[self.privilege] > webqtlConfig.USERDICT['user']:
+ access_to_confidential_dataset = 1
+ else:
+ AuthorisedUsersList=AuthorisedUsers.split(',')
+ if AuthorisedUsersList.__contains__(self.userName):
+ access_to_confidential_dataset = 1
+
+ if not access_to_confidential_dataset:
+ #Error, Confidential Database
+ heading = "Partial Correlation Table"
+ detail = ["The %s database you selected is not open to the public at this time, please go back and select another database." % indFullName]
+ self.error(heading=heading,detail=detail,error="Confidential Database")
+ return
+
+
+ primaryTrait.retrieveData()
+ _primarystrains, _primaryvals, _primaryvars = primaryTrait.exportInformative()
+
+ controlTraitNames = fd.formdata.getvalue('controlTraits')
+ _controlstrains,_controlvals,_controlvars,_controlNs = correlationFunction.controlStrains(controlTraitNames,_primarystrains)
+
+ ## If the strains for which each of the control traits and the primary trait have values are not identical,
+ ## we must remove from the calculation all vlaues for strains that are not present in each. Without doing this,
+ ## undesirable biases would be introduced.
+
+ common_primary_control_strains = _primarystrains #keep _primarystrains
+ fixed_primary_vals = _primaryvals #keep _primaryvals
+ fixed_control_vals = _controlvals
+
+ allsame = True
+ ##allsame is boolean for whether or not primary and control trait have values for the same strains
+ for i in _controlstrains:
+ if _primarystrains != i:
+ allsame=False
+ break
+
+ if not allsame:
+ common_primary_control_strains, fixed_primary_vals, fixed_control_vals, _vars, _controlvars = correlationFunction.fixStrains(_primarystrains,_controlstrains,_primaryvals,_controlvals,_primaryvars,_controlvars)
+
+ N = len(common_primary_control_strains)
+ if N < self.corrMinInformative:
+ heading = "Partial Correlation Table"
+ detail = ['Fewer than %d strain data were entered for %s data set. No calculation of correlation has been attempted.' % (self.corrMinInformative, RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ: We should check the value of control trait and primary trait here.
+ nameOfIdenticalTraits = correlationFunction.findIdenticalTraits ( fixed_primary_vals, primaryTraitString, fixed_control_vals, controlTraitsList )
+ if nameOfIdenticalTraits:
+ heading = "Partial Correlation Table"
+ detail = ['%s and %s have same values for the %s strains that will be used to calculate partial correlation (common for all primary and control traits). In such case, partial correlation can NOT be calculated. Please re-select your traits.' % (nameOfIdenticalTraits[0], nameOfIdenticalTraits[1], len(fixed_primary_vals))]
+ self.error(heading=heading,detail=detail)
+ return
+
+
+ #XZ, 09/28/2008: if user select "1", then display 1, 3 and 4.
+ #XZ, 09/28/2008: if user select "2", then display 2, 3 and 5.
+ #XZ, 09/28/2008: if user select "3", then display 1, 3 and 4.
+ #XZ, 09/28/2008: if user select "4", then display 1, 3 and 4.
+ #XZ, 09/28/2008: if user select "5", then display 2, 3 and 5.
+ methodDict = {"1":"Genetic Correlation (Pearson's r)","2":"Genetic Correlation (Spearman's rho)","3":"SGO Literature Correlation","4":"Tissue Correlation (Pearson's r)", "5":"Tissue Correlation (Spearman's rho)"}
+ self.method = fd.formdata.getvalue('method')
+ if self.method not in ("1","2","3","4","5"):
+ self.method = "1"
+
+ self.returnNumber = int(fd.formdata.getvalue('criteria'))
+
+ myTrait = primaryTrait
+ myTrait.retrieveInfo()
+
+ # We will not get Literature Correlations if there is no GeneId because there is nothing to look against
+ try:
+ input_trait_GeneId = myTrait.geneid
+ except:
+ input_trait_GeneId = None
+
+ # We will not get Tissue Correlations if there is no gene symbol because there is nothing to look against
+ try:
+ input_trait_symbol = myTrait.symbol
+ except:
+ input_trait_symbol = None
+
+
+ #XZ, 12/12/2008: if the species is rat or human, translate the geneid to mouse geneid
+ input_trait_mouse_geneid = self.translateToMouseGeneID(species, input_trait_GeneId)
+
+ #XZ: As of Nov/13/2010, this dataset is 'UTHSC Illumina V6.2 RankInv B6 D2 average CNS GI average (May 08)'
+ TissueProbeSetFreezeId = 1
+
+
+ #XZ, 09/22/2008: If we need search by GeneId,
+ #XZ, 09/22/2008: we have to check if this GeneId is in the literature or tissue correlation table.
+ #XZ, 10/15/2008: We also to check if the selected database is probeset type.
+ if self.method == "3" or self.method == "4" or self.method == "5":
+ if self.db.type != "ProbeSet":
+ self.error(heading="Wrong correlation type",detail="It is not possible to compute the %s between your trait and data in this %s database. Please try again after selecting another type of correlation." % (methodDict[self.method],self.db.name),error="Correlation Type Error")
+ return
+
+ """
+ if not input_trait_GeneId:
+ self.error(heading="No Associated GeneId",detail="This trait has no associated GeneId, so we are not able to show any literature or tissue related information.",error="No GeneId Error")
+ return
+ """
+
+ #XZ: We have checked geneid did exist
+
+ if self.method == "3":
+ if not input_trait_GeneId or not self.checkForLitInfo(input_trait_mouse_geneid):
+ self.error(heading="No Literature Info",detail="This gene does not have any associated Literature Information.",error="Literature Correlation Error")
+ return
+
+ if self.method == "4" or self.method == "5":
+ if not input_trait_symbol:
+ self.error(heading="No Tissue Correlation Information",detail="This gene does not have any associated Tissue Correlation Information.",error="Tissue Correlation Error")
+ return
+
+ if not self.checkSymbolForTissueCorr(TissueProbeSetFreezeId, myTrait.symbol):
+ self.error(heading="No Tissue Correlation Information",detail="This gene does not have any associated Tissue Correlation Information.",error="Tissue Correlation Error")
+ return
+
+#######################################################################################################################################
+
+ nnCorr = len(fixed_primary_vals)
+
+ #XZ: Use the fast method only for probeset dataset, and this dataset must have been created.
+ #XZ: Otherwise, use original method
+
+ useFastMethod = False
+
+ if self.db.type == "ProbeSet":
+ DatabaseFileName = self.getFileName( target_db_name=self.target_db_name )
+ DirectoryList = os.listdir(webqtlConfig.TEXTDIR) # List of existing text files. Used to check if a text file already exists
+ if DatabaseFileName in DirectoryList:
+ useFastMethod = True
+
+ if useFastMethod:
+ totalTraits, allcorrelations = self.getPartialCorrelationsFast(common_primary_control_strains , fixed_primary_vals, fixed_control_vals, nnCorr, DatabaseFileName, species, input_trait_GeneId, input_trait_symbol, TissueProbeSetFreezeId)
+
+ if totalTraits == 0:
+ useFastMethod = False
+
+ #XZ, 01/08/2009: use the original method to retrieve from database and compute.
+ if not useFastMethod:
+ totalTraits, allcorrelations = self.getPartialCorrelationsNormal(common_primary_control_strains, fixed_primary_vals, fixed_control_vals, nnCorr, species, input_trait_GeneId, input_trait_symbol,TissueProbeSetFreezeId)
+
+#############################################################
+
+ if self.method == "3" and input_trait_GeneId:
+ allcorrelations.sort(self.cmpLitCorr)
+ elif self.method in ["4","5"] and input_trait_GeneId:
+ allcorrelations.sort(self.cmpLitCorr)
+ else:
+ allcorrelations.sort(self.cmpPartialCorrPValue)
+
+ #XZ, 09/20/2008: we only need the top ones.
+ self.returnNumber = min(self.returnNumber,len(allcorrelations))
+ allcorrelations = allcorrelations[:self.returnNumber]
+
+ addLiteratureCorr = False
+ addTissueCorr = False
+
+ traitList = []
+ for item in allcorrelations:
+ thisTrait = webqtlTrait(db=self.db, name=item[0], cursor=self.cursor)
+ thisTrait.retrieveInfo()
+
+ thisTrait.Name = item[0]
+ thisTrait.NOverlap = item[1]
+
+ thisTrait.partial_corr = item[2]
+ thisTrait.partial_corrPValue = item[3]
+
+ thisTrait.corr = item[4]
+ thisTrait.corrPValue = item[5]
+ # NL, 07/19/2010
+ # js function changed, add a new parameter rankOrder for js function 'showTissueCorrPlot'
+ rankOrder = 0;
+ if self.method in ["2","5"]:
+ rankOrder = 1;
+ thisTrait.rankOrder = rankOrder
+
+ #XZ, 26/09/2008: Method is 4 or 5. Have fetched tissue corr, but no literature correlation yet.
+ if len(item) == 8:
+ thisTrait.tissueCorr = item[6]
+ thisTrait.tissuePValue = item[7]
+ addLiteratureCorr = True
+
+ #XZ, 26/09/2008: Method is 3, Have fetched literature corr, but no tissue corr yet.
+ elif len(item) == 7:
+ thisTrait.LCorr = item[6]
+ thisTrait.mouse_geneid = self.translateToMouseGeneID(species, thisTrait.geneid)
+ addTissueCorr = True
+
+ #XZ, 26/09/2008: Method is 1 or 2. Have NOT fetched literature corr and tissue corr yet.
+ # Phenotype data will not have geneid, and neither will some probes
+ # we need to handle this because we will get an attribute error
+ else:
+ if input_trait_mouse_geneid and self.db.type=="ProbeSet":
+ addLiteratureCorr = True
+ if input_trait_symbol and self.db.type=="ProbeSet":
+ addTissueCorr = True
+
+ traitList.append(thisTrait)
+
+ if addLiteratureCorr:
+ traitList = self.getLiteratureCorrelationByList(input_trait_mouse_geneid, species, traitList)
+ if addTissueCorr:
+ traitList = self.getTissueCorrelationByList(primaryTraitSymbol=input_trait_symbol, traitList=traitList,TissueProbeSetFreezeId=TissueProbeSetFreezeId, method=self.method)
+
+########################################################
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ mainfmName = webqtlUtil.genRandStr("fm_")
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name= mainfmName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase', 'ProbeSetID':'_','database':self.target_db_name, 'CellID':'_', 'RISet':RISet, 'identification':fd.identification}
+
+ if myTrait:
+ hddn['fullname']=str(myTrait)
+
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ #XZ, 11/21/2008: add two parameters to form
+ form.append(HT.Input(name="X_geneSymbol", value="", type='hidden'))
+ form.append(HT.Input(name="Y_geneSymbol", value="", type='hidden'))
+
+ #XZ, 3/11/2010: add one parameter to record if the method is rank order.
+
+ form.append(HT.Input(name="rankOrder", value="%s" % rankOrder, type='hidden'))
+
+ form.append(HT.Input(name="TissueProbeSetFreezeId", value="%s" % TissueProbeSetFreezeId, type='hidden'))
+
+
+ ####################################
+ # generate the info on top of page #
+ ####################################
+
+ info_form = self.getFormForPrimaryAndControlTraits (primaryTrait, controlTraits)
+ info = self.getTopInfo(myTrait=myTrait, method=self.method, db=self.db, target_db_name=self.target_db_name, returnNumber=self.returnNumber, methodDict=methodDict, totalTraits=totalTraits, identification=fd.identification )
+
+ ##############
+ # Excel file #
+ ##############
+ filename= webqtlUtil.genRandStr("Corr_")
+ xlsUrl = HT.Input(type='button', value = 'Download Table', onClick= "location.href='/tmp/%s.xls'" % filename, Class='button')
+ # Create a new Excel workbook
+ workbook = xl.Writer('%s.xls' % (webqtlConfig.TMPDIR+filename))
+ headingStyle = workbook.add_format(align = 'center', bold = 1, border = 1, size=13, fg_color = 0x1E, color="white")
+
+ #XZ, 3/18/2010: pay attention to the line number of header in this file. As of today, there are 7 lines.
+ worksheet = self.createExcelFileWithTitleAndFooter(workbook=workbook, identification=fd.identification, db=self.db, returnNumber=self.returnNumber)
+
+ newrow = 7
+
+
+
+#####################################################################
+
+ mintmap = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'showIntMap');" % mainfmName)
+ mintmap_img = HT.Image("/images/multiple_interval_mapping1_final.jpg", name='mintmap', alt="Multiple Interval Mapping", title="Multiple Interval Mapping", style="border:none;")
+ mintmap.append(mintmap_img)
+ mcorr = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'compCorr');" % mainfmName)
+ mcorr_img = HT.Image("/images/compare_correlates2_final.jpg", alt="Compare Correlates", title="Compare Correlates", style="border:none;")
+ mcorr.append(mcorr_img)
+ cormatrix = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'corMatrix');" % mainfmName)
+ cormatrix_img = HT.Image("/images/correlation_matrix1_final.jpg", alt="Correlation Matrix and PCA", title="Correlation Matrix and PCA", style="border:none;")
+ cormatrix.append(cormatrix_img)
+ networkGraph = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'networkGraph');" % mainfmName)
+ networkGraph_img = HT.Image("/images/network_graph1_final.jpg", name='mintmap', alt="Network Graphs", title="Network Graphs", style="border:none;")
+ networkGraph.append(networkGraph_img)
+ heatmap = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'heatmap');" % mainfmName)
+ heatmap_img = HT.Image("/images/heatmap2_final.jpg", name='mintmap', alt="QTL Heat Map and Clustering", title="QTL Heatmap and Clustering", style="border:none;")
+ heatmap.append(heatmap_img)
+ partialCorr = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'partialCorrInput');" % mainfmName)
+ partialCorr_img = HT.Image("/images/partial_correlation_final.jpg", name='partialCorr', alt="Partial Correlation", title="Partial Correlation", style="border:none;")
+ partialCorr.append(partialCorr_img)
+ addselect = HT.Href(url="#redirect", onClick="addRmvSelection('%s', document.getElementsByName('%s')[0], 'addToSelection');" % (RISet, mainfmName))
+ addselect_img = HT.Image("/images/add_collection1_final.jpg", name="addselect", alt="Add To Collection", title="Add To Collection", style="border:none;")
+ addselect.append(addselect_img)
+ selectall = HT.Href(url="#redirect", onClick="checkAll(document.getElementsByName('%s')[0]);" % mainfmName)
+ selectall_img = HT.Image("/images/select_all2_final.jpg", name="selectall", alt="Select All", title="Select All", style="border:none;")
+ selectall.append(selectall_img)
+ selectinvert = HT.Href(url="#redirect", onClick = "checkInvert(document.getElementsByName('%s')[0]);" % mainfmName)
+ selectinvert_img = HT.Image("/images/invert_selection2_final.jpg", name="selectinvert", alt="Invert Selection", title="Invert Selection", style="border:none;")
+ selectinvert.append(selectinvert_img)
+ reset = HT.Href(url="#redirect", onClick="checkNone(document.getElementsByName('%s')[0]); return false;" % mainfmName)
+ reset_img = HT.Image("/images/select_none2_final.jpg", alt="Select None", title="Select None", style="border:none;")
+ reset.append(reset_img)
+ selecttraits = HT.Input(type='button' ,name='selecttraits',value='Select Traits', onClick="checkTraits(this.form);",Class="button")
+ selectgt = HT.Input(type='text' ,name='selectgt',value='-1.0', size=6,maxlength=10,onChange="checkNumeric(this,1.0,'-1.0','gthan','greater than filed')")
+ selectlt = HT.Input(type='text' ,name='selectlt',value='1.0', size=6,maxlength=10,onChange="checkNumeric(this,-1.0,'1.0','lthan','less than field')")
+ selectandor = HT.Select(name='selectandor')
+ selectandor.append(('AND','and'))
+ selectandor.append(('OR','or'))
+ selectandor.selected.append('AND')
+
+ chrMenu = HT.Input(type='hidden',name='chromosomes',value='all')
+
+ corrHeading = HT.Paragraph('Partial Correlation Table', Class="title")
+
+
+ pageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%", border=0, align="Left")
+ containerTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="90%",border=0, align="Left")
+
+ optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="320", height="80", border=0, align="Left")
+ optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), align="left"))
+ optionsTable.append(HT.TR(HT.TD("&nbsp;"*1,"Select"), HT.TD("Deselect"), HT.TD("&nbsp;"*1,"Invert"), HT.TD("&nbsp;"*3,"Add")))
+ containerTable.append(HT.TR(HT.TD(optionsTable)))
+
+ functionTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="480",height="80", border=0, align="Left")
+ functionRow = HT.TR(HT.TD(networkGraph, width="16.7%"), HT.TD(cormatrix, width="16.7%"), HT.TD(partialCorr, width="16.7%"), HT.TD(mcorr, width="16.7%"), HT.TD(mintmap, width="16.7%"), HT.TD(heatmap), align="left")
+ labelRow = HT.TR(HT.TD("&nbsp;"*1,HT.Text("Graph")), HT.TD("&nbsp;"*1,HT.Text("Matrix")), HT.TD("&nbsp;"*1,HT.Text("Partial")), HT.TD(HT.Text("Compare")), HT.TD(HT.Text("QTL Map")), HT.TD(HT.Text(text="Heat Map")))
+ functionTable.append(functionRow, labelRow)
+ containerTable.append(HT.TR(HT.TD(functionTable), HT.BR()))
+
+ moreOptions = HT.Input(type='button',name='options',value='More Options', onClick="",Class="toggle")
+ fewerOptions = HT.Input(type='button',name='options',value='Fewer Options', onClick="",Class="toggle")
+
+ if (fd.formdata.getvalue('showHideOptions') == 'less'):
+ containerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD("&nbsp;")))
+ else:
+ containerTable.append(HT.TR(HT.TD("&nbsp;"), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD("&nbsp;")))
+
+ containerTable.append(HT.TR(HT.TD(HT.Span(selecttraits,' with partial r > ',selectgt, ' ',selectandor, ' r < ',selectlt,Class="bd1 cbddf fs11")), style="display:none;", Class="extra_options"))
+
+
+ tblobj = {}
+
+
+ if self.db.type=="Geno":
+
+ containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
+ pageTable.append(HT.TR(HT.TD(containerTable)))
+
+ tblobj['header'], worksheet = self.getTableHeaderForGeno( method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+ newrow += 1
+
+ corrScript = HT.Script(language="Javascript")
+ corrScript.append("var corrArray = new Array();")
+
+ sortby = self.getSortByValue( calculationMethod = self.method )
+
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForGeno(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript)
+
+ workbook.close()
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+ # NL, 07/27/2010. genTableObj function has been moved from templatePage.py to webqtlUtil.py;
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), corrScript, Id="sortable")
+ pageTable.append(HT.TR(HT.TD(div)))
+ form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
+ HT.Input(name='ShowLine',type='hidden', value =1),
+ HT.P(),pageTable)
+
+ TD_LR.append(corrHeading, info_form, HT.P(), info, form, HT.P())
+
+ self.dict['body'] = str(TD_LR)
+ # updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
+ self.dict['js1'] = ''
+ self.dict['title'] = 'Partial Correlation Result'
+
+ elif self.db.type=="Publish":
+
+ containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
+ pageTable.append(HT.TR(HT.TD(containerTable)))
+
+ tblobj['header'], worksheet = self.getTableHeaderForPublish(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+ newrow += 1
+
+ sortby = self.getSortByValue( calculationMethod = self.method )
+
+ corrScript = HT.Script(language="Javascript")
+ corrScript.append("var corrArray = new Array();")
+
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForPublish(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript)
+
+ workbook.close()
+
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+ # NL, 07/27/2010. genTableObj function has been moved from templatePage.py to webqtlUtil.py;
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), corrScript, Id="sortable")
+ pageTable.append(HT.TR(HT.TD(div)))
+
+ form.append(
+ HT.Input(name='ShowStrains',type='hidden', value =1),
+ HT.Input(name='ShowLine',type='hidden', value =1),
+ HT.P(),pageTable)
+
+ TD_LR.append(corrHeading, info_form, HT.P(), info, form, HT.P())
+
+ self.dict['body'] = str(TD_LR)
+ #updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
+ self.dict['js1'] = ''
+ self.dict['title'] = 'Partial Correlation Result'
+
+ elif self.db.type=="ProbeSet":
+
+ tblobj['header'], worksheet = self.getTableHeaderForProbeSet(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+ newrow += 1
+
+ sortby = self.getSortByValue( calculationMethod = self.method )
+
+ corrScript = HT.Script(language="Javascript")
+ corrScript.append("var corrArray = new Array();")
+
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForProbeSet(traitList=traitList, primaryTrait=myTrait, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript)
+
+ workbook.close()
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ '''
+ #XZ, 07/07/2010: I comment out this block of code.
+ WebGestaltScript = HT.Script(language="Javascript")
+ WebGestaltScript.append("""
+setTimeout('openWebGestalt()', 2000);
+function openWebGestalt(){
+ var thisForm = document['WebGestalt'];
+ makeWebGestaltTree(thisForm, '%s', %d, 'edag_only.php');
+}
+ """ % (mainfmName, len(traitList)))
+ '''
+
+ #XZ: here is the table of traits
+ # NL, 07/27/2010. genTableObj function has been moved from templatePage.py to webqtlUtil.py;
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), corrScript, Id="sortable")
+
+ self.cursor.execute('SELECT GeneChip.GO_tree_value FROM GeneChip, ProbeFreeze, ProbeSetFreeze WHERE GeneChip.Id = ProbeFreeze.ChipId and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Name = "%s"' % self.db.name)
+ result = self.cursor.fetchone()
+
+ if result:
+ GO_tree_value = result[0]
+
+ if GO_tree_value:
+
+ hddnWebGestalt = {
+ 'id_list':'',
+ 'correlation':'',
+ 'id_value':'',
+ 'llid_list':'',
+ 'id_type':GO_tree_value,
+ 'idtype':'',
+ 'species':'',
+ 'list':'',
+ 'client':''}
+
+ hddnWebGestalt['ref_type'] = hddnWebGestalt['id_type']
+ hddnWebGestalt['cat_type'] = 'GO'
+ hddnWebGestalt['significancelevel'] = 'Top10'
+
+ if species == 'rat':
+ hddnWebGestalt['org'] = 'Rattus norvegicus'
+ elif species == 'human':
+ hddnWebGestalt['org'] = 'Homo sapiens'
+ elif species == 'mouse':
+ hddnWebGestalt['org'] = 'Mus musculus'
+ else:
+ hddnWebGestalt['org'] = ''
+
+ for key in hddnWebGestalt.keys():
+ form.append(HT.Input(name=key, value=hddnWebGestalt[key], type='hidden'))
+
+ #XZ, 01/12/2009: create database menu for 'Add Correlation'
+ self.cursor.execute("""
+ select
+ ProbeSetFreeze.FullName, ProbeSetFreeze.Id, Tissue.name
+ from
+ ProbeSetFreeze, ProbeFreeze, ProbeSetFreeze as ps2, ProbeFreeze as p2, Tissue
+ where
+ ps2.Id = %d
+ and ps2.ProbeFreezeId = p2.Id
+ and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id
+ and (ProbeFreeze.InbredSetId = p2.InbredSetId or (ProbeFreeze.InbredSetId in (1, 3) and p2.InbredSetId in (1, 3)))
+ and p2.ChipId = ProbeFreeze.ChipId
+ and ps2.Id != ProbeSetFreeze.Id
+ and ProbeFreeze.TissueId = Tissue.Id
+ and ProbeSetFreeze.public > %d
+ order by
+ ProbeFreeze.TissueId, ProbeSetFreeze.CreateTime desc
+ """ % (self.db.id, webqtlConfig.PUBLICTHRESH))
+
+ results = self.cursor.fetchall()
+ dbCustomizer = HT.Select(results, name = "customizer")
+ databaseMenuSub = preTissue = ""
+ for item in results:
+ TName, TId, TTissue = item
+ if TTissue != preTissue:
+ if databaseMenuSub:
+ dbCustomizer.append(databaseMenuSub)
+ databaseMenuSub = HT.Optgroup(label = '%s mRNA ------' % TTissue)
+ preTissue = TTissue
+
+ databaseMenuSub.append(item[:2])
+ if databaseMenuSub:
+ dbCustomizer.append(databaseMenuSub)
+ #updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
+ #variables: filename, strainIds and vals are required by getquerystring function
+ strainIds=self.getStrainIds(species=species, strains=_primarystrains)
+ var1 = HT.Input(name="filename", value=filename, type='hidden')
+ var2 = HT.Input(name="strainIds", value=strainIds, type='hidden')
+ var3 = HT.Input(name="vals", value=_primaryvals, type='hidden')
+ customizerButton = HT.Input(type="button", Class="button", value="Add Correlation", onClick = "xmlhttpPost('%smain.py?FormID=AJAX_table', 'sortable', (getquerystring(this.form)))" % webqtlConfig.CGIDIR)
+
+ containerTable.append(HT.TR(HT.TD(HT.Span(var1,var2,var3,customizerButton, "with", dbCustomizer, Class="bd1 cbddf fs11"), HT.BR(), HT.BR()), style="display:none;", Class="extra_options"))
+
+ #outside analysis part
+ GCATButton = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'GCAT');" % mainfmName)
+ GCATButton_img = HT.Image("/images/GCAT_logo_final.jpg", name="GCAT", alt="GCAT", title="GCAT", style="border:none")
+ GCATButton.append(GCATButton_img)
+
+ ODE = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'ODE');" % mainfmName)
+ ODE_img = HT.Image("/images/ODE_logo_final.jpg", name="ode", alt="ODE", title="ODE", style="border:none")
+ ODE.append(ODE_img)
+
+ WebGestalt = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'GOTree');" % mainfmName)
+ WebGestalt_img = HT.Image("/images/webgestalt_icon_final.jpg", name="webgestalt", alt="Gene Set Analysis Toolkit", title="Gene Set Analysis Toolkit", style="border:none")
+ WebGestalt.append(WebGestalt_img)
+
+ LinkOutTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="320",height="80", border=0, align="Left")
+ if not GO_tree_value:
+ LinkOutRow = HT.TR(HT.TD(GCATButton, width="50%"), HT.TD(ODE, width="50%"), align="left")
+ LinkOutLabels = HT.TR(HT.TD("&nbsp;", HT.Text("GCAT"), width="50%"), HT.TD("&nbsp;",HT.Text("ODE"), width="50%"), align="left")
+ else:
+ LinkOutRow = HT.TR(HT.TD(WebGestalt, width="25%"), HT.TD(GCATButton, width="25%"), HT.TD(ODE, width="25%"), align="left")
+ LinkOutLabels = HT.TR(HT.TD(HT.Text("Gene Set")), HT.TD("&nbsp;"*2, HT.Text("GCAT")), HT.TD("&nbsp;"*3, HT.Text("ODE")), style="display:none;", Class="extra_options")
+ LinkOutTable.append(LinkOutRow,LinkOutLabels)
+
+ containerTable.append(HT.TR(HT.TD(LinkOutTable), Class="extra_options", style="display:none;"))
+
+ containerTable.append(HT.TR(HT.TD(xlsUrl, HT.BR(), HT.BR(), height=40)))
+
+ pageTable.append(HT.TR(HT.TD(containerTable)))
+
+ pageTable.append(HT.TR(HT.TD(div)))
+
+ if species == 'human':
+ heatmap = ""
+
+ form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
+ HT.Input(name='ShowLine',type='hidden', value =1),
+ info, HT.BR(), pageTable, HT.BR())
+
+ TD_LR.append(corrHeading, info_form, HT.P(), form, HT.P())
+
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = 'Partial Correlation Result'
+ # updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
+ self.dict['js1'] = ''
+ self.dict['js2'] = 'onLoad="pageOffset()"'
+ self.dict['layer'] = self.generateWarningLayer()
+
+ else:
+ self.dict['body'] = ""
+
+
+
+####################################
+# #
+#Partial CorrelationPage Functions #
+# #
+####################################
+
+
+ def getSortByValue(self, calculationMethod):
+
+ sortby = ("partial_pv", "up")
+
+ if calculationMethod == "3": #XZ: literature correlation
+ sortby = ("lcorr","down")
+ elif calculationMethod == "4" or calculationMethod == "5": #XZ: tissue correlation
+ sortby = ("tissuecorr", "down")
+
+ return sortby
+
+
+ #XZ, 3/31/2010:
+ #A[0] holds trait name.
+ #A[1] holds partial correlation coefficient number.
+ #A[2] holds N.
+ #A[3] holds p value of partial correlation.
+ def cmpPartialCorrPValue (self, A, B):
+ try:
+ if A[3] < B[3]:
+ return -1
+ elif A[3] == B[3]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+
+ #XZ, 4/1/2010:
+ #A[0] holds trait name.
+ #A[1] holds N.
+ #A[2] holds partial correlation coefficient number.
+ #A[3] holds p value of partial correlation.
+ #A[6] holds literature corr or tissue corr value.
+ #Sort by literature corr or tissue corr first, then by partial corr p value.
+ def cmpLitCorr(self, A, B):
+ try:
+ if abs(A[6]) < abs(B[6]):
+ return 1
+ elif abs(A[6]) == abs(B[6]):
+ if A[3] < B[3]:
+ return -1
+ elif A[3] == B[3]:
+ return 0
+ else:
+ return 1
+ else:
+ return -1
+ except:
+ return 0
+
+
+ def getPartialCorrelationsFast(self, _strains, _vals, _controlvals, nnCorr, DatabaseFileName, species, input_trait_GeneId,gene_symbol,TissueProbeSetFreezeId ):
+ """Calculates and returns correlation coefficients using data from a csv text file."""
+
+ try:
+ allcorrelations = []
+
+ useLit = False
+ if self.method == "3":
+ litCorrs = self.fetchLitCorrelations(species=species, GeneId=input_trait_GeneId, db=self.db, returnNumber=self.returnNumber)
+ useLit = True
+
+ useTissueCorr = False
+ if self.method == "4" or self.method == "5":
+ tissueCorrs = self.fetchTissueCorrelations(db=self.db,primaryTraitSymbol=gene_symbol, TissueProbeSetFreezeId=TissueProbeSetFreezeId, method=self.method, returnNumber=self.returnNumber)
+ useTissueCorr = True
+
+ datasetFile = open(webqtlConfig.TEXTDIR+DatabaseFileName,'r')
+
+ #XZ, 01/08/2009: read the first line
+ line = datasetFile.readline()
+ dataset_strains = webqtlUtil.readLineCSV(line)[1:]
+
+ #XZ, 3/30/2010: This step is critical.
+ good_dataset_strains_index = []
+
+ for i in range(len(_strains)):
+ found_in_dataset_strains = 0
+ for j, one_dataset_strain in enumerate(dataset_strains):
+ if one_dataset_strain == _strains[i]:
+ found_in_dataset_strains = 1
+ good_dataset_strains_index.append(j)
+ break
+
+ if not found_in_dataset_strains:
+ good_dataset_strains_index.append(-99999)
+
+ allTargetTraitNames = []
+ allTargetTraitValues = []
+
+ #XZ, 04/01/2009: If literature corr or tissue corr is selected,
+ #XZ: there is no need to compute partial correlation for all traits.
+ #XZ: If genetic corr is selected, compute partial correlation for all traits.
+ for line in datasetFile:
+ trait_line = webqtlUtil.readLineCSV(line)
+ trait_name = trait_line[0]
+ trait_data = trait_line[1:]
+
+ if useLit:
+ if not litCorrs.has_key( trait_name ):
+ continue
+
+ if useTissueCorr:
+ if not tissueCorrs.has_key( trait_name ):
+ continue
+
+ #XZ, 04/01/2010: If useLit or useTissueCorr, and this trait should not be added,
+ #it will not go to the next step.
+
+ good_dataset_vals = []
+ for i in good_dataset_strains_index:
+ if i == -99999:
+ good_dataset_vals.append(None)
+ else:
+ good_dataset_vals.append( float(trait_data[i]) )
+
+ allTargetTraitNames.append(trait_name)
+ allTargetTraitValues.append(good_dataset_vals)
+
+ datasetFile.close()
+
+ if self.method in ["2", "5"]: #Spearman
+ allcorrelations = correlationFunction.determinePartialsByR(primaryVal=_vals, controlVals=_controlvals, targetVals=allTargetTraitValues, targetNames=allTargetTraitNames, method='s')
+ else:
+ allcorrelations = correlationFunction.determinePartialsByR(primaryVal=_vals, controlVals=_controlvals, targetVals=allTargetTraitValues, targetNames=allTargetTraitNames)
+
+ totalTraits = len(allcorrelations)
+
+ if useLit or useTissueCorr:
+ for i, item in enumerate(allcorrelations):
+ if useLit:
+ allcorrelations[i].append(litCorrs[ item[0] ])
+ if useTissueCorr:
+ tempCorr, tempPValue = tissueCorrs[ item[0] ]
+ allcorrelations[i].append(tempCorr)
+ allcorrelations[i].append(tempPValue)
+
+ return totalTraits, allcorrelations
+ except:
+ return 0, 0
+
+
+ def getPartialCorrelationsNormal(self, _strains, _vals, _controlvals, nnCorr, species, input_trait_GeneId, input_trait_symbol,TissueProbeSetFreezeId):
+ """Calculates and returns correlation coefficients"""
+
+ traitdatabase, dataStartPos = self.fetchAllDatabaseData(species=species, GeneId=input_trait_GeneId, GeneSymbol=input_trait_symbol, strains=_strains, db=self.db, method=self.method, returnNumber=self.returnNumber, tissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ totalTraits = len(traitdatabase) #XZ, 09/18/2008: total trait number
+
+ allcorrelations = []
+
+ allTargetTraitNames = []
+ allTargetTraitValues = []
+
+ for traitdata in traitdatabase:
+ traitdataName = traitdata[0]
+ traitvals = traitdata[dataStartPos:]
+ allTargetTraitNames.append (traitdataName)
+ allTargetTraitValues.append (traitvals)
+
+ if self.method in ["2", "5"]: #Spearman
+ allcorrelations = correlationFunction.determinePartialsByR(primaryVal=_vals, controlVals=_controlvals, targetVals=allTargetTraitValues, targetNames=allTargetTraitNames, method='s')
+ else:
+ allcorrelations = correlationFunction.determinePartialsByR(primaryVal=_vals, controlVals=_controlvals, targetVals=allTargetTraitValues, targetNames=allTargetTraitNames)
+
+ #XZ, 09/28/2008: if user select '3', then fetchAllDatabaseData would give us LitCorr in the [1] position
+ #XZ, 09/28/2008: if user select '4' or '5', then fetchAllDatabaseData would give us Tissue Corr in the [1] position
+ #XZ, 09/28/2008: and Tissue Corr P Value in the [2] position
+ if input_trait_GeneId and self.db.type == "ProbeSet" and self.method in ["3", "4", "5"]:
+ for i, item in enumerate(allcorrelations):
+ if self.method == "3":
+ item.append( traitdatabase[1] )
+ if self.method == "4" or self.method == "5":
+ item.append( traitdatabase[1] )
+ item.append( traitdatabase[2] )
+
+
+ return totalTraits, allcorrelations
+
+
+ def getTableHeaderForPublish(self, method=None, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ if method in ["1", "3", "4"]:
+ tblobj_header = [[THCell(HT.TD('', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), sort=0),
+ THCell(HT.TD('Record', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="id", idx=1),
+ THCell(HT.TD('Phenotype', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="pheno", idx=2),
+ THCell(HT.TD('Authors', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="auth", idx=3),
+ THCell(HT.TD('Year', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="year", idx=4),
+ THCell(HT.TD('N', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="nstr", idx=5),
+ THCell(HT.TD('Partial r ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="partial_corr", idx=6),
+ THCell(HT.TD('p(partial r)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="partial_pv", idx=7),
+ THCell(HT.TD('r ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="corr", idx=8),
+ THCell(HT.TD('p(r)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="pv", idx=9),
+ THCell(HT.TD('delta r', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="delta_corr", idx=10)]]
+
+ for ncol, item in enumerate(["Record", "Phenotype", "Authors", "Year", "PubMedID", "N", "Partial r", "p(partial r)", "r ", "p(r)", "delta r"]):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+ else:
+ tblobj_header = [[THCell(HT.TD('', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), sort=0),
+ THCell(HT.TD('Record', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="id", idx=1),
+ THCell(HT.TD('Phenotype', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="pheno", idx=2),
+ THCell(HT.TD('Authors', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="auth", idx=3),
+ THCell(HT.TD('Year', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="year", idx=4),
+ THCell(HT.TD('N', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="nstr", idx=5),
+ THCell(HT.TD('Partial rho ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="partial_corr", idx=6),
+ THCell(HT.TD('p(partial rho)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="partial_pv", idx=7),
+ THCell(HT.TD('rho ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="corr", idx=8),
+ THCell(HT.TD('p(rho)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="pv", idx=9),
+ THCell(HT.TD('delta rho', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="delta_corr", idx=10)]]
+
+ for ncol, item in enumerate(["Record", "Phenotype", "Authors", "Year", "PubMedID", "N", "Partial rho", "p(partial rho)", "rho ", "p(rho)", "delta rho"]):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ return tblobj_header, worksheet
+
+
+ def getTableBodyForPublish(self, traitList, formName=None, worksheet=None, newrow=None, corrScript=None):
+
+ tblobj_body = []
+
+ for thisTrait in traitList:
+ tr = []
+
+ trId = str(thisTrait)
+
+ #partial corr value could be string 'NA'
+ try:
+ corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.partial_corr))
+ except:
+ corrScript.append('corrArray["%s"] = {corr:"NA"};' % (trId))
+
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn"), nowrap="yes",align="center", Class="fs12 fwn b1 c222"),str(thisTrait.name), thisTrait.name))
+
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ PhenotypeString = thisTrait.pre_publication_description
+ tr.append(TDCell(HT.TD(PhenotypeString, Class="fs12 fwn b1 c222"), PhenotypeString, PhenotypeString.upper()))
+
+ tr.append(TDCell(HT.TD(thisTrait.authors, Class="fs12 fwn b1 c222 fsI"),thisTrait.authors, thisTrait.authors.strip().upper()))
+
+ try:
+ PubMedLinkText = myear = repr = int(thisTrait.year)
+ except:
+ PubMedLinkText = repr = "N/A"
+ myear = 0
+ if thisTrait.pubmed_id:
+ PubMedLink = HT.Href(text= repr,url= webqtlConfig.PUBMEDLINK_URL % thisTrait.pubmed_id,target='_blank', Class="fs12 fwn")
+ else:
+ PubMedLink = repr
+
+ tr.append(TDCell(HT.TD(PubMedLink, Class="fs12 fwn b1 c222", align='center'), repr, myear))
+
+ repr = '%d' % thisTrait.NOverlap
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.NOverlap))
+
+ try:
+ repr = '%3.3f' % thisTrait.partial_corr
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn b1 c222", align='right', nowrap="on"), repr, abs(thisTrait.partial_corr)))
+ except:
+ repr = 'NA'
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='left'), text=repr, val=0 ))
+
+ repr = webqtlUtil.SciFloat(thisTrait.partial_corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.partial_corrPValue))
+
+ repr = '%3.3f' % thisTrait.corr
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn b1 c222", align='right', nowrap="on"), repr, abs(thisTrait.corr)))
+
+ repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
+
+ #delta
+ try:
+ delta = '%3.3f' % ( float(thisTrait.partial_corr) - float(thisTrait.corr) )
+ tr.append(TDCell(HT.TD(delta, Class="fs12 fwn ffl b1 c222", align='right', nowrap="on"), text=delta, val=abs(float(delta)) ))
+ except:
+ delta = 'NA'
+ tr.append(TDCell(HT.TD(delta, Class="fs12 fwn ffl b1 c222", align='left'), text=delta, val=0 ))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, PhenotypeString, thisTrait.authors, thisTrait.year, thisTrait.pubmed_id, thisTrait.NOverlap, thisTrait.partial_corr, thisTrait.partial_corrPValue, thisTrait.corr, thisTrait.corrPValue, delta]):
+ worksheet.write([newrow, ncol], str(item) )
+ newrow += 1
+
+ return tblobj_body, worksheet, corrScript
+
+
+ def getTableHeaderForGeno(self, method=None, worksheet=None, newrow=None, headingStyle=None):
+ tblobj_header = []
+
+ if method in ["1", "3", "4"]:
+ tblobj_header = [[THCell(HT.TD('', Class="fs13 fwb ffl b1 cw cbrb"), sort=0),
+ THCell(HT.TD('Locus', Class="fs13 fwb ffl b1 cw cbrb",align='center'), text='locus', idx=1),
+ THCell(HT.TD('Chr', Class="fs13 fwb ffl b1 cw cbrb"), text='chr', idx=2),
+ THCell(HT.TD('Megabase', Class="fs13 fwb ffl b1 cw cbrb"), text='Mb', idx=3),
+ THCell(HT.TD('N', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='nstr', idx=4),
+ THCell(HT.TD('Partial r ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='partial_corr', idx=5),
+ THCell(HT.TD('p(partial r)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='partial_pv', idx=6),
+ THCell(HT.TD('r ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='corr', idx=7),
+ THCell(HT.TD('p(r)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='pv', idx=8),
+ THCell(HT.TD('delta r', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='delta_corr', idx=9)]]
+
+ for ncol, item in enumerate(['Locus', 'Chr', ' Mb ', ' N ', 'Partial r', 'p(partial r)', 'r ', 'p(r)', 'delta r' ]):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+ else:
+ tblobj_header = [[THCell(HT.TD('', Class="fs13 fwb ffl b1 cw cbrb"), sort=0),
+ THCell(HT.TD('Locus', Class="fs13 fwb ffl b1 cw cbrb",align='center'), text='locus', idx=1),
+ THCell(HT.TD('Chr', Class="fs13 fwb ffl b1 cw cbrb"), text='chr', idx=2),
+ THCell(HT.TD('Megabase', Class="fs13 fwb ffl b1 cw cbrb"), text='Mb', idx=3),
+ THCell(HT.TD('N', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='nstr', idx=4),
+ THCell(HT.TD('Partial rho', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='partial_corr', idx=5),
+ THCell(HT.TD('p(partial rho)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='partial_pv', idx=6),
+ THCell(HT.TD('rho ', Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text='corr', idx=7),
+ THCell(HT.TD('p(rho)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='pv', idx=8),
+ THCell(HT.TD('delta rho', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='delta_corr', idx=9)]]
+
+ for ncol, item in enumerate(['Locus', 'Chr', ' Mb ', ' N ', 'Partial rho', 'p(partial rho)', 'rho ', 'p(rho)', 'delta rho' ]):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ return tblobj_header, worksheet
+
+
+
+ def getTableBodyForGeno(self, traitList, formName=None, worksheet=None, newrow=None, corrScript=None):
+
+ tblobj_body = []
+
+ for thisTrait in traitList:
+ tr = []
+
+ trId = str(thisTrait)
+
+ #partial corr value could be string 'NA'
+ try:
+ corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.partial_corr))
+ except:
+ corrScript.append('corrArray["%s"] = {corr:"NA"};' % (trId))
+
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn ffl"),align="center", Class="fs12 fwn ffl b1 c222"), text=thisTrait.name, val=thisTrait.name.upper()))
+
+ #tr.append(TDCell(HT.TD(thisTrait.chr, Class="fs12 fwn ffl b1 c222", align='right'), text=str(thisTrait.chr)))
+
+ try:
+ Mbvalue = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if not thisTrait.chr or not thisTrait.mb:
+ Mbvalue = 1000000
+ elif thisTrait.chr.upper() == 'X':
+ Mbvalue = 20*1000 + thisTrait.mb
+ else:
+ Mbvalue = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ tr.append(TDCell( HT.TD(thisTrait.chr, Class="fs12 fwn b1 c222", align='right'), thisTrait.chr, Mbvalue) )
+ tr.append(TDCell(HT.TD(thisTrait.mb, Class="fs12 fwn ffl b1 c222", align='right'), text=str(thisTrait.mb), val=Mbvalue))
+
+ repr = '%d' % thisTrait.NOverlap
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.NOverlap))
+
+ try:
+ repr='%3.3f' % thisTrait.partial_corr
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right',nowrap='ON'),repr,abs(thisTrait.partial_corr)))
+ except:
+ repr = 'NA'
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='left'), text=repr, val=0 ))
+
+ repr = webqtlUtil.SciFloat(thisTrait.partial_corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.partial_corrPValue))
+
+ repr = '%3.3f' % thisTrait.corr
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn b1 c222", align='right',nowrap='ON'), repr, abs(thisTrait.corr)))
+
+ repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
+
+ #delta
+ try:
+ delta = '%3.3f' % ( float(thisTrait.partial_corr) - float(thisTrait.corr) )
+ tr.append(TDCell(HT.TD(delta, Class="fs12 fwn ffl b1 c222", align='right', nowrap='ON'), text=delta, val=abs(float(delta)) ))
+ except:
+ delta = 'NA'
+ tr.append(TDCell(HT.TD(delta, Class="fs12 fwn ffl b1 c222", align='left'), text=delta, val=0 ))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, thisTrait.chr, thisTrait.mb, thisTrait.NOverlap, thisTrait.partial_corr, thisTrait.partial_corrPValue, thisTrait.corr, thisTrait.corrPValue, delta]):
+ worksheet.write([newrow, ncol], item)
+ newrow += 1
+
+ return tblobj_body, worksheet, corrScript
+
+
+ def getTableHeaderForProbeSet(self, method=None, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ if method in ["1","3","4"]:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
+ THCell(HT.TD('Record',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="id", idx=1),
+ THCell(HT.TD('','Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="symbol", idx=2),
+ THCell(HT.TD('','Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="desc", idx=3),
+ #XZ, 12/09/2008: sort chr
+ THCell(HT.TD('','Chr',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="chr", idx=4),
+ THCell(HT.TD('','Mb',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Mb", idx=5),
+ THCell(HT.TD('Mean',HT.BR(),'Expr',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="mean", idx=6),
+ THCell(HT.TD('N',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="nstr", idx=7),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'Partial r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="partial_corr", idx=8),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(partial r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="partial_pv", idx=9),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="corr", idx=10),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="pv", idx=11),
+ THCell(HT.TD('delta',HT.BR(), 'r', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="delta_corr", idx=12),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Pubmed',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#literatureCorr"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="lcorr", idx=13),
+ #XZ, 09/22/2008: tissue correlation
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuecorr", idx=14),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuepvalue", idx=15)]]
+
+ for ncol, item in enumerate(['Record', 'Gene ID', 'Symbol', 'Description', 'Chr', 'Megabase', 'Mean Expr', 'N ', 'Sample Partial r', 'Sample p(partial r)', 'Sample r', 'Sample p(r)', 'delta r', 'Lit Corr', 'Tissue r', 'Tissue p(r)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+ else:
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
+ THCell(HT.TD('Record',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="id", idx=1),
+ THCell(HT.TD('','Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="symbol", idx=2),
+ THCell(HT.TD('','Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="desc", idx=3),
+ THCell(HT.TD('','Chr',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="chr", idx=4),
+ THCell(HT.TD('','Mb',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Mb", idx=5),
+ THCell(HT.TD('Mean',HT.BR(),'Expr',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="mean", idx=6),
+ THCell(HT.TD('N',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="nstr", idx=7),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'Partial rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="partial_corr", idx=8),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(partial rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="partial_pv", idx=9),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="corr", idx=10),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Sample',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#genetic_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="pv", idx=11),
+ THCell(HT.TD('delta',HT.BR(),'rho', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="delta_corr", idx=12),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Pubmed',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#literatureCorr"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="lcorr", idx=13),
+ #XZ, 09/22/2008: tissue correlation
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuecorr", idx=14),
+ THCell(HT.TD(HT.Href(
+ text = HT.Span('Tissue',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_p_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuepvalue", idx=15)]]
+
+ for ncol, item in enumerate(['Record', 'Gene ID', 'Symbol', 'Description', 'Chr', 'Megabase', 'Mean Expr', 'N ', 'Sample Partial rho', 'Sample p(partial rho)', 'Sample rho', 'Sample p(rho)', 'delta rho', 'Pubmed r', 'Tissue rho', 'Tissue p(rho)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ return tblobj_header, worksheet
+
+
+ def getTableBodyForProbeSet(self, traitList=[], primaryTrait=None, formName=None, worksheet=None, newrow=None, corrScript=None):
+
+ tblobj_body = []
+
+ for thisTrait in traitList:
+
+ if thisTrait.symbol:
+ pass
+ else:
+ thisTrait.symbol = "N/A"
+
+ if thisTrait.geneid:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % thisTrait.geneid, Class="fs12 fwn")
+ else:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % thisTrait.symbol, Class="fs12 fwn")
+
+ tr = []
+
+ trId = str(thisTrait)
+
+ #partial corr value could be string 'NA'
+ try:
+ corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.partial_corr))
+ except:
+ corrScript.append('corrArray["%s"] = {corr:"NA"};' % (trId))
+
+ #XZ, 12/08/2008: checkbox
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+
+ #XZ, 12/08/2008: probeset name
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName,thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn b1 c222"), thisTrait.name, thisTrait.name.upper()))
+
+ #XZ, 12/08/2008: gene symbol
+ tr.append(TDCell(HT.TD(symbolurl, Class="fs12 fwn b1 c222 fsI"),thisTrait.symbol, thisTrait.symbol.upper()))
+
+ #XZ, 12/08/2008: description
+ #XZ, 06/05/2009: Rob asked to add probe target description
+ description_string = str(thisTrait.description).strip()
+ target_string = str(thisTrait.probe_target_description).strip()
+
+ description_display = ''
+
+ if len(description_string) > 1 and description_string != 'None':
+ description_display = description_string
+ else:
+ description_display = thisTrait.symbol
+
+ if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ description_display = description_display + '; ' + target_string.strip()
+
+ tr.append(TDCell(HT.TD(description_display, Class="fs12 fwn b1 c222"), description_display, description_display))
+
+ #XZ, 12/08/2008: Mbvalue is used for sorting
+ try:
+ Mbvalue = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if not thisTrait.chr or not thisTrait.mb:
+ Mbvalue = 1000000
+ elif thisTrait.chr.upper() == 'X':
+ Mbvalue = 20*1000 + thisTrait.mb
+ else:
+ Mbvalue = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ #XZ, 12/08/2008: chromosome number
+ #XZ, 12/10/2008: use Mbvalue to sort chromosome
+ tr.append(TDCell( HT.TD(thisTrait.chr, Class="fs12 fwn b1 c222", align='right'), thisTrait.chr, Mbvalue) )
+
+ #XZ, 12/08/2008: Rob wants 6 digit precision, and we have to deal with that the mb could be None
+ if not thisTrait.mb:
+ tr.append(TDCell(HT.TD(thisTrait.mb, Class="fs12 fwn b1 c222",align='right'), thisTrait.mb, Mbvalue))
+ else:
+ tr.append(TDCell(HT.TD('%.6f' % thisTrait.mb, Class="fs12 fwn b1 c222", align='right'), thisTrait.mb, Mbvalue))
+
+ #XZ, 01/12/08: This SQL query is much faster.
+ self.cursor.execute("""
+ select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %d and
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId and
+ ProbeSet.Name = '%s'
+ """ % (thisTrait.db.id, thisTrait.name))
+ result = self.cursor.fetchone()
+ if result:
+ if result[0]:
+ mean = result[0]
+ else:
+ mean=0
+ else:
+ mean = 0
+
+ #XZ, 06/05/2009: It is neccessary to turn on nowrap
+ repr = "%2.3f" % mean
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right', nowrap='ON'),repr, mean))
+
+ #XZ: number of overlaped cases for partial corr
+ repr = '%d' % thisTrait.NOverlap
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.NOverlap))
+
+ #XZ: sample partial correlation
+ try:
+ repr='%3.3f' % thisTrait.partial_corr
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right', nowrap='ON'),repr,abs(thisTrait.partial_corr)))
+ except:
+ repr = 'NA'
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='left'), text=repr, val=0 ))
+
+ #XZ: p value of genetic partial correlation
+ repr = webqtlUtil.SciFloat(thisTrait.partial_corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.partial_corrPValue))
+
+ repr = '%3.3f' % thisTrait.corr
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn b1 c222", align='right',nowrap='ON'), repr, abs(thisTrait.corr)))
+
+ repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
+ tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
+
+ #delta
+ try:
+ delta = '%3.3f' % ( float(thisTrait.partial_corr) - float(thisTrait.corr) )
+ tr.append(TDCell(HT.TD(delta, Class="fs12 fwn ffl b1 c222", align='right', nowrap='ON'), text=delta, val=abs(float(delta)) ))
+ except:
+ delta = 'NA'
+ tr.append(TDCell(HT.TD(delta, Class="fs12 fwn ffl b1 c222", align='left'), text=delta, val=0 ))
+
+ #XZ, 12/08/2008: literature correlation
+ LCorr = 0.0
+ LCorrStr = "N/A"
+ if hasattr(thisTrait, 'LCorr') and thisTrait.LCorr:
+ LCorr = thisTrait.LCorr
+ LCorrStr = "%2.3f" % thisTrait.LCorr
+ tr.append(TDCell(HT.TD(LCorrStr, Class="fs12 fwn b1 c222", align='right'), LCorrStr, abs(LCorr)))
+
+ #XZ, 09/22/2008: tissue correlation.
+ TCorr = 0.0
+ TCorrStr = "N/A"
+ #XZ, 11/18/2010: need to pass two gene symbols
+ if hasattr(thisTrait, 'tissueCorr') and thisTrait.tissueCorr:
+ TCorr = thisTrait.tissueCorr
+ TCorrStr = "%2.3f" % thisTrait.tissueCorr
+ #NL, 07/19/2010: add a new parameter rankOrder for js function 'showTissueCorrPlot'
+ rankOrder =thisTrait.rankOrder
+ TCorrPlotURL = "javascript:showTissueCorrPlot('%s','%s','%s',%d)" %(formName, primaryTrait.symbol, thisTrait.symbol,rankOrder)
+ tr.append(TDCell(HT.TD(HT.Href(text=TCorrStr, url=TCorrPlotURL, Class="fs12 fwn ff1"), Class="fs12 fwn ff1 b1 c222", align='right'), TCorrStr, abs(TCorr) ))
+ else:
+ tr.append(TDCell(HT.TD(TCorrStr, Class="fs12 fwn b1 c222", align='right'), TCorrStr, abs(TCorr)))
+
+ #XZ, 12/08/2008: p value of tissue correlation
+ TPValue = 1.0
+ TPValueStr = "N/A"
+ if hasattr(thisTrait, 'tissueCorr') and thisTrait.tissueCorr: #XZ, 09/22/2008: thisTrait.tissuePValue can't be used here because it could be 0
+ TPValue = thisTrait.tissuePValue
+ TPValueStr = "%2.3f" % thisTrait.tissuePValue
+ tr.append(TDCell(HT.TD(TPValueStr, Class="fs12 fwn b1 c222", align='right'), TPValueStr, abs(TPValue) ))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, thisTrait.geneid, thisTrait.symbol, thisTrait.description, thisTrait.chr, thisTrait.mb, mean, thisTrait.NOverlap, thisTrait.partial_corr, thisTrait.partial_corrPValue, thisTrait.corr, thisTrait.corrPValue, delta, LCorrStr, TCorrStr, TPValueStr]):
+ worksheet.write([newrow, ncol], item)
+
+ newrow += 1
+
+ return tblobj_body, worksheet, corrScript
+
+
+ def getFormForPrimaryAndControlTraits (self, primaryTrait, controlTraits):
+
+ info_form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+
+ hddn = {'FormID':'showDatabase', 'database':'_', 'ProbeSetID':'_', 'CellID':'_' }#XZ: These four parameters are required by javascript function showDatabase2.
+
+ for key in hddn.keys():
+ info_form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ info_form.append(HT.Paragraph("Primary Trait", Class="subtitle"), '\n')
+
+ primaryTraitTable = HT.TableLite(cellSpacing=4,cellPadding=0,width="90%",border=0)
+ descriptionString = primaryTrait.genHTML(dispFromDatabase=1)
+ if primaryTrait.db.type == 'Publish' and primaryTrait.confidential:
+ descriptionString = primaryTrait.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=primaryTrait.authorized_users)
+ primaryTraitTable.append(HT.TR(HT.TD(HT.Href(text='%s' % descriptionString, url="javascript:showDatabase2('%s','%s','%s')" % (primaryTrait.db.name,primaryTrait.name,primaryTrait.cellid), Class="fs12 fwn") )))
+
+ info_form.append(primaryTraitTable)
+
+ info_form.append(HT.Paragraph("Control Traits", Class="subtitle"), '\n')
+
+ controlTraitsTable = HT.TableLite(cellSpacing=4,cellPadding=0,width="90%",border=0)
+
+ seq = 1
+
+ ## Generate the listing table for control traits
+ for thisTrait in controlTraits:
+ descriptionString = thisTrait.genHTML(dispFromDatabase=1)
+ if thisTrait.db.type == 'Publish' and thisTrait.confidential:
+ descriptionString = thisTrait.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users)
+ controlTraitsTable.append(HT.TR(HT.TD("%d."%seq,align="right",width=10),
+ HT.TD(HT.Href(text='%s' % descriptionString,url="javascript:showDatabase2('%s','%s','%s')" % (thisTrait.db.name,thisTrait.name,thisTrait.cellid), Class="fs12 fwn") )))
+ seq += 1
+
+ info_form.append(controlTraitsTable)
+
+ return info_form
diff --git a/web/webqtl/correlation/PartialCorrInputPage.py b/web/webqtl/correlation/PartialCorrInputPage.py
new file mode 100755
index 00000000..7d32da6d
--- /dev/null
+++ b/web/webqtl/correlation/PartialCorrInputPage.py
@@ -0,0 +1,484 @@
+# 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
+
+import os
+import string
+import cPickle
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from dbFunction import webqtlDatabaseFunction
+from utility import webqtlUtil
+
+
+
+class PartialCorrInputPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ searchResult = fd.formdata.getvalue('searchResult')
+
+ if not searchResult:
+ heading = 'Partial Correlation'
+ detail = ['You need to select at least three traits in order to calculate partial correlation.']
+ self.error(heading=heading,detail=detail)
+ return
+
+
+ ## Adds the Trait instance for each trait name from the collection
+ traits = []
+
+ for item in searchResult:
+ traits.append(webqtlTrait(fullname=item, cursor=self.cursor))
+
+ RISet = fd.formdata.getvalue('RISet')
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=RISet)
+
+ #XZ: HTML part
+ TD_LR = HT.TD(colspan=2,height=200,width="100%",bgColor='#eeeeee')
+ TD_LR.append("Please select one primary trait, one to three control traits, and at least one target trait.", HT.P() )
+
+ mainFormName = 'showDatabase'
+ mainForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name=mainFormName,submit=HT.Input(type='hidden'))
+
+ #XZ: Add hidden form values
+ hddn = {'FormID':'calPartialCorrTrait', 'database':'', 'ProbeSetID':'', 'CellID':'', #XZ: These four parameters are required by javascript function showDatabase2.
+ 'controlTraits':'',
+ 'primaryTrait':'',
+ 'targetTraits':'',
+ 'pcMethod':'',
+ 'RISet':RISet
+ }
+
+
+ for key in hddn.keys():
+ mainForm.append(HT.Input(type='hidden', name=key, value=hddn[key]))
+
+ radioNames = []
+
+ for thisTrait in traits:
+ oneRadioName = thisTrait.getName()
+ radioNames.append(oneRadioName)
+
+ radioNamesString = ','.join(radioNames)
+
+ # Creates the image href that runs the javascript setting all traits as target or ignored
+ setAllTarget = HT.Href(url="#redirect", onClick="setAllAsTarget(document.getElementsByName('showDatabase')[0], '%s');" % radioNamesString)
+ setAllTargetImg = HT.Image("/images/select_all.gif", alt="Select All", title="Select All", style="border:none;")
+ setAllTarget.append(setAllTargetImg)
+ setAllIgnore = HT.Href(url="#redirect", onClick="setAllAsIgnore(document.getElementsByName('showDatabase')[0], '%s');" % radioNamesString)
+ setAllIgnoreImg = HT.Image("/images/select_all.gif", alt="Select All", title="Select All", style="border:none;")
+ setAllIgnore.append(setAllIgnoreImg)
+
+
+ tblobj = {}
+ tblobj['header'] = self.getCollectionTableHeader()
+
+ sortby = self.getSortByValue()
+
+ tblobj['body'] = self.getCollectionTableBody(traitList=traits, formName=mainFormName, species=species)
+
+ filename= webqtlUtil.genRandStr("Search_")
+
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), Id="sortable")
+
+ mainForm.append(div)
+
+ #XZ: Add button
+ radioNamesString = ','.join(radioNames)
+ jsCommand_1 = "validateTrait(this.form, \'" + radioNamesString + "\', 0, 1);"
+ jsCommand_2 = "validateTrait(this.form, \'" + radioNamesString + "\', 0, 2);"
+ partialCorrTraitButton_1 = HT.Input(type='button', name='submitPartialCorrTrait_1', value='Pearson\'s r', onClick='%s' % jsCommand_1, Class="button")
+ partialCorrTraitButton_2 = HT.Input(type='button', name='submitPartialCorrTrait_2', value='Spearman\'s rho', onClick='%s' % jsCommand_2, Class="button")
+ mainForm.append(HT.BR(), "Compute partial correlation for target selected above:", HT.BR(), partialCorrTraitButton_1, partialCorrTraitButton_2, HT.BR(), HT.BR(), HT.HR(color="gray",size=3) )
+
+ jsCommand = "validateTrait(this.form, \'" + radioNamesString + "\', 1);"
+ partialCorrDBButton = HT.Input(type='button', name='submitPartialCorrDB', value='Calculate', onClick='%s' % jsCommand,Class="button")
+
+ methodText = HT.Span("Calculate:", Class="ffl fwb fs12")
+
+ methodMenu = HT.Select(name='method')
+ methodMenu.append(('Genetic Correlation, Pearson\'s r','1'))
+ methodMenu.append(('Genetic Correlation, Spearman\'s rho','2'))
+ methodMenu.append(('SGO Literature Correlation','3'))
+ methodMenu.append(('Tissue Correlation, Pearson\'s r','4'))
+ methodMenu.append(('Tissue Correlation, Spearman\'s rho','5'))
+
+ databaseText = HT.Span("Choose Database:", Class="ffl fwb fs12")
+ databaseMenu = HT.Select(name='database2')
+
+ nmenu = 0
+
+ self.cursor.execute('SELECT PublishFreeze.FullName,PublishFreeze.Name FROM \
+ PublishFreeze,InbredSet WHERE PublishFreeze.InbredSetId = InbredSet.Id \
+ and InbredSet.Name = "%s" and PublishFreeze.public > %d' % \
+ (RISet,webqtlConfig.PUBLICTHRESH))
+ for item in self.cursor.fetchall():
+ databaseMenu.append(item)
+ nmenu += 1
+
+ self.cursor.execute('SELECT GenoFreeze.FullName,GenoFreeze.Name FROM GenoFreeze,\
+ InbredSet WHERE GenoFreeze.InbredSetId = InbredSet.Id and InbredSet.Name = \
+ "%s" and GenoFreeze.public > %d' % (RISet,webqtlConfig.PUBLICTHRESH))
+ for item in self.cursor.fetchall():
+ databaseMenu.append(item)
+ nmenu += 1
+
+ #03/09/2009: Xiaodong changed the SQL query to order by Name as requested by Rob.
+ self.cursor.execute('SELECT Id, Name FROM Tissue order by Name')
+ for item in self.cursor.fetchall():
+ TId, TName = item
+ databaseMenuSub = HT.Optgroup(label = '%s ------' % TName)
+ self.cursor.execute('SELECT ProbeSetFreeze.FullName,ProbeSetFreeze.Name FROM ProbeSetFreeze, ProbeFreeze, \
+ InbredSet WHERE ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeFreeze.TissueId = %d and \
+ ProbeSetFreeze.public > %d and ProbeFreeze.InbredSetId = InbredSet.Id and InbredSet.Name like "%s%%" \
+ order by ProbeSetFreeze.CreateTime desc, ProbeSetFreeze.AvgId ' % (TId,webqtlConfig.PUBLICTHRESH, RISet))
+ for item2 in self.cursor.fetchall():
+ databaseMenuSub.append(item2)
+ nmenu += 1
+ databaseMenu.append(databaseMenuSub)
+
+ if nmenu:
+ criteriaText = HT.Span("Return:", Class="ffl fwb fs12")
+ criteriaMenu = HT.Select(name='criteria', selected='500')
+ criteriaMenu.append(('top 100','100'))
+ criteriaMenu.append(('top 200','200'))
+ criteriaMenu.append(('top 500','500'))
+ criteriaMenu.append(('top 1000','1000'))
+ criteriaMenu.append(('top 2000','2000'))
+ criteriaMenu.append(('top 5000','5000'))
+ criteriaMenu.append(('top 10000','10000'))
+ criteriaMenu.append(('top 15000','15000'))
+ criteriaMenu.append(('top 20000','20000'))
+
+ self.MPDCell = HT.TD()
+ correlationMenus = HT.TableLite(
+ HT.TR(
+ HT.TD(databaseText,HT.BR(),databaseMenu, colspan=4)
+ ),
+ HT.TR(
+ HT.TD(methodText,HT.BR(),methodMenu),
+ self.MPDCell,
+ HT.TD(criteriaText,HT.BR(),criteriaMenu)),
+ border=0, cellspacing=4, cellpadding=0)
+ else:
+ correlationMenus = ""
+
+ mainForm.append(HT.Font('or',color='red', size=4), HT.BR(), HT.BR(), "Compute partial correlation for each trait in the database selected below:", HT.BR() )
+ mainForm.append( partialCorrDBButton, HT.BR(), HT.BR(), correlationMenus)
+
+ TD_LR.append(mainForm)
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['js1'] =''
+ self.dict['title'] = 'Partial Correlation Input'
+
+
+ def getCollectionTableHeader(self):
+
+ tblobj_header = []
+
+ className = "fs13 fwb ffl b1 cw cbrb"
+
+ tblobj_header = [[THCell(HT.TD('Index', Class=className, nowrap="on"), sort=0),
+ THCell(HT.TD("Primary (X)",align="center", Class="fs13 fwb ffl b1 cw cbrb", nowrap="ON"), text="primary", sort=0),
+ THCell(HT.TD("Control (Z)",align="center", Class="fs13 fwb ffl b1 cw cbrb", nowrap="ON"), text="control", sort=0),
+ THCell(HT.TD("Target (Y)",align="center", Class="fs13 fwb ffl b1 cw cbrb", nowrap="ON"), text="target", sort=0),
+ THCell(HT.TD("Ignored",align="center", Class="fs13 fwb ffl b1 cw cbrb", nowrap="ON"), text="target", sort=0),
+ THCell(HT.TD('Dataset', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="dataset", idx=1),
+ THCell(HT.TD('Trait', HT.BR(), 'ID', HT.BR(), valign="top", Class=className, nowrap="on"), text="name", idx=2),
+ THCell(HT.TD('Description', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="desc", idx=3),
+ THCell(HT.TD('Location', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="location", idx=4),
+ THCell(HT.TD('Mean', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="mean", idx=5),
+ THCell(HT.TD('N', HT.BR(), 'Cases', HT.BR(), valign="top", Class=className, nowrap="on"), text="samples", idx=6),
+ THCell(HT.TD('Max LRS', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="lrs", idx=7),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb', HT.BR(), valign="top", Class=className, nowrap="on"), text="lrs_location", idx=8)]]
+
+ return tblobj_header
+
+
+
+ def getCollectionTableBody(self, traitList=None, formName=None, species=''):
+
+ tblobj_body = []
+
+ className = "fs12 fwn b1 c222"
+
+ for thisTrait in traitList:
+ tr = []
+
+ if not thisTrait.haveinfo:
+ thisTrait.retrieveInfo(QTL=1)
+
+ trId = str(thisTrait)
+
+ oneRadioName = thisTrait.getName()
+
+ tr.append(TDCell( HT.TD(' ',align="center",valign="center",Class=className) ))
+ tr.append(TDCell( HT.TD(HT.Input(type="radio", name=oneRadioName, value="primary"),align="center",valign="center",Class=className) ))
+ tr.append(TDCell( HT.TD(HT.Input(type="radio", name=oneRadioName, value="control"),align="center",valign="center",Class=className) ))
+ tr.append(TDCell( HT.TD(HT.Input(type="radio", name=oneRadioName, value="target", checked="true"),align="center",valign="center",Class=className) ))
+ tr.append(TDCell( HT.TD(HT.Input(type="radio", name=oneRadioName, value="ignored"),align="center",valign="center",Class=className) ))
+
+ tr.append(TDCell(HT.TD(thisTrait.db.name, Class="fs12 fwn b1 c222"), thisTrait.db.name, thisTrait.db.name.upper()))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showDatabase3('%s','%s','%s','')" % (formName, thisTrait.db.name, thisTrait.name), Class="fs12 fwn"), nowrap="yes",align="left", Class=className
+),str(thisTrait.name), thisTrait.name))
+
+ #description column
+ if (thisTrait.db.type == "Publish"):
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ PhenotypeString = thisTrait.pre_publication_description
+ tr.append(TDCell(HT.TD(PhenotypeString, Class=className), PhenotypeString, PhenotypeString.upper()))
+ elif (thisTrait.db.type == "ProbeSet" or thisTrait.db.type == "Temp"):
+ description_string = str(thisTrait.description).strip()
+ if (thisTrait.db.type == "ProbeSet"):
+ target_string = str(thisTrait.probe_target_description).strip()
+
+ description_display = ''
+
+ if len(description_string) > 1 and description_string != 'None':
+ description_display = description_string
+ else:
+ description_display = thisTrait.symbol
+
+ if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ description_display = description_display + '; ' + target_string.strip()
+
+ description_string = description_display
+
+ tr.append(TDCell(HT.TD(description_string, Class=className), description_string, description_string))
+ else:
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+
+ #location column
+ if (thisTrait.db.type == "Publish"):
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+ else:
+ #ZS: trait_location_value is used for sorting
+ trait_location_repr = "N/A"
+ trait_location_value = 1000000
+
+ if hasattr(thisTrait, 'chr') and hasattr(thisTrait, 'mb') and thisTrait.chr and thisTrait.mb:
+ try:
+ trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if thisTrait.chr.upper() == "X":
+ trait_location_value = 20*1000 + thisTrait.mb
+ else:
+ trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ trait_location_repr = "Chr%s: %.6f" % (thisTrait.chr, float(thisTrait.mb) )
+
+ tr.append( TDCell(HT.TD(trait_location_repr, nowrap="yes", Class=className), trait_location_repr, trait_location_value) )
+
+ if (thisTrait.db.type == "ProbeSet"):
+ self.cursor.execute("""
+ select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %d and
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId and
+ ProbeSet.Name = '%s'
+ """ % (thisTrait.db.id, thisTrait.name))
+ result = self.cursor.fetchone()
+ if result:
+ if result[0]:
+ mean = result[0]
+ else:
+ mean=0
+ else:
+ mean = 0
+
+ #XZ, 06/05/2009: It is neccessary to turn on nowrap
+ repr = "%2.3f" % mean
+ tr.append(TDCell(HT.TD(repr, Class=className, align='right', nowrap='ON'),repr, mean))
+
+ elif (thisTrait.db.type == "Publish"):
+ self.cursor.execute("""
+ select count(PublishData.value), sum(PublishData.value) from PublishData, PublishXRef, PublishFreeze
+ where PublishData.Id = PublishXRef.DataId and
+ PublishXRef.Id = %s and
+ PublishXRef.InbredSetId = PublishFreeze.InbredSetId and
+ PublishFreeze.Id = %d
+ """ % (thisTrait.name, thisTrait.db.id))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ mean = result[1]/result[0]
+ else:
+ mean = 0
+ else:
+ mean = 0
+
+ repr = "%2.3f" % mean
+ tr.append(TDCell(HT.TD(repr, Class=className, align='right', nowrap='ON'),repr, mean))
+ else:
+ tr.append(TDCell(HT.TD("--", Class=className, align='left', nowrap='ON'),"--", 0))
+
+ #Number of cases
+ n_cases_value = 0
+ n_cases_repr = "--"
+ if (thisTrait.db.type == "Publish"):
+ self.cursor.execute("""
+ select count(PublishData.value) from PublishData, PublishXRef, PublishFreeze
+ where PublishData.Id = PublishXRef.DataId and
+ PublishXRef.Id = %s and
+ PublishXRef.InbredSetId = PublishFreeze.InbredSetId and
+ PublishFreeze.Id = %d
+ """ % (thisTrait.name, thisTrait.db.id))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0]:
+ n_cases_value = result[0]
+ n_cases_repr = result[0]
+
+ if (n_cases_value == "--"):
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='right', nowrap="on"), n_cases_repr, n_cases_value))
+
+ elif (thisTrait.db.type == "ProbeSet"):
+ self.cursor.execute("""
+ select count(ProbeSetData.value) from ProbeSet, ProbeSetXRef, ProbeSetData, ProbeSetFreeze
+ where ProbeSet.Name='%s' and
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id and
+ ProbeSetXRef.DataId = ProbeSetData.Id and
+ ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id and
+ ProbeSetFreeze.Name = '%s'
+ """ % (thisTrait.name, thisTrait.db.name))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0]:
+ n_cases_value = result[0]
+ n_cases_repr = result[0]
+ if (n_cases_value == "--"):
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='right', nowrap="on"), n_cases_repr, n_cases_value))
+
+ elif (thisTrait.db.type == "Geno"):
+ self.cursor.execute("""
+ select count(GenoData.value) from GenoData, GenoXRef, GenoFreeze, Geno, Strain
+ where Geno.SpeciesId = %s and Geno.Name='%s' and
+ GenoXRef.GenoId = Geno.Id and
+ GenoXRef.DataId = GenoData.Id and
+ GenoXRef.GenoFreezeId = GenoFreeze.Id and
+ GenoData.StrainId = Strain.Id and
+ GenoFreeze.Name = '%s'
+ """ % (webqtlDatabaseFunction.retrieveSpeciesId(self.cursor, thisTrait.db.riset), thisTrait.name, thisTrait.db.name))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0]:
+ n_cases_value = result[0]
+ n_cases_repr = result[0]
+ if (n_cases_value == "--"):
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='right', nowrap="on"), n_cases_repr, n_cases_value))
+
+ else:
+ tr.append(TDCell(HT.TD(n_cases_repr, Class=className, align='left', nowrap="on"), n_cases_repr, n_cases_value))
+
+
+ if (thisTrait.db.type != "Geno"):
+ #LRS and its location
+ LRS_score_repr = '--'
+ LRS_score_value = 0
+ LRS_location_repr = '--'
+ LRS_location_value = 1000000
+ LRS_flag = 1
+
+ #Max LRS and its Locus location
+ if hasattr(thisTrait, 'lrs') and hasattr(thisTrait, 'locus') and thisTrait.lrs and thisTrait.locus:
+ self.cursor.execute("""
+ select Geno.Chr, Geno.Mb from Geno, Species
+ where Species.Name = '%s' and
+ Geno.Name = '%s' and
+ Geno.SpeciesId = Species.Id
+ """ % (species, thisTrait.locus))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ LRS_Chr = result[0]
+ LRS_Mb = result[1]
+
+ #XZ: LRS_location_value is used for sorting
+ try:
+ LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
+ except:
+ if LRS_Chr.upper() == 'X':
+ LRS_location_value = 20*1000 + float(LRS_Mb)
+ else:
+ LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
+
+
+ LRS_score_repr = '%3.1f' % thisTrait.lrs
+ LRS_score_value = thisTrait.lrs
+ LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
+ LRS_flag = 0
+
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class=className, align='right', nowrap="on"), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class=className), LRS_location_repr, LRS_location_value))
+
+ if LRS_flag:
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class=className), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class=className), LRS_location_repr, LRS_location_value))
+ else:
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", 0))
+ tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", 1000000))
+
+ tblobj_body.append(tr)
+
+ return tblobj_body
+
+
+
+ def getSortByValue(self):
+
+ sortby = ("pv", "up")
+
+ return sortby
+
diff --git a/web/webqtl/correlation/PartialCorrTraitPage.py b/web/webqtl/correlation/PartialCorrTraitPage.py
new file mode 100755
index 00000000..1c79e250
--- /dev/null
+++ b/web/webqtl/correlation/PartialCorrTraitPage.py
@@ -0,0 +1,310 @@
+# 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
+
+import string
+import cPickle
+import os
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from CorrelationPage import CorrelationPage
+import correlationFunction
+
+
+
+class PartialCorrTraitPage(CorrelationPage):
+
+ corrMinInformative = 4
+
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ TD_LR = HT.TD(colspan=2,height=200,width="100%",bgColor='#eeeeee')
+
+ TD_LR.append(HT.Paragraph("Partial Correlation Table", Class="title"), '\n')
+
+ pc_method = fd.formdata.getvalue('pcMethod')
+
+ primaryTraitString = fd.formdata.getvalue('primaryTrait')
+ primaryTrait = (webqtlTrait(fullname=primaryTraitString, cursor=self.cursor))
+
+ controlTraitsString = fd.formdata.getvalue('controlTraits')
+ controlTraitsList = list(string.split(controlTraitsString,','))
+ controlTraits = []
+ for item in controlTraitsList:
+ controlTraits.append(webqtlTrait(fullname=item, cursor=self.cursor))
+
+ targetTraitsString = fd.formdata.getvalue('targetTraits')
+ targetTraitsList = list(string.split(targetTraitsString,','))
+ targetTraits = []
+ _targetnames = []
+ for item in targetTraitsList:
+ oneTargetTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ oneTargetTrait.retrieveInfo()
+ targetTraits.append( oneTargetTrait )
+ _targetnames.append( oneTargetTrait.name )
+
+ #XZ: filter out the strains that have no value.
+ primaryTrait.retrieveData()
+ _strains, _vals, _vars = primaryTrait.exportInformative()
+
+ #XZ: _controlstrains, _controlvals and _controlvars are list of list [ [], [], ...]. _controlNs is number
+ _controlstrains,_controlvals,_controlvars,_controlNs = correlationFunction.controlStrains(controlTraitsString,_strains)
+
+ N = len(_strains)
+
+ allsame = True
+ ##allsame is boolean for whether or not primary and control trait have values for the same strains
+ for i in _controlstrains:
+ if _strains != i:
+ allsame=False
+ break
+
+ ## If the strains for which each of the control traits and the primary trait have values are not identical,
+ ## we must remove from the calculation all vlaues for strains that are not present in each. Without doing this,
+ ## undesirable biases would be introduced.
+ # XZ, 01/11/2010: After execution of function fixStrains, variables _vals,_controlvals,_vars,_controlvars have the same number and same order of strains as strains in variable _strains. The _controlstrains remains intact.
+ if not allsame:
+ _strains,_vals,_controlvals,_vars,_controlvars = correlationFunction.fixStrains(_strains,_controlstrains,_vals,_controlvals,_vars,_controlvars)
+ N = len(_strains)
+
+ #XZ: We should check the value of control trait and primary trait here.
+ nameOfIdenticalTraits = correlationFunction.findIdenticalTraits ( _vals, primaryTraitString, _controlvals, controlTraitsList )
+ if nameOfIdenticalTraits:
+ heading = "Partial Correlation Table"
+ detail = ['%s and %s have same values for the %s strains that will be used to calculate partial correlation (common for all primary and control traits). In such case, partial correlation can NOT be calculated. Please re-select your traits.' % (nameOfIdenticalTraits[0], nameOfIdenticalTraits[1], len(_vals))]
+ self.error(heading=heading,detail=detail)
+ return
+
+
+ if N < self.corrMinInformative:
+ heading = "Partial Correlation Table"
+ detail = ['Fewer than %d strain data were entered for %s data set. No calculation of correlation has been attempted.' % (self.corrMinInformative, fd.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ, 01/11/2010: Pay attention to the target trait strain number and order!
+ #XZ 03/29/2010: need to input target trait values to this function.
+
+ _targetvals = []
+ for oneTargetTrait in targetTraits:
+ oneTargetTrait.retrieveData()
+ oneTraitVals = oneTargetTrait.exportData( _strains )
+ _targetvals.append(oneTraitVals)
+
+
+ if pc_method == 'spearman':
+ allcorrelations = correlationFunction.determinePartialsByR(primaryVal = _vals, controlVals = _controlvals, targetVals = _targetvals, targetNames = _targetnames, method='s')
+ else:
+ allcorrelations = correlationFunction.determinePartialsByR(primaryVal = _vals, controlVals = _controlvals, targetVals = _targetvals, targetNames = _targetnames)
+
+ totalTraits = len(allcorrelations)
+
+
+ info_form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+
+ hddn = {'FormID':'showDatabase', 'database':'_', 'ProbeSetID':'_', 'CellID':'_' }#XZ: These four parameters are required by javascript function showDatabase2.
+
+ for key in hddn.keys():
+ info_form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ info_form.append(HT.Paragraph("Primary Trait", Class="subtitle"), '\n')
+
+ primaryTraitTable = HT.TableLite(cellSpacing=4,cellPadding=0,width="90%",border=0)
+
+ descriptionString = primaryTrait.genHTML(dispFromDatabase=1)
+ if primaryTrait.db.type == 'Publish' and primaryTrait.confidential:
+ descriptionString = primaryTrait.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=primaryTrait.authorized_users)
+ primaryTraitTable.append(HT.TR(HT.TD(HT.Href(text='%s' % descriptionString, url="javascript:showDatabase2('%s','%s','%s')" % (primaryTrait.db.name,primaryTrait.name,primaryTrait.cellid), Class="fs12 fwn") )))
+
+ info_form.append(primaryTraitTable)
+
+ info_form.append(HT.Paragraph("Control Traits", Class="subtitle"), '\n')
+
+ controlTraitsTable = HT.TableLite(cellSpacing=4,cellPadding=0,width="90%",border=0)
+
+ seq = 1
+
+ ## Generate the listing table for control traits
+ for thisTrait in controlTraits:
+ descriptionString = thisTrait.genHTML(dispFromDatabase=1)
+ if thisTrait.db.type == 'Publish' and thisTrait.confidential:
+ descriptionString = thisTrait.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users)
+ controlTraitsTable.append(HT.TR(HT.TD("%d."%seq,align="left", width=10),
+ HT.TD(HT.Href(text='%s' % descriptionString,url="javascript:showDatabase2('%s','%s','%s')" % (thisTrait.db.name,thisTrait.name,thisTrait.cellid), Class="fs12 fwn") )))
+ seq += 1
+
+ info_form.append(controlTraitsTable)
+
+
+ TD_LR.append(info_form)
+
+
+ mainfmName = webqtlUtil.genRandStr("fm_")
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name= mainfmName, submit=HT.Input(type='hidden'))
+
+ hddn = {'FormID':'showDatabase', 'database':'_', 'ProbeSetID':'_', 'CellID':'_' }#XZ: These four parameters are required by javascript function showDatabase2.
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+
+ filename= webqtlUtil.genRandStr("Corr_")
+
+ tblobj = {}
+
+ if pc_method == 'spearman':
+ tblobj['header'] = \
+ [[THCell(HT.TD('', Class="fs13 fwb ffl b1 cw cbrb"), sort=0),
+ THCell(HT.TD('Database', Class="fs13 fwb ffl b1 cw cbrb",align='center'), text='db', idx=1),
+ THCell(HT.TD('Record', Class="fs13 fwb ffl b1 cw cbrb",align='center'), text='id', idx=2),
+ THCell(HT.TD('Symbol', Class="fs13 fwb ffl b1 cw cbrb"), text='symbol', idx=3),
+ THCell(HT.TD('Description', Class="fs13 fwb ffl b1 cw cbrb", align='center'), text='desc', idx=4),
+ THCell(HT.TD('N ', nowrap="on", Class="fs13 fwb ffl b1 cw cbrb"), text='nstr', idx=5),
+ THCell(HT.TD('Partial rho ', nowrap="on", Class="fs13 fwb ffl b1 cw cbrb"), text='partial_corr', idx=6),
+ THCell(HT.TD('p(partial rho)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='partial_pv', idx=7),
+ THCell(HT.TD('rho ', nowrap="on", Class="fs13 fwb ffl b1 cw cbrb"), text='corr', idx=8),
+ THCell(HT.TD('p(rho)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='pv', idx=9),
+ THCell(HT.TD('delta rho', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='delta_rho', idx=10)]]
+ else:
+ tblobj['header'] = \
+ [[THCell(HT.TD('', Class="fs13 fwb ffl b1 cw cbrb"), sort=0),
+ THCell(HT.TD('Database', Class="fs13 fwb ffl b1 cw cbrb",align='center'), text='db', idx=1),
+ THCell(HT.TD('Record', Class="fs13 fwb ffl b1 cw cbrb",align='center'), text='id', idx=2),
+ THCell(HT.TD('Symbol', Class="fs13 fwb ffl b1 cw cbrb"), text='symbol', idx=3),
+ THCell(HT.TD('Description', Class="fs13 fwb ffl b1 cw cbrb", align='center'), text='desc', idx=4),
+ THCell(HT.TD('N ', nowrap="on", Class="fs13 fwb ffl b1 cw cbrb"), text='nstr', idx=5),
+ THCell(HT.TD('Partial r ', nowrap="on", Class="fs13 fwb ffl b1 cw cbrb"), text='partial_corr', idx=6),
+ THCell(HT.TD('p(partial r)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='partial_pv', idx=7),
+ THCell(HT.TD('r ', nowrap="on", Class="fs13 fwb ffl b1 cw cbrb"), text='corr', idx=8),
+ THCell(HT.TD('p(r)', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='pv', idx=9),
+ THCell(HT.TD('delta r', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text='delta_r', idx=10)]]
+
+ sortby = ("partial_pv", "up")
+
+ tblobj['body'] = []
+ for i, thisTrait in enumerate(targetTraits):
+ tr = []
+
+ trId = str(thisTrait)
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.db.fullname,url=webqtlConfig.INFOPAGEHREF % thisTrait.db.name,target="_blank", Class="fs12 fwn"), Class="fs12 fwn ffl b1 c222"), text=thisTrait.db.name, val=thisTrait
+.db.name.upper()))
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showDatabase3('%s', '%s', '%s', '%s')" % (mainfmName,thisTrait.db.name,thisTrait.name,thisTrait.cellid), Class="fs12 fwn"), Class="fs12 fwn b1 c222"), text=thisTrait.name, val=thisTrait.name))
+
+ #XZ: Symbol column
+ if thisTrait.db.type =="ProbeSet":
+ if thisTrait.symbol:
+ tr.append(TDCell(HT.TD(thisTrait.symbol, Class="fs12 fwn ffl b1 c222"), text=thisTrait.symbol, val=thisTrait.symbol.upper()))
+ else:
+ tr.append(TDCell(HT.TD('NA', Class="fs12 fwn ffl b1 c222"), text='NA', val='NA'))
+ elif thisTrait.db.type =="Publish":
+ AbbreviationString = "--"
+ if (thisTrait.post_publication_abbreviation != None):
+ AbbreviationString = thisTrait.post_publication_abbreviation
+
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ if thisTrait.pre_publication_abbreviation:
+ AbbreviationString = thisTrait.pre_publication_abbreviation
+ else:
+ AbbreviationString = "--"
+
+ if AbbreviationString == "--":
+ tr.append(TDCell(HT.TD('NA', Class="fs12 fwn ffl b1 c222"), text='NA', val='NA'))
+ else:
+ tr.append(TDCell(HT.TD(AbbreviationString, Class="fs12 fwn ffl b1 c222"), text=AbbreviationString, val=AbbreviationString.upper()))
+ else:
+ tr.append(TDCell(HT.TD(thisTrait.name, Class="fs12 fwn ffl b1 c222"), text=thisTrait.name, val=thisTrait.name))
+
+ #XZ: Description column
+ if thisTrait.db.type =="ProbeSet" or thisTrait.db.type == "Temp":
+ tr.append(TDCell(HT.TD(thisTrait.description, Class="fs12 fwn ffl b1 c222"), text=thisTrait.description, val=thisTrait.description.upper()))
+ elif thisTrait.db.type =="Publish":
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ PhenotypeString = thisTrait.pre_publication_description
+ tr.append(TDCell(HT.TD(PhenotypeString, Class="fs12 fwn ffl b1 c222"), text=PhenotypeString, val=PhenotypeString.upper()))
+ else:
+ tr.append(TDCell(HT.TD(thisTrait.name, Class="fs12 fwn ffl b1 c222"), text=thisTrait.name, val=thisTrait.name))
+
+ tr.append(TDCell(HT.TD(allcorrelations[i][1], Class="fs12 fwn ffl b1 c222", align='right'), text=allcorrelations[i][1], val=allcorrelations[i][1]))
+
+ #partial correlation result
+ try:
+ repr = '%3.3f' % float(allcorrelations[i][2])
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'), text=repr, val=abs(allcorrelations[i][2])))
+ except:
+ repr = 'NA'
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='left'), text=repr, val=0 ))
+
+ repr = webqtlUtil.SciFloat(allcorrelations[i][3])
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", nowrap='ON', align='right'), text=repr, val=allcorrelations[i][3]))
+
+ #zero order correlation result
+ repr = '%3.3f' % float(allcorrelations[i][4])
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'), text=repr, val=abs(allcorrelations[i][4])))
+
+ repr = webqtlUtil.SciFloat(allcorrelations[i][5])
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", nowrap='ON', align='right'), text=repr, val=allcorrelations[i][5]))
+
+ #delta
+ try:
+ repr = '%3.3f' % ( float(allcorrelations[i][2]) - float(allcorrelations[i][4]) )
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'), text=repr, val=repr ))
+ except:
+ repr = 'NA'
+ tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='left'), text=repr, val=0 ))
+
+ tblobj['body'].append(tr)
+
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+ # NL, 07/27/2010. genTableObj function has been moved from templatePage.py to webqtlUtil.py;
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), Id="sortable")
+ form.append(div)
+
+
+ TD_LR.append(HT.Center(form),HT.P())
+
+ self.dict['body'] = str(TD_LR)
+ # updated by NL, moved js function xmlhttpPost() and updatepage() to dhtml.js
+ self.dict['js1'] = ''
+ self.dict['title'] = 'Partial Correlation Result'
+
diff --git a/web/webqtl/correlation/PlotCorrelationPage.py b/web/webqtl/correlation/PlotCorrelationPage.py
new file mode 100755
index 00000000..23d2ccde
--- /dev/null
+++ b/web/webqtl/correlation/PlotCorrelationPage.py
@@ -0,0 +1,683 @@
+# 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 Ning Liu 2011/01/11
+
+import string
+import piddle as pid
+import os
+
+from htmlgen import HTMLgen2 as HT
+
+from utility import svg #Code using this module currently commented out
+from utility import Plot
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+from correlation import correlationFunction
+
+#########################################
+# PlotCorrelationPage
+#########################################
+class PlotCorrelationPage(templatePage):
+ corrMinInformative = 4
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ self.initializeDisplayParameters(fd)
+
+ if not fd.genotype:
+ fd.readGenotype()
+
+ if fd.allstrainlist:
+ mdpchoice = fd.formdata.getvalue('MDPChoice')
+ if mdpchoice == "1":
+ strainlist = fd.f1list + fd.strainlist
+ elif mdpchoice == "2":
+ strainlist = []
+ strainlist2 = fd.f1list + fd.strainlist
+ for strain in fd.allstrainlist:
+ if strain not in strainlist2:
+ strainlist.append(strain)
+ #So called MDP Panel
+ if strainlist:
+ strainlist = fd.f1list+fd.parlist+strainlist
+ else:
+ strainlist = fd.allstrainlist
+ fd.readData(fd.allstrainlist)
+ else:
+ mdpchoice = None
+ strainlist = fd.strainlist
+ fd.readData()
+
+ #if fd.allstrainlist:
+ # fd.readData(fd.allstrainlist)
+ # strainlist = fd.allstrainlist
+ #else:
+ # fd.readData()
+ # strainlist = fd.strainlist
+
+
+ if not self.openMysql():
+ return
+
+ isSampleCorr = 0 #XZ: initial value is false
+ isTissueCorr = 0 #XZ: initial value is false
+
+ #Javascript functions (showCorrelationPlot2, showTissueCorrPlot) have made sure the correlation type is either sample correlation or tissue correlation.
+ if (self.database and (self.ProbeSetID != 'none')):
+ isSampleCorr = 1
+ elif (self.X_geneSymbol and self.Y_geneSymbol):
+ isTissueCorr = 1
+ else:
+ heading = "Correlation Type Error"
+ detail = ["For the input parameters, GN can not recognize the correlation type is sample correlation or tissue correlation."]
+ self.error(heading=heading,detail=detail)
+ return
+
+
+ TD_LR = HT.TD(colspan=2,height=200,width="100%",bgColor='#eeeeee', align="left", wrap="off")
+
+
+ dataX=[]
+ dataY=[]
+ dataZ=[] # shortname
+ fullTissueName=[]
+ xlabel = ''
+ ylabel = ''
+
+ if isTissueCorr:
+ dataX, dataY, xlabel, ylabel, dataZ, fullTissueName = self.getTissueLabelsValues(X_geneSymbol=self.X_geneSymbol, Y_geneSymbol=self.Y_geneSymbol, TissueProbeSetFreezeId=self.TissueProbeSetFreezeId)
+ plotHeading = HT.Paragraph('Tissue Correlation Scatterplot')
+ plotHeading.__setattr__("class","title")
+
+ if isSampleCorr:
+ plotHeading = HT.Paragraph('Sample Correlation Scatterplot')
+ plotHeading.__setattr__("class","title")
+
+ #XZ: retrieve trait 1 info, Y axis
+ trait1_data = [] #trait 1 data
+ trait1Url = ''
+
+ try:
+ Trait1 = webqtlTrait(db=self.database, name=self.ProbeSetID, cellid=self.CellID, cursor=self.cursor)
+ Trait1.retrieveInfo()
+ Trait1.retrieveData()
+ except:
+ heading = "Retrieve Data"
+ detail = ["The database you just requested has not been established yet."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ trait1_data = Trait1.exportData(strainlist)
+ if Trait1.db.type == 'Publish' and Trait1.confidential:
+ trait1Url = Trait1.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=Trait1.authorized_users)
+ else:
+ trait1Url = Trait1.genHTML(dispFromDatabase=1)
+ ylabel = '%s : %s' % (Trait1.db.shortname, Trait1.name)
+ if Trait1.cellid:
+ ylabel += ' : ' + Trait1.cellid
+
+
+ #XZ, retrieve trait 2 info, X axis
+ traitdata2 = [] #trait 2 data
+ _vals = [] #trait 2 data
+ trait2Url = ''
+
+ if ( self.database2 and (self.ProbeSetID2 != 'none') ):
+ try:
+ Trait2 = webqtlTrait(db=self.database2, name=self.ProbeSetID2, cellid=self.CellID2, cursor=self.cursor)
+ Trait2.retrieveInfo()
+ Trait2.retrieveData()
+ except:
+ heading = "Retrieve Data"
+ detail = ["The database you just requested has not been established yet."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ if Trait2.db.type == 'Publish' and Trait2.confidential:
+ trait2Url = Trait2.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=Trait2.authorized_users)
+ else:
+ trait2Url = Trait2.genHTML(dispFromDatabase=1)
+ traitdata2 = Trait2.exportData(strainlist)
+ _vals = traitdata2[:]
+ xlabel = '%s : %s' % (Trait2.db.shortname, Trait2.name)
+ if Trait2.cellid:
+ xlabel += ' : ' + Trait2.cellid
+ else:
+ for item in strainlist:
+ if fd.allTraitData.has_key(item):
+ _vals.append(fd.allTraitData[item].val)
+ else:
+ _vals.append(None)
+
+ if fd.identification:
+ xlabel = fd.identification
+ else:
+ xlabel = "User Input Data"
+
+ try:
+ Trait2 = webqtlTrait(fullname=fd.formdata.getvalue('fullname'), cursor=self.cursor)
+ trait2Url = Trait2.genHTML(dispFromDatabase=1)
+ except:
+ trait2Url = xlabel
+
+ if (_vals and trait1_data):
+ if len(_vals) != len(trait1_data):
+ errors = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('The number of traits are inconsistent, Program quit',color='black'))
+ errors.__setattr__("class","subtitle")
+ TD_LR.append(errors)
+ self.dict['body'] = str(TD_LR)
+ return
+
+ for i in range(len(_vals)):
+ if _vals[i]!= None and trait1_data[i]!= None:
+ dataX.append(_vals[i])
+ dataY.append(trait1_data[i])
+ strainName = strainlist[i]
+ if self.showstrains:
+ dataZ.append(webqtlUtil.genShortStrainName(RISet=fd.RISet, input_strainName=strainName))
+ else:
+ heading = "Correlation Plot"
+ detail = ['Empty Dataset for sample correlation, please check your data.']
+ self.error(heading=heading,detail=detail)
+ return
+
+
+ #XZ: We have gotten all data for both traits.
+ if len(dataX) >= self.corrMinInformative:
+
+ if self.rankOrder == 0:
+ rankPrimary = 0
+ rankSecondary = 1
+ else:
+ rankPrimary = 1
+ rankSecondary = 0
+
+ lineColor = self.setLineColor();
+ symbolColor = self.setSymbolColor();
+ idColor = self.setIdColor();
+
+ c = pid.PILCanvas(size=(self.plotSize, self.plotSize*0.90))
+ data_coordinate = Plot.plotXY(canvas=c, dataX=dataX, dataY=dataY, rank=rankPrimary, dataLabel = dataZ, labelColor=pid.black, lineSize=self.lineSize, lineColor=lineColor, idColor=idColor, idFont=self.idFont, idSize=self.idSize, symbolColor=symbolColor, symbolType=self.symbol, filled=self.filled, symbolSize=self.symbolSize, XLabel=xlabel, connectdot=0, YLabel=ylabel, title='', fitcurve=self.showline, displayR =1, offset= (90, self.plotSize/20, self.plotSize/10, 90), showLabel = self.showIdentifiers)
+
+ if rankPrimary == 1:
+ dataXlabel, dataYlabel = webqtlUtil.calRank(xVals=dataX, yVals=dataY, N=len(dataX))
+ else:
+ dataXlabel, dataYlabel = dataX, dataY
+
+ gifmap1 = HT.Map(name='CorrelationPlotImageMap1')
+
+ for i, item in enumerate(data_coordinate):
+ one_rect_coordinate = "%d, %d, %d, %d" % (item[0] - 5, item[1] - 5, item[0] + 5, item[1] + 5)
+ if isTissueCorr:
+ one_rect_title = "%s (%s, %s)" % (fullTissueName[i], dataXlabel[i], dataYlabel[i])
+ else:
+ one_rect_title = "%s (%s, %s)" % (dataZ[i], dataXlabel[i], dataYlabel[i])
+ gifmap1.areas.append(HT.Area(shape='rect',coords=one_rect_coordinate, title=one_rect_title) )
+
+ filename= webqtlUtil.genRandStr("XY_")
+ c.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img1=HT.Image('/image/'+filename+'.gif',border=0, usemap='#CorrelationPlotImageMap1')
+
+ mainForm_1 = HT.Form( cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':'_','CellID':'_','RISet':fd.RISet, 'ProbeSetID2':'_', 'database2':'_', 'CellID2':'_', 'allstrainlist':string.join(fd.strainlist, " "), 'traitList': fd.formdata.getvalue("traitList")}
+ if fd.incparentsf1:
+ hddn['incparentsf1'] = 'ON'
+ for key in hddn.keys():
+ mainForm_1.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ if isSampleCorr:
+ mainForm_1.append(HT.P(), HT.Blockquote(HT.Strong('X axis:'),HT.Blockquote(trait2Url),HT.Strong('Y axis:'),HT.Blockquote(trait1Url), style='width: %spx;' % self.plotSize, wrap="hard"))
+
+ graphForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='MDP_Form',submit=HT.Input(type='hidden'))
+ graph_hddn = self.setHiddenParameters(fd, rankPrimary)
+ webqtlUtil.exportData(graph_hddn, fd.allTraitData) #XZ: This is necessary to replot with different groups of strains
+
+ for key in graph_hddn.keys():
+ graphForm.append(HT.Input(name=key, value=graph_hddn[key], type='hidden'))
+
+ options = self.createOptionsMenu(fd, mdpchoice)
+
+ if (self.showOptions == '0'):
+ showOptionsButton = HT.Input(type='button' ,name='optionsButton',value='Hide Options', onClick="showHideOptions();", Class="button")
+ else:
+ showOptionsButton = HT.Input(type='button' ,name='optionsButton',value='Show Options', onClick="showHideOptions();", Class="button")
+
+ # updated by NL: 12-07-2011 add variables for tissue abbreviation page
+ if isTissueCorr:
+ graphForm.append(HT.Input(name='shortTissueName', value='', type='hidden'))
+ graphForm.append(HT.Input(name='fullTissueName', value='', type='hidden'))
+ shortTissueNameStr=string.join(dataZ, ",")
+ fullTissueNameStr=string.join(fullTissueName, ",")
+
+ tissueAbbrButton=HT.Input(type='button' ,name='tissueAbbrButton',value='Show Abbreviations', onClick="showTissueAbbr('MDP_Form','%s','%s')" % (shortTissueNameStr,fullTissueNameStr), Class="button")
+ graphForm.append(showOptionsButton,'&nbsp;&nbsp;&nbsp;&nbsp;',tissueAbbrButton, HT.BR(), HT.BR())
+ else:
+ graphForm.append(showOptionsButton, HT.BR(), HT.BR())
+
+ graphForm.append(options, HT.BR())
+ graphForm.append(HT.HR(), HT.BR(), HT.P())
+
+ TD_LR.append(plotHeading, HT.BR(),graphForm, HT.BR(), gifmap1, HT.P(), img1, HT.P(), mainForm_1)
+ TD_LR.append(HT.BR(), HT.HR(color="grey", size=5, width="100%"))
+
+
+
+ c = pid.PILCanvas(size=(self.plotSize, self.plotSize*0.90))
+ data_coordinate = Plot.plotXY(canvas=c, dataX=dataX, dataY=dataY, rank=rankSecondary, dataLabel = dataZ, labelColor=pid.black,lineColor=lineColor, lineSize=self.lineSize, idColor=idColor, idFont=self.idFont, idSize=self.idSize, symbolColor=symbolColor, symbolType=self.symbol, filled=self.filled, symbolSize=self.symbolSize, XLabel=xlabel, connectdot=0, YLabel=ylabel,title='', fitcurve=self.showline, displayR =1, offset= (90, self.plotSize/20, self.plotSize/10, 90), showLabel = self.showIdentifiers)
+
+ if rankSecondary == 1:
+ dataXlabel, dataYlabel = webqtlUtil.calRank(xVals=dataX, yVals=dataY, N=len(dataX))
+ else:
+ dataXlabel, dataYlabel = dataX, dataY
+
+ gifmap2 = HT.Map(name='CorrelationPlotImageMap2')
+
+ for i, item in enumerate(data_coordinate):
+ one_rect_coordinate = "%d, %d, %d, %d" % (item[0] - 6, item[1] - 6, item[0] + 6, item[1] + 6)
+ if isTissueCorr:
+ one_rect_title = "%s (%s, %s)" % (fullTissueName[i], dataXlabel[i], dataYlabel[i])
+ else:
+ one_rect_title = "%s (%s, %s)" % (dataZ[i], dataXlabel[i], dataYlabel[i])
+
+ gifmap2.areas.append(HT.Area(shape='rect',coords=one_rect_coordinate, title=one_rect_title) )
+
+ filename= webqtlUtil.genRandStr("XY_")
+ c.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img2=HT.Image('/image/'+filename+'.gif',border=0, usemap='#CorrelationPlotImageMap2')
+
+ mainForm_2 = HT.Form( cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase2', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase2','ProbeSetID':'_','database':'_','CellID':'_','RISet':fd.RISet, 'ProbeSetID2':'_', 'database2':'_', 'CellID2':'_', 'allstrainlist':string.join(fd.strainlist, " "), 'traitList': fd.formdata.getvalue("traitList")}
+ if fd.incparentsf1:
+ hddn['incparentsf1'] = 'ON'
+ for key in hddn.keys():
+ mainForm_2.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ if isSampleCorr:
+ mainForm_2.append(HT.P(), HT.Blockquote(HT.Strong('X axis:'),HT.Blockquote(trait2Url),HT.Strong('Y axis:'),HT.Blockquote(trait1Url), style='width:%spx;' % self.plotSize))
+
+
+ TD_LR.append(HT.BR(), HT.P())
+ TD_LR.append('\n', gifmap2, HT.P(), HT.P(), img2, HT.P(), mainForm_2)
+
+ self.dict['body'] = str(TD_LR)
+ else:
+ heading = "Correlation Plot"
+ detail = ['Fewer than %d strain data were entered for %s data set. No statitical analysis has been attempted.' % (self.corrMinInformative, fd.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+
+
+
+ def initializeDisplayParameters(self, fd):
+ """
+ Initializes all of the PlotCorrelationPage class parameters,
+ acquiring most values from the formdata (fd)
+ """
+
+ rankOrderString = fd.formdata.getvalue('rankOrder')
+ if rankOrderString == "1":
+ self.rankOrder = 1
+ else:
+ self.rankOrder = 0
+
+ self.dict['title'] = 'Correlation X-Y Scatterplot'
+ focusScript = "onLoad=\"document.getElementsByName('plotSize')[0].focus();\";"
+ self.dict['js2'] = focusScript
+
+ self.showstrains = fd.formdata.getvalue('ShowStrains')
+ self.showline = fd.formdata.getvalue('ShowLine')
+ self.X_geneSymbol = fd.formdata.getvalue('X_geneSymbol','')
+ self.Y_geneSymbol = fd.formdata.getvalue('Y_geneSymbol','')
+ self.TissueProbeSetFreezeId = fd.formdata.getvalue('TissueProbeSetFreezeId', '1')
+
+ self.symbolColor = fd.formdata.getvalue('symbolColor', 'black')
+ self.symbol = fd.formdata.getvalue('symbol', 'circle')
+ self.filled = fd.formdata.getvalue('filled', 'yes')
+ self.symbolSize = fd.formdata.getvalue('symbolSize', 'tiny')
+ self.idColor = fd.formdata.getvalue('idColor', 'blue')
+ self.idFont = fd.formdata.getvalue('idFont', 'arial')
+ self.idSize = fd.formdata.getvalue('idSize', '14')
+ self.lineColor = fd.formdata.getvalue('lineColor', 'grey')
+ self.lineSize = fd.formdata.getvalue('lineSize', 'medium')
+ self.showOptions = fd.formdata.getvalue('showOptions', '0')
+
+ try:
+ self.plotSize = int(fd.formdata.getvalue('plotSize', 900))
+ except:
+ self.plotSize = 900
+ try:
+ self.showIdentifiers = int(fd.formdata.getvalue('showIdentifiers', 1))
+ except:
+ self.showIdentifiers = 1
+
+ self.database = fd.formdata.getvalue('database')
+ self.ProbeSetID = fd.formdata.getvalue('ProbeSetID', 'none')
+ self.CellID = fd.formdata.getvalue('CellID')
+
+ self.database2 = fd.formdata.getvalue('database2')
+ self.ProbeSetID2 = fd.formdata.getvalue('ProbeSetID2', 'none')
+ self.CellID2 = fd.formdata.getvalue('CellID2')
+
+ def createOptionsMenu(self, fd, mdpchoice):
+ """
+ Create all the HTML for the options menu; the first if/else statements
+ determine whether the Div container holding all the other html is visible
+ or not.
+ """
+
+ if (self.showOptions == '0'):
+ options = HT.Div(name="options", id="options", style="display: none")
+ self.showOptions = '1'
+ else:
+ options = HT.Div(name="options", id="options", style="display: ''")
+ self.showOptions = '0'
+
+ if self.showIdentifiers:
+ containerTable = HT.TableLite(cellspacing=1, width=730, height=150, border=1)
+ else:
+ containerTable = HT.TableLite(cellspacing=1, width=730, height=130, border=1)
+
+ if self.showIdentifiers:
+ containerTable = HT.TableLite(cellspacing=1, width=730, height=150, border=1)
+ else:
+ containerTable = HT.TableLite(cellspacing=1, width=730, height=130, border=1)
+
+ containerRow = HT.TR()
+ containerCell = HT.TD(valign="middle", align="center")
+
+ optionsTable = HT.TableLite(Class="collap", cellspacing=2, width=700)
+
+ sizeOptions = HT.TR(align="right")
+ tagOptions = HT.TR(align="right")
+ markerOptions = HT.TR(align="right")
+ lineOptions = HT.TR(align="right")
+ replot_mdpOptions = HT.TR(align="right")
+
+ sizeOptions.append(HT.TD(HT.Bold("Size: "), "&nbsp;"*1, HT.Input(type='text' ,name='plotSize', value=self.plotSize, style="background-color: #FFFFFF; width: 50px;", onChange="checkWidth();"), align="left"))
+
+ idColorSel = HT.Select(name="idColorSel", onChange="changeIdColor(); submit();", selected=self.idColor)
+ idColorSel.append(("blue", "blue"))
+ idColorSel.append(("green", "green"))
+ idColorSel.append(("red", "red"))
+ idColorSel.append(("yellow", "yellow"))
+ idColorSel.append(("white", "white"))
+ idColorSel.append(("purple", "purple"))
+ idColorSel.append(("brown", "brown"))
+ idColorSel.append(("grey", "grey"))
+ idColorSel.append(("black","black"))
+
+ idFontSel = HT.Select(name="idFontSel", onChange="changeIdFont(); submit();", selected=self.idFont)
+ idFontSel.append(("Arial", "arial"))
+ idFontSel.append(("Trebuchet", "trebuc"))
+ idFontSel.append(("Verdana", "verdana"))
+ idFontSel.append(("Georgia", "Georgia"))
+ idFontSel.append(("Courier", "cour"))
+
+ idSizeSel = HT.Select(name="idSizeSel", onChange="changeIdSize(); submit();", selected=self.idSize)
+ idSizeSel.append(("10", "10"))
+ idSizeSel.append(("12", "12"))
+ idSizeSel.append(("14", "14"))
+ idSizeSel.append(("16", "16"))
+ idSizeSel.append(("18", "18"))
+
+ if self.showIdentifiers:
+ tagButton = HT.TD(HT.Input(type='button' ,name='',value=' Hide Tags ',onClick="this.form.showIdentifiers.value=0;submit();", Class="button"), align="right")
+ else:
+ tagButton = HT.TD(HT.Input(type='button' ,name='',value=' Show Tags ',onClick="this.form.showIdentifiers.value=1;submit();", Class="button"), align="right")
+
+ tagOptions.append(HT.TD(HT.Text(HT.Bold("Tag Settings: ")), align="left"))
+ tagOptions.append(HT.TD(HT.Text(text="Font: "), idFontSel))
+ tagOptions.append(HT.TD(HT.Text(text="Color: "), idColorSel))
+ tagOptions.append(HT.TD(HT.Text(text="Point: "), idSizeSel))
+ tagOptions.append(tagButton)
+ optionsTable.append(sizeOptions, tagOptions)
+
+ if fd.allstrainlist and mdpchoice:
+ allStrainList = HT.Input(name='allstrainlist', value=string.join(fd.allstrainlist, " "), type='hidden')
+ mdpChoice = HT.Input(name='MDPChoice', value=mdpchoice, type='hidden')
+ btn0 = HT.Input(type='button' ,name='',value='All Cases',onClick="this.form.MDPChoice.value=0;submit();", Class="button")
+ btn1 = HT.Input(type='button' ,name='',value='%s Only' % fd.RISet,onClick="this.form.MDPChoice.value=1;submit();", Class="button")
+ btn2 = HT.Input(type='button' ,name='',value='MDP Only', onClick="this.form.MDPChoice.value=2;submit();", Class="button")
+
+
+ colorSel = HT.Select(name="colorSel", onChange="changeSymbolColor(); submit();", selected=self.symbolColor)
+ colorSel.append(("red", "red"))
+ colorSel.append(("green", "green"))
+ colorSel.append(("blue", "blue"))
+ colorSel.append(("yellow", "yellow"))
+ colorSel.append(("purple", "purple"))
+ colorSel.append(("brown", "brown"))
+ colorSel.append(("grey", "grey"))
+ colorSel.append(("black","black"))
+
+ symbolSel = HT.Select(name="symbolSel", onChange="changeSymbol(); submit();", selected=self.symbol)
+ symbolSel.append(("4-star","4-star"))
+ symbolSel.append(("3-star","3-star"))
+ symbolSel.append(("cross", "cross"))
+ symbolSel.append(("circle","circle"))
+ symbolSel.append(("diamond", "diamond"))
+ symbolSel.append(("square", "square"))
+ symbolSel.append(("vert rect", "vertRect"))
+ symbolSel.append(("hori rect", "horiRect"))
+
+ sizeSel = HT.Select(name="sizeSel", onChange="changeSize(); submit();", selected=self.symbolSize)
+ sizeSel.append(("tiny","tiny"))
+ sizeSel.append(("small","small"))
+ sizeSel.append(("medium","medium"))
+ sizeSel.append(("large","large"))
+
+ fillSel = HT.Select(name="fillSel", onChange="changeFilled(); submit();", selected=self.filled)
+ fillSel.append(("no","no"))
+ fillSel.append(("yes","yes"))
+
+ lineColorSel = HT.Select(name="lineColorSel", onChange="changeLineColor(); submit();", selected=self.lineColor)
+ lineColorSel.append(("red", "red"))
+ lineColorSel.append(("green", "green"))
+ lineColorSel.append(("blue", "blue"))
+ lineColorSel.append(("yellow", "yellow"))
+ lineColorSel.append(("purple", "purple"))
+ lineColorSel.append(("brown", "brown"))
+ lineColorSel.append(("grey", "grey"))
+ lineColorSel.append(("black","black"))
+
+ lineSizeSel = HT.Select(name="lineSizeSel", onChange="changeLineSize(); submit();", selected=self.lineSize)
+ lineSizeSel.append(("thin", "thin"))
+ lineSizeSel.append(("medium", "medium"))
+ lineSizeSel.append(("thick", "thick"))
+
+
+ markerOptions.append(HT.TD(HT.Text(HT.Bold("Marker Settings: ")), align="left"))
+ markerOptions.append(HT.TD(HT.Text(text="Marker: "), symbolSel))
+ markerOptions.append(HT.TD(HT.Text(text="Color: "), colorSel))
+ markerOptions.append(HT.TD(HT.Text(text="Fill: "), fillSel))
+ markerOptions.append(HT.TD(HT.Text(text="Size: "), sizeSel))
+
+ lineOptions.append(HT.TD(HT.Text(HT.Bold("Line Settings: ")), align="left"))
+ lineOptions.append(HT.TD(HT.Text(text="Width: "), lineSizeSel))
+ lineOptions.append(HT.TD(HT.Text(text="Color: "), lineColorSel))
+
+ replotButton = HT.Input(type='button', name='', value=' Replot ',onClick="checkWidth(); submit();", Class="button")
+
+ if fd.allstrainlist and mdpchoice:
+ replot_mdpOptions.append(HT.TD(replotButton, align="left"), HT.TD(allStrainList, mdpChoice, btn0, btn1, btn2, align="center", colspan=3))
+ optionsTable.append(markerOptions, lineOptions, HT.TR(HT.TD(HT.BR())), replot_mdpOptions )
+ else:
+ replot_mdpOptions.append(HT.TD(replotButton, align="left"))
+ optionsTable.append(markerOptions, lineOptions, HT.TR(HT.TD(HT.BR())), replot_mdpOptions)
+
+ containerCell.append(optionsTable)
+ containerRow.append(containerCell)
+ containerTable.append(containerRow)
+
+ options.append(containerTable)
+
+ return options
+
+ def setHiddenParameters(self, fd, rankPrimary):
+ """
+ Create the dictionary of hidden form parameters from PlotCorrelationPage's class parameters
+ """
+
+ graph_hddn = {'FormID':'showCorrelationPlot','RISet':fd.RISet, 'identification':fd.identification, "incparentsf1":1, "showIdentifiers":self.showIdentifiers}
+
+ if self.database: graph_hddn['database']=self.database
+ if self.ProbeSetID: graph_hddn['ProbeSetID']=self.ProbeSetID
+ if self.CellID: graph_hddn['CellID']=self.CellID
+ if self.database2: graph_hddn['database2']=self.database2
+ if self.ProbeSetID2: graph_hddn['ProbeSetID2']=self.ProbeSetID2
+ if self.CellID2: graph_hddn['CellID2']=self.CellID2
+ if self.showstrains: graph_hddn['ShowStrains']=self.showstrains
+ if self.showline: graph_hddn['ShowLine']=self.showline
+ if self.X_geneSymbol: graph_hddn['X_geneSymbol']=self.X_geneSymbol
+ if self.Y_geneSymbol: graph_hddn['Y_geneSymbol']=self.Y_geneSymbol
+ if self.TissueProbeSetFreezeId: graph_hddn['TissueProbeSetFreezeId']=self.TissueProbeSetFreezeId
+ if self.rankOrder: graph_hddn['rankOrder'] = rankPrimary
+ if fd.formdata.getvalue('fullname'): graph_hddn['fullname']=fd.formdata.getvalue('fullname')
+ if self.lineColor: graph_hddn['lineColor'] = self.lineColor
+ if self.lineSize: graph_hddn['lineSize'] = self.lineSize
+ if self.idColor: graph_hddn['idColor'] = self.idColor
+ if self.idFont: graph_hddn['idFont'] = self.idFont
+ if self.idSize: graph_hddn['idSize'] = self.idSize
+ if self.symbolColor: graph_hddn['symbolColor'] = self.symbolColor
+ if self.symbol: graph_hddn['symbol'] = self.symbol
+ if self.filled: graph_hddn['filled'] = self.filled
+ if self.symbolSize: graph_hddn['symbolSize'] = self.symbolSize
+ if self.showOptions: graph_hddn['showOptions'] = self.showOptions
+
+ return graph_hddn
+
+ def setIdColor(self):
+ """
+ Set the plot tag/ID color based upon the value of the idColor class parameter
+ """
+
+ if self.idColor == 'black':
+ idColor = pid.black
+ elif self.idColor == 'white':
+ idColor = pid.white
+ elif self.idColor == 'yellow':
+ idColor = pid.yellow
+ elif self.idColor == 'grey':
+ idColor = pid.grey
+ elif self.idColor == 'blue':
+ idColor = pid.blue
+ elif self.idColor == 'purple':
+ idColor = pid.purple
+ elif self.idColor == 'brown':
+ idColor = pid.brown
+ elif self.idColor == 'green':
+ idColor = pid.green
+ else:
+ idColor = pid.red
+
+ return idColor
+
+ def setSymbolColor(self):
+ """
+ Set the plot symbol color based upon the value of the symbolColor class parameter
+ """
+
+ if self.symbolColor == 'black':
+ symbolColor = pid.black
+ elif self.symbolColor == 'grey':
+ symbolColor = pid.grey
+ elif self.symbolColor == 'yellow':
+ symbolColor = pid.yellow
+ elif self.symbolColor == 'blue':
+ symbolColor = pid.blue
+ elif self.symbolColor == 'purple':
+ symbolColor = pid.purple
+ elif self.symbolColor == 'brown':
+ symbolColor = pid.brown
+ elif self.symbolColor== 'green':
+ symbolColor = pid.green
+ else:
+ symbolColor = pid.red
+
+ return symbolColor
+
+ def setLineColor(self):
+ """
+ Set the plot line color based upon the lineColor class parameter
+ """
+
+ if self.lineColor == 'black':
+ lineColor = pid.black
+ elif self.lineColor == 'grey':
+ lineColor = pid.grey
+ elif self.lineColor == 'yellow':
+ lineColor = pid.yellow
+ elif self.lineColor == 'blue':
+ lineColor = pid.blue
+ elif self.lineColor == 'purple':
+ lineColor = pid.purple
+ elif self.lineColor == 'brown':
+ lineColor = pid.brown
+ elif self.lineColor== 'green':
+ lineColor = pid.green
+ else:
+ lineColor = pid.red
+
+ return lineColor
+
+
+ def getTissueLabelsValues(self, X_geneSymbol=None, Y_geneSymbol=None, TissueProbeSetFreezeId=None ):
+
+ dataX = []
+ dataY = []
+ data_fullLabel = []
+ data_shortLabel = []
+ # updated by NL, 2011-01-11 using new function getTissueProbeSetXRefInfo to get dataId value
+ X_symbolList,X_geneIdDict,X_dataIdDict,X_ChrDict,X_MbDict,X_descDict,X_pTargetDescDict = correlationFunction.getTissueProbeSetXRefInfo(cursor=self.cursor,GeneNameLst=[X_geneSymbol],TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ Y_symbolList,Y_geneIdDict,Y_dataIdDict,Y_ChrDict,Y_MbDict,Y_descDict,Y_pTargetDescDict = correlationFunction.getTissueProbeSetXRefInfo(cursor=self.cursor,GeneNameLst=[Y_geneSymbol],TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ # in dataIdDict, key is the lower cased geneSymbol
+ X_DataId = X_dataIdDict[X_geneSymbol.lower()]
+ Y_DataId = Y_dataIdDict[Y_geneSymbol.lower()]
+
+ self.cursor.execute("SELECT TissueID,value FROM TissueProbeSetData WHERE Id = %d ORDER BY TissueID" % int(X_DataId) )
+ results = self.cursor.fetchall()
+ for item in results:
+ TissueID, Value = item
+ dataX.append(Value)
+ self.cursor.execute("SELECT Tissue.Name, Tissue.Short_Name FROM Tissue WHERE Id = %d" % int(TissueID) )
+ temp = self.cursor.fetchone()
+ data_fullLabel.append( temp[0] )
+ data_shortLabel.append( temp[1] )
+
+ self.cursor.execute("SELECT TissueID,value FROM TissueProbeSetData WHERE Id = %d ORDER BY TissueID" % int(Y_DataId) )
+ results = self.cursor.fetchall()
+ for item in results:
+ TissueID, Value = item
+ dataY.append(Value)
+
+ X_label = "%s" % X_geneSymbol
+ Y_label = "%s" % Y_geneSymbol
+
+ return dataX, dataY, X_label, Y_label, data_shortLabel, data_fullLabel
diff --git a/web/webqtl/correlation/__init__.py b/web/webqtl/correlation/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/correlation/__init__.py
diff --git a/web/webqtl/correlation/correlationFunction.py b/web/webqtl/correlation/correlationFunction.py
new file mode 100755
index 00000000..cc19f54e
--- /dev/null
+++ b/web/webqtl/correlation/correlationFunction.py
@@ -0,0 +1,923 @@
+# 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 2011/03/23
+
+
+import math
+import rpy2.robjects
+import pp
+import string
+
+from utility import webqtlUtil
+from base.webqtlTrait import webqtlTrait
+from dbFunction import webqtlDatabaseFunction
+
+
+
+#XZ: The input 'controls' is String. It contains the full name of control traits.
+#XZ: The input variable 'strainlst' is List. It contains the strain names of primary trait.
+#XZ: The returned tcstrains is the list of list [[],[]...]. So are tcvals and tcvars. The last returned parameter is list of numbers.
+#XZ, 03/29/2010: For each returned control trait, there is no None value in it.
+def controlStrains(controls, strainlst):
+
+ controls = controls.split(',')
+
+ cvals = {}
+ for oneTraitName in controls:
+ oneTrait = webqtlTrait(fullname=oneTraitName, cursor=webqtlDatabaseFunction.getCursor() )
+ oneTrait.retrieveData()
+ cvals[oneTraitName] = oneTrait.data
+
+ tcstrains = []
+ tcvals = []
+ tcvars = []
+
+ for oneTraitName in controls:
+ strains = []
+ vals = []
+ vars = []
+
+ for _strain in strainlst:
+ if cvals[oneTraitName].has_key(_strain):
+ _val = cvals[oneTraitName][_strain].val
+ if _val != None:
+ strains.append(_strain)
+ vals.append(_val)
+ vars.append(None)
+
+ tcstrains.append(strains)
+ tcvals.append(vals)
+ tcvars.append(vars)
+
+ return tcstrains, tcvals, tcvars, [len(x) for x in tcstrains]
+
+
+
+#XZ, 03/29/2010: After execution of functon "controlStrains" and "fixStrains", primary trait and control traits have the same strains and in the same order. There is no 'None' value in them.
+def fixStrains(_strains,_controlstrains,_vals,_controlvals,_vars,_controlvars):
+ """Corrects strains, vals, and vars so that all contrain only those strains common
+ to the reference trait and all control traits."""
+
+ def dictify(strains,vals,vars):
+ subdict = {}
+ for i in xrange(len(strains)):
+ subdict[strains[i]] = (vals[i],vars[i])
+ return subdict
+
+ #XZ: The 'dicts' is a list of dictionary. The first element is the dictionary of reference trait. The rest elements are for control traits.
+ dicts = []
+ dicts.append(dictify(_strains,_vals,_vars))
+
+ nCstrains = len(_controlstrains)
+ for i in xrange(nCstrains):
+ dicts.append(dictify(_controlstrains[i],_controlvals[i],_controlvars[i]))
+
+ _newstrains = []
+ _vals = []
+ _vars = []
+ _controlvals = [[] for x in xrange(nCstrains)]
+ _controlvars = [[] for x in xrange(nCstrains)]
+
+ for strain in _strains:
+ inall = True
+ for d in dicts:
+ if strain not in d:
+ inall = False
+ break
+ if inall:
+ _newstrains.append(strain)
+ _vals.append(dicts[0][strain][0])
+ _vars.append(dicts[0][strain][1])
+ for i in xrange(nCstrains):
+ _controlvals[i].append(dicts[i+1][strain][0])
+ _controlvars[i].append(dicts[i+1][strain][1])
+
+ return _newstrains, _vals, _controlvals, _vars, _controlvars
+
+
+#XZ, 6/15/2010: If there is no identical control traits, the returned list is empty.
+#else, the returned list has two elements of control trait name.
+def findIdenticalControlTraits ( controlVals, controlNames ):
+ nameOfIdenticalTraits = []
+
+ controlTraitNumber = len(controlVals)
+
+ if controlTraitNumber > 1:
+
+ #XZ: reset the precision of values and convert to string type
+ for oneTraitVal in controlVals:
+ for oneStrainVal in oneTraitVal:
+ oneStrainVal = '%.3f' % oneStrainVal
+
+ for i, oneTraitVal in enumerate( controlVals ):
+ for j in range(i+1, controlTraitNumber):
+ if oneTraitVal == controlVals[j]:
+ nameOfIdenticalTraits.append(controlNames[i])
+ nameOfIdenticalTraits.append(controlNames[j])
+
+ return nameOfIdenticalTraits
+
+#XZ, 6/15/2010: If there is no identical control traits, the returned list is empty.
+#else, the returned list has two elements of control trait name.
+#primaryVal is of list type. It contains value of primary trait.
+#primaryName is of string type.
+#controlVals is of list type. Each element is list too. Each element contain value of one control trait.
+#controlNames is of list type.
+def findIdenticalTraits (primaryVal, primaryName, controlVals, controlNames ):
+ nameOfIdenticalTraits = []
+
+ #XZ: reset the precision of values and convert to string type
+ for oneStrainVal in primaryVal:
+ oneStrainVal = '%.3f' % oneStrainVal
+
+ for oneTraitVal in controlVals:
+ for oneStrainVal in oneTraitVal:
+ oneStrainVal = '%.3f' % oneStrainVal
+
+ controlTraitNumber = len(controlVals)
+
+ if controlTraitNumber > 1:
+ for i, oneTraitVal in enumerate( controlVals ):
+ for j in range(i+1, controlTraitNumber):
+ if oneTraitVal == controlVals[j]:
+ nameOfIdenticalTraits.append(controlNames[i])
+ nameOfIdenticalTraits.append(controlNames[j])
+ break
+
+ if len(nameOfIdenticalTraits) == 0:
+ for i, oneTraitVal in enumerate( controlVals ):
+ if primaryVal == oneTraitVal:
+ nameOfIdenticalTraits.append(primaryName)
+ nameOfIdenticalTraits.append(controlNames[i])
+ break
+
+ return nameOfIdenticalTraits
+
+
+
+#XZ, 03/29/2010: The strains in primaryVal, controlVals, targetVals must be of the same number and in same order.
+#XZ: No value in primaryVal and controlVals could be None.
+
+def determinePartialsByR (primaryVal, controlVals, targetVals, targetNames, method='p'):
+
+ def compute_partial ( primaryVal, controlVals, targetVals, targetNames, method ):
+
+ rpy2.robjects.r("""
+pcor.test <- function(x,y,z,use="mat",method="p",na.rm=T){
+ # The partial correlation coefficient between x and y given z
+ #
+ # pcor.test is free and comes with ABSOLUTELY NO WARRANTY.
+ #
+ # x and y should be vectors
+ #
+ # z can be either a vector or a matrix
+ #
+ # use: There are two methods to calculate the partial correlation coefficient.
+ # One is by using variance-covariance matrix ("mat") and the other is by using recursive formula ("rec").
+ # Default is "mat".
+ #
+ # method: There are three ways to calculate the correlation coefficient,
+ # which are Pearson's ("p"), Spearman's ("s"), and Kendall's ("k") methods.
+ # The last two methods which are Spearman's and Kendall's coefficient are based on the non-parametric analysis.
+ # Default is "p".
+ #
+ # na.rm: If na.rm is T, then all the missing samples are deleted from the whole dataset, which is (x,y,z).
+ # If not, the missing samples will be removed just when the correlation coefficient is calculated.
+ # However, the number of samples for the p-value is the number of samples after removing
+ # all the missing samples from the whole dataset.
+ # Default is "T".
+
+ x <- c(x)
+ y <- c(y)
+ z <- as.data.frame(z)
+
+ if(use == "mat"){
+ p.use <- "Var-Cov matrix"
+ pcor = pcor.mat(x,y,z,method=method,na.rm=na.rm)
+ }else if(use == "rec"){
+ p.use <- "Recursive formula"
+ pcor = pcor.rec(x,y,z,method=method,na.rm=na.rm)
+ }else{
+ stop("use should be either rec or mat!\n")
+ }
+
+ # print the method
+ if(gregexpr("p",method)[[1]][1] == 1){
+ p.method <- "Pearson"
+ }else if(gregexpr("s",method)[[1]][1] == 1){
+ p.method <- "Spearman"
+ }else if(gregexpr("k",method)[[1]][1] == 1){
+ p.method <- "Kendall"
+ }else{
+ stop("method should be pearson or spearman or kendall!\n")
+ }
+
+ # sample number
+ n <- dim(na.omit(data.frame(x,y,z)))[1]
+
+ # given variables' number
+ gn <- dim(z)[2]
+
+ # p-value
+ if(p.method == "Kendall"){
+ statistic <- pcor/sqrt(2*(2*(n-gn)+5)/(9*(n-gn)*(n-1-gn)))
+ p.value <- 2*pnorm(-abs(statistic))
+
+ }else{
+ statistic <- pcor*sqrt((n-2-gn)/(1-pcor^2))
+ p.value <- 2*pnorm(-abs(statistic))
+ }
+
+ data.frame(estimate=pcor,p.value=p.value,statistic=statistic,n=n,gn=gn,Method=p.method,Use=p.use)
+}
+
+# By using var-cov matrix
+pcor.mat <- function(x,y,z,method="p",na.rm=T){
+
+ x <- c(x)
+ y <- c(y)
+ z <- as.data.frame(z)
+
+ if(dim(z)[2] == 0){
+ stop("There should be given data\n")
+ }
+
+ data <- data.frame(x,y,z)
+
+ if(na.rm == T){
+ data = na.omit(data)
+ }
+
+ xdata <- na.omit(data.frame(data[,c(1,2)]))
+ Sxx <- cov(xdata,xdata,m=method)
+
+ xzdata <- na.omit(data)
+ xdata <- data.frame(xzdata[,c(1,2)])
+ zdata <- data.frame(xzdata[,-c(1,2)])
+ Sxz <- cov(xdata,zdata,m=method)
+
+ zdata <- na.omit(data.frame(data[,-c(1,2)]))
+ Szz <- cov(zdata,zdata,m=method)
+
+ # is Szz positive definite?
+ zz.ev <- eigen(Szz)$values
+ if(min(zz.ev)[1]<0){
+ stop("\'Szz\' is not positive definite!\n")
+ }
+
+ # partial correlation
+ Sxx.z <- Sxx - Sxz %*% solve(Szz) %*% t(Sxz)
+
+ rxx.z <- cov2cor(Sxx.z)[1,2]
+
+ rxx.z
+}
+
+# By using recursive formula
+pcor.rec <- function(x,y,z,method="p",na.rm=T){
+ #
+
+ x <- c(x)
+ y <- c(y)
+ z <- as.data.frame(z)
+
+ if(dim(z)[2] == 0){
+ stop("There should be given data\n")
+ }
+
+ data <- data.frame(x,y,z)
+
+ if(na.rm == T){
+ data = na.omit(data)
+ }
+
+ # recursive formula
+ if(dim(z)[2] == 1){
+ tdata <- na.omit(data.frame(data[,1],data[,2]))
+ rxy <- cor(tdata[,1],tdata[,2],m=method)
+
+ tdata <- na.omit(data.frame(data[,1],data[,-c(1,2)]))
+ rxz <- cor(tdata[,1],tdata[,2],m=method)
+
+ tdata <- na.omit(data.frame(data[,2],data[,-c(1,2)]))
+ ryz <- cor(tdata[,1],tdata[,2],m=method)
+
+ rxy.z <- (rxy - rxz*ryz)/( sqrt(1-rxz^2)*sqrt(1-ryz^2) )
+
+ return(rxy.z)
+ }else{
+ x <- c(data[,1])
+ y <- c(data[,2])
+ z0 <- c(data[,3])
+ zc <- as.data.frame(data[,-c(1,2,3)])
+
+ rxy.zc <- pcor.rec(x,y,zc,method=method,na.rm=na.rm)
+ rxz0.zc <- pcor.rec(x,z0,zc,method=method,na.rm=na.rm)
+ ryz0.zc <- pcor.rec(y,z0,zc,method=method,na.rm=na.rm)
+
+ rxy.z <- (rxy.zc - rxz0.zc*ryz0.zc)/( sqrt(1-rxz0.zc^2)*sqrt(1-ryz0.zc^2) )
+ return(rxy.z)
+ }
+}
+""")
+
+ R_pcorr_function = rpy2.robjects.r['pcor.test']
+ R_corr_test = rpy2.robjects.r['cor.test']
+
+ primary = rpy2.robjects.FloatVector(range(len(primaryVal)))
+ for i in range(len(primaryVal)):
+ primary[i] = primaryVal[i]
+
+ control = rpy2.robjects.r.matrix(rpy2.robjects.FloatVector( range(len(controlVals)*len(controlVals[0])) ), ncol=len(controlVals))
+ for i in range(len(controlVals)):
+ for j in range(len(controlVals[0])):
+ control[i*len(controlVals[0]) + j] = controlVals[i][j]
+
+ allcorrelations = []
+
+ for targetIndex, oneTargetVals in enumerate(targetVals):
+
+ this_primary = None
+ this_control = None
+ this_target = None
+
+ if None in oneTargetVals:
+
+ goodIndex = []
+ for i in range(len(oneTargetVals)):
+ if oneTargetVals[i] != None:
+ goodIndex.append(i)
+
+ this_primary = rpy2.robjects.FloatVector(range(len(goodIndex)))
+ for i in range(len(goodIndex)):
+ this_primary[i] = primaryVal[goodIndex[i]]
+
+ this_control = rpy2.robjects.r.matrix(rpy2.robjects.FloatVector( range(len(controlVals)*len(goodIndex)) ), ncol=len(controlVals))
+ for i in range(len(controlVals)):
+ for j in range(len(goodIndex)):
+ this_control[i*len(goodIndex) + j] = controlVals[i][goodIndex[j]]
+
+ this_target = rpy2.robjects.FloatVector(range(len(goodIndex)))
+ for i in range(len(goodIndex)):
+ this_target[i] = oneTargetVals[goodIndex[i]]
+
+ else:
+ this_primary = primary
+ this_control = control
+ this_target = rpy2.robjects.FloatVector(range(len(oneTargetVals)))
+ for i in range(len(oneTargetVals)):
+ this_target[i] = oneTargetVals[i]
+
+ one_name = targetNames[targetIndex]
+ one_N = len(this_primary)
+
+ #calculate partial correlation
+ one_pc_coefficient = 'NA'
+ one_pc_p = 1
+
+ try:
+ if method == 's':
+ result = R_pcorr_function(this_primary, this_target, this_control, method='s')
+ else:
+ result = R_pcorr_function(this_primary, this_target, this_control)
+
+ #XZ: In very few cases, the returned coefficient is nan.
+ #XZ: One way to detect nan is to compare the number to itself. NaN is always != NaN
+ if result[0][0] == result[0][0]:
+ one_pc_coefficient = result[0][0]
+ #XZ: when the coefficient value is 1 (primary trait and target trait are the same),
+ #XZ: occationally, the returned p value is nan instead of 0.
+ if result[1][0] == result[1][0]:
+ one_pc_p = result[1][0]
+ elif abs(one_pc_coefficient - 1) < 0.0000001:
+ one_pc_p = 0
+ except:
+ pass
+
+ #calculate zero order correlation
+ one_corr_coefficient = 0
+ one_corr_p = 1
+
+ try:
+ if method == 's':
+ R_result = R_corr_test(this_primary, this_target, method='spearman')
+ else:
+ R_result = R_corr_test(this_primary, this_target)
+
+ one_corr_coefficient = R_result[3][0]
+ one_corr_p = R_result[2][0]
+ except:
+ pass
+
+ traitinfo = [ one_name, one_N, one_pc_coefficient, one_pc_p, one_corr_coefficient, one_corr_p ]
+
+ allcorrelations.append(traitinfo)
+
+ return allcorrelations
+ #End of function compute_partial
+
+
+ allcorrelations = []
+
+ target_trait_number = len(targetVals)
+
+ if target_trait_number < 1000:
+ allcorrelations = compute_partial ( primaryVal, controlVals, targetVals, targetNames, method )
+ else:
+ step = 1000
+ job_number = math.ceil( float(target_trait_number)/step )
+
+ job_targetVals_lists = []
+ job_targetNames_lists = []
+
+ for job_index in range( int(job_number) ):
+ starti = job_index*step
+ endi = min((job_index+1)*step, target_trait_number)
+
+ one_job_targetVals_list = []
+ one_job_targetNames_list = []
+
+ for i in range( starti, endi ):
+ one_job_targetVals_list.append( targetVals[i] )
+ one_job_targetNames_list.append( targetNames[i] )
+
+ job_targetVals_lists.append( one_job_targetVals_list )
+ job_targetNames_lists.append( one_job_targetNames_list )
+
+ ppservers = ()
+ # Creates jobserver with automatically detected number of workers
+ job_server = pp.Server(ppservers=ppservers)
+
+ jobs = []
+ results = []
+
+ for i, one_job_targetVals_list in enumerate( job_targetVals_lists ):
+ one_job_targetNames_list = job_targetNames_lists[i]
+ #pay attention to modules from outside
+ jobs.append( job_server.submit(func=compute_partial, args=( primaryVal, controlVals, one_job_targetVals_list, one_job_targetNames_list, method), depfuncs=(), modules=("rpy2.robjects",)) )
+
+ for one_job in jobs:
+ one_result = one_job()
+ results.append( one_result )
+
+ for one_result in results:
+ for one_traitinfo in one_result:
+ allcorrelations.append( one_traitinfo )
+
+ return allcorrelations
+
+
+
+#XZ, April 30, 2010: The input primaryTrait and targetTrait are instance of webqtlTrait
+#XZ: The primaryTrait and targetTrait should have executed retrieveData function
+def calZeroOrderCorr (primaryTrait, targetTrait, method='pearson'):
+
+ #primaryTrait.retrieveData()
+
+ #there is no None value in primary_val
+ primary_strain, primary_val, primary_var = primaryTrait.exportInformative()
+
+ #targetTrait.retrieveData()
+
+ #there might be None value in target_val
+ target_val = targetTrait.exportData(primary_strain, type="val")
+
+ R_primary = rpy2.robjects.FloatVector(range(len(primary_val)))
+ for i in range(len(primary_val)):
+ R_primary[i] = primary_val[i]
+
+ N = len(target_val)
+
+ if None in target_val:
+ goodIndex = []
+ for i in range(len(target_val)):
+ if target_val[i] != None:
+ goodIndex.append(i)
+
+ N = len(goodIndex)
+
+ R_primary = rpy2.robjects.FloatVector(range(len(goodIndex)))
+ for i in range(len(goodIndex)):
+ R_primary[i] = primary_val[goodIndex[i]]
+
+ R_target = rpy2.robjects.FloatVector(range(len(goodIndex)))
+ for i in range(len(goodIndex)):
+ R_target[i] = target_val[goodIndex[i]]
+
+ else:
+ R_target = rpy2.robjects.FloatVector(range(len(target_val)))
+ for i in range(len(target_val)):
+ R_target[i] = target_val[i]
+
+ R_corr_test = rpy2.robjects.r['cor.test']
+
+ if method == 'spearman':
+ R_result = R_corr_test(R_primary, R_target, method='spearman')
+ else:
+ R_result = R_corr_test(R_primary, R_target)
+
+ corr_result = []
+ corr_result.append( R_result[3][0] )
+ corr_result.append( N )
+ corr_result.append( R_result[2][0] )
+
+ return corr_result
+
+#####################################################################################
+#Input: primaryValue(list): one list of expression values of one probeSet,
+# targetValue(list): one list of expression values of one probeSet,
+# method(string): indicate correlation method ('pearson' or 'spearman')
+#Output: corr_result(list): first item is Correlation Value, second item is tissue number,
+# third item is PValue
+#Function: get correlation value,Tissue quantity ,p value result by using R;
+#Note : This function is special case since both primaryValue and targetValue are from
+#the same dataset. So the length of these two parameters is the same. They are pairs.
+#Also, in the datatable TissueProbeSetData, all Tissue values are loaded based on
+#the same tissue order
+#####################################################################################
+
+def calZeroOrderCorrForTiss (primaryValue=[], targetValue=[], method='pearson'):
+
+ R_primary = rpy2.robjects.FloatVector(range(len(primaryValue)))
+ N = len(primaryValue)
+ for i in range(len(primaryValue)):
+ R_primary[i] = primaryValue[i]
+
+ R_target = rpy2.robjects.FloatVector(range(len(targetValue)))
+ for i in range(len(targetValue)):
+ R_target[i]=targetValue[i]
+
+ R_corr_test = rpy2.robjects.r['cor.test']
+ if method =='spearman':
+ R_result = R_corr_test(R_primary, R_target, method='spearman')
+ else:
+ R_result = R_corr_test(R_primary, R_target)
+
+ corr_result =[]
+ corr_result.append( R_result[3][0])
+ corr_result.append( N )
+ corr_result.append( R_result[2][0])
+
+ return corr_result
+
+
+
+
+def batchCalTissueCorr(primaryTraitValue=[], SymbolValueDict={}, method='pearson'):
+
+ def cal_tissue_corr(primaryTraitValue, oneSymbolValueDict, method ):
+
+ oneSymbolCorrDict = {}
+ oneSymbolPvalueDict = {}
+
+ R_corr_test = rpy2.robjects.r['cor.test']
+
+ R_primary = rpy2.robjects.FloatVector(range(len(primaryTraitValue)))
+
+ for i in range(len(primaryTraitValue)):
+ R_primary[i] = primaryTraitValue[i]
+
+ for (oneTraitSymbol, oneTraitValue) in oneSymbolValueDict.iteritems():
+ R_target = rpy2.robjects.FloatVector(range(len(oneTraitValue)))
+ for i in range(len(oneTraitValue)):
+ R_target[i] = oneTraitValue[i]
+
+ if method =='spearman':
+ R_result = R_corr_test(R_primary, R_target, method='spearman')
+ else:
+ R_result = R_corr_test(R_primary, R_target)
+
+ oneSymbolCorrDict[oneTraitSymbol] = R_result[3][0]
+ oneSymbolPvalueDict[oneTraitSymbol] = R_result[2][0]
+
+ return(oneSymbolCorrDict, oneSymbolPvalueDict)
+
+
+
+ symbolCorrDict = {}
+ symbolPvalueDict = {}
+
+ items_number = len(SymbolValueDict)
+
+ if items_number <= 1000:
+ symbolCorrDict, symbolPvalueDict = cal_tissue_corr(primaryTraitValue, SymbolValueDict, method)
+ else:
+ items_list = SymbolValueDict.items()
+
+ step = 1000
+ job_number = math.ceil( float(items_number)/step )
+
+ job_oneSymbolValueDict_list = []
+
+ for job_index in range( int(job_number) ):
+ starti = job_index*step
+ endi = min((job_index+1)*step, items_number)
+
+ oneSymbolValueDict = {}
+
+ for i in range( starti, endi ):
+ one_item = items_list[i]
+ one_symbol = one_item[0]
+ one_value = one_item[1]
+ oneSymbolValueDict[one_symbol] = one_value
+
+ job_oneSymbolValueDict_list.append( oneSymbolValueDict )
+
+
+ ppservers = ()
+ # Creates jobserver with automatically detected number of workers
+ job_server = pp.Server(ppservers=ppservers)
+
+ jobs = []
+ results = []
+
+ for i, oneSymbolValueDict in enumerate( job_oneSymbolValueDict_list ):
+
+ #pay attention to modules from outside
+ jobs.append( job_server.submit(func=cal_tissue_corr, args=(primaryTraitValue, oneSymbolValueDict, method), depfuncs=(), modules=("rpy2.robjects",)) )
+
+ for one_job in jobs:
+ one_result = one_job()
+ results.append( one_result )
+
+ for one_result in results:
+ oneSymbolCorrDict, oneSymbolPvalueDict = one_result
+ symbolCorrDict.update( oneSymbolCorrDict )
+ symbolPvalueDict.update( oneSymbolPvalueDict )
+
+ return (symbolCorrDict, symbolPvalueDict)
+
+###########################################################################
+#Input: cursor, GeneNameLst (list), TissueProbeSetFreezeId
+#output: geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict (Dict)
+#function: get multi dicts for short and long label functions, and for getSymbolValuePairDict and
+# getGeneSymbolTissueValueDict to build dict to get CorrPvArray
+#Note: If there are multiple probesets for one gene, select the one with highest mean.
+###########################################################################
+def getTissueProbeSetXRefInfo(cursor=None,GeneNameLst=[],TissueProbeSetFreezeId=0):
+ Symbols =""
+ symbolList =[]
+ geneIdDict ={}
+ dataIdDict = {}
+ ChrDict = {}
+ MbDict = {}
+ descDict = {}
+ pTargetDescDict = {}
+
+ count = len(GeneNameLst)
+
+ # Added by NL 01/06/2011
+ # Note that:inner join is necessary in this query to get distinct record in one symbol group with highest mean value
+ # Duo to the limit size of TissueProbeSetFreezeId table in DB, performance of inner join is acceptable.
+ if count==0:
+ query='''
+ select t.Symbol,t.GeneId, t.DataId,t.Chr, t.Mb,t.description,t.Probe_Target_Description
+ from (
+ select Symbol, max(Mean) as maxmean
+ from TissueProbeSetXRef
+ where TissueProbeSetFreezeId=%s and Symbol!='' and Symbol Is Not Null group by Symbol)
+ as x inner join TissueProbeSetXRef as t on t.Symbol = x.Symbol and t.Mean = x.maxmean;
+ '''%TissueProbeSetFreezeId
+
+ else:
+ for i, item in enumerate(GeneNameLst):
+
+ if i == count-1:
+ Symbols += "'%s'" %item
+ else:
+ Symbols += "'%s'," %item
+
+ Symbols = "("+ Symbols+")"
+ query='''
+ select t.Symbol,t.GeneId, t.DataId,t.Chr, t.Mb,t.description,t.Probe_Target_Description
+ from (
+ select Symbol, max(Mean) as maxmean
+ from TissueProbeSetXRef
+ where TissueProbeSetFreezeId=%s and Symbol in %s group by Symbol)
+ as x inner join TissueProbeSetXRef as t on t.Symbol = x.Symbol and t.Mean = x.maxmean;
+ '''% (TissueProbeSetFreezeId,Symbols)
+
+ try:
+
+ cursor.execute(query)
+ results =cursor.fetchall()
+ resultCount = len(results)
+ # Key in all dicts is the lower-cased symbol
+ for i, item in enumerate(results):
+ symbol = item[0]
+ symbolList.append(symbol)
+
+ key =symbol.lower()
+ geneIdDict[key]=item[1]
+ dataIdDict[key]=item[2]
+ ChrDict[key]=item[3]
+ MbDict[key]=item[4]
+ descDict[key]=item[5]
+ pTargetDescDict[key]=item[6]
+
+ except:
+ symbolList = None
+ geneIdDict=None
+ dataIdDict=None
+ ChrDict=None
+ MbDict=None
+ descDict=None
+ pTargetDescDict=None
+
+ return symbolList,geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict
+
+###########################################################################
+#Input: cursor, symbolList (list), dataIdDict(Dict)
+#output: symbolValuepairDict (dictionary):one dictionary of Symbol and Value Pair,
+# key is symbol, value is one list of expression values of one probeSet;
+#function: get one dictionary whose key is gene symbol and value is tissue expression data (list type).
+#Attention! All keys are lower case!
+###########################################################################
+def getSymbolValuePairDict(cursor=None,symbolList=None,dataIdDict={}):
+ symbolList = map(string.lower, symbolList)
+ symbolValuepairDict={}
+ valueList=[]
+
+ for key in symbolList:
+ if dataIdDict.has_key(key):
+ DataId = dataIdDict[key]
+
+ valueQuery = "select value from TissueProbeSetData where Id=%s" % DataId
+ try :
+ cursor.execute(valueQuery)
+ valueResults = cursor.fetchall()
+ for item in valueResults:
+ item =item[0]
+ valueList.append(item)
+ symbolValuepairDict[key] = valueList
+ valueList=[]
+ except:
+ symbolValuepairDict[key] = None
+
+ return symbolValuepairDict
+
+
+########################################################################################################
+#input: cursor, symbolList (list), dataIdDict(Dict): key is symbol
+#output: SymbolValuePairDict(dictionary):one dictionary of Symbol and Value Pair.
+# key is symbol, value is one list of expression values of one probeSet.
+#function: wrapper function for getSymbolValuePairDict function
+# build gene symbol list if necessary, cut it into small lists if necessary,
+# then call getSymbolValuePairDict function and merge the results.
+########################################################################################################
+
+def getGeneSymbolTissueValueDict(cursor=None,symbolList=None,dataIdDict={}):
+ limitNum=1000
+ count = len(symbolList)
+
+ SymbolValuePairDict = {}
+
+ if count !=0 and count <=limitNum:
+ SymbolValuePairDict = getSymbolValuePairDict(cursor=cursor,symbolList=symbolList,dataIdDict=dataIdDict)
+
+ elif count >limitNum:
+ SymbolValuePairDict={}
+ n = count/limitNum
+ start =0
+ stop =0
+
+ for i in range(n):
+ stop =limitNum*(i+1)
+ gList1 = symbolList[start:stop]
+ PairDict1 = getSymbolValuePairDict(cursor=cursor,symbolList=gList1,dataIdDict=dataIdDict)
+ start =limitNum*(i+1)
+
+ SymbolValuePairDict.update(PairDict1)
+
+ if stop < count:
+ stop = count
+ gList2 = symbolList[start:stop]
+ PairDict2 = getSymbolValuePairDict(cursor=cursor,symbolList=gList2,dataIdDict=dataIdDict)
+ SymbolValuePairDict.update(PairDict2)
+
+ return SymbolValuePairDict
+
+########################################################################################################
+#input: cursor, GeneNameLst (list), TissueProbeSetFreezeId(int)
+#output: SymbolValuePairDict(dictionary):one dictionary of Symbol and Value Pair.
+# key is symbol, value is one list of expression values of one probeSet.
+#function: wrapper function of getGeneSymbolTissueValueDict function
+# for CorrelationPage.py
+########################################################################################################
+
+def getGeneSymbolTissueValueDictForTrait(cursor=None,GeneNameLst=[],TissueProbeSetFreezeId=0):
+ SymbolValuePairDict={}
+ symbolList,geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict = getTissueProbeSetXRefInfo(cursor=cursor,GeneNameLst=GeneNameLst,TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ if symbolList:
+ SymbolValuePairDict = getGeneSymbolTissueValueDict(cursor=cursor,symbolList=symbolList,dataIdDict=dataIdDict)
+ return SymbolValuePairDict
+
+########################################################################################################
+#Input: cursor(cursor): MySQL connnection cursor;
+# priGeneSymbolList(list): one list of gene symbol;
+# symbolValuepairDict(dictionary): one dictionary of Symbol and Value Pair,
+# key is symbol, value is one list of expression values of one probeSet;
+#Output: corrArray(array): array of Correlation Value,
+# pvArray(array): array of PValue;
+#Function: build corrArray, pvArray for display by calling calculation function:calZeroOrderCorrForTiss
+########################################################################################################
+
+def getCorrPvArray(cursor=None,priGeneSymbolList=[],symbolValuepairDict={}):
+ # setting initial value for corrArray, pvArray equal to 0
+ Num = len(priGeneSymbolList)
+
+ corrArray = [([0] * (Num))[:] for i in range(Num)]
+ pvArray = [([0] * (Num))[:] for i in range(Num)]
+ i = 0
+ for pkey in priGeneSymbolList:
+ j = 0
+ pkey = pkey.strip().lower()# key in symbolValuepairDict is low case
+ if symbolValuepairDict.has_key(pkey):
+ priValue = symbolValuepairDict[pkey]
+ for tkey in priGeneSymbolList:
+ tkey = tkey.strip().lower()# key in symbolValuepairDict is low case
+ if priValue and symbolValuepairDict.has_key(tkey):
+ tarValue = symbolValuepairDict[tkey]
+
+ if tarValue:
+ if i>j:
+ # corrArray stores Pearson Correlation values
+ # pvArray stores Pearson P-Values
+ pcorr_result =calZeroOrderCorrForTiss(primaryValue=priValue,targetValue=tarValue)
+ corrArray[i][j] =pcorr_result[0]
+ pvArray[i][j] =pcorr_result[2]
+ elif i<j:
+ # corrArray stores Spearman Correlation values
+ # pvArray stores Spearman P-Values
+ scorr_result =calZeroOrderCorrForTiss(primaryValue=priValue,targetValue=tarValue,method='spearman')
+ corrArray[i][j] =scorr_result[0]
+ pvArray[i][j] =scorr_result[2]
+ else:
+ # on the diagonal line, correlation value is 1, P-Values is 0
+ corrArray[i][j] =1
+ pvArray[i][j] =0
+ j+=1
+ else:
+ corrArray[i][j] = None
+ pvArray[i][j] = None
+ j+=1
+ else:
+ corrArray[i][j] = None
+ pvArray[i][j] = None
+ j+=1
+ else:
+ corrArray[i][j] = None
+ pvArray[i][j] = None
+
+ i+=1
+
+ return corrArray, pvArray
+
+########################################################################################################
+#Input: cursor(cursor): MySQL connnection cursor;
+# primaryTraitSymbol(string): one gene symbol;
+# TissueProbeSetFreezeId (int): Id of related TissueProbeSetFreeze
+# method: '0' default value, Pearson Correlation; '1', Spearman Correlation
+#Output: symbolCorrDict(Dict): Dict of Correlation Value, key is symbol
+# symbolPvalueDict(Dict): Dict of PValue,key is symbol ;
+#Function: build symbolCorrDict, symbolPvalueDict for display by calling calculation function:calZeroOrderCorrForTiss
+########################################################################################################
+def calculateCorrOfAllTissueTrait(cursor=None, primaryTraitSymbol=None, TissueProbeSetFreezeId=None,method='0'):
+
+ symbolCorrDict = {}
+ symbolPvalueDict = {}
+
+ primaryTraitSymbolValueDict = getGeneSymbolTissueValueDictForTrait(cursor=cursor, GeneNameLst=[primaryTraitSymbol], TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ primaryTraitValue = primaryTraitSymbolValueDict.values()[0]
+
+ SymbolValueDict = getGeneSymbolTissueValueDictForTrait(cursor=cursor, GeneNameLst=[], TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+
+ if method =='1':
+ symbolCorrDict, symbolPvalueDict = batchCalTissueCorr(primaryTraitValue,SymbolValueDict,method='spearman')
+ else:
+ symbolCorrDict, symbolPvalueDict = batchCalTissueCorr(primaryTraitValue,SymbolValueDict)
+
+
+ return (symbolCorrDict, symbolPvalueDict)
diff --git a/web/webqtl/correlationMatrix/CorrelationMatrixPage.py b/web/webqtl/correlationMatrix/CorrelationMatrixPage.py
new file mode 100755
index 00000000..a01111f5
--- /dev/null
+++ b/web/webqtl/correlationMatrix/CorrelationMatrixPage.py
@@ -0,0 +1,595 @@
+# 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 2011/02/14
+
+import os
+import string
+from htmlgen import HTMLgen2 as HT
+import sys
+import time
+import numarray
+import numarray.linear_algebra as la
+import piddle as pid
+import math
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from base.webqtlTrait import webqtlTrait
+from utility import webqtlUtil
+from utility import Plot
+
+
+
+# XZ, 09/09/2008: After adding several traits to collection, click "Correlation Matrix" button,
+# XZ, 09/09/2008: This class will generate what you see.
+#########################################
+# Correlation Matrix Page
+#########################################
+
+class CorrelationMatrixPage(templatePage):
+
+ def __init__(self,fd,InputData=None):
+
+ templatePage.__init__(self, fd)
+
+ self.dict['title'] = 'Correlation Matrix'
+
+ if not self.openMysql():
+ return
+
+ if not fd.genotype:
+ fd.readGenotype()
+ fd.strainlist = fd.f1list + fd.strainlist
+
+ #self.searchResult = fd.formdata.getvalue('searchResult')
+ self.oldSearchResult = fd.formdata.getvalue('oldSearchResult')
+
+ if self.oldSearchResult:
+ try:
+ self.searchResult = fd.formdata.getvalue('oldSearchResult')
+ except:
+ self.searchResult = fd.formdata.getvalue('searchResult')
+
+ else:
+ self.searchResult = fd.formdata.getvalue('searchResult')
+
+ if not self.searchResult:
+ heading = 'Correlation Matrix'
+ detail = ['You need to select at least two traits in order to generate correlation matrix.']
+ self.error(heading=heading,detail=detail)
+ return
+ if type("1") == type(self.searchResult):
+ self.searchResult = [self.searchResult]
+
+ if self.searchResult:
+ #testvals,names,dbInfos = self.getAllSearchResult(fd,self.searchResult)
+ if len(self.searchResult) > webqtlConfig.MAXCORR:
+ heading = 'Correlation Matrix'
+ detail = ['In order to display Correlation Matrix properly, Do not select more than %d traits for Correlation Matrix.' % webqtlConfig.MAXCORR]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ, 7/22/2009: this block is not necessary
+ #elif len(self.searchResult) > 40:
+ # noPCA = 1
+ #else:
+ # noPCA = 0
+
+ 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 = 'Correlation Matrix'
+ detail = [HT.Font('Error : ',color='red'),HT.Font('Error occurs while retrieving data FROM database.',color='black')]
+ self.error(heading=heading,detail=detail)
+ return
+
+ NNN = len(traitList)
+
+ if NNN == 0:
+ heading = "Correlation Matrix"
+ detail = ['No trait was selected for %s data set. No matrix generated.' % self.data.RISet]
+ self.error(heading=heading,detail=detail)
+ return
+ elif NNN < 2:
+ heading = 'Correlation Matrix'
+ detail = ['You need to select at least two traits in order to generate correlation matrix.']
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+
+
+
+ corArray = [([0] * (NNN+1))[:] for i in range(NNN+1)]
+ pearsonArray = [([0] * (NNN))[:] for i in range(NNN)]
+ spearmanArray = [([0] * (NNN))[:] for i in range(NNN)]
+ corArray[0][0] = 'Correlation'
+ TD_LR = HT.TD(colspan=2,width="100%",bgColor='#eeeeee')
+ form = HT.Form( cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase', 'ProbeSetID':'_','database':'_',
+ 'CellID':'_','ProbeSetID2':'_','database2':'_','CellID2':'_',
+ 'newNames':fd.formdata.getvalue("newNames", "_"),
+ 'RISet':fd.RISet,'ShowStrains':'ON','ShowLine':'ON', 'rankOrder':'_',
+ "allstrainlist":string.join(fd.strainlist, " "), 'traitList':string.join(self.searchResult, "\t")}
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ for item in self.searchResult:
+ form.append(HT.Input(name='oldSearchResult', value=str(item), type='hidden'))
+
+ traiturls = []
+ traiturls2 = []
+ shortNames = []
+ verboseNames = []
+ verboseNames2 = []
+ verboseNames3 = []
+ abbreviation = ''
+
+ #dbInfo.ProbeSetID = ProbeSetID
+ #dbInfo.CellID = CellID
+ for i, thisTrait in enumerate(traitList):
+ _url = "javascript:showDatabase2('%s','%s','%s');" % (thisTrait.db.name, thisTrait.name, thisTrait.cellid)
+ #_text = 'Trait%d: ' % (i+1)+str(thisTrait)
+ _text = 'Trait %d: ' % (i+1)+thisTrait.displayName()
+
+ if thisTrait.db.type == 'Geno':
+ _shortName = 'Genotype'
+ abbreviation = 'Genotype'
+ _verboseName = 'Locus %s' % (thisTrait.name)
+ _verboseName2 = 'Chr %s @ %s Mb' % (thisTrait.chr, '%2.3f' % thisTrait.mb)
+ _verboseName3 = ''
+ elif thisTrait.db.type == 'Publish':
+ if thisTrait.post_publication_abbreviation:
+ AbbreviationString = thisTrait.post_publication_abbreviation
+ else:
+ AbbreviationString = ''
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ if thisTrait.pre_publication_abbreviation:
+ AbbreviationString = thisTrait.pre_publication_abbreviation
+ else:
+ AbbreviationString = ''
+ _shortName = 'Phenotype: %s' % (AbbreviationString)
+ _verboseName2 = ''
+ _verboseName3 = ''
+ if thisTrait.pubmed_id:
+ _verboseName = 'PubMed %d: ' % thisTrait.pubmed_id
+ else:
+ _verboseName = 'Unpublished '
+ _verboseName += 'RecordID/%s' % (thisTrait.name)
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ PhenotypeString = thisTrait.pre_publication_description
+ _verboseName2 = 'Phenotype: %s' % (PhenotypeString)
+ if thisTrait.authors:
+ a1 = string.split(thisTrait.authors,',')[0]
+ while a1[0] == '"' or a1[0] == "'" :
+ a1 = a1[1:]
+ _verboseName += ' by '
+ _verboseName += HT.Italic('%s, and colleagues' % (a1))
+ elif thisTrait.db.type == 'Temp':
+ abbreviation = ''
+ _shortName = thisTrait.name
+ if thisTrait.description:
+ _verboseName = thisTrait.description
+ else:
+ _verboseName = 'Temp'
+ _verboseName2 = ''
+ _verboseName3 = ''
+ else:
+ abbreviation = thisTrait.symbol
+ _shortName = 'Symbol: %s ' % thisTrait.symbol
+ _verboseName = thisTrait.symbol
+ _verboseName2 = ''
+ _verboseName3 = ''
+ if thisTrait.chr and thisTrait.mb:
+ _verboseName += ' on Chr %s @ %s Mb' % (thisTrait.chr,thisTrait.mb)
+ if thisTrait.description:
+ _verboseName2 = '%s' % (thisTrait.description)
+ if thisTrait.probe_target_description:
+ _verboseName3 = '%s' % (thisTrait.probe_target_description)
+
+ cururl = HT.Href(text=_text, url=_url,Class='fs12')
+ cururl2 = HT.Href(text='Trait%d' % (i+1),url=_url,Class='fs12')
+ traiturls.append(cururl)
+ traiturls2.append(cururl2)
+ shortName = HT.Div(id="shortName_" + str(i), style="display:none")
+ shortName.append(_shortName)
+ shortNames.append(shortName)
+ verboseName = HT.Div(id="verboseName_" + str(i), style="display:none")
+ verboseName.append(_verboseName)
+ verboseNames.append(verboseName)
+ verboseName2 = HT.Div(id="verboseName2_" + str(i), style="display:none")
+ verboseName2.append(_verboseName2)
+ verboseNames2.append(verboseName2)
+ verboseName3 = HT.Div(id="verboseName3_" + str(i), style="display:none")
+ verboseName3.append(_verboseName3)
+ verboseNames3.append(verboseName3)
+
+
+
+ corArray[i+1][0] = 'Trait%d: ' % (i+1)+str(thisTrait) + '/' + str(thisTrait) + ': ' + abbreviation + '/' + str(thisTrait) + ': ' + str(_verboseName) + ' : ' + str(_verboseName2) + ' : ' + str(_verboseName3)
+ corArray[0][i+1] = 'Trait%d: ' % (i+1)+str(thisTrait)
+
+ corMatrixHeading = HT.Paragraph('Correlation Matrix', Class="title")
+
+ tbl = HT.TableLite(Class="collap", border=0, cellspacing=1,
+ cellpadding=5, width='100%')
+ row1 = HT.TR(HT.TD(Class="fs14 fwb ffl b1 cw cbrb"),
+ HT.TD('Spearman Rank Correlation (rho)', Class="fs14 fwb ffl b1 cw cbrb", colspan= NNN+1,align="center")
+ )
+ row2 = HT.TR(
+ HT.TD("P e a r s o n &nbsp;&nbsp;&nbsp; r", rowspan= NNN+1,Class="fs14 fwb ffl b1 cw cbrb", width=10,align="center"),
+ HT.TD(Class="b1", width=300))
+ for i in range(NNN):
+ row2.append(HT.TD(traiturls2[i], Class="b1", align="center"))
+ tbl.append(row1,row2)
+
+ nOverlapTrait =9999
+ nnCorr = len(fd.strainlist)
+ for i, thisTrait in enumerate(traitList):
+ newrow = HT.TR()
+ newrow.append(HT.TD(traiturls[i], shortNames[i], verboseNames[i], verboseNames2[i],
+ verboseNames3[i], Class="b1"))
+ 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)
+
+ rank = fd.formdata.getvalue("rankOrder", "0")
+
+ if nOverlap < nOverlapTrait:
+ nOverlapTrait = nOverlap
+ if corr > 0.7:
+ fontcolor="red"
+ elif corr > 0.5:
+ fontcolor="#FF6600"
+ elif corr < -0.7:
+ fontcolor="blue"
+ elif corr < -0.5:
+ fontcolor="#009900"
+ else:
+ fontcolor ="#000000"
+
+ pearsonArray[i][j] = corr
+ pearsonArray[j][i] = corr
+ if corr!= 0.0:
+ corArray[i+1][j+1] = '%2.3f/%d' % (corr,nOverlap)
+ thisurl = HT.Href(text=HT.Font('%2.3f'% corr,HT.BR(),'%d' % nOverlap ,color=fontcolor, Class="fs11 fwn"),url = "javascript:showCorrelationPlot2(db='%s',ProbeSetID='%s',CellID='%s',db2='%s',ProbeSetID2='%s',CellID2='%s',rank='%s')" % (names1[0], names1[1], names1[2], names2[0], names2[1], names2[2], rank))
+ else:
+ corArray[i+1][j+1] = '---/%d' % nOverlap
+ thisurl = HT.Font('---',HT.BR(), '%d' % nOverlap)
+
+ newrow.append(HT.TD(thisurl,Class="b1",NOWRAP="ON",align="middle"))
+ elif j == i:
+ corr,nOverlap = webqtlUtil.calCorrelation(traitDataList[i],traitDataList[j],nnCorr)
+ pearsonArray[i][j] = 1.0
+ spearmanArray[i][j] = 1.0
+ corArray[i+1][j+1] = '%2.3f/%d' % (corr,nOverlap)
+ nOverlap = webqtlUtil.calCorrelation(traitDataList[i],traitDataList[j],nnCorr)[1]
+ newrow.append(HT.TD(HT.Href(text=HT.Font(HT.Italic("n"),HT.BR(),str(nOverlap),Class="fs11 fwn b1",align="center", color="000000"), url="javascript:showDatabase2('%s','%s','%s')" % (thisTrait.db.name, thisTrait.name, thisTrait.cellid)), bgColor='#cccccc', align="center", Class="b1", NOWRAP="ON"))
+ else:
+ corr,nOverlap = webqtlUtil.calCorrelationRank(traitDataList[i],traitDataList[j],nnCorr)
+
+ rank = fd.formdata.getvalue("rankOrder", "1")
+
+ if corr > 0.7:
+ fontcolor="red"
+ elif corr > 0.5:
+ fontcolor="#FF6600"
+ elif corr < -0.7:
+ fontcolor="blue"
+ elif corr < -0.5:
+ fontcolor="#009900"
+ else:
+ fontcolor ="#000000"
+ spearmanArray[i][j] = corr
+ spearmanArray[j][i] = corr
+ if corr!= 0.0:
+ corArray[i+1][j+1] = '%2.3f/%d' % (corr,nOverlap)
+ thisurl = HT.Href(text=HT.Font('%2.3f'% corr,HT.BR(),'%d' % nOverlap ,color=fontcolor, Class="fs11 fwn"),url = "javascript:showCorrelationPlot2(db='%s',ProbeSetID='%s',CellID='%s',db2='%s',ProbeSetID2='%s',CellID2='%s',rank='%s')" % (names1[0], names1[1], names1[2], names2[0], names2[1], names2[2], rank))
+ else:
+ corArray[i+1][j+1] = '---/%d' % nOverlap
+ thisurl = HT.Span('---',HT.BR(), '%d' % nOverlap, Class="fs11 fwn")
+ newrow.append(HT.TD(thisurl,Class="b1", NOWRAP="ON",align="middle"))
+ tbl.append(newrow)
+
+ info = HT.Blockquote('Lower left cells list Pearson product-moment correlations; upper right cells list Spearman rank order correlations. Each cell also contains the n of cases. Values higher than 0.7 are displayed in ',HT.Font('red', color='red'),'; those between 0.5 and 0.7 in ',HT.Font('orange', color='#FF6600'),'; Values lower than -0.7 are in ',HT.Font('blue', color='blue'),'; between -0.5 and -0.7 in ',HT.Font('green', color='#009900'),'. Select any cell to generate a scatter plot. Select trait labels for more information.', Class="fs13 fwn")
+
+ exportbutton = HT.Input(type='button', name='export', value='Export', onClick="exportText(allCorrelations);",Class="button")
+ shortButton = HT.Input(type='button' ,name='dispShort',value=' Short Labels ', onClick="displayShortName();",Class="button")
+ verboseButton = HT.Input(type='button' ,name='dispVerbose',value=' Long Labels ', onClick="displayVerboseName();", Class="button")
+ form.append(HT.Blockquote(tbl,HT.P(),shortButton,verboseButton,exportbutton))
+ TD_LR.append(corMatrixHeading,info,form,HT.P())
+
+ #if noPCA:
+ # TD_LR.append(HT.Blockquote('No PCA is computed if more than 32 traits are selected.'))
+
+ #print corArray
+ exportScript = """
+ <SCRIPT language=JavaScript>
+ var allCorrelations = %s;
+ </SCRIPT>
+
+ """
+ exportScript = exportScript % str(corArray)
+ self.dict['js1'] = exportScript+'<SCRIPT SRC="/javascript/correlationMatrix.js"></SCRIPT><BR>'
+ self.dict['body'] = str(TD_LR)
+
+ #don't calculate PCA while number exceed 32
+ #if noPCA:
+ # return
+
+ #XZ, 7/22/2009: deal with PCA stuff
+ #Only for Array Data
+
+ if NNN > 2:
+
+ traitname = map(lambda X:str(X.name), traitList)
+
+ #generate eigenvalues
+
+ # import sys
+ sys.argv=[" "]
+ # import numarray
+ # import numarray.linear_algebra as la
+ #spearmanEigen = eigenvectors(array(spearmanArray))
+ pearsonEigen = la.eigenvectors(numarray.array(pearsonArray))
+ #spearmanEigenValue,spearmanEigenVectors = self.sortEigenVectors(spearmanEigen)
+ pearsonEigenValue,pearsonEigenVectors = self.sortEigenVectors(pearsonEigen)
+
+
+ """
+ for i in range(len(pearsonEigenValue)):
+ if type(pearsonEigenValue[i]).__name__ == 'complex':
+ pearsonEigenValue[i] = pearsonEigenValue[i].real
+ for i in range(len(pearsonEigenVectors)):
+ for j in range(len(pearsonEigenVectors[i])):
+ if type(pearsonEigenVectors[i][j]).__name__ == 'complex':
+ pearsonEigenVectors[i][j] = pearsonEigenVectors[i][j].real
+ if type(pearsonEigenVectors[i][j]).__name__ == 'complex':
+ pearsonEigenVectors[i][j] = pearsonEigenVectors[i][j].real
+ """
+
+ if type(pearsonEigenValue[0]).__name__ == 'complex':
+ pass
+ else:
+ traitHeading = HT.Paragraph('PCA Traits',align='left', Class="title")
+
+ tbl2 = self.calcPCATraits(traitDataList=traitDataList, nnCorr=nnCorr, NNN=NNN, pearsonEigenValue=pearsonEigenValue,
+ pearsonEigenVectors=pearsonEigenVectors, form=form, fd=fd)
+ #Buttons on search page
+ #mintmap = HT.Input(type='button' ,name='mintmap',value='Multiple Mapping', onClick="databaseFunc(this.form,'showIntMap');",Class="button")
+ addselect = HT.Input(type='button' ,name='addselect',value='Add to Collection', onClick="addRmvSelection('%s', this.form, 'addToSelection');" % fd.RISet,Class="button")
+ selectall = HT.Input(type='button' ,name='selectall',value='Select All', onClick="checkAll(this.form);",Class="button")
+ reset = HT.Input(type='reset',name='',value='Select None',Class="button")
+ updateNames = HT.Input(type='button', name='updateNames',value='Update Trait Names', onClick="editPCAName(this.form);", Class="button")
+ chrMenu = HT.Input(type='hidden',name='chromosomes',value='all')
+
+ """
+ #need to be refined
+ if fd.genotype.Mbmap:
+ scaleMenu = HT.Select(name='scale')
+ scaleMenu.append(tuple(["Genetic Map",'morgan']))
+ scaleMenu.append(tuple(["Physical Map",'physic']))
+ else:
+ scaleMenu = ""
+ """
+
+ tbl2.append(HT.TR(HT.TD(HT.P(),chrMenu,updateNames,selectall,reset,addselect,colspan=3)))
+ form.append(HT.P(),traitHeading,HT.Blockquote(tbl2))
+
+ plotHeading1 = HT.Paragraph('Scree Plot', Class="title")
+ TD_LR.append(plotHeading1)
+ img1 = self.screePlot(NNN=NNN, pearsonEigenValue=pearsonEigenValue)
+
+ TD_LR.append(HT.Blockquote(img1))
+
+ plotHeading2 = HT.Paragraph('Factor Loadings Plot', Class="title")
+ TD_LR.append(plotHeading2)
+ img2 = self.factorLoadingsPlot(pearsonEigenVectors=pearsonEigenVectors, traitList=traitList)
+
+ TD_LR.append(HT.Blockquote(img2))
+
+ self.dict['body'] = str(TD_LR)
+
+ def screePlot(self, NNN=0, pearsonEigenValue=None):
+
+ c1 = pid.PILCanvas(size=(700,500))
+ Plot.plotXY(canvas=c1, dataX=range(1,NNN+1), dataY=pearsonEigenValue, rank=0, labelColor=pid.blue,plotColor=pid.red, symbolColor=pid.blue, XLabel='Factor Number', connectdot=1,YLabel='Percent of Total Variance %', title='Pearson\'s R Scree Plot')
+ filename= webqtlUtil.genRandStr("Scree_")
+ c1.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img=HT.Image('/image/'+filename+'.gif',border=0)
+
+ return img
+
+ def factorLoadingsPlot(self, pearsonEigenVectors=None, traitList=None):
+
+ traitname = map(lambda X:str(X.name), traitList)
+ c2 = pid.PILCanvas(size=(700,500))
+ Plot.plotXY(c2, pearsonEigenVectors[0],pearsonEigenVectors[1], 0, dataLabel = traitname, labelColor=pid.blue, plotColor=pid.red, symbolColor=pid.blue,XLabel='Factor (1)', connectdot=1, YLabel='Factor (2)', title='Factor Loadings Plot (Pearson)', loadingPlot=1)
+ filename= webqtlUtil.genRandStr("FacL_")
+ c2.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img = HT.Image('/image/'+filename+'.gif',border=0)
+
+ return img
+
+ def calcPCATraits(self, traitDataList=None, nnCorr=0, NNN=0, pearsonEigenValue=None, pearsonEigenVectors=None, form=None, fd=None):
+ """
+ This function currently returns the html to be displayed instead of the traits themselves. Need to fix later.
+ """
+
+ detailInfo = string.split(self.searchResult[0],':')
+
+ self.sameProbeSet = 'yes'
+ for item in self.searchResult[1:]:
+ detailInfo2 = string.split(item,':')
+ if detailInfo[0] != detailInfo2[0] or detailInfo[1] != detailInfo2[1]:
+ self.sameProbeSet = None
+ break
+
+ for item in traitDataList:
+ if len(item) != nnCorr:
+ return
+ infoStrains = []
+ infoStrainsPos = []
+ dataArray = [[] for i in range(NNN)]
+
+ for i in range(len(traitDataList[0])):
+ currentStrain = 1
+ for j in range(NNN):
+ if not traitDataList[j][i]:
+ currentStrain = 0
+ break
+ if currentStrain == 1:
+ infoStrains.append(fd.strainlist[i])
+ infoStrainsPos.append(i)
+ for j in range(NNN):
+ dataArray[j].append(traitDataList[j][i])
+
+
+ self.cursor.execute('delete Temp, TempData FROM Temp, TempData WHERE Temp.DataId = TempData.Id and UNIX_TIMESTAMP()-UNIX_TIMESTAMP(CreateTime)>%d;' % webqtlConfig.MAXLIFE)
+
+ StrainIds = []
+ for item in infoStrains:
+ self.cursor.execute('SELECT Strain.Id FROM Strain,StrainXRef, InbredSet WHERE Strain.Name="%s" and Strain.Id = StrainXRef.StrainId and StrainXRef.InbredSetId = InbredSet.Id and InbredSet.Name = "%s"' % (item, fd.RISet))
+ StrainIds.append('%d' % self.cursor.fetchone()[0])
+
+ """
+ #minimal 12 overlapping strains
+ if len(dataArray[0]) < 12:
+ form.append(HT.P(),traitHeading,HT.Blockquote(HT.Paragraph('The number of overlapping strains is less than 12, no PCA scores computed.',align='left')))
+ self.dict['body'] = str(TD_LR)
+ return
+ """
+ dataArray = self.zScore(dataArray)
+ dataArray = numarray.array(dataArray)
+ dataArray2 = numarray.dot(pearsonEigenVectors,dataArray)
+
+ tbl2 = HT.TableLite(cellSpacing=2,cellPadding=0,border=0, width="100%")
+
+ ct0 = time.localtime(time.time())
+ ct = time.strftime("%B/%d %H:%M:%S",ct0)
+ if self.sameProbeSet:
+ newDescription = 'PCA Traits generated at %s from %s' % (ct,detailInfo[1])
+ else:
+ newDescription = 'PCA Traits generated at %s from traits selected' % ct
+
+
+ j = 1
+ self.cursor.execute('SELECT Id FROM InbredSet WHERE Name = "%s"' % fd.RISet)
+ InbredSetId = self.cursor.fetchall()[0][0]
+ user_ip = fd.remote_ip
+ if fd.formdata.getvalue("newNames"):
+ newNames = fd.formdata.getvalue("newNames").split(",")
+ else:
+ newNames = 0
+
+ for item in dataArray2:
+ if pearsonEigenValue[j-1] < 100.0/NNN:
+ break
+
+ if (newNames == 0):
+ description = '%s : PC%02d' % (newDescription, j)
+ else:
+ description = '%s : %s' % (newDescription, newNames[j-1])
+
+ self.cursor.execute('SELECT max(id) FROM TempData')
+ try:
+ DataId = self.cursor.fetchall()[0][0] + 1
+ except:
+ DataId = 1
+ newProbeSetID = webqtlUtil.genRandStr("PCA_Tmp_")
+ self.cursor.execute('insert into Temp(Name,description, createtime,DataId,InbredSetId,IP) values(%s,%s,Now(),%s,%s,%s)' ,(newProbeSetID, description, DataId,InbredSetId,user_ip))
+
+ k = 0
+ for StrainId in StrainIds:
+ self.cursor.execute('insert into TempData(Id, StrainId, value) values(%s,%s,%s)' % (DataId, StrainId, item[k]*(-1.0)))
+ k += 1
+ setDescription = HT.Div(id="pcaTrait%s" % j)
+ descriptionLink = HT.Href(text=description, url="javascript:showDatabase2('Temp','%s','')" % newProbeSetID, Class="fwn")
+ descriptionEdit = HT.Input(type='text', value='', name='editName%s' % j)
+
+ #onBlur='editPDAName(this.form, %s);' % j
+
+ setDescription.append(descriptionLink)
+ setDescription.append(descriptionEdit)
+
+ traitName = "%s:%s" % ('Temp',newProbeSetID)
+ tbl2.append(HT.TR(HT.TD("%d."%j,align="right",valign="top"),HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=traitName),valign="top",width=50),HT.TD(setDescription)))
+ j += 1
+
+ return tbl2
+
+ def zScore(self,dataArray):
+ NN = len(dataArray[0])
+ if NN < 10:
+ return dataArray
+ else:
+ i = 0
+ for data in dataArray:
+ N = len(data)
+ S = reduce(lambda x,y: x+y, data, 0.)
+ SS = reduce(lambda x,y: x+y*y, data, 0.)
+ mean = S/N
+ var = SS - S*S/N
+ stdev = math.sqrt(var/(N-1))
+ data2 = map(lambda x:(x-mean)/stdev,data)
+ dataArray[i] = data2
+ i += 1
+ return dataArray
+
+ def sortEigenVectors(self,vector):
+ try:
+ eigenValues = vector[0].tolist()
+ eigenVectors = vector[1].tolist()
+ combines = []
+ i = 0
+ for item in eigenValues:
+ combines.append([eigenValues[i],eigenVectors[i]])
+ i += 1
+ combines.sort(webqtlUtil.cmpEigenValue)
+ A = []
+ B = []
+ for item in combines:
+ A.append(item[0])
+ B.append(item[1])
+ sum = reduce(lambda x,y: x+y, A, 0.0)
+ A = map(lambda x:x*100.0/sum, A)
+ return [A,B]
+ except:
+ return []
+
diff --git a/web/webqtl/correlationMatrix/TissueAbbreviationPage.py b/web/webqtl/correlationMatrix/TissueAbbreviationPage.py
new file mode 100755
index 00000000..ad8f0ac7
--- /dev/null
+++ b/web/webqtl/correlationMatrix/TissueAbbreviationPage.py
@@ -0,0 +1,79 @@
+# 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 2011/12/7
+#
+# Last updated by GeneNetwork Core Team 2011/12/7
+
+
+from base.templatePage import templatePage
+from htmlgen import HTMLgen2 as HT
+
+import string
+import os
+
+
+class TissueAbbreviationPage (templatePage):
+
+ def __init__(self,fd):
+ templatePage.__init__(self, fd)
+
+ shortName=fd.formdata.getfirst("shortTissueName", ',')
+ fullName=fd.formdata.getfirst("fullTissueName", ',')
+ shortNameList=[]
+ fullNameList=[]
+
+ if shortName:
+ shortNameList=shortName.split(',')
+
+ if fullName:
+ fullNameList=fullName.split(',')
+
+ tissueAbbrDict={}
+ for i, item in enumerate(shortNameList):
+ tissueAbbrDict[item]=fullNameList[i]
+
+ if tissueAbbrDict:
+
+ # Creates the table for the fullname and shortname of Tissue
+ tissueAbbrTable = HT.TableLite(border=1, cellspacing=5, cellpadding=3, Class="collap")
+ shortNameList = tissueAbbrDict.keys()
+ shortNameList.sort()
+ abbrHeaderStyle="fs14 fwb ffl"
+ abbrStyle="fs14 fwn ffl"
+
+ tissueAbbrTable.append(HT.TR(HT.TD('Abbr&nbsp;&nbsp;', Class=abbrHeaderStyle, NOWRAP = 1),HT.TD('Full Name&nbsp;&nbsp;', Class=abbrHeaderStyle, NOWRAP = 1)))
+ for item in shortNameList:
+ thisTR = HT.TR(HT.TD(item, Class=abbrStyle, NOWRAP = 1))
+ thisTR.append(HT.TD(tissueAbbrDict[item], Class=abbrStyle, NOWRAP = 1))
+
+ tissueAbbrTable.append(thisTR)
+
+ self.dict['body'] = HT.TD(HT.Paragraph("Tissue Abbreviation", Class="title"), HT.Blockquote(tissueAbbrTable))
+ self.dict['title'] = "Tissue Abbreviation"
+ else:
+ heading = "Tissue abbreviation"
+ detail = ["Cannot found Tissue Abbreviation. Please try again later."]
+ self.error(heading=heading,detail=detail)
+ return
+
+
diff --git a/web/webqtl/correlationMatrix/TissueCorrelationPage.py b/web/webqtl/correlationMatrix/TissueCorrelationPage.py
new file mode 100755
index 00000000..7cb86d8c
--- /dev/null
+++ b/web/webqtl/correlationMatrix/TissueCorrelationPage.py
@@ -0,0 +1,673 @@
+# 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)
+# user can search correlation value and P-Value by inputting one pair gene symbols or multiple gene symbols.
+
+# Created by GeneNetwork Core Team 2010/07/07
+# Last updated by NL, 2011/03/25
+
+from htmlgen import HTMLgen2 as HT
+import os
+import sys
+import time
+import string
+import pyXLWriter as xl
+import cPickle
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from base.webqtlTrait import webqtlTrait
+from correlationMatrix.tissueCorrelationMatrix import tissueCorrelationMatrix
+from utility import webqtlUtil
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+
+
+#########################################
+# Tissue Correlation Page
+#########################################
+
+class TissueCorrelationPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ #read input fields
+ self.action = fd.formdata.getvalue("action", "").strip()
+ self.geneSymbols = fd.formdata.getvalue("geneSymbols","").strip()
+ self.tissueProbeSetFeezeId = fd.formdata.getvalue("tissueProbeSetFeezeId", "").strip()
+ self.recordReturnNum = fd.formdata.getvalue("recordReturnNum", "0").strip()
+ self.calculateMethod = fd.formdata.getvalue("calculateMethod", "0").strip()
+
+ TissueCorrMatrixObject = tissueCorrelationMatrix(tissueProbeSetFreezeId=self.tissueProbeSetFeezeId)
+
+ if not self.geneSymbols:
+ # default page
+
+ Heading = HT.Paragraph("Tissue Correlation", Class="title")
+ Intro = HT.Blockquote("This function computes correlations between transcript expression across different organs and tissues.")
+ Intro.append(HT.BR(),"Select a data set from the pull-down menu and then compute correlations.")
+
+ formName='searchTissueCorrelation'
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), target='_blank',enctype='multipart/form-data', name= formName, submit=HT.Input(type='hidden'))
+ form.append(HT.Input(type="hidden", name="FormID", value=""))
+ form.append(HT.Input(type="hidden", name="action", value="disp"))
+
+ # added by NL 10/12/2010, retreive dataSet info from TissueProbeSetFreeze to get all TissueProbeSetFreezeId, datasetName and FullName
+ tissProbeSetFreezeIds,dataSetNames,dataSetfullNames = TissueCorrMatrixObject.getTissueDataSet()
+
+ dataSetList=[]
+ for i in range(len(tissProbeSetFreezeIds)):
+ dataSetList.append((dataSetfullNames[i], tissProbeSetFreezeIds[i]))
+ dataSetMenu = HT.Select(dataSetList,name="tissueProbeSetFeezeId")
+
+ InfoFile =HT.Input(type="button", Class="button", value=" Info ", onClick="tissueDatasetInfo(this.form.tissueProbeSetFeezeId,%s);"%(dataSetNames))
+ form.append(HT.Strong("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"),dataSetMenu,InfoFile,HT.BR());
+
+ form.append(HT.BR(),HT.Strong("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Please enter only one gene symbol/ENTREZ gene Id per line."),HT.BR(),HT.Strong("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"),HT.Textarea(name="geneSymbols", rows=10, cols=50, text=""),HT.BR(),HT.BR())
+ # calculate method radio button
+ calculateMethodMenu =HT.Input(type="radio", name="calculateMethod", value="0", checked="checked")
+ calculateMethodMenu1 =HT.Input(type="radio", name="calculateMethod", value="1")
+ # record Return method dropdown menu
+ recordReturnMenu = HT.Select(name="recordReturnNum")
+ recordReturnMenu.append(('Top 100','0'))
+ recordReturnMenu.append(('Top 200','1'))
+ recordReturnMenu.append(('Top 500','2'))
+ recordReturnMenu.append(('Top 1000','3'))
+ recordReturnMenu.append(('Top 2000','4'))
+ recordReturnMenu.append(('All','5'))
+
+ # working for input symbol has only one;
+ form.append(HT.Strong("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"),HT.Span("Return:", Class="ffl fwb fs12"),HT.Strong("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"),recordReturnMenu,HT.BR());
+ form.append(HT.BR(),HT.Strong("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"),'Pearson',calculateMethodMenu,"&nbsp;"*3,'Spearman Rank',calculateMethodMenu1,HT.BR(),HT.BR());
+ form.append(HT.Strong("&nbsp;&nbsp;&nbsp;"),HT.Input(type="button", value="&nbsp;Compute&nbsp;", Class="button",onClick="selectFormIdForTissueCorr('%s');"%formName))
+ form.append(HT.Strong("&nbsp;&nbsp;&nbsp;&nbsp;"),HT.Input(type="button", Class="button", value="&nbsp;Make Default&nbsp;", onClick = "makeTissueCorrDefault(this.form);"))
+
+ TD_LR = HT.TD(height=200,width="100%",bgcolor='#eeeeee',align="left")
+ TD_LR.append(Heading,Intro,form)
+ self.content_type = 'text/html'
+ self.dict['js1'] = '<SCRIPT SRC="/javascript/correlationMatrix.js"></SCRIPT><BR>'
+ # get tissueProbesetFreezeId from cookie
+ self.dict['js2'] = 'onload ="getTissueCorrDefault(\'searchTissueCorrelation\');"'
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = "Tissue Correlation"
+ elif self.action == 'disp':
+ TissueCount =TissueCorrMatrixObject.getTissueCountofCurrentDataset()
+
+ # add by NL for first Note part in the tissue correlation page. 2010-12-23
+ note =""
+ dataSetName=""
+ datasetFullName=""
+ dataSetName, datasetFullName= TissueCorrMatrixObject.getFullnameofCurrentDataset()
+
+ noteURL = "../dbdoc/"+ dataSetName+".html"
+ noteText = " was used to compute expression correlation across %s samples of tissues and organs.&nbsp["%TissueCount
+ # dataset download
+ datasetURL = "../dbdoc/"+ dataSetName+".xls"
+ datasetDownload =HT.Href(text="Download experiment data",url=datasetURL,Class='fs13',target="_blank")
+ note = HT.Blockquote(HT.Href(text=datasetFullName,url=noteURL,Class='fs13',target="_blank"),noteText, datasetDownload,"]",HT.BR())
+
+ geneSymbolLst = [] # gene Symbol list
+ geneSymbolLst = TissueCorrMatrixObject.getGeneSymbolLst(self.geneSymbols)
+
+ symbolCount = len(geneSymbolLst)
+ # The input symbol limit is 100.
+ heading = "Tissue Correlation"
+ if symbolCount > 100:
+ detail = ['The Gene symbols you have input are more than 100. Please limit them to 100.']
+ self.error(heading=heading,detail=detail)
+ return
+ elif symbolCount==0:
+ detail = ['No Gene Symbol was input. No Tissue Correlation matrix generated.' ]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ # search result page
+ # The input symbols should be no less than 1.
+ self.content_type = 'text/html'
+ if symbolCount == 1:
+ self.displaySingleSymbolResultPage(primaryGeneSymbol=geneSymbolLst[0],datasetFullName=datasetFullName,tProbeSetFreezeId=self.tissueProbeSetFeezeId, TissueCorrMatrixObject =TissueCorrMatrixObject,recordReturnNum=self.recordReturnNum,method=self.calculateMethod, note=note,TissueCount =TissueCount)
+ else:
+ self.displayMultiSymbolsResultPage(geneSymbolLst=geneSymbolLst, symbolCount=symbolCount, tProbeSetFreezeId=self.tissueProbeSetFeezeId,TissueCorrMatrixObject =TissueCorrMatrixObject,note=note,TissueCount =TissueCount)
+
+ else:
+ heading = "Tissue Correlation"
+ detail = ['There\'s something wrong with input gene symbol(s), or the value of parameter [action] is not right.' ]
+ self.error(heading=heading,detail=detail)
+ return
+#############################
+# functions
+#############################
+
+ # result page when input symbol has only one
+ def displaySingleSymbolResultPage(self,primaryGeneSymbol=None, datasetFullName=None,tProbeSetFreezeId=None, TissueCorrMatrixObject =None,recordReturnNum=None,method=None,note=None,TissueCount =None):
+ formName = webqtlUtil.genRandStr("fm_")
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data',name= formName, submit=HT.Input(type='hidden'))
+ # the following hidden elements are required parameter in Class(PlotCorrelationPage). So we need to define them here.
+ form.append(HT.Input(type="hidden", name="action", value="disp"))
+ form.append(HT.Input(type="hidden", name="FormID", value="dispSingleTissueCorrelation"))
+ form.append(HT.Input(type="hidden", name="X_geneSymbol", value=""))
+ form.append(HT.Input(type="hidden", name="Y_geneSymbol", value=""))
+ form.append(HT.Input(type="hidden", name="ProbeSetID", value=""))
+ # RISet is not using in Tissue correlation, but is a required parameter in Class(PlotCorrelationPage). So we set dummy value(BXD).
+ form.append(HT.Input(type="hidden", name="RISet", value="BXD"))
+ form.append(HT.Input(type="hidden", name="ShowLine", value="1"))
+ form.append(HT.Input(type="hidden", name="TissueProbeSetFreezeId", value=tProbeSetFreezeId))
+ form.append(HT.Input(type="hidden", name="rankOrder", value=0))
+
+ traitList =[]
+ try:
+ symbolCorrDict, symbolPvalueDict = TissueCorrMatrixObject.calculateCorrOfAllTissueTrait(primaryTraitSymbol=primaryGeneSymbol,method=method)
+ except:
+ heading = "Tissue Correlation"
+ detail = ['Please use the official NCBI gene symbol.' ]
+ self.error(heading=heading,detail=detail)
+ return
+
+ symbolList0,geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict=TissueCorrMatrixObject.getTissueProbeSetXRefInfo(GeneNameLst=[])
+ # In case, upper case and lower case issue of symbol, mappedByTargetList function will update input geneSymbolLst based on database search result
+ tempPrimaryGeneSymbol =self.mappedByTargetList(primaryList=symbolList0,targetList=[primaryGeneSymbol])
+ primaryGeneSymbol =tempPrimaryGeneSymbol[0]
+
+ returnNum = self.getReturnNum(recordReturnNum)
+ symbolListSorted=[]
+ symbolList=[]
+ # get key(list) of symbolCorrDict(dict) based on sorting symbolCorrDict(dict) by its' value in desc order
+ symbolListSorted=sorted(symbolCorrDict, key=symbolCorrDict.get, reverse=True)
+ symbolList = self.mappedByTargetList(primaryList=symbolList0,targetList=symbolListSorted)
+
+ if returnNum==None:
+ returnNum =len(symbolList0)
+ IntroReturnNum ="All %d "%returnNum
+ else:
+ IntroReturnNum ="The Top %d" %returnNum
+
+ symbolList = symbolList[:returnNum]
+
+ pageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%", border=0, align="Left")
+
+ ##############
+ # Excel file #
+ ##############
+ filename= webqtlUtil.genRandStr("Corr_")
+ xlsUrl = HT.Input(type='button', value = 'Download Table', onClick= "location.href='/tmp/%s.xls'" % filename, Class='button')
+ # Create a new Excel workbook
+ workbook = xl.Writer('%s.xls' % (webqtlConfig.TMPDIR+filename))
+ headingStyle = workbook.add_format(align = 'center', bold = 1, border = 1, size=13, fg_color = 0x1E, color="white")
+ #There are 6 lines of header in this file.
+ worksheet = self.createExcelFileWithTitleAndFooter(workbook=workbook, datasetName=datasetFullName, returnNumber=returnNum)
+ newrow = 6
+ pageTable.append(HT.TR(HT.TD(xlsUrl,height=40)))
+
+ # get header part of result table and export excel file
+ tblobj = {}
+ tblobj['header'], worksheet = self.getTableHeader( method=method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+ newrow += 1
+
+ # get body part of result table and export excel file
+ tblobj['body'], worksheet = self.getTableBody(symbolCorrDict=symbolCorrDict, symbolPvalueDict=symbolPvalueDict,symbolList=symbolList,geneIdDict=geneIdDict,ChrDict=ChrDict,MbDict=MbDict,descDict=descDict,pTargetDescDict=pTargetDescDict,primarySymbol=primaryGeneSymbol,TissueCount=TissueCount, formName=formName, worksheet=worksheet, newrow=newrow,method=method)
+ workbook.close()
+ # creat object for result table for sort function
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ sortby = ("tissuecorr", "down")
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), Id="sortable")
+
+ if method =="0":
+ IntroMethod="Pearson\'s r "
+ else:
+ IntroMethod="Spearman\'s rho "
+ Intro = HT.Blockquote('%s correlations ranked by the %s are displayed.' % (IntroReturnNum,IntroMethod),
+ ' You can resort this list using the small arrowheads in the top row.')
+ Intro.append(HT.BR(),' Click the correlation values to generate scatter plots. Select the symbol to open NCBI Entrez.')
+
+ pageTable.append(HT.TR(HT.TD(div)))
+ form.append(HT.P(), HT.P(),pageTable)
+ corrHeading = HT.Paragraph('Tissue Correlation Table', Class="title")
+ TD_LR = HT.TD(height=200,width="100%",bgcolor='#eeeeee',align="left")
+ TD_LR.append(corrHeading,note,Intro, form, HT.P())
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['js1'] = '<SCRIPT SRC="/javascript/correlationMatrix.js"></SCRIPT><BR>'
+ self.dict['title'] = 'Tissue Correlation Result'
+
+ return
+
+ # result page when input symbols are more than 1
+ def displayMultiSymbolsResultPage(self, geneSymbolLst=None, symbolCount=None, tProbeSetFreezeId=None,TissueCorrMatrixObject=None,note=None,TissueCount =None):
+
+ formName = webqtlUtil.genRandStr("fm_")
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data',name= formName, submit=HT.Input(type='hidden'))
+ # the following hidden elements are required parameter in Class(PlotCorrelationPage). So we need to define them here.
+ form.append(HT.Input(type="hidden", name="action", value="disp"))
+ form.append(HT.Input(type="hidden", name="FormID", value="dispMultiTissueCorrelation"))
+ form.append(HT.Input(type="hidden", name="X_geneSymbol", value=""))
+ form.append(HT.Input(type="hidden", name="Y_geneSymbol", value=""))
+ form.append(HT.Input(type="hidden", name="ProbeSetID", value=""))
+ # RISet is not using in Tissue correlation, but is a required parameter in Class(PlotCorrelationPage). So we set dummy value(BXD).
+ form.append(HT.Input(type="hidden", name="RISet", value="BXD"))
+ form.append(HT.Input(type="hidden", name="ShowLine", value="1"))
+ form.append(HT.Input(type="hidden", name="TissueProbeSetFreezeId", value=tProbeSetFreezeId))
+ form.append(HT.Input(type="hidden", name="rankOrder", value=0))
+
+ # updated by NL, 2011-01-06, build multi list for later use to descrease access to db again
+ symbolList,geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict = TissueCorrMatrixObject.getTissueProbeSetXRefInfo(GeneNameLst=geneSymbolLst)
+ # In case, upper case and lower case issue of symbol, mappedByTargetList function will update input geneSymbolLst based on database search result
+ geneSymbolLst =self.mappedByTargetList(primaryList=symbolList,targetList=geneSymbolLst)
+
+ # Added by NL, 2011-01-06, get all shortNames, verboseNames, verboseNames2, verboseNames3, exportArray
+ # for Short Label, Long Label, Export functions
+ geneIdLst,shortNames, verboseNames, verboseNames2, verboseNames3, exportArray = self.getAllLabelsInfo(geneSymbolList =geneSymbolLst, geneIdDict=geneIdDict,ChrDict=ChrDict, MbDict=MbDict, descDict=descDict, pTargetDescDict=pTargetDescDict)
+
+ heading = "Tissue Correlation Matrix"
+
+ #get correlation value and p value based on Gene Symbols list, and return the values in corrArray and pvArray seperately
+ corrArray,pvArray = TissueCorrMatrixObject.getTissueCorrPvArray(geneNameLst=geneSymbolLst,dataIdDict=dataIdDict)
+
+ # in the matrix table, top right corner displays Spearman Rank Correlation's Values and P-Values for each pair of geneSymbols;
+ # left bottom displays Pearson Correlation values and P-Vlues for each pair of geneSymbols.
+ tissueCorrMatrixHeading = HT.Paragraph(heading,Class="title")
+ tcmTable = HT.TableLite(Class="collap", border=0, cellspacing=1, cellpadding=5, width='100%')
+ row1 = HT.TR(HT.TD(Class="fs14 fwb ffl b1 cw cbrb"),HT.TD('Spearman Rank Correlation (rho)' , Class="fs14 fwb ffl b1 cw cbrb", colspan= symbolCount+2,align="center"))
+ col1 = HT.TR(HT.TD("P e a r s o n &nbsp;&nbsp;&nbsp; r", rowspan= symbolCount+1,Class="fs14 fwb ffl b1 cw cbrb", width=10,align="center"),HT.TD("Gene Symbol",Class="fs13 fwb cb b1", width=300))
+ for i in range(symbolCount):
+ GeneSymbol=geneSymbolLst[i].strip()
+ geneId = geneIdLst[i]
+
+ if geneId!=0:
+ _url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % geneId
+ curURL = HT.Href(text=GeneSymbol,url=_url,Class='fs13',target="_blank")
+ else:
+ curURL = GeneSymbol
+ col1.append(HT.TD(curURL,Class="b1", align="center"))
+
+ tcmTable.append(row1,col1)
+ # to decide to whether to show note for "*" or not
+ flag = 0
+ for i in range(symbolCount):
+ GeneSymbol=geneSymbolLst[i].strip()
+ geneId = geneIdLst[i]
+
+ newrow = HT.TR()
+ newrow.append(HT.Input(name="Symbol", value=GeneSymbol, type='hidden'))
+
+ if geneId!=0:
+ _url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" %geneId
+ geneIdURL = HT.Href(text="%s "%GeneSymbol,url=_url,Class="b1",target="_blank")
+ else:
+ # flag =1 will show note for "*"
+ flag = 1
+ geneIdURL =HT.Italic("%s"%GeneSymbol,HT.Font('*', color='red'))
+ newrow.append(HT.TD(geneIdURL,shortNames[i],verboseNames[i],verboseNames2[i],verboseNames3[i], Class="b1", align="left",NOWRAP="ON"))
+
+ for j in range(symbolCount):
+ GeneSymbol2=geneSymbolLst[j].strip()
+ corr = corrArray[i][j]
+ pValue = pvArray[i][j]
+ Color=''
+
+ if j==i:
+ newrow.append(HT.TD(HT.Font(HT.Italic("n"),HT.BR(),str(TissueCount),Class="fs11 fwn b1",align="center", color="000000"), bgColor='#cccccc', align="center", Class="b1", NOWRAP="ON"))
+ exportArray[i+1][j+1] = '%d/%d' % (TissueCount,TissueCount)
+ else:
+ if corr:
+ corr = float(corr)
+ tCorr = "%2.3f" % corr
+ pValue = float(pValue)
+ tPV = "%2.3f" % pValue
+
+ # updated by NL, based on Rob's requirement: delete p value, 2010-02-14
+ # set color for cells by correlationValue
+ if corr > 0.7:
+ fontcolor="red"
+ elif corr > 0.5:
+ fontcolor="#FF6600"
+ elif corr < -0.7:
+ fontcolor="blue"
+ elif corr < -0.5:
+ fontcolor="#009900"
+ else:
+ fontcolor ="#000000"
+
+ # set label for cells
+ # if rank is equal to 0, pearson correlation plot will be the first one;
+ # if rank is equal to 1, spearman ran correlation plot will be the first one.
+ if j>i:
+ exportArray[i+1][j+1] =tCorr+"/"+tPV
+ rank =1
+ elif j<i:
+ exportArray[i+1][j+1] =tCorr+"/"+tPV
+ rank =0
+
+ tCorrStr= tCorr
+ tPVStr = tPV
+ tCorrPlotURL = "javascript:showTissueCorrPlot('%s','%s','%s',%d)" %(formName,GeneSymbol, GeneSymbol2,rank)
+ corrURL= HT.Href(text=HT.Font(tCorrStr,HT.BR(),color=fontcolor, Class="fs11 fwn"), url = tCorrPlotURL)
+ else:
+ corr = 'N/A'
+ corrURL= HT.Font(corr)
+ exportArray[i+1][j+1] ="---/---"
+
+ newrow.append(HT.TD(corrURL,bgColor=Color,Class="b1",NOWRAP="ON",align="middle"))
+
+ tcmTable.append(newrow)
+
+
+
+ Intro = HT.Blockquote('Lower left cells list Pearson ',HT.EM('r'),' values; upper right cells list Spearman rho values. Each cell also contains the n samples of tissues and organs. Values higher than 0.7 are displayed in ',HT.Font('red', color='red'),'; those between 0.5 and 0.7 in ',HT.Font('orange', color='#FF6600'),'; Values lower than -0.7 are in ',HT.Font('blue', color='blue'),'; between -0.5 and -0.7 in ',HT.Font('green', color='#009900'),'.', HT.BR(),HT.BR(), HT.Strong('Make scatter plots by clicking on cell values '),'(', HT.EM('r'),' or rho). ', Class="fs13 fwn")
+
+ shortButton = HT.Input(type='button' ,name='dispShort',value=' Short Labels ', onClick="displayTissueShortName();",Class="button")
+ verboseButton = HT.Input(type='button' ,name='dispVerbose',value=' Long Labels ', onClick="displayTissueVerboseName();", Class="button")
+ exportbutton = HT.Input(type='button', name='export', value='Export', onClick="exportTissueText(allCorrelations);",Class="button")
+ lableNote = HT.Blockquote(HT.Italic(HT.Font('*', color='red',Class="fs9 fwn"), ' Symbol(s) can not be found in database.'))
+
+ # flag =1 will show note for "*", which means there's unidentified symbol.
+ if flag==1:
+ form.append(HT.Blockquote(tcmTable,lableNote,HT.P(),shortButton,verboseButton,exportbutton))
+ else:
+ form.append(HT.Blockquote(tcmTable,HT.P(),shortButton,verboseButton,exportbutton))
+
+ exportScript = """
+ <SCRIPT language=JavaScript>
+ var allCorrelations = %s;
+ </SCRIPT>
+ """
+ exportScript = exportScript % str(exportArray)
+ self.dict['js1'] = exportScript+'<SCRIPT SRC="/javascript/correlationMatrix.js"></SCRIPT><BR>'
+
+ TD_LR = HT.TD(colspan=2,width="100%",bgcolor="#eeeeee")
+ TD_LR.append(tissueCorrMatrixHeading,note,Intro,form,HT.P())
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = 'Tissue Correlation Result'
+ return
+
+ # Added by NL, 2011-01-06, get all shortNames, verboseNames, verboseNames2, verboseNames3, exportArray
+ # for Short Label, Long Label, Export functions
+ def getAllLabelsInfo(self, geneSymbolList=None,geneIdDict=None,ChrDict=None,MbDict=None,descDict=None,pTargetDescDict=None):
+
+ symbolCount= len(geneSymbolList)
+ geneIdLst =[]
+ exportArray = [([0] * (symbolCount+1))[:] for i in range(symbolCount+1)]
+ exportArray[0][0] = 'Tissue Correlation'
+ shortNames = []
+ verboseNames = []
+ verboseNames2 = []
+ verboseNames3 = []
+
+ # added by NL, 2010-12-21, build DIV and array for short label, long label and export functions
+ for i, geneSymbolItem in enumerate(geneSymbolList):
+ geneSymbol =geneSymbolItem.lower()
+ _shortName =HT.Italic("%s" %geneSymbolItem)
+ _verboseName =''
+ _verboseName2 = ''
+ _verboseName3 = ''
+ if geneIdDict.has_key(geneSymbol):
+ geneIdLst.append(geneIdDict[geneSymbol])
+ else:
+ geneIdLst.append(0)
+ if ChrDict.has_key(geneSymbol) and MbDict.has_key(geneSymbol):
+ _verboseName = ' on Chr %s @ %s Mb' % (ChrDict[geneSymbol],MbDict[geneSymbol])
+ if descDict.has_key(geneSymbol):
+ _verboseName2 = '%s' % (descDict[geneSymbol])
+ if pTargetDescDict.has_key(geneSymbol):
+ _verboseName3 = '%s' % (pTargetDescDict[geneSymbol])
+
+ shortName = HT.Div(id="shortName_" + str(i), style="display:none")
+ shortName.append('Symbol: ')
+ shortName.append(_shortName)
+ shortNames.append(shortName)
+
+ verboseName = HT.Div(id="verboseName_" + str(i), style="display:none")
+ verboseName.append(_shortName)
+ verboseName.append(_verboseName)
+ verboseNames.append(verboseName)
+ verboseName2 = HT.Div(id="verboseName2_" + str(i), style="display:none")
+ verboseName2.append(_verboseName2)
+ verboseNames2.append(verboseName2)
+ verboseName3 = HT.Div(id="verboseName3_" + str(i), style="display:none")
+ verboseName3.append(_verboseName3)
+ verboseNames3.append(verboseName3)
+
+ # exportTissueText in webqtl.js is using '/' as delimilator; add '/', otherwise the last letter in geneSymbol will missing
+ exportArray[i+1][0] =geneSymbolItem+ '/' + geneSymbolItem + '/' +geneSymbolItem + ':' + str(_verboseName) + ' : ' + str(_verboseName2) + ' : ' + str(_verboseName3)
+ exportArray[0][i+1] =geneSymbolItem+ '/'
+
+ return geneIdLst,shortNames, verboseNames, verboseNames2, verboseNames3, exportArray
+
+
+########################################################################
+# functions for display and download when input symbol has only one #
+########################################################################
+
+ # build header and footer parts for export excel file
+ def createExcelFileWithTitleAndFooter(self, workbook=None, datasetName=None,returnNumber=None):
+
+ worksheet = workbook.add_worksheet()
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=14, border = 1, border_color="gray")
+
+ ##Write title Info
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([2, 0], "Dataset : %s" % datasetName, titleStyle)
+ worksheet.write([3, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([4, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+ worksheet.write([5, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+ #Write footer info
+ worksheet.write([8 + returnNumber, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA21131), NCI MMHCC (U01CA105417), and NCRR (U01NR 105417)", titleStyle)
+ worksheet.write([9 + returnNumber, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+
+ return worksheet
+
+ # build header of table when input symbol has only one
+ def getTableHeader(self, method='0', worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+ exportList=[]
+ header=[]
+ header = [THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
+ THCell(HT.TD('Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="symbol", idx=1),
+ THCell(HT.TD('Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="desc", idx=2),
+ THCell(HT.TD('Location',HT.BR(),'Chr and Mb ', Class="fs13 fwb ffl b1 cw cbrb"), text="location", idx=3),
+ THCell(HT.TD('N Cases',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), text="nstr", idx=4)]
+ if method =="0":# Pearson Correlation
+ header.append( THCell(HT.TD(HT.Href(
+ text = HT.Span(' r ', HT.Sup(' ?', style="color:#f00"),HT.BR(),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuecorr", idx=5))
+ header.append( THCell(HT.TD(HT.Href(
+ text = HT.Span(' p(r) ', HT.Sup(' ?', style="color:#f00"),HT.BR(),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_p_r"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuepvalue", idx=6))
+
+ exportList =[ 'Gene ID', 'Symbol', 'Description', 'Location', 'N Cases', ' r ', ' p(r) ']
+
+ else:# Spearman Correlation
+ header.append( THCell(HT.TD(HT.Href(
+ text = HT.Span(' rho ', HT.Sup(' ?', style="color:#f00"),HT.BR(),HT.BR(), Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuecorr", idx=5))
+ header.append( THCell(HT.TD(HT.Href(
+ text = HT.Span('p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), HT.BR(),Class="fs13 fwb ffl cw"),
+ target = '_blank',
+ url = "/correlationAnnotation.html#tissue_p_rho"),
+ Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="tissuepvalue", idx=6))
+ exportList = ['Gene ID', 'Symbol', 'Description', 'Location', 'N Cases','rho', ' p(rho) ']
+
+ # build header of excel for download function
+ for ncol, item in enumerate(exportList):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ tblobj_header.append(header)
+
+ return tblobj_header, worksheet
+
+ # build body of table when input symbol has only one
+ def getTableBody(self, symbolCorrDict={}, symbolPvalueDict={},symbolList=[],geneIdDict={},ChrDict={},MbDict={},descDict={},pTargetDescDict={},primarySymbol=None, TissueCount=None,formName=None, worksheet=None, newrow=None,method="0"):
+
+ tblobj_body = []
+
+ for symbolItem in symbolList:
+ symbol =symbolItem.lower()
+ if symbol:
+ pass
+ else:
+ symbol ="N/A"
+
+ if geneIdDict.has_key(symbol) and geneIdDict[symbol]:
+ geneId = geneIdDict[symbol]
+ ncbiUrl = HT.Href(text="NCBI",target='_blank',url=webqtlConfig.NCBI_LOCUSID % geneIdDict[symbol], Class="fs10 fwn")
+ else:
+ geneId ="N/A"
+ symbolItem =symbolItem.replace('"','') # some symbol is saved in ["symbol"]format
+ ncbiUrl = HT.Href(text="NCBI",target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % symbol, Class="fs10 fwn")
+
+ _Species="mouse"
+ similarTraitUrl = "%s?cmd=sch&gene=%s&alias=1&species=%s" % (os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), symbolItem, _Species)
+ gnUrl = HT.Href(text="GN",target='_blank',url=similarTraitUrl, Class="fs10 fwn")
+
+ tr = []
+ # updated by NL, 04/25/2011: add checkbox and highlight function
+ # first column of table
+ # updated by NL. 12-7-2011
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="tissueResult",value=symbol, onClick="highlight(this)"), align='right',Class="fs12 fwn b1 c222 fsI",nowrap='ON'),symbol,symbol))
+ # updated by NL, 04/26/2011: add GN and NCBI links
+ #gene symbol (symbol column)
+ tr.append(TDCell(HT.TD(HT.Italic(symbolItem), HT.BR(),gnUrl,"&nbsp;&nbsp|&nbsp;&nbsp", ncbiUrl, Class="fs12 fwn b1 c222"),symbolItem, symbolItem))
+
+ #description and probe target description(description column)
+ description_string=''
+ if descDict.has_key(symbol):
+ description_string = str(descDict[symbol]).strip()
+ if pTargetDescDict.has_key(symbol):
+ target_string = str(pTargetDescDict[symbol]).strip()
+
+ description_display = ''
+ if len(description_string) > 1 and description_string != 'None':
+ description_display = description_string
+ else:
+ description_display = symbolItem
+
+ if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ description_display = description_display + '; ' + target_string.strip()
+
+ tr.append(TDCell(HT.TD(description_display, Class="fs12 fwn b1 c222"), description_display, description_display))
+
+ #trait_location_value is used for sorting (location column)
+ trait_location_repr = 'N/A'
+ trait_location_value = 1000000
+
+ if ChrDict.has_key(symbol) and MbDict.has_key(symbol):
+
+ if ChrDict[symbol] and MbDict[symbol]:
+ mb = float(MbDict[symbol])
+ try:
+ trait_location_value = int(ChrDict[symbol])*1000 + mb
+ except:
+ if ChrDict[symbol].upper() == 'X':
+ trait_location_value = 20*1000 + mb
+ else:
+ trait_location_value = ord(str(ChrDict[symbol]).upper()[0])*1000 + mb
+
+ trait_location_repr = 'Chr%s: %.6f' % (ChrDict[symbol], mb )
+ else:
+ trait_location_repr="N/A"
+ trait_location_value ="N/A"
+
+ tr.append(TDCell(HT.TD(trait_location_repr, Class="fs12 fwn b1 c222", nowrap="on"), trait_location_repr, trait_location_value))
+
+ # number of overlaped cases (N Case column)
+ tr.append(TDCell(HT.TD(TissueCount, Class="fs12 fwn ffl b1 c222", align='right'),TissueCount,TissueCount))
+
+ #tissue correlation (Tissue r column)
+ TCorr = 0.0
+ TCorrStr = "N/A"
+ if symbolCorrDict.has_key(symbol):
+ TCorr = symbolCorrDict[symbol]
+ TCorrStr = "%2.3f" % TCorr
+ symbol2 =symbolItem.replace('"','') # some symbol is saved in "symbol" format
+ # add a new parameter rankOrder for js function 'showTissueCorrPlot'
+ rankOrder = int(method)
+ TCorrPlotURL = "javascript:showTissueCorrPlot('%s','%s','%s',%d)" %(formName, primarySymbol, symbol2,rankOrder)
+ tr.append(TDCell(HT.TD(HT.Href(text=TCorrStr, url=TCorrPlotURL, Class="fs12 fwn ff1"), Class="fs12 fwn ff1 b1 c222", align='right'), TCorrStr, abs(TCorr)))
+ else:
+ tr.append(TDCell(HT.TD(TCorrStr, Class="fs12 fwn b1 c222", align='right'), TCorrStr, abs(TCorr)))
+
+ #p value of tissue correlation (Tissue p(r) column)
+ TPValue = 1.0
+ TPValueStr = "N/A"
+ if symbolPvalueDict.has_key(symbol):
+ TPValue = symbolPvalueDict[symbol]
+ #TPValueStr = "%2.3f" % TPValue
+ TPValueStr=webqtlUtil.SciFloat(TPValue)
+ tr.append(TDCell(HT.TD(TPValueStr, Class="fs12 fwn b1 c222", align='right'), TPValueStr, TPValue))
+
+ tblobj_body.append(tr)
+ # build body(records) of excel for download function
+ for ncol, item in enumerate([geneId, symbolItem, description_display, trait_location_repr,TissueCount, TCorr, TPValue]):
+ worksheet.write([newrow, ncol], item)
+
+ newrow += 1
+
+ return tblobj_body, worksheet
+
+
+ # get return number of records when input symbol has only one
+ def getReturnNum(self,recordReturnNum="0"):
+ if recordReturnNum=="0":
+ returnNum=100
+ elif recordReturnNum=="1":
+ returnNum=200
+ elif recordReturnNum=="2":
+ returnNum=500
+ elif recordReturnNum=="3":
+ returnNum=1000
+ elif recordReturnNum=="4":
+ returnNum=2000
+ elif recordReturnNum=="5":
+ returnNum= None
+
+ return returnNum
+
+ # map list based on the order of target List
+ # if item.lower() exist in both lists, then compare the difference of item's original value of two lists
+ # if not equal, then replace the item in targetList by using the item in primaryList(list from database)
+
+ def mappedByTargetList(self,primaryList=[],targetList=[]):
+
+ tempPrimaryList =[x.lower() for x in primaryList]
+ testTargetList =[y.lower() for y in targetList]
+
+ for i, item in enumerate(tempPrimaryList):
+ if item in testTargetList:
+ index = testTargetList.index(item)
+ if primaryList[i]!=targetList[index]:
+ targetList[index]= primaryList[i]
+
+ return targetList
diff --git a/web/webqtl/correlationMatrix/__init__.py b/web/webqtl/correlationMatrix/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/correlationMatrix/__init__.py
diff --git a/web/webqtl/correlationMatrix/tissueCorrelationMatrix.py b/web/webqtl/correlationMatrix/tissueCorrelationMatrix.py
new file mode 100755
index 00000000..23dc14eb
--- /dev/null
+++ b/web/webqtl/correlationMatrix/tissueCorrelationMatrix.py
@@ -0,0 +1,132 @@
+# 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/11/10
+#
+# Last updated by Ning Liu, 2011/01/26
+
+
+#tissueCorrelationMatrix: funciton part for TissueCorrelationPage.py
+from htmlgen import HTMLgen2 as HT
+from correlation import correlationFunction
+from dbFunction import webqtlDatabaseFunction
+import sys
+
+#########################################
+# Tissue Correlation Page
+#########################################
+
+class tissueCorrelationMatrix:
+ def __init__(self,tissueProbeSetFreezeId=None):
+
+ #initialize parameters
+ self.tProbeSetFreezeId = tissueProbeSetFreezeId
+ self.cursor = webqtlDatabaseFunction.getCursor()
+
+
+
+ #retreive dataSet info from database table TissueProbeSetFreeze to get all TissueProbeSetFreezeId(List), Name(List) and FullName(List)
+ def getTissueDataSet(self):
+ tissProbeSetFreezeIds,Names,fullNames = webqtlDatabaseFunction.getTissueDataSet(cursor=self.cursor)
+ return tissProbeSetFreezeIds,Names,fullNames
+
+
+ #retrieve DatasetName, DatasetFullName based on TissueProbeSetFreezeId, return DatasetName(string), DatasetFullName(string)
+ def getFullnameofCurrentDataset(self):
+
+ DatasetName, DatasetFullName =webqtlDatabaseFunction.getDatasetNamesByTissueProbeSetFreezeId(cursor=self.cursor, TissueProbeSetFreezeId=self.tProbeSetFreezeId)
+ return DatasetName, DatasetFullName
+
+
+ #retrieve how many tissue used in the specific dataset based on TissueProbeSetFreezeId, return TissueCount(int)
+ def getTissueCountofCurrentDataset(self):
+
+ TissueCount =webqtlDatabaseFunction.getTissueCountByTissueProbeSetFreezeId(cursor=self.cursor,TissueProbeSetFreezeId=self.tProbeSetFreezeId)
+ return TissueCount
+
+
+
+ #retrieve corrArray(array), pvArray(array) for display by calling calculation function:calZeroOrderCorrForTiss
+ def getTissueCorrPvArray(self,geneNameLst=None,dataIdDict=None):
+ #retrieve SymbolValuePairDict(Dict), dictionary of Symbol and Value Pair.key is symbol, value is one list of expression values of one probeSet
+ symbolValuepairDict =correlationFunction.getGeneSymbolTissueValueDict(cursor=self.cursor,symbolList=geneNameLst,dataIdDict=dataIdDict)
+ corrArray,pvArray = correlationFunction.getCorrPvArray(cursor=self.cursor,priGeneSymbolList=geneNameLst,symbolValuepairDict=symbolValuepairDict)
+ return corrArray,pvArray
+
+
+
+ #retrieve symbolList,geneIdList,dataIdList,ChrList,MbList,descList,pTargetDescList (all are list type) to
+ #get multi lists for short and long label functions, and for getSymbolValuePairDict and
+ #getGeneSymbolTissueValueDict to build dict to get CorrPvArray
+ def getTissueProbeSetXRefInfo(self,GeneNameLst=[]):
+ symbolList,geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict =correlationFunction.getTissueProbeSetXRefInfo(cursor=self.cursor,GeneNameLst=GeneNameLst,TissueProbeSetFreezeId=self.tProbeSetFreezeId)
+ return symbolList,geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict
+
+
+
+ #retrieve corrArray(array), pvArray(array) for gene symbol pair
+ def getCorrPvArrayForGeneSymbolPair(self,geneNameLst=None):
+ corrArray = None
+ pvArray = None
+
+ if len(geneNameLst) == 2:
+ #retrieve SymbolValuePairDict(Dict), dictionary of Symbol and Value Pair.key is symbol, value is one list of expression values of one probeSet
+ symbolList,geneIdDict,dataIdDict,ChrDict,MbDict,descDict,pTargetDescDict =correlationFunction.getTissueProbeSetXRefInfo(cursor=self.cursor,GeneNameLst=geneNameLst,TissueProbeSetFreezeId=self.tProbeSetFreezeId)
+ symbolValuepairDict =correlationFunction.getGeneSymbolTissueValueDict(cursor=self.cursor,symbolList=geneNameLst,dataIdDict=dataIdDict)
+ corrArray,pvArray = correlationFunction.getCorrPvArray(cursor=self.cursor,priGeneSymbolList=geneNameLst,symbolValuepairDict=symbolValuepairDict)
+
+ return corrArray,pvArray
+
+
+ #retrieve symbolCorrDict(dict), symbolPvalueDict(dict) to get all tissues' correlation value and P value; key is symbol
+ def calculateCorrOfAllTissueTrait(self, primaryTraitSymbol=None, method='0'):
+ symbolCorrDict, symbolPvalueDict = correlationFunction.calculateCorrOfAllTissueTrait(cursor=self.cursor, primaryTraitSymbol=primaryTraitSymbol, TissueProbeSetFreezeId=self.tProbeSetFreezeId,method=method)
+
+ return symbolCorrDict, symbolPvalueDict
+
+ #Translate GeneId to gene symbol and keep the original order.
+ def getGeneSymbolLst(self, geneSymbols=None):
+ geneSymbolLst=[]
+ geneIdLst=[]
+ #split the input string at every occurrence of the delimiter '\r', and return the substrings in an array.
+ tokens=geneSymbols.strip().split('\r')
+
+ #Ning: To keep the original order of input symbols and GeneIds
+ for i in tokens:
+ i=i.strip()
+ if (len(i) >0) and (i not in geneSymbolLst):
+ geneSymbolLst.append(i)
+ # if input includes geneId(s), then put it/them into geneIdLst
+ if i.isdigit():
+ geneIdLst.append(i)
+
+ #Ning: Replace GeneId with symbol if applicable
+ if len(geneIdLst)>0:
+ # if input includes geneId(s), replace geneId by geneSymbol;
+ geneIdSymbolPair =webqtlDatabaseFunction.getGeneIdSymbolPairByGeneId(cursor=self.cursor, geneIdLst =geneIdLst)
+ for geneId in geneIdLst:
+ if geneIdSymbolPair[geneId]:
+ index = geneSymbolLst.index(geneId)
+ geneSymbolLst[index] =geneIdSymbolPair[geneId]
+
+ return geneSymbolLst
+
+
+
diff --git a/web/webqtl/dataSharing/SharingBody.py b/web/webqtl/dataSharing/SharingBody.py
new file mode 100755
index 00000000..4445e0d1
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingBody.py
@@ -0,0 +1,290 @@
+# 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
+
+sharing_body_string = """
+<TD vAlign=top width="100%" align="left" height=10 bgColor=#eeeeee>
+
+ <p style="font-size:18px;font-family:verdana;color:black"><B> Data Set Download</B></p>
+ <Form METHOD="get" ACTION="/webqtl/main.py" name="SEARCHFORM">
+
+ <TABLE width="800" border="0">
+
+ <!-- SPECIES SELECTION -->
+ <TR>
+ <TD align=right height="35" style="font-size:14px;font-family:verdana;color:black" width="16%">
+ <B>Species:</B>
+ </TD>
+ <TD width="3%">
+ </TD>
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu0">
+ <Select NAME="species" size=1 id="species" onchange="fillOptions('species');">
+ </Select>
+ </DIV>
+ </TD>
+ </TR>
+
+ <!-- GROUP SELECTION -->
+ <TR>
+ <TD align="right" height="35" style="font-size:14px;font-family:verdana;color:black">
+ <B>Group:</B>
+ </TD>
+ <TD>
+ </TD>
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu1">
+
+ <Select NAME="cross" size=1 id="cross" onchange="fillOptions('cross');">
+ </Select>
+ <input type="button" class="button" value=" Info " onCLick="javascript:crossinfo();">
+ </DIV>
+ </TD>
+ </TR>
+
+ <!-- TYPE SELECTION -->
+ <TR>
+ <TD align=right height=35 style="font-size:14px;font-family:verdana;color:black">
+ <B>Type:</B>
+ </TD>
+ <TD>
+ </TD>
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu2">
+ <Select NAME="tissue" size=1 id="tissue" onchange="fillOptions('tissue');">
+
+ </Select>
+ </DIV>
+ </TD>
+ </TR>
+
+ <!-- DATABASE SELECTION -->
+ <TR>
+ <TD align=right height=35 style="font-size:14px;font-family:verdana;color:black">
+ <B>Database:</B>
+ </TD>
+ <TD>
+ </TD>
+ <TD NOWRAP width="85%" align="left">
+ <DIV Id="menu3">
+ <Select NAME="database" size=1 id="database">
+ </Select>
+ <input type="button" class="button" value=" Info " onCLick="javascript:databaseinfo();">
+ </DIV>
+ </TD>
+ </TR>
+
+<!-- SEARCH, MAKE DEFAULT, ADVANCED SEARCH -->
+ <TR>
+ <td></td>
+ <td></td>
+ <TD ALIGN="left" HEIGHT="40">
+ &nbsp;&nbsp;&nbsp;<INPUT TYPE="button" CLASS="button" STYLE="font-size:12px" VALUE="&nbsp;&nbsp;Download&nbsp;&nbsp;" onCLick="javascript:datasetinfo();">
+ </TD>
+ </TR>
+ </TABLE>
+
+ <SCRIPT SRC="/javascript/selectDatasetMenu.js"></SCRIPT>
+ </FORM>
+
+ <p style="font-size:18px;font-family:verdana;color:black"><B> GeneNetwork Accession Number</B></p>
+ <form method="get" action="/webqtl/main.py" name="f2" target="_blank">
+ <INPUT TYPE="hidden" NAME="FormID" VALUE="sharinginfo">
+ <TABLE width="800" border="0">
+ <tr>
+ <td align=right height="35" style="font-size:14px;font-family:verdana;color:black" width="16%"><b>GN:</b></td>
+ <td width=3%></td>
+ <td><input type="text" name="GN_AccessionId" size="40" />&nbsp;&nbsp;E.g. 112</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td HEIGHT="40">
+ &nbsp;&nbsp;&nbsp;<input type="Submit" class="button" STYLE="font-size:12px" VALUE="&nbsp;&nbsp;&nbsp;Submit&nbsp;&nbsp;&nbsp;">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+</td>
+"""
+
+sharinginfo_body_string = """<td>
+<a href="/webqtl/main.py?FormID=sharingListDataset">List of DataSets</a><br>
+<H1 class="title" id="parent-fieldname-title">%s
+<a href="/webqtl/main.py?FormID=sharinginfoedit&GN_AccessionId=%s"><img src="/images/modify.gif" alt="modify this page" border="0" valign="middle"></a>
+<span style="color:red;">%s</span>
+</H1>
+<table border="0" width="100%%">
+<tr>
+<td valign="top" width="50%%">
+<TABLE cellSpacing=0 cellPadding=5 width=100%% border=0>
+ <TR><td><b>GN Accession:</b> GN%s</TD></tr>
+ <TR><TD><b>GEO Series:</b> %s</TD></TR>
+ <TR><TD><b>Title:</b> %s</TD></TR>
+ <TR><TD><b>Organism:</b> <a href=http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=%s>%s</a></TD></tr>
+ <tr><TD><b>Group:</b> %s</TD></TR>
+ <TR><TD><b>Tissue:</b> %s</TD></tr>
+ <tr><TD><b>Dataset Status:</b> %s</TD></tr>
+ <TR><TD><b>Platforms:</b> %s</TD></TR>
+ <TR><TD><b>Normalization:</b> %s</TD></TR>
+ <TR><TD><!--Code below to Show hide Contact information -->
+ <a href="#" onclick="colapse('answer1')">See Contact Information</a><br>
+ <span id="answer1" style="display: none; return: false;">
+ %s<br>
+ %s<br>
+ %s<br>
+ %s<br>
+ %s, %s %s %s<br>
+ Tel. %s<br>
+ %s<br>
+ <a href="%s">%s</a>
+ </span><!--Code above to Show hide Contact information --></TD></TR>
+</TABLE>
+</td>
+<td valign="top" width="50%%">
+<table border="0" width="100%%">
+<tr>
+ <td bgcolor="#dce4e1"><b>Download datasets and supplementary data files</b></td>
+</tr>
+<tr>
+ <td>%s</td>
+</tr>
+</table>
+</td>
+</tr>
+</table>
+<HR>
+<p>
+<table width="100%%" border="0" cellpadding="5" cellspacing="0">
+<tr><td><span style="font-size:115%%;font-weight:bold;">Summary:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">About the cases used to generate this set of data:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">About the tissue used to generate this set of data:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">About downloading this data set:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">About the array platform:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">About data values and data processing:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Data source acknowledgment:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Experiment Type:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Overall Design:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Contributor:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Citation:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Submission Date:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Laboratory:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+<tr><td><span style="font-size:115%%;font-weight:bold;">Samples:</span></td></tr>
+ <tr><td> %s<br><br></td></tr>
+</table>
+</p>
+</td>
+"""
+
+sharinginfoedit_body_string = """<td>
+<H1 class="title">%s</H1>
+<script language="javascript">
+function CheckGNAccesionId(){
+ if (document.sharinginfoupdate.GN_AccesionId.value.length == 0){
+ alert("Please input GN Accesion Id");
+ document.sharinginfoupdate.GN_AccesionId.focus();
+ return false;
+ } else {
+ return true;
+ }
+}
+</script>
+<table border="0" CELLSPACING="0" CELLPADDING="8">
+<form name="sharinginfoupdate" method="post" action="/webqtl/main.py?FormID=sharinginfoupdate" onsubmit="return CheckGNAccesionId();">
+<input type="hidden" name="Id" value="%s">
+
+ <tr><TH COLSPAN=2><h2 class="title">Principal Investigator</h2></TH></tr>
+ <tr><td align="right" width="100"><b>Contact Name:</b></td><td width="200"><input type='text' name='Contact_Name' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Emails:</b></td><td><input type='text' name='Emails' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Phone:</b></td><td><input type='text' name='Phone' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>URL:</b></td><td><input type='text' name='URL' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Organization Name:</b></td><td><input type='text' name='Organization_Name' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Department:</b></td><td><input type='text' name='Department' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Laboratory:</b></td><td><input type='text' name='Laboratory' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Address:</b></td><td><input type='text' name='Street' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>City:</b></td><td><input type='text' name='City' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>State:</b></td><td><input type='text' name='State' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>ZIP:</b></td><td><input type='text' name='ZIP' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Country:</b></td><td><input type='text' name='Country' size='90' value='%s'></td></tr>
+
+ <tr><TH COLSPAN=2><h2 class="title">Summary</h2></TH></tr>
+ <tr><td align="right"><b>Summary: </b></td><td><TEXTAREA NAME="Summary" cols="77" rows="15">%s</textarea></td></tr>
+
+ <tr><TH COLSPAN=2><h2 class="title">Biology</h2></TH></tr>
+ <tr><td align="right"><b>Experiment Design:</b></td><td><TEXTAREA NAME="Experiment_Type" cols="77" rows="15">%s</textarea></td></tr>
+ <tr><td align="right"><b>About the cases used to<br>generate this set of data:</b></td><td><TEXTAREA NAME="About_Cases" cols="77" rows="15">%s</textarea></td></tr>
+ <tr><td align="right"><b>About the tissue used to<br>generate this set of data:</b></td><td><TEXTAREA NAME="About_Tissue" cols="77" rows="15">%s</textarea></td></tr>
+
+ <tr><TH COLSPAN=2><h2 class="title">Technique</h2></TH></tr>
+ <tr><td align="right"><b>About downloading this data set:</b></td><td><TEXTAREA NAME="About_Download" cols="77" rows="15">%s</textarea></td></tr>
+ <tr><td align="right"><b>About the array platform:</b></td><td><TEXTAREA NAME="About_Array_Platform" cols="77" rows="15">%s</textarea></td></tr>
+
+ <tr><TH COLSPAN=2><h2 class="title">Bioinformatics</h2></TH></tr>
+ <tr><td align="right"><b>About data values and<br>data processing:</b></td><td><TEXTAREA NAME="About_Data_Values_Processing" cols="77" rows="15">%s</textarea></td></tr>
+ <tr><td align="right"><b>Overall Design:</b></td><td><TEXTAREA NAME="Overall_Design" cols="77" rows="15">%s</textarea></td></tr>
+
+ <tr><TH COLSPAN=2><h2 class="title">Misc</h2></TH></tr>
+ <tr><td align="right"><b>Contributor:</b></td><td><TEXTAREA NAME="Contributor" cols="77" rows="15">%s</textarea></td></tr>
+ <tr><td align="right"><b>Citation:</b></td><td><TEXTAREA NAME="Citation" cols="77" rows="5">%s</textarea></td></tr>
+ <tr><td align="right"><b>Data source acknowledgment:</b></td><td><TEXTAREA NAME="Data_Source_Acknowledge" cols="77" rows="15">%s</textarea></td></tr>
+
+ <tr><TH COLSPAN=2><h2 class="title">Administrator ONLY</h2></TH></tr>
+ <tr><td align="right"><b>GN Accesion Id:</b></td><td><input type='text' name='GN_AccesionId' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>DB Title in GN:</b></td><td><input type='text' name='InfoPageTitle' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>GEO Series:</b></td><td><input type='text' name='GEO_Series' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Status:</b></td><td><input type='text' name='Status' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Title:</b></td><td><input type='text' name='Title' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Organism_Id (Taxonomy ID):</b></td><td><input type='text' name='Organism_Id' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Organism:</b></td><td><input type='text' name='Organism' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Submission Date:</b></td><td><input type='text' name='Submission_Date' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Platforms:</b></td><td><input type='text' name='Platforms' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Species:</b></td><td><input type='text' name='Species' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Tissue:</b></td><td><input type='text' name='Tissue' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Normalization:</b></td><td><input type='text' name='Normalization' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Inbred Set:</b></td><td><input type='text' name='InbredSet' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Info Page Name:</b></td><td><input type='text' name='InfoPageName' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Samples:</b></td><td><input type='text' name='Samples' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Authorized Users:</b></td><td><input type='text' name='AuthorizedUsers' size='90' value='%s'></td></tr>
+ <tr><td align="right"><b>Progress:</b></td><td><input type='text' name='Progress' size='90' value='%s'></td></tr>
+
+ <tr><td> <colspan='2' align="center"><input type="Submit" class="button" style="font-size:12px" value=" Submit "></td></tr>
+
+</form>
+</table>
+</td>"""
diff --git a/web/webqtl/dataSharing/SharingInfo.py b/web/webqtl/dataSharing/SharingInfo.py
new file mode 100755
index 00000000..10abcefa
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingInfo.py
@@ -0,0 +1,98 @@
+# 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
+
+import httplib
+
+from dbFunction import webqtlDatabaseFunction
+import SharingBody
+
+
+#########################################
+# Sharing Info
+#########################################
+class SharingInfo:
+
+ def __init__(self, GN_AccessionId, InfoPageName):
+ self.GN_AccessionId = GN_AccessionId
+ self.InfoPageName = InfoPageName
+
+ def getInfo(self):
+ cursor = webqtlDatabaseFunction.getCursor()
+ if (not cursor):
+ return
+ sql = "select Id, GEO_Series, Status, Title, Organism, Experiment_Type, Summary, Overall_Design, Contributor, Citation, Submission_Date, Contact_Name, Emails, Phone, URL, Organization_Name, Department, Laboratory, Street, City, State, ZIP, Country, Platforms, Samples, Species, Normalization, InbredSet, InfoPageName, DB_Name, Organism_Id, InfoPageTitle, GN_AccesionId, Tissue, AuthorizedUsers, About_Cases, About_Tissue, About_Download, About_Array_Platform, About_Data_Values_Processing, Data_Source_Acknowledge, Progreso from InfoFiles where "
+ if(self.GN_AccessionId):
+ sql += "GN_AccesionId = %s"
+ cursor.execute(sql, self.GN_AccessionId)
+ elif (self.InfoPageName):
+ sql += "InfoPageName = %s"
+ cursor.execute(sql, self.InfoPageName)
+ else:
+ raise 'No correct parameter found'
+ info = cursor.fetchone()
+ # fetch datasets file list
+ try:
+ conn = httplib.HTTPConnection("atlas.uthsc.edu")
+ conn.request("GET", "/scandatasets.php?GN_AccesionId=%s" % (info[32]))
+ response = conn.getresponse()
+ data = response.read()
+ filelist = data.split()
+ conn.close()
+ except Exception:
+ filelist = []
+ return info, filelist
+
+ def getBody(self, infoupdate=""):
+ info, filelist = self.getInfo()
+ if filelist:
+ htmlfilelist = '<ul style="line-height:160%;">\n'
+ for i in range(len(filelist)):
+ if i%2==0:
+ filename = filelist[i]
+ filesize = filelist[i+1]
+ htmlfilelist += "<li>"
+ htmlfilelist += '<a href="ftp://atlas.uthsc.edu/users/shared/Genenetwork/GN%s/%s">%s</a>' % (self.GN_AccessionId, filename, filename)
+ htmlfilelist += '&nbsp;&nbsp;&nbsp;'
+ #r=re.compile(r'(?<=\d)(?=(\d\d\d)+(?!\d))')
+ #htmlfilelist += '[%s&nbsp;B]' % r.sub(r',',filesize)
+ if 12<len(filesize):
+ filesize=filesize[0:-12]
+ filesize += ' T'
+ elif 9<len(filesize):
+ filesize=filesize[0:-9]
+ filesize += ' G'
+ elif 6<len(filesize):
+ filesize=filesize[0:-6]
+ filesize += ' M'
+ elif 3<len(filesize):
+ filesize=filesize[0:-3]
+ filesize += ' K'
+ htmlfilelist += '[%sB]' % filesize
+ htmlfilelist += "</li>\n"
+ htmlfilelist += "</ul>"
+ else:
+ htmlfilelist = "Data sets are not available or are not public yet."
+ return SharingBody.sharinginfo_body_string % (info[31], info[32], infoupdate, info[32], info[1], info[3], info[30], info[4], info[27], info[33], info[2], info[23], info[26], info[11], info[15], info[16], info[18], info[19], info[20], info[21], info[22], info[13], info[12], info[14], info[14], htmlfilelist, info[6], info[35], info[36], info[37], info[38], info[39], info[40], info[5], info[7], info[8], info[9], info[10], info[17], info[24])
diff --git a/web/webqtl/dataSharing/SharingInfoAddPage.py b/web/webqtl/dataSharing/SharingInfoAddPage.py
new file mode 100755
index 00000000..8174bf68
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingInfoAddPage.py
@@ -0,0 +1,47 @@
+# 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
+from base import webqtlConfig
+import SharingBody
+import SharingInfo
+
+
+#########################################
+# Sharing Info Edit Page
+#########################################
+class SharingInfoAddPage(templatePage):
+
+ def __init__(self, fd=None):
+ templatePage.__init__(self, fd)
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['admin']:
+ pass
+ else:
+ heading = "Adding Info"
+ detail = ["You don't have the permission to add new dataset"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ self.dict['body'] = SharingBody.sharinginfoedit_body_string % ("Add new dataset", "-1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "")
diff --git a/web/webqtl/dataSharing/SharingInfoDeletePage.py b/web/webqtl/dataSharing/SharingInfoDeletePage.py
new file mode 100755
index 00000000..edc0be7d
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingInfoDeletePage.py
@@ -0,0 +1,55 @@
+# 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
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+import SharingBody
+import SharingInfo
+
+
+#########################################
+# Sharing Info Delete Page
+#########################################
+class SharingInfoDeletePage(templatePage):
+
+ def __init__(self, fd=None):
+ templatePage.__init__(self, fd)
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['admin']:
+ pass
+ else:
+ heading = "Deleting Info"
+ detail = ["You don't have the permission to delete this dataset"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ cursor = webqtlDatabaseFunction.getCursor()
+ if (not cursor):
+ return
+ GN_AccessionId = fd.formdata.getvalue('GN_AccessionId')
+ sql = "delete from InfoFiles where GN_AccesionId=%s"
+ cursor.execute(sql, GN_AccessionId)
+ re = cursor.fetchone()
+ self.dict['body'] = "Delete dataset info record (GN_AccesionId=%s) successfully." % GN_AccessionId \ No newline at end of file
diff --git a/web/webqtl/dataSharing/SharingInfoEditPage.py b/web/webqtl/dataSharing/SharingInfoEditPage.py
new file mode 100755
index 00000000..266b8602
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingInfoEditPage.py
@@ -0,0 +1,51 @@
+# 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
+from base import webqtlConfig
+import SharingBody
+import SharingInfo
+
+
+#########################################
+# Sharing Info Edit Page
+#########################################
+class SharingInfoEditPage(templatePage):
+
+ def __init__(self, fd=None):
+ templatePage.__init__(self, fd)
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['admin']:
+ pass
+ else:
+ heading = "Editing Info"
+ detail = ["You don't have the permission to edit this dataset"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ GN_AccessionId = fd.formdata.getvalue('GN_AccessionId')
+ InfoPageName = fd.formdata.getvalue('InfoPageName')
+ sharingInfoObject = SharingInfo.SharingInfo(GN_AccessionId, InfoPageName)
+ info, filelist = sharingInfoObject.getInfo()
+ self.dict['body'] = SharingBody.sharinginfoedit_body_string % (info[31], info[0], info[11], info[12], info[13], info[14], info[15], info[16], info[17], info[18], info[19], info[20], info[21], info[22], info[6], info[5], info[35], info[36], info[37], info[38], info[39], info[7], info[8], info[9], info[40], info[32], info[31], info[1], info[2], info[3], info[30], info[4], info[10], info[23], info[25], info[33], info[26], info[27], info[28], info[24], info[34], info[41])
diff --git a/web/webqtl/dataSharing/SharingInfoPage.py b/web/webqtl/dataSharing/SharingInfoPage.py
new file mode 100755
index 00000000..230ba2f3
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingInfoPage.py
@@ -0,0 +1,52 @@
+# 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
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+import SharingBody
+import SharingInfo
+
+
+#########################################
+# Sharing Info Page
+#########################################
+class SharingInfoPage(templatePage):
+
+ def __init__(self, fd=None):
+ templatePage.__init__(self, fd)
+ GN_AccessionId = fd.formdata.getvalue('GN_AccessionId')
+ InfoPageName = fd.formdata.getvalue('InfoPageName')
+ cursor = webqtlDatabaseFunction.getCursor()
+ if InfoPageName and not GN_AccessionId:
+ sql = "select GN_AccesionId from InfoFiles where InfoPageName = %s"
+ cursor.execute(sql, InfoPageName)
+ GN_AccessionId = cursor.fetchone()
+ url = webqtlConfig.CGIDIR + "main.py?FormID=sharinginfo&GN_AccessionId=%s" % GN_AccessionId
+ self.redirection = url
+ else:
+ sharingInfoObject = SharingInfo.SharingInfo(GN_AccessionId, InfoPageName)
+ self.dict['body'] = sharingInfoObject.getBody(infoupdate="")
diff --git a/web/webqtl/dataSharing/SharingInfoUpdatePage.py b/web/webqtl/dataSharing/SharingInfoUpdatePage.py
new file mode 100755
index 00000000..a70238b9
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingInfoUpdatePage.py
@@ -0,0 +1,109 @@
+# 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
+
+import MySQLdb
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+import SharingBody
+import SharingInfo
+
+#########################################
+# Sharing Info Update Page
+#########################################
+class SharingInfoUpdatePage(templatePage):
+
+ def __init__(self, fd=None):
+ templatePage.__init__(self, fd)
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['admin']:
+ pass
+ else:
+ heading = "Editing Info"
+ detail = ["You don't have the permission to modify this file"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ cursor = webqtlDatabaseFunction.getCursor()
+ if (not cursor):
+ return
+ Id=fd.formdata.getvalue('Id')
+ GN_AccesionId=fd.formdata.getvalue('GN_AccesionId')
+ GEO_Series=fd.formdata.getvalue('GEO_Series')
+ Status=fd.formdata.getvalue('Status')
+ Title=fd.formdata.getvalue('Title')
+ Organism_Id=fd.formdata.getvalue('Organism_Id')
+ Organism=fd.formdata.getvalue('Organism')
+ Experiment_Type =fd.formdata.getvalue('Experiment_Type')
+ Summary=fd.formdata.getvalue('Summary')
+ Overall_Design=fd.formdata.getvalue('Overall_Design')
+ Contributor=fd.formdata.getvalue('Contributor')
+ Citation=fd.formdata.getvalue('Citation')
+ Submission_Date=fd.formdata.getvalue('Submission_Date')
+ Contact_Name=fd.formdata.getvalue('Contact_Name')
+ Emails=fd.formdata.getvalue('Emails')
+ Phone=fd.formdata.getvalue('Phone')
+ URL=fd.formdata.getvalue('URL')
+ Organization_Name=fd.formdata.getvalue('Organization_Name')
+ Department=fd.formdata.getvalue('Department')
+ Laboratory=fd.formdata.getvalue('Laboratory')
+ Street=fd.formdata.getvalue('Street')
+ City=fd.formdata.getvalue('City')
+ State=fd.formdata.getvalue('State')
+ ZIP=fd.formdata.getvalue('ZIP')
+ Country=fd.formdata.getvalue('Country')
+ Platforms=fd.formdata.getvalue('Platforms')
+ Samples=fd.formdata.getvalue('Samples')
+ Species=fd.formdata.getvalue('Species')
+ Tissue=fd.formdata.getvalue('Tissue')
+ Normalization=fd.formdata.getvalue('Normalization')
+ InbredSet=fd.formdata.getvalue('InbredSet')
+ InfoPageName=fd.formdata.getvalue('InfoPageName')
+ InfoPageTitle=fd.formdata.getvalue('InfoPageTitle')
+ About_Cases=fd.formdata.getvalue('About_Cases')
+ About_Tissue=fd.formdata.getvalue('About_Tissue')
+ About_Download=fd.formdata.getvalue('About_Download')
+ About_Array_Platform=fd.formdata.getvalue('About_Array_Platform')
+ About_Data_Values_Processing=fd.formdata.getvalue('About_Data_Values_Processing')
+ Data_Source_Acknowledge=fd.formdata.getvalue('Data_Source_Acknowledge')
+ AuthorizedUsers=fd.formdata.getvalue('AuthorizedUsers')
+ Progress=fd.formdata.getvalue('Progress')
+ if Id=='-1':
+ sharingInfoObject = SharingInfo.SharingInfo(GN_AccesionId, InfoPageName)
+ info, filelist = sharingInfoObject.getInfo()
+ if info:
+ heading = "Editing Info"
+ detail = ["The new dataset info record is duplicate."]
+ self.error(heading=heading, detail=detail, error="Error")
+ return
+ sql = """INSERT INTO InfoFiles SET GN_AccesionId=%s, GEO_Series=%s, Status=%s, Title=%s, Organism_Id=%s, Organism=%s, Experiment_Type=%s, Summary=%s, Overall_Design=%s, Contributor=%s, Citation=%s, Submission_Date=%s, Contact_Name=%s, Emails=%s, Phone=%s, URL=%s, Organization_Name=%s, Department=%s, Laboratory=%s, Street=%s, City=%s, State=%s, ZIP=%s, Country=%s, Platforms=%s, Samples=%s, Species=%s, Tissue=%s, Normalization=%s, InbredSet=%s, InfoPageName=%s, InfoPageTitle=%s, About_Cases=%s, About_Tissue=%s, About_Download=%s, About_Array_Platform=%s, About_Data_Values_Processing=%s, Data_Source_Acknowledge=%s, AuthorizedUsers=%s, Progreso=%s"""
+ cursor.execute(sql, tuple([GN_AccesionId, GEO_Series, Status, Title, Organism_Id, Organism, Experiment_Type, Summary, Overall_Design, Contributor, Citation, Submission_Date, Contact_Name, Emails, Phone, URL, Organization_Name, Department, Laboratory, Street, City, State, ZIP, Country, Platforms, Samples, Species, Tissue, Normalization, InbredSet, InfoPageName, InfoPageTitle, About_Cases, About_Tissue, About_Download, About_Array_Platform, About_Data_Values_Processing, Data_Source_Acknowledge, AuthorizedUsers, Progress]))
+ infoupdate="This record has been succesfully added."
+ else:
+ sql = """UPDATE InfoFiles SET GN_AccesionId=%s, GEO_Series=%s, Status=%s, Title=%s, Organism_Id=%s, Organism=%s, Experiment_Type=%s, Summary=%s, Overall_Design=%s, Contributor=%s, Citation=%s, Submission_Date=%s, Contact_Name=%s, Emails=%s, Phone=%s, URL=%s, Organization_Name=%s, Department=%s, Laboratory=%s, Street=%s, City=%s, State=%s, ZIP=%s, Country=%s, Platforms=%s, Samples=%s, Species=%s, Tissue=%s, Normalization=%s, InbredSet=%s, InfoPageName=%s, InfoPageTitle=%s, About_Cases=%s, About_Tissue=%s, About_Download=%s, About_Array_Platform=%s, About_Data_Values_Processing=%s, Data_Source_Acknowledge=%s, AuthorizedUsers=%s, Progreso=%s WHERE Id=%s"""
+ cursor.execute(sql, tuple([GN_AccesionId, GEO_Series, Status, Title, Organism_Id, Organism, Experiment_Type, Summary, Overall_Design, Contributor, Citation, Submission_Date, Contact_Name, Emails, Phone, URL, Organization_Name, Department, Laboratory, Street, City, State, ZIP, Country, Platforms, Samples, Species, Tissue, Normalization, InbredSet, InfoPageName, InfoPageTitle, About_Cases, About_Tissue, About_Download, About_Array_Platform, About_Data_Values_Processing, Data_Source_Acknowledge, AuthorizedUsers, Progress, Id]))
+ infoupdate="This record has been succesfully updated."
+ sharingInfoObject = SharingInfo.SharingInfo(GN_AccesionId, InfoPageName)
+ self.dict['body'] = sharingInfoObject.getBody(infoupdate=infoupdate) \ No newline at end of file
diff --git a/web/webqtl/dataSharing/SharingListDataSetPage.py b/web/webqtl/dataSharing/SharingListDataSetPage.py
new file mode 100755
index 00000000..ec90f5f3
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingListDataSetPage.py
@@ -0,0 +1,99 @@
+#
+# 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 htmlgen import HTMLgen2 as HT
+from base import webqtlConfig
+
+from base.templatePage import templatePage
+
+
+#########################################
+# Sharing List DataSet Page
+#########################################
+class SharingListDataSetPage(templatePage):
+
+ def __init__(self, fd=None):
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['admin']:
+ pass
+ else:
+ heading = "Editing Info"
+ detail = ["You don't have the permission to list the datasets"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ query = """select GN_AccesionId, InfoPageTitle, Progreso from InfoFiles order by GN_AccesionId"""
+ self.cursor.execute(query)
+ result = self.cursor.fetchall()
+
+ heading = HT.Paragraph('Dataset Table', Class="title")
+
+ newrecord = HT.Href(text="New Record", url="/webqtl/main.py?FormID=sharinginfoadd")
+
+ info = "Click the accession id to view the dataset info. Click the dataset name to edit the dataset info."
+
+ datasetTable = HT.TableLite(border=0, cellpadding=0, cellspacing=0, Class="collap", width="100%")
+
+ tableHeaderRow = HT.TR()
+ tableHeaderRow.append(HT.TD("Accession Id", Class='fs14 fwb ffl b1 cw cbrb', align="center"))
+ tableHeaderRow.append(HT.TD("Dataset name", Class='fs14 fwb ffl b1 cw cbrb', align="center"))
+ tableHeaderRow.append(HT.TD("Progress", Class='fs14 fwb ffl b1 cw cbrb', align="center"))
+ tableHeaderRow.append(HT.TD("Operation", Class='fs14 fwb ffl b1 cw cbrb', align="center"))
+ datasetTable.append(tableHeaderRow)
+
+ for one_row in result:
+ Accession_Id, InfoPage_title, Progress = one_row
+ datasetRow = HT.TR()
+ datasetRow.append(HT.TD(HT.Href(text="GN%s" % Accession_Id, url="/webqtl/main.py?FormID=sharinginfo&GN_AccessionId=%s" % Accession_Id, Class='fs12 fwn'), Class="fs12 fwn b1 c222"))
+ datasetRow.append(HT.TD(HT.Href(text="%s" % InfoPage_title, url="/webqtl/main.py?FormID=sharinginfo&GN_AccessionId=%s" % Accession_Id, Class='fs12 fwn'), Class="fs12 fwn b1 c222"))
+ datasetRow.append(HT.TD("%s" % Progress, Class='fs12 fwn ffl b1 c222'))
+ operation_edit = HT.Href(text="Edit", url="/webqtl/main.py?FormID=sharinginfoedit&GN_AccessionId=%s" % Accession_Id)
+ operation_delete = HT.Href(text="Delete", onClick="deleteRecord(%s); return false;" % Accession_Id)
+ operation = HT.TD(Class="fs12 fwn b1 c222", align="center")
+ operation.append(operation_edit)
+ operation.append("&nbsp;&nbsp;&nbsp;&nbsp;")
+ operation.append(operation_delete)
+ datasetRow.append(operation)
+ datasetTable.append(datasetRow)
+
+ TD_LR.append(heading, HT.P(), newrecord, HT.P(), info, HT.P(), datasetTable)
+
+ js1 = """ <script language="javascript" type="text/javascript">
+ function deleteRecord(id){
+ question = confirm("Are you sure you want to delete the dataset info record (Accession Id="+id+")?")
+ if (question != "0"){
+ window.open("/webqtl/main.py?FormID=sharinginfodelete&GN_AccessionId="+id, "_self");
+ }
+ }
+ </script>"""
+ self.dict['js1'] = js1
+ self.dict['body'] = str(TD_LR) \ No newline at end of file
diff --git a/web/webqtl/dataSharing/SharingPage.py b/web/webqtl/dataSharing/SharingPage.py
new file mode 100755
index 00000000..cf1d9ac3
--- /dev/null
+++ b/web/webqtl/dataSharing/SharingPage.py
@@ -0,0 +1,40 @@
+# 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 SharingBody
+
+#########################################
+# SharingPage
+#########################################
+
+class SharingPage(templatePage):
+
+ def __init__(self, fd):
+ templatePage.__init__(self, fd)
+ self.dict['title'] = 'GeneNetwork Data Sharing Zone'
+ self.dict['body'] = SharingBody.sharing_body_string
+ self.dict['js2'] = 'onload="javascript:initialDatasetSelection();"' \ No newline at end of file
diff --git a/web/webqtl/dataSharing/__init__.py b/web/webqtl/dataSharing/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/dataSharing/__init__.py
diff --git a/web/webqtl/dbFunction/__init__.py b/web/webqtl/dbFunction/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/dbFunction/__init__.py
diff --git a/web/webqtl/dbFunction/webqtlDatabaseFunction.py b/web/webqtl/dbFunction/webqtlDatabaseFunction.py
new file mode 100755
index 00000000..772e0526
--- /dev/null
+++ b/web/webqtl/dbFunction/webqtlDatabaseFunction.py
@@ -0,0 +1,265 @@
+# 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 Xiaodong Zhou 2011/Jan/20
+
+#webqtlDatabaseFunction.py
+#
+#This file consists of various database related functions; the names are generally self-explanatory.
+
+import MySQLdb
+import string
+from base import webqtlConfig
+
+###########################################################################
+#output: cursor instance
+#function: connect to database and return cursor instance
+###########################################################################
+def getCursor():
+ try:
+ con = MySQLdb.Connect(db=webqtlConfig.DB_NAME, host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER, passwd=webqtlConfig.DB_PASSWD)
+ cursor = con.cursor()
+ return cursor
+ except:
+ return None
+
+
+
+###########################################################################
+#input: cursor, groupName (string)
+#output: mappingMethodId (int) info, value will be Null or else
+#function: retrieve mappingMethodId info from InbredSet table
+###########################################################################
+
+def getMappingMethod(cursor=None, groupName=None):
+ cursor.execute("select MappingMethodId from InbredSet where Name= '%s'" % groupName)
+ mappingMethodId = cursor.fetchone()[0]
+ return mappingMethodId
+
+###########################################################################
+#input: cursor, inbredSetId (int), strainId (int)
+#output: isMappingId (bull) info, value will be 0,1,2 or else, 0 or Null means
+# "can not do mapping", >0 means "can do mapping", >1 means "there exsists
+# redundant data, user needs to choose one to do mapping function"
+#function: retrieve isMappingId info from StrainXRef table
+###########################################################################
+
+def isMapping(cursor=None, inbredSetId=None, strainId=None):
+ cursor.execute("select IsMapping from StrainXRef where InbredSetId='%d' and StrainId = '%d'" %(inbredSetId, strainId))
+ isMappingId = cursor.fetchone()[0]
+ return isMappingId
+
+###########################################################################
+#input: cursor, groupName (string)
+#output: all species data info (array), value will be Null or else
+#function: retrieve all species info from Species table
+###########################################################################
+
+def getAllSpecies(cursor=None):
+ cursor.execute("select Id, Name, MenuName, FullName, TaxonomyId,OrderId from Species Order by OrderId")
+ allSpecies = cursor.fetchall()
+ return allSpecies
+
+###########################################################################
+#input: cursor, RISet (string)
+#output: specie's name (string), value will be None or else
+#function: retrieve specie's name info based on RISet
+###########################################################################
+
+def retrieveSpecies(cursor=None, RISet=None):
+ try:
+ cursor.execute("select Species.Name from Species, InbredSet where InbredSet.Name = '%s' and InbredSet.SpeciesId = Species.Id" % RISet)
+ return cursor.fetchone()[0]
+ except:
+ return None
+
+###########################################################################
+#input: cursor, RISet (string)
+#output: specie's Id (string), value will be None or else
+#function: retrieve specie's Id info based on RISet
+###########################################################################
+
+def retrieveSpeciesId(cursor=None, RISet=None):
+ try:
+ cursor.execute("select SpeciesId from InbredSet where Name = '%s'" % RISet)
+ return cursor.fetchone()[0]
+ except:
+ return None
+
+###########################################################################
+# input: cursor
+# output: tissProbeSetFreezeIdList (list),
+# nameList (list),
+# fullNameList (list)
+# function: retrieve all TissueProbeSetFreezeId,Name,FullName info
+# from TissueProbeSetFreeze table.
+# These data will listed in the dropdown menu in the first page of Tissue Correlation
+###########################################################################
+
+def getTissueDataSet(cursor=None):
+ tissProbeSetFreezeIdList=[]
+ nameList =[]
+ fullNameList = []
+
+ query = "select Id,Name,FullName from TissueProbeSetFreeze; "
+ try:
+ cursor.execute(query)
+ result = cursor.fetchall()
+
+ for row in result:
+ tissProbeSetFreezeIdList.append(row[0])
+ nameList.append(row[1])
+ fullNameList.append(row[2])
+ except:
+ return None
+
+ return tissProbeSetFreezeIdList,nameList,fullNameList
+
+###########################################################################
+# input: cursor,GeneSymbol (string), and TissueProbeSetFreezeId (string)
+# output: geneId (string), dataId (string)
+# function: retrieve geneId and DataId from TissueProbeSetXRef table
+###########################################################################
+
+def getGeneIdDataIdForTissueBySymbol(cursor=None, GeneSymbol=None, TissueProbeSetFreezeId= 0):
+ query ="select GeneId, DataId from TissueProbeSetXRef where Symbol = '%s' and TissueProbeSetFreezeId=%s order by Mean desc" %(GeneSymbol,TissueProbeSetFreezeId)
+ try:
+ cursor.execute(query)
+ result = cursor.fetchone()
+ geneId = result[0]
+ dataId = result[1]
+ except:
+ geneId = 0
+ dataId = 0
+
+ return geneId,dataId
+
+###########################################################################
+# input: cursor, TissueProbeSetFreezeId (int)
+# output: chipId (int)
+# function: retrieve chipId from TissueProbeFreeze table
+###########################################################################
+
+def getChipIdByTissueProbeSetFreezeId(cursor=None, TissueProbeSetFreezeId=None):
+ query = "select TissueProbeFreezeId from TissueProbeSetFreeze where Id =%s" % TissueProbeSetFreezeId
+ try:
+ cursor.execute(query)
+ result = cursor.fetchone()
+ TissueProbeFreezeId = result[0]
+ except:
+ TissueProbeFreezeId =0
+
+ query1 = "select ChipId from TissueProbeFreeze where Id =%s" % TissueProbeFreezeId
+ try:
+ cursor.execute(query1)
+ result1 = cursor.fetchone()
+ chipId = result1[0]
+ except:
+ chipId =0
+
+ return chipId
+
+###########################################################################
+# input: cursor, TissueProbeSetFreezeId (int)
+# output: TissueCount (int)
+# function: retrieve how many tissue used in the specific dataset based on TissueProbeSetFreezeId
+###########################################################################
+def getTissueCountByTissueProbeSetFreezeId(cursor=None, TissueProbeSetFreezeId=None):
+ query1 ="select DataId from TissueProbeSetXRef where TissueProbeSetFreezeId =%s limit 1" % TissueProbeSetFreezeId
+ try:
+ cursor.execute(query1)
+ result1 = cursor.fetchone()
+ DataId = result1[0]
+
+ query2 =" select count(*) from TissueProbeSetData where Id=%s" % DataId
+ try:
+ cursor.execute(query2)
+ result2 = cursor.fetchone()
+ TissueCount = result2[0]
+ except:
+ TissueCount =0
+ except:
+ TissueCount =0
+
+ return TissueCount
+
+###########################################################################
+# input: cursor, TissueProbeSetFreezeId (int)
+# output: DatasetName(string),DatasetFullName(string)
+# function: retrieve DatasetName, DatasetFullName based on TissueProbeSetFreezeId
+###########################################################################
+def getDatasetNamesByTissueProbeSetFreezeId(cursor=None, TissueProbeSetFreezeId=None):
+ query ="select Name, FullName from TissueProbeSetFreeze where Id=%s" % TissueProbeSetFreezeId
+ try:
+ cursor.execute(query)
+ result = cursor.fetchone()
+ DatasetName = result[0]
+ DatasetFullName =result[1]
+ except:
+ DatasetName =None
+ DatasetFullName =None
+
+ return DatasetName, DatasetFullName
+
+###########################################################################
+# input: cursor, geneIdLst (list)
+# output: geneIdSymbolPair(dict),key is geneId, value is geneSymbol
+# function: retrieve GeneId, GeneSymbol based on geneId List
+###########################################################################
+def getGeneIdSymbolPairByGeneId(cursor=None, geneIdLst =None):
+ geneIdSymbolPair={}
+ for geneId in geneIdLst:
+ geneIdSymbolPair[geneId]=None
+
+ query ="select GeneId,GeneSymbol from GeneList where GeneId in (%s)" % string.join(geneIdLst, ", ")
+ try:
+ cursor.execute(query)
+ results = cursor.fetchall()
+ for item in results:
+ geneId =item[0]
+ geneSymbol =item[1]
+ geneIdSymbolPair[geneId]=geneSymbol
+ except:
+ geneIdSymbolPair=None
+
+ return geneIdSymbolPair
+
+
+def updateTissueProbesetXRefByProbesetId(cursor=None, probesetId=None):
+ query ="select Symbol,GeneId,Chr,Mb,description, Probe_Target_Description from ProbeSet where Id =%s"%probesetId
+ try:
+ cursor.execute(query)
+ result =cursor.fetchone()
+
+ updateQuery ='''
+ Update TissueProbeSetXRef
+ Set Symbol='%s',GeneId='%s', Chr='%s', Mb='%s', description ='%s',Probe_Target_Description='%s'
+ where ProbesetId=%s
+ '''%(result[0],result[1],result[2],result[3],result[4],result[5],probesetId)
+
+ cursor.execute(updateQuery)
+
+ except:
+ return None
+ \ No newline at end of file
diff --git a/web/webqtl/externalResource/GCATPage.py b/web/webqtl/externalResource/GCATPage.py
new file mode 100755
index 00000000..7e22f168
--- /dev/null
+++ b/web/webqtl/externalResource/GCATPage.py
@@ -0,0 +1,101 @@
+# 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
+
+#GCATPage.py
+
+from htmlgen import HTMLgen2 as HT
+
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+
+
+#Implemented by Xiaodong
+class GCATPage(templatePage):
+
+ def __init__(self,fd):
+
+ self.theseTraits = []
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="middle")
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ self.searchResult = fd.formdata.getvalue('searchResult', [])
+ if type("1") == type(self.searchResult):
+ self.searchResult = [self.searchResult]
+
+ for item in self.searchResult:
+ try:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo(QTL=1)
+ if thisTrait.db.type == "ProbeSet":
+ self.theseTraits.append(thisTrait)
+ except:
+ pass
+
+ if self.theseTraits:
+ pass
+ else:
+ templatePage.__init__(self, fd)
+ heading = 'GCAT'
+ detail = ['You need to select at least one microarray trait to submit to GCAT.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ geneSymbolList = self.getGeneSymbolList()
+
+ geneSymbolSet = set(geneSymbolList)
+
+ if ( len(geneSymbolSet) < 500 ):
+ temp = '+'.join(geneSymbolSet)
+ GCATurl = "http://binf1.memphis.edu/gcat/?organism=mouse&subset=all&year=2010&geneInput=%s" % temp
+
+ self.dict['js1'] = """
+ <SCRIPT LANGUAGE="JavaScript">
+ setTimeout( 'window.location = "%s"', 2000 );
+ </SCRIPT>
+ """ % GCATurl
+
+ TD_LR.append(HT.Paragraph("Your selection of %d genes is being submitted to GCAT" % len(geneSymbolSet), Class="cr fs16 fwb", align="Center"))
+ else:
+ TD_LR.append(HT.Paragraph("Your selection of %d genes exceeds the limit of 500. Please reduce your gene number to below the limit." % len(geneSymbolSet), Class="cr fs16 fwb", align="Center"))
+
+
+ self.dict['body'] = TD_LR
+
+
+ def getGeneSymbolList(self):
+ geneList = []
+
+ for item in self.theseTraits:
+ item.retrieveInfo()
+ geneList.append(str(item.symbol))
+
+ return geneList
+
+
diff --git a/web/webqtl/externalResource/GoTreePage.py b/web/webqtl/externalResource/GoTreePage.py
new file mode 100755
index 00000000..07144a23
--- /dev/null
+++ b/web/webqtl/externalResource/GoTreePage.py
@@ -0,0 +1,154 @@
+#GoTreePage.py
+
+import string
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from dbFunction import webqtlDatabaseFunction
+
+
+#########################################
+# GoTree Page
+#########################################
+class GoTreePage(templatePage):
+
+ def __init__(self,fd):
+
+ self.theseTraits = []
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="middle")
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ self.searchResult = fd.formdata.getvalue('searchResult', [])
+ if type("1") == type(self.searchResult):
+ self.searchResult = [self.searchResult]
+
+ #XZ, self.theseTraits holds the "ProbeSet" traits.
+
+ for item in self.searchResult:
+ try:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo(QTL=1)
+ if thisTrait.db.type == "ProbeSet":
+ self.theseTraits.append(thisTrait)
+ except:
+ pass
+
+ if self.theseTraits:
+ pass
+ else:
+ templatePage.__init__(self, fd)
+ heading = 'WebGestalt'
+ detail = ['You need to select at least one microarray trait to submit.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ chipName = self.testChip(fd)
+
+ #XZ, 8/24/2009: the name of arraylist is misleading. It holds the name of traits.
+ arraylist, geneIdList = self.genGeneIdList(fd)
+
+ target_url = "http://bioinfo.vanderbilt.edu/webgestalt/webgestalt.php"
+
+ formWebGestalt = HT.Form(cgi=target_url, enctype='multipart/form-data', name='WebGestalt', submit = HT.Input(type='hidden'))
+
+ id_type = chipName
+
+ hddnWebGestalt = {'id_list':string.join(arraylist, ","),
+ 'id_type':id_type}
+
+ hddnWebGestalt['ref_type'] = hddnWebGestalt['id_type']
+ hddnWebGestalt['analysis_type'] = 'GO'
+ hddnWebGestalt['significancelevel'] = 'Top10'
+ hddnWebGestalt['stat'] = 'Hypergeometric'
+ hddnWebGestalt['mtc'] = 'BH'
+ hddnWebGestalt['min'] = '2'
+ hddnWebGestalt['id_value'] = fd.formdata.getvalue('correlation')
+
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+
+ if species == 'rat':
+ hddnWebGestalt['org'] = 'Rattus norvegicus'
+ elif species == 'human':
+ hddnWebGestalt['org'] = 'Homo sapiens'
+ elif species == 'mouse':
+ hddnWebGestalt['org'] = 'Mus musculus'
+ else:
+ hddnWebGestalt['org'] = ''
+
+ hddnWebGestalt['org'] = hddnWebGestalt['org'].replace(' ','_')
+
+ for key in hddnWebGestalt.keys():
+ formWebGestalt.append(HT.Input(name=key, value=hddnWebGestalt[key], type='hidden'))
+
+ TD_LR.append(formWebGestalt)
+
+ TD_LR.append(HT.Paragraph("Your selection of %d traits is being submitted to GO Tree" % len(self.theseTraits), Class="cr fs16 fwb", align="Center"))
+
+ # updated by NL, moved mixedChipError() to webqtl.js and change it to mixedChipError(methodName)
+ # moved unknownChipError() to webqtl.js and change it to unknownChipError(chipName)
+ if chipName == 'mixed':
+ methodName = "WebGestalt"
+ self.dict['js1'] = """
+ <SCRIPT LANGUAGE="JavaScript">
+ setTimeout("mixedChipError('%s')" ,1000);
+ </SCRIPT>
+ """ % methodName
+ elif chipName.find('_NA') > 0:
+ chipName = chipName[0:-3]
+ self.dict['js1'] = """
+ <SCRIPT LANGUAGE="JavaScript">
+ setTimeout("unknownChipError('%s')",1000);
+ </SCRIPT>
+ """ % chipName
+ else:
+ self.dict['js1'] = """
+ <SCRIPT LANGUAGE="JavaScript">
+ setTimeout('document.WebGestalt.submit()',1000);
+ </SCRIPT>
+ """
+
+ self.dict['body'] = TD_LR
+
+ def testChip(self, fd):
+ chipName0 = ""
+
+ for item in self.theseTraits:
+ self.cursor.execute('SELECT GeneChip.GO_tree_value FROM GeneChip, ProbeFreeze, ProbeSetFreeze WHERE GeneChip.Id = ProbeFreeze.ChipId and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Name = "%s"' % item.db.name)
+ result = self.cursor.fetchone()
+ if result:
+ chipName = result[0]
+ if chipName:
+ if chipName != chipName0:
+ if chipName0:
+ return 'mixed'
+ else:
+ chipName0 = chipName
+ else:
+ pass
+ else:
+ self.cursor.execute('SELECT GeneChip.Name FROM GeneChip, ProbeFreeze, ProbeSetFreeze WHERE GeneChip.Id = ProbeFreeze.ChipId and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Name = "%s"' % item.db.name)
+ result = self.cursor.fetchone()
+ chipName = '%s_NA' % result[0]
+ return chipName
+ else:
+ self.cursor.execute('SELECT GeneChip.Name FROM GeneChip, ProbeFreeze, ProbeSetFreeze WHERE GeneChip.Id = ProbeFreeze.ChipId and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Name = "%s"' % item.db.name)
+ result = self.cursor.fetchone()
+ chipName = '%s_NA' % result[0]
+ return chipName
+ return chipName
+
+ def genGeneIdList(self, fd):
+ arrayList = []
+ geneList = []
+ for item in self.theseTraits:
+ arrayList.append(item.name)
+ item.retrieveInfo()
+ geneList.append(str(item.geneid))
+ return arrayList, geneList
+
diff --git a/web/webqtl/externalResource/ODEPage.py b/web/webqtl/externalResource/ODEPage.py
new file mode 100755
index 00000000..f02fe5aa
--- /dev/null
+++ b/web/webqtl/externalResource/ODEPage.py
@@ -0,0 +1,143 @@
+# 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
+
+#ODEPage.py
+
+import string
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from dbFunction import webqtlDatabaseFunction
+
+class ODEPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ #XZ, self.theseTraits holds the "ProbeSet" traits.
+ self.theseTraits = []
+
+ self.searchResult = fd.formdata.getvalue('searchResult', [])
+ if type("1") == type(self.searchResult):
+ self.searchResult = [self.searchResult]
+
+ for item in self.searchResult:
+ try:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo(QTL=1)
+ if thisTrait.db.type == "ProbeSet":
+ self.theseTraits.append(thisTrait)
+ except:
+ pass
+
+ if self.theseTraits:
+ pass
+ else:
+ heading = 'ODE'
+ detail = ['You need to select at least one microarray trait to submit.']
+ self.error(heading=heading,detail=detail)
+ return
+
+ chipName = self.getChipName(fd)
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+
+ if species == 'rat':
+ species = 'Rattus norvegicus'
+ elif species == 'human':
+ species = 'Homo sapiens'
+ elif species == 'mouse':
+ species = 'Mus musculus'
+ else:
+ species = ''
+
+ probesetNameList = self.getProbesetNameList(fd)
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="middle")
+
+ formODE = HT.Form(cgi="http://ontologicaldiscovery.org/index.php?action=manage&cmd=importGeneSet", enctype='multipart/form-data', name='formODE', submit = HT.Input(type='hidden'))
+
+ hddnODE = {}
+
+ hddnODE['client'] = 'genenetwork'
+ hddnODE['species'] = species
+ hddnODE['idtype'] = chipName
+ hddnODE['list'] = string.join(probesetNameList, ",")
+
+ for key in hddnODE.keys():
+ formODE.append(HT.Input(name=key, value=hddnODE[key], type='hidden'))
+
+ TD_LR.append(formODE)
+
+ TD_LR.append(HT.Paragraph("Your selections of %d traits is being exported to the ODE" % len(self.theseTraits), Class="cr fs16 fwb", align="Center"))
+ # updated by NL, moved mixedChipError() to webqtl.js and change it to mixedChipError(methodName)
+ if chipName == 'mixed':
+ methodName = "ODE"
+ self.dict['js1'] = """
+ <SCRIPT LANGUAGE="JavaScript">
+ setTimeout("mixedChipError('%s')",1000);
+ </SCRIPT>
+ """ % methodName
+ else:
+ self.dict['js1'] = """
+ <SCRIPT LANGUAGE="JavaScript">
+ setTimeout('document.formODE.submit()',1000);
+ </SCRIPT>
+ """
+
+ self.dict['body'] = TD_LR
+
+
+
+ def getProbesetNameList(self, fd):
+ probesetNameList = []
+
+ for item in self.theseTraits:
+ probesetNameList.append(item.name)
+
+ return probesetNameList
+
+
+
+ def getChipName(self, fd):
+ chipName0 = ""
+ for item in self.theseTraits:
+ self.cursor.execute('SELECT GeneChip.Name FROM GeneChip, ProbeFreeze, ProbeSetFreeze WHERE GeneChip.Id = ProbeFreeze.ChipId and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Name = "%s"' % item.db.name)
+ chipName = self.cursor.fetchone()[0]
+ if chipName != chipName0:
+ if chipName0:
+ return 'mixed'
+ else:
+ chipName0 = chipName
+ else:
+ pass
+
+ return chipName
diff --git a/web/webqtl/externalResource/__init__.py b/web/webqtl/externalResource/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/externalResource/__init__.py
diff --git a/web/webqtl/geneWiki/AddGeneRIFPage.py b/web/webqtl/geneWiki/AddGeneRIFPage.py
new file mode 100755
index 00000000..0a5038ef
--- /dev/null
+++ b/web/webqtl/geneWiki/AddGeneRIFPage.py
@@ -0,0 +1,635 @@
+# 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
+
+#geneWikiPage.py
+#
+#This one's pretty self-evident from the title. If you use the GeneWiki module, this is what's behind it. -KA
+
+# Xiaodong changed the dependancy structure
+
+import glob
+import re
+import piddle as pid
+from htmlgen import HTMLgen2 as HT
+import os
+import string
+
+from utility import Plot
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+#########################################
+# Gene Wiki Page
+#########################################
+
+class AddGeneRIFPage(templatePage):
+
+ fields = ['species', 'pubmedid', 'weburl', 'comment', 'email', 'initial', 'genecategory']
+ spliter = "__split__"
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.updMysql():
+ return
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+ self.privilege_to_delete_entry = 1
+ self.additional_colspan = 1
+ else:
+ self.privilege_to_delete_entry = 0
+ self.additional_colspan = 0
+
+ #read input fields
+ self.action = fd.formdata.getvalue("action", "disp").strip()
+ self.symbol = fd.formdata.getvalue("symbol", "").strip()
+ self.Id = fd.formdata.getvalue("Id")
+ self.comment = fd.formdata.getvalue("comment", "").strip()
+ self.email = fd.formdata.getvalue("email", "").strip()
+ self.pubmedid = fd.formdata.getvalue("pubmedid", "").strip()
+ self.species = fd.formdata.getvalue("species", "no specific species:0").strip()
+ self.genecategory = fd.formdata.getvalue("genecategory")
+ self.initial = fd.formdata.getvalue("initial", "").strip()
+ self.weburl = fd.formdata.getvalue("weburl", "").strip()
+ self.reason = fd.formdata.getvalue("reason", "").strip()
+
+ #self.dict['title'] = 'Add GeneWiki Entries for %s' % self.symbol
+
+ if not self.symbol:
+ self.content_type = 'text/html'
+ Heading = HT.Paragraph("GeneWiki Entries", Class="title")
+ help1 = HT.Href(url="/GeneWikihelp.html", text=" help document", Class="fwn", target="_blank")
+ Intro = HT.Blockquote("GeneWiki enables you to enrich the annotation of genes and transcripts. Please submit or edit a GeneWiki note (500 characters max) related to a gene, its transcripts, or proteins. When possible include PubMed identifiers or web resource links (URL addresses). Please ensure that the additions will have widespread use. For additional information, check the GeneWiki ", help1, ".")
+
+ Intro.append(HT.P(), "Please enter a gene symbol in the box below and then click submit.")
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='addgenerif',submit=HT.Input(type='hidden'))
+ form.append(HT.Input(type="text", size = 45, maxlength=100, name="symbol"))
+ form.append(HT.Input(type="hidden", name="FormID", value="geneWiki"))
+ form.append(HT.Input(type="submit", name="submit", value="submit", Class="button"))
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
+ TD_LR.append(Heading,Intro,HT.Center(form))
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = "Gene Wiki"
+ elif self.action == 'disp':
+ self.content_type = 'text/html'
+ self.dispWikiPage(fd)
+ elif self.action in ('add', 'update'):
+ if self.action == 'update':
+ self.cursor.execute("Select Id from GeneRIF where symbol='%s' and Id = %s and versionId=0" % (self.symbol, self.Id))
+ if not self.cursor.fetchall():
+ print 'Content-type: text/html\n'
+ heading = "Update Entry"
+ detail = ["The Entry cannot be located."]
+ self.error(heading=heading,detail=detail,error="Error")
+ self.write()
+ return
+ else:
+ pass
+ else:
+ pass
+ status = fd.formdata.getvalue('curStatus')
+ if status == 'insertResult':
+ i = self.insertResultPage(fd)
+ if i == 0:
+ self.content_type = 'text/html'
+ self.insertUpdateCheck(fd, "You entered wrong password, Please try again")
+ elif i == 2:
+ #prevent re-submit
+ url = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE) + "?FormID=geneWiki&symbol=%s" % self.symbol
+ self.redirection = url
+ return
+ else:
+ self.content_type = 'text/html'
+ pass
+ elif status == 'insertCheck':
+ self.content_type = 'text/html'
+ self.insertUpdateCheck(fd)
+ else:
+ self.content_type = 'text/html'
+ self.insertUpdateForm(fd)
+ elif self.action == 'del':
+ if self.Id:
+ try:
+ self.Id= int(self.Id)
+ self.delRIF()
+ except:
+ pass
+ self.redirection = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE) + "?FormID=geneWiki&symbol=%s" % self.symbol
+ return
+ elif self.action == 'history':
+ self.content_type = 'text/html'
+ self.cursor.execute("Select Id from GeneRIF where symbol='%s' and Id = %s and versionId=0" % (self.symbol, self.Id))
+ if not self.cursor.fetchall():
+ heading = "Update Entry"
+ detail = ["The Entry cannot be located."]
+ self.error(heading=heading,detail=detail,error="Error")
+ else:
+ pass
+ self.historyPage(fd)
+ else:
+ self.content_type = 'text/html'
+ pass
+
+ def historyPage(self, fd):
+ self.dict['title'] = "GeneWiki Entry History"
+ title = HT.Paragraph(self.dict['title'], Class= "title")
+
+ subtitle1 = HT.Blockquote("Most Recent Version:", Class="subtitle")
+ self.cursor.execute("select GeneRIF.Id, versionId, symbol, PubMed_ID, Species.Name, comment, createtime, weburl, reason from GeneRIF left Join Species on GeneRIF.SpeciesId = Species.Id Where GeneRIF.Id = %s and versionId = 0" % self.Id)
+ results = self.cursor.fetchone()
+ subtitle1.append(HT.Blockquote(self.genTable(results)))
+
+ subtitle2 = HT.Blockquote("Previous Version:", Class="subtitle")
+ self.cursor.execute("select GeneRIF.Id, versionId, symbol, PubMed_ID, Species.Name, comment, createtime, weburl, reason from GeneRIF Left Join Species on GeneRIF.SpeciesId = Species.Id Where GeneRIF.Id = %s and versionId > 0 order by versionId desc" % self.Id)
+ results = self.cursor.fetchall()
+ if results:
+ for item in results:
+ subtitle2.append(HT.Blockquote(self.genTable(item), HT.P()))
+ else:
+ subtitle2.append(HT.Blockquote("No Previous History"))
+
+ TD_LR = HT.TD(valign="top", bgcolor="#eeeeee")
+
+ TD_LR.append(title, subtitle1, subtitle2)
+ self.dict['body'] = TD_LR
+
+ def genTable(self, results):
+ if not results:
+ return ""
+ Id, versionId, symbol, PubMed_ID, Species_Name, comment, createtime, weburl, reason = results
+ if not Species_Name:
+ Species_Name="no specific species"
+ tbl = HT.TableLite(border=0, cellpadding=5, Class="collap ffv")
+
+ tbl.append(HT.TR(
+ HT.TD("Gene Symbol: ", width = 200, Class="fs13 fwb b1 c222"),
+ HT.TD(self.symbol, width = 600, Class="fs13 b1 c222"),
+ ))
+
+ tbl.append(HT.TR(
+ HT.TD("Species: ", width = 200, Class="fs13 fwb b1 c222"),
+ HT.TD(Species_Name, width = 600, Class="fs13 b1 c222")
+ ))
+ if PubMed_ID:
+ PubMed_ID = PubMed_ID.split()
+ pTD = HT.TD(Class="fs13 b1 c222")
+ for item in PubMed_ID:
+ pTD.append(HT.Href(text=item, target = "_blank",
+ url = webqtlConfig.PUBMEDLINK_URL % item, Class="fwn"), " ")
+ tbl.append(HT.TR(
+ HT.TD("PubMed IDs: ", Class="fs13 fwb b1 c222"),
+ pTD
+ ))
+
+ if weburl:
+ tbl.append(HT.TR(
+ HT.TD("Web URL: ", Class="fs13 fwb b1 c222"),
+ HT.TD(HT.Href(text=weburl, url=weburl, Class='fwn'), Class="fs13 b1 c222")
+ ))
+
+ tbl.append(HT.TR(
+ HT.TD("Entry: ", Class="fs13 fwb b1 c222"),
+ HT.TD(comment, Class="fs13 b1 c222")
+ ))
+
+ self.cursor.execute("select GeneCategory.Name from GeneCategory, GeneRIFXRef where GeneRIFXRef.GeneRIFId = %s and GeneRIFXRef.versionId=%s and GeneRIFXRef.GeneCategoryId = GeneCategory.Id" % (Id, versionId))
+ results = self.cursor.fetchall()
+ if results:
+ tHD = HT.TD(Class="fs13 b1 c222")
+ for i, item in enumerate(results):
+ tHD.append(item[0])
+ if i < len(results)-1:
+ tHD.append("; ")
+ if i%2 == 1:
+ tHD.append(HT.BR())
+
+ tbl.append(HT.TR(
+ HT.TD("Category: ", Class="fs13 fwb b1 c222"),
+ tHD
+ ))
+
+ tbl.append(HT.TR(
+ HT.TD("Add Time: ", Class="fs13 fwb b1 c222"),
+ HT.TD(createtime, Class="fs13 b1 c222")
+ ))
+ if reason:
+ tbl.append(HT.TR(
+ HT.TD("Reason for Modification: ", Class="fs13 fwb b1 c222"),
+ HT.TD(reason, Class="fs13 b1 c222")
+ ))
+ return tbl
+
+ def insertUpdateCheck(self, fd, warning= ""):
+ self.dict['title'] = "%s GeneWiki Entry for %s" % (self.action.title(), self.symbol)
+ #mailsrch = re.compile('([\w\-][\w\-\.]*@[\w\-][\w\-\.]+[a-zA-Z]{1,4})([\s,;])*')
+ mailsrch = re.compile('([\w\-][\w\-\.]*)@([\w\-\.]+)\.([a-zA-Z]{1,4})([\s,;])*')
+ httpsrch = re.compile('((?:http|ftp|gopher|file)://(?:[^ \n\r<\)]+))([\s,;])*')
+ if not self.comment or not self.email:
+ heading = self.dict['title']
+ detail = ["Please don't leave text field or email field empty."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ if self.action == 'update' and not self.reason:
+ heading = self.dict['title']
+ detail = ["Please submit your reason for this modification."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ if len(self.comment) >500:
+ heading = self.dict['title']
+ detail = ["Your entry is more than 500 characters."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ if self.email and re.sub(mailsrch, "", self.email) != "":
+ heading = self.dict['title']
+ detail = ["The format of your email address is incorrect."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ if self.weburl == "http://":
+ self.weburl = ""
+
+ if self.weburl and re.sub(httpsrch, "", self.weburl) != "":
+ heading = self.dict['title']
+ detail = ["The format of web resource link is incorrect."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ if self.pubmedid:
+ try:
+ test = map(int, string.split(self.pubmedid))
+ except:
+ heading = self.dict['title']
+ detail = ["PubMed IDs can only be integers."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='addgenerif',submit=HT.Input(type='hidden'))
+ recordInfoTable = HT.TableLite(border=0, cellspacing=1, cellpadding=5,align="center")
+
+ addButton = HT.Input(type='submit',name='submit', value='%s GeneWiki Entry' % self.action.title(),Class="button")
+ hddn = {'curStatus':'insertResult', 'FormID':'geneWiki', 'symbol':self.symbol,
+ 'comment':self.comment, 'email':self.email, 'species':self.species,
+ 'action':self.action, 'reason':self.reason}
+ if self.Id:
+ hddn['Id']=self.Id
+
+ formBody = HT.TableLite()
+
+ formBody.append(HT.TR(
+ HT.TD(HT.Strong("Species: ")),
+ HT.TD(width=10),
+ HT.TD(string.split(self.species, ":")[0])
+ ))
+ if self.pubmedid:
+ try:
+ formBody.append(HT.TR(
+ HT.TD(HT.Strong("PubMed IDs: ")),
+ HT.TD(width=10),
+ HT.TD(self.pubmedid)
+ ))
+ hddn['pubmedid'] = self.pubmedid
+ except:
+ pass
+ if self.weburl:
+ try:
+ formBody.append(HT.TR(
+ HT.TD(HT.Strong("Web URL: ")),
+ HT.TD(width=10),
+ HT.TD(HT.Href(text=self.weburl, url=self.weburl, Class='fwn'))
+ ))
+ hddn['weburl'] = self.weburl
+ except:
+ pass
+ formBody.append(HT.TR(
+ HT.TD(HT.Strong("Gene Notes: ")),
+ HT.TD(width=10),
+ HT.TD(self.comment)
+ ))
+ formBody.append(HT.TR(
+ HT.TD(HT.Strong("Email: ")),
+ HT.TD(width=10),
+ HT.TD(self.email)
+ ))
+ if self.initial:
+ formBody.append(HT.TR(
+ HT.TD(HT.Strong("Initial: ")),
+ HT.TD(width=10),
+ HT.TD(self.initial)
+ ))
+ hddn['initial'] = self.initial
+
+ if self.genecategory:
+ cTD = HT.TD()
+ if type(self.genecategory) == type(""):
+ self.genecategory = string.split(self.genecategory)
+ self.cursor.execute("Select Id, Name from GeneCategory where Id in (%s) order by Name " % string.join(self.genecategory, ', '))
+ results = self.cursor.fetchall()
+ for item in results:
+ cTD.append(item[1], HT.BR())
+
+ formBody.append(HT.TR(
+ HT.TD(HT.Strong("Category: ")),
+ HT.TD(width=10),
+ cTD
+ ))
+ hddn['genecategory'] = string.join(self.genecategory, " ")
+
+ formBody.append(HT.TR(
+ HT.TD(
+ HT.BR(), HT.BR(),
+ HT.Div("For security reasons, enter the code (case insensitive) in the image below to finalize your submission"), HT.BR(),
+ addButton, HT.Input(type="password", size = 25, name="password"),
+ colspan=3)
+ ))
+
+
+ code = webqtlUtil.genRandStr(length=5, chars="abcdefghkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789")
+ filename= webqtlUtil.genRandStr("Sec_")
+ hddn['filename'] = filename
+ securityCanvas = pid.PILCanvas(size=(300,100))
+ Plot.plotSecurity(securityCanvas, text=code)
+
+ os.system("touch %s_.%s" % (os.path.join(webqtlConfig.IMGDIR,filename), code))
+ securityCanvas.save(os.path.join(webqtlConfig.IMGDIR,filename), format='png')
+
+ formBody.append(HT.TR(
+ HT.TD(HT.Image("/image/"+filename+".png"), colspan=3)
+ ))
+
+ hddn['filename'] = filename
+ TD_LR = HT.TD(valign="top", bgcolor="#eeeeee")
+ title = HT.Paragraph("%s GeneWiki Entry for %s" % (self.action.title(), self.symbol), Class="title")
+
+ form.append(HT.P(), HT.Blockquote(formBody))
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ TD_LR.append(title, HT.Blockquote(warning, Id="red"), form)
+
+ self.dict['body'] = TD_LR
+
+ def insertUpdateForm(self, fd):
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='addgenerif',submit=HT.Input(type='hidden'))
+ addButton = HT.Input(type='submit',name='submit', value='%s GeneWiki Entry' % self.action.title(),Class="button")
+ resetButton = HT.Input(type='reset',Class="button")
+
+ hddn = {'curStatus':'insertCheck', 'FormID':'geneWiki', 'symbol':self.symbol, 'action':self.action, 'reason':self.reason}
+ if self.Id:
+ hddn['Id']=self.Id
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ if self.action == 'update':
+ self.cursor.execute("Select Species.Name, PubMed_ID, weburl, comment, email, initial from GeneRIF left JOIN Species on Species.Id = GeneRIF.SpeciesId where symbol='%s' and GeneRIF.Id = %s and versionId=0" % (self.symbol, self.Id))
+ oldSpeciesId, oldPubMed_ID, oldweburl, oldcomment, oldemail, oldinitial = self.cursor.fetchone()
+ if not oldSpeciesId:
+ oldSpeciesId="no specific species:0"
+ oldemail = ""
+ self.cursor.execute("Select GeneCategoryId from GeneRIFXRef where GeneRIFId = %s and versionId=0" % self.Id)
+ oldCategory = self.cursor.fetchall()
+ if oldCategory:
+ oldCategory = map(lambda X:X[0], oldCategory)
+ else:
+ oldSpeciesId = oldPubMed_ID = oldcomment = oldemail = oldinitial = oldweburl = ""
+ oldCategory= ()
+
+ if not oldweburl:
+ oldweburl = "http://"
+ #############################
+ TD_LR = HT.TD(valign="top", bgcolor="#eeeeee")
+ title = HT.Paragraph("%s GeneWiki Entry for %s" % (self.action.title(), self.symbol), Class="title")
+
+ smenu = HT.Select(name="species")
+ self.cursor.execute("select Id, Name from Species order by Name")
+ for Id, Name in self.cursor.fetchall():
+ smenu.append((Name, "%s:%s" % (Name, Id)))
+ smenu.append(("no specific species", "no specific species:0"))
+ if oldSpeciesId != "":
+ smenu.selected.append(oldSpeciesId)
+ else:
+ smenu.selected.append("mouse")
+ formBody = HT.TableLite()
+
+ if self.action == 'update':
+ formBody.append(HT.TR(
+ HT.TD("Reason for Modification: "),
+ HT.TD(width=10),
+ HT.TD(HT.Input(type="text", size = 45, maxlength=100, name="reason"))
+ ))
+ else:
+ pass
+
+ formBody.append(HT.TR(
+ HT.TD("Species: "),
+ HT.TD("&nbsp;", width=10),
+ HT.TD(smenu)
+ ))
+ formBody.append(HT.TR(
+ HT.TD("PubMed IDs: "),
+ HT.TD("&nbsp;", width=10),
+ HT.TD(HT.Input(type="text", size = 25, maxlength=25, name="pubmedid", value=oldPubMed_ID), " (optional, separate by blank space only)")
+ ))
+ formBody.append(HT.TR(
+ HT.TD("Web resource URL: "),
+ HT.TD("&nbsp;", width=10),
+ HT.TD(HT.Input(type="text", size = 50, maxlength=100, name="weburl", value=oldweburl), " (optional)")
+ ))
+ formBody.append(HT.TR(
+ HT.TD("Text: "),
+ HT.TD("&nbsp;", width=10),
+ HT.TD(HT.Textarea(cols = 60, rows=5, name="comment", text=oldcomment))
+ ))
+ formBody.append(HT.TR(
+ HT.TD("Email: "),
+ HT.TD("&nbsp;", width=10),
+ HT.TD(HT.Input(type="text", size = 40, maxlength=40, name="email", value=oldemail))
+ ))
+ formBody.append(HT.TR(
+ HT.TD("User Code: "),
+ HT.TD("&nbsp;", width=10),
+ HT.TD(HT.Input(type="text", size =15, maxlength=10, name="initial", value=oldinitial), " (optional user or project code or your initials)")
+ ))
+
+ self.cursor.execute("Select Id, Name from GeneCategory order by Name")
+ results = self.cursor.fetchall()
+ if results:
+ tbl2 = HT.TableLite()
+ tempTR = HT.TR()
+ for i, item in enumerate(results):
+ if item[0] in oldCategory:
+ boxchecked = 1
+ else:
+ boxchecked = 0
+ tempTR.append(HT.TD(HT.Input(type='checkbox', Class='checkbox', name='genecategory', value = item[0], checked=boxchecked), valign="top"), HT.TD(" ", item[1], valign="top"))
+ if (i%2):
+ tbl2.append(tempTR)
+ tempTR = HT.TR()
+ tbl2.append(tempTR)
+ formBody.append(HT.TR(
+ HT.TD("Category of Gene Note", HT.BR(), "(Please select one or", HT.BR(), "many categories):"),
+ HT.TD("&nbsp;", width=10),
+ HT.TD(tbl2)
+ ))
+ formBody.append(HT.TR(
+ HT.TD(addButton, "&nbsp;"*10, resetButton, colspan=3)
+ ))
+
+ form.append(HT.P(), HT.Blockquote(formBody))
+
+ TD_LR.append(title, form)
+ self.dict['title'] = "%s GeneWiki Entry for %s" % (self.action.title(), self.symbol)
+ self.dict['body'] = TD_LR
+
+ def dispWikiPage(self, fd):
+ addButton = HT.Input(type="button",value="New GeneWiki Entry",onClick= \
+ "openNewWin('%s')" % (os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE) + "?FormID=geneWiki&action=add&symbol=%s" % self.symbol),
+ Class="button")
+ geneRIFBody = HT.TableLite(cellpadding=3, width="100%")
+ geneRIFBody.append(HT.TR(HT.TD(HT.Paragraph("GeneWiki for %s: " % self.symbol, addButton, Class="subtitle"), colspan=5+self.additional_colspan, height=40)))
+
+ self.cursor.execute("select comment, PubMed_ID, weburl, Id from GeneRIF where symbol = '%s' and display > 0 and versionId=0" % self.symbol)
+ results = self.cursor.fetchall()
+ geneRIFBody.append(HT.TR(HT.TD(), HT.TD("GeneNetwork:", colspan=4+self.additional_colspan, Class="fwb")))
+ if results:
+ for i, item in enumerate(results):
+ PubMedLink = WebLink = comma = ""
+ if item[1]:
+ PubMedLink = HT.Href(text="PubMed", target = "_blank",
+ url = webqtlConfig.PUBMEDLINK_URL % item[1], Class="fwn")
+ if item[2]:
+ if PubMedLink: comma = ", "
+ WebLink = HT.Href(text="URL Link", target = "_blank",
+ url = item[2], Class="fwn")
+ myTR = HT.TR(
+ HT.TD("&nbsp", width=20),
+ HT.TD(HT.Strong(i+1, ". "), valign="top"),
+ HT.TD(HT.Paragraph(item[0], " ", PubMedLink, comma, WebLink), valign="top"),
+ #HT.TD(, width=40, valign="top"),
+ HT.TD(
+ HT.Href(url=os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+ \
+ "?FormID=geneWiki&action=update&Id=%d&symbol=%s" %(item[-1], self.symbol),
+ onClick = "return confirm('Any user can edit any GeneWiki entry, with changes showing up immediately. The history of previous versions of this entry are stored and available for reference. Click OK to continue.');" ,
+ text=HT.Image("/images/modify.gif", border=0), title="Modify Entry", Class="fwn")
+ , width=20, valign="top"
+ ),
+ HT.TD(
+ HT.Href(url=os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+ \
+ "?FormID=geneWiki&action=history&Id=%d&symbol=%s" %(item[-1], self.symbol),
+ text=HT.Image("/images/history.gif", border=0), title="History of Entry", Class="fwn")
+ , width=20, valign="top"
+ )
+ )
+ if self.privilege_to_delete_entry:
+ myTR.append(HT.TD(
+ HT.Href(url=os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+ \
+ "?FormID=geneWiki&action=del&Id=%d&symbol=%s" %(item[-1], self.symbol),
+ onClick = "return confirm('Do you really want to delete this entry, click YES to continue.');" ,
+ text=HT.Image("/images/trash.gif", border=0), title="Delete Entry", Class="fwn")
+ , width=20, valign="top"
+ ))
+ geneRIFBody.append(myTR)
+ else:
+ geneRIFBody.append(HT.TR(
+ HT.TD("&nbsp", width=20),
+ HT.TD(HT.U("There is no GeneWiki entry for this gene."), colspan=5+self.additional_colspan),
+ ))
+
+ self.cursor.execute("select distinct Species.FullName, GeneRIF_BASIC.GeneId, GeneRIF_BASIC.comment, GeneRIF_BASIC.PubMed_ID from GeneRIF_BASIC, Species where GeneRIF_BASIC.symbol='%s' and GeneRIF_BASIC.SpeciesId = Species.Id order by Species.Id, GeneRIF_BASIC.createtime" % self.symbol)
+ results = self.cursor.fetchall()
+ if results:
+ geneRIFBody.append(HT.TR(HT.TD(), HT.TD("GeneRIF from NCBI:", colspan=4+self.additional_colspan, Class="fwb")))
+ for i, item in enumerate(results):
+ PubMedLink = HT.Href(text="PubMed", target = "_blank",
+ url = webqtlConfig.PUBMEDLINK_URL % item[3], Class="fwn")
+ GeneLink = HT.Href(text= item[0], target='_blank',\
+ url=webqtlConfig.NCBI_LOCUSID % item[1], Class="fwn")
+ myTR = HT.TR(
+ HT.TD("&nbsp", width=20),
+ HT.TD(HT.Strong(i+1, ". "), valign="top"),
+ HT.TD(HT.Paragraph(item[2], " (", GeneLink,") ", PubMedLink), valign="top", colspan=3+self.additional_colspan))
+ geneRIFBody.append(myTR)
+
+ TD_LR = HT.TD(valign="top", bgcolor="#eeeeee")
+ help1 = HT.Href(url="/GeneWikihelp.html", text=" help document", Class="fwn", target="_blank")
+ title = HT.Paragraph("GeneWiki Entries", Class="title")
+ intro = HT.Blockquote("GeneWiki enables you to enrich the annotation of genes and transcripts. Please submit or edit a GeneWiki note (500 characters max) related to a gene, its transcripts, or proteins. When possible include PubMed identifiers or web resource links (URL addresses). Please ensure that the additions will have widespread use. For additional information, check the GeneWiki ", help1, ".")
+
+ TD_LR.append(title, intro, HT.Blockquote(geneRIFBody))
+ self.dict['title'] = "GeneWiki for %s" % self.symbol
+ self.dict['body'] = TD_LR
+
+
+ def delRIF(self):
+ if self.privilege_to_delete_entry:
+ self.cursor.execute("update GeneRIF set display= 0 where Id = %d" % self.Id)
+
+ def insertResultPage(self, fd):
+ try:
+ password = fd.formdata.getvalue("password", "")
+ filename = fd.formdata.getvalue("filename")
+ code = glob.glob(os.path.join(webqtlConfig.IMGDIR,filename+"_.*"))
+ code = string.split(code[0], '.')[-1]
+ if string.lower(code) != string.lower(password):
+ return 0
+ TD_LR = HT.TD(valign="top", bgcolor="#eeeeee")
+ title = HT.Paragraph("Add GeneWiki Entry", Class="title")
+ self.cursor.execute("Select max(Id) from GeneRIF")
+ if self.action == 'update':
+ #old record
+ maxId = int(self.Id)
+ self.cursor.execute("select max(versionId)+1 from GeneRIF where Id=%s" % maxId)
+ newversionId = self.cursor.fetchone()[0]
+ self.cursor.execute("update GeneRIF set versionId = %d where Id=%d and versionId = 0" % (newversionId, maxId))
+ self.cursor.execute("update GeneRIFXRef set versionId = %d where GeneRIFId=%d and versionId = 0" % (newversionId, maxId))
+ else:
+ #new record
+ try:
+ maxId = self.cursor.fetchone()[0] +1
+ except:
+ maxId = 1
+
+ for item in self.fields:
+ if not getattr(self, item):
+ setattr(self, item, None)
+ self.cursor.execute("""insert into GeneRIF (id, symbol, PubMed_ID, SpeciesId, comment, email, createtime, user_ip, display, weburl, initial, reason)
+ values (%s, %s, %s, %s, %s, %s, Now(), %s, 1, %s, %s, %s)""",
+ (maxId, self.symbol, self.pubmedid, string.split(self.species, ":")[-1], self.comment,
+ self.email, fd.remote_ip, self.weburl, self.initial, self.reason))
+ if self.genecategory:
+ Ids = string.split(self.genecategory)
+ for item in Ids:
+ self.cursor.execute("insert into GeneRIFXRef(GeneRIFId, GeneCategoryId) values(%s, %s)" % (maxId, item))
+ return 2
+ except:
+ heading = self.dict['title']
+ detail = ["Error occurred while adding your Gene RIFs."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return 1
+
+
diff --git a/web/webqtl/geneWiki/__init__.py b/web/webqtl/geneWiki/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/geneWiki/__init__.py
diff --git a/web/webqtl/genomeGraph/__init__.py b/web/webqtl/genomeGraph/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/genomeGraph/__init__.py
diff --git a/web/webqtl/genomeGraph/cmdGenomeScanPage.py b/web/webqtl/genomeGraph/cmdGenomeScanPage.py
new file mode 100755
index 00000000..d880ce69
--- /dev/null
+++ b/web/webqtl/genomeGraph/cmdGenomeScanPage.py
@@ -0,0 +1,532 @@
+# 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
+
+import string
+import piddle as pid
+import os
+import math
+
+from htmlgen import HTMLgen2 as HT
+
+from utility import svg
+from base import webqtlConfig
+from utility import Plot
+from utility import webqtlUtil
+from base.webqtlDataset import webqtlDataset
+from base.templatePage import templatePage
+
+
+#########################################
+# Genome Scan PAGE
+#########################################
+class cmdGenomeScanPage(templatePage):
+ def __init__(self,fd):
+ templatePage.__init__(self,fd)
+ if not self.openMysql():
+ return
+ self.database = fd.formdata.getvalue('database', '')
+ db = webqtlDataset(self.database, self.cursor)
+
+ try:
+ self.openURL = webqtlConfig.CGIDIR + webqtlConfig.SCRIPTFILE + \
+ '?FormID=showDatabase&database=%s&incparentsf1=1&ProbeSetID=' % self.database
+
+ if db.type != "ProbeSet" or not db.id:
+ raise DbNameError
+
+ self.cursor.execute("""
+ Select
+ InbredSet.Name
+ From
+ ProbeSetFreeze, ProbeFreeze, InbredSet
+ whERE
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id AND
+ ProbeFreeze.InbredSetId = InbredSet.Id AND
+ ProbeSetFreeze.Id = %d
+ """ % db.id)
+ thisRISet = self.cursor.fetchone()[0]
+ if thisRISet =='BXD300':
+ thisRISet = 'BXD'
+
+ ##################################################
+ # exon data is too huge for GenoGraph, skip it #
+ ##################################################
+ self.cursor.execute('select count(*) from ProbeSetXRef where ProbeSetFreezeId=%d' % db.id)
+ amount = self.cursor.fetchall()
+ if amount:
+ amount = amount[0][0]
+ if amount>100000:
+ heading = "Whole Transcriptome Mapping"
+ detail = ["Whole Transcriptome Mapping is not available for this data set."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.cursor.execute("""
+ Select
+ ProbeSet.Id, ProbeSet.Name, ProbeSet.Chr, ProbeSet.Mb, ProbeSetXRef.Locus, ProbeSetXRef.pValue
+ From
+ ProbeSet, ProbeSetXRef
+ whERE
+ ProbeSetXRef.ProbeSetFreezeId = %d AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetXRef.Locus is not NULL
+ """ % db.id)
+ results = self.cursor.fetchall()
+
+ if results:
+ self.mouseChrLengthDict, sum = self.readMouseGenome(thisRISet)
+
+ import reaper
+ markerGMb = {}
+ genotype_1 = reaper.Dataset()
+ genotype_1.read(os.path.join(webqtlConfig.GENODIR, thisRISet + '.geno'))
+ for chr in genotype_1:
+ chrlen = self.mouseChrLengthDict[chr.name]
+
+ for locus in chr:
+ markerGMb[locus.name] = locus.Mb + chrlen
+
+ try:
+ FDR = float(fd.formdata.getvalue("fdr", ""))
+ except:
+ FDR = 0.2
+ self.grid = fd.formdata.getvalue("grid", "")
+
+ NNN = len(results)
+ results = list(results)
+ results.sort(self.cmppValue)
+
+ MbCoord = []
+ MbCoord2 = []
+
+ for j in range(NNN, 0, -1):
+ if results[j-1][-1] <= (FDR*j)/NNN:
+ break
+
+ if j > 0:
+ for i in range(j-1, -1, -1):
+ _Id, _probeset, _chr, _Mb, _marker, _pvalue = results[i]
+ try:
+ MbCoord.append([markerGMb[_marker], _Mb+self.mouseChrLengthDict[string.strip(_chr)], _probeset, _chr, _Mb, _marker, _pvalue])
+ except:
+ pass
+
+ filename=webqtlUtil.genRandStr("gScan_")
+ canvas = pid.PILCanvas(size=(1280,880))
+ self.drawGraph(canvas, MbCoord, cLength=sum)
+
+ canvas.save(os.path.join(webqtlConfig.IMGDIR, filename), format='png')
+
+ canvasSVG = self.drawSVG(MbCoord, cLength=sum, size=(1280,880))
+ canvasSVG.toXml(os.path.join(webqtlConfig.IMGDIR, filename+'.svg')) #and write it to file
+
+ img = HT.Embed(src='/image/'+filename+'.png', width=1280, height=880, border=0, alt='Genome Scan')
+ img2 = HT.Embed(src='/image/'+filename+'.svg', width=1280, height=880, border=0)
+ TD_LR = HT.TD(colspan=2,height=200,width="100%",bgColor='#eeeeee')
+
+ heading = HT.Paragraph('Whole Transcriptome Mapping')
+ heading.__setattr__("class","title")
+ intro = HT.Blockquote()
+ intro.append('The plot below is the Whole Transcriptome Mapping of Database ')
+ intro.append(HT.Href(text=db.fullname, url = webqtlConfig.INFOPAGEHREF % db.name ,target='_blank',Class="normalsize"))
+ intro.append(". %d from a total of %d ProbeSets were utilized to generate this graph." % (len(MbCoord), len(results)))
+
+ mainfm = HT.Form(cgi = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', \
+ name=webqtlUtil.genRandStr("fm_"), submit=HT.Input(type='hidden'))
+ mainfm.append(HT.Input(name='database', value=self.database, type='hidden'))
+ mainfm.append(HT.Input(name='FormID', value='transciptMapping', type='hidden'))
+
+ mainfm.append("<BLOCKQUOTE>")
+ mainfm.append("0 < FDR <= 1.0 ")
+ mainfm.append(HT.Input(name='fdr', value=FDR, type='text'))
+
+ mainfm.append(HT.Input(name='submit', value='Redraw Graph', type='submit', Class='button'))
+ mainfm.append("</BLOCKQUOTE>")
+ mainfm.append("""
+<center>
+<div id="gallery">
+<div class="on" title="img1"><span>Static</span></div>
+<div class="off" title="img2"><span>Interactive</span></div>
+</div>
+
+<div id="img1" class="show">
+""")
+ mainfm.append(img)
+ mainfm.append("""
+</div>
+
+<div id="img2" class="hide">
+""")
+ mainfm.append(img2)
+ mainfm.append("""
+</div>
+</center>
+""")
+
+ TD_LR.append(heading, intro, HT.Paragraph(mainfm))
+
+ self.dict['title'] = 'Whole Transcriptome Mapping'
+ self.dict['body'] = TD_LR
+ else:
+ heading = "Whole Transcriptome Mapping"
+ detail = ["Database calculation is not finished."]
+ self.error(heading=heading,detail=detail)
+ return
+ except:
+ heading = "Whole Transcriptome Mapping"
+ detail = ["Whole Transcriptome Mapping only apply to Microarray database."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ def drawSVG(self, data, cLength = 2500, offset= (80, 160, 60, 60), size=(1280,880),
+ XLabel="Marker GMb", YLabel="Transcript GMb"):
+ entities = {
+ "colorText" : "fill:darkblue;",
+ "strokeText" : ";stroke:none;stroke-width:0;",
+ "allText" : "font-family:Helvetica;",
+ "titleText" : "font-size:22;font-weight:bold;",
+ "subtitleText" : "font-size:18;font-weight:bold;",
+ "headlineText" : "font-size:14;font-weight:bold;",
+ "normalText" : "font-size:12;",
+ "legendText" : "font-size:11;text-anchor:end;",
+ "valuesText" : "font-size:12;",
+ "boldValuesText" : "font-size:12;font-weight:bold;",
+ "smallText" : "font-size:10;",
+ "vText" : "writing-mode:tb-rl",
+ "rightText" : "text-anchor:end;",
+ "middleText" : "text-anchor:middle;",
+ "bezgrenzstyle" : "fill:none;stroke:#11A0FF;stroke-width:40;stroke-antialiasing:true;",
+ "rectstyle" : "fill:lightblue;stroke:none;opacity:0.2;",
+ "fillUnbebaut" : "fill:#CCFFD4;stroke:none;",
+ "fillNodata" : "fill:#E7E7E7;stroke:black;stroke-width:2;stroke-antialiasing:true;",
+ "fillNodataLegend" : "fill:#E7E7E7;stroke:black;stroke-width:0.5;stroke-antialiasing:true;",
+ "grundzeitstyle" : "fill:none;stroke:#E00004;stroke-width:60;stroke-antialiasing:true;",
+ "bezgrenzstyle" : "fill:none;stroke:#11A0FF;stroke-width:40;stroke-antialiasing:true;",
+ "mapAuthor" : "A. Neumann",
+ }
+ cWidth, cHeight = size
+ canvasSVG = svg.drawing(entities) #create a drawing
+ drawSpace=svg.svg((0, 0, cWidth, cHeight), cWidth, cHeight, xml__space="preserve",
+ zoomAndPan="disable", onload="initMap(evt);",
+ xmlns__a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/",
+ a3__scriptImplementation="Adobe") #create a svg drawingspace
+ canvasds=svg.description('Genome Graph') #define a description
+ drawSpace.addElement(canvasds) #add the description to the svg
+
+ #need to be modified or deleted
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = cWidth - xLeftOffset - xRightOffset
+ plotHeight = cHeight - yTopOffset - yBottomOffset
+ drawSpace.addElement(svg.script("", language="javascript", xlink__href="/javascript/svg.js"))
+
+ #add defs
+ defs = svg.defs()
+ symbol1= svg.symbol(id="magnifyer", overflow="visible",
+ style="fill:white;stroke:orange;stroke-width:2;")
+ symbol1.addElement(svg.line(0, 0, -8, 20))
+ symbol1.addElement(svg.circle(0, 0, 8))
+ symbol1.addElement(svg.line(-4, 0, 4, 0, style="stroke:orange;stroke-width:2;"))
+ defs.addElement(symbol1)
+ symbol2= svg.symbol(id="magnifyerZoomIn",overflow="visible")
+ symbol2.addElement(svg.use(link="#magnifyer", id="zoomIn"))
+ symbol2.addElement(svg.line(0, -4, 0, 4, style="stroke:orange;stroke-width:2;"))
+ defs.addElement(symbol2)
+ drawSpace.addElement(defs)
+
+ symbol3= svg.symbol(id="msgbox", overflow="visible",
+ style="fill:white;stroke:orange;stroke-width:1;opacity:0.8;")
+ symbol3.addElement(svg.rect(-80, -190, 300, 150, rx=10, ry=10))
+ symbol3.addElement(svg.line(21, -40, 58, -40, style="stroke:white;"))
+ symbol3.addElement(svg.polyline([[20, -40], [0, 0], [60, -40]]))
+ symbol3.addElement(svg.text(-60, -160, "ProbeSet ", style="&colorText; &allText; &subtitleText; &strokeText;"))
+ symbol3.addElement(svg.text(-60, -125, "Marker ", style="&colorText; &allText; &subtitleText; &strokeText;"))
+ symbol3.addElement(svg.text(-60, -90, "LRS ", style="&colorText; &allText; &subtitleText; &strokeText;"))
+ symbol3.addElement(svg.text(-60, -55, "P value ", style="&colorText; &allText; &subtitleText; &strokeText;"))
+ defs.addElement(symbol3)
+
+ g = svg.group("title")
+ g.addElement(svg.text(cWidth-40, 30, "Genome Graph", style="&colorText; &allText; &titleText; &rightText;"))
+ g.addElement(svg.text(cWidth-40, 50, "Whole Transcriptome Mapping", style="&colorText; &allText; &subtitleText; &rightText;"))
+ drawSpace.addElement(g)
+
+ #draw Main display area border
+ mainSquare = cHeight-60
+ cordZOOM = 10
+ drawSpace.addElement(svg.rect(8, 8, mainSquare+4, mainSquare+4,'none',"orange",0.5, rx="5", ry="5"))
+ drawSpace.addElement(svg.text(10+mainSquare/2, 40+mainSquare,'Marker GMb',
+ style="&colorText; &allText; &titleText; &middleText;", id="XLabel"))
+ drawSpace.addElement(svg.text(mainSquare + 80, 10+mainSquare/2,'Transcript GMb',
+ style="&colorText; &allText; &titleText; &middleText; &vText;", id="YLabel"))
+
+ #draw overview display area
+ drawSpace.addElement(svg.rect(cWidth-40-260, 60, 260, 260,'none',"orange",0.5, rx="5", ry="5"))
+ drawSpaceThumb= svg.svg(id="overviewPlot",x=cWidth-40-260,y="60",width="260",
+ height="260",viewBox=(0, 0, mainSquare*cordZOOM, mainSquare*cordZOOM))
+ g = svg.group(style="&bezgrenzstyle;")
+ g.addElement(svg.use("#grid"))
+ drawSpaceThumb.addElement(g)
+ drawSpaceThumb.addElement(svg.rect(id="overviewRect",style="&rectstyle;",
+ x="0",y="0",width=mainSquare*cordZOOM,height=mainSquare*cordZOOM,
+ onmouseover="statusChange('click and drag rectangle to change extent');",
+ onmousedown="beginPan(evt);", onmousemove="doPan(evt);",
+ onmouseup="endPan();", onmouseout="endPan();"))
+ drawSpace.addElement(drawSpaceThumb)
+
+ #draw navigator
+ g = svg.group(id="navigatorElements")
+ g.addElement(svg.use("#magnifyerZoomIn", id="zoomIn", transform="translate(%d,350)" % (cWidth-40-130-20),
+ onmouseover="magnify(evt,1.3,'in');", onmouseout="magnify(evt,1,'in');", onclick="zoomIt('in');"))
+ g.addElement(svg.use("#magnifyer", id="zoomOut", transform="translate(%d,350)" % (cWidth-40-130+20),
+ onmouseover="magnify(evt,1.3,'out');",onmouseout="magnify(evt,1,'out');", onclick="zoomIt('out');"))
+
+ drawSpace.addElement(g)
+
+ g = svg.group(id="statusBar")
+ g.addElement(svg.text(cWidth-40-260, 360, "ZOOM: 100%", style="fill:orange; font-size:14;", id="zoomValueObj"))
+ g.addElement(svg.text(cWidth-40-260, 380, "Status:", style="&colorText; &allText; &smallText;"))
+ g.addElement(svg.text(cWidth-40-260, 395, "Loading Plot", style="&colorText; &allText; &smallText;", id="statusText"))
+ drawSpace.addElement(g)
+
+ #draw main display area
+ drawSpaceMain= svg.svg((0, 0, mainSquare*cordZOOM, mainSquare*cordZOOM), mainSquare, mainSquare,
+ id="mainPlot",x="10",y="10")
+ mPlotWidth = mPlotHeight = 0.8*mainSquare*cordZOOM
+
+ drawSpaceMain.addElement(svg.rect(mainSquare*cordZOOM*0.1, mainSquare*cordZOOM*0.1, mPlotWidth, mPlotHeight,style="fill:white",
+ onmousemove="showChr(evt);", onmouseover="showChr(evt);", onmouseout="showNoChr(evt);"))
+ #draw grid
+ g = svg.group("grid", style="stroke:lightblue;stroke-width:3",
+ transform="translate(%d,%d)" % (mainSquare*cordZOOM*0.1, mainSquare*cordZOOM*0.1))
+
+ if 1: #self.grid == "on":
+ js = []
+ for key in self.mouseChrLengthDict.keys():
+ length = self.mouseChrLengthDict[key]
+ js.append(mPlotWidth*length/cLength)
+ if length != 0:
+ yCoord = mPlotHeight*(1.0-length/cLength)
+ l = svg.line(0,yCoord ,mPlotWidth, yCoord)
+ g.addElement(l)
+ xCoord = mPlotWidth*length/cLength
+ l = svg.line(xCoord, 0 ,xCoord, mPlotHeight)
+ g.addElement(l)
+ js.sort()
+ drawSpace.addElement(svg.script("",language="javascript", cdata="var openURL=\"%s\";\nvar chrLength=%s;\n" % (self.openURL, js)))
+
+ g.addElement(svg.rect(0, 0, mPlotWidth, mPlotHeight,'none','black',10))
+ drawSpaceMain.addElement(g)
+
+ #draw Scale
+ g = svg.group("scale", style="stroke:black;stroke-width:0",
+ transform="translate(%d,%d)" % (mainSquare*cordZOOM*0.1, mainSquare*cordZOOM*0.1))
+ i = 100
+ scaleFontSize = 11*cordZOOM
+ while i < cLength:
+ yCoord = mPlotHeight - mPlotHeight*i/cLength
+ l = svg.line(0,yCoord ,-5*cordZOOM, yCoord)
+ g.addElement(l)
+ t = svg.text(-40*cordZOOM, yCoord +5*cordZOOM, "%d"% i, 100, "verdana") # coordinate tag Y
+ g.addElement(t)
+ xCoord = mPlotWidth*i/cLength
+ l = svg.line(xCoord, mPlotHeight, xCoord, mPlotHeight+5*cordZOOM)
+ g.addElement(l)
+ if i%200 == 0:
+ t = svg.text(xCoord, mPlotHeight+10*cordZOOM, "%d"% i, 100, "verdana") # coordinate tag X
+ g.addElement(t)
+ i += 100
+
+ drawSpaceMain.addElement(g)
+ #draw Points
+ finecolors = Plot.colorSpectrumSVG(12)
+ finecolors.reverse()
+ g = preColor = ""
+ for item in data:
+ _probeset, _chr, _Mb, _marker, _pvalue = item[2:]
+ try:
+ _idx = int((-math.log10(_pvalue))*12/6.0) # add module name
+ _color = finecolors[_idx]
+ except:
+ _color = finecolors[-1]
+ if _color != preColor:
+ preColor = _color
+ if g:
+ drawSpaceMain.addElement(g)
+ g = svg.group("points", style="stroke:%s;stroke-width:5" % _color,
+ transform="translate(%d,%d)" % (mainSquare*cordZOOM*0.1, mainSquare*cordZOOM*0.1),
+ onmouseover="mvMsgBox(evt);", onmouseout="hdMsgBox();", onmousedown="openPage(evt);")
+ else:
+ pass
+ px = mPlotWidth*item[0]/cLength
+ py = mPlotHeight*(1.0-item[1]/cLength)
+ l = svg.line("%2.1f" % (px-3*cordZOOM), "%2.1f" % py, "%2.1f" % (px+3*cordZOOM), "%2.1f" % py, ps=_probeset, mk=_marker)
+ g.addElement(l)
+
+ drawSpaceMain.addElement(g)
+
+ """
+ #draw spectrum
+ i = 0
+ j = 0
+ middleoffsetX = 40
+ labelFont=pid.Font(ttf="tahoma",size=12,bold=0)
+ for dcolor in finecolors:
+ drawSpace.drawLine(xLeftOffset+ plotWidth + middleoffsetX -15 , plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth + middleoffsetX+15 , plotHeight + yTopOffset - i, color=dcolor)
+ if i % 50 == 0:
+ drawSpace.drawLine(xLeftOffset+ plotWidth +middleoffsetX+15 ,plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth +middleoffsetX+20,plotHeight + yTopOffset - i, color=pid.black)
+ drawSpace.drawString("%1.1f" % -j , xLeftOffset+ plotWidth +middleoffsetX+25 ,plotHeight + yTopOffset - i+5, font = labelFont)
+ j += 1
+ i += 1
+ drawSpace.drawLine(xLeftOffset+ plotWidth +middleoffsetX+15 ,plotHeight + yTopOffset - i+1, \
+ xLeftOffset+ plotWidth +middleoffsetX+20,plotHeight + yTopOffset - i+1, color=pid.black)
+ drawSpace.drawString("%1.1f" % -j , xLeftOffset+ plotWidth +middleoffsetX+25 ,plotHeight + yTopOffset - i+6, font = labelFont)
+ labelFont=pid.Font(ttf="tahoma",size=14,bold=1)
+ drawSpace.drawString("Log(pValue)" , xLeftOffset+ plotWidth +middleoffsetX+60 ,plotHeight + yTopOffset - 100, font = labelFont, angle =90)
+
+ labelFont=pid.Font(ttf="verdana",size=18,bold=0)
+ drawSpace.drawString(XLabel, xLeftOffset + (plotWidth -drawSpace.stringWidth(XLabel,font=labelFont))/2.0, plotHeight + yTopOffset +40, color=pid.blue, font=labelFont)
+ drawSpace.drawString(YLabel,xLeftOffset-60, plotHeight + yTopOffset-(plotHeight -drawSpace.stringWidth(YLabel,font=labelFont))/2.0, color=pid.blue, font=labelFont, angle =90)
+ """
+ drawSpace.addElement(drawSpaceMain)
+
+ g= svg.group(id="dispBox", overflow="visible",
+ style="fill:white;stroke:orange;stroke-width:1;opacity:0.85;",
+ transform="translate(%d,650)" % (cWidth-40-300), visibility="hidden")
+ g.addElement(svg.rect(-80, -190, 300, 150, rx=10, ry=10))
+ g.addElement(svg.line(21, -40, 58, -40, style="stroke:white;"))
+ g.addElement(svg.polyline([[20, -40], [0, 0], [60, -40]]))
+ g.addElement(svg.text(-60, -160, "ProbeSet ", style="&colorText; &allText; &subtitleText; &strokeText;", id="_probeset"))
+ g.addElement(svg.text(-60, -125, "Marker ", style="&colorText; &allText; &subtitleText; &strokeText;", id="_marker"))
+
+ drawSpace.addElement(g)
+
+ canvasSVG.setSVG(drawSpace) #set the svg of the drawing to the svg
+ return canvasSVG
+
+
+ def drawGraph(self, canvas, data, cLength = 2500, offset= (80, 160, 60, 60), XLabel="QTL location (GMb)", YLabel="Gene location (GMb)"):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+
+ #draw Frame
+ canvas.drawRect(plotWidth+xLeftOffset, plotHeight + yTopOffset, xLeftOffset, yTopOffset)
+
+ #draw Scale
+ i = 100
+ scaleFont=pid.Font(ttf="cour",size=11,bold=1)
+ while i < cLength:
+ yCoord = plotHeight + yTopOffset - plotHeight*i/cLength
+ canvas.drawLine(xLeftOffset,yCoord ,xLeftOffset-5, yCoord)
+ canvas.drawString("%d"% i, xLeftOffset -40, yCoord +5,font=scaleFont)
+ xCoord = xLeftOffset + plotWidth*i/cLength
+ canvas.drawLine(xCoord, plotHeight + yTopOffset ,xCoord, plotHeight + yTopOffset+5)
+ canvas.drawString("%d"% i, xCoord -10, plotHeight + yTopOffset+15,font=scaleFont)
+ i += 100
+
+ #draw Points
+ finecolors = Plot.colorSpectrum(300)
+ finecolors.reverse()
+ for item in data:
+ _pvalue = item[-1]
+ try:
+ _idx = int((-math.log10(_pvalue))*300/6.0) # XZ, 09/11/2008: add module name
+ _color = finecolors[_idx]
+ except:
+ _color = finecolors[-1]
+
+ canvas.drawCross(xLeftOffset + plotWidth*item[0]/cLength, plotHeight + yTopOffset - plotHeight*item[1]/cLength, color=_color,size=3)
+
+ #draw grid / always draw grid
+ if 1: #self.grid == "on":
+ for key in self.mouseChrLengthDict.keys():
+ length = self.mouseChrLengthDict[key]
+ if length != 0:
+ yCoord = plotHeight + yTopOffset - plotHeight*length/cLength
+ canvas.drawLine(xLeftOffset,yCoord ,xLeftOffset+plotWidth, yCoord, color=pid.lightgrey)
+ xCoord = xLeftOffset + plotWidth*length/cLength
+ canvas.drawLine(xCoord, plotHeight + yTopOffset ,xCoord, yTopOffset, color=pid.lightgrey)
+
+ #draw spectrum
+ i = 0
+ j = 0
+ middleoffsetX = 40
+ labelFont=pid.Font(ttf="tahoma",size=12,bold=0)
+ for dcolor in finecolors:
+ canvas.drawLine(xLeftOffset+ plotWidth + middleoffsetX -15 , plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth + middleoffsetX+15 , plotHeight + yTopOffset - i, color=dcolor)
+ if i % 50 == 0:
+ canvas.drawLine(xLeftOffset+ plotWidth +middleoffsetX+15 ,plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth +middleoffsetX+20,plotHeight + yTopOffset - i, color=pid.black)
+ canvas.drawString("%1.1f" % -j , xLeftOffset+ plotWidth +middleoffsetX+25 ,plotHeight + yTopOffset - i+5, font = labelFont)
+ j += 1
+ i += 1
+ canvas.drawLine(xLeftOffset+ plotWidth +middleoffsetX+15 ,plotHeight + yTopOffset - i+1, \
+ xLeftOffset+ plotWidth +middleoffsetX+20,plotHeight + yTopOffset - i+1, color=pid.black)
+ canvas.drawString("%1.1f" % -j , xLeftOffset+ plotWidth +middleoffsetX+25 ,plotHeight + yTopOffset - i+6, font = labelFont)
+ labelFont=pid.Font(ttf="tahoma",size=14,bold=1)
+ canvas.drawString("Log(pValue)" , xLeftOffset+ plotWidth +middleoffsetX+60 ,plotHeight + yTopOffset - 100, font = labelFont, angle =90)
+
+ labelFont=pid.Font(ttf="verdana",size=18,bold=0)
+ canvas.drawString(XLabel, xLeftOffset + (plotWidth -canvas.stringWidth(XLabel,font=labelFont))/2.0, plotHeight + yTopOffset +40, color=pid.blue, font=labelFont)
+ canvas.drawString(YLabel,xLeftOffset-60, plotHeight + yTopOffset-(plotHeight -canvas.stringWidth(YLabel,font=labelFont))/2.0, color=pid.blue, font=labelFont, angle =90)
+ return
+
+ def readMouseGenome(self, RISet):
+ ldict = {}
+ lengths = []
+ sum = 0
+ #####################################
+ # Retrieve Chr Length Information
+ #####################################
+ self.cursor.execute("""
+ Select
+ Chr_Length.Name, Length from Chr_Length, InbredSet
+ where
+ Chr_Length.SpeciesId = InbredSet.SpeciesId AND
+ InbredSet.Name = '%s'
+ Order by
+ OrderId
+ """ % RISet)
+ lengths = self.cursor.fetchall()
+ ldict[lengths[0][0]] = 0
+ prev = lengths[0][1]/1000000.0
+ sum += lengths[0][1]/1000000.0
+ for item in lengths[1:]:
+ ldict[item[0]] = prev
+ prev += item[1]/1000000.0
+ sum += item[1]/1000000.0
+ return ldict, sum
+
+ def cmppValue(self, A,B):
+ if A[-1] < B[-1]:
+ return -1
+ elif A[-1] == B[-1]:
+ return 0
+ else:
+ return 1
+
diff --git a/web/webqtl/genomeGraph/genAllDbResultPage.py b/web/webqtl/genomeGraph/genAllDbResultPage.py
new file mode 100755
index 00000000..f0663a7c
--- /dev/null
+++ b/web/webqtl/genomeGraph/genAllDbResultPage.py
@@ -0,0 +1,309 @@
+# 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
+
+import string
+import os
+import time
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility import webqtlUtil
+from base.webqtlDataset import webqtlDataset
+from base.templatePage import templatePage
+
+
+#########################################
+# Genome Scan PAGE
+#########################################
+class genAllDbResultPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self,fd)
+
+ if not self.openMysql():
+ return
+
+ self.database = fd.formdata.getvalue('database', '')
+ db = webqtlDataset(self.database, self.cursor)
+
+ try:
+ if db.type != "ProbeSet" or not db.id:
+ raise DbNameError
+ except:
+ print 'Content-type: text/html\n'
+ heading = "Download Results"
+ detail = ["Only results of microarray database are available to download."]
+ self.error(heading=heading,detail=detail)
+ self.write()
+ return
+
+
+ #XZ, protect confidential dataset.
+ userExist = None
+ self.cursor.execute('SELECT Id, Name, FullName, confidentiality, AuthorisedUsers FROM ProbeSetFreeze WHERE Name = "%s"' % self.database)
+ indId, indName, indFullName, indConfid, AuthorisedUsers = self.cursor.fetchall()[0]
+ if indConfid == 1 and userExist == None:
+ try:
+
+ userExist = self.userName
+
+ #for the dataset that confidentiality is 1
+ #1. 'admin' and 'root' can see all of the dataset
+ #2. 'user' can see the dataset that AuthorisedUsers contains his id(stored in the Id field of User table)
+ if webqtlConfig.USERDICT[self.privilege] < webqtlConfig.USERDICT['admin']:
+ if not AuthorisedUsers:
+ userExist=None
+ else:
+ AuthorisedUsersList=AuthorisedUsers.split(',')
+ if not AuthorisedUsersList.__contains__(self.userName):
+ userExist=None
+ except:
+ pass
+
+ if not userExist:
+ #Error, Confidential Database
+ heading = "Correlation Table"
+ detail = ["The %s database you selected is not open to the public at this time, please go back and select other database." % indFullName]
+ self.error(heading=heading,detail=detail,error="Confidential Database")
+ return
+
+ self.cursor.execute("""
+ Select
+ InbredSet.Name
+ From
+ ProbeSetFreeze, ProbeFreeze, InbredSet
+ whERE
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id AND
+ ProbeFreeze.InbredSetId = InbredSet.Id AND
+ ProbeSetFreeze.Id = %d
+ """ % db.id)
+ thisRISet = self.cursor.fetchone()[0]
+ if thisRISet =='BXD300':
+ thisRISet = 'BXD'
+
+ #XZ, 06/26/2009: It seems that this query is not neccessary. It doesn't return any result.
+ #XZ: It seems it is just for test purpose. The next try-except block does the real work.
+ #XZ: I think it should be deleted to shorten the response time.
+ #self.cursor.execute("""
+ # Select
+ # ProbeSet.Name, ProbeSet.symbol, ProbeSet.description, ProbeSet.Chr, ProbeSet.Mb, ProbeSetXRef.Locus,
+ # ProbeSetXRef.LRS, ProbeSetXRef.pValue, ProbeSetXRef.additive, ProbeSetXRef.mean
+ # From
+ # ProbeSet, ProbeSetXRef
+ # whERE
+ # ProbeSetXRef.ProbeSetFreezeId = %d AND
+ # ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ # ProbeSetXRef.Locus is not NULL
+ # Order by
+ # ProbeSet.name_num
+ # """ % db.id)
+
+ filename = os.path.join(webqtlConfig.SECUREDIR, db.name+'.result.xls')
+
+ try:
+ import random234
+ if random.choice(range(10)) == 0:
+ raise "ReCalculate"
+ fp = open(filename, 'rb')
+ text = fp.read()
+ fp.close()
+ except:
+ self.cursor.execute("Select ProbeSetXRef.ProbeSetId from ProbeSetXRef where ProbeSetFreezeId=%d" % db.id)
+ ProbeSetIds = self.cursor.fetchall()
+ self.mouseChrLengthDict, sum = self.readMouseGenome(thisRISet)
+
+ if ProbeSetIds:
+ import reaper
+ markerGMb = {}
+ genotype_1 = reaper.Dataset()
+ genotype_1.read(os.path.join(webqtlConfig.GENODIR, thisRISet + '.geno'))
+ for chr in genotype_1:
+ chrlen = self.mouseChrLengthDict[chr.name]
+ for locus in chr:
+ markerGMb[locus.name] = [chr.name, locus.Mb, locus.Mb + chrlen]
+
+ text = []
+ text.append(['ProbeSetId', 'Symbol', 'Description', 'Target Description', 'Chr', 'TMb', 'TGMb', 'Locus', 'LRS', 'Additive', 'pvalue', 'markerChr', 'markerMb', 'markerGMb', 'meanExpression'])
+ ProbeSetIdList = []
+ for ProbeSetId in ProbeSetIds:
+ ProbeSetIdList.append(ProbeSetId[0])
+ if len(ProbeSetIdList)==1000:
+ ProbeSetIdStr = ','.join(map(str, ProbeSetIdList))
+ ProbeSetIdList = []
+
+ cmd = """
+ Select
+ ProbeSet.Name, ProbeSet.symbol, ProbeSet.description,ProbeSet.Probe_Target_Description,ProbeSet.Chr, ProbeSet.Mb,
+ ProbeSetXRef.Locus, ProbeSetXRef.LRS, ProbeSetXRef.pValue,
+ ProbeSetXRef.additive, ProbeSetXRef.mean
+ From
+ ProbeSet, ProbeSetXRef
+ Where
+ ProbeSetXRef.ProbeSetFreezeId = %s AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetXRef.Locus is not NULL AND
+ ProbeSet.Id in (%s)
+ Order by
+ ProbeSet.name_num
+ """ % (db.id, ProbeSetIdStr)
+
+ self.cursor.execute(cmd)
+ results = self.cursor.fetchall()
+
+ for result in results:
+ _Id, _symbol, _desc,_targetDesc, _chr, _TMb, _marker, _lrs, _pvalue, _additive, _mean = result
+ if _marker == "-":
+ continue
+ if not _additive:
+ _additive = ""
+
+ try:
+ _TGMb = _TMb + self.mouseChrLengthDict[string.strip(_chr)]
+ except:
+ _TGMb = ""
+
+ result2 = [_Id, _symbol, _desc, _targetDesc, _chr, _TMb, _TGMb, _marker, _lrs, _additive, _pvalue]
+ try:
+ result2 += markerGMb[_marker]
+ except:
+ result2 += ['', '', '']
+ result2 += [_mean]
+ text.append(map(str, result2))
+
+ #XZ, 06/29/2007: This block is dealing with the last several probesets that fall out of the 1000-probeset block.
+ if ProbeSetIdList:
+ ProbeSetIdStr = ','.join(map(str, ProbeSetIdList))
+
+ cmd = """
+ Select
+ ProbeSet.Name, ProbeSet.symbol, ProbeSet.description,ProbeSet.Probe_Target_Description, ProbeSet.Chr, ProbeSet.Mb,
+ ProbeSetXRef.Locus, ProbeSetXRef.LRS, ProbeSetXRef.pValue,
+ ProbeSetXRef.additive, ProbeSetXRef.mean
+ From
+ ProbeSet, ProbeSetXRef
+ Where
+ ProbeSetXRef.ProbeSetFreezeId = %s AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetXRef.Locus is not NULL AND
+ ProbeSet.Id in (%s)
+ Order by
+ ProbeSet.name_num
+ """ % (db.id, ProbeSetIdStr)
+
+ self.cursor.execute(cmd)
+ results = self.cursor.fetchall()
+
+ for result in results:
+ _Id, _symbol, _desc, _targetDesc,_chr, _TMb, _marker, _lrs, _pvalue, _additive, _mean = result
+ if _marker == "-":
+ continue
+ if not _additive:
+ _additive = ""
+
+ try:
+ _TGMb = _TMb + self.mouseChrLengthDict[string.strip(_chr)]
+ except:
+ _TGMb = ""
+
+ result2 = [_Id, _symbol, _desc,_targetDesc, _chr, _TMb, _TGMb, _marker, _lrs, _additive, _pvalue]
+ try:
+ result2 += markerGMb[_marker]
+ except:
+ result2 += ['', '', '']
+ result2 += [_mean]
+ text.append(map(str, result2))
+
+
+ import pyXLWriter as xl
+ # Create a new Excel workbook
+ workbook = xl.Writer(filename)
+ worksheet = workbook.add_worksheet()
+ heading = workbook.add_format(align = 'center', bold = 1, size=13, color = 'red')
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=14, border = 1, border_color="gray")
+
+ worksheet.write([0, 0], "Data source: The GeneNetwork at http://www.genenetwork.org", titleStyle)
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([2, 0], "Database : %s" % db.fullname, titleStyle)
+ worksheet.write([3, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([4, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+ worksheet.write([5, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+
+ table_row_start_index = 7
+ nrow = table_row_start_index
+ for row in text:
+ for ncol, cell in enumerate(row):
+ if nrow == table_row_start_index:
+ worksheet.write([nrow, ncol], cell.strip(), heading)
+ worksheet.set_column([ncol, ncol], 20)
+ else:
+ worksheet.write([nrow, ncol], cell.strip())
+ nrow += 1
+
+ worksheet.write([1+nrow, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA21131), NCI MMHCC (U01CA105417), and NCRR (U01NR 105417)", titleStyle)
+ worksheet.write([2+nrow, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+
+ workbook.close()
+
+ fp = open(filename, 'rb')
+ text = fp.read()
+ fp.close()
+ else:
+ heading = "Download Results"
+ detail = ["Database calculation is not finished."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.content_type = 'application/xls'
+ self.content_disposition = 'attachment; filename=%s' % ('export-%s.xls' % time.strftime("%y-%m-%d-%H-%M"))
+ self.attachment = text
+
+ def readMouseGenome(self, RISet):
+ ldict = {}
+ lengths = []
+ sum = 0
+ #####################################
+ # Retrieve Chr Length Information
+ #####################################
+ self.cursor.execute("""
+ Select
+ Chr_Length.Name, Length from Chr_Length, InbredSet
+ where
+ Chr_Length.SpeciesId = InbredSet.SpeciesId AND
+ InbredSet.Name = '%s'
+ Order by
+ OrderId
+ """ % RISet)
+ lengths = self.cursor.fetchall()
+ ldict[lengths[0][0]] = 0
+ prev = lengths[0][1]/1000000.0
+ sum += lengths[0][1]/1000000.0
+ for item in lengths[1:]:
+ ldict[item[0]] = prev
+ prev += item[1]/1000000.0
+ sum += item[1]/1000000.0
+ return ldict, sum
diff --git a/web/webqtl/heatmap/Heatmap.py b/web/webqtl/heatmap/Heatmap.py
new file mode 100755
index 00000000..c4543cee
--- /dev/null
+++ b/web/webqtl/heatmap/Heatmap.py
@@ -0,0 +1,437 @@
+# 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
+
+import os
+import string
+import piddle as pid
+import cPickle
+
+from base import webqtlConfig
+from base.webqtlTrait import webqtlTrait
+from dbFunction import webqtlDatabaseFunction
+from utility import webqtlUtil
+from utility import Plot
+import slink
+
+
+# XZ, 09/09/2008: After adding several traits to collection, click "QTL Heatmap" button,
+# XZ, 09/09/2008: This class will generate what you see.
+#########################################
+# QTL heatmap Page
+#########################################
+class Heatmap:
+
+ def __init__(self, fd=None, searchResult=None, colorScheme=None, userPrivilege=None, userName=None):
+ cursor = webqtlDatabaseFunction.getCursor()
+ if (not cursor):
+ return
+ targetDescriptionChecked = fd.formdata.getvalue('targetDescriptionCheck', '')
+ clusterChecked = fd.formdata.getvalue('clusterCheck', '')
+ sessionfile = fd.formdata.getvalue("session")
+ genotype = fd.genotype
+ strainlist = fd.strainlist
+ ppolar = fd.ppolar
+ mpolar = fd.mpolar
+ traitList = []
+ traitDataList = []
+ for item in searchResult:
+ thisTrait = webqtlTrait(fullname=item, cursor=cursor)
+ thisTrait.retrieveInfo()
+ thisTrait.retrieveData(fd.strainlist)
+ traitList.append(thisTrait)
+ traitDataList.append(thisTrait.exportData(fd.strainlist))
+ self.buildCanvas(colorScheme=colorScheme, targetDescriptionChecked=targetDescriptionChecked, clusterChecked=clusterChecked, sessionfile=sessionfile, genotype=genotype, strainlist=strainlist, ppolar=ppolar, mpolar=mpolar, traitList=traitList, traitDataList=traitDataList, userPrivilege=userPrivilege, userName=userName)
+
+ def buildCanvas(self, colorScheme='', targetDescriptionChecked='', clusterChecked='', sessionfile='', genotype=None, strainlist=None, ppolar=None, mpolar=None, traitList=None, traitDataList=None, userPrivilege=None, userName=None):
+ labelFont = pid.Font(ttf="tahoma",size=14,bold=0)
+ topHeight = 0
+ NNN = len(traitList)
+ #XZ: It's necessory to define canvas here
+ canvas = pid.PILCanvas(size=(80+NNN*20,880))
+ names = map(webqtlTrait.displayName, traitList)
+ #XZ, 7/29/2009: create trait display and find max strWidth
+ strWidth = 0
+ for j in range(len(names)):
+ thisTrait = traitList[j]
+ if targetDescriptionChecked:
+ if thisTrait.db.type == 'ProbeSet':
+ if thisTrait.probe_target_description:
+ names[j] += ' [%s at Chr %s @ %2.3fMB, %s]' % (thisTrait.symbol, thisTrait.chr, thisTrait.mb, thisTrait.probe_target_description)
+ else:
+ names[j] += ' [%s at Chr %s @ %2.3fMB]' % (thisTrait.symbol, thisTrait.chr, thisTrait.mb)
+ elif thisTrait.db.type == 'Geno':
+ names[j] += ' [Chr %s @ %2.3fMB]' % (thisTrait.chr, thisTrait.mb)
+ elif thisTrait.db.type == 'Publish':
+ if thisTrait.confidential:
+ if webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=userPrivilege, userName=userName, authorized_users=thisTrait.authorized_users):
+ if thisTrait.post_publication_abbreviation:
+ names[j] += ' [%s]' % (thisTrait.post_publication_abbreviation)
+ else:
+ if thisTrait.pre_publication_abbreviation:
+ names[j] += ' [%s]' % (thisTrait.pre_publication_abbreviation)
+ else:
+ if thisTrait.post_publication_abbreviation:
+ names[j] += ' [%s]' % (thisTrait.post_publication_abbreviation)
+ else:
+ pass
+
+ i = canvas.stringWidth(names[j], font=labelFont)
+ if i > strWidth:
+ strWidth = i
+
+ width = NNN*20
+ xoffset = 40
+ yoffset = 40
+ cellHeight = 3
+ nLoci = reduce(lambda x,y: x+y, map(lambda x: len(x),genotype),0)
+
+ if nLoci > 2000:
+ cellHeight = 1
+ elif nLoci > 1000:
+ cellHeight = 2
+ elif nLoci < 200:
+ cellHeight = 10
+ else:
+ pass
+
+ pos = range(NNN)
+ neworder = []
+ BWs = Plot.BWSpectrum()
+ colors100 = Plot.colorSpectrum()
+ colors = Plot.colorSpectrum(130)
+ finecolors = Plot.colorSpectrum(250)
+ colors100.reverse()
+ colors.reverse()
+ finecolors.reverse()
+
+ scaleFont=pid.Font(ttf="tahoma",size=10,bold=0)
+
+ if not clusterChecked: #XZ: this part is for original order
+ for i in range(len(names)):
+ neworder.append((xoffset+20*(i+1), i))
+
+ canvas = pid.PILCanvas(size=(80+NNN*20+240,80+ topHeight +5+5+strWidth+nLoci*cellHeight+80+20*cellHeight))
+
+ self.drawTraitNameBottom(canvas,names,yoffset,neworder,strWidth,topHeight,labelFont)
+ else: #XZ: this part is to cluster traits
+ topHeight = 400
+ canvas = pid.PILCanvas(size=(80+NNN*20+240,80+ topHeight +5+5+strWidth+nLoci*cellHeight+80+20*cellHeight))
+
+ corArray = [([0] * (NNN))[:] for i in range(NNN)]
+
+ nnCorr = len(strainlist)
+
+ #XZ, 08/04/2009: I commented out pearsonArray, spearmanArray
+ 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)
+ if (1-corr) < 0:
+ distance = 0.0
+ else:
+ distance = 1-corr
+ corArray[i][j] = distance
+ corArray[j][i] = distance
+ elif j == i:
+ corArray[i][j] = 0.0
+ else:
+ pass
+
+ #XZ, 7/29/2009: The parameter d has info of cluster (group member and distance). The format of d is tricky. Print it out to see it's format.
+ d = slink.slink(corArray)
+
+ #XZ, 7/29/2009: Attention: The 'neworder' is changed by the 'draw' function
+ #XZ, 7/30/2009: Only toppos[1][0] and top[1][1] are used later. Then what toppos[0] is used for?
+ toppos = self.draw(canvas,names,d,xoffset,yoffset,neworder,topHeight)
+ self.drawTraitNameTop(canvas,names,yoffset,neworder,strWidth,topHeight,labelFont)
+
+ #XZ, 7/29/2009: draw the top vertical line
+ canvas.drawLine(toppos[1][0],toppos[1][1],toppos[1][0],yoffset)
+
+ #XZ: draw string 'distance = 1-r'
+ canvas.drawString('distance = 1-r',neworder[-1][0] + 50, topHeight*3/4,font=labelFont,angle=90)
+
+ #draw Scale
+ scaleFont=pid.Font(ttf="tahoma",size=10,bold=0)
+ x = neworder[-1][0]
+ canvas.drawLine(x+5, topHeight+yoffset, x+5, yoffset, color=pid.black)
+ y = 0
+ while y <=2:
+ canvas.drawLine(x+5, topHeight*y/2.0+yoffset, x+10, topHeight*y/2.0+yoffset)
+ canvas.drawString('%2.1f' % (2-y), x+12, topHeight*y/2.0+yoffset, font=scaleFont)
+ y += 0.5
+
+
+ chrname = 0
+ chrnameFont=pid.Font(ttf="tahoma",size=24,bold=0)
+ Ncol = 0
+
+ nearestMarkers = self.getNearestMarker(traitList, genotype)
+
+ # import cPickle
+ if sessionfile:
+ fp = open(os.path.join(webqtlConfig.TMPDIR, sessionfile + '.session'), 'rb')
+ permData = cPickle.load(fp)
+ fp.close()
+ else:
+ permData = {}
+
+ areas = []
+ #XZ, 7/31/2009: This for loop is to generate the heatmap
+ #XZ: draw trait by trait instead of marker by marker
+ for order in neworder:
+ #startHeight = 40+400+5+5+strWidth
+ startHeight = topHeight + 40+5+5+strWidth
+ startWidth = order[0]-5
+ if Ncol and Ncol % 5 == 0:
+ drawStartPixel = 8
+ else:
+ drawStartPixel = 9
+
+ tempVal = traitDataList[order[1]]
+ _vals = []
+ _strains = []
+ for i in range(len(strainlist)):
+ if tempVal[i] != None:
+ _strains.append(strainlist[i])
+ _vals.append(tempVal[i])
+
+ qtlresult = genotype.regression(strains = _strains, trait = _vals)
+
+ if sessionfile:
+ LRSArray = permData[str(traitList[order[1]])]
+ else:
+ LRSArray = genotype.permutation(strains = _strains, trait = _vals, nperm = 1000)
+ permData[str(traitList[order[1]])] = LRSArray
+
+ sugLRS = LRSArray[369]
+ sigLRS = LRSArray[949]
+ prechr = 0
+ chrstart = 0
+ nearest = nearestMarkers[order[1]]
+ midpoint = []
+
+ for item in qtlresult:
+ if item.lrs > webqtlConfig.MAXLRS:
+ adjustlrs = webqtlConfig.MAXLRS
+ else:
+ adjustlrs = item.lrs
+
+ if item.locus.chr != prechr:
+ if prechr:
+ canvas.drawRect(startWidth-drawStartPixel, startHeight, startWidth+10, startHeight+3,edgeColor=pid.white, edgeWidth=0, fillColor=pid.white)
+ startHeight+= 3
+ if not chrname:
+ canvas.drawString(prechr,xoffset-20,(chrstart+startHeight)/2,font = chrnameFont,color=pid.dimgray)
+ prechr = item.locus.chr
+ chrstart = startHeight
+ if colorScheme == '0':
+ if adjustlrs <= sugLRS:
+ colorIndex = int(65*adjustlrs/sugLRS)
+ else:
+ colorIndex = int(65 + 35*(adjustlrs-sugLRS)/(sigLRS-sugLRS))
+ if colorIndex > 99:
+ colorIndex = 99
+ colorIndex = colors100[colorIndex]
+ elif colorScheme == '1':
+ sugLRS = LRSArray[369]/2.0
+ if adjustlrs <= sugLRS:
+ colorIndex = BWs[20+int(50*adjustlrs/sugLRS)]
+ else:
+ if item.additive > 0:
+ colorIndex = int(80 + 50*(adjustlrs-sugLRS)/(sigLRS-sugLRS))
+ else:
+ colorIndex = int(50 - 50*(adjustlrs-sugLRS)/(sigLRS-sugLRS))
+ if colorIndex > 129:
+ colorIndex = 129
+ if colorIndex < 0:
+ colorIndex = 0
+ colorIndex = colors[colorIndex]
+ elif colorScheme == '2':
+ if item.additive > 0:
+ colorIndex = int(150 + 100*(adjustlrs/sigLRS))
+ else:
+ colorIndex = int(100 - 100*(adjustlrs/sigLRS))
+ if colorIndex > 249:
+ colorIndex = 249
+ if colorIndex < 0:
+ colorIndex = 0
+ colorIndex = finecolors[colorIndex]
+ else:
+ colorIndex = pid.white
+
+ if startHeight > 1:
+ canvas.drawRect(startWidth-drawStartPixel, startHeight, startWidth+10, startHeight+cellHeight,edgeColor=colorIndex, edgeWidth=0, fillColor=colorIndex)
+ else:
+ canvas.drawLine(startWidth-drawStartPixel, startHeight, startWidth+10, startHeight, Color=colorIndex)
+
+ if item.locus.name == nearest:
+ midpoint = [startWidth,startHeight-5]
+ startHeight+=cellHeight
+
+ #XZ, map link to trait name and band
+ COORDS = "%d,%d,%d,%d" %(startWidth-drawStartPixel,topHeight+40,startWidth+10,startHeight)
+ HREF = "javascript:showDatabase2('%s','%s','%s');" % (traitList[order[1]].db.name, traitList[order[1]].name, traitList[order[1]].cellid)
+ area = (COORDS, HREF, '%s' % names[order[1]])
+ areas.append(area)
+
+ if midpoint:
+ traitPixel = ((midpoint[0],midpoint[1]),(midpoint[0]-6,midpoint[1]+12),(midpoint[0]+6,midpoint[1]+12))
+ canvas.drawPolygon(traitPixel,edgeColor=pid.black,fillColor=pid.orange,closed=1)
+
+ if not chrname:
+ canvas.drawString(prechr,xoffset-20,(chrstart+startHeight)/2,font = chrnameFont,color=pid.dimgray)
+ chrname = 1
+ Ncol += 1
+
+
+ #draw Spectrum
+ startSpect = neworder[-1][0] + 30
+ startHeight = topHeight + 40+5+5+strWidth
+
+ if colorScheme == '0':
+ for i in range(100):
+ canvas.drawLine(startSpect+i,startHeight+20,startSpect+i,startHeight+40,color=colors100[i])
+ scaleFont=pid.Font(ttf="tahoma",size=10,bold=0)
+ canvas.drawLine(startSpect,startHeight+45,startSpect,startHeight+39,color=pid.black)
+ canvas.drawString('LRS = 0',startSpect,startHeight+55,font=scaleFont)
+ canvas.drawLine(startSpect+64,startHeight+45,startSpect+64,startHeight+39,color=pid.black)
+ canvas.drawString('Suggestive LRS',startSpect+64,startHeight+55,font=scaleFont)
+ canvas.drawLine(startSpect+99,startHeight+45,startSpect+99,startHeight+39,color=pid.black)
+ canvas.drawString('Significant LRS',startSpect+105,startHeight+40,font=scaleFont)
+ elif colorScheme == '1':
+ for i in range(50):
+ canvas.drawLine(startSpect+i,startHeight,startSpect+i,startHeight+40,color=BWs[20+i])
+ for i in range(50,100):
+ canvas.drawLine(startSpect+i,startHeight,startSpect+i,startHeight+20,color=colors[100-i])
+ canvas.drawLine(startSpect+i,startHeight+20,startSpect+i,startHeight+40,color=colors[30+i])
+
+ canvas.drawLine(startSpect,startHeight+45,startSpect,startHeight+39,color=pid.black)
+ canvas.drawString('LRS = 0',startSpect,startHeight+60,font=scaleFont)
+ canvas.drawLine(startSpect+50,startHeight+45,startSpect+50,startHeight+39,color=pid.black)
+ canvas.drawString('0.5*Suggestive LRS',startSpect+50,startHeight+ 60,font=scaleFont)
+ canvas.drawLine(startSpect+99,startHeight+45,startSpect+99,startHeight+39,color=pid.black)
+ canvas.drawString('Significant LRS',startSpect+105,startHeight+50,font=scaleFont)
+ textFont=pid.Font(ttf="verdana",size=18,bold=0)
+ canvas.drawString('%s +' % ppolar,startSpect+120,startHeight+ 35,font=textFont,color=pid.red)
+ canvas.drawString('%s +' % mpolar,startSpect+120,startHeight+ 15,font=textFont,color=pid.blue)
+ elif colorScheme == '2':
+ for i in range(100):
+ canvas.drawLine(startSpect+i,startHeight,startSpect+i,startHeight+20,color=finecolors[100-i])
+ canvas.drawLine(startSpect+i,startHeight+20,startSpect+i,startHeight+40,color=finecolors[150+i])
+
+ canvas.drawLine(startSpect,startHeight+45,startSpect,startHeight+39,color=pid.black)
+ canvas.drawString('LRS = 0',startSpect,startHeight+60,font=scaleFont)
+ canvas.drawLine(startSpect+99,startHeight+45,startSpect+99,startHeight+39,color=pid.black)
+ canvas.drawString('Significant LRS',startSpect+105,startHeight+50,font=scaleFont)
+ textFont=pid.Font(ttf="verdana",size=18,bold=0)
+ canvas.drawString('%s +' % ppolar,startSpect+120,startHeight+ 35,font=textFont,color=pid.red)
+ canvas.drawString('%s +' % mpolar,startSpect+120,startHeight+ 15,font=textFont,color=pid.blue)
+
+ filename= webqtlUtil.genRandStr("Heatmap_")
+ canvas.save(webqtlConfig.IMGDIR+filename, format='png')
+ if not sessionfile:
+ sessionfile = webqtlUtil.generate_session()
+ webqtlUtil.dump_session(permData, os.path.join(webqtlConfig.TMPDIR, sessionfile +'.session'))
+ self.filename=filename
+ self.areas=areas
+ self.sessionfile=sessionfile
+
+ def getResult(self):
+ return self.filename, self.areas, self.sessionfile
+
+ #XZ, 7/31/2009: This function put the order of traits into parameter neworder,
+ #XZ: return the position of the top vertical line of the hierarchical tree, draw the hierarchical tree.
+ def draw(self,canvas,names,d,xoffset,yoffset,neworder,topHeight):
+ maxDistance = topHeight
+ fontoffset = 4 #XZ, 7/31/2009: used only for drawing tree
+ if type(d[0]) == type(1) and type(d[1]) == type(1):
+ neworder.append((xoffset+20,d[0]))
+ neworder.append((xoffset+40,d[1]))
+ height = d[2]*maxDistance/2
+ canvas.drawLine(xoffset+20-fontoffset,maxDistance+yoffset,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(xoffset+40-fontoffset,maxDistance+yoffset,xoffset+40-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(xoffset+40-fontoffset,maxDistance+yoffset-height,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ return (40,(xoffset+30-fontoffset,maxDistance-height+yoffset))
+ elif type(d[0]) == type(1):
+ neworder.append((xoffset+20,d[0]))
+ d2 = self.draw(canvas,names,d[1],xoffset+20,yoffset,neworder,topHeight)
+ height = d[2]*maxDistance/2
+ canvas.drawLine(xoffset+20-fontoffset,maxDistance+yoffset,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(d2[1][0],d2[1][1],d2[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d2[1][0],maxDistance-height+yoffset,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ return (20+d2[0],((d2[1][0]+xoffset+20-fontoffset)/2,maxDistance-height+yoffset))
+ elif type(d[1]) == type(1):
+ d1 = self.draw(canvas,names,d[0],xoffset,yoffset,neworder,topHeight)
+ neworder.append((xoffset+d1[0]+20,d[1]))
+ height = d[2]*maxDistance/2
+ canvas.drawLine(xoffset+d1[0]+20-fontoffset,maxDistance+yoffset,xoffset+d1[0]+20-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],d1[1][1],d1[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],maxDistance-height+yoffset,xoffset+d1[0]+20-fontoffset,maxDistance-height+yoffset)
+ return (d1[0]+20,((d1[1][0]+xoffset+d1[0]+20-fontoffset)/2,maxDistance-height+yoffset))
+ else:
+ d1 = self.draw(canvas,names,d[0],xoffset,yoffset,neworder,topHeight)
+ d2 = self.draw(canvas,names,d[1],xoffset+d1[0],yoffset,neworder,topHeight)
+ height = d[2]*maxDistance/2
+ canvas.drawLine(d2[1][0],d2[1][1],d2[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],d1[1][1],d1[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],maxDistance-height+yoffset,d2[1][0],maxDistance-height+yoffset)
+ return (d1[0]+d2[0],((d1[1][0]+d2[1][0])/2,maxDistance-height+yoffset))
+
+ #XZ, 7/31/2009: dras trait names
+ def drawTraitNameBottom (self,canvas,names,yoffset,neworder,strWidth,topHeight,labelFont):
+ maxDistance = topHeight
+ for oneOrder in neworder:
+ canvas.drawString(names[oneOrder[1]],oneOrder[0]-5,maxDistance+yoffset+5+strWidth-canvas.stringWidth(names[oneOrder[1]],font=labelFont),font=labelFont,color=pid.black,angle=270)
+
+ def drawTraitNameTop (self,canvas,names,yoffset,neworder,strWidth,topHeight,labelFont):
+ maxDistance = topHeight
+ for oneOrder in neworder:
+ canvas.drawString(names[oneOrder[1]],oneOrder[0]-5,maxDistance+yoffset+5,font=labelFont,color=pid.black,angle=270)
+
+
+ def getNearestMarker(self, traitList, genotype):
+ out = []
+ if not genotype.Mbmap:
+ return [None]* len(traitList)
+ for item in traitList:
+ try:
+ nearest = None
+ for _chr in genotype:
+ if _chr.name != item.chr:
+ continue
+ distance = 1e30
+ for _locus in _chr:
+ if abs(_locus.Mb-item.mb) < distance:
+ distance = abs(_locus.Mb-item.mb)
+ nearest = _locus.name
+ out.append(nearest)
+ except:
+ out.append(None)
+
+ return out
diff --git a/web/webqtl/heatmap/__init__.py b/web/webqtl/heatmap/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/heatmap/__init__.py
diff --git a/web/webqtl/heatmap/heatmapPage.py b/web/webqtl/heatmap/heatmapPage.py
new file mode 100755
index 00000000..b407b0c8
--- /dev/null
+++ b/web/webqtl/heatmap/heatmapPage.py
@@ -0,0 +1,116 @@
+# 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
+
+import os
+import string
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from heatmap.Heatmap import Heatmap
+
+
+# XZ, 09/09/2008: After adding several traits to collection, click "QTL Heatmap" button,
+# XZ, 09/09/2008: This class will generate what you see.
+#########################################
+# QTL heatmap Page
+#########################################
+class heatmapPage(templatePage):
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+ if not fd.genotype:
+ fd.readGenotype()
+
+ searchResult = fd.formdata.getvalue('searchResult')
+ if not searchResult:
+ heading = 'QTL Heatmap'
+ detail = ['You need to select at least two traits in order to generate QTL heatmap.']
+ self.error(heading=heading,detail=detail)
+ return
+ if type("1") == type(searchResult):
+ searchResult = string.split(searchResult,'\t')
+ if searchResult:
+ if len(searchResult) > webqtlConfig.MAXCORR:
+ heading = 'QTL Heatmap'
+ detail = ['In order to display the QTL heat map properly, do not select more than %d traits for analysis.' % webqtlConfig.MAXCORR]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = 'QTL Heatmap'
+ detail = [HT.Font('Error : ',color='red'),HT.Font('Error occurs while retrieving data from database.',color='black')]
+ self.error(heading=heading,detail=detail)
+ return
+ self.dict['title'] = 'QTL heatmap'
+ NNN = len(searchResult)
+ if NNN == 0:
+ heading = "QTL Heatmap"
+ detail = ['No trait was selected for %s data set. No QTL heatmap was generated.' % fd.RISet]
+ self.error(heading=heading,detail=detail)
+ return
+ elif NNN < 2:
+ heading = 'QTL Heatmap'
+ detail = ['You need to select at least two traits in order to generate QTL heatmap.']
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ colorScheme = fd.formdata.getvalue('colorScheme')
+ if not colorScheme:
+ colorScheme = '1'
+ heatmapObject = Heatmap(fd=fd, searchResult=searchResult, colorScheme=colorScheme, userPrivilege=self.privilege, userName=self.userName)
+ filename, areas, sessionfile = heatmapObject.getResult()
+ gifmap = HT.Map(name='traitMap')
+ for area in areas:
+ Areas = HT.Area(shape='rect', coords=area[0], href=area[1], title=area[2])
+ gifmap.areas.append(Areas)
+ img2=HT.Image('/image/'+filename+'.png',border=0,usemap='#traitMap')
+ imgUrl = 'Right-click or control-click on the link to download this graph as a <a href="/image/%s.png" class="normalsize" target="_blank">PNG file</a>' % filename
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_','RISet':fd.RISet,'searchResult':string.join(searchResult,'\t')}
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+ heatmapButton = HT.Input(type='button' ,name='mintmap',value='Redraw QTL Heatmap', onClick="databaseFunc(this.form,'heatmap');",Class="button")
+ spects = {'0':'Single Spectrum','1':'Grey + Blue + Red','2':'Blue + Red'}
+ schemeMenu = HT.Select(name='colorScheme')
+ schemeMenu.append(('Single Spectrum',0))
+ schemeMenu.append(('Grey + Blue + Red',1))
+ schemeMenu.append(('Blue + Red',2))
+ schemeMenu.selected.append(spects[colorScheme])
+ clusterCheck= HT.Input(type='checkbox', Class='checkbox', name='clusterCheck',checked=0)
+ targetDescriptionCheck = HT.Input(type='checkbox', Class='checkbox', name='targetDescriptionCheck',checked=0)
+ form.append(gifmap,schemeMenu, heatmapButton, HT.P(), clusterCheck, ' Cluster traits ', targetDescriptionCheck, ' Add description', HT.P(),img2, HT.P(), imgUrl)
+ form.append(HT.Input(name='session', value=sessionfile, type='hidden'))
+ heatmapHelp = HT.Input(type='button' ,name='heatmapHelpButton',value='Info', onClick="openNewWin('/heatmap.html');",Class="button")
+ heatmapHeading = HT.Paragraph('QTL Heatmap ', heatmapHelp, Class="title")
+ TD_LR = HT.TD(colspan=2,height=200,width="100%",bgColor='#eeeeee')
+ TD_LR.append(heatmapHeading, HT.P(),HT.P(),HT.P(),HT.P(),HT.P(),form)
+ self.dict['body'] = str(TD_LR)
diff --git a/web/webqtl/heatmap/heatmapPage_GN.py b/web/webqtl/heatmap/heatmapPage_GN.py
new file mode 100755
index 00000000..abc5d8aa
--- /dev/null
+++ b/web/webqtl/heatmap/heatmapPage_GN.py
@@ -0,0 +1,522 @@
+# 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
+
+import os
+import string
+import piddle as pid
+import cPickle
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from base.webqtlTrait import webqtlTrait
+from utility import webqtlUtil
+from utility import Plot
+import slink
+
+
+# XZ, 09/09/2008: After adding several traits to collection, click "QTL Heatmap" button,
+# XZ, 09/09/2008: This class will generate what you see.
+#########################################
+# QTL heatmap Page
+#########################################
+class heatmapPage(templatePage):
+
+ labelFont=pid.Font(ttf="tahoma",size=14,bold=0)
+
+ topHeight = 0
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+ if not fd.genotype:
+ fd.readGenotype()
+
+
+ self.searchResult = fd.formdata.getvalue('searchResult')
+
+ if not self.searchResult:
+ templatePage.__init__(self, fd)
+ heading = 'QTL Heatmap'
+ detail = ['You need to select at least two traits in order to generate correlation matrix.']
+ self.error(heading=heading,detail=detail)
+ return
+ if type("1") == type(self.searchResult):
+ self.searchResult = string.split(self.searchResult,'\t')
+
+
+ if self.searchResult:
+ if len(self.searchResult) > webqtlConfig.MAXCORR:
+ heading = 'QTL Heatmap'
+ detail = ['In order to display the QTL heat map properly, do not select more than %d traits for analysis.' % webqtlConfig.MAXCORR]
+ self.error(heading=heading,detail=detail)
+ return
+
+ 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 = 'QTL Heatmap'
+ detail = [HT.Font('Error : ',color='red'),HT.Font('Error occurs while retrieving data from database.',color='black')]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.colorScheme = fd.formdata.getvalue('colorScheme')
+ if not self.colorScheme:
+ self.colorScheme = '1'
+
+ self.dict['title'] = 'QTL heatmap'
+
+ NNN = len(traitList)
+
+ if NNN == 0:
+ heading = "QTL Heatmap"
+ detail = ['No trait was selected for %s data set. No QTL heatmap was generated.' % fd.RISet]
+ self.error(heading=heading,detail=detail)
+ return
+ elif NNN < 2:
+ templatePage.__init__(self, fd)
+ heading = 'QTL Heatmap'
+ detail = ['You need to select at least two traits in order to generate QTL heatmap.']
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ #XZ: It's necessory to define canvas here
+ canvas = pid.PILCanvas(size=(80+NNN*20,880))
+
+ names = map(webqtlTrait.displayName, traitList)
+
+ self.targetDescriptionChecked = fd.formdata.getvalue('targetDescriptionCheck', '')
+
+ #XZ, 7/29/2009: create trait display and find max strWidth
+ strWidth = 0
+ for j in range(len(names)):
+ thisTrait = traitList[j]
+
+ if self.targetDescriptionChecked:
+ if thisTrait.db.type == 'ProbeSet':
+ if thisTrait.probe_target_description:
+ names[j] += ' [%s at Chr %s @ %2.3fMB, %s]' % (thisTrait.symbol, thisTrait.chr, thisTrait.mb, thisTrait.probe_target_description)
+ else:
+ names[j] += ' [%s at Chr %s @ %2.3fMB]' % (thisTrait.symbol, thisTrait.chr, thisTrait.mb)
+ elif thisTrait.db.type == 'Geno':
+ names[j] += ' [Chr %s @ %2.3fMB]' % (thisTrait.chr, thisTrait.mb)
+ elif thisTrait.db.type == 'Publish':
+ if thisTrait.abbreviation:
+ names[j] += ' [%s]' % (thisTrait.abbreviation)
+ else:
+ pass
+ else:
+ pass
+
+ i = canvas.stringWidth(names[j],font=self.labelFont)
+ if i > strWidth:
+ strWidth = i
+
+ width = NNN*20
+ xoffset = 40
+ yoffset = 40
+ cellHeight = 3
+ nLoci = reduce(lambda x,y: x+y, map(lambda x: len(x),fd.genotype),0)
+
+ if nLoci > 2000:
+ cellHeight = 1
+ elif nLoci > 1000:
+ cellHeight = 2
+ elif nLoci < 200:
+ cellHeight = 10
+ else:
+ pass
+
+ pos = range(NNN)
+ neworder = []
+ BWs = Plot.BWSpectrum()
+ colors100 = Plot.colorSpectrum()
+ colors = Plot.colorSpectrum(130)
+ finecolors = Plot.colorSpectrum(250)
+ colors100.reverse()
+ colors.reverse()
+ finecolors.reverse()
+
+ scaleFont=pid.Font(ttf="tahoma",size=10,bold=0)
+
+ self.clusterChecked = fd.formdata.getvalue('clusterCheck', '')
+
+
+ if not self.clusterChecked: #XZ: this part is for original order
+ for i in range(len(names)):
+ neworder.append((xoffset+20*(i+1), i))
+
+ canvas = pid.PILCanvas(size=(80+NNN*20+240,80+ self.topHeight +5+5+strWidth+nLoci*cellHeight+80+20*cellHeight))
+
+ self.drawTraitNameBottom(canvas,names,yoffset,neworder,strWidth)
+ else: #XZ: this part is to cluster traits
+ self.topHeight = 400
+ canvas = pid.PILCanvas(size=(80+NNN*20+240,80+ self.topHeight +5+5+strWidth+nLoci*cellHeight+80+20*cellHeight))
+
+ corArray = [([0] * (NNN))[:] for i in range(NNN)]
+
+ nnCorr = len(fd.strainlist)
+
+ #XZ, 08/04/2009: I commented out pearsonArray, spearmanArray
+ 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)
+ if (1-corr) < 0:
+ distance = 0.0
+ else:
+ distance = 1-corr
+ corArray[i][j] = distance
+ corArray[j][i] = distance
+ elif j == i:
+ corArray[i][j] = 0.0
+ else:
+ pass
+
+ #XZ, 7/29/2009: The parameter d has info of cluster (group member and distance). The format of d is tricky. Print it out to see it's format.
+ d = slink.slink(corArray)
+
+ #XZ, 7/29/2009: Attention: The 'neworder' is changed by the 'draw' function
+ #XZ, 7/30/2009: Only toppos[1][0] and top[1][1] are used later. Then what toppos[0] is used for?
+ toppos = self.draw(canvas,names,d,xoffset,yoffset,neworder)
+ self.drawTraitNameTop(canvas,names,yoffset,neworder,strWidth)
+
+ #XZ, 7/29/2009: draw the top vertical line
+ canvas.drawLine(toppos[1][0],toppos[1][1],toppos[1][0],yoffset)
+
+ #XZ: draw string 'distance = 1-r'
+ canvas.drawString('distance = 1-r',neworder[-1][0] + 50, self.topHeight*3/4,font=self.labelFont,angle=90)
+
+ #draw Scale
+ scaleFont=pid.Font(ttf="tahoma",size=10,bold=0)
+ x = neworder[-1][0]
+ canvas.drawLine(x+5, self.topHeight+yoffset, x+5, yoffset, color=pid.black)
+ y = 0
+ while y <=2:
+ canvas.drawLine(x+5, self.topHeight*y/2.0+yoffset, x+10, self.topHeight*y/2.0+yoffset)
+ canvas.drawString('%2.1f' % (2-y), x+12, self.topHeight*y/2.0+yoffset, font=scaleFont)
+ y += 0.5
+
+
+ chrname = 0
+ chrnameFont=pid.Font(ttf="tahoma",size=24,bold=0)
+ Ncol = 0
+
+ gifmap = HT.Map(name='traitMap')
+
+ nearestMarkers = self.getNearestMarker(traitList, fd.genotype)
+
+ # import cPickle
+ sessionfile = fd.formdata.getvalue("session")
+
+ if sessionfile:
+ fp = open(os.path.join(webqtlConfig.TMPDIR, sessionfile + '.session'), 'rb')
+ permData = cPickle.load(fp)
+ fp.close()
+ else:
+ permData = {}
+
+ #XZ, 7/31/2009: This for loop is to generate the heatmap
+ #XZ: draw trait by trait instead of marker by marker
+ for order in neworder:
+ #startHeight = 40+400+5+5+strWidth
+ startHeight = self.topHeight + 40+5+5+strWidth
+ startWidth = order[0]-5
+ if Ncol and Ncol % 5 == 0:
+ drawStartPixel = 8
+ else:
+ drawStartPixel = 9
+
+ tempVal = traitDataList[order[1]]
+ _vals = []
+ _strains = []
+ for i in range(len(fd.strainlist)):
+ if tempVal[i] != None:
+ _strains.append(fd.strainlist[i])
+ _vals.append(tempVal[i])
+
+ qtlresult = fd.genotype.regression(strains = _strains, trait = _vals)
+
+ if sessionfile:
+ LRSArray = permData[str(traitList[order[1]])]
+ else:
+ LRSArray = fd.genotype.permutation(strains = _strains, trait = _vals, nperm = 1000)
+ permData[str(traitList[order[1]])] = LRSArray
+
+ sugLRS = LRSArray[369]
+ sigLRS = LRSArray[949]
+ prechr = 0
+ chrstart = 0
+ nearest = nearestMarkers[order[1]]
+ midpoint = []
+
+ for item in qtlresult:
+ if item.lrs > webqtlConfig.MAXLRS:
+ adjustlrs = webqtlConfig.MAXLRS
+ else:
+ adjustlrs = item.lrs
+
+ if item.locus.chr != prechr:
+ if prechr:
+ canvas.drawRect(startWidth-drawStartPixel, startHeight, startWidth+10, startHeight+3,edgeColor=pid.white, edgeWidth=0, fillColor=pid.white)
+ startHeight+= 3
+ if not chrname:
+ canvas.drawString(prechr,xoffset-20,(chrstart+startHeight)/2,font = chrnameFont,color=pid.dimgray)
+ prechr = item.locus.chr
+ chrstart = startHeight
+ if self.colorScheme == '0':
+ if adjustlrs <= sugLRS:
+ colorIndex = int(65*adjustlrs/sugLRS)
+ else:
+ colorIndex = int(65 + 35*(adjustlrs-sugLRS)/(sigLRS-sugLRS))
+ if colorIndex > 99:
+ colorIndex = 99
+ colorIndex = colors100[colorIndex]
+ elif self.colorScheme == '1':
+ sugLRS = LRSArray[369]/2.0
+ if adjustlrs <= sugLRS:
+ colorIndex = BWs[20+int(50*adjustlrs/sugLRS)]
+ else:
+ if item.additive > 0:
+ colorIndex = int(80 + 50*(adjustlrs-sugLRS)/(sigLRS-sugLRS))
+ else:
+ colorIndex = int(50 - 50*(adjustlrs-sugLRS)/(sigLRS-sugLRS))
+ if colorIndex > 129:
+ colorIndex = 129
+ if colorIndex < 0:
+ colorIndex = 0
+ colorIndex = colors[colorIndex]
+ elif self.colorScheme == '2':
+ if item.additive > 0:
+ colorIndex = int(150 + 100*(adjustlrs/sigLRS))
+ else:
+ colorIndex = int(100 - 100*(adjustlrs/sigLRS))
+ if colorIndex > 249:
+ colorIndex = 249
+ if colorIndex < 0:
+ colorIndex = 0
+ colorIndex = finecolors[colorIndex]
+ else:
+ colorIndex = pid.white
+
+ if startHeight > 1:
+ canvas.drawRect(startWidth-drawStartPixel, startHeight, startWidth+10, startHeight+cellHeight,edgeColor=colorIndex, edgeWidth=0, fillColor=colorIndex)
+ else:
+ canvas.drawLine(startWidth-drawStartPixel, startHeight, startWidth+10, startHeight, Color=colorIndex)
+
+ if item.locus.name == nearest:
+ midpoint = [startWidth,startHeight-5]
+ startHeight+=cellHeight
+
+ #XZ, map link to trait name and band
+ COORDS = "%d,%d,%d,%d" %(startWidth-drawStartPixel,self.topHeight+40,startWidth+10,startHeight)
+ HREF = "javascript:showDatabase2('%s','%s','%s');" % (traitList[order[1]].db.name, traitList[order[1]].name, traitList[order[1]].cellid)
+ Areas = HT.Area(shape='rect',coords=COORDS,href=HREF, title='%s' % names[order[1]])
+ gifmap.areas.append(Areas)
+
+ if midpoint:
+ traitPixel = ((midpoint[0],midpoint[1]),(midpoint[0]-6,midpoint[1]+12),(midpoint[0]+6,midpoint[1]+12))
+ canvas.drawPolygon(traitPixel,edgeColor=pid.black,fillColor=pid.orange,closed=1)
+
+ if not chrname:
+ canvas.drawString(prechr,xoffset-20,(chrstart+startHeight)/2,font = chrnameFont,color=pid.dimgray)
+ chrname = 1
+ Ncol += 1
+
+
+ #draw Spectrum
+ startSpect = neworder[-1][0] + 30
+ startHeight = self.topHeight + 40+5+5+strWidth
+
+ if self.colorScheme == '0':
+ for i in range(100):
+ canvas.drawLine(startSpect+i,startHeight+20,startSpect+i,startHeight+40,color=colors100[i])
+ scaleFont=pid.Font(ttf="tahoma",size=10,bold=0)
+ canvas.drawLine(startSpect,startHeight+45,startSpect,startHeight+39,color=pid.black)
+ canvas.drawString('LRS = 0',startSpect,startHeight+55,font=scaleFont)
+ canvas.drawLine(startSpect+64,startHeight+45,startSpect+64,startHeight+39,color=pid.black)
+ canvas.drawString('Suggestive LRS',startSpect+64,startHeight+55,font=scaleFont)
+ canvas.drawLine(startSpect+99,startHeight+45,startSpect+99,startHeight+39,color=pid.black)
+ canvas.drawString('Significant LRS',startSpect+105,startHeight+40,font=scaleFont)
+ elif self.colorScheme == '1':
+ for i in range(50):
+ canvas.drawLine(startSpect+i,startHeight,startSpect+i,startHeight+40,color=BWs[20+i])
+ for i in range(50,100):
+ canvas.drawLine(startSpect+i,startHeight,startSpect+i,startHeight+20,color=colors[100-i])
+ canvas.drawLine(startSpect+i,startHeight+20,startSpect+i,startHeight+40,color=colors[30+i])
+
+ canvas.drawLine(startSpect,startHeight+45,startSpect,startHeight+39,color=pid.black)
+ canvas.drawString('LRS = 0',startSpect,startHeight+60,font=scaleFont)
+ canvas.drawLine(startSpect+50,startHeight+45,startSpect+50,startHeight+39,color=pid.black)
+ canvas.drawString('0.5*Suggestive LRS',startSpect+50,startHeight+ 60,font=scaleFont)
+ canvas.drawLine(startSpect+99,startHeight+45,startSpect+99,startHeight+39,color=pid.black)
+ canvas.drawString('Significant LRS',startSpect+105,startHeight+50,font=scaleFont)
+ textFont=pid.Font(ttf="verdana",size=18,bold=0)
+ canvas.drawString('%s +' % fd.ppolar,startSpect+120,startHeight+ 35,font=textFont,color=pid.red)
+ canvas.drawString('%s +' % fd.mpolar,startSpect+120,startHeight+ 15,font=textFont,color=pid.blue)
+ elif self.colorScheme == '2':
+ for i in range(100):
+ canvas.drawLine(startSpect+i,startHeight,startSpect+i,startHeight+20,color=finecolors[100-i])
+ canvas.drawLine(startSpect+i,startHeight+20,startSpect+i,startHeight+40,color=finecolors[150+i])
+
+ canvas.drawLine(startSpect,startHeight+45,startSpect,startHeight+39,color=pid.black)
+ canvas.drawString('LRS = 0',startSpect,startHeight+60,font=scaleFont)
+ canvas.drawLine(startSpect+99,startHeight+45,startSpect+99,startHeight+39,color=pid.black)
+ canvas.drawString('Significant LRS',startSpect+105,startHeight+50,font=scaleFont)
+ textFont=pid.Font(ttf="verdana",size=18,bold=0)
+ canvas.drawString('%s +' % fd.ppolar,startSpect+120,startHeight+ 35,font=textFont,color=pid.red)
+ canvas.drawString('%s +' % fd.mpolar,startSpect+120,startHeight+ 15,font=textFont,color=pid.blue)
+
+
+ filename= webqtlUtil.genRandStr("Heatmap_")
+ canvas.save(webqtlConfig.IMGDIR+filename, format='png')
+ img2=HT.Image('/image/'+filename+'.png',border=0,usemap='#traitMap')
+ imgUrl = 'Right-click or control-click on the link to download this graph as a <a href="/image/%s.png" class="normalsize" target="_blank">PNG file</a>' % filename
+
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_','RISet':fd.RISet,'searchResult':string.join(self.searchResult,'\t')}
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ heatmap = HT.Input(type='button' ,name='mintmap',value='Redraw QTL Heatmap', onClick="databaseFunc(this.form,'heatmap');",Class="button")
+ spects = {'0':'Single Spectrum','1':'Grey + Blue + Red','2':'Blue + Red'}
+ schemeMenu = HT.Select(name='colorScheme')
+ schemeMenu.append(('Single Spectrum',0))
+ schemeMenu.append(('Grey + Blue + Red',1))
+ schemeMenu.append(('Blue + Red',2))
+ schemeMenu.selected.append(spects[self.colorScheme])
+
+ clusterCheck= HT.Input(type='checkbox', Class='checkbox', name='clusterCheck',checked=0)
+ targetDescriptionCheck = HT.Input(type='checkbox', Class='checkbox', name='targetDescriptionCheck',checked=0)
+
+ form.append(gifmap,schemeMenu, heatmap, HT.P(), clusterCheck, ' Cluster traits ', targetDescriptionCheck, ' Add description', HT.P(),img2, HT.P(), imgUrl)
+
+ if not sessionfile:
+ filename = webqtlUtil.generate_session()
+ webqtlUtil.dump_session(permData, os.path.join(webqtlConfig.TMPDIR, filename +'.session'))
+ sessionfile=filename
+
+ form.append(HT.Input(name='session', value=sessionfile, type='hidden'))
+
+ heatmapHelp = HT.Input(type='button' ,name='heatmapHelpButton',value='Info', onClick="openNewWin('/heatmap.html');",Class="button")
+
+ heatmapHeading = HT.Paragraph('QTL Heatmap ', heatmapHelp, Class="title")
+
+ TD_LR = HT.TD(colspan=2,height=200,width="100%",bgColor='#eeeeee')
+ TD_LR.append(heatmapHeading, HT.P(),HT.P(),HT.P(),HT.P(),HT.P(),form)
+
+ self.dict['body'] = str(TD_LR)
+
+ #XZ, 7/31/2009: This function put the order of traits into parameter neworder,
+ #XZ: return the position of the top vertical line of the hierarchical tree, draw the hierarchical tree.
+ def draw(self,canvas,names,d,xoffset,yoffset,neworder):
+ maxDistance = self.topHeight
+ fontoffset = 4 #XZ, 7/31/2009: used only for drawing tree
+
+ if type(d[0]) == type(1) and type(d[1]) == type(1):
+ neworder.append((xoffset+20,d[0]))
+ neworder.append((xoffset+40,d[1]))
+ height = d[2]*maxDistance/2
+ canvas.drawLine(xoffset+20-fontoffset,maxDistance+yoffset,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(xoffset+40-fontoffset,maxDistance+yoffset,xoffset+40-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(xoffset+40-fontoffset,maxDistance+yoffset-height,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ return (40,(xoffset+30-fontoffset,maxDistance-height+yoffset))
+ elif type(d[0]) == type(1):
+ neworder.append((xoffset+20,d[0]))
+ d2 = self.draw(canvas,names,d[1],xoffset+20,yoffset,neworder)
+ height = d[2]*maxDistance/2
+ canvas.drawLine(xoffset+20-fontoffset,maxDistance+yoffset,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(d2[1][0],d2[1][1],d2[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d2[1][0],maxDistance-height+yoffset,xoffset+20-fontoffset,maxDistance-height+yoffset)
+ return (20+d2[0],((d2[1][0]+xoffset+20-fontoffset)/2,maxDistance-height+yoffset))
+ elif type(d[1]) == type(1):
+ d1 = self.draw(canvas,names,d[0],xoffset,yoffset,neworder)
+ neworder.append((xoffset+d1[0]+20,d[1]))
+ height = d[2]*maxDistance/2
+ canvas.drawLine(xoffset+d1[0]+20-fontoffset,maxDistance+yoffset,xoffset+d1[0]+20-fontoffset,maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],d1[1][1],d1[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],maxDistance-height+yoffset,xoffset+d1[0]+20-fontoffset,maxDistance-height+yoffset)
+ return (d1[0]+20,((d1[1][0]+xoffset+d1[0]+20-fontoffset)/2,maxDistance-height+yoffset))
+ else:
+ d1 = self.draw(canvas,names,d[0],xoffset,yoffset,neworder)
+ d2 = self.draw(canvas,names,d[1],xoffset+d1[0],yoffset,neworder)
+ height = d[2]*maxDistance/2
+ canvas.drawLine(d2[1][0],d2[1][1],d2[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],d1[1][1],d1[1][0],maxDistance-height+yoffset)
+ canvas.drawLine(d1[1][0],maxDistance-height+yoffset,d2[1][0],maxDistance-height+yoffset)
+ return (d1[0]+d2[0],((d1[1][0]+d2[1][0])/2,maxDistance-height+yoffset))
+
+ #XZ, 7/31/2009: dras trait names
+ def drawTraitNameBottom (self,canvas,names,yoffset,neworder,strWidth):
+ maxDistance = self.topHeight
+
+ for oneOrder in neworder:
+ canvas.drawString(names[oneOrder[1]],oneOrder[0]-5,maxDistance+yoffset+5+strWidth-canvas.stringWidth(names[oneOrder[1]],font=self.labelFont),font=self.labelFont,color=pid.black,angle=270)
+
+ def drawTraitNameTop (self,canvas,names,yoffset,neworder,strWidth):
+ maxDistance = self.topHeight
+
+ for oneOrder in neworder:
+ canvas.drawString(names[oneOrder[1]],oneOrder[0]-5,maxDistance+yoffset+5,font=self.labelFont,color=pid.black,angle=270)
+
+
+ def getNearestMarker(self,traitList, genotype):
+ out = []
+ if not genotype.Mbmap:
+ return [None]* len(traitList)
+ for item in traitList:
+ try:
+ nearest = None
+ for _chr in genotype:
+ if _chr.name != item.chr:
+ continue
+ distance = 1e30
+ for _locus in _chr:
+ if abs(_locus.Mb-item.mb) < distance:
+ distance = abs(_locus.Mb-item.mb)
+ nearest = _locus.name
+ out.append(nearest)
+ except:
+ out.append(None)
+
+ return out
+
+
+
+
diff --git a/web/webqtl/heatmap/slink.py b/web/webqtl/heatmap/slink.py
new file mode 100755
index 00000000..3de41de4
--- /dev/null
+++ b/web/webqtl/heatmap/slink.py
@@ -0,0 +1,141 @@
+# 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
+
+#--Only imported by correlationPage.py.
+#
+#Functions:
+#slink(lists) -- the only function called outside of this file.
+#nearest(lists,i,j) -- some sort of recursive function.
+#printarray(array,n) -- prints n elements of the given array
+#this is a myseterious piece of code in GN that Kev Adler and Rob Williams do not understand.
+#but is used in some way by the Traits Correlation function
+#Kev and Rob suspect that the d2 matrix below is unused
+#We do not understand the signifance of "d" but Kev suspects it is unimportant
+#These comments by Kev and Rob: May 23, 2008
+
+d = [[0,9,3,6,11],[9,0,7,5,10],[3,7,0,9,2],[6,5,9,0,8],[11,10,2,8,0]]
+d2 = [[0,9,5.5,6,11],[9,0,7,5,10],[5.5,7,0,9,2],[6,5,9,0,3],[11,10,2,3,0]]
+
+def nearest(lists,i,j):
+ if type(i) == type(1) and type(j) == type(1):
+ return lists[i][j]
+ elif type(i) == type(1):
+ dist = 1e10
+ for itemj in j[:-1]:
+ d = nearest(lists,i,itemj)
+ if dist > d:
+ dist = d
+ elif type(j) == type(1):
+ dist = 1e10
+ for itemi in i[:-1]:
+ d = nearest(lists,itemi,j)
+ if dist > d:
+ dist = d
+ else:
+ dist = 1e10
+ for itemi in i[:-1]:
+ for itemj in j[:-1]:
+ d = nearest(lists,itemi,itemj)
+ if dist > d:
+ dist = d
+ return dist
+
+def printarray(array,n):
+ print "\n"
+ for i in range(n):
+ print array[i][:n]
+ print "\n"
+
+def slink(lists):
+ try:
+ if type(lists) != type([]) and type(lists) != type(()):
+ raise 'FormatError'
+ else:
+ size = len(lists)
+ for item in lists:
+ if type(item) != type([]) and type(item) != type(()):
+ raise 'FormatError'
+ else:
+ if len(item) != size:
+ raise 'LengthError'
+ for i in range(size):
+ if lists[i][i] != 0:
+ raise 'ValueError'
+ for j in range(0,i):
+ if lists[i][j] < 0:
+ raise 'ValueError'
+ if lists[i][j] != lists[j][i]:
+ raise 'MirrorError'
+ except 'FormatError':
+ print "the format of the list is incorrect!"
+ return []
+ except 'LengthError':
+ print "the list is not a square list!"
+ return []
+ except 'MirrorError':
+ print "the list is not symmetric!"
+ return []
+ except 'ValueError':
+ print "the distance is negative value!"
+ return []
+ except:
+ print "Unknown Error"
+ return []
+ listindex = range(size)
+ listindexcopy = range(size)
+ listscopy = []
+ for i in range(size):
+ listscopy.append(lists[i][:])
+ initSize = size
+ candidate = []
+ while initSize >2:
+ mindist = 1e10
+ for i in range(initSize):
+ for j in range(i+1,initSize):
+ if listscopy[i][j] < mindist:
+ mindist = listscopy[i][j]
+ candidate=[[i,j]]
+ elif listscopy[i][j] == mindist:
+ mindist = listscopy[i][j]
+ candidate.append([i,j])
+ else:
+ pass
+ newmem = (listindexcopy[candidate[0][0]],listindexcopy[candidate[0][1]],mindist)
+ listindexcopy.pop(candidate[0][1])
+ listindexcopy[candidate[0][0]] = newmem
+
+ initSize -= 1
+ for i in range(initSize):
+ for j in range(i+1,initSize):
+ listscopy[i][j] = nearest(lists,listindexcopy[i],listindexcopy[j])
+ listscopy[j][i] = listscopy[i][j]
+ #print listindexcopy
+ #printarray(listscopy,initSize)
+ listindexcopy.append(nearest(lists,listindexcopy[0],listindexcopy[1]))
+ return listindexcopy
+
+
+
diff --git a/web/webqtl/intervalAnalyst/GeneUtil.py b/web/webqtl/intervalAnalyst/GeneUtil.py
new file mode 100755
index 00000000..43008ecf
--- /dev/null
+++ b/web/webqtl/intervalAnalyst/GeneUtil.py
@@ -0,0 +1,124 @@
+# 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
+
+import string
+
+#Just return a list of dictionaries
+#each dictionary contains sub-dictionary
+def loadGenes(cursor, chrName, diffCol, startMb, endMb, webqtlDb =None, species='mouse'):
+ #cursor.execute("desc GeneList")
+ #results = cursor.fetchall()
+ #fetchFields = map(lambda X:X[0], results)
+ fetchFields = ['SpeciesId', 'Id', 'GeneSymbol', 'GeneDescription', 'Chromosome', 'TxStart', 'TxEnd',
+ 'Strand', 'GeneID', 'NM_ID', 'kgID', 'GenBankID', 'UnigenID', 'ProteinID', 'AlignID',
+ 'exonCount', 'exonStarts', 'exonEnds', 'cdsStart', 'cdsEnd']
+
+ ##List All Species in the Gene Table
+ speciesDict = {}
+ cursor.execute("select Species.Name, GeneList.SpeciesId from Species, GeneList where \
+ GeneList.SpeciesId = Species.Id group by GeneList.SpeciesId")
+ results = cursor.fetchall()
+ for item in results:
+ speciesDict[item[0]] = item[1]
+
+ ##List current Species and other Species
+ speciesId = speciesDict[species]
+ otherSpecies = map(lambda X: [X, speciesDict[X]], speciesDict.keys())
+ otherSpecies.remove([species, speciesId])
+
+ cursor.execute("""SELECT %s from GeneList
+ where
+ SpeciesId = %d AND Chromosome = '%s' AND
+ ((TxStart > %f and TxStart <= %f) OR (TxEnd > %f and TxEnd <= %f))
+ order by txStart
+ """
+ % (string.join(fetchFields, ", "), speciesId, chrName, startMb, endMb, startMb, endMb))
+ results = cursor.fetchall()
+ GeneList = []
+
+ if results:
+ for result in results:
+ newdict = {}
+ for j, item in enumerate(fetchFields):
+ newdict[item] = result[j]
+ #count SNPs if possible
+ if diffCol and species=='mouse':
+ cursor.execute("""
+ select
+ count(*) from BXDSnpPosition
+ where
+ Chr = '%s' AND Mb >= %2.6f AND Mb < %2.6f AND
+ StrainId1 = %d AND StrainId2 = %d
+ """ % (chrName, newdict["TxStart"], newdict["TxEnd"], diffCol[0], diffCol[1]))
+ newdict["snpCount"] = cursor.fetchone()[0]
+ newdict["snpDensity"] = newdict["snpCount"]/(newdict["TxEnd"]-newdict["TxStart"])/1000.0
+ else:
+ newdict["snpDensity"] = newdict["snpCount"] = 0
+
+ try:
+ newdict['GeneLength'] = 1000.0*(newdict['TxEnd'] - newdict['TxStart'])
+ except:
+ pass
+
+ #load gene from other Species by the same name
+ for item in otherSpecies:
+ othSpec, othSpecId = item
+ newdict2 = {}
+
+ cursor.execute("SELECT %s from GeneList where SpeciesId = %d and geneSymbol= '%s' limit 1" %
+ (string.join(fetchFields, ", "), othSpecId, newdict["GeneSymbol"]))
+ resultsOther = cursor.fetchone()
+ if resultsOther:
+ for j, item in enumerate(fetchFields):
+ newdict2[item] = resultsOther[j]
+
+ #count SNPs if possible, could be a separate function
+ if diffCol and othSpec == 'mouse':
+ cursor.execute("""
+ select
+ count(*) from BXDSnpPosition
+ where
+ Chr = '%s' AND Mb >= %2.6f AND Mb < %2.6f AND
+ StrainId1 = %d AND StrainId2 = %d
+ """ % (chrName, newdict["TxStart"], newdict["TxEnd"], diffCol[0], diffCol[1]))
+
+ newdict2["snpCount"] = cursor.fetchone()[0]
+ newdict2["snpDensity"] = newdict2["snpCount"]/(newdict2["TxEnd"]-newdict2["TxStart"])/1000.0
+ else:
+ newdict2["snpDensity"] = newdict2["snpCount"] = 0
+
+ try:
+ newdict2['GeneLength'] = 1000.0*(newdict2['TxEnd'] - newdict2['TxStart'])
+ except:
+ pass
+
+ newdict['%sGene' % othSpec] = newdict2
+
+ GeneList.append(newdict)
+
+ return GeneList
+
+
diff --git a/web/webqtl/intervalAnalyst/IntervalAnalystPage.py b/web/webqtl/intervalAnalyst/IntervalAnalystPage.py
new file mode 100755
index 00000000..ec9aa29c
--- /dev/null
+++ b/web/webqtl/intervalAnalyst/IntervalAnalystPage.py
@@ -0,0 +1,405 @@
+# 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 mod_python import apache, util, Cookie
+import os
+import time
+import pyXLWriter as xl
+
+from htmlgen import HTMLgen2 as HT
+
+import GeneUtil
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+
+class IntervalAnalystPage(templatePage):
+ filename = webqtlUtil.genRandStr("Itan_")
+
+ _scriptfile = "main.py?FormID=intervalAnalyst"
+
+ #A dictionary that lets us map the html form names "txStart_mm6" -> "Mb Start (mm8)"
+ #the first item is the short name (column headers) and the second item is the long name (dropdown list)
+ # [short name, long name, category]
+ columnNames = {"GeneSymbol" : ["Gene", "Gene Name", 'gene'],
+ "GeneDescription" : ["Description", "Gene Description", 'species'],
+ 'GeneNeighborsCount' : ["Neighbors", "Gene Neighbors", 'gene'],
+ 'GeneNeighborsRange' : ["Neighborhood", "Gene Neighborhood (Mb)", 'gene'],
+ 'GeneNeighborsDensity' : ["Gene Density", "Gene Density (Neighbors/Mb)", 'gene'],
+ "ProteinID" : ["Prot ID", "Protein ID", 'protein'],
+ "Chromosome" : ["Chr", "Chromosome", 'species'],
+ "TxStart" : ["Start", "Mb Start", 'species'],
+ "TxEnd" : ["End", "Mb End", 'species'],
+ "GeneLength" : ["Length", "Kb Length", 'species'],
+ "cdsStart" : ["CDS Start", "Mb CDS Start", 'species'],
+ "cdsEnd" : ["CDS End", "Mb CDS End", 'species'],
+ "exonCount" : ["Num Exons", "Exon Count", 'species'],
+ "exonStarts" : ["Exon Starts", "Exon Starts", 'species'],
+ "exonEnds" : ["Exon Ends", "Exon Ends", 'species'],
+ "Strand" : ["Strand", "Strand", 'species'],
+ "GeneID" : ["Gene ID", "Gene ID", 'species'],
+ "GenBankID" : ["GenBank", "GenBank ID", 'species'],
+ "UnigenID" : ["Unigen", "Unigen ID", 'species'],
+ "NM_ID" : ["NM ID", "NM ID", 'species'],
+ "kgID" : ["kg ID", "kg ID", 'species'],
+ "snpCount" : ["SNPs", "SNP Count", 'species'],
+ "snpDensity" : ["SNP Density", "SNP Density", 'species'],
+ "lrs" : ["LRS", "Likelihood Ratio Statistic", 'misc'],
+ "lod" : ["LOD", "Likelihood Odds Ratio", 'misc'],
+ "pearson" : ["Pearson", "Pearson Product Moment", 'misc'],
+ "literature" : ["Lit Corr", "Literature Correlation", 'misc'],
+ }
+
+ ###Species Freeze
+ speciesFreeze = {'mouse':'mm9', 'rat':'rn3', 'human':'hg19'}
+ for key in speciesFreeze.keys():
+ speciesFreeze[speciesFreeze[key]] = key
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ fd.formdata['remote_ip'] = fd.remote_ip
+ if not self.openMysql():
+ return
+
+ self.species = fd.formdata.getvalue("species", "mouse")
+ try:
+ self.startMb = float(fd.formdata.getvalue("startMb"))
+ except:
+ self.startMb = 10
+ try:
+ self.endMb = float(fd.formdata.getvalue("endMb"))
+ except:
+ self.endMb = self.startMb + 10
+
+ self.Chr = fd.formdata.getvalue("chromosome", "1")
+ self.xls = fd.formdata.getvalue("xls", "1")
+ try:
+ s1 = int(fd.formdata.getvalue("s1"))
+ s2 = int(fd.formdata.getvalue("s2"))
+ self.diffColDefault = self.diffCol = [s1, s2]
+ except:
+ self.diffColDefault = self.diffCol = []
+ if self.species != 'mouse':
+ self.diffColDefault = [2, 3]#default is B6 and D2 for other species
+
+ controlFrm, dispFields = self.genControlForm(fd)
+ geneTable, filename = self.genGeneTable(fd, dispFields)
+
+ infoTD = HT.TD(width=400, valign= "top")
+ infoTD.append(HT.Paragraph("Interval Analyst : Chr %s" % self.Chr, Class="title"),
+ HT.Strong("Species : "), self.species.title(), HT.BR(),
+ HT.Strong("Database : "), "UCSC %s" % self.speciesFreeze[self.species], HT.BR(),
+ HT.Strong("Range : "), "%2.6f Mb - %2.6f Mb" % (self.startMb, self.endMb), HT.BR(),
+ )
+ if filename:
+ infoTD.append(HT.BR(), HT.BR(), HT.Href(text="Download", url = "/tmp/" + filename, Class="normalsize")
+ , " output in MS excel format.")
+
+ mainTable = HT.TableLite(HT.TR(infoTD, HT.TD(controlFrm, Class="doubleBorder", width=400), HT.TD("&nbsp;", width="")), cellpadding=10)
+ mainTable.append(HT.TR(HT.TD(geneTable, colspan=3)))
+ self.dict['body'] = HT.TD(mainTable)
+ self.dict['title'] = "Interval Analyst"
+
+ def genGeneTable(self, fd, dispFields):
+ filename = ""
+ if self.xls:
+ #import pyXLWriter as xl
+ filename = "IntAn_Chr%s_%2.6f-%2.6f" % (self.Chr, self.startMb, self.endMb)
+ filename += ".xls"
+
+ # Create a new Excel workbook
+ workbook = xl.Writer(os.path.join(webqtlConfig.TMPDIR, filename))
+ worksheet = workbook.add_worksheet()
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=18, border = 1, border_color="gray")
+ headingStyle = workbook.add_format(align = 'center', bold = 1, size=13, fg_color = 0x1E, color="white", border = 1, border_color="gray")
+
+ ##Write title Info
+ worksheet.write([0, 0], "GeneNetwork Interval Analyst Table", titleStyle)
+ worksheet.write([1, 0], "%s%s" % (webqtlConfig.PORTADDR, os.path.join(webqtlConfig.CGIDIR, self._scriptfile)))
+ #
+ worksheet.write([2, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()))
+ worksheet.write([3, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()))
+ worksheet.write([4, 0], "Search by : %s" % fd.formdata['remote_ip'])
+ worksheet.write([5, 0], "view region : Chr %s %2.6f - %2.6f Mb" % (self.Chr, self.startMb, self.endMb))
+ nTitleRow = 7
+
+ geneTable = HT.TableLite(Class="collap", cellpadding=5)
+ headerRow = HT.TR(HT.TD(" ", Class="fs13 fwb ffl b1 cw cbrb", width="1"))
+ if self.xls:
+ worksheet.write([nTitleRow, 0], "Index", headingStyle)
+
+ for ncol, column in enumerate(dispFields):
+ if len(column) == 1:
+ headerRow.append(HT.TD(self.columnNames[column[0]][0], Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = self.columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ else:
+ headerRow.append(HT.TD(self.columnNames[column[0]][0], HT.BR(), " (%s)" % self.speciesFreeze[column[1]],
+ Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1, align="Center"))
+ if self.xls:
+ colTitle = self.columnNames[column[0]][0] + " (%s)" % self.speciesFreeze[column[1]]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ #headerRow.append(HT.TD(self.columnNames[column[0]][0], HT.BR(),
+ # "(%s %s)" % (column[1].title(), self.speciesFreeze[column[1]]),
+ # Class="colorBlue", NOWRAP=1, align="Center"))
+ geneTable.append(headerRow)
+
+ geneCol = GeneUtil.loadGenes(self.cursor, self.Chr, self.diffColDefault, self.startMb, self.endMb, species=self.species)
+ for gIndex, theGO in enumerate(geneCol):
+ geneRow = HT.TR(HT.TD(gIndex+1, Class="fs12 fwn b1", align="right"))
+ if self.xls:
+ nTitleRow += 1
+ worksheet.write([nTitleRow, 0], gIndex + 1)
+
+ for ncol, column in enumerate(dispFields):
+ if len(column) == 1 or column[1]== self.species:
+ keyValue = ""
+ fieldName = column[0]
+ curSpecies = self.species
+ curGO = theGO
+ if theGO.has_key(fieldName):
+ keyValue = theGO[fieldName]
+ else:
+ fieldName , othSpec = column
+ curSpecies = othSpec
+ subGO = '%sGene' % othSpec
+ keyValue = ""
+ curGO = theGO[subGO]
+ if theGO[subGO].has_key(fieldName):
+ keyValue = theGO[subGO][fieldName]
+
+ if self.xls:
+ worksheet.write([nTitleRow, ncol+1], keyValue)
+ geneRow.append(self.formatTD(keyValue, fieldName, curSpecies, curGO))
+
+ geneTable.append(geneRow)
+
+ if self.xls:
+ workbook.close()
+ return geneTable, filename
+
+ def formatTD(self, keyValue, fieldName, Species, theGO):
+ if keyValue is None:
+ keyValue = ""
+ if keyValue != "":
+ if fieldName in ("exonStarts", "exonEnds"):
+ keyValue = string.replace(keyValue, ',', ' ')
+ return HT.TD(HT.Span(keyValue, Class="code", Id="green"), width=350, Class="fs12 fwn b1")
+ elif fieldName in ("GeneDescription"):
+ if keyValue == "---":
+ keyValue = ""
+ return HT.TD(keyValue, Class="fs12 fwn b1", width=300)
+ elif fieldName in ("GeneSymbol"):
+ webqtlLink = HT.Href("./%s?cmd=sch&gene=%s&alias=1&species=%s" % (webqtlConfig.SCRIPTFILE, keyValue, Species),
+ HT.Image("/images/webqtl_search.gif", border=0, valign="top"), target="_blank")
+ if theGO['GeneID']:
+ geneSymbolLink = HT.Href(webqtlConfig.NCBI_LOCUSID % theGO['GeneID'], keyValue, Class="normalsize", target="_blank")
+ else:
+ geneSymbolLink = keyValue
+ return HT.TD(webqtlLink, geneSymbolLink, Class="fs12 fwn b1",NOWRAP=1)
+ elif fieldName == 'UnigenID':
+ try:
+ gurl = HT.Href(webqtlConfig.UNIGEN_ID % tuple(string.split(keyValue,'.')[:2]), keyValue, Class="normalsize", target="_blank")
+ except:
+ gurl = keyValue
+ return HT.TD(gurl, Class="fs12 fwn b1",NOWRAP=1)
+ elif fieldName in ("exonCount", "Chromosome"):
+ return HT.TD(keyValue, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("snpCount"):
+ if keyValue:
+ snpString = HT.Href(url="%s&chr=%s&start=%s&end=%s&geneName=%s&s1=%d&s2=%d" % (os.path.join(webqtlConfig.CGIDIR, 'main.py?FormID=snpBrowser'),
+ theGO["Chromosome"], theGO["TxStart"], theGO["TxEnd"], theGO["GeneSymbol"], self.diffColDefault[0], self.diffColDefault[1]),
+ text=theGO["snpCount"], target="_blank", Class="normalsize")
+ else:
+ snpString = keyValue
+ return HT.TD(snpString, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("snpDensity", "GeneLength"):
+ if keyValue: keyValue = "%2.3f" % keyValue
+ else: keyValue = ""
+ return HT.TD(keyValue, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("TxStart", "TxEnd"):
+ return HT.TD("%2.6f" % keyValue, Class="fs12 fwn b1",align="right")
+ else:
+ return HT.TD(keyValue, Class="fs12 fwn b1",NOWRAP=1)
+ else:
+ return HT.TD(keyValue, Class="fs12 fwn b1",NOWRAP=1,align="right")
+
+ def genControlForm(self, fd):
+ ##desc GeneList
+ self.cursor.execute("Desc GeneList")
+ GeneListFields = self.cursor.fetchall()
+ GeneListFields = map(lambda X: X[0], GeneListFields)
+
+ #group columns by category--used for creating the dropdown list of possible columns
+ categories = {}
+ for item in self.columnNames.keys():
+ category = self.columnNames[item]
+ if category[-1] not in categories.keys():
+ categories[category[-1]] = [item ]
+ else:
+ categories[category[-1]] = categories[category[-1]]+[item]
+
+ ##List All Species in the Gene Table
+ speciesDict = {}
+ self.cursor.execute("select Species.Name, GeneList.SpeciesId from Species, GeneList where \
+ GeneList.SpeciesId = Species.Id group by GeneList.SpeciesId order by Species.Id")
+ results = self.cursor.fetchall()
+ speciesField = categories.pop('species', [])
+ categoriesOrder = ['gene', 'protein']
+ for item in results:
+ specName, specId = item
+ categoriesOrder.append(specName)
+ speciesDict[specName] = specId
+ AppliedField = []
+ for item2 in speciesField:
+ if item2 in GeneListFields:
+ self.cursor.execute("select %s from GeneList where SpeciesId = %d and %s is not NULL limit 1 " % (item2, specId, item2))
+ columnApply = self.cursor.fetchone()
+ if not columnApply:
+ continue
+ elif specName != 'mouse' and item2 in ('snpCount', 'snpDensity'):
+ continue
+ else:
+ pass
+ AppliedField.append(item2)
+ categories[specName] = AppliedField
+
+ categoriesOrder += ['misc']
+
+ ############################################################
+ ## Create the list of possible columns for the dropdown list
+ ############################################################
+ allColumnsList = HT.Select(name="allColumns", Class="snpBrowserDropBox")
+
+ for category in categoriesOrder:
+ allFields = categories[category]
+ if allFields:
+ geneOpt = HT.Optgroup(label=category.title())
+ for item in allFields:
+ if category in self.speciesFreeze.keys():
+ geneOpt.append(("%s (%s %s)" % (self.columnNames[item][1], category.title(), self.speciesFreeze[category]),
+ "%s__%s" % (item, self.speciesFreeze[category])))
+ else:
+ geneOpt.append((self.columnNames[item][1], item))
+ geneOpt.sort()
+ allColumnsList.append(geneOpt)
+
+ ######################################
+ ## Create the list of selected columns
+ ######################################
+
+ #cols contains the value of all the selected columns
+ submitCols = cols = fd.formdata.getvalue("columns", "default")
+
+ if cols == "default":
+ if self.species=="mouse": #these are the same columns that are shown on intervalPage.py
+ cols = ['GeneSymbol', 'GeneDescription', 'Chromosome', 'TxStart', 'Strand', 'GeneLength', 'GeneID', 'NM_ID', 'snpCount', 'snpDensity']
+ elif self.species=="rat":
+ cols = ['GeneSymbol', 'GeneDescription', 'Chromosome', 'TxStart', 'GeneLength', 'Strand', 'GeneID', 'UnigenID']
+ else:
+ #should not happen
+ cols = []
+ else:
+ if type(cols)==type(""):
+ cols = [cols]
+
+ colsLst = []
+ dispFields = []
+ for column in cols:
+ if submitCols == "default" and column not in ('GeneSymbol') and (column in GeneListFields or column in speciesField):
+ colsLst.append(("%s (%s %s)" % (self.columnNames[column][1], self.species.title(), self.speciesFreeze[self.species]),
+ "%s__%s" % (column, self.speciesFreeze[self.species])))
+ dispFields.append([column, self.species])
+ else:
+ column2 = column.split("__")
+ if len(column2) == 1:
+ colsLst.append((self.columnNames[column2[0]][1], column))
+ dispFields.append([column])
+ else:
+ thisSpecies = self.speciesFreeze[column2[1]]
+ colsLst.append(("%s (%s %s)" % (self.columnNames[column2[0]][1], thisSpecies.title(), column2[1]),
+ column))
+ dispFields.append((column2[0], thisSpecies))
+ selectedColumnsList = HT.Select(name="columns", Class="snpBrowserSelectBox", multiple="true", data=colsLst, size=6)
+
+ ##########################
+ ## Create the columns form
+ ##########################
+ columnsForm = HT.Form(name="columnsForm", submit=HT.Input(type='hidden'), cgi=os.path.join(webqtlConfig.CGIDIR, self._scriptfile), enctype="multipart/form-data")
+ columnsForm.append(HT.Input(type="hidden", name="fromdatabase", value= fd.formdata.getvalue("fromdatabase", "unknown")))
+ columnsForm.append(HT.Input(type="hidden", name="species", value=self.species))
+ if self.diffCol:
+ columnsForm.append(HT.Input(type="hidden", name="s1", value=self.diffCol[0]))
+ columnsForm.append(HT.Input(type="hidden", name="s2", value=self.diffCol[1]))
+ startBox = HT.Input(type="text", name="startMb", value=self.startMb, size=10)
+ endBox = HT.Input(type="text", name="endMb", value=self.endMb, size=10)
+ addButton = HT.Input(type="button", name="add", value="Add", Class="button", onClick="addToList(this.form.allColumns.options[this.form.allColumns.selectedIndex].text, this.form.allColumns.options[this.form.allColumns.selectedIndex].value, this.form.columns)")
+ removeButton = HT.Input(type="button", name="remove", value="Remove", Class="button", onClick="removeFromList(this.form.columns.selectedIndex, this.form.columns)")
+ upButton = HT.Input(type="button", name="up", value="Up", Class="button", onClick="swapOptions(this.form.columns.selectedIndex, this.form.columns.selectedIndex-1, this.form.columns)")
+ downButton = HT.Input(type="button", name="down", value="Down", Class="button", onClick="swapOptions(this.form.columns.selectedIndex, this.form.columns.selectedIndex+1, this.form.columns)")
+ clearButton = HT.Input(type="button", name="clear", value="Clear", Class="button", onClick="deleteAllElements(this.form.columns)")
+ submitButton = HT.Input(type="submit", value="Refresh", Class="button", onClick="selectAllElements(this.form.columns)")
+
+ selectChrBox = HT.Select(name="chromosome")
+ self.cursor.execute("""
+ Select
+ Chr_Length.Name, Length from Chr_Length, Species
+ where
+ Chr_Length.SpeciesId = Species.Id AND
+ Species.Name = '%s'
+ Order by
+ Chr_Length.OrderId
+ """ % self.species)
+
+ results = self.cursor.fetchall()
+ for chrInfo in results:
+ selectChrBox.append((chrInfo[0], chrInfo[0]))
+ selectChrBox.selected.append(self.Chr)
+
+ innerColumnsTable = HT.TableLite(border=0, Class="collap", cellpadding = 2)
+ innerColumnsTable.append(HT.TR(HT.TD(selectedColumnsList)),
+ HT.TR(HT.TD(clearButton, removeButton, upButton, downButton)))
+ columnsTable = HT.TableLite(border=0, cellpadding=2, cellspacing=0)
+ columnsTable.append(HT.TR(HT.TD(HT.Font("Chr: ", size=-1)),
+ HT.TD(selectChrBox, submitButton)),
+ HT.TR(HT.TD(HT.Font("View: ", size=-1)),
+ HT.TD(startBox, HT.Font("Mb to ", size=-1), endBox, HT.Font("Mb", size=-1))),
+ HT.TR(HT.TD(HT.Font("Show: ", size=-1)),
+ HT.TD(allColumnsList, addButton)),
+ HT.TR(HT.TD(""),
+ HT.TD(innerColumnsTable)))
+ columnsForm.append(columnsTable)
+ #columnsForm.append(HT.Input(type="hidden", name="sort", value=diffCol),
+ # HT.Input(type="hidden", name="identification", value=identification),
+ # HT.Input(type="hidden", name="traitInfo", value=traitInfo))
+
+ return columnsForm, dispFields
diff --git a/web/webqtl/intervalAnalyst/__init__.py b/web/webqtl/intervalAnalyst/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/intervalAnalyst/__init__.py
diff --git a/web/webqtl/intervalMapping/IntervalMappingPage.py b/web/webqtl/intervalMapping/IntervalMappingPage.py
new file mode 100644
index 00000000..4bdf45ab
--- /dev/null
+++ b/web/webqtl/intervalMapping/IntervalMappingPage.py
@@ -0,0 +1,2454 @@
+# 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 Zach 12/14/2010
+
+
+import time
+import string
+from math import *
+import piddle as pid
+import sys,os
+import httplib, urllib
+
+from htmlgen import HTMLgen2 as HT
+from utility import Plot
+from intervalAnalyst import GeneUtil
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+from base.GeneralObject import GeneralObject
+
+#########################################
+# Inteval Mapping Plot Page
+#########################################
+class IntervalMappingPage(templatePage):
+ cMGraphInterval = 5
+ maxBootStrap = 50
+ GRAPH_MIN_WIDTH = 900
+ GRAPH_MAX_WIDTH = 10000 # Don't set this too high
+ GRAPH_DEFAULT_WIDTH = 1280
+ MULT_GRAPH_DEFAULT_WIDTH = 2000
+ MULT_GRAPH_MIN_WIDTH = 1400
+ MULT_GRAPH_DEFAULT_WIDTH = 1600
+ GRAPH_DEFAULT_HEIGHT = 600
+
+
+ # Display order:
+ # UCSC BAND =========
+ # ENSEMBL BAND -=-=-=
+ # ** GENES **********
+ BAND_SPACING = 4
+
+ #ENSEMBL_BAND_Y = UCSC_BAND_Y + UCSC_BAND_HEIGHT + BAND_SPACING
+ UCSC_BAND_HEIGHT = 10
+ ENSEMBL_BAND_HEIGHT = 10
+ WEBQTL_BAND_HEIGHT = 10
+
+ #GENE_START_Y = ENSEMBL_BAND_Y + ENSEMBL_BAND_HEIGHT + BAND_SPACING
+ NUM_GENE_ROWS = 10
+ EACH_GENE_HEIGHT = 6 # number of pixels tall, for each gene to display
+ EACH_GENE_ARROW_WIDTH = 5
+ EACH_GENE_ARROW_SPACING = 14
+ DRAW_DETAIL_MB = 4
+ DRAW_UTR_LABELS_MB = 4
+
+ MIN_PIXELS_BETWEEN_LABELS = 50
+
+ qmarkImg = HT.Image('/images/qmarkBoxBlue.gif', width=10, height=13, border=0, alt='Glossary')
+ # Note that "qmark.gif" is a similar, smaller, rounded-edges question mark. It doesn't look
+ # like the ones on the image, though, which is why we don't use it here.
+
+ HELP_WINDOW_NAME = 'helpWind'
+
+ ## BEGIN HaplotypeAnalyst
+ NR_INDIVIDUALS = 0
+ ## END HaplotypeAnalyst
+
+ ALEX_DEBUG_BOOL_COLORIZE_GENES = 1 # 0=don't colorize, 1=colorize
+ ALEX_DEBUG_BOOL_PRINT_GENE_LIST = 1
+
+ kWIDTH_DEFAULT=1
+
+ kONE_MILLION = 1000000
+
+ LODFACTOR = 4.61
+
+ SNP_COLOR = pid.orange # Color for the SNP "seismograph"
+ TRANSCRIPT_LOCATION_COLOR = pid.mediumpurple
+
+ GENE_FILL_COLOR = pid.HexColor(0x6666FF)
+ GENE_OUTLINE_COLOR = pid.HexColor(0x000077)
+ BOOTSTRAP_BOX_COLOR = pid.yellow
+ LRS_COLOR = pid.HexColor(0x0000FF)
+ LRS_LINE_WIDTH = 2
+ SIGNIFICANT_COLOR = pid.HexColor(0xEBC7C7)
+ SUGGESTIVE_COLOR = pid.gainsboro
+ SIGNIFICANT_WIDTH = 5
+ SUGGESTIVE_WIDTH = 5
+ ADDITIVE_COLOR_POSITIVE = pid.green
+ ADDITIVE_COLOR_NEGATIVE = pid.red
+ ADDITIVE_COLOR = ADDITIVE_COLOR_POSITIVE
+ DOMINANCE_COLOR_POSITIVE = pid.darkviolet
+ DOMINANCE_COLOR_NEGATIVE = pid.orange
+
+ ## BEGIN HaplotypeAnalyst
+ HAPLOTYPE_POSITIVE = pid.green
+ HAPLOTYPE_NEGATIVE = pid.red
+ HAPLOTYPE_HETEROZYGOUS = pid.blue
+ HAPLOTYPE_RECOMBINATION = pid.darkgray
+ ## END HaplotypeAnalyst
+
+ QMARK_EDGE_COLOR = pid.HexColor(0x718118)
+ QMARK_FILL_COLOR = pid.HexColor(0xDEE3BB)
+
+ TOP_RIGHT_INFO_COLOR = pid.black
+ X_AXIS_LABEL_COLOR = pid.black #HexColor(0x505050)
+
+ MINI_VIEW_MAGNIFIED_REGION_COLOR = pid.HexColor(0xCC0000)
+ MINI_VIEW_OUTSIDE_REGION_COLOR = pid.HexColor(0xEEEEEE)
+ MINI_VIEW_BORDER_COLOR = pid.black
+
+ CLICKABLE_WEBQTL_REGION_COLOR = pid.HexColor(0xF5D3D3)
+ CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR = pid.HexColor(0xFCE9E9)
+ CLICKABLE_WEBQTL_TEXT_COLOR = pid.HexColor(0x912828)
+
+ CLICKABLE_UCSC_REGION_COLOR = pid.HexColor(0xDDDDEE)
+ CLICKABLE_UCSC_REGION_OUTLINE_COLOR = pid.HexColor(0xEDEDFF)
+ CLICKABLE_UCSC_TEXT_COLOR = pid.HexColor(0x333366)
+
+ CLICKABLE_ENSEMBL_REGION_COLOR = pid.HexColor(0xEEEEDD)
+ CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR = pid.HexColor(0xFEFEEE)
+ CLICKABLE_ENSEMBL_TEXT_COLOR = pid.HexColor(0x555500)
+
+ GRAPH_BACK_LIGHT_COLOR = pid.HexColor(0xFBFBFF)
+ GRAPH_BACK_DARK_COLOR = pid.HexColor(0xF1F1F9)
+
+ HELP_PAGE_REF = '/glossary.html'
+
+ DRAW_UTR_LABELS=0
+
+ def __init__(self,fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ #RISet and Species
+ if not fd.genotype:
+ fd.readGenotype()
+
+ fd.parentsf14regression = fd.formdata.getvalue('parentsf14regression')
+
+ if ((fd.parentsf14regression == 'on') and fd.genotype_2):
+ fd.genotype = fd.genotype_2
+ else:
+ fd.genotype = fd.genotype_1
+ fd.strainlist = list(fd.genotype.prgy)
+
+ self.species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+ if self.species == "rat":
+ self._ucscDb = "rn3"
+ elif self.species == "mouse":
+ self._ucscDb = "mm9"
+ else:
+ self._ucscDb = ""
+
+ #####################################
+ # Options
+ #####################################
+ #Mapping options
+ self.plotScale = fd.formdata.getvalue('scale', 'physic')
+ if self.plotScale == 'physic' and not fd.genotype.Mbmap:
+ self.plotScale = 'morgan'
+ self.permChecked = fd.formdata.getvalue('permCheck')
+ self.bootChecked = fd.formdata.getvalue('bootCheck', '')
+ self.controlLocus = fd.formdata.getvalue('controlLocus', '')
+ try:
+ self.selectedChr = int(fd.formdata.getvalue('chromosomes', "-1"))
+ except:
+ self.selectedChr = -1
+
+ #whether include parents and F1 for InbredSet
+ fd.parentsf14regression = fd.formdata.getvalue('parentsf14regression')
+ if ((fd.parentsf14regression == 'on') and fd.genotype_2):
+ fd.genotype = fd.genotype_2
+ else:
+ fd.genotype = fd.genotype_1
+ self.strainlist = list(fd.genotype.prgy)
+ self.genotype = fd.genotype
+
+ #Darwing Options
+ try:
+ if self.selectedChr > -1:
+ self.graphWidth = min(self.GRAPH_MAX_WIDTH, max(self.GRAPH_MIN_WIDTH, int(fd.formdata.getvalue('graphWidth'))))
+ else:
+ self.graphWidth = min(self.GRAPH_MAX_WIDTH, max(self.MULT_GRAPH_MIN_WIDTH, int(fd.formdata.getvalue('graphWidth'))))
+ except:
+ if self.selectedChr > -1:
+ self.graphWidth = self.GRAPH_DEFAULT_WIDTH
+ else:
+ self.graphWidth = self.MULT_GRAPH_DEFAULT_WIDTH
+
+## BEGIN HaplotypeAnalyst
+ self.haplotypeAnalystChecked = fd.formdata.getvalue('haplotypeAnalystCheck')
+## END HaplotypeAnalyst
+
+
+ self.graphHeight = self.GRAPH_DEFAULT_HEIGHT
+ self.additiveChecked = fd.formdata.getvalue('additiveCheck')
+ self.dominanceChecked = fd.formdata.getvalue('dominanceCheck')
+ self.LRS_LOD = fd.formdata.getvalue('LRSCheck', 'LRS')
+ self.intervalAnalystChecked = fd.formdata.getvalue('intervalAnalystCheck')
+ self.legendChecked = fd.formdata.getvalue('viewLegend')
+ self.geneChecked = fd.formdata.getvalue('showGenes')
+ self.SNPChecked = fd.formdata.getvalue('showSNP')
+ self.draw2X = fd.formdata.getvalue('draw2X')
+ self.lrsMax = float(fd.formdata.getvalue('lrsMax', 0))
+
+ self.startMb = fd.formdata.getvalue('startMb', "-1")
+ self.endMb = fd.formdata.getvalue('endMb', "-1")
+ try:
+ self.startMb = float(self.startMb)
+ self.endMb = float(self.endMb)
+ if self.startMb > self.endMb:
+ temp = self.startMb
+ self.startMb = self.endMb
+ self.endMb = temp
+ #minimal distance 10bp
+ if self.endMb - self.startMb < 0.00001:
+ self.endMb = self.startMb + 0.00001
+ except:
+ self.startMb = self.endMb = -1
+ #Trait Infos
+ self.identification = fd.formdata.getvalue('identification', "")
+
+ ################################################################
+ # Generate Chr list and Retrieve Length Information
+ ################################################################
+ self.ChrList = [("All", -1)]
+ for i, indChr in enumerate(self.genotype):
+ self.ChrList.append((indChr.name, i))
+
+ self.cursor.execute("""
+ Select
+ Length from Chr_Length, InbredSet
+ where
+ Chr_Length.SpeciesId = InbredSet.SpeciesId AND
+ InbredSet.Name = '%s' AND
+ Chr_Length.Name in (%s)
+ Order by
+ OrderId
+ """ % (fd.RISet, string.join(map(lambda X: "'%s'" % X[0], self.ChrList[1:]), ", ")))
+
+ self.ChrLengthMbList = self.cursor.fetchall()
+ self.ChrLengthMbList = map(lambda x: x[0]/1000000.0, self.ChrLengthMbList)
+ self.ChrLengthMbSum = reduce(lambda x, y:x+y, self.ChrLengthMbList, 0.0)
+ if self.ChrLengthMbList:
+ self.MbGraphInterval = self.ChrLengthMbSum/(len(self.ChrLengthMbList)*12) #Empirical Mb interval
+ else:
+ self.MbGraphInterval = 1
+
+ self.ChrLengthCMList = []
+ for i, _chr in enumerate(self.genotype):
+ self.ChrLengthCMList.append(_chr[-1].cM - _chr[0].cM)
+ self.ChrLengthCMSum = reduce(lambda x, y:x+y, self.ChrLengthCMList, 0.0)
+
+ if self.plotScale == 'physic':
+ self.GraphInterval = self.MbGraphInterval #Mb
+ else:
+ self.GraphInterval = self.cMGraphInterval #cM
+
+
+ ################################################################
+ # Get Trait Values and Infomation
+ ################################################################
+ #input from search page or selection page
+ self.searchResult = fd.formdata.getvalue('searchResult')
+ #convert single selection into a list
+ if type("1") == type(self.searchResult):
+ self.searchResult = string.split(self.searchResult,'\t')
+
+ self.traitList = []
+ if self.searchResult and len(self.searchResult) > webqtlConfig.MULTIPLEMAPPINGLIMIT:
+ heading = 'Multiple Interval Mapping'
+ detail = ['In order to get clear result, do not select more than %d traits for \
+ Multiple Interval Mapping analysis.' % webqtlConfig.MULTIPLEMAPPINGLIMIT]
+ self.error(heading=heading,detail=detail)
+ return
+ elif self.searchResult:
+ self.dataSource = 'selectionPage'
+ for item in self.searchResult:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo()
+ thisTrait.retrieveData(fd.strainlist)
+ self.traitList.append(thisTrait)
+ else:
+ #input from data editing page
+ fd.readData()
+ if not fd.allTraitData:
+ heading = "Mapping"
+ detail = ['No trait data was selected for %s data set. No mapping attempted.' % fd.RISet]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.dataSource = 'editingPage'
+ fullname = fd.formdata.getvalue('fullname', '')
+ if fullname:
+ thisTrait = webqtlTrait(fullname=fullname, data=fd.allTraitData, cursor=self.cursor)
+ thisTrait.retrieveInfo()
+ else:
+ thisTrait = webqtlTrait(data=fd.allTraitData)
+ self.traitList.append(thisTrait)
+
+
+
+
+
+
+
+## BEGIN HaplotypeAnalyst
+## count the amount of individuals to be plotted, and increase self.graphHeight
+ if self.haplotypeAnalystChecked and self.selectedChr > -1:
+ thisTrait = self.traitList[0]
+ _strains, _vals, _vars = thisTrait.exportInformative()
+ smd=[]
+ for ii, _val in enumerate(_vals):
+ temp = GeneralObject(name=_strains[ii], value=_val)
+ smd.append(temp)
+ bxdlist=list(self.genotype.prgy)
+ for j,_geno in enumerate (self.genotype[0][1].genotype):
+ for item in smd:
+ if item.name == bxdlist[j]:
+ self.NR_INDIVIDUALS = self.NR_INDIVIDUALS + 1
+## default:
+ self.graphHeight = self.graphHeight + 2 * (self.NR_INDIVIDUALS+10) * self.EACH_GENE_HEIGHT
+## for paper:
+ #self.graphHeight = self.graphHeight + 1 * self.NR_INDIVIDUALS * self.EACH_GENE_HEIGHT - 180
+
+
+
+## END HaplotypeAnalyst
+
+ ################################################################
+ # Calculations QTL goes here
+ ################################################################
+ self.multipleInterval = len(self.traitList) > 1
+ errorMessage = self.calculateAllResult(fd)
+ if errorMessage:
+ heading = "Mapping"
+ detail = ['%s' % errorMessage]
+ self.error(heading=heading,detail=detail)
+ return
+
+ if self.multipleInterval:
+ self.colorCollection = Plot.colorSpectrum(len(self.qtlresults))
+ else:
+ self.colorCollection = [self.LRS_COLOR]
+
+
+ #########################
+ ## Get the sorting column
+ #########################
+ RISet = fd.RISet
+ if RISet in ('AXB', 'BXA', 'AXBXA'):
+ self.diffCol = ['B6J', 'A/J']
+ elif RISet in ('BXD', 'BXD300', 'B6D2F2', 'BDF2-2005', 'BDF2-1999', 'BHHBF2'):
+ self.diffCol = ['B6J', 'D2J']
+ elif RISet in ('CXB'):
+ self.diffCol = ['CBY', 'B6J']
+ elif RISet in ('BXH', 'BHF2'):
+ self.diffCol = ['B6J', 'C3H']
+ elif RISet in ('B6BTBRF2'):
+ self.diffCol = ['B6J', 'BTB']
+ elif RISet in ('LXS'):
+ self.diffCol = ['ILS', 'ISS']
+ else:
+ self.diffCol= []
+
+ for i, strain in enumerate(self.diffCol):
+ self.cursor.execute("select Id from Strain where Symbol = %s", strain)
+ self.diffCol[i] = self.cursor.fetchone()[0]
+ #print self.diffCol
+
+ ################################################################
+ # GeneCollection goes here
+ ################################################################
+ if self.plotScale == 'physic':
+ #StartMb or EndMb
+ if self.startMb < 0 or self.endMb < 0:
+ self.startMb = 0
+ self.endMb = self.ChrLengthMbList[self.selectedChr]
+
+ geneTable = ""
+ if self.plotScale == 'physic' and self.selectedChr > -1 and (self.intervalAnalystChecked or self.geneChecked):
+ chrName = self.genotype[0].name
+ # Draw the genes for this chromosome / region of this chromosome
+ if self.traitList and self.traitList[0] and len(self.traitList) == 1 and self.traitList[0].db:
+ webqtldatabase = self.traitList[0].db.name
+ else:
+ webqtldatabase = None
+
+ self.geneCol = None
+
+ if self.species == "mouse":
+ self.geneCol = GeneUtil.loadGenes(self.cursor, chrName, self.diffCol, self.startMb, self.endMb, webqtldatabase, "mouse")
+ elif self.species == "rat":
+ self.geneCol = GeneUtil.loadGenes(self.cursor, chrName, self.diffCol, self.startMb, self.endMb, webqtldatabase, "rat")
+ else:
+ self.geneCol = None
+
+ if self.geneCol and self.intervalAnalystChecked:
+ #######################################################################
+ #Nick use GENEID as RefGene to get Literature Correlation Informations#
+ #For Interval Mapping, Literature Correlation isn't useful, so skip it#
+ #through set GENEID is None #
+ ########################################################################
+
+ #GENEID = fd.formdata.getvalue('GeneId') or None
+ GENEID = None
+ geneTable = self.geneTables(self.geneCol,GENEID)
+
+ else:
+ self.geneCol = None
+
+ ################################################################
+ # Plots goes here
+ ################################################################
+ if self.plotScale != 'physic' or self.multipleInterval:
+ showLocusForm = webqtlUtil.genRandStr("fm_")
+ else:
+ showLocusForm = ""
+ intCanvas = pid.PILCanvas(size=(self.graphWidth,self.graphHeight))
+ gifmap = self.plotIntMapping(fd, intCanvas, startMb = self.startMb, endMb = self.endMb, showLocusForm= showLocusForm)
+
+ filename= webqtlUtil.genRandStr("Itvl_")
+ intCanvas.save(os.path.join(webqtlConfig.IMGDIR, filename), format='png')
+ intImg=HT.Image('/image/'+filename+'.png', border=0, usemap='#WebQTLImageMap')
+
+ if self.draw2X:
+ intCanvasX2 = pid.PILCanvas(size=(self.graphWidth*2,self.graphHeight*2))
+ gifmapX2 = self.plotIntMapping(fd, intCanvasX2, startMb = self.startMb, endMb = self.endMb, showLocusForm= showLocusForm, zoom=2)
+ intCanvasX2.save(os.path.join(webqtlConfig.IMGDIR, filename+"X2"), format='png')
+ DLintImgX2=HT.Href(text='Download',url = '/image/'+filename+'X2.png', Class='smallsize', target='_blank')
+
+ textUrl = self.writeQTL2Text(fd, filename)
+
+ ################################################################
+ # Info tables goes here
+ ################################################################
+ traitInfoTD = self.traitInfoTD(fd)
+
+ if self.draw2X:
+ traitInfoTD.append(HT.P(), DLintImgX2, ' a higher resolution 2X image. ')
+ else:
+ traitInfoTD.append(HT.P())
+
+ if textUrl:
+ traitInfoTD.append(HT.BR(), textUrl, ' results in tab-delimited text format.')
+ traitRemapTD = self.traitRemapTD(self.cursor, fd)
+
+ topTable = HT.TableLite(HT.TR(traitInfoTD, HT.TD("&nbsp;", width=25), traitRemapTD), border=0, cellspacing=0, cellpadding=0)
+
+ ################################################################
+ # Outputs goes here
+ ################################################################
+ #this form is used for opening Locus page or trait page, only available for genetic mapping
+ if showLocusForm:
+ showLocusForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data',
+ name=showLocusForm, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase', 'ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_', 'RISet':fd.RISet, 'incparentsf1':'ON'}
+ for key in hddn.keys():
+ showLocusForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+ showLocusForm.append(intImg)
+ else:
+ showLocusForm = intImg
+
+ ################################################################
+ # footnote goes here
+ ################################################################
+ btminfo = HT.Paragraph(Id="smallsize") #Small('More information about this graph is available here.')
+
+ if (self.additiveChecked):
+ btminfo.append(HT.BR(), 'A positive additive coefficient (', HT.Font('green', color='green'), ' line) indicates that %s alleles increase trait values. In contrast, a negative additive coefficient (' % fd.ppolar, HT.Font('red', color='red'), ' line) indicates that %s alleles increase trait values.' % fd.mpolar)
+
+ if self.traitList and self.traitList[0].db and self.traitList[0].db.type == 'Geno':
+ btminfo.append(HT.BR(), 'Mapping using genotype data as a trait will result in infinity LRS at one locus. In order to display the result properly, all LRSs higher than 100 are capped at 100.')
+
+ TD_LR = HT.TD(HT.Blockquote(topTable), HT.Blockquote(gifmap, showLocusForm, HT.P(), btminfo), bgColor='#eeeeee', height = 200)
+
+ if geneTable:
+ iaForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, "main.py?FormID=intervalAnalyst"), enctype='multipart/form-data',
+ name="iaForm", submit=HT.Input(type='hidden'))
+ hddn = {'chromosome':self.genotype[0].name, 'species':self.species,'startMb':self.startMb,'endMb':self.endMb}
+ if self.diffCol:
+ hddn['s1'] = self.diffCol[0]
+ hddn['s2'] = self.diffCol[1]
+ for key in hddn.keys():
+ iaForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+ iaForm.append(HT.Paragraph("Interval Analyst : Chr %s from %2.6f to %2.6f Mb" % (self.genotype[0].name, self.startMb, self.endMb),
+ HT.Input(name='customize', value='Customize', onClick= "formInNewWindow(this.form);", type='button', Class="button"), Class="subtitle"))
+ TD_LR.append(HT.Blockquote(iaForm, geneTable))
+
+ self.dict['body'] = TD_LR
+ self.dict['title'] = "Mapping"
+
+ def writeQTL2Text(self, fd, filename):
+ if self.multipleInterval:
+ return ""
+ _dominance = (self.genotype.type == 'intercross')
+ _Mb = self.genotype.Mbmap
+
+ ###Write to text file
+ fpText = open(os.path.join(webqtlConfig.TMPDIR, filename) + '.txt','wb')
+
+ fpText.write("Source: WebQTL, The GeneNetwork (%s)\n" % webqtlConfig.PORTADDR)
+ #
+ fpText.write("Site: %s\n" % webqtlConfig.SITENAME)
+ fpText.write("Page: Map Viewer\n")
+ fpText.write(time.strftime("Date and Time (US Center): %b %d, %Y at %I.%M %p\n", time.localtime()))
+ fpText.write("Trait ID: %s\n" % fd.identification)
+ fpText.write("Suggestive LRS = %0.2f\n" % self.suggestive)
+ fpText.write("Significant LRS = %0.2f\n" % self.significance)
+ """
+ if fd.traitInfo:
+ writeSymbol, writeChromosome, writeMb = string.split(fd.traitInfo)
+ else:
+ writeSymbol, writeChromosome, writeMb = (" ", " ", " ")
+ fpText.write("Gene Symbol: %s\n" % writeSymbol)
+ fpText.write("Location: Chr %s @ %s Mb\n" % (writeChromosome, writeMb))
+ selectedChr = self.indexToChrName(int(fd.formdata.getvalue('chromosomes', -1)))
+ fpText.write("Chromosome: %s\n" % selectedChr)
+ fpText.write("Region: %0.6f-%0.6f Mb\n\n" % (self.startMb, self.endMb))
+ """
+
+ if hasattr(self, 'LRSArray'):
+ if _dominance:
+ fpText.write('Chr\tLocus\tcM\tMb\tLRS\tP-value\tAdditive\tDominance\n')
+ else:
+ fpText.write('Chr\tLocus\tcM\tMb\tLRS\tP-value\tAdditive\n')
+ else:
+ if _dominance:
+ fpText.write('Chr\tLocus\tcM\tMb\tLRS\tAdditive\tDominance\n')
+ else:
+ fpText.write('Chr\tLocus\tcM\tMb\tLRS\tAdditive\n')
+
+ i = 0
+ for qtlresult in self.qtlresults[0]:
+ if _Mb:
+ locusMb = '%2.3f' % qtlresult.locus.Mb
+ else:
+ locusMb = 'N/A'
+
+ if hasattr(self, 'LRSArray'):
+ P_value = self.calculatePValue(qtlresult.lrs, self.LRSArray)
+
+ if _dominance:
+ fpText.write("%s\t%s\t%2.3f\t%s\t%2.3f\t%2.3f\t%2.3f\t%2.3f\n" %(qtlresult.locus.chr, \
+ qtlresult.locus.name, qtlresult.locus.cM, locusMb , qtlresult.lrs, P_value, qtlresult.additive, qtlresult.dominance))
+ else:
+ fpText.write("%s\t%s\t%2.3f\t%s\t%2.3f\t%2.3f\t%2.3f\n" %(qtlresult.locus.chr, \
+ qtlresult.locus.name, qtlresult.locus.cM, locusMb , qtlresult.lrs, P_value, qtlresult.additive))
+ else:
+ if _dominance:
+ fpText.write("%s\t%s\t%2.3f\t%s\t%2.3f\t%2.3f\t%2.3f\n" %(qtlresult.locus.chr, \
+ qtlresult.locus.name, qtlresult.locus.cM, locusMb , qtlresult.lrs, qtlresult.additive, qtlresult.dominance))
+ else:
+ fpText.write("%s\t%s\t%2.3f\t%s\t%2.3f\t%2.3f\n" %(qtlresult.locus.chr, \
+ qtlresult.locus.name, qtlresult.locus.cM, locusMb , qtlresult.lrs, qtlresult.additive))
+
+ i += 1
+
+ fpText.close()
+ textUrl = HT.Href(text = 'Download', url= '/tmp/'+filename+'.txt', target = "_blank", Class='smallsize')
+ return textUrl
+
+ def plotIntMapping(self, fd, canvas, offset= (80, 120, 20, 80), zoom = 1, startMb = None, endMb = None, showLocusForm = ""):
+ #calculating margins
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ if self.multipleInterval:
+ yTopOffset = max(80, yTopOffset)
+ else:
+ if self.legendChecked:
+ yTopOffset = max(80, yTopOffset)
+ else:
+ pass
+
+ if self.plotScale != 'physic':
+ yBottomOffset = max(120, yBottomOffset)
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ xLeftOffset = int(xLeftOffset*fontZoom)
+ xRightOffset = int(xRightOffset*fontZoom)
+ yBottomOffset = int(yBottomOffset*fontZoom)
+
+ cWidth = canvas.size[0]
+ cHeight = canvas.size[1]
+ plotWidth = cWidth - xLeftOffset - xRightOffset
+ plotHeight = cHeight - yTopOffset - yBottomOffset
+ startPixelX = xLeftOffset
+ endPixelX = (xLeftOffset + plotWidth)
+
+ #Drawing Area Height
+ drawAreaHeight = plotHeight
+ if self.plotScale == 'physic' and self.selectedChr > -1:
+ drawAreaHeight -= self.ENSEMBL_BAND_HEIGHT + self.UCSC_BAND_HEIGHT+ self.WEBQTL_BAND_HEIGHT + 3*self.BAND_SPACING+ 10*zoom
+ if self.geneChecked:
+ drawAreaHeight -= self.NUM_GENE_ROWS*self.EACH_GENE_HEIGHT + 3*self.BAND_SPACING + 10*zoom
+ else:
+ if self.selectedChr > -1:
+ drawAreaHeight -= 20
+ else:
+ drawAreaHeight -= 30
+
+## BEGIN HaplotypeAnalyst
+ if self.haplotypeAnalystChecked and self.selectedChr > -1:
+ drawAreaHeight -= self.EACH_GENE_HEIGHT * (self.NR_INDIVIDUALS+10) * 2 * zoom
+## END HaplotypeAnalyst
+
+ #Image map
+ gifmap = HT.Map(name='WebQTLImageMap')
+
+ newoffset = (xLeftOffset, xRightOffset, yTopOffset, yBottomOffset)
+ # Draw the alternating-color background first and get plotXScale
+ plotXScale = self.drawGraphBackground(canvas, gifmap, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+
+ #draw bootstap
+ if self.bootChecked and not self.multipleInterval:
+ self.drawBootStrapResult(canvas, fd.nboot, drawAreaHeight, plotXScale, offset=newoffset)
+
+ # Draw clickable region and gene band if selected
+ if self.plotScale == 'physic' and self.selectedChr > -1:
+ self.drawClickBand(canvas, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+ if self.geneChecked and self.geneCol:
+ self.drawGeneBand(canvas, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+ if self.SNPChecked:
+ self.drawSNPTrackNew(canvas, offset=newoffset, zoom= 2*zoom, startMb=startMb, endMb = endMb)
+## BEGIN HaplotypeAnalyst
+ if self.haplotypeAnalystChecked:
+ self.drawHaplotypeBand(canvas, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+## END HaplotypeAnalyst
+ # Draw X axis
+ self.drawXAxis(fd, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+ # Draw QTL curve
+ self.drawQTL(canvas, drawAreaHeight, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+
+ #draw legend
+ if self.multipleInterval:
+ self.drawMultiTraitName(fd, canvas, gifmap, showLocusForm, offset=newoffset)
+ elif self.legendChecked:
+ self.drawLegendPanel(fd, canvas, offset=newoffset)
+ else:
+ pass
+
+ #draw position, no need to use a separate function
+ if fd.genotype.Mbmap:
+ self.drawProbeSetPosition(canvas, plotXScale, offset=newoffset)
+
+ return gifmap
+
+ def drawBootStrapResult(self, canvas, nboot, drawAreaHeight, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ bootHeightThresh = drawAreaHeight*3/4
+
+ #break bootstrap result into groups
+ BootCoord = []
+ i = 0
+ startX = xLeftOffset
+ for j, _chr in enumerate(self.genotype):
+ BootCoord.append( [])
+ for _locus in _chr:
+ if self.plotScale == 'physic':
+ Xc = startX + (_locus.Mb-self.startMb)*plotXScale
+ else:
+ Xc = startX + (_locus.cM-_chr[0].cM)*plotXScale
+ BootCoord[-1].append([Xc, self.bootResult[i]])
+ i += 1
+ startX += (self.ChrLengthDistList[j] + self.GraphInterval)*plotXScale
+
+ #reduce bootResult
+ if self.selectedChr > -1:
+ maxBootBar = 80.0
+ else:
+ maxBootBar = 200.0
+ stepBootStrap = plotWidth/maxBootBar
+ reducedBootCoord = []
+ maxBootCount = 0
+
+ for BootChrCoord in BootCoord:
+ nBoot = len(BootChrCoord)
+ bootStartPixX = BootChrCoord[0][0]
+ bootCount = BootChrCoord[0][1]
+ for i in range(1, nBoot):
+ if BootChrCoord[i][0] - bootStartPixX < stepBootStrap:
+ bootCount += BootChrCoord[i][1]
+ continue
+ else:
+ if maxBootCount < bootCount:
+ maxBootCount = bootCount
+ # end if
+ reducedBootCoord.append([bootStartPixX, BootChrCoord[i][0], bootCount])
+ bootStartPixX = BootChrCoord[i][0]
+ bootCount = BootChrCoord[i][1]
+ # end else
+ # end for
+ #add last piece
+ if BootChrCoord[-1][0] - bootStartPixX > stepBootStrap/2.0:
+ reducedBootCoord.append([bootStartPixX, BootChrCoord[-1][0], bootCount])
+ else:
+ reducedBootCoord[-1][2] += bootCount
+ reducedBootCoord[-1][1] = BootChrCoord[-1][0]
+ # end else
+ if maxBootCount < reducedBootCoord[-1][2]:
+ maxBootCount = reducedBootCoord[-1][2]
+ # end if
+ for item in reducedBootCoord:
+ if item[2] > 0:
+ if item[0] < xLeftOffset:
+ item[0] = xLeftOffset
+ if item[0] > xLeftOffset+plotWidth:
+ item[0] = xLeftOffset+plotWidth
+ if item[1] < xLeftOffset:
+ item[1] = xLeftOffset
+ if item[1] > xLeftOffset+plotWidth:
+ item[1] = xLeftOffset+plotWidth
+ if item[0] != item[1]:
+ canvas.drawRect(item[0], yZero, item[1], yZero - item[2]*bootHeightThresh/maxBootCount,
+ fillColor=self.BOOTSTRAP_BOX_COLOR)
+
+ ###draw boot scale
+ highestPercent = (maxBootCount*100.0)/nboot
+ bootScale = Plot.detScale(0, highestPercent)
+ bootScale = Plot.frange(bootScale[0], bootScale[1], bootScale[1]/bootScale[2])
+ bootScale = bootScale[:-1] + [highestPercent]
+
+ bootOffset = 50*fontZoom
+ bootScaleFont=pid.Font(ttf="verdana",size=13*fontZoom,bold=0)
+ canvas.drawRect(canvas.size[0]-bootOffset,yZero-bootHeightThresh,canvas.size[0]-bootOffset-15*zoom,yZero,fillColor = pid.yellow)
+ canvas.drawLine(canvas.size[0]-bootOffset+4, yZero, canvas.size[0]-bootOffset, yZero, color=pid.black)
+ canvas.drawString('0%' ,canvas.size[0]-bootOffset+10,yZero+5,font=bootScaleFont,color=pid.black)
+ for item in bootScale:
+ if item == 0:
+ continue
+ bootY = yZero-bootHeightThresh*item/highestPercent
+ canvas.drawLine(canvas.size[0]-bootOffset+4,bootY,canvas.size[0]-bootOffset,bootY,color=pid.black)
+ canvas.drawString('%2.1f'%item ,canvas.size[0]-bootOffset+10,bootY+5,font=bootScaleFont,color=pid.black)
+
+ if self.legendChecked:
+ startPosY = 30
+ nCol = 2
+ smallLabelFont = pid.Font(ttf="trebuc", size=12, bold=1)
+ leftOffset = xLeftOffset+(nCol-1)*200
+ canvas.drawRect(leftOffset,startPosY-6, leftOffset+12,startPosY+6, fillColor=pid.yellow)
+ canvas.drawString('Frequency of the Peak LRS',leftOffset+ 20, startPosY+5,font=smallLabelFont,color=pid.black)
+
+ def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ if len(self.traitList) != 1:
+ return
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ try:
+ Chr = self.traitList[0].chr
+ Mb = self.traitList[0].mb
+ except:
+ return
+
+ if self.plotScale == 'physic':
+ if self.selectedChr > -1:
+ if self.genotype[0].name != Chr or Mb < self.startMb or Mb > self.endMb:
+ return
+ else:
+ locPixel = xLeftOffset + (Mb-self.startMb)*plotXScale
+ else:
+ locPixel = xLeftOffset
+ for i, _chr in enumerate(self.genotype):
+ if _chr.name != Chr:
+ locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale
+ else:
+ locPixel += Mb*plotXScale
+ break
+ else:
+ if self.selectedChr > -1:
+ if self.genotype[0].name != Chr:
+ return
+ else:
+ for i, _locus in enumerate(self.genotype[0]):
+ #the trait's position is on the left of the first genotype
+ if i==0 and _locus.Mb >= Mb:
+ locPixel=-1
+ break
+
+ #the trait's position is between two traits
+ if i > 0 and self.genotype[0][i-1].Mb < Mb and _locus.Mb >= Mb:
+ locPixel = xLeftOffset + plotXScale*(self.genotype[0][i-1].cM+(_locus.cM-self.genotype[0][i-1].cM)*(Mb -self.genotype[0][i-1].Mb)/(_locus.Mb-self.genotype[0][i-1].Mb))
+ break
+
+ #the trait's position is on the right of the last genotype
+ if i==len(self.genotype[0]) and Mb>=_locus.Mb:
+ locPixel = -1
+ else:
+ locPixel = xLeftOffset
+ for i, _chr in enumerate(self.genotype):
+ if _chr.name != Chr:
+ locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale
+ else:
+ locPixel += (Mb*(_chr[-1].cM-_chr[0].cM)/self.ChrLengthCMList[i])*plotXScale
+ break
+ if locPixel >= 0:
+ traitPixel = ((locPixel, yZero), (locPixel-6, yZero+12), (locPixel+6, yZero+12))
+ canvas.drawPolygon(traitPixel, edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1)
+
+ if self.legendChecked:
+ startPosY = 15
+ nCol = 2
+ smallLabelFont = pid.Font(ttf="trebuc", size=12, bold=1)
+ leftOffset = xLeftOffset+(nCol-1)*200
+ canvas.drawPolygon(((leftOffset+6, startPosY-6), (leftOffset, startPosY+6), (leftOffset+12, startPosY+6)), edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1)
+ canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR)
+
+
+ def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ if self.plotScale != 'physic' or self.selectedChr == -1 or not self.diffCol:
+ return
+
+ SNP_HEIGHT_MODIFIER = 18.0
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ drawSNPLocationY = yTopOffset + plotHeight
+ chrName = self.genotype[0].name
+
+ stepMb = (endMb-startMb)/plotWidth
+ strainId1, strainId2 = self.diffCol
+ SNPCounts = []
+
+ while startMb<endMb:
+ self.cursor.execute("""
+ select
+ count(*) from BXDSnpPosition
+ where
+ Chr = '%s' AND Mb >= %2.6f AND Mb < %2.6f AND
+ StrainId1 = %d AND StrainId2 = %d
+ """ % (chrName, startMb, startMb+stepMb, strainId1, strainId2))
+ SNPCounts.append(self.cursor.fetchone()[0])
+ startMb += stepMb
+
+ if (len(SNPCounts) > 0):
+ maxCount = max(SNPCounts)
+ if maxCount>0:
+ for i in range(xLeftOffset, xLeftOffset + plotWidth):
+ snpDensity = float(SNPCounts[i-xLeftOffset]*SNP_HEIGHT_MODIFIER/maxCount)
+ canvas.drawLine(i, drawSNPLocationY+(snpDensity)*zoom, i, drawSNPLocationY-(snpDensity)*zoom, color=self.SNP_COLOR, width=1)
+
+ def drawMultiTraitName(self, fd, canvas, gifmap, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, locLocation= None):
+ nameWidths = []
+ yPaddingTop = 10
+ colorFont=pid.Font(ttf="trebuc",size=12,bold=1)
+ if len(self.qtlresults) >20 and self.selectedChr > -1:
+ rightShift = 20
+ rightShiftStep = 60
+ rectWidth = 10
+ else:
+ rightShift = 40
+ rightShiftStep = 80
+ rectWidth = 15
+
+ for k, thisTrait in enumerate(self.traitList):
+ thisLRSColor = self.colorCollection[k]
+ kstep = k % 4
+ if k!=0 and kstep==0:
+ if nameWidths:
+ rightShiftStep = max(nameWidths[-4:]) + rectWidth + 20
+ rightShift += rightShiftStep
+
+ name = thisTrait.displayName()
+ nameWidth = canvas.stringWidth(name,font=colorFont)
+ nameWidths.append(nameWidth)
+
+ canvas.drawRect(rightShift,yPaddingTop+kstep*15, rectWidth+rightShift,yPaddingTop+10+kstep*15, fillColor=thisLRSColor)
+ canvas.drawString(name,rectWidth+2+rightShift,yPaddingTop+10+kstep*15,font=colorFont,color=pid.black)
+ if thisTrait.db:
+
+ COORDS = "%d,%d,%d,%d" %(rectWidth+2+rightShift,yPaddingTop+kstep*15,rectWidth+2+rightShift+nameWidth,yPaddingTop+10+kstep*15,)
+ HREF= "javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm, thisTrait.db.name, thisTrait.name)
+ Areas = HT.Area(shape='rect',coords=COORDS,href=HREF)
+ gifmap.areas.append(Areas)
+
+
+ def drawLegendPanel(self, fd, canvas, offset= (40, 120, 80, 10), zoom = 1, locLocation= None):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+
+ labelFont=pid.Font(ttf="trebuc",size=12, bold=1)
+ startPosY = 15
+ stepPosY = 12
+ canvas.drawLine(xLeftOffset,startPosY,xLeftOffset+32,startPosY,color=self.LRS_COLOR, width=2)
+ canvas.drawString(self.LRS_LOD, xLeftOffset+40,startPosY+5,font=labelFont,color=pid.black)
+ startPosY += stepPosY
+
+ if self.additiveChecked:
+ startPosX = xLeftOffset
+ canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.ADDITIVE_COLOR_POSITIVE, width=2)
+ canvas.drawLine(startPosX+18,startPosY,startPosX+32,startPosY,color=self.ADDITIVE_COLOR_NEGATIVE, width=2)
+ canvas.drawString('Additive Effect',startPosX+40,startPosY+5,font=labelFont,color=pid.black)
+
+ if self.genotype.type == 'intercross' and self.dominanceChecked:
+ startPosX = xLeftOffset
+ startPosY += stepPosY
+ canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.DOMINANCE_COLOR_POSITIVE, width=4)
+ canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.DOMINANCE_COLOR_NEGATIVE, width=4)
+ canvas.drawString('Dominance Effect',startPosX+42,startPosY+5,font=labelFont,color=pid.black)
+
+ if self.haplotypeAnalystChecked:
+ startPosY += stepPosY
+ startPosX = xLeftOffset
+ canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.HAPLOTYPE_POSITIVE, width=4)
+ canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.HAPLOTYPE_NEGATIVE, width=4)
+ canvas.drawLine(startPosX+36,startPosY,startPosX+53,startPosY,color=self.HAPLOTYPE_HETEROZYGOUS, width=4)
+ canvas.drawLine(startPosX+54,startPosY,startPosX+67,startPosY,color=self.HAPLOTYPE_RECOMBINATION, width=4)
+ canvas.drawString('Haplotypes (Pat, Mat, Het, Unk)',startPosX+76,startPosY+5,font=labelFont,color=pid.black)
+
+ if self.permChecked:
+ startPosY += stepPosY
+ startPosX = xLeftOffset
+ canvas.drawLine(startPosX, startPosY, startPosX + 32, startPosY, color=self.SIGNIFICANT_COLOR, width=self.SIGNIFICANT_WIDTH)
+ canvas.drawLine(startPosX, startPosY + stepPosY, startPosX + 32, startPosY + stepPosY, color=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH)
+ lod = 1
+ if self.LRS_LOD == 'LOD':
+ lod = self.LODFACTOR
+ canvas.drawString('Significant %s = %2.2f' % (self.LRS_LOD, self.significance/lod),xLeftOffset+42,startPosY +5,font=labelFont,color=pid.black)
+ canvas.drawString('Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive/lod),xLeftOffset+42,startPosY + 5 +stepPosY,font=labelFont,color=pid.black)
+
+
+
+ labelFont=pid.Font(ttf="verdana",size=12)
+ labelColor = pid.black
+ if self.selectedChr == -1:
+ string1 = 'Mapping for Dataset: %s, mapping on All Chromosomes' % fd.RISet
+ else:
+ string1 = 'Mapping for Dataset: %s, mapping on Chromosome %s' % (fd.RISet,self.genotype[0].name)
+ if self.controlLocus:
+ string2 = 'Using %s as control' % self.controlLocus
+ else:
+ string2 = 'Using Haldane mapping function with no control for other QTLs'
+ d = 4+ max(canvas.stringWidth(string1,font=labelFont),canvas.stringWidth(string2,font=labelFont))
+ if fd.identification:
+ identification = "Trait ID: %s" % fd.identification
+ canvas.drawString(identification,canvas.size[0] - xRightOffset-d,20,font=labelFont,color=labelColor)
+
+ canvas.drawString(string1,canvas.size[0] - xRightOffset-d,35,font=labelFont,color=labelColor)
+ canvas.drawString(string2,canvas.size[0] - xRightOffset-d,50,font=labelFont,color=labelColor)
+
+
+ def drawGeneBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol:
+ return
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ yPaddingTop = yTopOffset
+
+ displayStartInBases = startMb*self.kONE_MILLION
+ displayEndInBases = endMb*self.kONE_MILLION
+
+ for gIndex, theGO in enumerate(self.geneCol):
+ geneNCBILink = 'http://www.ncbi.nlm.nih.gov/gene?term=%s'
+ if self.species == "mouse":
+ txStart = theGO["TxStart"]
+ txEnd = theGO["TxEnd"]
+ geneLength = (txEnd - txStart)*1000.0
+ tenPercentLength = geneLength*0.0001
+ SNPdensity = theGO["snpCount"]/geneLength
+
+ exonStarts = map(float, theGO['exonStarts'].split(",")[:-1])
+ exonEnds = map(float, theGO['exonEnds'].split(",")[:-1])
+ cdsStart = theGO['cdsStart']
+ cdsEnd = theGO['cdsEnd']
+ accession = theGO['NM_ID']
+ geneId = theGO['GeneID']
+ geneSymbol = theGO["GeneSymbol"]
+ strand = theGO["Strand"]
+ exonCount = theGO["exonCount"]
+
+ geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb)
+ geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) #at least one pixel
+
+ if (geneEndPix < xLeftOffset):
+ return; # this gene is not on the screen
+ elif (geneEndPix > xLeftOffset + plotWidth):
+ geneEndPix = xLeftOffset + plotWidth; # clip the last in-range gene
+ if (geneStartPix > xLeftOffset + plotWidth):
+ return; # we are outside the valid on-screen range, so stop drawing genes
+ elif (geneStartPix < xLeftOffset):
+ geneStartPix = xLeftOffset; # clip the first in-range gene
+
+ #color the gene based on SNP density
+
+
+ #found earlier, needs to be recomputed as snps are added
+
+ #always apply colors now, even if SNP Track not checked - Zach 11/24/2010
+
+ densities=[1.0000000000000001e-05, 0.094094033555233408, 0.3306166377816987, 0.88246026851027781, 2.6690084029581951, 4.1, 61.0]
+ if SNPdensity < densities[0]:
+ myColor = pid.black
+ elif SNPdensity < densities[1]:
+ myColor = pid.purple
+ elif SNPdensity < densities[2]:
+ myColor = pid.darkblue
+ elif SNPdensity < densities[3]:
+ myColor = pid.darkgreen
+ elif SNPdensity < densities[4]:
+ myColor = pid.gold
+ elif SNPdensity < densities[5]:
+ myColor = pid.darkorange
+ else:
+ myColor = pid.darkred
+
+ outlineColor = myColor
+ fillColor = myColor
+
+ TITLE = "Gene: %s (%s)\nFrom %2.3f to %2.3f Mb (%s)\nNum. exons: %d." % (geneSymbol, accession, float(txStart), float(txEnd), strand, exonCount)
+ # NL: 06-02-2011 Rob required to change this link for gene related
+ HREF=geneNCBILink %geneSymbol
+
+ elif self.species == "rat":
+ exonStarts = []
+ exonEnds = []
+ txStart = theGO["TxStart"]
+ txEnd = theGO["TxEnd"]
+ cdsStart = theGO["TxStart"]
+ cdsEnd = theGO["TxEnd"]
+ geneId = theGO["GeneID"]
+ geneSymbol = theGO["GeneSymbol"]
+ strand = theGO["Strand"]
+ exonCount = 0
+
+ geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb)
+ geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) #at least one pixel
+
+ if (geneEndPix < xLeftOffset):
+ return; # this gene is not on the screen
+ elif (geneEndPix > xLeftOffset + plotWidth):
+ geneEndPix = xLeftOffset + plotWidth; # clip the last in-range gene
+ if (geneStartPix > xLeftOffset + plotWidth):
+ return; # we are outside the valid on-screen range, so stop drawing genes
+ elif (geneStartPix < xLeftOffset):
+ geneStartPix = xLeftOffset; # clip the first in-range gene
+
+ outlineColor = pid.darkblue
+ fillColor = pid.darkblue
+ TITLE = "Gene: %s\nFrom %2.3f to %2.3f Mb (%s)" % (geneSymbol, float(txStart), float(txEnd), strand)
+ # NL: 06-02-2011 Rob required to change this link for gene related
+ HREF=geneNCBILink %geneSymbol
+ else:
+ outlineColor = pid.orange
+ fillColor = pid.orange
+ TITLE = "Gene: %s" % geneSymbol
+
+ #Draw Genes
+ geneYLocation = yPaddingTop + (gIndex % self.NUM_GENE_ROWS) * self.EACH_GENE_HEIGHT*zoom
+
+ if 1:#drawClickableRegions:
+ geneYLocation += self.UCSC_BAND_HEIGHT + self.BAND_SPACING + self.ENSEMBL_BAND_HEIGHT + self.BAND_SPACING + self.WEBQTL_BAND_HEIGHT + self.BAND_SPACING
+ else:
+ geneYLocation += self.BAND_SPACING
+
+ #draw the detail view
+ if self.endMb - self.startMb <= self.DRAW_DETAIL_MB and geneEndPix - geneStartPix > self.EACH_GENE_ARROW_SPACING * 3:
+ utrColor = pid.Color(0.66, 0.66, 0.66)
+ arrowColor = pid.Color(0.7, 0.7, 0.7)
+
+ #draw the line that runs the entire length of the gene
+ #canvas.drawString(str(geneStartPix), 300, 400)
+ canvas.drawLine(geneStartPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom, geneEndPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom, color=outlineColor, width=1)
+
+ #draw the arrows
+ for xCoord in range(0, geneEndPix-geneStartPix):
+
+ if (xCoord % self.EACH_GENE_ARROW_SPACING == 0 and xCoord + self.EACH_GENE_ARROW_SPACING < geneEndPix-geneStartPix) or xCoord == 0:
+ if strand == "+":
+ canvas.drawLine(geneStartPix + xCoord, geneYLocation, geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1)
+ canvas.drawLine(geneStartPix + xCoord, geneYLocation + self.EACH_GENE_HEIGHT*zoom, geneStartPix + xCoord+self.EACH_GENE_ARROW_WIDTH, geneYLocation + (self.EACH_GENE_HEIGHT / 2) * zoom, color=arrowColor, width=1)
+ else:
+ canvas.drawLine(geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation, geneStartPix + xCoord, geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1)
+ canvas.drawLine(geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation + self.EACH_GENE_HEIGHT*zoom, geneStartPix + xCoord, geneYLocation + (self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1)
+
+ #draw the blocks for the exon regions
+ for i in range(0, len(exonStarts)):
+ exonStartPix = (exonStarts[i]-startMb)*plotXScale + xLeftOffset
+ exonEndPix = (exonEnds[i]-startMb)*plotXScale + xLeftOffset
+ if (exonStartPix < xLeftOffset):
+ exonStartPix = xLeftOffset
+ if (exonEndPix < xLeftOffset):
+ exonEndPix = xLeftOffset
+ if (exonEndPix > xLeftOffset + plotWidth):
+ exonEndPix = xLeftOffset + plotWidth
+ if (exonStartPix > xLeftOffset + plotWidth):
+ exonStartPix = xLeftOffset + plotWidth
+ canvas.drawRect(exonStartPix, geneYLocation, exonEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = fillColor)
+
+ #draw gray blocks for 3' and 5' UTR blocks
+ if cdsStart and cdsEnd:
+
+ utrStartPix = (txStart-startMb)*plotXScale + xLeftOffset
+ utrEndPix = (cdsStart-startMb)*plotXScale + xLeftOffset
+ if (utrStartPix < xLeftOffset):
+ utrStartPix = xLeftOffset
+ if (utrEndPix < xLeftOffset):
+ utrEndPix = xLeftOffset
+ if (utrEndPix > xLeftOffset + plotWidth):
+ utrEndPix = xLeftOffset + plotWidth
+ if (utrStartPix > xLeftOffset + plotWidth):
+ utrStartPix = xLeftOffset + plotWidth
+ canvas.drawRect(utrStartPix, geneYLocation, utrEndPix, (geneYLocation+self.EACH_GENE_HEIGHT*zoom), edgeColor=utrColor, fillColor =utrColor)
+
+ if self.DRAW_UTR_LABELS and self.endMb - self.startMb <= self.DRAW_UTR_LABELS_MB:
+ if strand == "-":
+ labelText = "3'"
+ else:
+ labelText = "5'"
+ canvas.drawString(labelText, utrStartPix-9, geneYLocation+self.EACH_GENE_HEIGHT, pid.Font(face="helvetica", size=2))
+
+ #the second UTR region
+
+ utrStartPix = (cdsEnd-startMb)*plotXScale + xLeftOffset
+ utrEndPix = (txEnd-startMb)*plotXScale + xLeftOffset
+ if (utrStartPix < xLeftOffset):
+ utrStartPix = xLeftOffset
+ if (utrEndPix < xLeftOffset):
+ utrEndPix = xLeftOffset
+ if (utrEndPix > xLeftOffset + plotWidth):
+ utrEndPix = xLeftOffset + plotWidth
+ if (utrStartPix > xLeftOffset + plotWidth):
+ utrStartPix = xLeftOffset + plotWidth
+ canvas.drawRect(utrStartPix, geneYLocation, utrEndPix, (geneYLocation+self.EACH_GENE_HEIGHT*zoom), edgeColor=utrColor, fillColor =utrColor)
+
+ if self.DRAW_UTR_LABELS and self.endMb - self.startMb <= self.DRAW_UTR_LABELS_MB:
+ if tstrand == "-":
+ labelText = "5'"
+ else:
+ labelText = "3'"
+ canvas.drawString(labelText, utrEndPix+2, geneYLocation+self.EACH_GENE_HEIGHT, pid.Font(face="helvetica", size=2))
+
+ #draw the genes as rectangles
+ else:
+ canvas.drawRect(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = fillColor)
+
+ COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT))
+ # NL: 06-02-2011 Rob required to display NCBI info in a new window
+ gifmap.areas.append(HT.Area(shape='rect',coords=COORDS,href=HREF, title=TITLE,target="_blank"))
+
+## BEGIN HaplotypeAnalyst
+ def drawHaplotypeBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol:
+ return
+
+
+ fpText = open(os.path.join(webqtlConfig.TMPDIR, "hallo") + '.txt','wb')
+
+ clickableRegionLabelFont=pid.Font(ttf="verdana", size=9, bold=0)
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ widthMultiplier = 1
+
+ yPaddingTop = yTopOffset
+
+ exprdrawn = 0
+
+ thisTrait = self.traitList[0]
+ _strains, _vals, _vars = thisTrait.exportInformative()
+
+ smd=[]
+ for ii, _val in enumerate(_vals):
+ temp = GeneralObject(name=_strains[ii], value=_val)
+ smd.append(temp)
+
+ smd.sort(lambda A, B: cmp(A.value, B.value))
+
+ bxdlist=list(self.genotype.prgy)
+
+ oldgeneEndPix = -1
+ #Initializing plotRight, error before
+ plotRight = xRightOffset
+
+#### find out PlotRight
+ for i, _locus in enumerate(self.genotype[0]):
+ txStart = self.genotype[0][i].Mb
+ txEnd = self.genotype[0][i].Mb
+
+ geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - 0
+ geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) - 0
+
+ drawit = 1
+ if (geneStartPix < xLeftOffset):
+ drawit = 0;
+ if (geneStartPix > xLeftOffset + plotWidth):
+ drawit = 0;
+
+ if drawit == 1:
+
+ if self.genotype[0][i].name != " - " :
+
+ plotRight = geneEndPix + 4
+
+
+
+#### end find out PlotRight
+
+ firstGene = 1
+ lastGene = 0
+
+ #Sets the length to the length of the strain list. Beforehand, "oldgeno = self.genotype[0][i].genotype"
+ #was the only place it was initialized, which worked as long as the very start (startMb = None/0) wasn't being mapped.
+ #Now there should always be some value set for "oldgeno" - Zach 12/14/2010
+ oldgeno = [None]*len(self.strainlist)
+
+ for i, _locus in enumerate(self.genotype[0]):
+ txStart = self.genotype[0][i].Mb
+ txEnd = self.genotype[0][i].Mb
+
+ geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - 0
+ geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) + 0
+
+ if oldgeneEndPix >= xLeftOffset:
+ drawStart = oldgeneEndPix + 4
+ else:
+ drawStart = xLeftOffset + 3
+
+ drawEnd = plotRight - 9
+
+ drawit = 1
+
+ if (geneStartPix < xLeftOffset):
+ if firstGene == 1:
+ drawit = 1
+ else:
+ drawit = 0
+
+ elif (geneStartPix > (xLeftOffset + plotWidth - 3)):
+ if lastGene == 0:
+ drawit = 1
+ drawEnd = xLeftOffset + plotWidth - 6
+ lastGene = 1
+ else:
+ break
+
+ else:
+ firstGene = 0
+ drawit = 1
+
+ if drawit == 1:
+ myColor = pid.darkblue
+ outlineColor = myColor
+ fillColor = myColor
+
+ maxind=0
+
+ #Draw Genes
+
+ geneYLocation = yPaddingTop + self.NUM_GENE_ROWS * (self.EACH_GENE_HEIGHT)*zoom
+
+ if 1:#drawClickableRegions:
+ geneYLocation += self.UCSC_BAND_HEIGHT + self.BAND_SPACING + self.ENSEMBL_BAND_HEIGHT + self.BAND_SPACING + self.WEBQTL_BAND_HEIGHT + self.BAND_SPACING
+ else:
+ geneYLocation += self.BAND_SPACING
+
+ if self.genotype[0][i].name != " - " :
+
+ if (firstGene == 1) and (lastGene != 1):
+ oldgeneEndPix = drawStart = xLeftOffset
+ oldgeno = self.genotype[0][i].genotype
+ continue
+
+ for j,_geno in enumerate (self.genotype[0][i].genotype):
+
+ plotbxd=0
+ for item in smd:
+ if item.name == bxdlist[j]:
+ plotbxd=1
+
+ if (plotbxd == 1):
+ ind = 0
+ counter = 0
+ for item in smd:
+ counter = counter + 1
+ if item.name == bxdlist[j]:
+ ind = counter
+ maxind=max(ind,maxind)
+
+ # lines
+ if (oldgeno[j] == -1 and _geno == -1):
+ mylineColor = self.HAPLOTYPE_NEGATIVE
+ elif (oldgeno[j] == 1 and _geno == 1):
+ mylineColor = self.HAPLOTYPE_POSITIVE
+ elif (oldgeno[j] == 0 and _geno == 0):
+ mylineColor = self.HAPLOTYPE_HETEROZYGOUS
+ else:
+ mylineColor = self.HAPLOTYPE_RECOMBINATION # XZ: Unknown
+
+ canvas.drawLine(drawStart, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, drawEnd, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, color = mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2))
+
+ fillColor=pid.black
+ outlineColor=pid.black
+ if lastGene == 0:
+ canvas.drawRect(geneStartPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT*zoom, geneEndPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT+ 2*self.EACH_GENE_HEIGHT*zoom, edgeColor = outlineColor, fillColor = fillColor)
+
+
+ COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation+ind*self.EACH_GENE_HEIGHT, geneEndPix+1, (geneYLocation + ind*self.EACH_GENE_HEIGHT))
+ TITLE = "Strain: %s, marker (%s) \n Position %2.3f Mb." % (bxdlist[j], self.genotype[0][i].name, float(txStart))
+ HREF = ''
+ gifmap.areas.append(HT.Area(shape='rect',coords=COORDS,href=HREF, title=TITLE))
+
+ # if there are no more markers in a chromosome, the plotRight value calculated above will be before the plotWidth
+ # resulting in some empty space on the right side of the plot area. This draws an "unknown" bar from plotRight to the edge.
+ if (plotRight < (xLeftOffset + plotWidth - 3)) and (lastGene == 0):
+ drawEnd = xLeftOffset + plotWidth - 6
+ mylineColor = self.HAPLOTYPE_RECOMBINATION
+ canvas.drawLine(plotRight, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, drawEnd, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, color = mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2))
+
+
+ if lastGene == 0:
+ canvas.drawString("%s" % (self.genotype[0][i].name), geneStartPix , geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black, angle=-90)
+
+ oldgeneEndPix = geneEndPix;
+ oldgeno = self.genotype[0][i].genotype
+ firstGene = 0
+ else:
+ lastGene = 0
+
+ for j,_geno in enumerate (self.genotype[0][1].genotype):
+
+ plotbxd=0
+ for item in smd:
+ if item.name == bxdlist[j]:
+ plotbxd=1
+
+ if (plotbxd == 1):
+
+ ind = 0
+ counter = 0
+ expr = 0
+ for item in smd:
+ counter = counter + 1
+ if item.name == bxdlist[j]:
+ ind = counter
+ expr = item.value
+
+ # Place where font is hardcoded
+ canvas.drawString("%s" % (bxdlist[j]), (xLeftOffset + plotWidth + 10) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black)
+ canvas.drawString("%2.2f" % (expr), (xLeftOffset + plotWidth + 60) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black)
+
+ fpText.close()
+
+## END HaplotypeAnalyst
+
+ def drawClickBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ if self.plotScale != 'physic' or self.selectedChr == -1:
+ return
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ # only draw this many clickable regions (if you set it higher, you get more precision in clicking,
+ # but it makes the HTML huge, and takes forever to render the page in the first place)
+ # Draw the bands that you can click on to go to UCSC / Ensembl
+ MAX_CLICKABLE_REGION_DIVISIONS = 100
+ clickableRegionLabelFont=pid.Font(ttf="verdana", size=9, bold=0)
+ pixelStep = max(5, int(float(plotWidth)/MAX_CLICKABLE_REGION_DIVISIONS))
+ # pixelStep: every N pixels, we make a new clickable area for the user to go to that area of the genome.
+
+ numBasesCurrentlyOnScreen = self.kONE_MILLION*abs(startMb - endMb) # Number of bases on screen now
+ flankingWidthInBases = int ( min( (float(numBasesCurrentlyOnScreen) / 2.0), (5*self.kONE_MILLION) ) )
+ webqtlZoomWidth = numBasesCurrentlyOnScreen / 16.0
+ # Flanking width should be such that we either zoom in to a 10 million base region, or we show the clicked region at the same scale as we are currently seeing.
+
+ currentChromosome = self.genotype[0].name
+ i = 0
+ for pixel in range(xLeftOffset, xLeftOffset + plotWidth, pixelStep):
+
+ calBase = self.kONE_MILLION*(startMb + (endMb-startMb)*(pixel-xLeftOffset-0.0)/plotWidth)
+
+ xBrowse1 = pixel
+ xBrowse2 = min(xLeftOffset + plotWidth, (pixel + pixelStep - 1))
+
+ paddingTop = yTopOffset
+ ucscPaddingTop = paddingTop + self.WEBQTL_BAND_HEIGHT + self.BAND_SPACING
+ ensemblPaddingTop = ucscPaddingTop + self.UCSC_BAND_HEIGHT + self.BAND_SPACING
+
+ WEBQTL_COORDS = "%d, %d, %d, %d" % (xBrowse1, paddingTop, xBrowse2, (paddingTop+self.WEBQTL_BAND_HEIGHT))
+ bandWidth = xBrowse2 - xBrowse1
+ WEBQTL_HREF = "javascript:centerIntervalMapOnRange2('%s', %f, %f, document.changeViewForm)" % (currentChromosome, max(0, (calBase-webqtlZoomWidth))/1000000.0, (calBase+webqtlZoomWidth)/1000000.0)
+
+ WEBQTL_TITLE = "Click to view this section of the genome in WebQTL"
+ gifmap.areas.append(HT.Area(shape='rect',coords=WEBQTL_COORDS,href=WEBQTL_HREF, title=WEBQTL_TITLE))
+ canvas.drawRect(xBrowse1, paddingTop, xBrowse2, (paddingTop + self.WEBQTL_BAND_HEIGHT), edgeColor=self.CLICKABLE_WEBQTL_REGION_COLOR, fillColor=self.CLICKABLE_WEBQTL_REGION_COLOR)
+ canvas.drawLine(xBrowse1, paddingTop, xBrowse1, (paddingTop + self.WEBQTL_BAND_HEIGHT), color=self.CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR)
+
+ UCSC_COORDS = "%d, %d, %d, %d" %(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.UCSC_BAND_HEIGHT))
+ if self.species == "mouse":
+ UCSC_HREF = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d&hgt.customText=%s/snp/chr%s" % (self._ucscDb, currentChromosome, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases, webqtlConfig.PORTADDR, currentChromosome)
+ else:
+ UCSC_HREF = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d" % (self._ucscDb, currentChromosome, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases)
+ UCSC_TITLE = "Click to view this section of the genome in the UCSC Genome Browser"
+ gifmap.areas.append(HT.Area(shape='rect',coords=UCSC_COORDS,href=UCSC_HREF, title=UCSC_TITLE))
+ canvas.drawRect(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.UCSC_BAND_HEIGHT), edgeColor=self.CLICKABLE_UCSC_REGION_COLOR, fillColor=self.CLICKABLE_UCSC_REGION_COLOR)
+ canvas.drawLine(xBrowse1, ucscPaddingTop, xBrowse1, (ucscPaddingTop+self.UCSC_BAND_HEIGHT), color=self.CLICKABLE_UCSC_REGION_OUTLINE_COLOR)
+
+ ENSEMBL_COORDS = "%d, %d, %d, %d" %(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.ENSEMBL_BAND_HEIGHT))
+ if self.species == "mouse":
+ ENSEMBL_HREF = "http://www.ensembl.org/Mus_musculus/contigview?highlight=&chr=%s&vc_start=%d&vc_end=%d&x=35&y=12" % (currentChromosome, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases)
+ else:
+ ENSEMBL_HREF = "http://www.ensembl.org/Rattus_norvegicus/contigview?chr=%s&start=%d&end=%d" % (currentChromosome, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases)
+ ENSEMBL_TITLE = "Click to view this section of the genome in the Ensembl Genome Browser"
+ gifmap.areas.append(HT.Area(shape='rect',coords=ENSEMBL_COORDS,href=ENSEMBL_HREF, title=ENSEMBL_TITLE))
+ canvas.drawRect(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.ENSEMBL_BAND_HEIGHT), edgeColor=self.CLICKABLE_ENSEMBL_REGION_COLOR, fillColor=self.CLICKABLE_ENSEMBL_REGION_COLOR)
+ canvas.drawLine(xBrowse1, ensemblPaddingTop, xBrowse1, (ensemblPaddingTop+self.ENSEMBL_BAND_HEIGHT), color=self.CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR)
+ # end for
+
+ canvas.drawString("Click to view the corresponding section of the genome in an 8x expanded WebQTL map", (xLeftOffset + 10), paddingTop + self.WEBQTL_BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_WEBQTL_TEXT_COLOR)
+ canvas.drawString("Click to view the corresponding section of the genome in the UCSC Genome Browser", (xLeftOffset + 10), ucscPaddingTop + self.UCSC_BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_UCSC_TEXT_COLOR)
+ canvas.drawString("Click to view the corresponding section of the genome in the Ensembl Genome Browser", (xLeftOffset+10), ensemblPaddingTop + self.ENSEMBL_BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_ENSEMBL_TEXT_COLOR)
+
+ #draw the gray text
+ chrFont = pid.Font(ttf="verdana", size=26, bold=1)
+ traitFont = pid.Font(ttf="verdana", size=14, bold=0)
+ chrX = xLeftOffset + plotWidth - 2 - canvas.stringWidth("Chr %s" % currentChromosome, font=chrFont)
+ canvas.drawString("Chr %s" % currentChromosome, chrX, ensemblPaddingTop-5, font=chrFont, color=pid.gray)
+ traitX = chrX - 28 - canvas.stringWidth("database", font=traitFont)
+ # end of drawBrowserClickableRegions
+
+ pass
+
+ def drawXAxis(self, fd, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ #Parameters
+ NUM_MINOR_TICKS = 5 # Number of minor ticks between major ticks
+ X_MAJOR_TICK_THICKNESS = 2
+ X_MINOR_TICK_THICKNESS = 1
+ X_AXIS_THICKNESS = 1*zoom
+
+ # ======= Alex: Draw the X-axis labels (megabase location)
+ MBLabelFont = pid.Font(ttf="verdana", size=12*fontZoom, bold=0)
+ xMajorTickHeight = 15 # How high the tick extends below the axis
+ xMinorTickHeight = 5*zoom
+ xAxisTickMarkColor = pid.black
+ xAxisLabelColor = pid.black
+ fontHeight = 12*fontZoom # How tall the font that we're using is
+ spacingFromLabelToAxis = 20
+ spacingFromLineToLabel = 3
+
+ if self.plotScale == 'physic':
+ strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont)
+ ###Physical single chromosome view
+ if self.selectedChr > -1:
+ graphMbWidth = endMb - startMb
+ XScale = Plot.detScale(startMb, endMb)
+ XStart, XEnd, XStep = XScale
+ if XStep < 8:
+ XStep *= 2
+ spacingAmtX = spacingAmt = (XEnd-XStart)/XStep
+
+ j = 0
+ while abs(spacingAmtX -int(spacingAmtX)) >= spacingAmtX/100.0 and j < 6:
+ j += 1
+ spacingAmtX *= 10
+
+ formatStr = '%%2.%df' % j
+
+ for counter, _Mb in enumerate(Plot.frange(XStart, XEnd, spacingAmt / NUM_MINOR_TICKS)):
+ if _Mb < startMb or _Mb > endMb:
+ continue
+ Xc = xLeftOffset + plotXScale*(_Mb - startMb)
+ if counter % NUM_MINOR_TICKS == 0: # Draw a MAJOR mark, not just a minor tick mark
+ canvas.drawLine(Xc, yZero, Xc, yZero+xMajorTickHeight, color=xAxisTickMarkColor, width=X_MAJOR_TICK_THICKNESS) # Draw the MAJOR tick mark
+ labelStr = str(formatStr % _Mb) # What Mbase location to put on the label
+ strWidth = canvas.stringWidth(labelStr, font=MBLabelFont)
+ drawStringXc = (Xc - (strWidth / 2.0))
+ canvas.drawString(labelStr, drawStringXc, strYLoc, font=MBLabelFont, color=xAxisLabelColor, angle=0)
+ else:
+ canvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=xAxisTickMarkColor, width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark
+ # end else
+
+ ###Physical genome wide view
+ else:
+ distScale = 0
+ startPosX = xLeftOffset
+ for i, distLen in enumerate(self.ChrLengthDistList):
+ if distScale == 0: #universal scale in whole genome mapping
+ if distLen > 75:
+ distScale = 25
+ elif distLen > 30:
+ distScale = 10
+ else:
+ distScale = 5
+ for tickdists in range(distScale, ceil(distLen), distScale):
+ canvas.drawLine(startPosX + tickdists*plotXScale, yZero, startPosX + tickdists*plotXScale, yZero + 7, color=pid.black, width=1*zoom)
+ canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=pid.black, font=MBLabelFont, angle=270)
+ startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale
+
+ megabaseLabelFont = pid.Font(ttf="verdana", size=14*zoom*1.5, bold=0)
+ canvas.drawString("Megabases", xLeftOffset + (plotWidth -canvas.stringWidth("Megabases", font=megabaseLabelFont))/2,
+ strYLoc + canvas.fontHeight(MBLabelFont) + 5*zoom, font=megabaseLabelFont, color=pid.black)
+ pass
+ else:
+ ChrAInfo = []
+ preLpos = -1
+ distinctCount = 0.0
+ if len(self.genotype) > 1:
+ for i, _chr in enumerate(self.genotype):
+ thisChr = []
+ Locus0CM = _chr[0].cM
+ nLoci = len(_chr)
+ if nLoci <= 8:
+ for _locus in _chr:
+ if _locus.name != ' - ':
+ if _locus.cM != preLpos:
+ distinctCount += 1
+ preLpos = _locus.cM
+ thisChr.append([_locus.name, _locus.cM-Locus0CM])
+ else:
+ for j in (0, nLoci/4, nLoci/2, nLoci*3/4, -1):
+ while _chr[j].name == ' - ':
+ j += 1
+ if _chr[j].cM != preLpos:
+ distinctCount += 1
+ preLpos = _chr[j].cM
+ thisChr.append([_chr[j].name, _chr[j].cM-Locus0CM])
+ ChrAInfo.append(thisChr)
+ else:
+ for i, _chr in enumerate(self.genotype):
+ thisChr = []
+ Locus0CM = _chr[0].cM
+ for _locus in _chr:
+ if _locus.name != ' - ':
+ if _locus.cM != preLpos:
+ distinctCount += 1
+ preLpos = _locus.cM
+ thisChr.append([_locus.name, _locus.cM-Locus0CM])
+ ChrAInfo.append(thisChr)
+
+ stepA = (plotWidth+0.0)/distinctCount
+
+ LRectWidth = 10
+ LRectHeight = 3
+ offsetA = -stepA
+ lineColor = pid.lightblue
+ startPosX = xLeftOffset
+ for j, ChrInfo in enumerate(ChrAInfo):
+ preLpos = -1
+ for i, item in enumerate(ChrInfo):
+ Lname,Lpos = item
+ if Lpos != preLpos:
+ offsetA += stepA
+ differ = 1
+ else:
+ differ = 0
+ preLpos = Lpos
+ Lpos *= plotXScale
+ if self.selectedChr > -1:
+ Zorder = i % 5
+ else:
+ Zorder = 0
+ if differ:
+ canvas.drawLine(startPosX+Lpos,yZero,xLeftOffset+offsetA,\
+ yZero+25, color=lineColor)
+ canvas.drawLine(xLeftOffset+offsetA,yZero+25,xLeftOffset+offsetA,\
+ yZero+40+Zorder*(LRectWidth+3),color=lineColor)
+ rectColor = pid.orange
+ else:
+ canvas.drawLine(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)-3,\
+ xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),color=lineColor)
+ rectColor = pid.deeppink
+ canvas.drawRect(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),\
+ xLeftOffset+offsetA-LRectHeight,yZero+40+Zorder*(LRectWidth+3)+LRectWidth,\
+ edgeColor=rectColor,fillColor=rectColor,edgeWidth = 0)
+ COORDS="%d,%d,%d,%d"%(xLeftOffset+offsetA-LRectHeight, yZero+40+Zorder*(LRectWidth+3),\
+ xLeftOffset+offsetA,yZero+40+Zorder*(LRectWidth+3)+LRectWidth)
+ HREF="javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm,fd.RISet+"Geno", Lname)
+ Areas=HT.Area(shape='rect',coords=COORDS,href=HREF, title="Locus : " + Lname)
+ gifmap.areas.append(Areas)
+ ##piddle bug
+ if j == 0:
+ canvas.drawLine(startPosX,yZero,startPosX,yZero+40, color=lineColor)
+ startPosX += (self.ChrLengthDistList[j]+self.GraphInterval)*plotXScale
+
+ canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.black, width=X_AXIS_THICKNESS) # Draw the X axis itself
+
+
+ def drawQTL(self, canvas, drawAreaHeight, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ INTERCROSS = (self.genotype.type=="intercross")
+
+ LRSHeightThresh = drawAreaHeight
+ AdditiveHeightThresh = drawAreaHeight/2
+ DominanceHeightThresh = drawAreaHeight/2
+
+ #draw the LRS scale
+ #We first determine whether or not we are using a sliding scale.
+ #If so, we need to compute the maximum LRS value to determine where the max y-value should be, and call this LRSMax.
+ #LRSTop is then defined to be above the LRSMax by enough to add one additional LRSScale increment.
+ #if we are using a set-scale, then we set LRSTop to be the user's value, and LRSMax doesn't matter.
+
+ if self.LRS_LOD == 'LOD':
+ lodm = self.LODFACTOR
+ else:
+ lodm = 1.0
+
+ if self.lrsMax <= 0: #sliding scale
+ LRSMax = max(map(max, self.qtlresults)).lrs
+ #genotype trait will give infinite LRS
+ LRSMax = min(LRSMax, webqtlConfig.MAXLRS)
+ if self.permChecked and not self.multipleInterval:
+ self.significance = min(self.significance, webqtlConfig.MAXLRS)
+ self.suggestive = min(self.suggestive, webqtlConfig.MAXLRS)
+ LRSMax = max(self.significance, LRSMax)
+ else:
+ LRSMax = self.lrsMax*lodm
+
+ if LRSMax/lodm > 100:
+ LRSScale = 20.0
+ elif LRSMax/lodm > 20:
+ LRSScale = 5.0
+ elif LRSMax/lodm > 7.5:
+ LRSScale = 2.5
+ else:
+ LRSScale = 1.0
+
+ LRSAxisList = Plot.frange(LRSScale, LRSMax/lodm, LRSScale)
+ #make sure the user's value appears on the y-axis
+ #update by NL 6-21-2011: round the LOD value to 100 when LRSMax is equal to 460
+ LRSAxisList.append(round(LRSMax/lodm))
+
+ #draw the "LRS" or "LOD" string to the left of the axis
+ LRSScaleFont=pid.Font(ttf="verdana", size=14*fontZoom, bold=0)
+ LRSLODFont=pid.Font(ttf="verdana", size=14*zoom*1.5, bold=0)
+ yZero = yTopOffset + plotHeight
+
+
+ canvas.drawString(self.LRS_LOD, xLeftOffset - canvas.stringWidth("999.99", font=LRSScaleFont) - 10*zoom, \
+ yZero - 150, font=LRSLODFont, color=pid.black, angle=90)
+
+ for item in LRSAxisList:
+ yLRS = yZero - (item*lodm/LRSMax) * LRSHeightThresh
+ canvas.drawLine(xLeftOffset, yLRS, xLeftOffset - 4, yLRS, color=self.LRS_COLOR, width=1*zoom)
+ scaleStr = "%2.1f" % item
+ canvas.drawString(scaleStr, xLeftOffset-4-canvas.stringWidth(scaleStr, font=LRSScaleFont)-5, yLRS+3, font=LRSScaleFont, color=self.LRS_COLOR)
+
+
+ #"Significant" and "Suggestive" Drawing Routine
+ # ======= Draw the thick lines for "Significant" and "Suggestive" ===== (crowell: I tried to make the SNPs draw over these lines, but piddle wouldn't have it...)
+ if self.permChecked and not self.multipleInterval:
+ significantY = yZero - self.significance*LRSHeightThresh/LRSMax
+ suggestiveY = yZero - self.suggestive*LRSHeightThresh/LRSMax
+ startPosX = xLeftOffset
+ for i, _chr in enumerate(self.genotype):
+ rightEdge = int(startPosX + self.ChrLengthDistList[i]*plotXScale - self.SUGGESTIVE_WIDTH/1.5)
+ canvas.drawLine(startPosX+self.SUGGESTIVE_WIDTH/1.5, suggestiveY, rightEdge, suggestiveY, color=self.SUGGESTIVE_COLOR,
+ width=self.SUGGESTIVE_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2))
+ canvas.drawLine(startPosX+self.SUGGESTIVE_WIDTH/1.5, significantY, rightEdge, significantY, color=self.SIGNIFICANT_COLOR,
+ width=self.SIGNIFICANT_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2))
+ sugg_coords = "%d, %d, %d, %d" % (startPosX, suggestiveY-2, rightEdge + 2*zoom, suggestiveY+2)
+ sig_coords = "%d, %d, %d, %d" % (startPosX, significantY-2, rightEdge + 2*zoom, significantY+2)
+ if self.LRS_LOD == 'LRS':
+ sugg_title = "Suggestive LRS = %0.2f" % self.suggestive
+ sig_title = "Significant LRS = %0.2f" % self.significance
+ else:
+ sugg_title = "Suggestive LOD = %0.2f" % (self.suggestive/4.61)
+ sig_title = "Significant LOD = %0.2f" % (self.significance/4.61)
+ Areas1 = HT.Area(shape='rect',coords=sugg_coords,title=sugg_title)
+ Areas2 = HT.Area(shape='rect',coords=sig_coords,title=sig_title)
+ gifmap.areas.append(Areas1)
+ gifmap.areas.append(Areas2)
+
+ startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale
+
+
+ if self.multipleInterval:
+ lrsEdgeWidth = 1
+ else:
+ additiveMax = max(map(lambda X : abs(X.additive), self.qtlresults[0]))
+ if INTERCROSS:
+ dominanceMax = max(map(lambda X : abs(X.dominance), self.qtlresults[0]))
+ else:
+ dominanceMax = -1
+ lrsEdgeWidth = 2
+ for i, qtlresult in enumerate(self.qtlresults):
+ m = 0
+ startPosX = xLeftOffset
+ thisLRSColor = self.colorCollection[i]
+ for j, _chr in enumerate(self.genotype):
+ LRSCoordXY = []
+ AdditiveCoordXY = []
+ DominanceCoordXY = []
+ for k, _locus in enumerate(_chr):
+ if self.plotScale == 'physic':
+ Xc = startPosX + (_locus.Mb-startMb)*plotXScale
+ else:
+ Xc = startPosX + (_locus.cM-_chr[0].cM)*plotXScale
+ # updated by NL 06-18-2011:
+ # fix the over limit LRS graph issue since genotype trait may give infinite LRS;
+ # for any lrs is over than 460(LRS max in this system), it will be reset to 460
+ if qtlresult[m].lrs> 460 or qtlresult[m].lrs=='inf':
+ Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/LRSMax
+ else:
+ Yc = yZero - qtlresult[m].lrs*LRSHeightThresh/LRSMax
+
+ LRSCoordXY.append((Xc, Yc))
+ if not self.multipleInterval and self.additiveChecked:
+ Yc = yZero - qtlresult[m].additive*AdditiveHeightThresh/additiveMax
+ AdditiveCoordXY.append((Xc, Yc))
+ if not self.multipleInterval and INTERCROSS and self.additiveChecked:
+ Yc = yZero - qtlresult[m].dominance*DominanceHeightThresh/dominanceMax
+ DominanceCoordXY.append((Xc, Yc))
+ m += 1
+ canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ if not self.multipleInterval and self.additiveChecked:
+ plusColor = self.ADDITIVE_COLOR_POSITIVE
+ minusColor = self.ADDITIVE_COLOR_NEGATIVE
+ for k, aPoint in enumerate(AdditiveCoordXY):
+ if k > 0:
+ Xc0, Yc0 = AdditiveCoordXY[k-1]
+ Xc, Yc = aPoint
+ if (Yc0-yZero)*(Yc-yZero) < 0:
+ if Xc == Xc0: #genotype , locus distance is 0
+ Xcm = Xc
+ else:
+ Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0
+ if Yc0 < yZero:
+ canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ elif (Yc0-yZero)*(Yc-yZero) > 0:
+ if Yc < yZero:
+ canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ minYc = min(Yc-yZero, Yc0-yZero)
+ if minYc < 0:
+ canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ if not self.multipleInterval and INTERCROSS and self.dominanceChecked:
+ plusColor = self.DOMINANCE_COLOR_POSITIVE
+ minusColor = self.DOMINANCE_COLOR_NEGATIVE
+ for k, aPoint in enumerate(DominanceCoordXY):
+ if k > 0:
+ Xc0, Yc0 = DominanceCoordXY[k-1]
+ Xc, Yc = aPoint
+ if (Yc0-yZero)*(Yc-yZero) < 0:
+ if Xc == Xc0: #genotype , locus distance is 0
+ Xcm = Xc
+ else:
+ Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0
+ if Yc0 < yZero:
+ canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ elif (Yc0-yZero)*(Yc-yZero) > 0:
+ if Yc < yZero:
+ canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ minYc = min(Yc-yZero, Yc0-yZero)
+ if minYc < 0:
+ canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ else:
+ canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=1, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+ startPosX += (self.ChrLengthDistList[j]+self.GraphInterval)*plotXScale
+
+ ###draw additive scale
+ if not self.multipleInterval and self.additiveChecked:
+ additiveScaleFont=pid.Font(ttf="verdana",size=12*fontZoom,bold=0)
+ additiveScale = Plot.detScaleOld(0,additiveMax)
+ additiveStep = (additiveScale[1]-additiveScale[0])/additiveScale[2]
+ additiveAxisList = Plot.frange(0, additiveScale[1], additiveStep)
+ maxAdd = additiveScale[1]
+ addPlotScale = AdditiveHeightThresh/additiveMax
+
+ additiveAxisList.append(additiveScale[1])
+ for item in additiveAxisList:
+ additiveY = yZero - item*addPlotScale
+ canvas.drawLine(xLeftOffset + plotWidth,additiveY,xLeftOffset+4+ plotWidth,additiveY,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
+ scaleStr = "%2.3f" % item
+ canvas.drawString(scaleStr,xLeftOffset + plotWidth +6,additiveY+5,font=additiveScaleFont,color=self.ADDITIVE_COLOR_POSITIVE)
+
+ canvas.drawLine(xLeftOffset+plotWidth,additiveY,xLeftOffset+plotWidth,yZero,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
+
+ canvas.drawLine(xLeftOffset, yZero, xLeftOffset, yTopOffset, color=self.LRS_COLOR, width=1*zoom) #the blue line running up the y axis
+
+
+ def drawGraphBackground(self, canvas, gifmap, offset= (80, 120, 80, 50), zoom = 1, startMb = None, endMb = None):
+ ##conditions
+ ##multiple Chromosome view
+ ##single Chromosome Physical
+ ##single Chromosome Genetic
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ #calculate plot scale
+ if self.plotScale != 'physic':
+ self.ChrLengthDistList = self.ChrLengthCMList
+ drawRegionDistance = self.ChrLengthCMSum
+ else:
+ self.ChrLengthDistList = self.ChrLengthMbList
+ drawRegionDistance = self.ChrLengthMbSum
+
+ if self.selectedChr > -1: #single chromosome view
+ spacingAmt = plotWidth/13.5
+ i = 0
+ for startPix in Plot.frange(xLeftOffset, xLeftOffset+plotWidth, spacingAmt):
+ if (i % 2 == 0):
+ theBackColor = self.GRAPH_BACK_DARK_COLOR
+ else:
+ theBackColor = self.GRAPH_BACK_LIGHT_COLOR
+ i += 1
+ canvas.drawRect(startPix, yTopOffset, min(startPix+spacingAmt, xLeftOffset+plotWidth), \
+ yTopOffset+plotHeight, edgeColor=theBackColor, fillColor=theBackColor)
+
+ drawRegionDistance = self.ChrLengthDistList[self.selectedChr]
+ self.ChrLengthDistList = [drawRegionDistance]
+ if self.plotScale == 'physic':
+ plotXScale = plotWidth / (endMb-startMb)
+ else:
+ plotXScale = plotWidth / drawRegionDistance
+
+ else: #multiple chromosome view
+ plotXScale = plotWidth / ((len(self.genotype)-1)*self.GraphInterval + drawRegionDistance)
+
+ startPosX = xLeftOffset
+ chrLabelFont=pid.Font(ttf="verdana",size=24*fontZoom,bold=0)
+
+ for i, _chr in enumerate(self.genotype):
+ if (i % 2 == 0):
+ theBackColor = self.GRAPH_BACK_DARK_COLOR
+ else:
+ theBackColor = self.GRAPH_BACK_LIGHT_COLOR
+
+ #draw the shaded boxes and the sig/sug thick lines
+ canvas.drawRect(startPosX, yTopOffset, startPosX + self.ChrLengthDistList[i]*plotXScale, \
+ yTopOffset+plotHeight, edgeColor=pid.gainsboro,fillColor=theBackColor)
+
+ chrNameWidth = canvas.stringWidth(_chr.name, font=chrLabelFont)
+ chrStartPix = startPosX + (self.ChrLengthDistList[i]*plotXScale -chrNameWidth)/2
+ chrEndPix = startPosX + (self.ChrLengthDistList[i]*plotXScale +chrNameWidth)/2
+
+ canvas.drawString(_chr.name, chrStartPix, yTopOffset +20,font = chrLabelFont,color=pid.dimgray)
+ COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20)
+
+ #add by NL 09-03-2010
+ HREF = "javascript:changeView(%d,%s);" % (i,self.ChrLengthMbList)
+ Areas = HT.Area(shape='rect',coords=COORDS,href=HREF)
+ gifmap.areas.append(Areas)
+ startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale
+
+ return plotXScale
+
+ def calculateAllResult(self, fd):
+
+ weightedRegression = fd.formdata.getvalue('applyVarianceSE')
+
+ self.genotype = self.genotype.addinterval()
+ resultSlice = []
+ controlGeno = []
+
+ if self.multipleInterval:
+ self.suggestive = 0
+ self.significance = 0
+ if self.selectedChr > -1:
+ self.genotype.chromosome = [self.genotype[self.selectedChr]]
+ else:
+ #single interval mapping
+ try:
+ self.suggestive = float(fd.formdata.getvalue('permSuggestive'))
+ self.significance = float(fd.formdata.getvalue('permSignificance'))
+ except:
+ self.suggestive = None
+ self.significance = None
+
+ _strains, _vals, _vars = self.traitList[0].exportInformative(weightedRegression)
+
+ if webqtlUtil.ListNotNull(_vars):
+ pass
+ else:
+ weightedRegression = 0
+ _strains, _vals, _vars = self.traitList[0].exportInformative()
+
+ ##locate genotype of control Locus
+ if self.controlLocus:
+ controlGeno2 = []
+ _FIND = 0
+ for _chr in self.genotype:
+ for _locus in _chr:
+ if _locus.name == self.controlLocus:
+ controlGeno2 = _locus.genotype
+ _FIND = 1
+ break
+ if _FIND:
+ break
+ if controlGeno2:
+ _prgy = list(self.genotype.prgy)
+ for _strain in _strains:
+ _idx = _prgy.index(_strain)
+ controlGeno.append(controlGeno2[_idx])
+ else:
+ return "The control marker you selected is not in the genofile."
+
+
+ if self.significance and self.suggestive:
+ pass
+ else:
+ if self.permChecked:
+ if weightedRegression:
+ self.LRSArray = self.genotype.permutation(strains = _strains, trait = _vals,
+ variance = _vars, nperm=fd.nperm)
+ else:
+ self.LRSArray = self.genotype.permutation(strains = _strains, trait = _vals,
+ nperm=fd.nperm)
+ self.suggestive = self.LRSArray[int(fd.nperm*0.37-1)]
+ self.significance = self.LRSArray[int(fd.nperm*0.95-1)]
+
+ else:
+ self.suggestive = 9.2
+ self.significance = 16.1
+
+ #calculating bootstrap
+ #from now on, genotype could only contain a single chromosome
+ #permutation need to be performed genome wide, this is not the case for bootstrap
+
+ #due to the design of qtlreaper, composite regression need to be performed genome wide
+ if not self.controlLocus and self.selectedChr > -1:
+ self.genotype.chromosome = [self.genotype[self.selectedChr]]
+ elif self.selectedChr > -1: #self.controlLocus and self.selectedChr > -1
+ lociPerChr = map(len, self.genotype)
+ resultSlice = reduce(lambda X, Y: X+Y, lociPerChr[:self.selectedChr], 0)
+ resultSlice = [resultSlice,resultSlice+lociPerChr[self.selectedChr]]
+ else:
+ pass
+
+ #calculate QTL for each trait
+ self.qtlresults = []
+
+ for thisTrait in self.traitList:
+ _strains, _vals, _vars = thisTrait.exportInformative(weightedRegression)
+ if self.controlLocus:
+ if weightedRegression:
+ qtlresult = self.genotype.regression(strains = _strains, trait = _vals,
+ variance = _vars, control = self.controlLocus)
+ else:
+ qtlresult = self.genotype.regression(strains = _strains, trait = _vals,
+ control = self.controlLocus)
+ if resultSlice:
+ qtlresult = qtlresult[resultSlice[0]:resultSlice[1]]
+ else:
+ if weightedRegression:
+ qtlresult = self.genotype.regression(strains = _strains, trait = _vals,
+ variance = _vars)
+ else:
+ qtlresult = self.genotype.regression(strains = _strains, trait = _vals)
+
+ self.qtlresults.append(qtlresult)
+
+ if not self.multipleInterval:
+ if self.controlLocus and self.selectedChr > -1:
+ self.genotype.chromosome = [self.genotype[self.selectedChr]]
+
+ if self.bootChecked:
+ if controlGeno:
+ self.bootResult = self.genotype.bootstrap(strains = _strains, trait = _vals,
+ control = controlGeno, nboot=fd.nboot)
+ elif weightedRegression:
+ self.bootResult = self.genotype.bootstrap(strains = _strains, trait = _vals,
+ variance = _vars, nboot=fd.nboot)
+ else:
+ self.bootResult = self.genotype.bootstrap(strains = _strains, trait = _vals,
+ nboot=fd.nboot)
+ else:
+ self.bootResult = []
+
+ def calculatePValue (self, query_LRS, permutation_LRS_array):
+ query_index = len(permutation_LRS_array)
+ for i, one_permutation_LRS in enumerate(permutation_LRS_array):
+ if one_permutation_LRS >= query_LRS:
+ query_index = i
+ break
+
+ P_value = float(len(permutation_LRS_array) - query_index) / len(permutation_LRS_array)
+
+ return P_value
+
+ def helpButton(self, anchor):
+ return HT.Href(self.HELP_PAGE_REF + '#%s' % anchor, self.qmarkImg, target=self.HELP_WINDOW_NAME)
+
+
+ def traitRemapTD(self, cursor, fd):
+ chrList = HT.Select(name="chromosomes", data=self.ChrList, selected=[self.selectedChr],
+ onChange="chrLength(this.form.chromosomes.value, this.form.scale.value, this.form, self.ChrLengthMbList);")
+
+ physicOnly = HT.Span(' *', Class="cr")
+
+ showSNPCheck = HT.Input(type='checkbox', Class='checkbox', name='showSNP', value='ON', checked=self.SNPChecked)
+ showSNPText = HT.Span('SNP Track ', self.helpButton("snpSeismograph"), Class="fs12 fwn")
+
+ showGenesCheck = HT.Input(type='checkbox', Class='checkbox', name='showGenes', value='ON', checked=self.geneChecked)
+ showGenesText = HT.Span('Gene Track', Class="fs12 fwn")
+
+ showIntervalAnalystCheck = HT.Input(type='checkbox', Class='checkbox', name='intervalAnalystCheck', value='ON', checked=self.intervalAnalystChecked)
+ showIntervalAnalystText = HT.Span('Interval Analyst', Class="fs12 fwn")
+## BEGIN HaplotypeAnalyst
+
+ showHaplotypeAnalystCheck = HT.Input(type='checkbox', Class='checkbox', name='haplotypeAnalystCheck', value='ON', checked=self.haplotypeAnalystChecked)
+ showHaplotypeAnalystText = HT.Span('Haplotype Analyst', Class="fs12 fwn")
+## END HaplotypeAnalyst
+
+ leftBox = HT.Input(type="text", name="startMb", size=10)
+ rightBox = HT.Input(type="text", name="endMb", size=10)
+ if self.selectedChr > -1 and self.plotScale=='physic':
+ leftBox.value = self.startMb
+ rightBox.value = self.endMb
+
+ scaleBox = HT.Select(name="scale", onChange="chrLength(this.form.chromosomes.value, this.form.scale.value, this.form, self.ChrLengthMbList);")
+ scaleBox.append(("Genetic", "morgan"))
+ if fd.genotype.Mbmap:
+ scaleBox.append(("Physical", "physic"))
+ scaleBox.selected.append(self.plotScale)
+
+ permBox = HT.Input(type="checkbox", name="permCheck", value='ON', checked=self.permChecked, Class="checkbox")
+ permText = HT.Span("Permutation Test ", self.helpButton("Permutation"), Class="fs12 fwn")
+ bootBox = HT.Input(type="checkbox", name="bootCheck", value='ON', checked=self.bootChecked, Class="checkbox")
+ bootText = HT.Span("Bootstrap Test ", self.helpButton("bootstrap"), Class="fs12 fwn")
+ additiveBox = HT.Input(type="checkbox", name="additiveCheck", value='ON', checked=self.additiveChecked, Class="checkbox")
+ additiveText = HT.Span("Allele Effects ", self.helpButton("additive"), Class="fs12 fwn")
+ dominanceBox = HT.Input(type="checkbox", name="dominanceCheck", value='ON', checked=self.dominanceChecked, Class="checkbox")
+ dominanceText = HT.Span("Dominance Effects ", self.helpButton("Dominance"), Class="fs12 fwn")
+
+ lrsRadio = HT.Input(type="radio", name="LRSCheck", value='LRS', checked = (self.LRS_LOD == "LRS"))
+ lodRadio = HT.Input(type="radio", name="LRSCheck", value='LOD', checked = (self.LRS_LOD != "LRS"))
+ lrsMaxBox = HT.Input(type="text", name="lrsMax", value=self.lrsMax, size=3)
+ widthBox = HT.Input(type="text", name="graphWidth", size=5, value=str(self.graphWidth))
+ legendBox = HT.Input(type="checkbox", name="viewLegend", value='ON', checked=self.legendChecked, Class="checkbox")
+ legendText = HT.Span("Legend", Class="fs12 fwn")
+
+ draw2XBox = HT.Input(type="checkbox", name="draw2X", value='ON', Class="checkbox")
+ draw2XText = HT.Span("2X Plot", Class="fs12 fwn")
+
+ regraphButton = HT.Input(type="button", Class="button", onClick="javascript:databaseFunc(this.form,'showIntMap');", value="Remap")
+
+ controlsForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype="multipart/form-data", name="changeViewForm", submit=HT.Input(type='hidden'))
+ controlsTable = HT.TableLite(border=0)
+ innerControlsTable = HT.TableLite(border=0)
+ if self.selectedChr == -1:
+ minimumGraphWidth = self.MULT_GRAPH_MIN_WIDTH
+ else:
+ minimumGraphWidth = self.GRAPH_MIN_WIDTH
+
+ innerControlsTable.append(
+ HT.TR(HT.TD("Chr: ", Class="fs12 fwb ffl"),HT.TD(chrList, scaleBox, regraphButton)),
+ HT.TR(HT.TD("View: ", Class="fs12 fwb ffl"),HT.TD(leftBox, " to ", rightBox, "Mb", physicOnly, NOWRAP="on")),
+ HT.TR(HT.TD("Units: ", Class="fs12 fwb ffl"), HT.TD(lrsRadio, "LRS ", lodRadio, "LOD ", self.helpButton("LOD"))),
+ HT.TR(HT.TD(" ", Class="fs12 fwb ffl"), HT.TD(lrsMaxBox, "units on Y-axis (0 for default)", Class="fs11 fwn")),
+ HT.TR(HT.TD("Width: ", Class="fs12 fwb ffl"), HT.TD(widthBox, "pixels (minimum=%d)" % minimumGraphWidth, Class="fs11 fwn "))
+ )
+ #whether SNP
+ cursor.execute("Select Species.Id from SnpAll, Species where SnpAll.SpeciesId = Species.Id and Species.Name = %s limit 1", self.species)
+ SNPorNot = cursor.fetchall()
+ #Whether Gene
+ cursor.execute("Select Species.Id from GeneList, Species where GeneList.SpeciesId = Species.Id and Species.Name = %s limit 1", self.species)
+ GeneorNot = cursor.fetchall()
+
+ if self.multipleInterval:
+ optionPanel = HT.TD(valign="top", NOWRAP="on")
+ else:
+ optionPanel = HT.TD(permBox, permText, HT.BR(), bootBox, bootText, HT.BR(), additiveBox, additiveText, HT.BR(), valign="top", NOWRAP="on")
+ #whether dominance
+ if self.genotype.type == 'intercross':
+ optionPanel.append(dominanceBox, dominanceText, HT.BR())
+ if SNPorNot:
+ optionPanel.append(showSNPCheck, showSNPText, physicOnly, HT.BR())
+ if GeneorNot:
+ optionPanel.append(showGenesCheck, showGenesText, physicOnly, HT.BR(),
+ showIntervalAnalystCheck, showIntervalAnalystText, physicOnly, HT.BR())
+## BEGIN HaplotypeAnalyst
+ optionPanel.append(showHaplotypeAnalystCheck, showHaplotypeAnalystText, physicOnly, HT.BR())
+## END HaplotypeAnalyst
+ optionPanel.append(legendBox, legendText, HT.BR(),draw2XBox, draw2XText)
+ controlsTable.append(
+ HT.TR(HT.TD(innerControlsTable, valign="top"),
+ HT.TD("&nbsp;", width=15), optionPanel),
+ HT.TR(HT.TD(physicOnly, " only apply to single chromosome physical mapping", align="Center", colspan=3, Class="fs11 fwn"))
+ )
+ controlsForm.append(controlsTable)
+
+ controlsForm.append(HT.Input(name="permSuggestive", value=self.suggestive, type="hidden"))
+ controlsForm.append(HT.Input(name="permSignificance", value=self.significance, type="hidden"))
+
+## BEGIN HaplotypeAnalyst #### haplotypeAnalystCheck added below
+## END HaplotypeAnalyst
+
+ for key in fd.formdata.keys():
+ if key == "searchResult" and type([]) == type(fd.formdata.getvalue(key)):
+ controlsForm.append(HT.Input(name=key, value=string.join(fd.formdata.getvalue(key), "\t"), type="hidden"))
+ elif key not in ("endMb", "startMb", "chromosomes", "scale", "permCheck", "bootCheck", "additiveCheck", "dominanceCheck",
+ "LRSCheck", "intervalAnalystCheck", "haplotypeAnalystCheck", "lrsMax", "graphWidth", "viewLegend", 'showGenes', 'showSNP', 'draw2X',
+ 'permSuggestive', "permSignificance"):
+ controlsForm.append(HT.Input(name=key, value=fd.formdata.getvalue(key), type="hidden"))
+ else:
+ pass
+
+ # updated by NL, move function changeView(i) to webqtl.js and change it to function changeView(i, Chr_Mb_list)
+ # move function chrLength(a, b, c) to webqtl.js and change it to function chrLength(a, b, c, Chr_Mb_list)
+ self.dict['js1'] = ''
+
+ return HT.TD(controlsForm, Class="doubleBorder", width=400)
+
+ def traitInfoTD(self, fd):
+ if self.selectedChr == -1:
+ intMapHeading = HT.Paragraph('Map Viewer: Whole Genome', Class="title")
+ else:
+ intMapHeading = HT.Paragraph('Map Viewer: Chr %s' % self.genotype[0].name, Class="title")
+
+ heading2 = HT.Paragraph(HT.Strong('Population: '), "%s %s" % (self.species.title(), fd.RISet) , HT.BR())
+ #Trait is from an database
+ if self.traitList and self.traitList[0] and self.traitList[0].db:
+ #single trait
+ if len(self.traitList) == 1:
+ thisTrait = self.traitList[0]
+ trait_url = HT.Href(text=thisTrait.name, url = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE) + \
+ "?FormID=showDatabase&incparentsf1=1&database=%s&ProbeSetID=%s" % (thisTrait.db.name, thisTrait.name), \
+ target='_blank', Class="normalsize")
+ heading2.append(HT.Strong("Database: "), HT.Href(text=thisTrait.db.fullname, url = webqtlConfig.INFOPAGEHREF % thisTrait.db.name ,\
+ target='_blank',Class="normalsize"),HT.BR())
+ if thisTrait.db.type == 'ProbeSet':
+ heading2.append(HT.Strong('Trait ID: '), trait_url, HT.BR(),
+ HT.Strong("Gene Symbol: "), HT.Italic('%s' % thisTrait.symbol,id="green"),HT.BR())
+ if thisTrait.chr and thisTrait.mb:
+ heading2.append(HT.Strong("Location: "), 'Chr %s @ %s Mb' % (thisTrait.chr, thisTrait.mb))
+ elif thisTrait.db.type == 'Geno':
+ heading2.append(HT.Strong('Locus : '), trait_url, HT.BR())
+ if thisTrait.chr and thisTrait.mb:
+ heading2.append(HT.Strong("Location: "), 'Chr %s @ %s Mb' % (thisTrait.chr, thisTrait.mb))
+ elif thisTrait.db.type == 'Publish':
+ heading2.append(HT.Strong('Record ID: '), trait_url, HT.BR())
+ else:
+ pass
+ else:
+ heading2.append(HT.Strong("Traits: "), "Multiple Traits")
+ else:
+ heading2.append(HT.Strong("Trait Name: "), fd.identification)
+ return HT.TD(intMapHeading, heading2, valign="top")
+
+ def geneTables(self, geneCol, refGene=None):
+ SNPLink = 0
+ tableIterationsCnt = 0
+ if self.species == "mouse":
+ geneTableMain = HT.TableLite(border=0, width=1280, cellpadding=0, cellspacing=0, Class="collap")
+ columns = HT.TR(HT.TD(' ', Class="fs14 fwb ffl b1 cw cbrb"),
+ HT.TD('Gene Symbol',Class="fs14 fwb ffl b1 cw cbrb", colspan=2),
+ HT.TD('Mb Start (mm9)',Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Gene Length (Kb)',Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD("SNP Count", Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD("SNP Density (SNP/Kb)", Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Avg. Expr. Value', Class="fs14 fwb ffl b1 cw cbrb", width=1), # Max of all transcripts
+ HT.TD('Human Chr',Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Mb Start (hg19)', Class="fs14 fwb ffl b1 cw cbrb", width=1))
+
+ # http://compbio.uthsc.edu/miRSNP/
+
+ td_pd = HT.TD(Class="fs14 fwb ffl b1 cw cbrb")
+ td_pd.append(HT.Text("PolymiRTS"))
+ td_pd.append(HT.BR())
+ td_pd.append(HT.Text("Database"))
+ td_pd.append(HT.BR())
+ td_pd.append(HT.Href(url='http://compbio.uthsc.edu/miRSNP/', text='>>', target="_blank", Class="normalsize"))
+
+ if refGene:
+ columns.append(HT.TD('Literature Correlation', Class="fs14 fwb ffl b1 cw cbrb", width=1))
+ columns.append(HT.TD('Gene Description',Class="fs14 fwb ffl b1 cw cbrb"))
+ columns.append(td_pd)
+ geneTableMain.append(columns)
+
+ # polymiRTS
+ # http://lily.uthsc.edu:8080/20090422_UTHSC_cuiyan/PolymiRTS_CLS?chrom=2&chrom_from=115&chrom_to=125
+ #XZ: We can NOT assume their web service is always on. We must put this block of code in try except.
+ try:
+ conn = httplib.HTTPConnection("lily.uthsc.edu:8080")
+ conn.request("GET", "/20090422_UTHSC_cuiyan/PolymiRTS_CLS?chrom=%s&chrom_from=%s&chrom_to=%s" % (self.genotype[0].name, self.startMb, self.endMb))
+ response = conn.getresponse()
+ data = response.read()
+ data = data.split()
+ conn.close()
+ dic = {}
+ index = 0
+ for i in data:
+ if index%3==0:
+ dic[data[index]] = HT.Href(url=data[index+2], text=data[index+1], target="_blank", Class="normalsize")
+ index = index+1
+ except Exception:
+ dic={}
+
+
+ for gIndex, theGO in enumerate(geneCol):
+ geneLength = (theGO["TxEnd"] - theGO["TxStart"])*1000.0
+ tenPercentLength = geneLength*0.0001
+ txStart = theGO["TxStart"]
+ txEnd = theGO["TxEnd"]
+ theGO["snpDensity"] = theGO["snpCount"]/geneLength
+ if (self.ALEX_DEBUG_BOOL_PRINT_GENE_LIST and geneTableMain):
+ #accessionString = 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=Display&DB=gene&term=%s' % theGO["NM_ID"]
+ geneIdString = 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s' % theGO["GeneID"]
+
+ allProbeString = '%s?cmd=sch&gene=%s&alias=1' % (os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), theGO["GeneSymbol"])
+ if theGO["snpCount"]:
+ snpString = HT.Href(url="%s&chr=%s&start=%s&end=%s&geneName=%s&s1=%d&s2=%d" % (os.path.join(webqtlConfig.CGIDIR, 'main.py?FormID=snpBrowser'),
+ theGO["Chromosome"], theGO["TxStart"], theGO["TxEnd"], theGO["GeneSymbol"], self.diffCol[0], self.diffCol[1]),
+ text=theGO["snpCount"], target="_blank", Class="normalsize")
+ else:
+ snpString = 0
+
+ mouseStartString = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=vertebrate&org=Mouse&db=mm9&position=chr" + theGO["Chromosome"] + "%3A" + str(int(theGO["TxStart"] * 1000000.0)) + "-" + str(int(theGO["TxEnd"]*1000000.0)) +"&pix=620&Submit=submit"
+
+ if theGO['humanGene']:
+ huGO = theGO['humanGene']
+ if huGO["TxStart"] == '':
+ humanStartDisplay = ""
+ else:
+ humanStartDisplay = "%0.6f" % huGO["TxStart"]
+ humanChr = huGO["Chromosome"]
+ if humanChr.find("q") > -1:
+ humanChr = humanChr[:humanChr.find("q")]
+ if humanChr.find("p") > -1:
+ humanChr = humanChr[:humanChr.find("p")]
+ humanStartString = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=vertebrate&org=Human&db=hg17&position=chr%s:%d-%d" % (humanChr, int(1000000*huGO["TxStart"]), int(1000000*huGO["TxEnd"]))
+ else:
+ humanStartString = humanChr = humanStartDisplay = ""
+
+ geneDescription = theGO["GeneDescription"]
+ if len(geneDescription) > 26:
+ geneDescription = geneDescription[:26]+"..."
+ probeSetSearch = HT.Href(allProbeString, HT.Image("/images/webqtl_search.gif", border=0), target="_blank")
+
+ if theGO["snpDensity"] < 0.000001:
+ snpDensityStr = "0"
+ else:
+ snpDensityStr = "%0.6f" % theGO["snpDensity"]
+
+ avgExpr = []#theGO["avgExprVal")
+ if avgExpr in ([], None):
+ avgExpr = ""
+ else:
+ avgExpr = "%0.6f" % avgExpr
+
+ tableIterationsCnt = tableIterationsCnt + 1
+
+ # polymiRTS
+ polymiRTS = ' '
+ if dic.has_key(theGO["GeneID"]):
+ polymiRTS = dic[theGO["GeneID"]]
+
+ # If we have a referenceGene then we will show the Literature Correlation
+ if refGene:
+ literatureCorrelation = str(self.getLiteratureCorrelation(self.cursor,refGene,theGO['GeneID']) or "N/A")
+ geneTableMain.append(HT.TR(HT.TD(tableIterationsCnt, align="right", Class="fs13 b1 cbw c222"),
+ HT.TD(probeSetSearch, align="center", Class="fs13 bt1 bb1 cbw c222", width=21),
+ HT.TD(HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank", Class="normalsize"), align='left', Class="fs13 bt1 bb1 cbw c222"),
+ HT.TD(HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank", Class="normalsize"), align='right', Class="fs13 b1 cbw c222"),
+ HT.TD(HT.Href("javascript:centerIntervalMapOnRange2('%s', " % theGO["Chromosome"]+str(txStart-tenPercentLength) + ", " + str(txEnd+tenPercentLength) + ", document.changeViewForm)", "%0.3f" % geneLength, Class="normalsize"), align='right', Class="fs13 b1 cbw c222"),
+ HT.TD(snpString, align="right", Class="fs13 b1 cbw c222"),
+ HT.TD(snpDensityStr, align='right', Class='fs13 b1 cbw c222'),
+ HT.TD(avgExpr, align="right", Class="fs13 b1 cbw c222"), # This should have a link to the "basic stats" (button on main selection page) of the gene
+ HT.TD(humanChr, align="right",Class="fs13 b1 cbw c222"),
+ HT.TD(HT.Href(humanStartString, humanStartDisplay, target="_blank", Class="normalsize"), align="right", Class="fs13 b1 cbw c222"),
+ HT.TD(literatureCorrelation, align='left',Class="fs13 b1 cbw c222"),
+ HT.TD(geneDescription, align='left',Class="fs13 b1 cbw c222"),
+ HT.TD(polymiRTS, align='left', Class="fs13 b1 cbw c222")))
+
+ else:
+ geneTableMain.append(HT.TR(HT.TD(tableIterationsCnt, align="right", Class="fs13 b1 cbw c222"),
+ HT.TD(probeSetSearch, align="center", Class="fs13 bt1 bb1 cbw c222", width=21),
+ HT.TD(HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank", Class="normalsize"), align='left', Class="fs13 bt1 bb1 cbw c222"),
+ HT.TD(HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank", Class="normalsize"), align='right', Class="fs13 b1 cbw c222"),
+ HT.TD(HT.Href("javascript:centerIntervalMapOnRange2('%s', " % theGO["Chromosome"]+str(txStart-tenPercentLength) + ", " + str(txEnd+tenPercentLength) + ", document.changeViewForm)", "%0.3f" % geneLength, Class="normalsize"), align='right', Class="fs13 b1 cbw c222"),
+ HT.TD(snpString, align="right", Class="fs13 b1 cbw c222"),
+ HT.TD(snpDensityStr, align='right', Class='fs13 b1 cbw c222'),
+ HT.TD(avgExpr, align="right", Class="fs13 b1 cbw c222"), # This should have a link to the "basic stats" (button on main selection page) of the gene
+ HT.TD(humanChr, align="right",Class="fs13 b1 cbw c222"),
+ HT.TD(HT.Href(humanStartString, humanStartDisplay, target="_blank", Class="normalsize"), align="right", Class="fs13 b1 cbw c222"),
+ HT.TD(geneDescription, align='left',Class="fs13 b1 cbw c222"),
+ HT.TD(polymiRTS, align='left', Class="fs13 b1 cbw c222")))
+
+ return geneTableMain
+ elif self.species == "rat":
+ geneTableMain = HT.TableLite(border=0, width=1050, cellpadding=0, cellspacing=0, Class="collap")
+ geneTableMain.append(HT.TR(HT.TD(' ', Class="fs14 fwb ffl b1 cw cbrb"),
+ HT.TD('Gene Symbol',Class="fs14 fwb ffl b1 cw cbrb", colspan=2),
+ HT.TD('Mb Start (rn3)',Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Gene Length (Kb)',Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Avg. Expr. Value', Class="fs14 fwb ffl b1 cw cbrb", width=1), # Max of all transcripts
+ HT.TD('Mouse Chr', Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Mb Start (mm9)', Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Human Chr',Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Mb Start (hg19)', Class="fs14 fwb ffl b1 cw cbrb", width=1),
+ HT.TD('Gene Description',Class="fs14 fwb ffl b1 cw cbrb")))
+
+ for gIndex, theGO in enumerate(geneCol):
+ geneDesc = theGO["GeneDescription"]
+ if geneDesc == "---":
+ geneDesc = ""
+ geneLength = (float(theGO["TxEnd"]) - float(theGO["TxStart"]))
+ geneLengthURL = "javascript:centerIntervalMapOnRange2('%s', %f, %f, document.changeViewForm)" % (theGO["Chromosome"], float(theGO["TxStart"])-(geneLength*0.1), float(theGO["TxEnd"])+(geneLength*0.1))
+
+ #the chromosomes for human 1 are 1qXX.XX
+ if theGO['humanGene']:
+ humanChr = theGO['humanGene']["Chromosome"]
+ if 'q' in humanChr:
+ humanChr = humanChr[:humanChr.find("q")]
+ if 'p' in humanChr:
+ humanChr = humanChr[:humanChr.find("p")]
+ humanTxStart = theGO['humanGene']["TxStart"]
+ else:
+ humanChr = humanTxStart = ""
+
+ #Mouse Gene
+ if theGO['mouseGene']:
+ mouseChr = theGO['mouseGene']["Chromosome"]
+ mouseTxStart = theGO['mouseGene']["TxStart"]
+ else:
+ mouseChr = mouseTxStart = ""
+
+ if theGO["GeneID"] != "":
+ geneSymbolURL = HT.Href("http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % theGO["GeneID"], theGO["GeneSymbol"], Class="normalsize", target="_blanK")
+ else:
+ geneSymbolURL = theGO["GeneSymbol"]
+
+ if len(geneDesc) > 34:
+ geneDesc = geneDesc[:32] + "..."
+
+ avgExprVal = [] #theGO["avgExprVal"]
+ if avgExprVal != "" and avgExprVal:
+ avgExprVal = "%0.5f" % float(avgExprVal)
+ else:
+ avgExprVal = ""
+
+ geneTableMain.append(HT.TR(HT.TD(gIndex+1, align="right", Class="fs13 b1 cbw c222"),
+ HT.TD(HT.Href(os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+"?cmd=sch&gene=%s&alias=1&species=rat" % theGO["GeneSymbol"], HT.Image("/images/webqtl_search.gif", border=0), target="_blank"), Class="fs13 bt1 bb1 cbw c222"),
+ HT.TD(geneSymbolURL, Class="fs13 bt1 bb1 cbw c222"),
+ HT.TD(theGO["TxStart"], Class="fs13 b1 cbw c222"),
+ HT.TD(HT.Href(geneLengthURL, "%0.3f" % (geneLength*1000.0), Class="normalsize"), Class="fs13 b1 cbw c222"),
+ HT.TD(avgExprVal, Class="fs13 b1 cbw c222"),
+ HT.TD(mouseChr, Class="fs13 b1 cbw c222"),
+ HT.TD(mouseTxStart, Class="fs13 b1 cbw c222"),
+ HT.TD(humanChr, Class="fs13 b1 cbw c222"),
+ HT.TD(humanTxStart, Class="fs13 b1 cbw c222"),
+ HT.TD(geneDesc, Class="fs13 b1 cbw c222")))
+ return geneTableMain
+ else:
+ return ""
+
+ def getLiteratureCorrelation(cursor,geneId1=None,geneId2=None):
+ if not geneId1 or not geneId2:
+ return None
+ if geneId1 == geneId2:
+ return 1.0
+ geneId1 = str(geneId1)
+ geneId2 = str(geneId2)
+ lCorr = None
+ try:
+ query = 'SELECT Value FROM LCorrRamin3 WHERE GeneId1 = %s and GeneId2 = %s'
+ for x,y in [(geneId1,geneId2),(geneId2,geneId1)]:
+ cursor.execute(query,(x,y))
+ lCorr = cursor.fetchone()
+ if lCorr:
+ lCorr = lCorr[0]
+ break
+ except: raise #lCorr = None
+ return lCorr
diff --git a/web/webqtl/intervalMapping/__init__.py b/web/webqtl/intervalMapping/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/intervalMapping/__init__.py
diff --git a/web/webqtl/main.py b/web/webqtl/main.py
new file mode 100644
index 00000000..f37fae01
--- /dev/null
+++ b/web/webqtl/main.py
@@ -0,0 +1,699 @@
+# 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 mod_python import apache, util, Session, Cookie
+import time
+import string
+
+from base.webqtlFormData import webqtlFormData
+
+import logging
+logging.basicConfig(filename="/tmp/gn_log", level=logging.INFO)
+_log = logging.getLogger("main")
+
+
+
+def handler(req):
+ _log.info("Handling a request")
+ req.content_type = 'text/html'
+
+ formdata = util.FieldStorage(req)
+
+ formID = formdata.getfirst('FormID')
+ sid = formdata.getfirst('sid')
+ cmdID = formdata.getfirst('cmd')
+ page = None
+
+ #XZ: this statement must be put into handler function
+ _log.info("Loading session")
+ mod_python_session = Session.Session(req, timeout=864000, lock=0)
+ mod_python_session.load()
+ _log.info("Done loading session")
+
+ if sid:
+ from cmdLine import procPage
+ reload(procPage)
+ req.content_type = 'text/html'
+ procPage.procPage(sid, req)
+ else:
+ fd = webqtlFormData(req=req, mod_python_session=mod_python_session, FieldStorage_formdata=formdata)
+
+ if formID:
+ _log.info("Dispatching on %s, %s"%(formID, fd.formID))
+ #XZ: Special case. Pay attention to parameters! We can NOT pass 'fd'!
+ if fd.formID == 'uploadFile':
+ from base import cookieData
+ from misc import uploadFilePage
+ reload(uploadFilePage)
+ reload(cookieData)
+ cookies = cookieData.cookieData(Cookie.get_cookies(req)) #new module
+ req.content_type = 'text/html'
+ page = uploadFilePage.uploadFilePage(fd, formdata, cookies)
+
+ #search
+ elif fd.formID in ('searchResult','asearchResult'):
+ from search import SearchResultPage
+ reload(SearchResultPage)
+ req.content_type = 'text/html'
+ page = SearchResultPage.SearchResultPage(fd)
+
+ #showTrait
+ elif fd.formID == 'showDatabase':
+ from showTrait import ShowTraitPage
+ reload(ShowTraitPage)
+ req.content_type = 'text/html'
+ page = ShowTraitPage.ShowTraitPage(fd)
+ elif fd.formID == 'showBest':
+ from showTrait import ShowBestTrait
+ reload(ShowBestTrait)
+ req.content_type = 'text/html'
+ page = ShowBestTrait.ShowBestTrait(fd)
+ elif fd.formID == 'showProbeInfo':
+ from showTrait import ShowProbeInfoPage
+ reload(ShowProbeInfoPage)
+ page = ShowProbeInfoPage.ShowProbeInfoPage(fd)
+ req.content_type = 'text/html'
+ elif fd.formID in ('crossChoice', 'varianceChoice'):
+ if not fd.submitID:
+ req.content_type = 'text/html'
+ req.write('check your page')
+ elif fd.submitID == 'sample':
+ from showTrait import testTraitPage # new module
+ reload(testTraitPage)
+ page = testTraitPage.testTraitPage()
+ req.content_type = 'text/html'
+ else:
+ from showTrait import DataEditingPage
+ reload(DataEditingPage)
+ req.content_type = 'text/html'
+ page = DataEditingPage.DataEditingPage(fd)
+
+ #from Trait Data and Analysis form page
+ elif fd.formID == 'dataEditing':
+ if not fd.submitID:
+ req.content_type = 'text/html'
+ req.write('check your page')
+ elif fd.submitID == 'basicStatistics': #Updated Basic Statistics page (pop-up when user hits "update" button in DataEditingPage.py
+ from basicStatistics import updatedBasicStatisticsPage
+ reload(updatedBasicStatisticsPage)
+ req.content_type = 'text/html'
+ page = updatedBasicStatisticsPage.updatedBasicStatisticsPage(fd)
+ elif fd.submitID == 'updateRecord':
+ from updateTrait import DataUpdatePage
+ reload(DataUpdatePage)
+ req.content_type = 'text/html'
+ page=DataUpdatePage.DataUpdatePage(fd)
+ elif fd.submitID == 'addRecord':
+ from collection import AddUserInputToSelectionPage
+ reload(AddUserInputToSelectionPage)
+ page = AddUserInputToSelectionPage.AddUserInputToSelectionPage(fd)
+ req.content_type = 'text/html'
+ elif fd.submitID == 'addPublish':
+ from submitTrait import AddUserInputToPublishPage
+ reload(AddUserInputToPublishPage)
+ req.content_type = 'text/html'
+ page = AddUserInputToPublishPage.AddUserInputToPublishPage(fd)
+ elif fd.submitID == 'correlation':
+ from cmdLine import cmdCorrelationPage
+ reload(cmdCorrelationPage)
+ page = cmdCorrelationPage.cmdCorrelationPage(fd)
+ elif fd.submitID == 'intervalMap':
+ from cmdLine import cmdIntervalMappingPage
+ reload(cmdIntervalMappingPage)
+ page = cmdIntervalMappingPage.cmdIntervalMappingPage(fd)
+ elif fd.submitID == 'markerRegression':
+ from cmdLine import cmdMarkerRegressionPage
+ reload(cmdMarkerRegressionPage)
+ req.content_type = 'text/html'
+ page = cmdMarkerRegressionPage.cmdMarkerRegressionPage(fd)
+
+ elif fd.submitID == 'directPlot':
+ from cmdLine import cmdDirectPlotPage
+ reload(cmdDirectPlotPage)
+ req.content_type = 'text/html'
+ page = cmdDirectPlotPage.cmdDirectPlotPage(fd)
+ elif fd.submitID == 'exportData':
+ from showTrait import exportPage
+ reload(exportPage)
+ req.content_type = 'text/html'
+ page = exportPage.ExportPage(fd)
+ elif fd.submitID == 'showAll':
+ from cmdLine import cmdShowAllPage
+ reload(cmdShowAllPage)
+ page = cmdShowAllPage.cmdShowAllPage(fd)
+ elif fd.submitID == 'showAll2':
+ from cmdLine import cmdShowAllPage2
+ reload(cmdShowAllPage2)
+ page=cmdShowAllPage2.cmdShowAllPage2(fd)
+ else:
+ pass
+
+ #from marker regression result page
+ elif fd.formID == 'secondRegression':
+ if not fd.submitID:
+ req.content_type = 'text/html'
+ req.write('check your page')
+ elif fd.submitID == 'compositeRegression':
+ req.content_type = 'text/html'
+ from markerRegression import CompositeMarkerRegressionPage
+ reload(CompositeMarkerRegressionPage)
+ page = CompositeMarkerRegressionPage.CompositeMarkerRegressionPage(fd)
+ elif fd.submitID == 'intervalMap':
+ from intervalMapping import IntervalMappingPage
+ reload(IntervalMappingPage)
+ page = IntervalMappingPage.IntervalMappingPage(fd)
+ else:
+ pass
+
+ #cmdLine
+ elif fd.formID == 'showIntMap':
+ from cmdLine import cmdIntervalMappingPage
+ reload(cmdIntervalMappingPage)
+ page = cmdIntervalMappingPage.cmdIntervalMappingPage(fd)
+ elif fd.formID == 'heatmap':
+ from cmdLine import cmdHeatmapPage
+ reload(cmdHeatmapPage)
+ page = cmdHeatmapPage.cmdHeatmapPage(fd)
+ elif fd.formID == 'networkGraph':
+ from cmdLine import cmdNetworkGraphPage
+ reload(cmdNetworkGraphPage)
+ page = cmdNetworkGraphPage.cmdNetworkGraphPage(fd)
+ elif fd.formID == 'compCorr2':
+ from cmdLine import cmdCompCorrPage
+ reload(cmdCompCorrPage)
+ page = cmdCompCorrPage.cmdCompCorrPage(fd)
+ elif fd.formID == 'calPartialCorrDB':
+ from cmdLine import cmdPartialCorrelationPage
+ reload(cmdPartialCorrelationPage)
+ page = cmdPartialCorrelationPage.cmdPartialCorrelationPage(fd)
+
+ #pairScan
+ elif fd.formID == 'showCategoryGraph':
+ from pairScan import CategoryGraphPage
+ reload(CategoryGraphPage)
+ req.content_type = 'text/html'
+ page = CategoryGraphPage.CategoryGraphPage(fd)
+ elif fd.formID == 'pairPlot':
+ from pairScan import PairPlotPage
+ reload(PairPlotPage)
+ req.content_type = 'text/html'
+ page = PairPlotPage.PairPlotPage(fd)
+
+ #compareCorrelates
+ elif fd.formID == 'compCorr':
+ from compareCorrelates import MultipleCorrelationPage
+ reload(MultipleCorrelationPage)
+ page = MultipleCorrelationPage.MultipleCorrelationPage(fd)
+
+ #correlationMatrix
+ elif fd.formID == 'corMatrix':
+ from correlationMatrix import CorrelationMatrixPage
+ reload(CorrelationMatrixPage)
+ req.content_type = 'text/html'
+ page = CorrelationMatrixPage.CorrelationMatrixPage(fd)
+ elif fd.formID=='tissueCorrelation' or fd.formID=='dispMultiSymbolsResult':
+ from correlationMatrix import TissueCorrelationPage
+ reload(TissueCorrelationPage)
+ page = TissueCorrelationPage.TissueCorrelationPage(fd)
+ elif fd.formID =='dispTissueCorrelationResult':
+ from cmdLine import cmdTissueCorrelationResultPage
+ reload (cmdTissueCorrelationResultPage)
+ page = cmdTissueCorrelationResultPage.cmdTissueCorrelationResultPage(fd)
+ elif fd.formID=='tissueAbbreviation':
+ from correlationMatrix import TissueAbbreviationPage
+ reload(TissueAbbreviationPage)
+ page = TissueAbbreviationPage.TissueAbbreviationPage(fd)
+
+ #collection
+ elif fd.formID == 'dispSelection':
+ from collection import DisplaySelectionPage
+ reload(DisplaySelectionPage)
+ page = DisplaySelectionPage.DisplaySelectionPage(fd)
+ req.content_type = 'text/html'
+ elif fd.formID == 'addToSelection':
+ from collection import AddToSelectionPage
+ reload(AddToSelectionPage)
+ page = AddToSelectionPage.AddToSelectionPage(fd)
+ req.content_type = 'text/html'
+ elif fd.formID == 'removeSelection':
+ from collection import RemoveSelectionPage
+ reload(RemoveSelectionPage)
+ page = RemoveSelectionPage.RemoveSelectionPage(fd)
+ req.content_type = 'text/html'
+ elif fd.formID == 'exportSelect':
+ from collection import ExportSelectionPage
+ reload(ExportSelectionPage)
+ page = ExportSelectionPage.ExportSelectionPage(fd)
+ elif fd.formID == 'importSelect':
+ from collection import ImportSelectionPage
+ reload(ImportSelectionPage)
+ page = ImportSelectionPage.ImportSelectionPage(fd)
+ req.content_type = 'text/html'
+ elif fd.formID == 'exportSelectionDetailInfo':
+ from collection import ExportSelectionDetailInfoPage
+ reload(ExportSelectionDetailInfoPage)
+ page = ExportSelectionDetailInfoPage.ExportSelectionDetailInfoPage(fd)
+ elif fd.formID == 'batSubmitResult':
+ from collection import BatchSubmitSelectionPage
+ reload(BatchSubmitSelectionPage)
+ page = BatchSubmitSelectionPage.BatchSubmitSelectionPage(fd)
+ req.content_type = 'text/html'
+
+ #user
+ elif fd.formID == 'userLogin':
+ from user import userLogin
+ reload(userLogin)
+ page = userLogin.userLogin(fd)
+ req.content_type = 'text/html'
+ elif fd.formID == 'userLogoff':
+ from user import userLogoff
+ reload(userLogoff)
+ page = userLogoff.userLogoff(fd)
+ req.content_type = 'text/html'
+ elif fd.formID == 'userPasswd':
+ from user import userPasswd
+ reload(userPasswd)
+ page = userPasswd.userPasswd(fd)
+ req.content_type = 'text/html'
+
+ #submitTrait
+ elif fd.formID == 'pre_dataEditing':
+ from submitTrait import VarianceChoicePage
+ reload(VarianceChoicePage)
+ page = VarianceChoicePage.VarianceChoicePage(fd)
+ req.content_type = 'text/html'
+ elif fd.formID == 'batSubmit':
+ from submitTrait import BatchSubmitPage
+ reload(BatchSubmitPage)
+ req.content_type = 'text/html'
+ page = BatchSubmitPage.BatchSubmitPage(fd)
+
+
+ #misc
+ elif fd.formID == 'editHtml':
+ from misc import editHtmlPage
+ reload(editHtmlPage)
+ req.content_type = 'text/html'
+ page = editHtmlPage.editHtmlPage(fd)
+
+ #genomeGraph
+ elif fd.formID == 'transciptMapping':
+ from genomeGraph import cmdGenomeScanPage
+ reload(cmdGenomeScanPage)
+ req.content_type = 'text/html'
+ page = cmdGenomeScanPage.cmdGenomeScanPage(fd)
+ elif fd.formID == 'genAllDbResult':
+ from genomeGraph import genAllDbResultPage
+ reload(genAllDbResultPage)
+ page = genAllDbResultPage.genAllDbResultPage(fd)
+
+ #geneWiki
+ elif fd.formID == 'geneWiki':
+ from geneWiki import AddGeneRIFPage
+ reload(AddGeneRIFPage)
+ page = AddGeneRIFPage.AddGeneRIFPage(fd)
+
+ #externalResource
+ elif fd.formID == 'GOTree':
+ from externalResource import GoTreePage
+ reload(GoTreePage)
+ req.content_type = 'text/html'
+ page = GoTreePage.GoTreePage(fd)
+ elif fd.formID == 'ODE':
+ from externalResource import ODEPage
+ reload(ODEPage)
+ req.content_type = 'text/html'
+ page = ODEPage.ODEPage(fd)
+ elif fd.formID == 'GCAT':
+ from externalResource import GCATPage
+ reload(GCATPage)
+ req.content_type = 'text/html'
+ page = GCATPage.GCATPage(fd)
+
+ #management
+ elif fd.formID == 'managerMain':
+ from management import managerMainPage
+ reload(managerMainPage)
+ req.content_type = 'text/html'
+ page = managerMainPage.managerMainPage(fd)
+ elif fd.formID == 'createUserAccount':
+ from management import createUserAccountPage
+ reload(createUserAccountPage)
+ req.content_type = 'text/html'
+ page = createUserAccountPage.createUserAccountPage(fd)
+ elif fd.formID == 'assignUserToDataset':
+ from management import assignUserToDatasetPage
+ reload(assignUserToDatasetPage)
+ req.content_type = 'text/html'
+ page = assignUserToDatasetPage.assignUserToDatasetPage(fd)
+ elif fd.formID == 'deletePhenotypeTrait':
+ from management import deletePhenotypeTraitPage
+ reload(deletePhenotypeTraitPage)
+ req.content_type = 'text/html'
+ page = deletePhenotypeTraitPage.deletePhenotypeTraitPage(fd)
+ elif fd.formID == 'exportPhenotypeDataset':
+ from management import exportPhenotypeDatasetPage
+ reload(exportPhenotypeDatasetPage)
+ req.content_type = 'text/html'
+ page = exportPhenotypeDatasetPage.exportPhenotypeDatasetPage(fd)
+ elif fd.formID == 'editHeaderFooter':
+ from management import editHeaderFooter
+ reload(editHeaderFooter)
+ req.content_type = 'text/html'
+ page = editHeaderFooter.editHeaderFooter(fd)
+ elif fd.formID == 'updGeno':
+ from management import GenoUpdate
+ reload(GenoUpdate)
+ req.content_type = 'text/html'
+ page = GenoUpdate.GenoUpdate(fd)
+
+ #correlation
+ elif fd.formID == 'showCorrelationPlot':
+ from correlation import PlotCorrelationPage
+ reload(PlotCorrelationPage)
+ req.content_type = 'text/html'
+ page = PlotCorrelationPage.PlotCorrelationPage(fd)
+ elif fd.formID == 'partialCorrInput':
+ from correlation import PartialCorrInputPage
+ reload(PartialCorrInputPage)
+ req.content_type = 'text/html'
+ page = PartialCorrInputPage.PartialCorrInputPage(fd)
+ elif fd.formID == 'calPartialCorrTrait':
+ from correlation import PartialCorrTraitPage
+ reload(PartialCorrTraitPage)
+ req.content_type = 'text/html'
+ page = PartialCorrTraitPage.PartialCorrTraitPage(fd)
+
+ #elif fd.formID == 'BNInput':
+ # from BN import BNInputPage
+ # reload(BNInputPage)
+ # req.content_type = 'text/html'
+ # page = BNInputPage.BNInputPage(fd)
+
+ elif fd.formID == 'updateRecord':
+ from updateTrait import DataUpdatePage
+ reload(DataUpdatePage)
+ req.content_type = 'text/html'
+ page=DataUpdatePage.DataUpdatePage(fd)
+
+ #schema
+ elif fd.formID == 'schemaShowPage':
+ from schema import ShowSchemaPage
+ reload(ShowSchemaPage)
+ req.content_type = 'text/html'
+ page = ShowSchemaPage.ShowSchemaPage(fd)
+ elif fd.formID == 'schemaShowComment':
+ from schema import ShowCommentPage
+ reload(ShowCommentPage)
+ req.content_type = 'text/html'
+ page = ShowCommentPage.ShowCommentPage(fd)
+ elif fd.formID == 'schemaUpdateComment':
+ from schema import UpdateCommentPage
+ reload(UpdateCommentPage)
+ req.content_type = 'text/html'
+ page = UpdateCommentPage.UpdateCommentPage(fd)
+
+ #snpBrowser
+ elif fd.formID == 'snpBrowser':
+ req.content_type = 'text/html'
+ snpId = fd.formdata.getfirst('snpId')
+ if snpId:
+ from snpBrowser import snpDetails
+ reload(snpDetails)
+ page = snpDetails.snpDetails(fd, snpId)
+ else:
+ from snpBrowser import snpBrowserPage
+ reload(snpBrowserPage)
+ page = snpBrowserPage.snpBrowserPage(fd)
+ elif fd.formID =='SnpBrowserResultPage':
+ from cmdLine import cmdSnpBrowserResultPage
+ reload (cmdSnpBrowserResultPage)
+ page = cmdSnpBrowserResultPage.cmdSnpBrowserResultPage(fd)
+
+ #intervalAnalyst
+ elif fd.formID == 'intervalAnalyst':
+ from intervalAnalyst import IntervalAnalystPage
+ reload(IntervalAnalystPage)
+ req.content_type = 'text/html'
+ page = IntervalAnalystPage.IntervalAnalystPage(fd)
+
+ #AJAX_table
+ elif fd.formID == 'AJAX_table':
+ from utility import AJAX_table
+ reload(AJAX_table)
+ req.content_type = 'text/html'
+ req.write(AJAX_table.AJAX_table(fd).write())
+
+ elif fd.formID == 'submitSingleTrait':
+ from submitTrait import CrossChoicePage
+ reload(CrossChoicePage)
+ page = CrossChoicePage.CrossChoicePage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'sharing':
+ from dataSharing import SharingPage
+ reload(SharingPage)
+ page = SharingPage.SharingPage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'sharinginfo':
+ from dataSharing import SharingInfoPage
+ reload(SharingInfoPage)
+ page = SharingInfoPage.SharingInfoPage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'sharinginfoedit':
+ from dataSharing import SharingInfoEditPage
+ reload(SharingInfoEditPage)
+ page = SharingInfoEditPage.SharingInfoEditPage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'sharinginfodelete':
+ from dataSharing import SharingInfoDeletePage
+ reload(SharingInfoDeletePage)
+ page = SharingInfoDeletePage.SharingInfoDeletePage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'sharinginfoupdate':
+ from dataSharing import SharingInfoUpdatePage
+ reload(SharingInfoUpdatePage)
+ page = SharingInfoUpdatePage.SharingInfoUpdatePage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'sharingListDataset':
+ from dataSharing import SharingListDataSetPage
+ reload(SharingListDataSetPage)
+ page = SharingListDataSetPage.SharingListDataSetPage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'sharinginfoadd':
+ from dataSharing import SharingInfoAddPage
+ reload(SharingInfoAddPage)
+ page = SharingInfoAddPage.SharingInfoAddPage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'annotation':
+ from annotation import AnnotationPage
+ reload(AnnotationPage)
+ page = AnnotationPage.AnnotationPage(fd)
+ req.content_type = 'text/html'
+
+ elif fd.formID == 'qtlminer':
+ from qtlminer import QTLminer
+ reload(QTLminer)
+ req.content_type = 'text/html'
+ page = QTLminer.QTLminer(fd)
+ elif fd.formID == 'qtlminerresult':
+ from cmdLine import cmdQTLminerPage
+ reload (cmdQTLminerPage)
+ page = cmdQTLminerPage.cmdQTLminerPage(fd)
+
+ else:
+ from search import IndexPage
+ reload(IndexPage)
+ page = IndexPage.IndexPage(fd)
+ req.content_type = 'text/html'
+
+ #elif fd.formID == 'updGeno':
+ # import GenoUpdate
+ # reload(GenoUpdate)
+ # req.content_type = 'text/html'
+ # page=GenoUpdate.GenoUpdate(fd)
+ #elif fd.formID == 'updStrain':
+ # import StrainUpdate
+ # reload(StrainUpdate)
+ # req.content_type = 'text/html'
+ # page=StrainUpdate.StrainUpdate(fd)
+ #elif fd.formID == 'showTextResult':
+ # import resultPage
+ # reload(resultPage)
+ # page = resultPage.ShowTextResult(fd)
+ #elif fd.formID == 'showStrainInfo':
+ # import dataPage
+ # reload(dataPage)
+ # req.content_type = 'text/html'
+ # page = dataPage.ShowStrainInfoPage(fd)
+ #elif fd.formID == 'showImage':
+ # import dataPage
+ # reload(dataPage)
+ # req.content_type = 'text/html'
+ # page = dataPage.ShowImagePage(fd)
+ #XZ, 04/29/2009: There is one webpage gn/web/webqtl/blat.html and I have moved it to junk folder. This function is very old and I don't think it is being used.
+ #elif fd.formID == 'BlatSearch':
+ # import miscPage
+ # reload(miscPage)
+ # page = miscPage.ShowBlatResult(fd)
+ #elif fd.formID == 'admin':
+ # import adminPage
+ # reload(adminPage)
+ # req.content_type = 'text/html'
+ # page = adminPage.adminModifyPage(fd)
+
+ elif cmdID:
+ #need to rewrite
+ cmdID = string.lower(cmdID)
+ if cmdID in ('get','trait','tra'):
+ from textUI import cmdGet
+ reload(cmdGet)
+ req.content_type = 'text/plain'
+ req.write(cmdGet.cmdGet(fd).write())
+ elif cmdID in ('help', 'hlp'):
+ from textUI import cmdHelp
+ reload(cmdHelp)
+ req.content_type = 'text/plain'
+ req.write(cmdHelp.cmdHelp(fd).write())
+ elif cmdID in ('correlation','cor','pea','pearson'):
+ from textUI import cmdCorrelation
+ reload(cmdCorrelation)
+ req.content_type = 'text/plain'
+ req.write(cmdCorrelation.cmdCorrelation(fd).write())
+ elif cmdID in ('map','marker'):
+ from textUI import cmdMap
+ reload(cmdMap)
+ req.content_type = 'text/plain'
+ req.write(cmdMap.cmdMap(fd).write())
+ elif cmdID in ('geno','gen','genotype'):
+ from textUI import cmdGeno
+ reload(cmdGeno)
+ req.content_type = 'text/plain'
+ req.write(cmdGeno.cmdGeno(fd).write())
+ elif cmdID in ('interval','int'):
+ from textUI import cmdInterval
+ reload(cmdInterval)
+ req.content_type = 'text/plain'
+ req.write(cmdInterval.cmdInterval(fd).write())
+ elif cmdID in ('show','shw'):
+ from textUI import cmdShowEditing
+ reload(cmdShowEditing)
+ req.content_type = 'text/html'
+ result = cmdShowEditing.cmdShowEditing(fd)
+ page = result.page
+ elif cmdID in ('search','sch'):
+ req.content_type = 'text/plain'
+ from textUI import cmdSearchGene
+ reload(cmdSearchGene)
+ result = cmdSearchGene.cmdSearchGene(fd)
+ page = result.page
+ req.write(result.text)
+
+ #elif cmdID in ('tst','Test'):
+ # req.write('Content-type: application/x-download')
+ # req.write('Content-disposition: attachment; filename=my.txt\n')
+ # genotype_file = GENODIR + 'AKXD.geno'
+ # fp = open(genotype_file)
+ # line = fp.read()
+ # fp.close()
+ # req.write(line)
+ #XZ, 03/03/2009: This fuction must be initiated from URL
+ #XZ: http://www.genenetwork.org/webqtl/WebQTL.py?cmd=birn&species=mouse&tissue=Hippocampus&ProbeId=1436869_at&Strain=BXD1
+ #elif cmdID[0:4]=="birn":
+ # req.content_type = 'text/plain'
+ # import BIRN
+ # reload(BIRN)
+ # result = BIRN.birnSwitch(fd)
+ # req.write(result.text)
+ #elif cmdID in ('spear','spearman','spe'):
+ # import cmdSpearman # new modules
+ # reload(cmdSpearman)
+ # req.content_type = 'text/plain'
+ # req.write(cmdSpearman.cmdSpearman(fd).write())
+ #elif cmdID in ('snp','track'):
+ # import cmdSnpTrack # new modules
+ # reload(cmdSnpTrack)
+ # req.content_type = 'text/plain'
+ # req.write(cmdSnpTrack.cmdSnpTrack(fd).write())
+
+ else:
+ req.content_type = 'text/html'
+ req.write("###Wrong Command")
+
+ ######## Create first page when called with no formID ########
+
+ else:
+ _log.info("Going to the search page")
+ from search import IndexPage
+ reload(IndexPage)
+ page = IndexPage.IndexPage(fd)
+ req.content_type = 'text/html'
+
+ if page:
+ #send Cookie first
+ if page.cookie:
+ for item in page.cookie:
+ if (item):
+ modcookie = Cookie.Cookie(item.name, item.value)
+ modcookie.path = item.path
+ if item.expire != None:
+ modcookie.expires = time.time() + item.expire
+ Cookie.add_cookie(req, modcookie)
+
+ #save session
+ if page.session_data_changed:
+ for one_key in page.session_data_changed.keys():
+ mod_python_session[one_key] = page.session_data_changed[one_key]
+ mod_python_session.save()
+
+
+ req.content_type= page.content_type
+
+ #send attachment
+ if page.redirection:
+ util.redirect(req, page.redirection)
+ elif page.content_disposition:
+ req.headers_out["Content-Disposition"] = page.content_disposition
+ req.write(page.attachment)
+ elif page.debug: # for debug
+ req.write(page.debug)
+ #send regular content
+ else:
+ req.write(page.write())
+ else:
+ pass
+
+ return apache.OK
+
+
diff --git a/web/webqtl/maintainance/__init__.py b/web/webqtl/maintainance/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/maintainance/__init__.py
diff --git a/web/webqtl/maintainance/addRif.py b/web/webqtl/maintainance/addRif.py
new file mode 100755
index 00000000..c7cdde7a
--- /dev/null
+++ b/web/webqtl/maintainance/addRif.py
@@ -0,0 +1,107 @@
+# 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 Lei Yan 2011/02/08
+
+# created by Lei Yan 02/08/2011
+
+import string
+import MySQLdb
+import time
+import os
+import sys
+
+path1 = os.path.abspath(os.path.dirname(__file__))
+path2 = path1 + "/.."
+path3 = path1 + "/../../tmp"
+sys.path.insert(0, path2)
+from base import webqtlConfig
+
+try:
+ con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+ cursor = con.cursor()
+ print "You have successfully connected to mysql.\n"
+except:
+ print "You entered incorrect password.\n"
+ sys.exit(0)
+
+taxIds = {'10090':1, '9606':4, '10116':2, '3702':3}
+taxIdKeys = taxIds.keys()
+
+os.chdir(path3)
+cdict = {}
+
+os.system("rm -f gene_info")
+os.system("wget ftp://ftp.ncbi.nlm.nih.gov/gene/DATA/gene_info.gz")
+os.system("gunzip gene_info.gz")
+try:
+ fp = open("gene_info")
+except:
+ print "gene_info doesn't exit"
+ sys.exit(1)
+
+i=0
+line = fp.readline()
+while line:
+ line2 = map(string.strip, string.split(line.strip(), "\t"))
+ if line2[0] in taxIdKeys:
+ cdict[line2[1]] = line2[2]
+ line = fp.readline()
+ i += 1
+ if i%1000 == 0:
+ print "finished ", i
+fp.close()
+
+os.system("rm -f generifs_basic")
+os.system("wget ftp://ftp.ncbi.nlm.nih.gov/gene/GeneRIF/generifs_basic.gz")
+os.system("gunzip generifs_basic.gz")
+try:
+ fp = open("generifs_basic")
+except:
+ print "generifs_basic doesn't exist"
+ sys.exit(1)
+
+cursor.execute("delete from GeneRIF_BASIC")
+count = 0
+line = fp.readline()
+while line:
+ line2 = map(string.strip, string.split(line.strip(), "\t"))
+ if line2[0] in taxIdKeys:
+ count += 1
+ line2[0] = taxIds[line2[0]]
+ if len(line2) !=5:
+ print line
+ else:
+ try:
+ symbol=cdict[line2[1]]
+ except:
+ symbol= ""
+
+ line2 = line2[:2] + [symbol] + line2[2:]
+ cursor.execute("insert into GeneRIF_BASIC(SpeciesId, GeneId, Symbol, PubMed_ID, createtime, comment) values(%s, %s, %s, %s, %s, %s)", tuple(line2))
+ line = fp.readline()
+
+fp.close()
+print count, "\n"
+cursor.close()
diff --git a/web/webqtl/maintainance/checkInfoFile.py b/web/webqtl/maintainance/checkInfoFile.py
new file mode 100755
index 00000000..6aa0d771
--- /dev/null
+++ b/web/webqtl/maintainance/checkInfoFile.py
@@ -0,0 +1,102 @@
+# 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 2011/01/28
+
+# created by Ning Liu 2011/01/27
+# This script is to check whether dataset related Info file exist or not; if not, the tempate Info file will be generated
+# This script should be only run at GeneNetwork production server
+
+import sys, os
+import MySQLdb
+
+current_file_name = __file__
+pathname = os.path.dirname( current_file_name )
+abs_path = os.path.abspath(pathname)
+sys.path.insert(0, abs_path + '/..')
+
+from base import template
+from base import webqtlConfig
+from base import header
+from base import footer
+
+# build MySql database connection
+con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+cursor = con.cursor()
+
+InfoFilePath =webqtlConfig.HTMLPATH+'dbdoc/'
+
+# create template for Info file
+def createTemplateForInfoFile(datasetId=None,datasetFullName=None,InfoFileURL=None):
+ #template.py has been changed with dynamic header and footer
+ userInfo=""
+ headerInfo=header.header_string % userInfo
+ serverInfo=""
+ footerInfo=footer.footer_string % serverInfo
+
+ title =datasetFullName
+ contentTitle = '''
+ <P class="title">%s<A HREF="/webqtl/main.py?FormID=editHtml"><img src="/images/modify.gif" alt="modify this page" border= 0 valign="middle"></A><BR><BR>
+ ''' % datasetFullName
+ content ='''
+ Accession number: <A HREF="/webqtl/main.py?FormID=sharinginfo&GN_AccessionId=%s">GN%s</A></P>
+ <br><br>
+ This page will be updated soon.
+ <br><br>
+ ''' % (datasetId,datasetId)
+
+ body=contentTitle+content
+ # Note: 'templateParameters' includes parameters required for template.py
+ # templateParameters = ['title','basehref','js1','js2','layer','header','body', 'footer']
+ templateParameters =[title,'','','','',headerInfo,body,footerInfo]
+
+ # build template file
+ templateFile=template.template % tuple(templateParameters)
+ InfoFileHandler = open(InfoFileURL, 'w')
+ # write template file into Info .html file
+ InfoFileHandler.write(templateFile)
+ InfoFileHandler.close()
+
+
+# select all ProbeSet names from datatable 'ProbeSetFreeze'
+cursor.execute("select Id, Name, FullName from ProbeSetFreeze ")
+results = cursor.fetchall()
+for item in results:
+ datasetId = item[0]
+ datasetName =item[1]
+ datasetFullName =item[2]
+ InfoFileURL = InfoFilePath+datasetName+".html"
+ # check Info html file exist or not
+ if not os.path.exists(InfoFileURL):
+ createTemplateForInfoFile(datasetId=datasetId,datasetFullName=datasetFullName,InfoFileURL=InfoFileURL)
+
+
+
+
+
+
+
+
+
+
diff --git a/web/webqtl/maintainance/genSelectDatasetJS.py b/web/webqtl/maintainance/genSelectDatasetJS.py
new file mode 100755
index 00000000..bc88beec
--- /dev/null
+++ b/web/webqtl/maintainance/genSelectDatasetJS.py
@@ -0,0 +1,637 @@
+# 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 2011/01/27
+
+# created by Ning Liu 07/01/2010
+# This script is to generate selectDatasetMenu.js file for cascade menu in the main search page http://www.genenetwork.org/.
+# This script will be run automatically every one hour or manually when database has been changed .
+import sys, os
+
+current_file_name = __file__
+pathname = os.path.dirname( current_file_name )
+abs_path = os.path.abspath(pathname)
+sys.path.insert(0, abs_path + '/..')
+
+import MySQLdb
+import os
+import string
+import time
+import datetime
+
+from base import template
+from base import webqtlConfig
+
+#################################################################################
+# input: searchArray, targetValue
+# function: retrieve index info of target value in designated array (searchArray)
+# output: return index info
+##################################################################################
+def getIndex(searchArray=None, targetValue=None):
+ for index in range(len(searchArray)):
+ if searchArray[index][0]==targetValue:
+ return index
+
+# build MySql database connection
+con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+cursor = con.cursor()
+
+# create js_select.js file
+fileHandler = open(webqtlConfig.HTMLPATH + 'javascript/selectDatasetMenu.js', 'w')
+
+# define SpeciesString, GroupString, TypeString, DatabasingString, LinkageString for output
+# outputSpeciesStr is for building Species Array(sArr) in js file; outputGroupStr is for Group Array(gArr)
+# outputTypeStr is for Type Array(tArr); outputDatabaseStr is for Database Array(dArr)
+# outputLinkStr is for Linkage Array(lArr)
+outputTimeStr ="/* Generated Date : %s , Time : %s */ \n" % (datetime.date.today(),time.strftime("%H:%M ", time.localtime()))
+outputTimeStr =""
+outputSpeciesStr ='var sArr = [\n{txt:\'\',val:\'\'},\n'
+outputGroupStr ='var gArr = [\n{txt:\'\',val:\'\'},\n'
+outputTypeStr ='var tArr = [\n{txt:\'\',val:\'\'},\n'
+outputDatabaseStr ='var dArr = [\n{txt:\'\',val:\'\'},\n'
+outputLinkStr ='var lArr = [\n null,\n'
+
+# built speices array in js file for select menu in the main search page http://www.genenetwork.org/
+cursor.execute("select Name, MenuName from Species order by OrderId")
+speciesResult = cursor.fetchall()
+speciesTotalResult = list(speciesResult)
+speciesResultsTotalNum = cursor.rowcount
+if speciesResultsTotalNum >0:
+ for speciesItem in speciesResult:
+ speciesVal = speciesItem[0]
+ speciesTxt = speciesItem[1]
+ outputSpeciesStr += '{txt:\'%s\',val:\'%s\'},\n'%(speciesTxt,speciesVal)
+# 'All Species' option for 'Species' select menu
+outputSpeciesStr +='{txt:\'All Species\',val:\'All Species\'}];\n\n'
+#speciesTotalResult is a list which inclues all species' options
+speciesTotalResult.append(('All Species','All Species'))
+
+# built group array in js file for select menu in the main search page http://www.genenetwork.org/
+cursor.execute("select distinct InbredSet.Name, InbredSet.FullName from InbredSet, Species, ProbeFreeze, GenoFreeze, PublishFreeze where InbredSet.SpeciesId= Species.Id and InbredSet.Name != 'BXD300' and (PublishFreeze.InbredSetId = InbredSet.Id or GenoFreeze.InbredSetId = InbredSet.Id or ProbeFreeze.InbredSetId = InbredSet.Id) order by InbredSet.Name")
+groupResults = cursor.fetchall()
+groupTotalResults = list(groupResults)
+groupResultsTotalNum = cursor.rowcount
+if groupResultsTotalNum > 0:
+ for groupItem in groupResults:
+ groupVal = groupItem[0]
+ groupTxt = groupItem[1]
+ outputGroupStr += '{txt:\'%s\',val:\'%s\'},\n'%(groupTxt,groupVal)
+# add 'All Groups' option for 'Group' select menu
+outputGroupStr +='{txt:\'All Groups\',val:\'all groups\'}];\n\n'
+# groupTotalResults is a list which inclues all groups' options
+groupTotalResults.append(('all groups','All Groups'))
+
+# built type array in js file for select menu in the main search page http://www.genenetwork.org/
+cross = groupVal
+cursor.execute("select distinct Tissue.Name, concat(Tissue.Name, ' mRNA') from ProbeFreeze, ProbeSetFreeze, InbredSet, Tissue where ProbeFreeze.TissueId = Tissue.Id and ProbeFreeze.InbredSetId = InbredSet.Id and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.public > %d order by Tissue.Name" % (webqtlConfig.PUBLICTHRESH))
+typeResults = cursor.fetchall()
+typeTotalResults = list(typeResults)
+typeResultsTotalNum = cursor.rowcount
+if typeResultsTotalNum > 0:
+ for typeItem in typeResults:
+ typeVal = typeItem[0]
+ typeTxt = typeItem[1]
+ outputTypeStr += '{txt:\'%s\',val:\'%s\'},\n'%(typeTxt,typeVal)
+# add 'Phenotypes' and 'Genotypes' options for 'Type' select menu
+outputTypeStr +='{txt:\'Phenotypes\',val:\'Phenotypes\'},\n'
+outputTypeStr +='{txt:\'Genotypes\',val:\'Genotypes\'}];\n\n'
+# typeTotalResults is a list which inclues all types' options
+typeTotalResults.append(('Phenotypes','Phenotypes'))
+typeTotalResults.append(('Genotypes','Genotypes'))
+
+# built dataset array in js file for select menu in the main search page http://www.genenetwork.org/
+tissue = typeVal
+cursor.execute("select ProbeSetFreeze.Name, ProbeSetFreeze.FullName from ProbeSetFreeze, ProbeFreeze, InbredSet, Tissue where ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeFreeze.TissueId = Tissue.Id and ProbeFreeze.InbredSetId = InbredSet.Id and ProbeSetFreeze.public > %d order by ProbeSetFreeze.CreateTime desc" % (webqtlConfig.PUBLICTHRESH))
+datasetResults = cursor.fetchall()
+datasetTotalResults = list(datasetResults)
+datasetResultsTotalNum = cursor.rowcount
+if datasetResultsTotalNum > 0:
+ for datasetItem in datasetResults:
+ datasetVal = datasetItem[0]
+ datasetTxt = datasetItem[1]
+ outputDatabaseStr += '{txt:\'%s\',val:\'%s\'},\n'%(datasetTxt,datasetVal)
+
+# This part is to built linkage array in js file, the linkage is among Species, Group, Type and Database.
+# The format of linkage array is [speciesIndex, groupIndex, typeIndex, databaseIndex]
+if speciesResultsTotalNum >0:
+ for speciesItem in speciesResult:
+ speciesVal = speciesItem[0]
+ sIndex = getIndex(searchArray=speciesTotalResult,targetValue=speciesVal)+1
+
+ # retrieve group info based on specie
+ cursor.execute("select distinct InbredSet.Name, InbredSet.FullName from InbredSet, Species, ProbeFreeze, GenoFreeze, PublishFreeze where InbredSet.SpeciesId= Species.Id and Species.Name='%s' and InbredSet.Name != 'BXD300' and (PublishFreeze.InbredSetId = InbredSet.Id or GenoFreeze.InbredSetId = InbredSet.Id or ProbeFreeze.InbredSetId = InbredSet.Id) order by InbredSet.Name" % speciesVal)
+ groupResults = cursor.fetchall()
+ groupResultsNum = cursor.rowcount
+
+ if groupResultsNum > 0:
+ for groupItem in groupResults:
+ groupVal = groupItem[0]
+ gIndex = getIndex(searchArray=groupTotalResults, targetValue=groupVal)+1
+
+ cross = groupVal
+ # if group also exists in PublishFreeze table, then needs to add related Published Phenotypes in Database Array(dArr) and Linkage Array(lArr)
+ # 'MDP' case is related to 'Mouse Phenome Database'
+ cursor.execute("select PublishFreeze.Id from PublishFreeze, InbredSet where PublishFreeze.InbredSetId = InbredSet.Id and InbredSet.Name = '%s'" % cross)
+ if (cursor.fetchall()):
+ typeVal = "Phenotypes"
+ if cross=='MDP':
+ datasetTxt = "Mouse Phenome Database"
+ else:
+ datasetTxt = "%s Published Phenotypes" % cross
+ datasetVal = "%sPublish" % cross
+ outputDatabaseStr += '{txt:\'%s\',val:\'%s\'},\n'% (datasetTxt,datasetVal)
+ datasetTotalResults.append(('%s'% datasetVal,'%s' % datasetTxt))
+
+ tIndex = getIndex(searchArray=typeTotalResults,targetValue=typeVal)+1
+ dIndex = getIndex(searchArray=datasetTotalResults, targetValue=datasetVal)+1
+ outputLinkStr +='[%d,%d,%d,%d],\n'%(sIndex,gIndex,tIndex,dIndex)
+
+ # if group also exists in GenoFreeze table, then needs to add related Genotypes in database Array(dArr)
+ cursor.execute("select GenoFreeze.Id from GenoFreeze, InbredSet where GenoFreeze.InbredSetId = InbredSet.Id and InbredSet.Name = '%s'" % cross)
+ if (cursor.fetchall()):
+ typeVal = "Genotypes"
+ datasetTxt = "%s Genotypes" % cross
+ datasetVal = "%sGeno" % cross
+ outputDatabaseStr += '{txt:\'%s\',val:\'%s\'},\n'%(datasetTxt,datasetVal)
+ typeTotalResults.append(('Genotypes','Genotypes'))
+ datasetTotalResults.append(('%s'% datasetVal,'%s' % datasetTxt))
+
+ tIndex = getIndex(searchArray=typeTotalResults,targetValue=typeVal)+1
+ dIndex = getIndex(searchArray=datasetTotalResults, targetValue=datasetVal)+1
+ outputLinkStr +='[%d,%d,%d,%d],\n'%(sIndex,gIndex,tIndex,dIndex)
+
+ # retrieve type(tissue) info based on group
+ # if cross is equal to 'BXD', then need to seach for 'BXD' and 'BXD300' InbredSet
+ if cross == "BXD":
+ cross2 = "BXD', 'BXD300"
+ else:
+ cross2 = cross
+ cursor.execute("select distinct Tissue.Name, concat(Tissue.Name, ' mRNA') from ProbeFreeze, ProbeSetFreeze, InbredSet, Tissue where ProbeFreeze.TissueId = Tissue.Id and ProbeFreeze.InbredSetId = InbredSet.Id and InbredSet.Name in ('%s') and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.public > %d order by Tissue.Name" % (cross2, webqtlConfig.PUBLICTHRESH))
+ typeResults = cursor.fetchall()
+ typeResultsNum = cursor.rowcount
+
+ if typeResultsNum > 0:
+ for typeItem in typeResults:
+ typeVal = typeItem[0]
+ tIndex = getIndex(searchArray=typeTotalResults, targetValue=typeVal)+1
+ # retrieve database(dataset) info based on group(InbredSet) and type(Tissue)
+ tissue = typeVal
+ cursor.execute("select ProbeSetFreeze.Name, ProbeSetFreeze.FullName from ProbeSetFreeze, ProbeFreeze, InbredSet, Tissue where ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeFreeze.TissueId = Tissue.Id and ProbeFreeze.InbredSetId = InbredSet.Id and InbredSet.Name in ('%s') and Tissue.name = '%s' and ProbeSetFreeze.public > %d order by ProbeSetFreeze.CreateTime desc" % (cross2, tissue, webqtlConfig.PUBLICTHRESH))
+ datasetResults = cursor.fetchall()
+ datasetResultsNum = cursor.rowcount
+
+ if datasetResultsNum > 0:
+ for datasetItem in datasetResults:
+ datasetVal = datasetItem[0]
+ dIndex = getIndex(searchArray=datasetTotalResults, targetValue=datasetVal)+1
+ outputLinkStr +='[%d,%d,%d,%d],\n'%(sIndex,gIndex,tIndex,dIndex)
+
+# add 'All Phenotypes' option for 'Database' select menu
+# for 'All Species'option in 'Species' select menu, 'Database' select menu will show 'All Phenotypes' option
+outputDatabaseStr += '{txt:\'%s\',val:\'%s\'}];\n\n'%('All Phenotypes','_allPublish')
+datasetTotalResults.append(('_allPublish','All Phenotypes'))
+
+sIndex = getIndex(searchArray=speciesTotalResult,targetValue='All Species')+1
+gIndex = getIndex(searchArray=groupTotalResults, targetValue='all groups')+1
+tIndex = getIndex(searchArray=typeTotalResults,targetValue='Phenotypes')+1
+dIndex = getIndex(searchArray=datasetTotalResults, targetValue='_allPublish')+1
+outputLinkStr +='[%d,%d,%d,%d]];\n\n'%(sIndex,gIndex,tIndex,dIndex)
+
+# Combine sArr, gArr, tArr, dArr and lArr output string together
+outputStr = outputTimeStr+outputSpeciesStr+outputGroupStr+outputTypeStr+outputDatabaseStr+outputLinkStr
+outputStr +='''
+
+/*
+* function: based on different browser use, will have different initial actions;
+* Once the index.html page is loaded, this function will be called
+*/
+function initialDatasetSelection()
+{
+ defaultSpecies =getDefaultValue('species');
+ defaultSet =getDefaultValue('cross');
+ defaultType =getDefaultValue('tissue');
+ defaultDB =getDefaultValue('database');
+
+ if (navigator.userAgent.indexOf('MSIE')>=0)
+ {
+ sOptions = fillOptionsForIE(null,defaultSpecies);
+ var menu0 ="<SELECT NAME='species' ID='species' SIZE='1' onChange='fillOptions(\\"species\\");'>"+sOptions+"</Select>";
+ document.getElementById('menu0').innerHTML = menu0;
+
+ gOptions = fillOptionsForIE('species',defaultSet);
+ var menu1 ="<Select NAME='cross' size=1 id='cross' onchange='fillOptions(\\"cross\\");'>"+gOptions+"</Select><input type=\\"button\\" class=\\"button\\" value=\\"Info\\" onCLick=\\"javascript:crossinfo();\\">";
+ document.getElementById('menu1').innerHTML =menu1;
+
+ tOptions = fillOptionsForIE('cross',defaultType);
+ var menu2 ="<Select NAME='tissue' size=1 id='tissue' onchange='fillOptions(\\"tissue\\");'>"+tOptions+"</Select>";
+ document.getElementById('menu2').innerHTML =menu2;
+
+ dOptions = fillOptionsForIE('tissue',defaultDB);
+ var menu3 ="<Select NAME='database' size=1 id='database'>"+dOptions+"</Select><input type=\\"button\\" class=\\"button\\" value=\\"Info\\" onCLick=\\"javascript:databaseinfo();\\">";
+ document.getElementById('menu3').innerHTML =menu3;
+
+ }else{
+ fillOptions(null);
+ }
+ searchtip();
+}
+
+/*
+* input: selectObjId (designated select menu, such as species, cross, etc... )
+* defaultValue (default Value of species, cross,tissue or database)
+* function: special for IE browser,setting options value for select menu dynamically based on linkage array(lArr),
+* output: options string
+*/
+function fillOptionsForIE(selectObjId,defaultValue)
+{
+ var options='';
+ if(selectObjId==null)
+ {
+ var len = sArr.length;
+ for (var i=1; i < len; i++) {
+ // setting Species' option
+ if( sArr[i].val==defaultValue){
+ options =options+"<option selected=\\"selected\\" value='"+sArr[i].val+"'>"+sArr[i].txt+"</option>";
+ }else{
+ options =options+"<option value='"+sArr[i].val+"'>"+sArr[i].txt+"</option>";
+ }
+ }
+ }else if(selectObjId=='species')
+ {
+ var speciesObj = document.getElementById('species');
+ var len = lArr.length;
+ var arr = [];
+ var idx = 0;
+ for (var i=1; i < len; i++) {
+ //get group(cross) info from lArr
+ if(lArr[i][0]==(getIndexByValue('species',speciesObj.value)).toString()&&!Contains(arr,lArr[i][1]))
+ {
+ arr[idx++]=lArr[i][1];
+ }
+ }
+ idx=0;
+ len = arr.length;
+ removeOptions("cross");
+ for (var i=0; i < len; i++) {
+ // setting Group's option
+ if( gArr[arr[i]].val==defaultValue){
+ options =options+"<option selected=\\"selected\\" value='"+gArr[arr[i]].val+"'>"+gArr[arr[i]].txt+"</option>";
+ }else{
+ options =options+"<option value='"+gArr[arr[i]].val+"'>"+gArr[arr[i]].txt+"</option>";
+ }
+
+ }
+ }else if(selectObjId=='cross')
+ {
+ var speciesObj = document.getElementById('species');
+ var groupObj = document.getElementById('cross');
+ var len = lArr.length;
+ var arr = [];
+ var idx = 0;
+ for (var i=1; i < len; i++) {
+ //get type(tissue) info from lArr
+ if(lArr[i][0]==(getIndexByValue('species',speciesObj.value)).toString()&&lArr[i][1]==(getIndexByValue('cross',groupObj.value)).toString()&&!Contains(arr,lArr[i][2]))
+ {
+ arr[idx++]=lArr[i][2];
+ }
+ }
+ idx=0;
+ len = arr.length;
+ removeOptions("tissue");
+ for (var i=0; i < len; i++) {
+ // setting Type's option
+ if( tArr[arr[i]].val==defaultValue){
+ options =options+"<option selected=\\"selected\\" value='"+tArr[arr[i]].val+"'>"+tArr[arr[i]].txt+"</option>";
+ }else{
+ options =options+"<option value='"+tArr[arr[i]].val+"'>"+tArr[arr[i]].txt+"</option>";
+ }
+ }
+
+ }else if(selectObjId=='tissue')
+ {
+ var speciesObj = document.getElementById('species');
+ var groupObj = document.getElementById('cross');
+ var typeObj = document.getElementById('tissue');
+
+ var len = lArr.length;
+ var arr = [];
+ var idx = 0;
+ for (var i=1; i < len; i++) {
+ //get dataset(database) info from lArr
+ if(lArr[i][0]==(getIndexByValue('species',speciesObj.value)).toString()&&lArr[i][1]==(getIndexByValue('cross',groupObj.value)).toString()&&lArr[i][2]==(getIndexByValue('tissue',typeObj.value)).toString()&&!Contains(arr,lArr[i][3]))
+ {
+ arr[idx++]=lArr[i][3];
+ }
+ }
+ idx=0;
+ len = arr.length;
+ removeOptions("database");
+ for (var i=0; i < len; i++) {
+ // setting Database's option
+ if( dArr[arr[i]].val==defaultValue){
+ options =options+"<option SELECTED value='"+dArr[arr[i]].val+"'>"+dArr[arr[i]].txt+"</option>";
+ }else{
+ options =options+"<option value='"+dArr[arr[i]].val+"'>"+dArr[arr[i]].txt+"</option>";
+ }
+ }
+ }
+ return options;
+}
+/*
+* input: selectObjId (designated select menu, such as species, cross, etc... )
+* function: setting options value for select menu dynamically based on linkage array(lArr)
+* output: null
+*/
+function fillOptions(selectObjId)
+{
+ if(selectObjId==null)
+ {
+
+ var speciesObj = document.getElementById('species');
+ var len = sArr.length;
+ for (var i=1; i < len; i++) {
+ // setting Species' option
+ speciesObj.options[i-1] = new Option(sArr[i].txt, sArr[i].val);
+ }
+ updateChocie('species');
+
+ }else if(selectObjId=='species')
+ {
+ var speciesObj = document.getElementById('species');
+ var groupObj = document.getElementById('cross');
+ var len = lArr.length;
+ var arr = [];
+ var idx = 0;
+ for (var i=1; i < len; i++) {
+ //get group(cross) info from lArr
+ if(lArr[i][0]==(getIndexByValue('species',speciesObj.value)).toString()&&!Contains(arr,lArr[i][1]))
+ {
+ arr[idx++]=lArr[i][1];
+ }
+ }
+ idx=0;
+ len = arr.length;
+ removeOptions("cross");
+ for (var i=0; i < len; i++) {
+ // setting Group's option
+ groupObj.options[idx++] = new Option(gArr[arr[i]].txt, gArr[arr[i]].val);
+ }
+ updateChocie('cross');
+
+ }else if(selectObjId=='cross')
+ {
+ var speciesObj = document.getElementById('species');
+ var groupObj = document.getElementById('cross');
+ var typeObj = document.getElementById('tissue');
+ var len = lArr.length;
+ var arr = [];
+ var idx = 0;
+ for (var i=1; i < len; i++) {
+ //get type(tissue) info from lArr
+ if(lArr[i][0]==(getIndexByValue('species',speciesObj.value)).toString()&&lArr[i][1]==(getIndexByValue('cross',groupObj.value)).toString()&&!Contains(arr,lArr[i][2]))
+ {
+ arr[idx++]=lArr[i][2];
+ }
+ }
+ idx=0;
+ len = arr.length;
+ removeOptions("tissue");
+ for (var i=0; i < len; i++) {
+ // setting Type's option
+ typeObj.options[idx++] = new Option(tArr[arr[i]].txt, tArr[arr[i]].val);
+ }
+ updateChocie('tissue');
+
+ }else if(selectObjId=='tissue')
+ {
+ var speciesObj = document.getElementById('species');
+ var groupObj = document.getElementById('cross');
+ var typeObj = document.getElementById('tissue');
+ var databaseObj = document.getElementById('database');
+
+ var len = lArr.length;
+ var arr = [];
+ var idx = 0;
+ for (var i=1; i < len; i++) {
+ //get dataset(database) info from lArr
+ if(lArr[i][0]==(getIndexByValue('species',speciesObj.value)).toString()&&lArr[i][1]==(getIndexByValue('cross',groupObj.value)).toString()&&lArr[i][2]==(getIndexByValue('tissue',typeObj.value)).toString()&&!Contains(arr,lArr[i][3]))
+ {
+ arr[idx++]=lArr[i][3];
+ }
+ }
+ idx=0;
+ len = arr.length;
+ removeOptions("database");
+ for (var i=0; i < len; i++) {
+ // setting Database's option
+ databaseObj.options[idx++] = new Option(dArr[arr[i]].txt, dArr[arr[i]].val);
+ }
+ updateChocie('database');
+ }
+}
+
+/*
+* input: arr (targeted array); obj (targeted value)
+* function: check whether targeted array contains targeted value or not
+* output: return true, if array contains targeted value, otherwise return false
+*/
+function Contains(arr,obj) {
+ var i = arr.length;
+ while (i--) {
+ if (arr[i] == obj) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+* input: selectObj (designated select menu, such as species, cross, etc... )
+* function: clear designated select menu's option
+* output: null
+*/
+function removeOptions(selectObj) {
+ if (typeof selectObj != 'object'){
+ selectObj = document.getElementById(selectObj);
+ }
+ var len = selectObj.options.length;
+ for (var i=0; i < len; i++) {
+ // clear current selection
+ selectObj.options[0] = null;
+ }
+}
+
+/*
+* input: selectObjId (designated select menu, such as species, cross, etc... )
+* Value: target value
+* function: retrieve Index info of target value in designated array
+* output: index info
+*/
+function getIndexByValue(selectObjId,val)
+{
+ if(selectObjId=='species')
+ {
+ for(var i=1;i<sArr.length;i++){
+ if(sArr[i].val==val)
+ return i;
+ }
+ }else if(selectObjId=='cross')
+ {
+ for(var i=1;i<gArr.length;i++)
+ if(gArr[i].val==val)
+ return i;
+ }else if(selectObjId=='tissue')
+ {
+ for(var i=1;i<tArr.length;i++)
+ if(tArr[i].val==val)
+ return i;
+ }
+ else return;
+}
+
+/*
+* input: objId (designated select menu, such as species, cross, etc... )
+* val(targeted value)
+* function: setting option's selected status for designated select menu based on target value, also update the following select menu in the main search page
+* output: return true if selected status has been set, otherwise return false.
+*/
+function setChoice(objId,val)
+{
+ var Obj = document.getElementById(objId);
+ var idx=-1;
+
+ for(i=0;i<Obj.options.length;i++){
+ if(Obj.options[i].value==val){
+ idx=i;
+ break;
+ }
+ }
+
+ if(idx>=0){
+ //setting option's selected status
+ Obj.options[idx].selected=true;
+ //update the following select menu
+ fillOptions(objId);
+ }else{
+ Obj.options[0].selected=true;
+ fillOptions(objId);
+ }
+}
+
+// setting option's selected status based on default setting or cookie setting for Species, Group, Type and Database select menu in the main search page http://www.genenetwork.org/
+function updateChocie(selectObjId){
+
+ if (selectObjId =='species')
+ {
+ defaultSpecies= getDefaultValue('species');
+ //setting option's selected status
+ setChoice('species',defaultSpecies);
+ }else if (selectObjId =='cross')
+ {
+ defaultSet= getDefaultValue('cross');
+ //setting option's selected status
+ setChoice('cross',defaultSet);
+ }else if (selectObjId =='tissue')
+ {
+ defaultType= getDefaultValue('tissue');
+ //setting option's selected status
+ setChoice('tissue',defaultType);
+ }else if (selectObjId =='database')
+ {
+ defaultDB= getDefaultValue('database');
+ //setting option's selected status
+ setChoice('database',defaultDB);
+ }
+}
+
+//get default value;if cookie exists, then use cookie value, otherwise use default value
+function getDefaultValue(selectObjId){
+ //define default value
+ var defaultSpecies = 'mouse'
+ var defaultSet = 'BXD'
+ var defaultType = 'Hippocampus'
+ var defaultDB = 'HC_M2_0606_P'
+
+ if (selectObjId =='species')
+ {
+ //if cookie exists, then use cookie value, otherwise use default value
+ var cookieSpecies = getCookie('defaultSpecies');
+ if(cookieSpecies)
+ {
+ defaultSpecies= cookieSpecies;
+ }
+ return defaultSpecies;
+ }else if (selectObjId =='cross'){
+ var cookieSet = getCookie('defaultSet');
+ if(cookieSet){
+ defaultSet= cookieSet;
+ }
+ return defaultSet;
+ }else if (selectObjId =='tissue'){
+ var cookieType = getCookie('defaultType');
+ if(cookieType){
+ defaultType= cookieType;
+ }
+ return defaultType;
+ }else if (selectObjId =='database')
+ {
+ var cookieDB = getCookie('defaultDB');
+ if(cookieDB){
+ defaultDB= cookieDB;
+ }
+ return defaultDB;
+ }
+
+}
+
+//setting default value into cookies for the dropdown menus: Species,Group, Type, and Database
+function setDefault(thisform){
+
+ setCookie('cookieTest', 'cookieTest', 1);
+ var cookieTest = getCookie('cookieTest');
+ delCookie('cookieTest');
+ if (cookieTest){
+ var defaultSpecies = thisform.species.value;
+ setCookie('defaultSpecies', defaultSpecies, 10);
+ var defaultSet = thisform.cross.value;
+ setCookie('defaultSet', defaultSet, 10);
+ var defaultType = thisform.tissue.value;
+ setCookie('defaultType', defaultType, 10);
+ var defaultDB = thisform.database.value;
+ setCookie('defaultDB', defaultDB, 10);
+ updateChocie('species');
+ updateChocie('cross');
+ updateChocie('tissue');
+ updateChocie('database');
+ alert("The current settings are now your default");
+ }
+ else{
+ alert("You need to enable Cookies in your browser.");
+ }
+}
+
+'''
+# write all strings' info into selectDatasetMenu.js file
+fileHandler.write(outputStr)
+fileHandler.close()
diff --git a/web/webqtl/maintainance/updateMenuJS.py b/web/webqtl/maintainance/updateMenuJS.py
new file mode 100755
index 00000000..8b6e25d3
--- /dev/null
+++ b/web/webqtl/maintainance/updateMenuJS.py
@@ -0,0 +1,127 @@
+# 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
+#
+# created by Lei Yan 02/08/2011
+import sys, os
+import MySQLdb
+import string
+
+
+
+abs_path = os.path.abspath(os.path.dirname(__file__))
+path1 = abs_path + "/.."
+path2 = abs_path + "/../../javascript"
+sys.path.insert(0, path1)
+
+#must import GN python files after add path
+from base import webqtlConfig
+
+# build MySql database connection
+con = MySQLdb.Connect(db=webqtlConfig.DB_NAME, host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER, passwd=webqtlConfig.DB_PASSWD)
+cursor = con.cursor()
+cursor.execute("SELECT id,menuname FROM Species ORDER BY OrderId")
+results = list(cursor.fetchall())
+collectionsText = ""
+for result in results:
+ specieid = result[0]
+ speciename = result[1]
+ collectionsText += ("['" + speciename + "', ")
+ collectionsText += ("null, ")
+ collectionsText += ("null, ")
+ collectionsText += "\n"
+ cursor.execute("select name from InbredSet where speciesid=" + str(specieid))
+ results2 = list(cursor.fetchall())
+ for result2 in results2:
+ inbredsetName = result2[0]
+ if not cmp(inbredsetName, "BXD300"):
+ continue
+ collectionsText += "\t"
+ collectionsText += ("['" + inbredsetName + "', ")
+ collectionsText += ("'/webqtl/main.py?FormID=dispSelection&RISet=" + inbredsetName + "'], ")
+ collectionsText += "\n"
+ collectionsText += "],"
+ collectionsText += "\n"
+collectionsText = collectionsText.strip()
+
+jstext = """/*
+ --- menu items ---
+ note that this structure has changed its format since previous version.
+ additional third parameter is added for item scope settings.
+ Now this structure is compatible with Tigra Menu GOLD.
+ Format description can be found in product documentation.
+*/
+var MENU_ITEMS = [
+ ['menu_grp1', null, null,
+ ['GeneNetwork Intro', '/home.html'],
+ ['Enter Trait Data', '/webqtl/main.py?FormID=submitSingleTrait'],
+ ['Batch Submission', '/webqtl/main.py?FormID=batSubmit'],
+ ],
+ ['menu_grp2', null, null,
+ ['Search Databases', '/'],
+ ['Tissue Correlation', '/webqtl/main.py?FormID=tissueCorrelation'],
+ ['SNP Browser', '/webqtl/main.py?FormID=snpBrowser'],
+ ['Gene Wiki', '/webqtl/main.py?FormID=geneWiki'],
+ ['Interval Analyst', '/webqtl/main.py?FormID=intervalAnalyst'],
+ ['QTLminer', '/webqtl/main.py?FormID=qtlminer'],
+ ['GenomeGraph', '/dbResults.html'],
+ ['Trait Collections',null,null,
+%s
+ ],
+ ['Scriptable Interface', '/CGIDoc.html'],
+ /* ['Simple Query Interface', '/GUI.html'], */
+ ['Database Information',null,null,
+ ['Database Schema', '/webqtl/main.py?FormID=schemaShowPage'],
+ ],
+ ['Data Sharing', '/webqtl/main.py?FormID=sharing'],
+ ['Microarray Annotations', '/webqtl/main.py?FormID=annotation'],
+ ],
+ ['menu_grp3', null, null,
+ ['Movies','http://www.genenetwork.org/tutorial/movies'],
+ ['Tutorials', null, null,
+ ['GN Barley Tutorial','/tutorial/pdf/GN_Barley_Tutorial.pdf'],
+ ['GN Powerpoint', '/tutorial/ppt/index.html']],
+ ['HTML Tour','/tutorial/WebQTLTour/'],
+ ['FAQ','/faq.html'],
+ ['Glossary of Terms','/glossary.html'],
+ ['GN MediaWiki','http://wiki.genenetwork.org/'],
+ ],
+ ['menu_grp4', '/whats_new.html'
+ ],
+ ['menu_grp5', '/reference.html'
+ ],
+ ['menu_grp6', null, null,
+ ['Conditions and Limitation', '/conditionsofUse.html'],
+ ['Data Sharing Policy', '/dataSharing.html'],
+ ['Status and Contacts', '/statusandContact.html'],
+ ['Privacy Policy', '/privacy.html'],
+ ],
+ ['menu_grp8', '/links.html'
+ ],
+];
+"""
+
+# create menu_items.js file
+fileHandler = open(path2 + '/menu_items.js', 'w')
+fileHandler.write(jstext % collectionsText)
+fileHandler.close()
diff --git a/web/webqtl/management/GenoUpdate.py b/web/webqtl/management/GenoUpdate.py
new file mode 100755
index 00000000..6ee87dec
--- /dev/null
+++ b/web/webqtl/management/GenoUpdate.py
@@ -0,0 +1,1279 @@
+"""
+Maintainnce module. Update Genotype data, user can update the Marker
+one by one through web interface, or batch update one Population
+through submit genotype file
+"""
+
+import string
+import os
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+from dbFunction import webqtlDatabaseFunction
+
+
+
+"""
+The Fields of Geno, GenoXRef table that be shown to user for updating
+"""
+MarkerSpeciesInfoField = ['Name', 'Chr', 'Mb', 'Sequence', 'Source']
+MarkerGroupInfoField = ['cM', 'Used_for_mapping']
+MarkerInfoField = MarkerSpeciesInfoField + MarkerGroupInfoField
+markerName_Feild_Separator = '_and_'
+
+
+# retrieve all of the Inbred Set names and group them by Species
+def retrieveSpeciesInbredSetGroup(cursor):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ rtype: dictionary
+ return: dictionary, the key are the name of Species, the value are
+ the InbredSet Names that related with the Species
+ """
+
+ SpeciesInbredSet={}
+ cursor.execute("""
+ SELECT
+ Species.Id, Species.Name
+ FROM
+ Species, InbredSet
+ WHERE
+ Species.Id=InbredSet.SpeciesId AND
+ MappingMethodId = 1
+ GROUP BY
+ Species.Id
+ """)
+ species=cursor.fetchall()
+
+ for item in species:
+ SpeciesId, SpeciesName = item
+ cursor.execute("SELECT distinct(InbredSet.Name) FROM InbredSet, GenoFreeze, GenoXRef WHERE SpeciesId=%d and GenoFreeze.InbredSetId = InbredSet.Id and GenoXRef.GenoFreezeId = GenoFreeze.Id and GenoXRef.Used_for_mapping='Y' " % SpeciesId)
+ InbredSetNames=cursor.fetchall()
+
+ InbredSetNameList=[]
+ for InbredSetName in InbredSetNames:
+ if InbredSetName[0]=='BXD300':
+ continue
+ InbredSetNameList.append(InbredSetName[0])
+ SpeciesInbredSet[SpeciesName]=InbredSetNameList
+
+ return SpeciesInbredSet
+
+
+#XZ: This function will be called in many places.
+# Each caller might organize the result in different way.
+# So the raw database results are returned.
+def retrieveGenoCode(cursor, InbredSetName):
+
+ cursor.execute("""
+ SELECT
+ AlleleType, AlleleSymbol, DatabaseValue
+ FROM
+ GenoCode, InbredSet
+ WHERE
+ InbredSet.Name = '%s' AND
+ InbredSetId = InbredSet.Id
+ """ % InbredSetName )
+ results = cursor.fetchall()
+
+ GenoCode = []
+
+ for one_result in results:
+ GenoCode.append(one_result)
+
+ return GenoCode
+
+
+def retrieveGeneticTypeOfInbredSet(cursor, InbredSetName):
+
+ GeneticType = ''
+
+ cursor.execute("""
+ SELECT
+ GeneticType
+ FROM
+ InbredSet
+ WHERE
+ InbredSet.Name=%s
+ """, InbredSetName)
+ result=cursor.fetchone()
+
+ if result:
+ GeneticType = result[0]
+
+ return GeneticType
+
+
+
+
+#XZ: For one group, retrieve the list of all strains that are in StrainXRef and used for mapping
+def retrieveStrainUsedForMapping(cursor, GroupName):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type GroupName: string
+ @param GroupName: In MySQL table, it's called Inbred Set name, in GeneNetwork's Homepage, it's called group
+
+ @rtype: list
+ @return: The Strain's names that related with the Inbred Set
+ """
+
+ cursor.execute("""
+ SELECT
+ Strain.Name
+ FROM
+ Strain, StrainXRef, InbredSet
+ WHERE
+ InbredSet.Name = '%s' AND
+ StrainXRef.InbredSetId=InbredSet.Id AND
+ StrainXRef.StrainId = Strain.Id AND
+ StrainXRef.Used_for_mapping = 'Y'
+ ORDER BY
+ StrainXRef.OrderId
+ """ % GroupName)
+ results = cursor.fetchall()
+
+ StrainList=[]
+ for item in results:
+ StrainList.append(item[0])
+
+ return StrainList
+
+
+#XZ: For one group, retrieve the dictionary of all strain id, name pairs that are in StrainXRef and used for mapping
+def retrieveStrainNameIdUsedForMapping(cursor, GroupName):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type GroupName: string
+ @param GroupName: In MySQL table, it's called Inbred Set name, in GeneNetwork's Homepage, it's called group
+
+ @rtype: dictionary
+ @return: dictionary, the key is Strain's name, the value is Strain's Id
+ """
+
+ StrainNameId = {}
+
+ cursor.execute("""
+ SELECT
+ Strain.Name, Strain.Id
+ FROM
+ Strain, StrainXRef, InbredSet
+ WHERE
+ InbredSet.Name = '%s' AND
+ StrainXRef.InbredSetId=InbredSet.Id AND
+ StrainXRef.StrainId = Strain.Id AND
+ StrainXRef.Used_for_mapping = 'Y'
+ ORDER BY
+ StrainXRef.OrderId
+ """ % GroupName)
+ results = cursor.fetchall()
+
+ for item in results:
+ StrainNameId[item[0]] = item[1]
+
+ return StrainNameId
+
+
+
+# retrieve the strain's id by name, the Strain should bind with Inbred Set
+#if the strain's name cann't be found, the id will be set to 'None'
+def retrieveStrainIds(cursor, StrainList, InbredSetName):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type StrainList: list
+ @param StrainList: the list of Strains' Name
+ @type InbredSetName: string
+
+ @rtype: dictionary
+ @return: dictionary, the key is Strain's name, the value is Strain's Id
+ """
+
+ StrainIds={}
+ for Strain in StrainList:
+ cursor.execute("""
+ SELECT
+ Strain.Id
+ FROM
+ Strain,StrainXRef,InbredSet
+ WHERE
+ Strain.Id=StrainXRef.StrainId AND
+ StrainXRef.InbredSetId=InbredSet.Id AND
+ Strain.Name=%s AND
+ InbredSet.Name=%s
+ """, (Strain, InbredSetName))
+ result=cursor.fetchone()
+ if result:
+ StrainIds[Strain]=result[0]
+ else:
+ StrainIds[Strain]=None
+
+ return StrainIds
+
+
+
+# retrieve the GenoFreezeId
+def retrieveGenoFreezeId(cursor, InbredSetName):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type InbredSetName: string
+
+ @rtype: int
+ @return: the GenoFreezeId related with the Inbred Set's name
+ """
+
+ cursor.execute("""
+ SELECT
+ GenoFreeze.Id
+ FROM
+ InbredSet, GenoFreeze
+ WHERE
+ GenoFreeze.InbredSetId=InbredSet.Id AND
+ InbredSet.Name=%s
+ """, InbredSetName)
+ result=cursor.fetchone()
+
+ if result:
+ return result[0]
+ else:
+ return None
+
+
+# retrieve the DataId
+def retrieveDataId(cursor, GenoId, InbredSetName):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type GenoId: int
+ @type InbredSetName: int
+
+ @rtype: int
+ @return: the DataId relate with the Geno(Marker) and the Inbred Set
+ """
+
+ cursor.execute("""
+ SELECT
+ GenoXRef.DataId
+ FROM
+ GenoXRef, GenoFreeze, InbredSet
+ WHERE
+ GenoXRef.GenoFreezeId=GenoFreeze.Id AND
+ GenoFreeze.InbredSetId=InbredSet.Id AND
+ GenoXRef.GenoId=%s AND
+ InbredSet.Name=%s
+ """, (GenoId, InbredSetName))
+ result=cursor.fetchone()
+
+ if result:
+ return result[0]
+ else:
+ return None
+
+
+# retrieve the max Id from GenoData table
+def retrieveMaxGenoDataId(cursor):
+ """
+ @type cursor: MySQLdb.connect.cursor
+
+ @rtype: int
+ @return: the maximal Id of the Data table
+ """
+
+ cursor.execute('SELECT max(Id) FROM GenoData')
+ results = cursor.fetchone()
+
+ return results[0]
+
+
+# retrieve the max Id from Geno table
+def retrieveMaxGenoId(cursor):
+ """
+ @type cursor: MySQLdb.connect.cursor
+
+ @rtype: int
+ @return: the maximal Id of the Geno table
+ """
+
+ cursor.execute('SELECT max(Id) FROM Geno')
+ results = cursor.fetchone()
+
+ return results[0]
+
+
+# retrieve the strain names related with a data.Id
+# Note that for one group, even if one strain is labelled as Used_for_mapping in StrainXRef table,
+# if the allele value for this strain is unknown, there is no record for this strain along with this group in GenoData table.
+# So the list of strains returned by this function <= list of strains returned by function retrieveStrainUsedForMapping.
+def retrieveDataStrains(cursor, DataId):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type DataId: int
+
+ @rtype: list
+ @return: the names list of the Strains that related with the DataId
+ """
+
+ cursor.execute("SELECT Strain.Name FROM Strain, GenoData WHERE GenoData.StrainId=Strain.Id AND GenoData.Id=%s", DataId)
+ results=cursor.fetchall()
+
+ Strains=[]
+ for item in results:
+ Strains.append(item[0])
+
+ return Strains
+
+
+
+def retrieveMarkerNameForGroupByRange(cursor, InbredSetName, Chr, MbStart, MbEnd):
+
+ MarkerName = []
+
+ SpeciesId = webqtlDatabaseFunction.retrieveSpeciesId(cursor, InbredSetName)
+
+ GenoFreezeId = retrieveGenoFreezeId(cursor, InbredSetName)
+
+ MbStartClause = ''
+ MbEndClause = ''
+
+ try:
+ MbStartClause = 'and Mb >= %s ' % float(MbStart)
+ except:
+ pass
+
+ try:
+ MbEndClause = 'and Mb <= %s' % float(MbEnd)
+ except:
+ pass
+
+
+ cmd = "SELECT Geno.Name FROM Geno, GenoXRef WHERE Geno.SpeciesId=%s and Chr='%s' " % (SpeciesId, Chr) + MbStartClause + MbEndClause + " and GenoXRef.GenoFreezeId=%s and GenoXRef.GenoId=Geno.Id and GenoXRef.Used_for_mapping='Y' order by Mb" % (GenoFreezeId)
+
+ cursor.execute(cmd)
+
+ results = cursor.fetchall()
+ for one_result in results:
+ MarkerName.append( one_result[0] )
+
+ return MarkerName
+
+
+
+# retrive the Marker's infomation from Geno and GenoXRef table,
+# the information includes the Id of the marker matchs and all of the MarkerInfoField that defined upper
+def retrieveMarkerInfoForGroup(cursor, MarkerName, InbredSetName):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type MarkerName: string
+
+ @rtype: list
+ @return: the Marker's Id, Name, Chr, cM, Mb, Sequence, Source
+ """
+
+
+ SpeciesId = webqtlDatabaseFunction.retrieveSpeciesId(cursor, InbredSetName)
+
+ GenoFreezeId = retrieveGenoFreezeId(cursor, InbredSetName)
+
+ cmd = ','.join( MarkerInfoField )
+ cmd = "SELECT Geno.Id," + cmd + " FROM Geno, GenoXRef WHERE Geno.SpeciesId=%s and Geno.Name='%s' and GenoXRef.GenoFreezeId=%s and GenoXRef.GenoId=Geno.Id" % (SpeciesId, MarkerName, GenoFreezeId)
+ cursor.execute(cmd)
+ result = cursor.fetchone()
+
+ if result:
+ return result
+ else:
+ return None
+
+
+def retrieveMarkerPositionForSpecies(cursor, GenoId):
+
+ Chr = ''
+ Mb = ''
+
+ cursor.execute( "select Chr, Mb from Geno where Id=%s" % GenoId )
+ result = cursor.fetchone()
+
+ Chr = result[0]
+ Mb = result[1]
+
+ return Chr, Mb
+
+
+def checkIfMarkerInSpecies (cursor, MarkerName, InbredSetName):
+
+ cmd = "SELECT Geno.Id FROM Geno, InbredSet, Species WHERE Geno.SpeciesId=Species.Id AND Geno.Name='%s' and InbredSet.Name = '%s' and InbredSet.SpeciesId = Species.Id" % (MarkerName, InbredSetName)
+ cursor.execute(cmd)
+ result = cursor.fetchone()
+
+ if result:
+ return result
+ else:
+ return None
+
+
+
+
+# retrive the Marker's Used_for_mapping status from MySQL
+# for one marker, if we want it be contains in the special genotype file, we can set its value in Used_for_mapping column to 'Y' in the GenoXRef table.
+# In GenoXRef table, the default value of column Used_for_mapping is 'N'.
+# GenoXRef table is the relationship of the Marker and the allele value that this marker in special genotype
+def mappingForThisGroup(cursor, GenoFreezeId, GenoId):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type MarkerName: string
+ @type InbredSetName: string
+
+ @rtype: boolean
+ @return: the status that if the marker's exprssion value in special Inbred Set will be hide(not shown in genotype file)
+ """
+
+ cursor.execute("""
+ SELECT
+ Used_for_mapping
+ FROM
+ GenoXRef
+ WHERE
+ GenoFreezeId = %s AND
+ GenoId = %s
+ """, (GenoFreezeId, GenoId))
+ result = cursor.fetchone()
+
+ Used_for_mapping = False
+ if result:
+ if result[0] == 'Y':
+ Used_for_mapping = True
+
+ return Used_for_mapping
+
+
+# Retrieve the allele values of a Marker in specific genotype
+#
+# 1. Retrieve strain name and allele value from GenoData table
+# 2. Put the result into dictionary, the key is strain name. The value is allele (-1, 0, 1).
+#
+# Note even one strain is used for mapping for one group in GenoXRef table. When its genotype is unknown,
+# it has no record in GenoData table (e.g., BXD102 strain for marker rs6376963).
+# In this case, the dictionary key doesn't include this strain.
+def retrieveAllele (cursor, GenoFreezeId, GenoId):
+ """
+ @type cursor: MySQLdb.connect.cursor
+ @type MarkerName: string
+ @type InbredSetName: string
+
+ @rtype: dictionary
+ @return: dictionary, the keys are strain names, the values are alleles
+ that the Marker in specials Inbred Set
+ """
+
+ Alleles = {}
+
+ #retrieve the strains' name and their allele values
+ cursor.execute("""
+ SELECT
+ Strain.Name, GenoData.Value
+ FROM
+ Strain, GenoData, GenoXRef
+ WHERE
+ GenoXRef.GenoFreezeId=%s AND
+ GenoXRef.GenoId=%s AND
+ GenoXRef.DataId=GenoData.Id AND
+ GenoData.StrainId=Strain.Id
+ """, (GenoFreezeId, GenoId))
+ results = cursor.fetchall()
+
+ # set the allele value of the strain that appears in Data to the value from Data
+ for item in results:
+ Alleles[item[0]]=item[1]
+
+ return Alleles
+
+
+
+def retrieveGroupNeedExported (cursor, GenoId):
+
+ Groups = []
+
+ cursor.execute("""
+ SELECT
+ InbredSet.Name
+ FROM
+ InbredSet, GenoFreeze, GenoXRef
+ WHERE
+ Used_for_mapping = 'Y' AND
+ GenoXRef.GenoId = %s AND
+ GenoXRef.GenoFreezeId = GenoFreeze.Id AND
+ GenoFreeze.InbredSetId = InbredSet.Id
+ """, (GenoId) )
+ results = cursor.fetchall()
+
+ if results:
+ for one_result in results:
+ Groups.append( one_result[0] )
+
+ return Groups
+
+
+def get_chr_num (cursor, Chr='', SpeciesId=0):
+
+ chr_num = 99
+
+ cmd = "SELECT OrderId FROM Chr_Length WHERE Name='%s' and SpeciesId=%s " % (Chr, SpeciesId)
+
+ cursor.execute(cmd)
+ result = cursor.fetchone()
+
+ if result:
+ chr_num = result[0]
+
+ return chr_num
+
+
+
+def addGeno(cursor, GenoId, InbredSetName, MarkerWebID, fd):
+
+ SpeciesId = webqtlDatabaseFunction.retrieveSpeciesId(cursor, InbredSetName)
+
+ Name = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Name' )
+ Chr = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Chr' )
+ Mb = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Mb' )
+ Sequence = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Sequence' )
+ Source = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Source' )
+
+ chr_num = get_chr_num (cursor, Chr, SpeciesId)
+
+ cmd = "INSERT INTO Geno (Id, SpeciesId, Name, Marker_Name, Chr, Mb, Sequence, Source, chr_num) VALUES (%s, %s, '%s', '%s', '%s', %s, '%s', '%s', %s )" % (GenoId, SpeciesId, Name, Name, Chr, Mb, Sequence, Source, chr_num)
+ cursor.execute(cmd)
+
+
+
+def updateGeno(cursor, GenoId, InbredSetName, MarkerWebID, fd):
+
+ SpeciesId = webqtlDatabaseFunction.retrieveSpeciesId(cursor, InbredSetName)
+
+ Chr = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Chr' )
+ cmd = "UPDATE Geno SET Chr='%s' WHERE Id=%s" % (Chr, GenoId)
+ cursor.execute(cmd)
+
+ chr_num = get_chr_num (cursor, Chr, SpeciesId)
+ cmd = "UPDATE Geno SET chr_num=%s WHERE Id=%s" % (chr_num, GenoId)
+ cursor.execute(cmd)
+
+ Mb = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Mb' )
+ cmd = "UPDATE Geno SET Mb=%s WHERE Id=%s" % (Mb, GenoId)
+ cursor.execute(cmd)
+
+ Sequence = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Sequence' )
+ cmd = "UPDATE Geno SET Sequence='%s' WHERE Id=%s" % (Sequence, GenoId)
+ cursor.execute(cmd)
+
+ Source = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Source' )
+ cmd = "UPDATE Geno SET Source='%s' WHERE Id=%s" % (Source, GenoId)
+ cursor.execute(cmd)
+
+
+def updateGenoXRef(cursor, GenoFreezeId, GenoId, MarkerWebID, fd):
+
+ cM = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'cM' )
+ cmd = "UPDATE GenoXRef SET cM=%s WHERE GenoFreezeId=%s AND GenoId=%s" % (cM, GenoFreezeId, GenoId)
+ cursor.execute(cmd)
+
+ Used_for_mapping = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Used_for_mapping')
+
+ if Used_for_mapping == 'on':
+ cmd = "UPDATE GenoXRef SET Used_for_mapping='Y' WHERE GenoFreezeId=%s AND GenoId=%s" % (GenoFreezeId, GenoId)
+ else:
+ cmd = "UPDATE GenoXRef SET Used_for_mapping='N' WHERE GenoFreezeId=%s AND GenoId=%s" % (GenoFreezeId, GenoId)
+ cursor.execute(cmd)
+
+
+
+def addGenoXRef(cursor, GenoFreezeId, GenoId, DataId, MarkerWebID, fd):
+
+ cM = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'cM')
+
+ Used_for_mapping = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Used_for_mapping')
+
+ Used_for_mapping_db_value = 'N'
+ if Used_for_mapping == 'on':
+ Used_for_mapping_db_value = 'Y'
+
+ cmd = "INSERT INTO GenoXRef (GenoFreezeId, GenoId, DataId, cM, Used_for_mapping) VALUES (%s, %s, %s, %s, '%s')" % (GenoFreezeId, GenoId, DataId, cM, Used_for_mapping_db_value)
+
+ cursor.execute(cmd)
+
+
+
+def insertGenoData(cursor, InbredSetName, DataId, MarkerWebID, fd):
+
+ StrainList = retrieveStrainUsedForMapping (cursor, InbredSetName)
+ StrainIds = retrieveStrainIds(cursor, StrainList, InbredSetName)
+
+ for Strain in StrainList:
+ if fd.formdata.has_key( MarkerWebID + markerName_Feild_Separator + Strain ):
+ value = fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + Strain )
+
+ # XZ: The legitimate values are hard coded. Should be dynamical (from database).
+ try:
+ int_value = int(float(value))
+
+ if int_value in (0, 1, -1):
+ cmd = "INSERT INTO GenoData VALUES(%d,%d,%s)"%(DataId, StrainIds[Strain], int_value)
+ cursor.execute(cmd)
+ except:
+ pass
+
+
+#XZ: This function is to compare the input position (Chr, Mb) with position in database.
+# It should be executed before update database record.
+def getAllGroupsNeedExported(cursor, GroupNeedExport=[], GenoId=0, Chr='', Mb=''):
+
+ db_Chr, db_Mb = retrieveMarkerPositionForSpecies(cursor, GenoId)
+
+ if str(Chr) == str(db_Chr) and str(Mb) == str(db_Mb):
+ pass
+ else:
+ temp = retrieveGroupNeedExported (cursor, GenoId)
+ for one_group in temp:
+ try:
+ GroupNeedExport.index(one_group)
+ except:
+ GroupNeedExport.append(one_group)
+
+ return GroupNeedExport
+
+
+
+
+class GenoUpdate(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ # get mysql connection, if not, show error
+ if not self.openMysql():
+ heading = "Geno Updating"
+ detail = ["Can't connect to MySQL server"]
+ self.error(heading=heading,detail=detail)
+ return
+
+
+ self.dict['title'] = 'Geno Updating'
+
+ # status is the switch, direct what's the next step
+ try:
+ status = fd.formdata.getvalue('status')
+ except:
+ status = ''
+
+ if fd.formdata.getvalue('submit')=='Clear':
+ status=''
+
+ if not status: # show
+ self.dict['body']=self.showSelectionPage()
+ elif status=='search' or status == 'addNewMarker':
+ InbredSetName = fd.formdata.getvalue('InbredSetName')
+ Chr = fd.formdata.getvalue('Chr')
+
+ if not InbredSetName:
+ self.dict['body']= "Please select the population."
+ return
+ elif not Chr:
+ self.dict['body']= "Please input Chr."
+ return
+ else:
+ self.dict['body']=self.showAllMarkers (InbredSetName, Chr, fd)
+
+ elif status == 'editMarkerTable':
+ self.dict['body'] = self.editMarkerTable(fd)
+
+ elif status == 'checkMarkerHasBeenInGroup': # check if there is anything changed.
+ InbredSetName = fd.formdata.getvalue('InbredSetName')
+ Marker = fd.formdata.getvalue('Name')
+ self.dict['body'] = self.checkMarkerHasBeenInGroup (InbredSetName, Marker, fd)
+
+ elif status=='changeMarker': #insert new marker
+ InbredSetName = fd.formdata.getvalue('InbredSetName')
+ self.dict['body']=self.changeMarker(InbredSetName, fd)
+
+ else: #this part is used to test, the proceduce won't come here in normal cycle
+ HTTable = HT.TableLite(border=0, cellspacing=1, cellpadding=1,align="center")
+ for key in fd.formdata.keys():
+ HTTable.append(HT.TR(HT.TD(key), HT.TD(':'), HT.TD(fd.formdata.getvalue(key))))
+ self.dict['body'] = HTTable
+
+
+
+
+ # this is the first page, user upload their genotype file here, or input
+ # which marker they want to update
+ def showSelectionPage(self):
+ """
+ The first page, in this page, user can upload a genotype file for batch updating,
+ or enter a Marker for one by one updating
+
+ @rtype: string
+ @return: HTML
+ """
+
+ # get the InbredSet Name list
+ SpeciesInbredSet = retrieveSpeciesInbredSetGroup(self.cursor)
+
+ # generate homepage
+
+ HTTableLite_Population = HT.TableLite(border=0, width="100%")
+
+ HTTD_InbredSet = HT.TD(width="30%")
+
+ HTSelect_InbredSetNames = HT.Select(name='InbredSetName')
+ HTSelect_InbredSetNames.append("")
+ for SpeciesName in SpeciesInbredSet.keys():
+ HT_OptGroup_Species=HT.Optgroup()
+ HT_OptGroup_Species.label=SpeciesName
+ for InbredSetName in SpeciesInbredSet[SpeciesName]:
+ HT_OptGroup_Species.append(InbredSetName)
+ HTSelect_InbredSetNames.append(HT_OptGroup_Species)
+
+ HTTD_InbredSet.append( HT.Font(HT.Strong('Group (required) '), color="red") )
+ HTTD_InbredSet.append(HTSelect_InbredSetNames)
+
+ HTTableLite_Population.append(HT.TR(HTTD_InbredSet))
+
+ HTTableLite_Marker = HT.TableLite(border=0, width="100%")
+ HTTD_Chr = HT.TD()
+ HTTD_Chr.append( HT.Font(HT.Strong('Chr (required) '), color="red") )
+ HTTD_Chr.append(HT.Input(name='Chr', size=3))
+ HTTD_Mb = HT.TD()
+ HTTD_Mb.append(HT.Font(HT.Strong('Mb')), ' from ')
+ HTTD_Mb.append(HT.Input(name='MbStart', size=10))
+ HTTD_Mb.append(' to ')
+ HTTD_Mb.append(HT.Input(name='MbEnd', size=10))
+ HTTableLite_Marker.append(HT.TR(HTTD_Chr), HT.TR(), HT.TR(HTTD_Mb) )
+
+
+
+ HTTableLite_Search = HT.TableLite(border=1, width="100%")
+ HTTableLite_Search.append(
+ HT.TR(HT.TD(HTTableLite_Population, height="100")),
+ HT.TR(HT.TD("Enter Chr and Mb range", HT.BR(), HT.BR(),
+ HTTableLite_Marker,
+ height="100"))
+ )
+
+
+ HTInput_Submit = HT.Input(type='submit', name='submit', value='Submit',Class="button")
+ HTInput_Clear = HT.Input(type='submit', name='submit', value='Clear', Class="button")
+ HTInput_FormId = HT.Input(type='hidden', name='FormID', value='updGeno')
+ HTInput_Status = HT.Input(type='hidden', name='status', value='search')
+
+ HTForm_Search = HT.Form(cgi=os.path.join(webqtlConfig.CGIDIR, 'main.py'), \
+ enctype= 'multipart/form-data', submit='')
+ HTForm_Search.append(HTTableLite_Search)
+ HTForm_Search.append(HTInput_Submit)
+ HTForm_Search.append(HTInput_Clear)
+
+ HTForm_Search.append(HTInput_FormId)
+ HTForm_Search.append(HTInput_Status)
+
+ HTTableLite_Content = HT.TableLite(border=1, width="100%")
+ HTTableLite_Content.append(HT.TR(HT.TD(HTForm_Search, width="50%"), \
+ HT.TD(HT.Font(HT.Strong("Instructions:"), HT.BR(),HT.BR(), "The \"from\" and \"to\" inputs for Mb range are optional.", HT.BR(),HT.BR(), "If only the \"from\" input is provided, the result will be all markers from the input position to the end of chromosome.", HT.BR(),HT.BR(), "If only the \"to\" input is provided, the result will be all markers from the beginning of the chromosome to the input position.", HT.BR(),HT.BR(), "If no input is provided for Mb range, the result will be all markers on the chromosome."), valign='top', width="50%") \
+ ))
+
+ return HTTableLite_Content
+
+
+
+
+ def searchMappingMarkerInDB (self, InbredSetName="", Chr='', MbStart='', MbEnd=''):
+ """
+ Show Marker's information for updating or inserting
+
+ @type InbredSetName: string
+ @type MarkerName: string
+
+ @rtype: string
+ @return: The HTML form that contains the Marker's information
+ """
+
+
+ MarkerInfoDic = {}
+
+ MarkerNamesByRange = retrieveMarkerNameForGroupByRange(self.cursor, InbredSetName, Chr, MbStart, MbEnd)
+
+ for one_MarkerName in MarkerNamesByRange:
+ one_MarkerGroupInfo = retrieveMarkerInfoForGroup (self.cursor, one_MarkerName, InbredSetName)
+ MarkerInfoDic[ one_MarkerName ] = one_MarkerGroupInfo
+
+ return MarkerNamesByRange, MarkerInfoDic
+
+
+
+ def showAllMarkers( self, InbredSetName, Chr, fd ):
+
+ MbStart = fd.formdata.getvalue('MbStart')
+ MbEnd = fd.formdata.getvalue('MbEnd')
+
+ inputStatus = fd.formdata.getvalue('status')
+
+ newMarkerNameQuantityDic = {}
+ MarkerNameAdded = []
+
+ MarkerNames, MarkerInfoDic = self.searchMappingMarkerInDB (InbredSetName=InbredSetName, Chr=Chr, MbStart=MbStart, MbEnd=MbEnd)
+
+ MainTable = HT.TableLite(border=1, cellspacing=1, cellpadding=1,align="left")
+
+ if inputStatus == 'search':
+
+
+ InputTable = HT.TableLite(border=1, cellspacing=1, cellpadding=1,align="left")
+
+ InputTable.append( HT.TR( HT.TD( HT.Textarea(name="InputNewMarker", rows=10, cols=20)),
+ HT.TD(HT.Font( "Add one input per line.", HT.BR(), HT.BR(), \
+ "Each input must be in the format of: existing marker name,quantity", HT.BR(), HT.BR(), \
+ "For instance, the input rs6376963, 2 will add two markers after rs6376963", HT.BR(), HT.BR(), \
+ "The input existing marker name must have been shown in the table below.", HT.BR(), HT.BR(), color="red"), \
+ HT.Input(type='submit', name='inputmarker_submit', value='Add new markers', Class="button", onClick= "changeStatusSubmit(this.form, 'addNewMarker');" ) ) ) )
+
+ MainTable.append( HT.TR(HT.TD(InputTable)) )
+ else:
+ InputNewMarkerString = fd.formdata.getvalue('InputNewMarker')
+
+ InputNewMarkerLines = InputNewMarkerString.split('\n')
+ for one_line in InputNewMarkerLines:
+ one_line = one_line.strip()
+ if len(one_line) > 0:
+ one_line_tokens = one_line.split(',')
+ try:
+ first_token = one_line_tokens[0].strip()
+ second_token = one_line_tokens[1].strip()
+ second_token = int( second_token )
+ if first_token in MarkerNames:
+ newMarkerNameQuantityDic[ first_token ] = second_token
+ except:
+ pass
+
+
+ MarkerTable = HT.TableLite(border=1, cellspacing=1, cellpadding=1,align="left")
+
+ HeaderRow = HT.TR()
+
+
+ for one_field in MarkerSpeciesInfoField:
+ HeaderRow.append( HT.TD(one_field) )
+
+ for one_field in MarkerGroupInfoField:
+ HeaderRow.append( HT.TD(one_field) )
+
+ GenoFreezeId = retrieveGenoFreezeId(self.cursor, InbredSetName)
+ StrainList = retrieveStrainUsedForMapping (self.cursor, InbredSetName)
+
+ for one_strain in StrainList:
+ HeaderRow.append( HT.TD(one_strain) )
+
+ MarkerTable.append( HeaderRow )
+
+
+ for one_MarkerName in MarkerNames:
+ one_MarkerGroupInfo = MarkerInfoDic[ one_MarkerName ]
+ oneMarkerRow = self.showOneMarker (InbredSetName=InbredSetName, MarkerName=one_MarkerName, suffix="", MarkerGroupInfo=one_MarkerGroupInfo, StrainList=StrainList, marker_type='existed')
+ MarkerTable.append( oneMarkerRow )
+
+ if newMarkerNameQuantityDic.has_key(one_MarkerName):
+ for i in range(0, newMarkerNameQuantityDic[one_MarkerName]):
+ MarkerNameAdded.append( one_MarkerName + '_add_' + str(i) )
+ oneMarkerRow = self.showOneMarker (InbredSetName=InbredSetName, MarkerName=one_MarkerName, suffix='_add_' + str(i), MarkerGroupInfo=one_MarkerGroupInfo, StrainList=StrainList, marker_type='add')
+ MarkerTable.append( oneMarkerRow )
+
+
+
+ MarkerTable.append( HT.TR(HT.TD( HT.Input(type='submit', name='markertable_submit', value='Edit marker table',Class="button", onClick= "changeStatusSubmit(this.form, 'editMarkerTable');") )) )
+
+ MainTable.append( HT.TR(HT.TD(MarkerTable)) )
+
+
+ HTInput_Submit = HT.Input(type='hidden', name='submit', value='Submit',Class="button")
+ HTInput_FormId = HT.Input(type='hidden', name='FormID', value='updGeno')
+ HTInput_Status = HT.Input(type='hidden', name='status', value='')
+ HTInput_InbredSetName = HT.Input(type='hidden', name='InbredSetName', value=InbredSetName)
+ HTInput_Chr = HT.Input(type='hidden', name='Chr', value=Chr)
+ HTInput_MbStart = HT.Input(type='hidden', name='MbStart', value=MbStart)
+ HTInput_MbEnd = HT.Input(type='hidden', name='MbEnd', value=MbEnd)
+ HTInput_MarkerNamesExisted = HT.Input(type='hidden', name='MarkerNamesExisted', value=','.join(MarkerNames) )
+ HTInput_MarkerNamesAdded = HT.Input(type='hidden', name='MarkerNamesAdded', value=','.join(MarkerNameAdded) )
+
+
+ HTForm_showAllMarkers = HT.Form(cgi=os.path.join(webqtlConfig.CGIDIR, 'main.py'), enctype= 'multipart/form-data', submit=HTInput_Submit)
+
+ HTForm_showAllMarkers.append( MainTable )
+ HTForm_showAllMarkers.append(HTInput_FormId)
+ HTForm_showAllMarkers.append(HTInput_Status)
+ HTForm_showAllMarkers.append(HTInput_InbredSetName)
+ HTForm_showAllMarkers.append(HTInput_Chr)
+ HTForm_showAllMarkers.append(HTInput_MbStart)
+ HTForm_showAllMarkers.append(HTInput_MbEnd)
+ HTForm_showAllMarkers.append(HTInput_MarkerNamesExisted)
+ HTForm_showAllMarkers.append(HTInput_MarkerNamesAdded)
+
+ return HTForm_showAllMarkers
+
+
+
+ def showOneMarker (self, InbredSetName="", MarkerName="", suffix="", MarkerGroupInfo=[], StrainList=[], marker_type=''):
+
+ GenoInfo={}
+
+ #XZ: The first item of MarkerInfo is Geno.Id
+ GenoId = MarkerGroupInfo[0]
+
+ for i in range(1, len(MarkerGroupInfo)):
+ if MarkerGroupInfo[i] != None:
+ GenoInfo[ MarkerInfoField[i-1] ] = str(MarkerGroupInfo[i])
+ else:
+ GenoInfo[ MarkerInfoField[i-1] ] = ''
+
+ if GenoInfo['Used_for_mapping'] == 'Y':
+ GenoInfo['Used_for_mapping'] = True
+ else:
+ GenoInfo['Used_for_mapping'] = False
+
+
+ MarkerRow = HT.TR()
+
+ # Species level info
+ for i in range(0, len(MarkerSpeciesInfoField)):
+ if MarkerSpeciesInfoField[i] == 'Name':
+ if marker_type == 'existed':
+ MarkerRow.append( HT.TD(GenoInfo['Name']) )
+ else:
+ MarkerRow.append(HT.TD(HT.Input(name = MarkerName + suffix + markerName_Feild_Separator + MarkerSpeciesInfoField[i], size=20, maxlength=500, value=MarkerName + suffix )))
+ else:
+ MarkerRow.append(HT.TD(HT.Input(name = MarkerName + suffix + markerName_Feild_Separator + MarkerSpeciesInfoField[i], size=10, maxlength=500, value=GenoInfo[MarkerSpeciesInfoField[i]])))
+
+ # Group level info
+ for i in range(0, len(MarkerGroupInfoField)):
+ if MarkerGroupInfoField[i] != 'Used_for_mapping':
+ MarkerRow.append( HT.TD(HT.Input(name = MarkerName + suffix + markerName_Feild_Separator + MarkerGroupInfoField[i], size=10, value=GenoInfo[MarkerGroupInfoField[i]])))
+ else:
+ MarkerRow.append( HT.TD(HT.Input(type='checkbox', name= MarkerName + suffix + markerName_Feild_Separator + 'Used_for_mapping', checked=GenoInfo['Used_for_mapping'] )))
+
+ # retrive Marker allele values
+ GenoFreezeId = retrieveGenoFreezeId(self.cursor, InbredSetName)
+ Alleles = retrieveAllele (self.cursor, GenoFreezeId, GenoId)
+
+ for i in range(0, len(StrainList)):
+ try:
+ Value = Alleles[StrainList[i]]
+ except:
+ Value = 'X' # 'X' is the symbol for unknown allele
+ MarkerRow.append( HT.TD(HT.Input(name = MarkerName + suffix + markerName_Feild_Separator + StrainList[i], size=3, maxlength=5, value=Value)))
+
+
+ return MarkerRow
+
+
+ def editMarkerTable (self, fd):
+
+ InbredSetName = fd.formdata.getvalue('InbredSetName')
+ Chr = fd.formdata.getvalue('Chr')
+
+ MbStart = fd.formdata.getvalue('MbStart')
+ MbEnd = fd.formdata.getvalue('MbEnd')
+
+ MarkerNamesExistedString = fd.formdata.getvalue('MarkerNamesExisted')
+ MarkerNamesAddedString = fd.formdata.getvalue('MarkerNamesAdded')
+
+ MarkerNamesExisted = []
+ MarkerNamesAdded = []
+
+ MarkerNamesExistedString = MarkerNamesExistedString.strip()
+ MarkerNamesExisted = MarkerNamesExistedString.split(',')
+
+ MarkerNamesAddedString = MarkerNamesAddedString.strip()
+ if MarkerNamesAddedString:
+ MarkerNamesAdded = MarkerNamesAddedString.split(',')
+
+ GroupNeedExport = []
+ # To simplify the business logic, just add this group to the list anyway
+ GroupNeedExport.append(InbredSetName)
+
+
+ for one_marker in MarkerNamesExisted:
+ if self.checkMarkerHasBeenInGroup(InbredSetName=InbredSetName, MarkerName=one_marker, fd=fd):
+ GroupNeedExport = self.changeMarker( InbredSetName=InbredSetName, MarkerWebID=one_marker, MarkerName=one_marker, GroupNeedExport=GroupNeedExport, fd=fd)
+
+ if MarkerNamesAdded:
+ for one_marker in MarkerNamesAdded:
+ input_name = fd.formdata.getvalue( one_marker + markerName_Feild_Separator + 'Name' )
+ GroupNeedExport = self.changeMarker( InbredSetName=InbredSetName, MarkerWebID=one_marker, MarkerName=input_name, GroupNeedExport=GroupNeedExport, fd=fd)
+
+ export_info = self.exportAllGenoFiles( GroupNeedExport )
+
+ contents = []
+
+ contents.append(export_info)
+
+ HTInput_FormId = HT.Input(type='hidden', name='FormID', value='updGeno')
+ HTInput_Back = HT.Input(type="submit", name="backButton", value="Back to main page", Class="button")
+ HTForm_Back = HT.Form(name='StrainForm', cgi=os.path.join(webqtlConfig.CGIDIR, 'main.py'), \
+ enctype= 'multipart/form-data', submit=HTInput_Back)
+ HTForm_Back.append(HTInput_FormId)
+
+ contents.append(str(HTForm_Back))
+
+ return '<BR>'.join(contents)
+
+ # return "%s" % export_info
+
+
+
+ def checkMarkerHasBeenInGroup(self, InbredSetName="", MarkerName="", fd=None):
+
+ isChanged = False
+
+ # retrive Marker information from database
+ MarkerGroupInfo = retrieveMarkerInfoForGroup (self.cursor, MarkerName, InbredSetName)
+
+ GenoId = MarkerGroupInfo[0]
+
+ GenoInfo={}
+
+ for i in range(1, len(MarkerGroupInfo)):
+ if MarkerGroupInfo[i] != None:
+ GenoInfo[MarkerInfoField[i-1]] = str( MarkerGroupInfo[i] )
+ else:
+ GenoInfo[MarkerInfoField[i-1]] = ''
+
+ if GenoInfo['Used_for_mapping'] == 'Y':
+ GenoInfo['Used_for_mapping'] = True
+ else:
+ GenoInfo['Used_for_mapping'] = False
+
+
+ # check the changing of Geno information
+
+ for i in range(0, len(MarkerInfoField)):
+
+ if MarkerInfoField[i] == 'Name':
+ continue
+
+ webInputValue = fd.formdata.getvalue( MarkerName + markerName_Feild_Separator + MarkerInfoField[i] )
+
+
+ if MarkerInfoField[i] == 'Used_for_mapping':
+ if webInputValue == 'on':
+ webInputValue = True
+ else:
+ webInputValue = False
+
+
+ if GenoInfo[MarkerInfoField[i]] != webInputValue:
+ isChanged = True
+
+ # retrive Marker alleles
+ GenoFreezeId = retrieveGenoFreezeId(self.cursor, InbredSetName)
+ db_alleles = retrieveAllele (self.cursor, GenoFreezeId, GenoId)
+ StrainList = retrieveStrainUsedForMapping (self.cursor, InbredSetName)
+
+
+ # check the changing of allele values
+
+ for i in range(0, len(StrainList)):
+ webInputValue = fd.formdata.getvalue(MarkerName + markerName_Feild_Separator + StrainList[i])
+
+ if not db_alleles.has_key(StrainList[i]):
+ #XZ: This is hard coded.
+ #XZ: The best way is to check if the input value is in ('B', 'D', 'H').
+ if webInputValue.upper() != 'X': # 'X' is the symbol for unknown allele.
+ isChanged = True
+ else:
+ if str( db_alleles[StrainList[i]]) != webInputValue:
+ isChanged = True
+
+
+ return isChanged
+
+
+ def changeMarker(self,InbredSetName="", MarkerWebID="", MarkerName="", GroupNeedExport=[], fd=None):
+
+ GenoFreezeId = retrieveGenoFreezeId( self.cursor, InbredSetName )
+
+ MarkerGroupInfo = retrieveMarkerInfoForGroup(self.cursor, MarkerName, InbredSetName)
+
+ # This marker has record for this group.
+ # Need to keep the original GeneId and marker name.
+ if MarkerGroupInfo:
+
+ #XZ: The first item of MarkerInfo is Geno.Id
+ GenoId = MarkerGroupInfo[0]
+
+ #This function should be excuted before update Chr and Mb in database.
+ GroupNeedExport = getAllGroupsNeedExported(self.cursor, GroupNeedExport=GroupNeedExport, GenoId=GenoId, \
+ Chr=fd.formdata.getvalue(MarkerWebID + markerName_Feild_Separator + 'Chr'), \
+ Mb=fd.formdata.getvalue(MarkerWebID + markerName_Feild_Separator + 'Mb') )
+
+ # Update the info in Geno (Chr, Mb, Sequence, Source).
+ updateGeno(self.cursor, GenoId, InbredSetName, MarkerWebID, fd)
+
+ # Update GenoXRef (cM, Used_for_mapping)
+ updateGenoXRef(self.cursor, GenoFreezeId, GenoId, MarkerWebID, fd)
+
+ # Keep the original GenoXRef.DataId value.
+ DataId = retrieveDataId(self.cursor, GenoId, InbredSetName)
+
+ # Delete the original alleles
+ cmd = "delete from GenoData where Id=%s" % DataId
+ self.cursor.execute(cmd)
+
+ # Insert new alleles.
+ insertGenoData(cursor=self.cursor, InbredSetName=InbredSetName, DataId=DataId, MarkerWebID=MarkerWebID, fd=fd)
+
+ else: # No record for this group.
+
+ hasInfoForSpecies = checkIfMarkerInSpecies(self.cursor, MarkerName, InbredSetName)
+
+ if hasInfoForSpecies:
+
+ # Keep the original GenoId.
+ GenoId = hasInfoForSpecies[0]
+
+ #This function should be excuted before update Chr and Mb in database.
+ GroupNeedExport = getAllGroupsNeedExported(self.cursor, GroupNeedExport=GroupNeedExport, GenoId=GenoId, \
+ Chr=fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Chr' ), \
+ Mb=fd.formdata.getvalue( MarkerWebID + markerName_Feild_Separator + 'Mb') )
+
+
+ # Update the info in Geno (Chr, Mb, Sequence, Source).
+ updateGeno(self.cursor, GenoId, InbredSetName, MarkerWebID, fd)
+
+
+ # Get new GenoData.Id
+ DataId = retrieveMaxGenoDataId(self.cursor) + 1
+
+ # Add record in GenoXRef table for this group.
+ addGenoXRef(self.cursor, GenoFreezeId, GenoId, DataId, MarkerWebID, fd)
+
+ # Add record in GenoData table.
+ insertGenoData(cursor=self.cursor, InbredSetName=InbredSetName, DataId=DataId, MarkerWebID=MarkerWebID, fd=fd)
+
+ else:
+ # Get new Geno.Id
+ GenoId = retrieveMaxGenoId(cursor=self.cursor) + 1
+
+ # Add record in Geno
+ addGeno(self.cursor, GenoId, InbredSetName, MarkerWebID, fd)
+
+ # Get new GenoData.Id
+ DataId = retrieveMaxGenoDataId(self.cursor) + 1
+
+ # Add record into GenoXRef table.
+ addGenoXRef(self.cursor, GenoFreezeId, GenoId, DataId, MarkerWebID, fd)
+
+ #Add record into GenoData table.
+ insertGenoData(cursor=self.cursor, InbredSetName=InbredSetName, DataId=DataId, MarkerWebID=MarkerWebID, fd=fd)
+
+ return GroupNeedExport
+
+
+
+ def exportAllGenoFiles (self, InbredSetNameList = []):
+
+ warning = "As to the change made, the following groups need to be exported to generate new geno files: %s\n<br><br> " % str(InbredSetNameList)
+
+ whiteList = ['BXD']
+
+ warning = warning + "At current development stage, the following groups can be exported to generate geno files: %s\n<br><br>" % str(whiteList)
+ warning = warning + "Here are the geno files that are ACTUALLY exported according to the change you made:\n<br>"
+
+ blackList = []
+ for one_group in InbredSetNameList:
+ if one_group in whiteList:
+ self.exportOneGenoFile( one_group )
+ warning = warning + "<a href='/genotypes/%s.geno" % one_group + "'>" + one_group + " geno file</a>\n<br>"
+ else:
+ blackList.append(one_group)
+
+ return warning
+
+
+
+ def exportOneGenoFile (self, InbredSetName=''):
+
+ geno_file = open(webqtlConfig.GENODIR + InbredSetName + '.geno', 'w')
+
+ query = "select SpeciesId from InbredSet where Name='%s' " % InbredSetName
+ self.cursor.execute( query )
+ SpeciesId = self.cursor.fetchone()[0]
+
+ GenoFreezeId = retrieveGenoFreezeId( self.cursor, InbredSetName )
+
+ StrainUsedForMapping = retrieveStrainUsedForMapping(self.cursor, InbredSetName )
+
+ StrainNameIdUsedForMapping = retrieveStrainNameIdUsedForMapping( self.cursor, InbredSetName )
+
+ GenoCode_record = retrieveGenoCode(self.cursor, InbredSetName )
+
+ Allle_value_symbol = {}
+ symbol_for_unknown = ''
+
+ for one_result in GenoCode_record:
+ if str(one_result[2]) != 'None':
+ Allle_value_symbol[one_result[2]] = one_result[1]
+ else:
+ symbol_for_unknown = one_result[1]
+
+
+ geno_file.write('@name:%s\n' % InbredSetName )
+
+ GeneticType = retrieveGeneticTypeOfInbredSet(self.cursor, InbredSetName )
+
+ geno_file.write('@type:%s\n' % str(GeneticType) )
+
+ for one_result in GenoCode_record:
+ geno_file.write('@%s:%s\n' % (one_result[0], one_result[1]) )
+
+ geno_file.write('Chr\tLocus\tcM\tMb')
+
+ for one_strain in StrainUsedForMapping:
+ geno_file.write('\t%s' % one_strain )
+
+
+ query = "select Geno.Chr, Geno.Name, GenoXRef.cM, Geno.Mb, GenoXRef.DataId from Geno, GenoXRef where SpeciesId=%s and GenoFreezeId=%s and Used_for_mapping='Y' and Geno.Id=GenoId order by chr_num, Mb" % (SpeciesId, GenoFreezeId)
+ self.cursor.execute( query )
+ results = self.cursor.fetchall()
+
+ StrainId_Allele = {}
+
+ for one_result in results:
+ Chr, Name, cM, Mb, DataId = one_result
+ geno_file.write('\n%s\t%s\t%s\t%s' % (Chr, Name, cM, Mb) )
+
+ StrainId_Allele = {}
+
+ query = "select StrainId, value from GenoData where Id=%s " % DataId
+ self.cursor.execute( query )
+ GenoData_results = self.cursor.fetchall()
+
+ for one_GenoData_result in GenoData_results:
+ StrainId_Allele[ one_GenoData_result[0] ] = one_GenoData_result[1]
+
+ for one_strain_name in StrainUsedForMapping:
+ one_strain_id = StrainNameIdUsedForMapping[ one_strain_name ]
+
+ if StrainId_Allele.has_key( one_strain_id ):
+ one_allele_value = StrainId_Allele[one_strain_id]
+ one_allele_symbol = Allle_value_symbol[ one_allele_value ]
+ geno_file.write( '\t%s' % one_allele_symbol )
+ else:
+ geno_file.write( '\t%s' % symbol_for_unknown )
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/webqtl/management/__init__.py b/web/webqtl/management/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/management/__init__.py
diff --git a/web/webqtl/management/assignUserToDatasetPage.py b/web/webqtl/management/assignUserToDatasetPage.py
new file mode 100755
index 00000000..8e089526
--- /dev/null
+++ b/web/webqtl/management/assignUserToDatasetPage.py
@@ -0,0 +1,159 @@
+# 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
+
+import os
+import string
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+
+#XZ, 02/06/2009: Xiaodong created this class
+class assignUserToDatasetPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+
+ ifVerified = fd.formdata.getvalue('ifVerified')
+
+ if ifVerified != 'GN@UTHSC':
+ heading = "Error page"
+ detail = ["You are NoT verified as administrator."]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+
+ ProbeSetFreeze_FullName = fd.formdata.getvalue('ProbeSetFreeze_FullName')
+ User_name = fd.formdata.getvalue('User_name')
+
+ if ProbeSetFreeze_FullName and User_name:
+ ProbeSetFreeze_FullName = string.strip(ProbeSetFreeze_FullName)
+ User_name = string.strip(User_name)
+
+ #XZ, check if the input dataset name exists.
+ self.cursor.execute( 'select count(FullName) from ProbeSetFreeze where FullName="%s"' % ProbeSetFreeze_FullName )
+ result = self.cursor.fetchone()
+ if result:
+ row_count = result[0]
+ if row_count:
+ pass
+ else:
+ heading = "Error page"
+ detail = ["The dataset name %s does NOT exist in database." % ProbeSetFreeze_FullName]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = "Error page"
+ detail = ["No sql result returned when check dataset name."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ, check if the input user name exists.
+ self.cursor.execute( 'select count(name) from User where name="%s"' % User_name )
+ result = self.cursor.fetchone()
+ if result:
+ row_count = result[0]
+ if row_count:
+ pass
+ else:
+ heading = "Error page"
+ detail = ["The user name %s does NOT exist in database." % User_name]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = "Error page"
+ detail = ["No sql result returned when check user name."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.cursor.execute( 'select AuthorisedUsers from ProbeSetFreeze where FullName="%s"' % ProbeSetFreeze_FullName )
+ result = self.cursor.fetchone() # The FullName is unique.
+ if result:
+ AuthorisedUsers = result[0]
+ if not AuthorisedUsers:
+ self.cursor.execute('update ProbeSetFreeze set AuthorisedUsers="%s" where FullName="%s"' %(User_name, ProbeSetFreeze_FullName) )
+ else:
+ AuthorisedUsersList=AuthorisedUsers.split(',')
+ if not AuthorisedUsersList.__contains__(User_name):
+ AuthorisedUsers = AuthorisedUsers + ',%s' % User_name
+ self.cursor.execute('update ProbeSetFreeze set AuthorisedUsers="%s" where FullName="%s"' %(AuthorisedUsers, ProbeSetFreeze_FullName) )
+ else:
+ heading = "Error page"
+ detail = ["No sql result returned when query AuthorisedUsers."]
+ self.error(heading=heading,detail=detail)
+ return
+
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ dataHeading = HT.Paragraph('Confidential Dataset Table', Class="title")
+
+ dataTable = HT.TableLite(border=1, cellpadding=0, cellspacing=0, Class="collap", width="100%")
+
+ dataHeaderRow = HT.TR()
+ dataHeaderRow.append(HT.TD("Dataset Id", Class='fs14 fwb ffl b1 cw cbrb'))
+ dataHeaderRow.append(HT.TD("Dataset Full Name", Class='fs14 fwb ffl b1 cw cbrb'))
+ dataHeaderRow.append(HT.TD("Authorised User", Class='fs14 fwb ffl b1 cw cbrb'))
+ dataTable.append(dataHeaderRow)
+
+ self.cursor.execute('select Id, FullName, AuthorisedUsers from ProbeSetFreeze where confidentiality=1 order by FullName,Id')
+
+ result = self.cursor.fetchall()
+
+ dataInfo = HT.Blockquote( 'There are %d confidential datasets.' % len(result) )
+
+
+ for one_row in result:
+ ProbeSetFreeze_Id, ProbeSetFreeze_FullName, ProbeSetFreeze_AuthorisedUsers = one_row
+ dataRow = HT.TR()
+ dataRow.append(HT.TD("%s" % ProbeSetFreeze_Id, Class='fs12 fwn ffl b1 c222'))
+ dataRow.append(HT.TD("%s" % ProbeSetFreeze_FullName, Class='fs12 fwn ffl b1 c222'))
+ dataRow.append(HT.TD("%s" % ProbeSetFreeze_AuthorisedUsers, Class='fs12 fwn ffl b1 c222'))
+ dataTable.append(dataRow)
+
+ assignUserForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='assignUserForm', submit=HT.Input(type='hidden'))
+ assignUserForm.append(
+ HT.Blockquote(
+ HT.Font('Dataset Full Name ', color='red'),
+ HT.Input(type='text' ,name='ProbeSetFreeze_FullName',value='', size=50,maxlength=200),
+ HT.Font(' User name ', color='red'),
+ HT.Input(type='text' ,name='User_name',value='', size=20,maxlength=20),
+ HT.Input(type='Submit', value='Submit', Class="button")),
+ HT.Input(type='hidden',name='FormID',value='assignUserToDataset'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC')
+ )
+
+ TD_LR.append(dataHeading, dataInfo, assignUserForm, dataTable, assignUserForm)
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = 'Confidential datasets'
+
diff --git a/web/webqtl/management/createUserAccountPage.py b/web/webqtl/management/createUserAccountPage.py
new file mode 100755
index 00000000..f002c6ed
--- /dev/null
+++ b/web/webqtl/management/createUserAccountPage.py
@@ -0,0 +1,161 @@
+# 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
+
+import os
+import string
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+
+
+
+#XZ, 02/06/2009: Xiaodong created this class
+class createUserAccountPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+
+ ifVerified = fd.formdata.getvalue('ifVerified')
+
+ if ifVerified != 'GN@UTHSC':
+ heading = "Error page"
+ detail = ["You are NoT verified as administrator."]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+
+ user_name = fd.formdata.getvalue('user_name')
+ password = fd.formdata.getvalue('password')
+ retype_password = fd.formdata.getvalue('retype_password')
+
+ if user_name or password or retype_password:
+ user_name = string.strip(user_name)
+ password = string.strip(password)
+ retype_password = string.strip(retype_password)
+
+ #XZ, check if the input user name exists.
+
+ if len(user_name) == 0:
+ heading = "Error page"
+ detail = ["The user name can NOT be empty."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.cursor.execute( 'select count(name) from User where name="%s"' % user_name )
+ result = self.cursor.fetchone()
+ if result:
+ row_count = result[0]
+ if row_count:
+ heading = "Error page"
+ detail = ["The user name %s already exists in database. Please make up another user name." % user_name]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = "Error page"
+ detail = ["No sql result returned when check user name."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ # check password
+ if len(password) == 0 or len(retype_password) == 0:
+ heading = "Error page"
+ detail = ["The password can NOT be empty."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ if password != retype_password:
+ heading = "Error page"
+ detail = ["The passwords you entered are NOT consistent. Please go back and try again."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ, create new account
+ self.cursor.execute( "insert into User (name, password, createtime, privilege) values ('%s', SHA('%s'), Now(), 'user')" % (user_name, password) )
+
+
+ #show user table.
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ userHeading = HT.Paragraph('User Table', Class="title")
+
+ self.cursor.execute( 'select id, name, privilege from User order by name' )
+
+ result = self.cursor.fetchall()
+
+ userInfo = HT.Blockquote( 'There are %d users.' % len(result) )
+
+ userTable = HT.TableLite(border=0, cellpadding=0, cellspacing=0, Class="collap", width="100%")
+
+ userHeaderRow = HT.TR()
+ userHeaderRow.append(HT.TD("User Id", Class='fs14 fwb ffl b1 cw cbrb'))
+ userHeaderRow.append(HT.TD("User name", Class='fs14 fwb ffl b1 cw cbrb'))
+ userHeaderRow.append(HT.TD("User privilege", Class='fs14 fwb ffl b1 cw cbrb'))
+ userTable.append(userHeaderRow)
+
+ for one_row in result:
+ User_Id, User_name, User_privilege = one_row
+ userRow = HT.TR()
+ userRow.append(HT.TD("%s" % User_Id, Class='fs12 fwn ffl b1 c222'))
+ userRow.append(HT.TD("%s" % User_name, Class='fs12 fwn ffl b1 c222'))
+ userRow.append(HT.TD("%s" % User_privilege, Class='fs12 fwn ffl b1 c222'))
+ userTable.append(userRow)
+
+ #add user form
+ createUserAccountForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='createUserAccountForm', submit=HT.Input(type='hidden'))
+
+ user_name = HT.Input(type='text' ,name='user_name',value='', size=20,maxlength=20)
+ password = HT.Input(type='password' ,name='password',value='', size=20,maxlength=20)
+ retype_password = HT.Input(type='password' ,name='retype_password',value='', size=20,maxlength=20)
+ submit_button = HT.Input(type='Submit', value='Submit', Class="button")
+
+ createUserAccountForm.append(
+ HT.Blockquote( HT.Font('Create one new account: User Name ', color='red'), user_name, HT.Font(' Password ', color='red'), password, HT.Font(' Retype Password ', color='red'), retype_password, submit_button ),
+ HT.Input(type='hidden',name='FormID',value='createUserAccount'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC')
+ )
+
+ """
+ #manager form
+ managerForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='managerForm', submit=HT.Input(type='hidden'))
+ managerForm.append(
+ HT.Input(type='Submit', value='Go to manager main page', Class="button"),
+ HT.Input(type='hidden',name='FormID',value='managerMain'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC')
+ )
+ """
+
+ #TD_LR.append(managerForm, HT.BR(), userHeading, userInfo, HT.P(), createUserAccountForm, userTable, createUserAccountForm, HT.BR(), managerForm)
+ TD_LR.append(userHeading, userInfo, HT.P(), createUserAccountForm, userTable, createUserAccountForm)
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = 'User account'
diff --git a/web/webqtl/management/deletePhenotypeTraitPage.py b/web/webqtl/management/deletePhenotypeTraitPage.py
new file mode 100755
index 00000000..de071003
--- /dev/null
+++ b/web/webqtl/management/deletePhenotypeTraitPage.py
@@ -0,0 +1,196 @@
+# 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
+
+import os
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from base.webqtlDataset import webqtlDataset
+from base.webqtlTrait import webqtlTrait
+
+
+#XZ, 09/07/2009: Xiaodong created this class
+class deletePhenotypeTraitPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ ifVerified = fd.formdata.getvalue('ifVerified')
+ status = fd.formdata.getvalue('status')
+
+ if ifVerified != 'GN@UTHSC':
+ heading = "Error page"
+ detail = ["You are NoT verified as administrator."]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ if status == 'input':
+ self.dict['body'] = self.genInputPage()
+ self.dict['title'] = 'Delete Phenotype Trait Input Page'
+ if status == 'check':
+ PublishFreeze_Name = fd.formdata.getvalue('PublishFreeze_Name')
+ traitID = fd.formdata.getvalue('traitID')
+ self.dict['body'] = self.checkInputPage(PublishFreeze_Name, traitID)
+ self.dict['title'] = 'Delete Phenotype Trait Check Input Page'
+ if status == 'delete':
+ PublishFreeze_Name = fd.formdata.getvalue('PublishFreeze_Name')
+ traitID = fd.formdata.getvalue('traitID')
+ self.dict['body'] = self.deleteResultPage(PublishFreeze_Name, traitID)
+ self.dict['title'] = 'Delete Phenotype Trait Result Page'
+
+
+ def genInputPage(self):
+
+ crossMenu = HT.Select(name='PublishFreeze_Name', onChange='xchange()')
+
+ self.cursor.execute('select PublishFreeze.Name from PublishFreeze, InbredSet where InbredSetId=InbredSet.Id')
+ result = self.cursor.fetchall()
+
+ for one_row in result:
+ Name = one_row
+ crossMenu.append(tuple([Name,Name]))
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ deletePhenotypeTraitForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='deletePhenotypeTraitForm', submit=HT.Input(type='hidden'))
+ deletePhenotypeTraitForm.append(
+ HT.Blockquote(
+ HT.Font('Publish Freeze Name '),
+ crossMenu,
+ HT.Font(' Phenotype Trait ID '),
+ HT.Input(type='text' ,name='traitID',value='', size=20,maxlength=20),
+ HT.Input(type='Submit', value='Submit', Class="button")),
+ HT.Input(type='hidden',name='FormID',value='deletePhenotypeTrait'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC'),
+ HT.Input(type='hidden',name='status',value='check')
+ )
+
+ TD_LR.append(deletePhenotypeTraitForm)
+
+ return str(TD_LR)
+
+
+ def checkInputPage(self, PublishFreeze_Name, traitID):
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ try:
+ db = webqtlDataset(PublishFreeze_Name, self.cursor)
+ thisTrait = webqtlTrait(db=db, cursor=self.cursor, name=traitID)
+ thisTrait.retrieveInfo()
+ setDescription = thisTrait.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users)
+ except:
+ TD_LR.append( HT.Font('This trait is not found. Please go back to check if you selected correct Group Name and inputed correct trait ID.', color='red') )
+ return str(TD_LR)
+
+ #TD_LR.append(HT.Font('Publish Freeze Name: %s' % PublishFreeze_Name, color='red'),HT.BR(), HT.Font('trait ID: %s' % traitID, color='red'), HT.BR())
+
+ formMain = HT.Form(cgi=os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+
+ formMain.append(
+ HT.Blockquote(
+ HT.Font('The trait '),
+ setDescription,
+ HT.Font(' will be deleted.'),
+ HT.BR(), HT.BR(),
+ HT.Font('Please open the trait and make sure you do want to delete it.', color = 'red')
+ ),
+ HT.Input(type='hidden',name='FormID',value=''),
+ HT.Input(type='hidden',name='database',value=''),
+ HT.Input(type='hidden',name='ProbeSetID',value=''),
+ HT.Input(type='hidden',name='CellID',value='')
+ )
+
+ deletePhenotypeTraitForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='deletePhenotypeTraitForm', submit=HT.Input(type='hidden'))
+ deletePhenotypeTraitForm.append(
+ HT.Input(type='Submit', value='Delete Trait', Class="button"),
+ HT.Input(type='hidden',name='FormID',value='deletePhenotypeTrait'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC'),
+ HT.Input(type='hidden',name='status',value='delete'),
+ HT.Input(type='hidden',name='PublishFreeze_Name',value=db),
+ HT.Input(type='hidden',name='traitID',value=traitID)
+ )
+
+
+ TD_LR.append(formMain, HT.BR(), HT.BR(), deletePhenotypeTraitForm)
+ return str(TD_LR)
+
+ def deleteResultPage(self, PublishFreeze_Name, traitID):
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ #TD_LR.append(HT.Font('Publish Freeze Name: %s' % PublishFreeze_Name, color='red'),HT.BR(), HT.Font('trait ID: %s' % traitID, color='red'), HT.BR(), HT.BR(), 'Being constructed...')
+
+ self.cursor.execute( 'select InbredSetId from PublishFreeze where Name="%s"' % PublishFreeze_Name )
+ InbredSetId = self.cursor.fetchone()[0]
+ #TD_LR.append(HT.BR(), HT.BR(), 'InbredSetId: ', InbredSetId)
+
+ self.cursor.execute( 'select PhenotypeId, PublicationId, DataId from PublishXRef where Id = %s and InbredSetId = %s' % (traitID, InbredSetId) )
+ result = self.cursor.fetchone()
+ PhenotypeId, PublicationId, DataId = result
+
+ #TD_LR.append(HT.BR(), 'PhenotypeId: ', PhenotypeId)
+ #TD_LR.append(HT.BR(), 'PublicationId: ', PublicationId)
+ #TD_LR.append(HT.BR(), 'DataId: ', DataId)
+
+ #PublishData
+ self.cursor.execute('delete from PublishData where Id = %s' % DataId)
+
+ #PublishSE
+ self.cursor.execute('delete from PublishSE where DataId = %s' % DataId)
+
+ #NStrain
+ self.cursor.execute('delete from NStrain where DataId = %s' % DataId)
+
+ #Phenotype
+ self.cursor.execute( 'select count(*) from PublishXRef where PhenotypeId = %s' % PhenotypeId )
+ PhenotypeId_count = self.cursor.fetchone()[0]
+ #TD_LR.append(HT.BR(), HT.BR(), 'PhenotypeId_count: ', PhenotypeId_count)
+ if PhenotypeId_count > 1:
+ pass
+ else:
+ self.cursor.execute('delete from Phenotype where Id = %s' % PhenotypeId)
+
+ #Publication
+ self.cursor.execute( 'select count(*) from PublishXRef where PublicationId = %s' % PublicationId )
+ PublicationId_count = self.cursor.fetchone()[0]
+ #TD_LR.append(HT.BR(), 'PublicationId_count: ', PublicationId_count)
+ if PublicationId_count > 1:
+ pass
+ else:
+ self.cursor.execute('delete from Publication where Id = %s' % PublicationId)
+
+ #PublishXRef
+ self.cursor.execute( 'delete from PublishXRef where Id = %s and InbredSetId = %s' % (traitID, InbredSetId) )
+
+ #TD_LR.append(HT.BR(), HT.BR() )
+ TD_LR.append('The trait %s has been successfully deleted from %s' % (traitID, PublishFreeze_Name))
+
+ return str(TD_LR)
diff --git a/web/webqtl/management/editHeaderFooter.py b/web/webqtl/management/editHeaderFooter.py
new file mode 100755
index 00000000..1461fa3a
--- /dev/null
+++ b/web/webqtl/management/editHeaderFooter.py
@@ -0,0 +1,200 @@
+# 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 htmlgen import HTMLgen2 as HT
+import os
+import string
+import urlparse
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+
+# 20100309 Lei Yan
+class editHeaderFooter(templatePage):
+
+ htmlPath = webqtlConfig.ChangableHtmlPath
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ self.templateInclude = 1
+ self.dict['title'] = "Editing HTML"
+
+ if not self.updMysql():
+ return
+
+ path = fd.formdata.getvalue('path')
+ preview = fd.formdata.getvalue('preview')
+ newHtmlCode = fd.formdata.getvalue('htmlSrc')
+ hf = fd.formdata.getvalue('hf')
+
+ if newHtmlCode:
+ newHtmlCode = string.replace(newHtmlCode,"&amp;", "&")
+ if path and preview:
+ self.templateInclude = 0
+ if hf=='h':
+ tempH = newHtmlCode
+ fp = open(self.htmlPath+'/footer.html', 'r')
+ tempF = fp.read()
+ fp.close()
+ else:
+ fp = open(self.htmlPath+'/header.html', 'r')
+ tempH = fp.read()
+ fp.close()
+ tempF = newHtmlCode
+ tempHtml = """
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD><TITLE>Header Footer Test</TITLE>
+<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<LINK REL="stylesheet" TYPE="text/css" HREF='/css/general.css'>
+<LINK REL="stylesheet" TYPE="text/css" HREF='/css/menu.css'>
+<link rel="stylesheet" media="all" type="text/css" href="/css/tabbed_pages.css" />
+<SCRIPT SRC="/javascript/webqtl.js"></SCRIPT>
+<SCRIPT SRC="/javascript/tooltip.js"></SCRIPT>
+<SCRIPT SRC="/javascript/dhtml.js"></SCRIPT>
+<SCRIPT SRC="/javascript/beta2.js"></SCRIPT>
+<script src="/javascript/tabbed_pages.js" type="text/javascript"></script>
+</HEAD>
+<BODY bottommargin="2" leftmargin="2" rightmargin="2" topmargin="2" text=#000000 bgColor=#ffffff>
+<TABLE cellSpacing=5 cellPadding=4 width="100%%" border=0>
+ <TBODY>
+ <TR>
+ %s
+ </TR>
+ <TR>
+ <TD bgColor=#eeeeee class="solidBorder">
+ <Table width= "100%%" cellSpacing=0 cellPadding=5>
+ <TR>
+ <!-- split from Here -->
+ <!-- Body Start from Here -->
+ <br><br><br><br><br><br><br><br><br><br><br><br>
+ <center style="font-size:16px;font-family:verdana;color:red">Header Footer Test</center>
+ <br><br><br><br><br><br><br><br><br><br><br><br>
+ </TR></TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD align=center bgColor=#ddddff class="solidBorder">
+ <!--Start of footer-->
+ <TABLE width="100%%">
+ %s
+ </TABLE>
+ <!--End of footer-->
+ </TD>
+ </TR>
+</TABLE>
+<!-- /Footer -->
+<!-- menu script itself. you should not modify this file -->
+<script language="JavaScript" src="/javascript/menu_new.js"></script>
+<!-- items structure. menu hierarchy and links are stored there -->
+<script language="JavaScript" src="/javascript/menu_items.js"></script>
+<!-- files with geometry and styles structures -->
+<script language="JavaScript" src="/javascript/menu_tpl.js"></script>
+<script language="JavaScript">
+ <!--//
+ // Note where menu initialization block is located in HTML document.
+ // Don't try to position menu locating menu initialization block in
+ // some table cell or other HTML element. Always put it before </body>
+ // each menu gets two parameters (see demo files)
+ // 1. items structure
+ // 2. geometry structure
+ new menu (MENU_ITEMS, MENU_POS);
+ // make sure files containing definitions for these variables are linked to the document
+ // if you got some javascript error like "MENU_POS is not defined", then you've made syntax
+ // error in menu_tpl.js file or that file isn't linked properly.
+ // also take a look at stylesheets loaded in header in order to set styles
+ //-->
+</script>
+</BODY>
+</HTML>
+""" %(tempH, tempF)
+ self.debug = tempHtml
+ elif path:
+ #edit result
+ fileName = self.htmlPath + path
+
+ fp1 = open(fileName, 'w')
+ fp1.write(newHtmlCode)
+ fp1.close()
+
+ fp1 = open(fileName, 'r')
+ lines = fp1.readlines()
+ fp1.close
+
+ if 'h'==hf:
+ fp2 = open(self.htmlPath + '/javascript/header.js', 'w')
+ else:
+ fp2 = open(self.htmlPath + '/javascript/footer.js', 'w')
+ fp2.write("ctext = ''\r\n")
+ fp2.flush()
+ for line in lines:
+ fp2.write("ctext += '%s'\r\n" %(line.rstrip()))
+ fp2.flush()
+ fp2.write('document.write(ctext)')
+ fp2.flush()
+ fp2.close()
+
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#eeeeee", height=200)
+ mainTitle = HT.Paragraph("Edit HTML", Class="title")
+ url = HT.Href(text = "page", url =path, Class = "normal")
+ intro = HT.Blockquote("This ",url, " has been succesfully modified. ")
+ TD_LR.append(mainTitle, intro)
+ self.dict['body'] = TD_LR
+ elif fd.refURL:
+ #retrieve file to be edited
+ #refURL = os.environ['HTTP_REFERER']
+ addressing_scheme, network_location, path, parameters, query, fragment_identifier = urlparse.urlparse(fd.refURL)
+ if 'h'==hf:
+ path = "/header.html"
+ else:
+ path = "/footer.html"
+ fileName = self.htmlPath + path
+ fp = open(fileName,'r')
+ htmlCode = fp.read()
+ htmlCode = string.replace(htmlCode, "&","&amp;")
+ fp.close()
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='editHtml',submit=HT.Input(type='hidden'))
+ inputBox = HT.Textarea(name='htmlSrc', cols="100", rows=30,text=htmlCode)
+ hddn = {'FormID':'editHeaderFooter', 'path':path, 'preview':'', 'hf':hf}
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+ previewButton = HT.Input(type='button',name='previewhtml', value='Preview',Class="button", onClick= "editHTML(this.form, 'preview');")
+ submitButton = HT.Input(type='button',name='submitchange', value='Submit Change',Class="button", onClick= "editHTML(this.form, 'submit');")
+ resetButton = HT.Input(type='reset',Class="button")
+ form.append(HT.Center(inputBox, HT.P(), previewButton, submitButton, resetButton))
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#eeeeee")
+ mainTitle = HT.Paragraph("Edit HTML", Class="title")
+ intro = HT.Blockquote("You may edit the HTML source code in the editbox below, or you can copy the content of the editbox to your favorite HTML editor. ")
+ imgUpload = HT.Href(url="javascript:openNewWin('/upload.html', 'menubar=0,toolbar=0,location=0,resizable=0,status=1,scrollbars=1,height=400, width=600');", text="here", Class="normalsize")
+ intro2 = HT.Blockquote("Click ", imgUpload, " to upload Images. ")
+ TD_LR.append(mainTitle, intro, intro2, HT.Center(form))
+ self.dict['body'] = TD_LR
+ else:
+ heading = "Editing HTML"
+ detail = ["Error occured while trying to edit the html file."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
diff --git a/web/webqtl/management/exportPhenotypeDatasetPage.py b/web/webqtl/management/exportPhenotypeDatasetPage.py
new file mode 100755
index 00000000..bbd86385
--- /dev/null
+++ b/web/webqtl/management/exportPhenotypeDatasetPage.py
@@ -0,0 +1,228 @@
+# 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
+
+import os
+import string
+import pyXLWriter as xl
+import time
+
+import reaper
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+from base.webqtlTrait import webqtlTrait
+
+
+
+#XZ, 11/06/2009: Xiaodong created this class
+class exportPhenotypeDatasetPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ ifVerified = fd.formdata.getvalue('ifVerified')
+ status = fd.formdata.getvalue('status')
+
+ if ifVerified != 'GN@UTHSC':
+ heading = "Error page"
+ detail = ["You are NoT verified as administrator."]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ if status == 'input':
+ self.dict['body'] = self.genInputPage()
+ self.dict['title'] = 'Export Phenotype Dataset Input Page'
+ if status == 'output':
+ PublishFreeze_Name = fd.formdata.getvalue('PublishFreeze_Name')
+ self.dict['body'] = self.exportDatasetPage( fd, PublishFreeze_Name )
+ self.dict['title'] = 'Export Phenotype Dataset Page'
+
+
+ def genInputPage(self):
+
+ crossMenu = HT.Select(name='PublishFreeze_Name', onChange='xchange()')
+
+ self.cursor.execute('select PublishFreeze.Name from PublishFreeze, InbredSet where InbredSetId=InbredSet.Id')
+ result = self.cursor.fetchall()
+
+ for one_row in result:
+ Name = one_row
+ crossMenu.append(tuple([Name,Name]))
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ exportPhenotypeDatasetForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='exportPhenotypeDatasetForm', submit=HT.Input(type='hidden'))
+ exportPhenotypeDatasetForm.append(
+ HT.Blockquote(
+ HT.Font('Publish Freeze Name '),
+ crossMenu,
+ HT.Input(type='Submit', value='Submit', Class="button")),
+ HT.Input(type='hidden',name='FormID',value='exportPhenotypeDataset'),
+ HT.Input(type='hidden',name='status',value='output'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC')
+ )
+
+ TD_LR.append( exportPhenotypeDatasetForm )
+
+ return str(TD_LR)
+
+
+ def exportDatasetPage(self, fd, PublishFreeze_Name):
+
+ #return PublishFreeze_Name
+
+ if not self.openMysql():
+ return
+
+ self.cursor.execute( "select InbredSet.Name from PublishFreeze, InbredSet where PublishFreeze.InbredSetId=InbredSet.Id and PublishFreeze.Name='%s'" % PublishFreeze_Name )
+ self.RISet = self.cursor.fetchone()[0]
+
+ fd.RISet = self.RISet
+ fd.incparentsf1 = 1
+ fd.readGenotype()
+ strainlist = fd.f1list + fd.strainlist
+
+ #return str(strainlist)
+
+ self.cursor.execute("Select Species.Name from Species, InbredSet where InbredSet.SpeciesId = Species.Id and InbredSet.Name = '%s'" % fd.RISet)
+ self.Species = self.cursor.fetchone()[0]
+
+ #return Species
+
+ self.searchResult = []
+
+ self.cursor.execute("Select PublishXRef.Id from PublishXRef, InbredSet where PublishXRef.InbredSetId = InbredSet.Id and InbredSet.Name = '%s'" % self.RISet)
+ result = self.cursor.fetchall()
+
+ for one_result in result:
+ self.searchResult.append( "%s::%s" % (PublishFreeze_Name, one_result[0]) )
+
+ #return self.searchResult
+
+
+ fields = ["ID", "Species", "Cross", "Database", "ProbeSetID / RecordID", "Symbol", "Description", "ProbeTarget", "PubMed_ID", "Phenotype", "Chr", "Mb", "Alias", "Gene_ID", "UniGene_ID", "Strand_Probe ", "Strand_Gene ",
+"Probe_set_specificity", "Probe_set_BLAT_score", "Probe_set_BLAT_Mb_start", "Probe_set_BLAT_Mb_end ", "QTL_Chr", "Locus_at_Peak", "Max_LRS", "P_value_of_MAX", "Mean_Expression"] + strainlist
+
+
+ if self.searchResult:
+ traitList = []
+ for item in self.searchResult:
+ thisTrait = webqtlTrait(fullname=item, cursor=self.cursor)
+ thisTrait.retrieveInfo(QTL=1)
+ thisTrait.retrieveData(strainlist=strainlist)
+ traitList.append(thisTrait)
+
+ text = [fields]
+ for i, thisTrait in enumerate(traitList):
+ if thisTrait.db.type == 'ProbeSet':
+ if not thisTrait.cellid: #ProbeSet
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, thisTrait.symbol, thisTrait.description, thisTrait.probe_target_description,"", "", thisTrait.chr, thisTrait.mb, thisTrait.alias, thisTrait.geneid, thisTrait.unigeneid, thisTrait.strand_probe, thisTrait.strand_gene, thisTrait.probe_set_specificity, thisTrait.probe_set_blat_score, thisTrait.probe_set_blat_mb_start, thisTrait.probe_set_blat_mb_end, locusChr[thisTrait.locus], thisTrait.locus, thisTrait.lrs, thisTrait.pvalue])
+ else: #Probe
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name + " : " + thisTrait.cellid, thisTrait.symbol, thisTrait.description, thisTrait.probe_target_description,"", "", thisTrait.chr, thisTrait.mb, thisTrait.alias, thisTrait.geneid, thisTrait.unigeneid, "", "", "", "", "", "", "", "", "", ""])
+ elif thisTrait.db.type == 'Publish':
+ if thisTrait.pre_publication_description:
+ if thisTrait.pubmed_id:
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", "", "", thisTrait.pubmed_id, thisTrait.post_publication_description, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""])
+ else:
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", "", "", "", thisTrait.pre_publication_description, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""])
+ else:
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", "", "", thisTrait.pubmed_id, thisTrait.post_publication_description, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""])
+
+ elif thisTrait.db.type == 'Temp':
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", thisTrait.description, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""])
+ elif thisTrait.db.type == 'Geno':
+ text.append([str(i+1), self.Species, self.RISet, thisTrait.db.fullname, thisTrait.name, "", thisTrait.name,"", "", "", thisTrait.chr, thisTrait.mb, "", "", "", "", "", "", "", "", "", "", "", "", ""])
+ else:
+ continue
+
+ testval = thisTrait.exportData(strainlist)
+ try:
+ mean = reaper.anova(testval)[0]
+ except:
+ mean = 'N/A'
+ text[-1].append(mean)
+ text[-1] += testval
+ if len(text[0]) < 255 or len(text) < 255:
+ transpose = 0
+ if len(text[0]) >= 255:
+ text = webqtlUtil.transpose(text)
+ transpose = 1
+ filename = os.path.join(webqtlConfig.TMPDIR, webqtlUtil.generate_session() +'.xls')
+
+ # Create a new Excel workbook
+ workbook = xl.Writer(filename)
+ worksheet = workbook.add_worksheet()
+ headingStyle = workbook.add_format(align = 'center', bold = 1, size=13, color = 'green')
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=13, border = 1, border_color="gray")
+
+ ##Write title Info
+ worksheet.write([0, 0], "Data source: The GeneNetwork at %s" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([2, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([3, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+ worksheet.write([4, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([6, 0], "This output file contains data from %d GeneNetwork databases listed below" % len(traitList), titleStyle)
+
+ # Row and column are zero indexed
+ nrow = startRow = 8
+ for row in text:
+ for ncol, cell in enumerate(row):
+ if nrow == startRow:
+ worksheet.write([nrow, ncol], cell.strip(), headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(cell))
+ else:
+ worksheet.write([nrow, ncol], cell)
+ nrow += 1
+
+ worksheet.write([nrow+1, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA 21131), NCI MMHCC (U01CA105417), and NCRR (U24 RR021760)", titleStyle)
+ worksheet.write([nrow+2, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+ workbook.close()
+
+ fp = open(filename, 'rb')
+ text = fp.read()
+ fp.close()
+
+ self.content_type = 'application/xls'
+ self.content_disposition = 'attachment; filename=%s' % ('export-%s.xls' % time.strftime("%y-%m-%d-%H-%M"))
+ self.attachment = text
+ else:
+ self.content_type = 'application/xls'
+ self.content_disposition = 'attachment; filename=%s' % ('export-%s.txt' % time.strftime("%y-%m-%d-%H-%M"))
+ for item in text:
+ self.attachment += string.join(map(str, item), '\t')+ "\n"
+ self.cursor.close()
+ else:
+ fd.req.content_type = 'text/html'
+ heading = 'Export Collection'
+ detail = [HT.Font('Error : ',color='red'),HT.Font('Error occurs while retrieving data from database.',color='black')]
+ self.error(heading=heading,detail=detail)
+
diff --git a/web/webqtl/management/managerMainPage.py b/web/webqtl/management/managerMainPage.py
new file mode 100755
index 00000000..36f744ad
--- /dev/null
+++ b/web/webqtl/management/managerMainPage.py
@@ -0,0 +1,130 @@
+# 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
+
+import os
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+#XZ, 02/06/2009: Xiaodong created this class
+class managerMainPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ ifVerified = None
+
+ ifVerified = fd.formdata.getvalue('ifVerified')
+
+ if ifVerified != 'GN@UTHSC':
+ user = fd.formdata.getvalue('user')
+ password = fd.formdata.getvalue('password')
+ privilege, user_id, userExist = webqtlUtil.authUser(user,password,self.cursor,encrypt = None)[:3]
+
+ if userExist and webqtlConfig.USERDICT[privilege] >= webqtlConfig.USERDICT['admin']:
+ ifVerified = True
+
+
+ if not ifVerified:
+ heading = "Error page"
+ detail = ["You do not have privilege to change system configuration."]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ TD_LR = HT.TD(height=200,width="100%", bgColor='#eeeeee')
+
+ heading = "Please click button to make your selection"
+
+ createUserAccountForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='createUserAccountForm', submit=HT.Input(type='hidden'))
+ createUserAccountForm.append(
+ HT.Input(type='button', name='', value='Manage User Accounts', Class="button", onClick="submitToNewWindow(this.form);"),
+ HT.Input(type='hidden',name='FormID',value='createUserAccount'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC')
+ )
+
+ assignUserToDatasetForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='assignUserToDatasetForm', submit=HT.Input(type='hidden'))
+ assignUserToDatasetForm.append(
+ HT.Input(type='button', name='', value='Manage Confidential Datasets', Class="button", onClick="submitToNewWindow(this.form);"),
+ HT.Input(type='hidden',name='FormID',value='assignUserToDataset'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC')
+ )
+
+ deletePhenotypeTraitForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='deletePhenotypeTraitForm', submit=HT.Input(type='hidden'))
+ deletePhenotypeTraitForm.append(
+ HT.Input(type='button', name='', value='Delete Phenotype Trait', Class="button", onClick="submitToNewWindow(this.form);"),
+ HT.Input(type='hidden',name='FormID',value='deletePhenotypeTrait'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC'),
+ HT.Input(type='hidden',name='status',value='input')
+ )
+
+ exportPhenotypeDatasetForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='exportPhenotypeDatasetForm', submit=HT.Input(type='hidden'))
+ exportPhenotypeDatasetForm.append(
+ HT.Input(type='button', name='', value='Export Phenotype Dataset', Class="button", onClick="submitToNewWindow(this.form);"),
+ HT.Input(type='hidden',name='FormID',value='exportPhenotypeDataset'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC'),
+ HT.Input(type='hidden',name='status',value='input')
+ )
+
+ updateGenotypeForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='updateGenotypeForm', submit=HT.Input(type='hidden'))
+ updateGenotypeForm.append(
+ HT.Input(type='button', name='', value='Update Genotype', Class="button", onClick="submitToNewWindow(this.form);"),
+ HT.Input(type='hidden',name='FormID',value='updGeno'),
+ HT.Input(type='hidden',name='ifVerified',value='GN@UTHSC')
+ )
+
+ editHeaderForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='editHeaderForm', submit=HT.Input(type='hidden'))
+ editHeaderForm.append(
+ HT.Input(type='button', name='', value='Edit Header', Class="button", onClick="submitToNewWindow(this.form);"),
+ HT.Input(type='hidden', name='FormID', value='editHeaderFooter'),
+ HT.Input(type='hidden', name='hf', value='h'),
+ )
+
+ editFooterForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='editFooterForm', submit=HT.Input(type='hidden'))
+ editFooterForm.append(
+ HT.Input(type='button', name='', value='Edit Footer', Class="button", onClick="submitToNewWindow(this.form);"),
+ HT.Input(type='hidden', name='FormID', value='editHeaderFooter'),
+ HT.Input(type='hidden', name='hf', value='f'),
+ )
+
+ TD_LR.append(heading, HT.P(),HT.P(),
+ createUserAccountForm, HT.P(),HT.P(),
+ assignUserToDatasetForm, HT.P(),HT.P(),
+ deletePhenotypeTraitForm, HT.P(),HT.P(),
+ exportPhenotypeDatasetForm, HT.P(),HT.P(),
+ updateGenotypeForm, HT.P(),HT.P(),
+ editHeaderForm, HT.P(),HT.P(),
+ editFooterForm)
+
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = 'Manager Main Page'
+
diff --git a/web/webqtl/markerRegression/CompositeMarkerRegressionPage.py b/web/webqtl/markerRegression/CompositeMarkerRegressionPage.py
new file mode 100755
index 00000000..6cd8c53a
--- /dev/null
+++ b/web/webqtl/markerRegression/CompositeMarkerRegressionPage.py
@@ -0,0 +1,211 @@
+# 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
+
+import string
+import piddle as pid
+import os
+
+from htmlgen import HTMLgen2 as HT
+import reaper
+
+from utility import Plot
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+
+
+class CompositeMarkerRegressionPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not fd.genotype:
+ fd.readData()
+
+ fd.parentsf14regression = fd.formdata.getvalue('parentsf14regression')
+
+ weightedRegression = fd.formdata.getvalue('applyVarianceSE')
+
+ if fd.parentsf14regression and fd.genotype_2:
+ _genotype = fd.genotype_2
+ else:
+ _genotype = fd.genotype_1
+
+ _strains, _vals, _vars, N = fd.informativeStrains(_genotype.prgy, weightedRegression)
+
+ self.data = fd
+ if self.data.identification:
+ heading2 = HT.Paragraph('Trait ID: %s' % self.data.identification)
+ heading2.__setattr__("class","subtitle")
+ self.dict['title'] = '%s: Composite Regression' % self.data.identification
+ else:
+ heading2 = ""
+ self.dict['title'] = 'Composite Regression'
+
+ if self.data.traitInfo:
+ symbol,chromosome,MB = string.split(fd.traitInfo,'\t')
+ heading3 = HT.Paragraph('[ ',HT.Strong(HT.Italic('%s' % symbol,id="green")),' on Chr %s @ %s Mb ]' % (chromosome,MB))
+ else:
+ heading3 = ""
+ if N < webqtlConfig.KMININFORMATIVE:
+ heading = "Composite Regression"
+ detail = ['Fewer than %d strain data were entered for %s data set. No mapping attempted.' % (webqtlConfig.KMININFORMATIVE, self.data.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = HT.Paragraph('Trait Data Entered for %s Set' % self.data.RISet)
+ heading.__setattr__("class","title")
+ tt = HT.TableLite()
+ for ii in range(N/2):
+ tt.append(HT.TR(HT.TD(_strains[2*ii],nowrap="yes"),HT.TD(width=10), HT.TD(_vals[2*ii], nowrap="yes"), \
+ HT.TD(width=20), HT.TD(_strains[2*ii+1],nowrap="yes"),HT.TD(width=10), HT.TD(_vals[2*ii+1],nowrap="yes")))
+ if N % 2:
+ tt.append(HT.TR(HT.TD(_strains[N-1],nowrap="yes"),HT.TD(width=10), HT.TD(_vals[N-1],nowrap="yes"), \
+ HT.TD(width=20), HT.TD("",nowrap="yes"),HT.TD(width=10), HT.TD("",nowrap="yes")))
+ indata = tt
+
+ mean, median, var, stdev, sem, N = reaper.anova(_vals)
+
+ stats = HT.Paragraph('Number of entered values = %d ' % N,HT.BR(),\
+ 'Mean value = %8.3f ' % mean, HT.BR(), \
+ 'Median value = %8.3f ' % median, HT.BR(), \
+ 'Variance = %8.3f ' % var, HT.BR(), \
+ 'Standard Deviation = %8.3f ' % stdev, HT.BR(), \
+ 'Standard Error = %8.3f ' % sem)
+
+ self.controlLocus = fd.formdata.getvalue('controlLocus')
+ heading4 = HT.Blockquote('Control Background Selected for %s Data Set:' % self.data.RISet)
+ heading4.__setattr__("class","subtitle")
+
+ datadiv = HT.TD(heading, HT.Center(heading2,heading3,indata, stats, heading4,HT.Center(self.controlLocus)), width='45%',valign='top', bgColor='#eeeeee')
+
+ resultstable = self.GenReport(fd, _genotype, _strains, _vals, _vars)
+ self.dict['body'] = str(datadiv)+str(resultstable)
+
+ def GenReport(self, fd, _genotype, _strains, _vals, _vars= []):
+ 'Create an HTML division which reports any loci which are significantly associated with the submitted trait data.'
+ if webqtlUtil.ListNotNull(_vars):
+ qtlresults = _genotype.regression(strains = _strains, trait = _vals, variance = _vars, control = self.controlLocus)
+ LRSArray = _genotype.permutation(strains = _strains, trait = _vals, variance = _vars, nperm=fd.nperm)
+ else:
+ qtlresults = _genotype.regression(strains = _strains, trait = _vals, control = self.controlLocus)
+ LRSArray = _genotype.permutation(strains = _strains, trait = _vals,nperm=fd.nperm)
+
+ myCanvas = pid.PILCanvas(size=(400,300))
+ #plotBar(myCanvas,10,10,390,290,LRSArray,XLabel='LRS',YLabel='Frequency',title=' Histogram of Permutation Test',identification=fd.identification)
+ Plot.plotBar(myCanvas, LRSArray,XLabel='LRS',YLabel='Frequency',title=' Histogram of Permutation Test')
+ filename= webqtlUtil.genRandStr("Reg_")
+ myCanvas.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img=HT.Image('/image/'+filename+'.gif',border=0,alt='Histogram of Permutation Test')
+
+ if fd.suggestive == None:
+ fd.suggestive = LRSArray[int(fd.nperm*0.37-1)]
+ else:
+ fd.suggestive = float(fd.suggestive)
+ if fd.significance == None:
+ fd.significance = LRSArray[int(fd.nperm*0.95-1)]
+ else:
+ fd.significance = float(fd.significance)
+
+ #########################################
+ # Permutation Graph
+ #########################################
+ permutationHeading = HT.Paragraph('Histogram of Permutation Test')
+ permutationHeading.__setattr__("class","title")
+ lrs = HT.Blockquote('Total of %d permutations' % fd.nperm,HT.P(),'Suggestive LRS = %2.2f' % LRSArray[int(fd.nperm*0.37-1)],\
+ HT.BR(),'Significant LRS = %2.2f' % LRSArray[int(fd.nperm*0.95-1)],HT.BR(),'Highly Significant LRS =%2.2f' % LRSArray[int(fd.nperm*0.99-1)])
+
+ permutation = HT.TableLite()
+ permutation.append(HT.TR(HT.TD(img)),HT.TR(HT.TD(lrs)))
+
+ _dispAllLRS = 0
+ if fd.formdata.getvalue('displayAllLRS'):
+ _dispAllLRS = 1
+ qtlresults2 = []
+ if _dispAllLRS:
+ filtered = qtlresults[:]
+ else:
+ filtered = filter(lambda x, y=fd.suggestive: x.lrs > y, qtlresults)
+ if len(filtered) == 0:
+ qtlresults2 = qtlresults[:]
+ qtlresults2.sort()
+ filtered = qtlresults2[-10:]
+
+ #########################################
+ # Marker regression report
+ #########################################
+ locusFormName = webqtlUtil.genRandStr("fm_")
+ locusForm = HT.Form(cgi = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), \
+ enctype='multipart/form-data', name=locusFormName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_', \
+ 'RISet':fd.RISet, 'incparentsf1':'on'}
+ for key in hddn.keys():
+ locusForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ regressionHeading = HT.Paragraph('Marker Regression Report')
+ regressionHeading.__setattr__("class","title")
+ if qtlresults2 != []:
+ report = HT.Blockquote(HT.Font('No association ',color="#FF0000"),HT.Font('with a likelihood ratio statistic greater than %3.1f was found. Here are the top 10 LRSs.' % fd.suggestive,color="#000000"))
+ else:
+ report = HT.Blockquote('The following loci in the %s data set have associations with the above trait data.\n' % fd.RISet, HT.P())
+ report.__setattr__("class","normalsize")
+
+ fpText = open('%s.txt' % (webqtlConfig.TMPDIR+filename), 'wb')
+ textUrl = HT.Href(text = 'Download', url= '/tmp/'+filename+'.txt', target = "_blank", Class='fs12 fwn')
+
+ bottomInfo = HT.Paragraph(textUrl, ' result in tab-delimited text format.', HT.BR(), HT.BR(),'LRS values marked with',HT.Font(' * ',color="red"), 'are greater than the significance threshold (specified by you or by permutation test). ' , HT.BR(), HT.BR(), HT.Strong('Additive Effect'), ' is half the difference in the mean phenotype of all cases that are homozygous for one parental allel at this marker minus the mean of all cases that are homozygous for the other parental allele at this marker. ','In the case of %s strains, for example,' % fd.RISet,' A positive additive effect indicates that %s alleles increase trait values. Negative additive effect indicates that %s alleles increase trait values.'% (fd.ppolar,fd.mpolar),Class="fs12 fwn")
+
+ c1 = HT.TD('LRS',Class="fs14 fwb ffl b1 cw cbrb")
+ c2 = HT.TD('Chr',Class="fs14 fwb ffl b1 cw cbrb")
+ c3 = HT.TD('Mb',Class="fs14 fwb ffl b1 cw cbrb")
+ c4 = HT.TD('Locus',Class="fs14 fwb ffl b1 cw cbrb")
+ c5 = HT.TD('Additive Effect',Class="fs14 fwb ffl b1 cw cbrb")
+
+ fpText.write('LRS\tChr\tMb\tLocus\tAdditive Effect\n')
+ hr = HT.TR(c1, c2, c3, c4, c5)
+ tbl = HT.TableLite(border=0, width="90%", cellpadding=0, cellspacing=0, Class="collap")
+ tbl.append(hr)
+ for ii in filtered:
+ #add by NL 06-22-2011: set LRS to 460 when LRS is infinite,
+ if ii.lrs==float('inf') or ii.lrs>webqtlConfig.MAXLRS:
+ LRS=webqtlConfig.MAXLRS #maximum LRS value
+ else:
+ LRS=ii.lrs
+ fpText.write('%2.3f\t%s\t%s\t%s\t%2.3f\n' % (LRS, ii.locus.chr, ii.locus.Mb, ii.locus.name, ii.additive))
+ if LRS > fd.significance:
+ c1 = HT.TD('%3.3f*' % LRS, Class="fs13 b1 cbw cr")
+ else:
+ c1 = HT.TD('%3.3f' % LRS,Class="fs13 b1 cbw c222")
+ tbl.append(HT.TR(c1, HT.TD(ii.locus.chr,Class="fs13 b1 cbw c222"), HT.TD(ii.locus.Mb,Class="fs13 b1 cbw c222"), HT.TD(HT.Href(text=ii.locus.name, url = "javascript:showTrait('%s','%s');" % (locusFormName, ii.locus.name), Class='normalsize'), Class="fs13 b1 cbw c222"), HT.TD('%3.3f' % ii.additive,Class="fs13 b1 cbw c222"),bgColor='#eeeeee'))
+
+ locusForm.append(tbl)
+ tbl2 = HT.TableLite(border=0, cellspacing=0, cellpadding=0,width="90%")
+ tbl2.append(HT.TR(HT.TD(bottomInfo)))
+ rv=HT.TD(permutationHeading,HT.Center(permutation),regressionHeading,report, HT.Center(locusForm,HT.P(),tbl2,HT.P()),width='55%',valign='top', bgColor='#eeeeee')
+ return rv
+
diff --git a/web/webqtl/markerRegression/MarkerRegressionPage.py b/web/webqtl/markerRegression/MarkerRegressionPage.py
new file mode 100755
index 00000000..7f830b4b
--- /dev/null
+++ b/web/webqtl/markerRegression/MarkerRegressionPage.py
@@ -0,0 +1,1626 @@
+# 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
+
+import time
+import string
+import math
+from math import *
+import piddle as pid
+import sys,os
+import httplib, urllib
+
+from htmlgen import HTMLgen2 as HT
+from utility import Plot
+from intervalAnalyst import GeneUtil
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+from dbFunction import webqtlDatabaseFunction
+from base.GeneralObject import GeneralObject
+
+import reaper
+import cPickle
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+
+class MarkerRegressionPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ self.initializeParameters(fd)
+
+ filename= webqtlUtil.genRandStr("Itvl_")
+ ChrList,ChrNameOrderIdDict,ChrOrderIdNameDict,ChrLengthMbList= self.getChrNameOrderIdLength(RISet=fd.RISet)
+
+ if self.mappingMethodId == '4': # For PLINK
+
+ traitInfoList = string.split(string.strip(fd.identification),':')
+ probesetName = string.strip(traitInfoList[-1])
+ plinkOutputFileName= webqtlUtil.genRandStr("%s_%s_"%(fd.RISet,probesetName))
+
+ # get related values from fd.allTraitData; the format of 'allTraitValueDict'is {strainName1: value=-0.2...}
+ fd.readData()
+ allTraitValueDict = fd.allTraitData
+
+ #automatically generate pheno txt file for PLINK
+ self.genPhenoTxtFileForPlink(phenoFileName=plinkOutputFileName,RISetName=fd.RISet,probesetName=probesetName, valueDict=allTraitValueDict)
+ # os.system full path is required for input and output files; specify missing value is -9999
+ plink_command = '%splink/plink --noweb --ped %splink/%s.ped --no-fid --no-parents --no-sex --no-pheno --map %splink/%s.map --pheno %s/%s.txt --pheno-name %s --missing-phenotype -9999 --out %s%s --assoc ' % (webqtlConfig.HTMLPATH, webqtlConfig.HTMLPATH, fd.RISet, webqtlConfig.HTMLPATH, fd.RISet, webqtlConfig.TMPDIR, plinkOutputFileName, probesetName, webqtlConfig.TMPDIR, plinkOutputFileName)
+
+ os.system(plink_command)
+
+ if fd.identification:
+ heading2 = HT.Paragraph('Trait ID: %s' % fd.identification)
+ heading2.__setattr__("class","subtitle")
+ self.dict['title'] = '%s: Genome Association' % fd.identification
+ else:
+ heading2 = ""
+ self.dict['title'] = 'Genome Association'
+
+ if fd.traitInfo:
+ symbol,chromosome,MB = string.split(fd.traitInfo,'\t')
+ heading3 = HT.Paragraph('[ ',HT.Strong(HT.Italic('%s' % symbol,id="green")),' on Chr %s @ %s Mb ]' % (chromosome,MB))
+ else:
+ heading3 = ""
+
+ heading = HT.Paragraph('Trait Data Entered for %s Set' % fd.RISet)
+ heading.__setattr__("class","title")
+
+ # header info part:Trait Data Entered for HLC Set & Trait ID:
+ headerdiv = HT.TR(HT.TD(heading, heading2,heading3, width='45%',valign='top', align='left', bgColor='#eeeeee'))
+
+ self.ChrList=ChrList # get chr name from '1' to 'X'
+ self.ChrLengthMbList = ChrLengthMbList
+
+ # build plink result dict based on chr, key is chr name, value is in list type including Snpname, bp and pvalue info
+ plinkResultDict={}
+ count,minPvalue,plinkResultDict =self.getPlinkResultDict(outputFileName=plinkOutputFileName,thresholdPvalue=self.pValue,ChrOrderIdNameDict=ChrOrderIdNameDict)
+
+ # if can not find results which are matched with assigned p-value, system info will show up
+ if count >0:
+
+ #for genome association report table
+ reportTable=""
+ # sortable table object
+ resultstable,tblobj,bottomInfo = self.GenReportForPLINK(ChrNameOrderIdDict=ChrNameOrderIdDict, RISet=fd.RISet,plinkResultDict=plinkResultDict,thresholdPvalue=self.pValue,chrList=self.ChrList)
+
+ # creat object for result table for sort function
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ sortby = ("Index", "up")
+ reportTable =HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "0"), Id="sortable")
+
+ descriptionTable = HT.TableLite(border=0, cellpadding=0, cellspacing=0)
+ descriptionTable.append(HT.TR(HT.TD(reportTable, colspan=3)))
+ descriptionTable.append(HT.TR(HT.TD(HT.BR(),HT.BR())))
+ descriptionTable.append(bottomInfo)
+
+ # get each chr's length
+ self.ChrLengthMbList = map(lambda x: x/1000000.0, self.ChrLengthMbList) # change unit from bp to mb
+ self.ChrLengthMbSum = reduce(lambda x, y:x+y, self.ChrLengthMbList, 0.0)# get total length of all chrs
+ if self.ChrLengthMbList:
+ self.GraphInterval = self.ChrLengthMbSum/(len(self.ChrLengthMbList)*12) #Empirical Mb interval
+ else:
+ self.GraphInterval = 1
+
+ # for human data, there's no CM value
+ self.ChrLengthCMList = []
+ self.ChrLengthCMSum = 0
+
+ # begin: common part with human data
+ intCanvas = pid.PILCanvas(size=(self.graphWidth,self.graphHeight))
+ gifmap = self.plotIntMappingForPLINK(fd, intCanvas, startMb = self.startMb, endMb = self.endMb, plinkResultDict=plinkResultDict)
+
+ intCanvas.save(os.path.join(webqtlConfig.IMGDIR, filename), format='png')
+ intImg=HT.Image('/image/'+filename+'.png', border=0, usemap='#WebQTLImageMap')
+
+ TD_LR = HT.TR(HT.TD(HT.Blockquote(gifmap,intImg, HT.P()), bgColor='#eeeeee', height = 200))
+ self.dict['body'] = str(headerdiv)+str(TD_LR)+str(resultstable)+str(HT.TR(HT.TD(descriptionTable)))
+
+ else:
+ heading = "Genome Association"
+ detail = ['There is no association with marker that meets this criteria. Please provide a less stringend threshold. The minimun p-value is %s.'%minPvalue]
+ self.error(heading=heading,detail=detail)
+ return
+
+ elif self.mappingMethodId == '1': # QTLreaper result
+ if not fd.genotype:
+ fd.readData()
+
+ fd.parentsf14regression = fd.formdata.getvalue('parentsf14regression')
+ weightedRegression = fd.formdata.getvalue('applyVarianceSE')
+
+ if fd.parentsf14regression and fd.genotype_2:
+ _genotype = fd.genotype_2
+ else:
+ _genotype = fd.genotype_1
+
+ _strains, _vals, _vars, N = fd.informativeStrains(_genotype.prgy, weightedRegression)
+
+ if fd.identification:
+ heading2 = HT.Paragraph('Trait ID: %s' % fd.identification)
+ heading2.__setattr__("class","subtitle")
+ self.dict['title'] = '%s: Genome Association' % fd.identification
+ else:
+ heading2 = ""
+ self.dict['title'] = 'Genome Association'
+
+ if fd.traitInfo:
+ symbol,chromosome,MB = string.split(fd.traitInfo,'\t')
+ heading3 = HT.Paragraph('[ ',HT.Strong(HT.Italic('%s' % symbol,id="green")),' on Chr %s @ %s Mb ]' % (chromosome,MB))
+ else:
+ heading3 = ""
+
+ if N < webqtlConfig.KMININFORMATIVE:
+ heading = "Genome Association"
+ detail = ['Fewer than %d strain data were entered for %s data set. No mapping attempted.' % (webqtlConfig.KMININFORMATIVE, fd.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = HT.Paragraph('Trait Data Entered for %s Set' % fd.RISet)
+ heading.__setattr__("class","title")
+
+ datadiv = HT.TD(heading, heading2,heading3, width='45%',valign='top', align='left', bgColor='#eeeeee')
+ resultstable,tblobj,bottomInfo = self.GenReport(ChrNameOrderIdDict,fd, _genotype, _strains, _vals, _vars)
+ #resultstable = self.GenReport(fd, _genotype, _strains, _vals, _vars)
+
+ # creat object for result table for sort function
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ sortby = ("Index", "up")
+ reportTable =HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "0"), Id="sortable")
+
+ descriptionTable = HT.TableLite(border=0, cellpadding=0, cellspacing=0)
+ descriptionTable.append(HT.TR(HT.TD(reportTable, colspan=3)))
+ descriptionTable.append(HT.TR(HT.TD(HT.BR(),HT.BR())))
+ descriptionTable.append(bottomInfo)
+
+ self.traitList=_vals
+
+ ##########################plot#######################
+
+ ################################################################
+ # Generate Chr list and Retrieve Length Information
+ ################################################################
+ self.genotype= _genotype
+ self.ChrList = [("All", -1)]
+
+ for i, indChr in enumerate(self.genotype):
+ self.ChrList.append((indChr.name, i))
+
+ self.cursor.execute("""
+ Select
+ Length from Chr_Length, InbredSet
+ where
+ Chr_Length.SpeciesId = InbredSet.SpeciesId AND
+ InbredSet.Name = '%s' AND
+ Chr_Length.Name in (%s)
+ Order by
+ OrderId
+ """ % (fd.RISet, string.join(map(lambda X: "'%s'" % X[0], self.ChrList[1:]), ", ")))
+
+ self.ChrLengthMbList = self.cursor.fetchall()
+ self.ChrLengthMbList = map(lambda x: x[0]/1000000.0, self.ChrLengthMbList)
+ self.ChrLengthMbSum = reduce(lambda x, y:x+y, self.ChrLengthMbList, 0.0)
+ if self.ChrLengthMbList:
+ self.MbGraphInterval = self.ChrLengthMbSum/(len(self.ChrLengthMbList)*12) #Empirical Mb interval
+ else:
+ self.MbGraphInterval = 1
+
+ self.ChrLengthCMList = []
+ for i, _chr in enumerate(self.genotype):
+ self.ChrLengthCMList.append(_chr[-1].cM - _chr[0].cM)
+ self.ChrLengthCMSum = reduce(lambda x, y:x+y, self.ChrLengthCMList, 0.0)# used for calculate plot scale
+
+ self.GraphInterval = self.MbGraphInterval #Mb
+
+ # begin: common part with human data
+ intCanvas = pid.PILCanvas(size=(self.graphWidth,self.graphHeight))
+ gifmap = self.plotIntMapping(fd, intCanvas, startMb = self.startMb, endMb = self.endMb, showLocusForm= "")
+ filename= webqtlUtil.genRandStr("Itvl_")
+ intCanvas.save(os.path.join(webqtlConfig.IMGDIR, filename), format='png')
+ intImg=HT.Image('/image/'+filename+'.png', border=0, usemap='#WebQTLImageMap')
+
+ ################################################################
+ # footnote goes here
+ ################################################################
+ btminfo = HT.Paragraph(Id="smallsize") #Small('More information about this graph is available here.')
+
+ if (self.additiveChecked):
+ btminfo.append(HT.BR(), 'A positive additive coefficient (', HT.Font('green', color='green'), ' line) indicates that %s alleles increase trait values. In contrast, a negative additive coefficient (' % fd.ppolar, HT.Font('red', color='red'), ' line) indicates that %s alleles increase trait values.' % fd.mpolar)
+
+
+ TD_LR = HT.TR(HT.TD(HT.Blockquote(gifmap,intImg, HT.P()), bgColor='#eeeeee', height = 200))
+
+ self.dict['body'] = str(datadiv)+str(TD_LR)+str(resultstable)+str(HT.TR(HT.TD(descriptionTable)))
+
+ # end: common part with human data
+
+ else:
+ pass
+
+
+ # add by NL 10-2-2011
+ def initializeParameters(self, fd):
+ """
+ Initializes all of the MarkerRegressionPage class parameters,
+ acquiring most values from the formdata (fd)
+ """
+ ###################################
+ # manhattam plot parameters
+ ###################################
+
+ self.graphHeight = 600
+ self.graphWidth = 1280
+ self.plotScale = 'physic'
+ self.selectedChr = -1
+ self.GRAPH_BACK_DARK_COLOR = pid.HexColor(0xF1F1F9)
+ self.GRAPH_BACK_LIGHT_COLOR = pid.HexColor(0xFBFBFF)
+ self.LRS_COLOR = pid.HexColor(0x0000FF)
+ self.LRS_LOD ='LRS'
+ self.lrsMax = float(fd.formdata.getvalue('lrsMax', 0))
+ self.startMb = fd.formdata.getvalue('startMb', "-1")
+ self.endMb = fd.formdata.getvalue('endMb', "-1")
+ self.mappingMethodId = fd.formdata.getvalue('mappingMethodId', "0")
+ self.permChecked=True
+ self.multipleInterval=False
+ self.SIGNIFICANT_WIDTH = 5
+ self.SUGGESTIVE_WIDTH = 5
+ self.SIGNIFICANT_COLOR = pid.HexColor(0xEBC7C7)
+ self.SUGGESTIVE_COLOR = pid.gainsboro
+ self.colorCollection = [self.LRS_COLOR]
+ self.additiveChecked= True
+ self.ADDITIVE_COLOR_POSITIVE = pid.green
+ self.legendChecked =False
+ self.pValue=float(fd.formdata.getvalue('pValue',-1))
+
+ # allow user to input p-value greater than 1,
+ # in this case, the value will be treated as -lgP value. so the input value needs to be transferred to power of 10 format
+ if self.pValue >1:
+ self.pValue =10**-(self.pValue)
+
+ try:
+ self.startMb = float(self.startMb)
+ self.endMb = float(self.endMb)
+ if self.startMb > self.endMb:
+ temp = self.startMb
+ self.startMb = self.endMb
+ self.endMb = temp
+ #minimal distance 10bp
+ if self.endMb - self.startMb < 0.00001:
+ self.endMb = self.startMb + 0.00001
+ except:
+ self.startMb = self.endMb = -1
+
+ def GenReportForPLINK(self, ChrNameOrderIdDict={},RISet='',plinkResultDict= {},thresholdPvalue=-1,chrList=[]):
+
+ 'Create an HTML division which reports any loci which are significantly associated with the submitted trait data.'
+ #########################################
+ # Genome Association report
+ #########################################
+ locusFormName = webqtlUtil.genRandStr("fm_")
+ locusForm = HT.Form(cgi = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), \
+ enctype='multipart/form-data', name=locusFormName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':RISet+"Geno",'CellID':'_', \
+ 'RISet':RISet, 'incparentsf1':'on'}
+ for key in hddn.keys():
+ locusForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ regressionHeading = HT.Paragraph('Genome Association Report')
+ regressionHeading.__setattr__("class","title")
+
+ filename= webqtlUtil.genRandStr("GenomeAsscociation_")
+ fpText = open('%s.txt' % (webqtlConfig.TMPDIR+filename), 'wb')
+ fpText.write('The loci meet the criteria of P-Value <= %3.6f.\n'%thresholdPvalue)
+ pValueInfo =HT.Paragraph('The loci meet the criteria of P-Value <= %3.6f.\n'%thresholdPvalue)
+
+ textUrl = HT.Href(text = 'Download', url= '/tmp/'+filename+'.txt', target = "_blank", Class='fs12 fwn')
+ bottomInfo = HT.TR(HT.TD(HT.Paragraph(textUrl, ' result in tab-delimited text format.', HT.BR(), HT.BR(),Class="fs12 fwn"), colspan=3))
+
+ tblobj={} # build dict for genTableObj function; keys include header and body
+ tblobj_header = [] # value of key 'header'
+ tblobj_body=[] # value of key 'body'
+ reportHeaderRow=[] # header row list for tblobj_header (html part)
+ headerList=['Index','SNP Name','Chr','Mb','-log(P)']
+ headerStyle="fs14 fwb ffl b1 cw cbrb" # style of the header
+ cellColorStyle = "fs13 b1 fwn c222" # style of the cells
+
+ if headerList:
+ for ncol, item in enumerate(headerList):
+ reportHeaderRow.append(THCell(HT.TD(item, Class=headerStyle, valign='bottom',nowrap='ON'),text=item, idx=ncol))
+ #download file for table headers' names
+ fpText.write('SNP_Name\tChromosome\tMb\t-log(P)\n')
+
+ tblobj_header.append(reportHeaderRow)
+ tblobj['header']=tblobj_header
+
+ index=1
+ for chr in chrList:
+
+ if plinkResultDict.has_key(chr):
+ if chr in ChrNameOrderIdDict.keys():
+ chrOrderId =ChrNameOrderIdDict[chr]
+ else:
+ chrOrderId=chr
+
+ valueList=plinkResultDict[chr]
+
+ for value in valueList:
+ reportBodyRow=[] # row list for tblobj_body (html part)
+ snpName=value[0]
+ bp=value[1]
+ mb=int(bp)/1000000.0
+
+ try:
+ pValue =float(value[2])
+ except:
+ pValue =1
+ formattedPvalue = -math.log10(pValue)
+
+ formattedPvalue = webqtlUtil.SciFloat(formattedPvalue)
+ dbSnprs=snpName.replace('rs','')
+ SnpHref = HT.Href(text=snpName, url="http://www.ncbi.nlm.nih.gov/projects/SNP/snp_ref.cgi?rs=%s"%dbSnprs, target="_blank")
+
+ selectCheck=HT.Input(type="checkbox", Class="checkbox", name="index",value=index, onClick="highlight(this)")
+ reportBodyRow.append(TDCell(HT.TD(str(index),selectCheck, align='right',Class=cellColorStyle,nowrap='ON'),str(index),index))
+ reportBodyRow.append(TDCell(HT.TD(SnpHref, Class=cellColorStyle,nowrap='ON'),snpName, snpName))
+ reportBodyRow.append(TDCell(HT.TD(chr, Class=cellColorStyle, align="center",nowrap='ON'),chr, chrOrderId))
+ reportBodyRow.append(TDCell(HT.TD('%3.6f'%mb, Class=cellColorStyle, align="center",nowrap='ON'),mb, mb))
+ reportBodyRow.append(TDCell(HT.TD(formattedPvalue, Class=cellColorStyle, align="center",nowrap='ON'),formattedPvalue, float(formattedPvalue)))
+
+ fpText.write('%s\t%s\t%3.6f\t%s\n' % (snpName, str(chr), mb, formattedPvalue))
+ index+=1
+
+ tblobj_body.append(reportBodyRow)
+
+ tblobj['body']=tblobj_body
+ rv=HT.TR(HT.TD(regressionHeading,pValueInfo, locusForm, HT.P(), width='55%',valign='top', align='left',bgColor='#eeeeee'))
+
+ return rv, tblobj,bottomInfo
+
+
+ def GenReport(self, ChrNameOrderIdDict,fd, _genotype, _strains, _vals, _vars= []):
+ 'Create an HTML division which reports any loci which are significantly associated with the submitted trait data.'
+ #calculate QTL for each trait
+ self.qtlresults = []
+ if webqtlUtil.ListNotNull(_vars):
+ qtlresults = _genotype.regression(strains = _strains, trait = _vals, variance = _vars)
+ LRSArray = _genotype.permutation(strains = _strains, trait = _vals, variance = _vars, nperm=fd.nperm)
+ else:
+ qtlresults = _genotype.regression(strains = _strains, trait = _vals)
+ LRSArray = _genotype.permutation(strains = _strains, trait = _vals,nperm=fd.nperm)
+
+ self.qtlresults.append(qtlresults)
+
+ filename= webqtlUtil.genRandStr("GenomeAsscociation_")
+
+ # set suggestive, significant and highly significant LRS
+ if fd.suggestive == None:
+ fd.suggestive = LRSArray[int(fd.nperm*0.37-1)]
+ else:
+ fd.suggestive = float(fd.suggestive)
+ if fd.significance == None:
+ fd.significance = LRSArray[int(fd.nperm*0.95-1)]
+ else:
+ fd.significance = float(fd.significance)
+
+ self.significance =fd.significance
+ self.suggestive = fd.suggestive
+ self.highlysignificant = LRSArray[int(fd.nperm*0.99-1)]
+ _dispAllLRS = 0
+ if fd.formdata.getvalue('displayAllLRS'):
+ _dispAllLRS = 1
+ qtlresults2 = []
+ if _dispAllLRS:
+ filtered = qtlresults[:]
+ else:
+ filtered = filter(lambda x, y=fd.suggestive: x.lrs > y, qtlresults)
+ if len(filtered) == 0:
+ qtlresults2 = qtlresults[:]
+ qtlresults2.sort()
+ filtered = qtlresults2[-10:]
+
+
+
+ #########################################
+ # Genome Association report
+ #########################################
+ locusFormName = webqtlUtil.genRandStr("fm_")
+ locusForm = HT.Form(cgi = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), \
+ enctype='multipart/form-data', name=locusFormName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_', \
+ 'RISet':fd.RISet, 'incparentsf1':'on'}
+ for key in hddn.keys():
+ locusForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ regressionHeading = HT.Paragraph('Genome Association Report')
+ regressionHeading.__setattr__("class","title")
+ # report is the info part above report table
+ if qtlresults2 != []:
+ report = HT.Blockquote(HT.Font('No association ',color="#FF0000"),HT.Font('with a likelihood ratio statistic greater than %3.1f was found. Here are the top 10 LRSs.' % fd.suggestive,color="#000000"))
+ else:
+ report = HT.Blockquote('The following loci in the %s data set have associations with the above trait data.\n' % fd.RISet, HT.P())
+ report.__setattr__("class","normalsize")
+
+ fpText = open('%s.txt' % (webqtlConfig.TMPDIR+filename), 'wb')
+ fpText.write('Suggestive LRS =%3.2f\n'%self.suggestive)
+ fpText.write('Significant LRS =%3.2f\n'%self.significance)
+ fpText.write('Highly Significant LRS =%3.2f\n'%self.highlysignificant)
+ LRSInfo =HT.Paragraph('&nbsp;&nbsp;&nbsp;&nbsp;Suggestive LRS =%3.2f\n'%fd.suggestive, HT.BR(), '&nbsp;&nbsp;&nbsp;&nbsp;Significant LRS =%3.2f\n'%fd.significance,HT.BR(),'&nbsp;&nbsp;&nbsp;&nbsp;Highly Significant LRS =%3.2f\n' % self.highlysignificant)
+
+ textUrl = HT.Href(text = 'Download', url= '/tmp/'+filename+'.txt', target = "_blank", Class='fs12 fwn')
+
+ bottomInfo = HT.TR(HT.TD(HT.Paragraph(textUrl, ' result in tab-delimited text format.', HT.BR(), HT.BR(),'LRS values marked with',HT.Font(' * ',color="red"), 'are greater than the significance threshold (specified by you or by permutation test). ' , HT.BR(), HT.BR(), HT.Strong('Additive Effect'), ' is half the difference in the mean phenotype of all cases that are homozygous for one parental allel at this marker minus the mean of all cases that are homozygous for the other parental allele at this marker. ','In the case of %s strains, for example,' % fd.RISet,' A positive additive effect indicates that %s alleles increase trait values. Negative additive effect indicates that %s alleles increase trait values.'% (fd.ppolar,fd.mpolar),Class="fs12 fwn")))
+
+ tblobj={} # build dict for genTableObj function; keys include header and body
+ tblobj_header = [] # value of key 'header'
+ tblobj_body=[] # value of key 'body'
+ reportHeaderRow=[] # header row list for tblobj_header (html part)
+ headerStyle="fs14 fwb ffl b1 cw cbrb" # style of the header
+ cellColorStyle = "fs13 b1 fwn c222" # style of the cells
+
+ headerList=['Index','LRS','Chr','Mb','Locus','Additive Effect']
+ for ncol, item in enumerate(headerList):
+ reportHeaderRow.append(THCell(HT.TD(item, Class=headerStyle, valign='bottom',nowrap='ON'),text=item, idx=ncol))
+
+ if fd.genotype.type == 'intercross':
+ ncol =len(headerList)
+ reportHeaderRow.append(THCell(HT.TD('Dominance Effect', Class=headerStyle, valign='bottom',nowrap='ON'),text='Dominance Effect', idx=ncol))
+
+ #download file for table headers' names
+ fpText.write('LRS\tChromosome\tMb\tLocus\tAdditive Effect\tDominance Effect\n')
+
+ index=1
+ for ii in filtered:
+ #add by NL 06-20-2011: set LRS to 460 when LRS is infinite,
+ if ii.lrs==float('inf') or ii.lrs>webqtlConfig.MAXLRS:
+ LRS=webqtlConfig.MAXLRS #maximum LRS value
+ else:
+ LRS=ii.lrs
+
+ if LRS > fd.significance:
+ lrs = HT.TD(HT.Font('%3.3f*' % LRS, color='#FF0000'),Class=cellColorStyle)
+ else:
+ lrs = HT.TD('%3.3f' % LRS,Class=cellColorStyle)
+
+ if ii.locus.chr in ChrNameOrderIdDict.keys():
+ chrOrderId =ChrNameOrderIdDict[ii.locus.chr]
+ else:
+ chrOrderId=ii.locus.chr
+
+ reportBodyRow=[] # row list for tblobj_body (html part)
+ selectCheck=HT.Input(type="checkbox", Class="checkbox", name="index",value=index, onClick="highlight(this)")
+ reportBodyRow.append(TDCell(HT.TD(str(index),selectCheck, align='right',Class=cellColorStyle,nowrap='ON'),str(index),index))
+ reportBodyRow.append(TDCell(lrs,LRS, LRS))
+ reportBodyRow.append(TDCell(HT.TD(ii.locus.chr, Class=cellColorStyle, align="center",nowrap='ON'),ii.locus.chr, chrOrderId))
+ reportBodyRow.append(TDCell(HT.TD('%3.6f'%ii.locus.Mb, Class=cellColorStyle, align="center",nowrap='ON'),ii.locus.Mb, ii.locus.Mb))
+ reportBodyRow.append(TDCell(HT.TD(HT.Href(text=ii.locus.name, url = "javascript:showTrait('%s','%s');" % (locusFormName, ii.locus.name), Class='normalsize'), Class=cellColorStyle, align="center",nowrap='ON'),ii.locus.name, ii.locus.name))
+ reportBodyRow.append(TDCell(HT.TD('%3.3f' % ii.additive, Class=cellColorStyle, align="center",nowrap='ON'),ii.additive, ii.additive))
+ reportBodyRow.append(TDCell(HT.TD('%3.3f' % ii.dominance, Class=cellColorStyle, align="center",nowrap='ON'),ii.dominance, ii.dominance))
+
+ fpText.write('%2.3f\t%s\t%3.6f\t%s\t%2.3f\t%2.3f\n' % (LRS, ii.locus.chr, ii.locus.Mb, ii.locus.name, ii.additive, ii.dominance))
+ index+=1
+ tblobj_body.append(reportBodyRow)
+ else:
+ #download file for table headers' names
+ fpText.write('LRS\tChromosome\tMb\tLocus\tAdditive Effect\n')
+
+ index=1
+ for ii in filtered:
+ #add by NL 06-20-2011: set LRS to 460 when LRS is infinite,
+ if ii.lrs==float('inf') or ii.lrs>webqtlConfig.MAXLRS:
+ LRS=webqtlConfig.MAXLRS #maximum LRS value
+ else:
+ LRS=ii.lrs
+
+ if LRS > fd.significance:
+ lrs = HT.TD(HT.Font('%3.3f*' % LRS, color='#FF0000'),Class=cellColorStyle)
+ else:
+ lrs = HT.TD('%3.3f' % LRS,Class=cellColorStyle)
+
+ if ii.locus.chr in ChrNameOrderIdDict.keys():
+ chrOrderId =ChrNameOrderIdDict[ii.locus.chr]
+ else:
+ chrOrderId=ii.locus.chr
+
+ reportBodyRow=[] # row list for tblobj_body (html part)
+ selectCheck=HT.Input(type="checkbox", Class="checkbox", name="index",value=index, onClick="highlight(this)")
+ reportBodyRow.append(TDCell(HT.TD(str(index),selectCheck, align='right',Class=cellColorStyle,nowrap='ON'),str(index),index))
+ reportBodyRow.append(TDCell(lrs,LRS, LRS))
+ reportBodyRow.append(TDCell(HT.TD(ii.locus.chr, Class=cellColorStyle, align="center",nowrap='ON'),ii.locus.chr, chrOrderId))
+ reportBodyRow.append(TDCell(HT.TD('%3.6f'%ii.locus.Mb, Class=cellColorStyle, align="center",nowrap='ON'),ii.locus.Mb, ii.locus.Mb))
+ reportBodyRow.append(TDCell(HT.TD(HT.Href(text=ii.locus.name, url = "javascript:showTrait('%s','%s');" % (locusFormName, ii.locus.name), Class='normalsize'), Class=cellColorStyle, align="center",nowrap='ON'),ii.locus.name, ii.locus.name))
+ reportBodyRow.append(TDCell(HT.TD('%3.3f' % ii.additive, Class=cellColorStyle, align="center",nowrap='ON'),ii.additive, ii.additive))
+
+ fpText.write('%2.3f\t%s\t%3.6f\t%s\t%2.3f\n' % (LRS, ii.locus.chr, ii.locus.Mb, ii.locus.name, ii.additive))
+ index+=1
+ tblobj_body.append(reportBodyRow)
+
+ tblobj_header.append(reportHeaderRow)
+ tblobj['header']=tblobj_header
+ tblobj['body']=tblobj_body
+
+ rv=HT.TD(regressionHeading,LRSInfo,report, locusForm, HT.P(),width='55%',valign='top', align='left', bgColor='#eeeeee')
+ if fd.genotype.type == 'intercross':
+ bottomInfo.append(HT.BR(), HT.BR(), HT.Strong('Dominance Effect'),' is the difference between the mean trait value of cases heterozygous at a marker and the average mean for the two groups homozygous at this marker: e.g., BD - (BB+DD)/2]. A positive dominance effect indicates that the average phenotype of BD heterozygotes exceeds the mean of BB and DD homozygotes. No dominance deviation can be computed for a set of recombinant inbred strains or for a backcross.')
+ return rv,tblobj,bottomInfo
+
+ return rv,tblobj,bottomInfo
+
+ def plotIntMappingForPLINK(self, fd, canvas, offset= (80, 120, 20, 80), zoom = 1, startMb = None, endMb = None, showLocusForm = "",plinkResultDict={}):
+ #calculating margins
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ xLeftOffset = int(xLeftOffset*fontZoom)
+ xRightOffset = int(xRightOffset*fontZoom)
+ yBottomOffset = int(yBottomOffset*fontZoom)
+
+ cWidth = canvas.size[0]
+ cHeight = canvas.size[1]
+ plotWidth = cWidth - xLeftOffset - xRightOffset
+ plotHeight = cHeight - yTopOffset - yBottomOffset
+ startPixelX = xLeftOffset
+ endPixelX = (xLeftOffset + plotWidth)
+
+ #Drawing Area Height
+ drawAreaHeight = plotHeight
+ if self.plotScale == 'physic' and self.selectedChr > -1: # for single chr
+ drawAreaHeight -= self.ENSEMBL_BAND_HEIGHT + self.UCSC_BAND_HEIGHT+ self.WEBQTL_BAND_HEIGHT + 3*self.BAND_SPACING+ 10*zoom
+ if self.geneChecked:
+ drawAreaHeight -= self.NUM_GENE_ROWS*self.EACH_GENE_HEIGHT + 3*self.BAND_SPACING + 10*zoom
+ else:
+ if self.selectedChr > -1:
+ drawAreaHeight -= 20
+ else:# for all chrs
+ drawAreaHeight -= 30
+
+ #Image map
+ gifmap = HT.Map(name='WebQTLImageMap')
+
+ newoffset = (xLeftOffset, xRightOffset, yTopOffset, yBottomOffset)
+ # Draw the alternating-color background first and get plotXScale
+ plotXScale = self.drawGraphBackgroundForPLINK(canvas, gifmap, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb,plinkResultDict=plinkResultDict)
+
+ # Draw X axis
+ self.drawXAxisForPLINK(fd, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+ # Draw manhattam plot
+ self.drawManhattanPlotForPLINK(canvas, drawAreaHeight, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb,plinkResultDict=plinkResultDict,thresholdPvalue=self.pValue)
+
+ return gifmap
+
+
+ def plotIntMapping(self, fd, canvas, offset= (80, 120, 20, 80), zoom = 1, startMb = None, endMb = None, showLocusForm = ""):
+ #calculating margins
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ xLeftOffset = int(xLeftOffset*fontZoom)
+ xRightOffset = int(xRightOffset*fontZoom)
+ yBottomOffset = int(yBottomOffset*fontZoom)
+
+ cWidth = canvas.size[0]
+ cHeight = canvas.size[1]
+ plotWidth = cWidth - xLeftOffset - xRightOffset
+ plotHeight = cHeight - yTopOffset - yBottomOffset
+ startPixelX = xLeftOffset
+ endPixelX = (xLeftOffset + plotWidth)
+
+ #Drawing Area Height
+ drawAreaHeight = plotHeight
+ if self.plotScale == 'physic' and self.selectedChr > -1: # for single chr
+ drawAreaHeight -= self.ENSEMBL_BAND_HEIGHT + self.UCSC_BAND_HEIGHT+ self.WEBQTL_BAND_HEIGHT + 3*self.BAND_SPACING+ 10*zoom
+ if self.geneChecked:
+ drawAreaHeight -= self.NUM_GENE_ROWS*self.EACH_GENE_HEIGHT + 3*self.BAND_SPACING + 10*zoom
+ else:# for all chrs
+ if self.selectedChr > -1:
+ drawAreaHeight -= 20
+ else:
+ drawAreaHeight -= 30
+
+ #Image map
+ gifmap = HT.Map(name='WebQTLImageMap')
+
+ newoffset = (xLeftOffset, xRightOffset, yTopOffset, yBottomOffset)
+ # Draw the alternating-color background first and get plotXScale
+ plotXScale = self.drawGraphBackground(canvas, gifmap, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+
+ # Draw X axis
+ self.drawXAxis(fd, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+ # Draw QTL curve
+ self.drawQTL(canvas, drawAreaHeight, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb)
+
+ #draw legend
+ if self.multipleInterval:
+ self.drawMultiTraitName(fd, canvas, gifmap, showLocusForm, offset=newoffset)
+ elif self.legendChecked:
+ self.drawLegendPanel(fd, canvas, offset=newoffset)
+ else:
+ pass
+
+ #draw position, no need to use a separate function
+ if fd.genotype.Mbmap:
+ self.drawProbeSetPosition(canvas, plotXScale, offset=newoffset)
+
+ return gifmap
+
+
+ # functions for manhattam plot of markers
+ def drawManhattanPlotForPLINK(self, canvas, drawAreaHeight, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None,plinkResultDict={},thresholdPvalue=-1):
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ # INTERCROSS = (self.genotype.type=="intercross")
+ INTERCROSS ='' #??????
+
+ ChrLengthDistList = self.ChrLengthMbList
+ drawRegionDistance = self.ChrLengthMbSum
+ GraphInterval=self.GraphInterval
+ pvalueHeightThresh = drawAreaHeight - 80 #ZS: Otherwise the plot gets very close to the chromosome labels
+
+ #draw the pvalue scale
+ #We first determine whether or not we are using a sliding scale.
+ #If so, we need to compute the maximum pvalue value to determine where the max y-value should be, and call this pvalueMax.
+ #pvalueTop is then defined to be above the pvalueMax by enough to add one additional pvalueScale increment.
+ #if we are using a set-scale, then we set pvalueTop to be the user's value, and pvalueMax doesn't matter.
+
+ # for human data we use p value instead of lrs
+ pValueList=[]
+ for key in plinkResultDict:
+ valueList = plinkResultDict[key]
+ for item in valueList:
+ pValue = item[-1]
+ pValueList.append(pValue)
+
+ formattedPValueList=[]
+ for pValue in pValueList:
+ try:
+ pValue=float(pValue)
+ except:
+ pValue =1
+ formattedpValue = -math.log10(pValue)
+ formattedPValueList.append(formattedpValue)
+
+ #sliding scale
+ pvalueMax = max(formattedPValueList)
+ #pvalueMax =pvalueMax +1
+ # no permutation result for plink func: GenReport()
+ pvalueMin = int(-math.log10(thresholdPvalue))
+
+ if pvalueMax> 100:
+ pvalueScale = 20.0
+ elif pvalueMax > 20:
+ pvalueScale = 5.0
+ elif pvalueMax > 7.5:
+ pvalueScale = 2.5
+ else:
+ pvalueScale = 1.0
+
+ # the base line for x-axis is -log(thresholdPvalue)
+ pvalueAxisList = Plot.frange(pvalueMin, pvalueMax, pvalueScale)
+ #make sure the user's value appears on the y-axis
+ #ZS: There is no way to do this without making the position of the points not directly proportional to a given distance on the y-axis
+ #tempPvalueMax=round(pvalueMax)
+ tempPvalueMax = pvalueAxisList[len(pvalueAxisList)-1] + pvalueScale
+ pvalueAxisList.append(tempPvalueMax)
+
+ #ZS: I don't understand this; the if statement will be true for any number that isn't exactly X.5.
+ #if abs(tempPvalueMax-pvalueMax) <0.5:
+ # tempPvalueMax=tempPvalueMax+1
+ # pvalueAxisList.append(tempPvalueMax)
+
+ #draw the "pvalue" string to the left of the axis
+ pvalueScaleFont=pid.Font(ttf="verdana", size=14*fontZoom, bold=0)
+ pvalueLODFont=pid.Font(ttf="verdana", size=14*zoom*1.5, bold=0)
+ yZero = yTopOffset + plotHeight
+
+ #yAxis label display area
+ yAxis_label ='-log(P)'
+ canvas.drawString(yAxis_label, xLeftOffset - canvas.stringWidth("999.99", font=pvalueScaleFont) - 10*zoom, \
+ yZero - 150, font=pvalueLODFont, color=pid.black, angle=90)
+
+ for i,item in enumerate(pvalueAxisList):
+ ypvalue = yZero - (float(i)/float(len(pvalueAxisList) - 1)) * pvalueHeightThresh
+ canvas.drawLine(xLeftOffset, ypvalue, xLeftOffset - 4, ypvalue, color=self.LRS_COLOR, width=1*zoom)
+ scaleStr = "%2.1f" % item
+ #added by NL 6-24-2011:Y-axis scale display
+ canvas.drawString(scaleStr, xLeftOffset-4-canvas.stringWidth(scaleStr, font=pvalueScaleFont)-5, ypvalue+3, font=pvalueScaleFont, color=self.LRS_COLOR)
+
+ ChrList=self.ChrList
+ startPosX = xLeftOffset
+
+ for i, chr in enumerate(ChrList):
+
+ if plinkResultDict.has_key(chr):
+ plinkresultList = plinkResultDict[chr]
+
+ m = 0
+ #add by NL 06-24-2011: for mahanttam plot
+ symbolFont = pid.Font(ttf="fnt_bs", size=5,bold=0)
+ # color for point in each chr
+ chrCount=len(ChrList)
+ chrColorDict =self.getColorForMarker(chrCount=chrCount,flag=1)
+ for j, item in enumerate(plinkresultList):
+ try :
+ mb=float(item[1])/1000000.0
+ except:
+ mb=0
+
+ try :
+ pvalue =float(item[-1])
+ except:
+ pvalue =1
+
+ try:
+ snpName = item[0]
+ except:
+ snpName=''
+
+ formattedPvalue = -math.log10(pvalue)
+
+ Xc = startPosX + (mb-startMb)*plotXScale
+ Yc = yZero - (formattedPvalue-pvalueMin)*pvalueHeightThresh/(tempPvalueMax - pvalueMin)
+ canvas.drawString("5", Xc-canvas.stringWidth("5",font=symbolFont)/2+1,Yc+2,color=chrColorDict[i], font=symbolFont)
+ m += 1
+
+ startPosX += (ChrLengthDistList[i]+GraphInterval)*plotXScale
+
+ canvas.drawLine(xLeftOffset, yZero, xLeftOffset, yTopOffset, color=self.LRS_COLOR, width=1*zoom) #the blue line running up the y axis
+
+ def drawQTL(self, canvas, drawAreaHeight, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ INTERCROSS = (self.genotype.type=="intercross")
+
+ ChrLengthDistList = self.ChrLengthMbList
+ GraphInterval=self.GraphInterval
+ LRSHeightThresh = drawAreaHeight
+ AdditiveHeightThresh = drawAreaHeight/2
+ DominanceHeightThresh = drawAreaHeight/2
+
+ #draw the LRS scale
+ #We first determine whether or not we are using a sliding scale.
+ #If so, we need to compute the maximum LRS value to determine where the max y-value should be, and call this LRSMax.
+ #LRSTop is then defined to be above the LRSMax by enough to add one additional LRSScale increment.
+ #if we are using a set-scale, then we set LRSTop to be the user's value, and LRSMax doesn't matter.
+
+ if self.LRS_LOD == 'LOD':
+ lodm = self.LODFACTOR
+ else:
+ lodm = 1.0
+
+ if self.lrsMax <= 0: #sliding scale
+ LRSMax = max(map(max, self.qtlresults)).lrs
+ #genotype trait will give infinite LRS
+ LRSMax = min(LRSMax, webqtlConfig.MAXLRS)
+ LRSMax = max(self.significance, LRSMax)
+ else:
+ LRSMax = self.lrsMax*lodm
+
+ if LRSMax/lodm > 100:
+ LRSScale = 20.0
+ elif LRSMax/lodm > 20:
+ LRSScale = 5.0
+ elif LRSMax/lodm > 7.5:
+ LRSScale = 2.5
+ else:
+ LRSScale = 1.0
+
+ LRSAxisList = Plot.frange(LRSScale, LRSMax/lodm, LRSScale)
+ #make sure the user's value appears on the y-axis
+ #update by NL 6-21-2011: round the LOD value to 100 when LRSMax is equal to 460
+ LRSAxisList.append(round(LRSMax/lodm))
+
+ #draw the "LRS" or "LOD" string to the left of the axis
+ LRSScaleFont=pid.Font(ttf="verdana", size=14*fontZoom, bold=0)
+ LRSLODFont=pid.Font(ttf="verdana", size=14*zoom*1.5, bold=0)
+ yZero = yTopOffset + plotHeight
+
+ #yAxis label display area
+ canvas.drawString(self.LRS_LOD, xLeftOffset - canvas.stringWidth("999.99", font=LRSScaleFont) - 10*zoom, \
+ yZero - 150, font=LRSLODFont, color=pid.black, angle=90)
+
+ for item in LRSAxisList:
+ yLRS = yZero - (item*lodm/LRSMax) * LRSHeightThresh
+ canvas.drawLine(xLeftOffset, yLRS, xLeftOffset - 4, yLRS, color=self.LRS_COLOR, width=1*zoom)
+ scaleStr = "%2.1f" % item
+ #added by NL 6-24-2011:Y-axis scale display
+ canvas.drawString(scaleStr, xLeftOffset-4-canvas.stringWidth(scaleStr, font=LRSScaleFont)-5, yLRS+3, font=LRSScaleFont, color=self.LRS_COLOR)
+
+
+ #"Significant" and "Suggestive" Drawing Routine
+ # ======= Draw the thick lines for "Significant" and "Suggestive" ===== (crowell: I tried to make the SNPs draw over these lines, but piddle wouldn't have it...)
+ if self.permChecked and not self.multipleInterval:
+ significantY = yZero - self.significance*LRSHeightThresh/LRSMax
+ suggestiveY = yZero - self.suggestive*LRSHeightThresh/LRSMax
+
+
+ startPosX = xLeftOffset
+ for i, _chr in enumerate(self.genotype):
+ rightEdge = int(startPosX + self.ChrLengthDistList[i]*plotXScale - self.SUGGESTIVE_WIDTH/1.5)
+ #added by NL 6-24-2011:draw suggestive line (grey one)
+ canvas.drawLine(startPosX+self.SUGGESTIVE_WIDTH/1.5, suggestiveY, rightEdge, suggestiveY, color=self.SUGGESTIVE_COLOR,
+ width=self.SUGGESTIVE_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2))
+ #added by NL 6-24-2011:draw significant line (pink one)
+ canvas.drawLine(startPosX+self.SUGGESTIVE_WIDTH/1.5, significantY, rightEdge, significantY, color=self.SIGNIFICANT_COLOR,
+ width=self.SIGNIFICANT_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2))
+ sugg_coords = "%d, %d, %d, %d" % (startPosX, suggestiveY-2, rightEdge + 2*zoom, suggestiveY+2)
+ sig_coords = "%d, %d, %d, %d" % (startPosX, significantY-2, rightEdge + 2*zoom, significantY+2)
+ if self.LRS_LOD == 'LRS':
+ sugg_title = "Suggestive LRS = %0.2f" % self.suggestive
+ sig_title = "Significant LRS = %0.2f" % self.significance
+ else:
+ sugg_title = "Suggestive LOD = %0.2f" % (self.suggestive/4.61)
+ sig_title = "Significant LOD = %0.2f" % (self.significance/4.61)
+ Areas1 = HT.Area(shape='rect',coords=sugg_coords,title=sugg_title)
+ Areas2 = HT.Area(shape='rect',coords=sig_coords,title=sig_title)
+ gifmap.areas.append(Areas1)
+ gifmap.areas.append(Areas2)
+
+ startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale
+
+
+ if self.multipleInterval:
+ lrsEdgeWidth = 1
+ else:
+ additiveMax = max(map(lambda X : abs(X.additive), self.qtlresults[0]))
+ if INTERCROSS:
+ dominanceMax = max(map(lambda X : abs(X.dominance), self.qtlresults[0]))
+ else:
+ dominanceMax = -1
+ lrsEdgeWidth = 2
+ for i, qtlresult in enumerate(self.qtlresults):
+ m = 0
+ startPosX = xLeftOffset
+ thisLRSColor = self.colorCollection[i]
+
+ #add by NL 06-24-2011: for mahanttam plot
+ symbolFont = pid.Font(ttf="fnt_bs", size=5,bold=0)
+
+ for j, _chr in enumerate(self.genotype):
+ chrCount=len(self.genotype)
+ chrColorDict =self.getColorForMarker(chrCount=chrCount,flag=1)
+ LRSCoordXY = []
+ AdditiveCoordXY = []
+ DominanceCoordXY = []
+ for k, _locus in enumerate(_chr):
+ if self.plotScale == 'physic':
+ Xc = startPosX + (_locus.Mb-startMb)*plotXScale
+ else:
+ Xc = startPosX + (_locus.cM-_chr[0].cM)*plotXScale
+ # updated by NL 06-18-2011:
+ # fix the over limit LRS graph issue since genotype trait may give infinite LRS;
+ # for any lrs is over than 460(LRS max in this system), it will be reset to 460
+ if qtlresult[m].lrs> 460 or qtlresult[m].lrs=='inf':
+ Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/LRSMax
+ else:
+ Yc = yZero - qtlresult[m].lrs*LRSHeightThresh/LRSMax
+
+ LRSCoordXY.append((Xc, Yc))
+ #add by NL 06-24-2011: for mahanttam plot
+ #self.significance/4.61 consider chr and LOD
+ # significantY = yZero - self.significance*LRSHeightThresh/LRSMax
+ # if Yc >significantY:
+ # canvas.drawString(":", Xc-canvas.stringWidth(":",font=symbolFont)/2+1,Yc+2,color=pid.black, font=symbolFont)
+ # else:
+ # canvas.drawString(":", Xc-canvas.stringWidth(":",font=symbolFont)/2+1,Yc+2,color=pid.black, font=symbolFont)
+
+ # add by NL 06-27-2011: eliminate imputed value when locus name is equal to '-'
+ if (qtlresult[m].locus.name) and (qtlresult[m].locus.name!=' - '):
+ canvas.drawString("5", Xc-canvas.stringWidth("5",font=symbolFont)/2+1,Yc+2,color=chrColorDict[j], font=symbolFont)
+
+ if not self.multipleInterval and self.additiveChecked:
+ Yc = yZero - qtlresult[m].additive*AdditiveHeightThresh/additiveMax
+ AdditiveCoordXY.append((Xc, Yc))
+ if not self.multipleInterval and INTERCROSS and self.additiveChecked:
+ Yc = yZero - qtlresult[m].dominance*DominanceHeightThresh/dominanceMax
+ DominanceCoordXY.append((Xc, Yc))
+ m += 1
+
+ startPosX += (ChrLengthDistList[j]+GraphInterval)*plotXScale
+
+
+ ###draw additive scale
+ if not self.multipleInterval and self.additiveChecked:
+ additiveScaleFont=pid.Font(ttf="verdana",size=12*fontZoom,bold=0)
+ additiveScale = Plot.detScaleOld(0,additiveMax)
+ additiveStep = (additiveScale[1]-additiveScale[0])/additiveScale[2]
+ additiveAxisList = Plot.frange(0, additiveScale[1], additiveStep)
+ maxAdd = additiveScale[1]
+ addPlotScale = AdditiveHeightThresh/additiveMax
+
+ additiveAxisList.append(additiveScale[1])
+ for item in additiveAxisList:
+ additiveY = yZero - item*addPlotScale
+ canvas.drawLine(xLeftOffset + plotWidth,additiveY,xLeftOffset+4+ plotWidth,additiveY,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
+ scaleStr = "%2.3f" % item
+ canvas.drawString(scaleStr,xLeftOffset + plotWidth +6,additiveY+5,font=additiveScaleFont,color=self.ADDITIVE_COLOR_POSITIVE)
+
+ canvas.drawLine(xLeftOffset+plotWidth,additiveY,xLeftOffset+plotWidth,yZero,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
+
+ canvas.drawLine(xLeftOffset, yZero, xLeftOffset, yTopOffset, color=self.LRS_COLOR, width=1*zoom) #the blue line running up the y axis
+
+ def drawGraphBackgroundForPLINK(self, canvas, gifmap, offset= (80, 120, 80, 50), zoom = 1, startMb = None, endMb = None,plinkResultDict={} ):
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ #calculate plot scale
+ #XZ: all of these global variables should be passed from function signiture
+ ChrLengthDistList = self.ChrLengthMbList
+ drawRegionDistance = self.ChrLengthMbSum
+ GraphInterval=self.GraphInterval
+ ChrList =self.ChrList
+
+ #multiple chromosome view
+ plotXScale = plotWidth / ((len(ChrList)-1)*GraphInterval + drawRegionDistance)
+
+ startPosX = xLeftOffset
+ chrLabelFont=pid.Font(ttf="verdana",size=24*fontZoom,bold=0)
+
+ for i, _chr in enumerate(ChrList):
+
+ if (i % 2 == 0):
+ theBackColor = self.GRAPH_BACK_DARK_COLOR
+ else:
+ theBackColor = self.GRAPH_BACK_LIGHT_COLOR
+ # NL:resize chr width for drawing
+ if float(ChrLengthDistList[i])<90:
+ ChrLengthDistList[i]=90
+ #draw the shaded boxes and the sig/sug thick lines
+ canvas.drawRect(startPosX, yTopOffset, startPosX + ChrLengthDistList[i]*plotXScale, \
+ yTopOffset+plotHeight, edgeColor=pid.gainsboro,fillColor=theBackColor)
+
+ chrNameWidth = canvas.stringWidth(_chr, font=chrLabelFont)
+ chrStartPix = startPosX + (ChrLengthDistList[i]*plotXScale -chrNameWidth)/2
+ chrEndPix = startPosX + (ChrLengthDistList[i]*plotXScale +chrNameWidth)/2
+
+ canvas.drawString(_chr, chrStartPix, yTopOffset +20,font = chrLabelFont,color=pid.dimgray)
+ COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20)
+
+ #add by NL 09-03-2010
+ HREF = "javascript:changeView(%d,%s);" % (i,ChrLengthDistList)
+ Areas = HT.Area(shape='rect',coords=COORDS,href=HREF)
+ gifmap.areas.append(Areas)
+ startPosX += (ChrLengthDistList[i]+GraphInterval)*plotXScale
+
+ return plotXScale
+
+
+ def drawGraphBackground(self, canvas, gifmap, offset= (80, 120, 80, 50), zoom = 1, startMb = None, endMb = None):
+ ##conditions
+ ##multiple Chromosome view
+ ##single Chromosome Physical
+ ##single Chromosome Genetic
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ #calculate plot scale
+ if self.plotScale != 'physic':
+ self.ChrLengthDistList = self.ChrLengthCMList
+ drawRegionDistance = self.ChrLengthCMSum
+ else:
+ self.ChrLengthDistList = self.ChrLengthMbList
+ drawRegionDistance = self.ChrLengthMbSum
+
+ if self.selectedChr > -1: #single chromosome view
+ spacingAmt = plotWidth/13.5
+ i = 0
+ for startPix in Plot.frange(xLeftOffset, xLeftOffset+plotWidth, spacingAmt):
+ if (i % 2 == 0):
+ theBackColor = self.GRAPH_BACK_DARK_COLOR
+ else:
+ theBackColor = self.GRAPH_BACK_LIGHT_COLOR
+ i += 1
+ canvas.drawRect(startPix, yTopOffset, min(startPix+spacingAmt, xLeftOffset+plotWidth), \
+ yTopOffset+plotHeight, edgeColor=theBackColor, fillColor=theBackColor)
+
+ drawRegionDistance = self.ChrLengthDistList[self.selectedChr]
+ self.ChrLengthDistList = [drawRegionDistance]
+ if self.plotScale == 'physic':
+ plotXScale = plotWidth / (endMb-startMb)
+ else:
+ plotXScale = plotWidth / drawRegionDistance
+
+ else: #multiple chromosome view
+ plotXScale = plotWidth / ((len(self.genotype)-1)*self.GraphInterval + drawRegionDistance)
+
+ startPosX = xLeftOffset
+ chrLabelFont=pid.Font(ttf="verdana",size=24*fontZoom,bold=0)
+
+ for i, _chr in enumerate(self.genotype):
+
+ if (i % 2 == 0):
+ theBackColor = self.GRAPH_BACK_DARK_COLOR
+ else:
+ theBackColor = self.GRAPH_BACK_LIGHT_COLOR
+
+ #draw the shaded boxes and the sig/sug thick lines
+ canvas.drawRect(startPosX, yTopOffset, startPosX + self.ChrLengthDistList[i]*plotXScale, \
+ yTopOffset+plotHeight, edgeColor=pid.gainsboro,fillColor=theBackColor)
+
+ chrNameWidth = canvas.stringWidth(_chr.name, font=chrLabelFont)
+ chrStartPix = startPosX + (self.ChrLengthDistList[i]*plotXScale -chrNameWidth)/2
+ chrEndPix = startPosX + (self.ChrLengthDistList[i]*plotXScale +chrNameWidth)/2
+
+ canvas.drawString(_chr.name, chrStartPix, yTopOffset +20,font = chrLabelFont,color=pid.dimgray)
+ COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20)
+
+ #add by NL 09-03-2010
+ HREF = "javascript:changeView(%d,%s);" % (i,self.ChrLengthMbList)
+ Areas = HT.Area(shape='rect',coords=COORDS,href=HREF)
+ gifmap.areas.append(Areas)
+ startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale
+
+ return plotXScale
+
+ # XZ: The only difference of function drawXAxisForPLINK and function drawXAxis are the function name and the self.plotScale condition.
+ def drawXAxisForPLINK(self, fd, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ #Parameters
+ ChrLengthDistList = self.ChrLengthMbList
+ GraphInterval=self.GraphInterval
+
+ NUM_MINOR_TICKS = 5 # Number of minor ticks between major ticks
+ X_MAJOR_TICK_THICKNESS = 2
+ X_MINOR_TICK_THICKNESS = 1
+ X_AXIS_THICKNESS = 1*zoom
+
+ # ======= Alex: Draw the X-axis labels (megabase location)
+ MBLabelFont = pid.Font(ttf="verdana", size=12*fontZoom, bold=0)
+ xMajorTickHeight = 15 # How high the tick extends below the axis
+ xMinorTickHeight = 5*zoom
+ xAxisTickMarkColor = pid.black
+ xAxisLabelColor = pid.black
+ fontHeight = 12*fontZoom # How tall the font that we're using is
+ spacingFromLabelToAxis = 20
+ spacingFromLineToLabel = 3
+
+ if self.plotScale == 'physic':
+ strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont)
+ ###Physical single chromosome view
+ if self.selectedChr > -1:
+ graphMbWidth = endMb - startMb
+ XScale = Plot.detScale(startMb, endMb)
+ XStart, XEnd, XStep = XScale
+ if XStep < 8:
+ XStep *= 2
+ spacingAmtX = spacingAmt = (XEnd-XStart)/XStep
+
+ j = 0
+ while abs(spacingAmtX -int(spacingAmtX)) >= spacingAmtX/100.0 and j < 6:
+ j += 1
+ spacingAmtX *= 10
+
+ formatStr = '%%2.%df' % j
+
+ for counter, _Mb in enumerate(Plot.frange(XStart, XEnd, spacingAmt / NUM_MINOR_TICKS)):
+ if _Mb < startMb or _Mb > endMb:
+ continue
+ Xc = xLeftOffset + plotXScale*(_Mb - startMb)
+ if counter % NUM_MINOR_TICKS == 0: # Draw a MAJOR mark, not just a minor tick mark
+ canvas.drawLine(Xc, yZero, Xc, yZero+xMajorTickHeight, color=xAxisTickMarkColor, width=X_MAJOR_TICK_THICKNESS) # Draw the MAJOR tick mark
+ labelStr = str(formatStr % _Mb) # What Mbase location to put on the label
+ strWidth = canvas.stringWidth(labelStr, font=MBLabelFont)
+ drawStringXc = (Xc - (strWidth / 2.0))
+ canvas.drawString(labelStr, drawStringXc, strYLoc, font=MBLabelFont, color=xAxisLabelColor, angle=0)
+ else:
+ canvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=xAxisTickMarkColor, width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark
+ # end else
+
+ ###Physical genome wide view
+ else:
+ distScale = 0
+ startPosX = xLeftOffset
+ for i, distLen in enumerate(ChrLengthDistList):
+ if distScale == 0: #universal scale in whole genome mapping
+ if distLen > 75:
+ distScale = 25
+ elif distLen > 30:
+ distScale = 10
+ else:
+ distScale = 5
+ for tickdists in range(distScale, ceil(distLen), distScale):
+ canvas.drawLine(startPosX + tickdists*plotXScale, yZero, startPosX + tickdists*plotXScale, yZero + 7, color=pid.black, width=1*zoom)
+ canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=pid.black, font=MBLabelFont, angle=270)
+ startPosX += (ChrLengthDistList[i]+GraphInterval)*plotXScale
+
+ megabaseLabelFont = pid.Font(ttf="verdana", size=14*zoom*1.5, bold=0)
+ canvas.drawString("Megabases", xLeftOffset + (plotWidth -canvas.stringWidth("Megabases", font=megabaseLabelFont))/2,
+ strYLoc + canvas.fontHeight(MBLabelFont) + 5*zoom, font=megabaseLabelFont, color=pid.black)
+ pass
+
+ canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.black, width=X_AXIS_THICKNESS) # Draw the X axis itself
+
+ def drawXAxis(self, fd, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ #Parameters
+ NUM_MINOR_TICKS = 5 # Number of minor ticks between major ticks
+ X_MAJOR_TICK_THICKNESS = 2
+ X_MINOR_TICK_THICKNESS = 1
+ X_AXIS_THICKNESS = 1*zoom
+
+ # ======= Alex: Draw the X-axis labels (megabase location)
+ MBLabelFont = pid.Font(ttf="verdana", size=12*fontZoom, bold=0)
+ xMajorTickHeight = 15 # How high the tick extends below the axis
+ xMinorTickHeight = 5*zoom
+ xAxisTickMarkColor = pid.black
+ xAxisLabelColor = pid.black
+ fontHeight = 12*fontZoom # How tall the font that we're using is
+ spacingFromLabelToAxis = 20
+ spacingFromLineToLabel = 3
+
+ if self.plotScale == 'physic':
+ strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont)
+ ###Physical single chromosome view
+ if self.selectedChr > -1:
+ graphMbWidth = endMb - startMb
+ XScale = Plot.detScale(startMb, endMb)
+ XStart, XEnd, XStep = XScale
+ if XStep < 8:
+ XStep *= 2
+ spacingAmtX = spacingAmt = (XEnd-XStart)/XStep
+
+ j = 0
+ while abs(spacingAmtX -int(spacingAmtX)) >= spacingAmtX/100.0 and j < 6:
+ j += 1
+ spacingAmtX *= 10
+
+ formatStr = '%%2.%df' % j
+
+ for counter, _Mb in enumerate(Plot.frange(XStart, XEnd, spacingAmt / NUM_MINOR_TICKS)):
+ if _Mb < startMb or _Mb > endMb:
+ continue
+ Xc = xLeftOffset + plotXScale*(_Mb - startMb)
+ if counter % NUM_MINOR_TICKS == 0: # Draw a MAJOR mark, not just a minor tick mark
+ canvas.drawLine(Xc, yZero, Xc, yZero+xMajorTickHeight, color=xAxisTickMarkColor, width=X_MAJOR_TICK_THICKNESS) # Draw the MAJOR tick mark
+ labelStr = str(formatStr % _Mb) # What Mbase location to put on the label
+ strWidth = canvas.stringWidth(labelStr, font=MBLabelFont)
+ drawStringXc = (Xc - (strWidth / 2.0))
+ canvas.drawString(labelStr, drawStringXc, strYLoc, font=MBLabelFont, color=xAxisLabelColor, angle=0)
+ else:
+ canvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=xAxisTickMarkColor, width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark
+ # end else
+
+ ###Physical genome wide view
+ else:
+ distScale = 0
+ startPosX = xLeftOffset
+ for i, distLen in enumerate(self.ChrLengthDistList):
+ if distScale == 0: #universal scale in whole genome mapping
+ if distLen > 75:
+ distScale = 25
+ elif distLen > 30:
+ distScale = 10
+ else:
+ distScale = 5
+ for tickdists in range(distScale, ceil(distLen), distScale):
+ canvas.drawLine(startPosX + tickdists*plotXScale, yZero, startPosX + tickdists*plotXScale, yZero + 7, color=pid.black, width=1*zoom)
+ canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=pid.black, font=MBLabelFont, angle=270)
+ startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale
+
+ megabaseLabelFont = pid.Font(ttf="verdana", size=14*zoom*1.5, bold=0)
+ canvas.drawString("Megabases", xLeftOffset + (plotWidth -canvas.stringWidth("Megabases", font=megabaseLabelFont))/2,
+ strYLoc + canvas.fontHeight(MBLabelFont) + 5*zoom, font=megabaseLabelFont, color=pid.black)
+ pass
+ else:
+ ChrAInfo = []
+ preLpos = -1
+ distinctCount = 0.0
+ if len(self.genotype) > 1:
+ for i, _chr in enumerate(self.genotype):
+ thisChr = []
+ Locus0CM = _chr[0].cM
+ nLoci = len(_chr)
+ if nLoci <= 8:
+ for _locus in _chr:
+ if _locus.name != ' - ':
+ if _locus.cM != preLpos:
+ distinctCount += 1
+ preLpos = _locus.cM
+ thisChr.append([_locus.name, _locus.cM-Locus0CM])
+ else:
+ for j in (0, nLoci/4, nLoci/2, nLoci*3/4, -1):
+ while _chr[j].name == ' - ':
+ j += 1
+ if _chr[j].cM != preLpos:
+ distinctCount += 1
+ preLpos = _chr[j].cM
+ thisChr.append([_chr[j].name, _chr[j].cM-Locus0CM])
+ ChrAInfo.append(thisChr)
+ else:
+ for i, _chr in enumerate(self.genotype):
+ thisChr = []
+ Locus0CM = _chr[0].cM
+ for _locus in _chr:
+ if _locus.name != ' - ':
+ if _locus.cM != preLpos:
+ distinctCount += 1
+ preLpos = _locus.cM
+ thisChr.append([_locus.name, _locus.cM-Locus0CM])
+ ChrAInfo.append(thisChr)
+
+ stepA = (plotWidth+0.0)/distinctCount
+
+ LRectWidth = 10
+ LRectHeight = 3
+ offsetA = -stepA
+ lineColor = pid.lightblue
+ startPosX = xLeftOffset
+ for j, ChrInfo in enumerate(ChrAInfo):
+ preLpos = -1
+ for i, item in enumerate(ChrInfo):
+ Lname,Lpos = item
+ if Lpos != preLpos:
+ offsetA += stepA
+ differ = 1
+ else:
+ differ = 0
+ preLpos = Lpos
+ Lpos *= plotXScale
+ if self.selectedChr > -1:
+ Zorder = i % 5
+ else:
+ Zorder = 0
+ if differ:
+ canvas.drawLine(startPosX+Lpos,yZero,xLeftOffset+offsetA,\
+ yZero+25, color=lineColor)
+ canvas.drawLine(xLeftOffset+offsetA,yZero+25,xLeftOffset+offsetA,\
+ yZero+40+Zorder*(LRectWidth+3),color=lineColor)
+ rectColor = pid.orange
+ else:
+ canvas.drawLine(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)-3,\
+ xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),color=lineColor)
+ rectColor = pid.deeppink
+ canvas.drawRect(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),\
+ xLeftOffset+offsetA-LRectHeight,yZero+40+Zorder*(LRectWidth+3)+LRectWidth,\
+ edgeColor=rectColor,fillColor=rectColor,edgeWidth = 0)
+ COORDS="%d,%d,%d,%d"%(xLeftOffset+offsetA-LRectHeight, yZero+40+Zorder*(LRectWidth+3),\
+ xLeftOffset+offsetA,yZero+40+Zorder*(LRectWidth+3)+LRectWidth)
+ HREF="javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm,fd.RISet+"Geno", Lname)
+ Areas=HT.Area(shape='rect',coords=COORDS,href=HREF, title="Locus : " + Lname)
+ gifmap.areas.append(Areas)
+ ##piddle bug
+ if j == 0:
+ canvas.drawLine(startPosX,yZero,startPosX,yZero+40, color=lineColor)
+ startPosX += (self.ChrLengthDistList[j]+self.GraphInterval)*plotXScale
+
+ canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.black, width=X_AXIS_THICKNESS) # Draw the X axis itself
+
+ def getColorForMarker(self, chrCount,flag):# no change is needed
+ chrColorDict={}
+ for i in range(chrCount):
+ if flag==1: # display blue and lightblue intercross
+ chrColorDict[i]=pid.black
+ elif flag==0:
+ if (i%2==0):
+ chrColorDict[i]=pid.blue
+ else:
+ chrColorDict[i]=pid.lightblue
+ else:#display different color for different chr
+ if i in [0,8,16]:
+ chrColorDict[i]=pid.black
+ elif i in [1,9,17]:
+ chrColorDict[i]=pid.red
+ elif i in [2,10,18]:
+ chrColorDict[i]=pid.lightgreen
+ elif i in [3,11,19]:
+ chrColorDict[i]=pid.blue
+ elif i in [4,12]:
+ chrColorDict[i]=pid.lightblue
+ elif i in [5,13]:
+ chrColorDict[i]=pid.hotpink
+ elif i in [6,14]:
+ chrColorDict[i]=pid.gold
+ elif i in [7,15]:
+ chrColorDict[i]=pid.grey
+
+ return chrColorDict
+
+
+ def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+ if len(self.traitList) != 1:
+ return
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ yZero = canvas.size[1] - yBottomOffset
+ fontZoom = zoom
+ if zoom == 2:
+ fontZoom = 1.5
+
+ try:
+ Chr = self.traitList[0].chr # self.traitListChr =self.traitList[0].chr=_vals need to change to chrList and mbList
+ Mb = self.traitList[0].mb # self.traitListMb =self.traitList[0].mb=_vals
+ except:
+ return
+
+ if self.plotScale == 'physic':
+ if self.selectedChr > -1:
+ if self.genotype[0].name != Chr or Mb < self.startMb or Mb > self.endMb:
+ return
+ else:
+ locPixel = xLeftOffset + (Mb-self.startMb)*plotXScale
+ else:
+ locPixel = xLeftOffset
+ for i, _chr in enumerate(self.genotype):
+ if _chr.name != Chr:
+ locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale
+ else:
+ locPixel += Mb*plotXScale
+ break
+ else:
+ if self.selectedChr > -1:
+ if self.genotype[0].name != Chr:
+ return
+ else:
+ for i, _locus in enumerate(self.genotype[0]):
+ #the trait's position is on the left of the first genotype
+ if i==0 and _locus.Mb >= Mb:
+ locPixel=-1
+ break
+
+ #the trait's position is between two traits
+ if i > 0 and self.genotype[0][i-1].Mb < Mb and _locus.Mb >= Mb:
+ locPixel = xLeftOffset + plotXScale*(self.genotype[0][i-1].cM+(_locus.cM-self.genotype[0][i-1].cM)*(Mb -self.genotype[0][i-1].Mb)/(_locus.Mb-self.genotype[0][i-1].Mb))
+ break
+
+ #the trait's position is on the right of the last genotype
+ if i==len(self.genotype[0]) and Mb>=_locus.Mb:
+ locPixel = -1
+ else:
+ locPixel = xLeftOffset
+ for i, _chr in enumerate(self.genotype):
+ if _chr.name != Chr:
+ locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale
+ else:
+ locPixel += (Mb*(_chr[-1].cM-_chr[0].cM)/self.ChrLengthCMList[i])*plotXScale
+ break
+ if locPixel >= 0:
+ traitPixel = ((locPixel, yZero), (locPixel-6, yZero+12), (locPixel+6, yZero+12))
+ canvas.drawPolygon(traitPixel, edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1)
+
+ if self.legendChecked:
+ startPosY = 15
+ nCol = 2
+ smallLabelFont = pid.Font(ttf="trebuc", size=12, bold=1)
+ leftOffset = xLeftOffset+(nCol-1)*200
+ canvas.drawPolygon(((leftOffset+6, startPosY-6), (leftOffset, startPosY+6), (leftOffset+12, startPosY+6)), edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1)
+ canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR)
+
+ # build dict based on plink result, key is chr, value is list of [snp,BP,pValue]
+ def getPlinkResultDict(self,outputFileName='',thresholdPvalue=-1,ChrOrderIdNameDict={}):
+
+ ChrList =self.ChrList
+ plinkResultDict={}
+
+ plinkResultfp = open("%s%s.qassoc"% (webqtlConfig.TMPDIR, outputFileName), "rb")
+
+ headerLine=plinkResultfp.readline()# read header line
+ line = plinkResultfp.readline()
+
+ valueList=[] # initialize value list, this list will include snp, bp and pvalue info
+ pValueList=[]
+ count=0
+
+ while line:
+ #convert line from str to list
+ lineList=self.buildLineList(line=line)
+
+ # only keep the records whose chromosome name is in db
+ if ChrOrderIdNameDict.has_key(int(lineList[0])) and lineList[-1] and lineList[-1].strip()!='NA':
+
+ chrName=ChrOrderIdNameDict[int(lineList[0])]
+ snp = lineList[1]
+ BP = lineList[2]
+ pValue = float(lineList[-1])
+ pValueList.append(pValue)
+
+ if plinkResultDict.has_key(chrName):
+ valueList=plinkResultDict[chrName]
+
+ # pvalue range is [0,1]
+ if thresholdPvalue >=0 and thresholdPvalue<=1:
+ if pValue < thresholdPvalue:
+ valueList.append((snp,BP,pValue))
+ count+=1
+
+ plinkResultDict[chrName]=valueList
+ valueList=[]
+ else:
+ if thresholdPvalue>=0 and thresholdPvalue<=1:
+ if pValue < thresholdPvalue:
+ valueList.append((snp,BP,pValue))
+ count+=1
+
+ if valueList:
+ plinkResultDict[chrName]=valueList
+
+ valueList=[]
+
+
+ line =plinkResultfp.readline()
+ else:
+ line=plinkResultfp.readline()
+
+ if pValueList:
+ minPvalue= min(pValueList)
+ else:
+ minPvalue=0
+
+ return count,minPvalue,plinkResultDict
+
+
+ ######################################################
+ # input: line: str,one line read from file
+ # function: convert line from str to list;
+ # output: lineList list
+ #######################################################
+ def buildLineList(self,line=None):
+
+ lineList = string.split(string.strip(line),' ')# irregular number of whitespaces between columns
+ lineList =[ item for item in lineList if item <>'']
+ lineList = map(string.strip, lineList)
+
+ return lineList
+
+ #added by NL: automatically generate pheno txt file for PLINK based on strainList passed from dataEditing page
+ def genPhenoTxtFileForPlink(self,phenoFileName='', RISetName='', probesetName='', valueDict={}):
+ pedFileStrainList=self.getStrainNameFromPedFile(RISetName=RISetName)
+ outputFile = open("%s%s.txt"%(webqtlConfig.TMPDIR,phenoFileName),"wb")
+ headerLine = 'FID\tIID\t%s\n'%probesetName
+ outputFile.write(headerLine)
+
+ newValueList=[]
+
+ #if valueDict does not include some strain, value will be set to -9999 as missing value
+ for item in pedFileStrainList:
+ try:
+ value=valueDict[item]
+ value=str(value).replace('value=','')
+ value=value.strip()
+ except:
+ value=-9999
+
+ newValueList.append(value)
+
+
+ newLine=''
+ for i, strain in enumerate(pedFileStrainList):
+ j=i+1
+ value=newValueList[i]
+ newLine+='%s\t%s\t%s\n'%(strain, strain, value)
+
+ if j%1000==0:
+ outputFile.write(newLine)
+ newLine=''
+
+ if newLine:
+ outputFile.write(newLine)
+
+ outputFile.close()
+
+ # get strain name from ped file in order
+ def getStrainNameFromPedFile(self, RISetName=''):
+ pedFileopen= open("%splink/%s.ped"%(webqtlConfig.HTMLPATH, RISetName),"r")
+ line =pedFileopen.readline()
+ strainNameList=[]
+
+ while line:
+ lineList=string.split(string.strip(line),'\t')
+ lineList=map(string.strip,lineList)
+
+ strainName=lineList[0]
+ strainNameList.append(strainName)
+
+ line =pedFileopen.readline()
+
+ return strainNameList
+
+ ################################################################
+ # Generate Chr list, Chr OrderId and Retrieve Length Information
+ ################################################################
+ def getChrNameOrderIdLength(self,RISet=''):
+
+ try:
+ query = """
+ Select
+ Chr_Length.Name,Chr_Length.OrderId,Length from Chr_Length, InbredSet
+ where
+ Chr_Length.SpeciesId = InbredSet.SpeciesId AND
+ InbredSet.Name = '%s'
+ Order by OrderId
+ """ % (RISet)
+ self.cursor.execute(query)
+
+ results =self.cursor.fetchall()
+ ChrList=[]
+ ChrLengthMbList=[]
+ ChrNameOrderIdDict={}
+ ChrOrderIdNameDict={}
+
+ for item in results:
+ ChrList.append(item[0])
+ ChrNameOrderIdDict[item[0]]=item[1] # key is chr name, value is orderId
+ ChrOrderIdNameDict[item[1]]=item[0] # key is orderId, value is chr name
+ ChrLengthMbList.append(item[2])
+
+ except:
+ ChrList=[]
+ ChrNameOrderIdDict={}
+ ChrLengthMbList=[]
+
+ return ChrList,ChrNameOrderIdDict,ChrOrderIdNameDict,ChrLengthMbList
+
+
diff --git a/web/webqtl/markerRegression/__init__.py b/web/webqtl/markerRegression/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/markerRegression/__init__.py
diff --git a/web/webqtl/misc/__init__.py b/web/webqtl/misc/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/misc/__init__.py
diff --git a/web/webqtl/misc/editHtmlPage.py b/web/webqtl/misc/editHtmlPage.py
new file mode 100755
index 00000000..68595b83
--- /dev/null
+++ b/web/webqtl/misc/editHtmlPage.py
@@ -0,0 +1,129 @@
+# 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
+
+import string
+import os
+import urlparse
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+
+#########################################
+# Edit HTML Page
+#########################################
+
+class editHtmlPage(templatePage):
+ htmlPath = webqtlConfig.ChangableHtmlPath
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ self.templateInclude = 1
+ self.dict['title'] = "Editing HTML"
+
+ if not self.updMysql():
+ return
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+ pass
+ else:
+ heading = "Editing HTML"
+ detail = ["You don't have the permission to modify this file"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ path = fd.formdata.getvalue('path')
+ preview = fd.formdata.getvalue('preview')
+ newHtmlCode = fd.formdata.getvalue('htmlSrc')
+ if newHtmlCode:
+ #newHtmlCode = string.replace(newHtmlCode, "&amp;image", "&image")
+ newHtmlCode = string.replace(newHtmlCode,"&amp;", "&")
+ if path and preview:
+ #preview
+ self.templateInclude = 0
+ #print newHtmlCode
+ self.debug = newHtmlCode
+ elif path:
+ #edit result
+ fileName = self.htmlPath + path
+ newfileName = fileName +'.old'
+ os.system("/bin/cp -f %s %s" % (fileName, newfileName))
+ fp = open(fileName, 'wb')
+ fp.write(newHtmlCode)
+ fp.close()
+ #print "chown qyh %s" % fileName
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#eeeeee", height=200)
+ mainTitle = HT.Paragraph("Edit HTML", Class="title")
+ url = HT.Href(text = "page", url =path, Class = "normal")
+ intro = HT.Blockquote("This ",url, " has been succesfully modified. ")
+ TD_LR.append(mainTitle, intro)
+ self.dict['body'] = TD_LR
+ #elif os.environ.has_key('HTTP_REFERER'):
+ elif fd.refURL:
+ #retrieve file to be edited
+ #refURL = os.environ['HTTP_REFERER']
+ addressing_scheme, network_location, path, parameters, query, fragment_identifier = urlparse.urlparse(fd.refURL)
+ if path[-1] == "/":
+ path += 'index.html'
+
+ fileName = self.htmlPath + path
+ try:
+ fp = open(fileName,'rb')
+ except:
+ fp = open(os.path.join(self.htmlPath, 'temp.html'),'rb')
+ htmlCode = fp.read()
+ #htmlCode = string.replace(htmlCode, "&nbsp","&amp;nbsp")
+ htmlCode = string.replace(htmlCode, "&","&amp;")
+ fp.close()
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='editHtml',submit=HT.Input(type='hidden'))
+ inputBox = HT.Textarea(name='htmlSrc', cols="100", rows=30,text=htmlCode)
+
+ hddn = {'FormID':'editHtml', 'path':path, 'preview':''}
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+ previewButton = HT.Input(type='button',name='previewhtml', value='Preview',Class="button", onClick= "editHTML(this.form, 'preview');")
+ submitButton = HT.Input(type='button',name='submitchange', value='Submit Change',Class="button", onClick= "editHTML(this.form, 'submit');")
+ resetButton = HT.Input(type='reset',Class="button")
+ form.append(HT.Center(inputBox, HT.P(), previewButton, submitButton, resetButton))
+
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#eeeeee")
+ mainTitle = HT.Paragraph("Edit HTML", Class="title")
+ intro = HT.Blockquote("You may edit the HTML source code in the editbox below, or you can copy the content of the editbox to your favorite HTML editor. ")
+ imgUpload = HT.Href(url="javascript:openNewWin('/upload.html', 'menubar=0,toolbar=0,location=0,resizable=0,status=1,scrollbars=1,height=400, width=600');", text="here", Class="fs14")
+ intro2 = HT.Blockquote("Click ", imgUpload, " to upload Images. ")
+ TD_LR.append(mainTitle, intro, intro2, HT.Center(form))
+ self.dict['body'] = TD_LR
+ else:
+ heading = "Editing HTML"
+ detail = ["Error occured while trying to edit the html file."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
diff --git a/web/webqtl/misc/uploadFilePage.py b/web/webqtl/misc/uploadFilePage.py
new file mode 100755
index 00000000..da679910
--- /dev/null
+++ b/web/webqtl/misc/uploadFilePage.py
@@ -0,0 +1,137 @@
+# 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
+
+import os
+import string
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+#########################################
+# Upload File Page
+#########################################
+
+class uploadFilePage(templatePage):
+
+ uploadPath = webqtlConfig.UPLOADPATH
+
+ def __init__(self, fd, formdata, cookies):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+ pass
+ else:
+ heading = "Upload File"
+ detail = ["You don't have the permission to upload file to the server."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ self.cursor.close()
+
+ file1 = self.save_uploaded_file (formdata, 'imgName1')
+ file2 = self.save_uploaded_file (formdata, 'imgName2')
+ file3 = self.save_uploaded_file (formdata, 'imgName3')
+ file4 = self.save_uploaded_file (formdata, 'imgName4')
+ file5 = self.save_uploaded_file (formdata, 'imgName5')
+
+ i = 0
+ uploaded = []
+
+ for filename in (file1, file2, file3, file4, file5):
+ if filename:
+ i += 1
+ uploaded.append(filename)
+
+ if i == 0:
+ heading = "Upload File"
+ detail = ["No file was selected, no file uploaded."]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ imgTbl = HT.TableLite(border=0, width = "90%",cellspacing=2, cellpadding=2, align="Center")
+ imgTbl.append(HT.TR(HT.TD("Thumbnail", width="%30", align='center',Class="colorBlue"),
+ HT.TD("URL", width="%60",Class="colorBlue", align='center')))
+ for item in uploaded:
+ img = HT.Image("/images/upload/" + item, border = 0, width=80)
+
+ #url = "%s/images/upload/" % webqtlConfig.PORTADDR + item
+ #url = HT.Href(text=url, url = url, Class='normalsize', target="_blank")
+ url2 = "/images/upload/" + item
+ url2 = HT.Href(text=url2, url = url2, Class='normalsize', target="_blank")
+ imgTbl.append(HT.TR(HT.TD(img, width="%30", align='center',Class="colorWhite"),
+ #HT.TD(url, HT.BR(), 'OR', HT.BR(), url2, width="%60",Class="colorWhite", align='center')))
+ HT.TD(url2, width="%60",Class="colorWhite", align='center')))
+
+ intro = HT.Paragraph('A total of %d files are uploaded' % i)
+ TD_LR.append( HT.Center(intro) )
+
+ TD_LR.append( imgTbl )
+
+ self.dict['body'] = str(TD_LR)
+
+ def save_uploaded_file(self, form, form_field, upload_dir=""):
+ if not upload_dir:
+ upload_dir = self.uploadPath
+ if not form.has_key(form_field):
+ return None
+ fileitem = form[form_field]
+
+ if not fileitem.filename or not fileitem.file:
+ return None
+
+ seqs = [""] + range(200)
+ try:
+ newfileName = string.split(fileitem.filename, ".")
+ for seq in seqs:
+ newfileName2 = newfileName[:]
+ if seq != "":
+ newfileName2[-2] = "%s-%s" % (newfileName2[-2], seq)
+ fileExist = glob.glob(os.path.join(upload_dir, string.join(newfileName2, ".")))
+ if not fileExist:
+ break
+ except:
+ pass
+
+ newfileName = string.join(newfileName2, ".")
+ #print [newfileName, os.path.join(upload_dir, newfileName)]
+ #return
+
+ fout = file (os.path.join(upload_dir, newfileName), 'wb')
+ while 1:
+ chunk = fileitem.file.read(100000)
+ if not chunk: break
+ fout.write (chunk)
+ fout.close()
+ return newfileName
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>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <input type="submit" name="mintmap" value=" Redraw " class="button" onClick="return sortSearchResults(this.form);" />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <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'>
+ &nbsp;<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'>&nbsp;</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&amp;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>
+ &nbsp&nbsp&nbsp&nbsp&nbsp
+ <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
+
diff --git a/web/webqtl/pairScan/CategoryGraphPage.py b/web/webqtl/pairScan/CategoryGraphPage.py
new file mode 100755
index 00000000..696c05ce
--- /dev/null
+++ b/web/webqtl/pairScan/CategoryGraphPage.py
@@ -0,0 +1,199 @@
+# 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
+
+import string
+import piddle as pid
+from htmlgen import HTMLgen2 as HT
+
+from utility import Plot
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+#########################################
+# Category Graph Page
+#########################################
+class CategoryGraphPage(templatePage):
+ def __init__(self, fd):
+
+ LRSFullThresh = 30
+ LRSInteractThresh = 25
+ maxPlotSize = 800
+ mainfmName = webqtlUtil.genRandStr("fm_")
+
+ templatePage.__init__(self, fd)
+
+ if not fd.genotype:
+ fd.readData()
+
+ ##Remove F1 and Parents
+ fd.genotype = fd.genotype_1
+
+ plotType = fd.formdata.getvalue('plotType')
+ self.dict['title'] = '%s Plot' % plotType
+ main_title = HT.Paragraph("%s Plot" % plotType)
+ main_title.__setattr__("class","title")
+
+ interval1 = fd.formdata.getvalue('interval1')
+ interval2 = fd.formdata.getvalue('interval2')
+
+ flanka1, flanka2, chram = string.split(interval1)
+ flankb1, flankb2, chrbm = string.split(interval2)
+
+ traitValues = string.split(fd.formdata.getvalue('traitValues'), ',')
+ traitValues = map(webqtlUtil.StringAsFloat, traitValues)
+ traitStrains = string.split(fd.formdata.getvalue('traitStrains'), ',')
+
+ flankaGeno = []
+ flankbGeno = []
+
+ for chr in fd.genotype:
+ for locus in chr:
+ if locus.name in (flanka1, flankb1):
+ if locus.name == flanka1:
+ flankaGeno = locus.genotype[:]
+ else:
+ flankbGeno = locus.genotype[:]
+ if flankaGeno and flankbGeno:
+ break
+
+ flankaDict = {}
+ flankbDict = {}
+ for i in range(len(fd.genotype.prgy)):
+ flankaDict[fd.genotype.prgy[i]] = flankaGeno[i]
+ flankbDict[fd.genotype.prgy[i]] = flankbGeno[i]
+
+ BB = []
+ BD = []
+ DB = []
+ DD = []
+
+ iValues = []
+ for i in range(len(traitValues)):
+ if traitValues[i] != None:
+ iValues.append(traitValues[i])
+ thisstrain = traitStrains[i]
+ try:
+ a1 = flankaDict[thisstrain]
+ b1 = flankbDict[thisstrain]
+ except:
+ continue
+ if a1 == -1.0:
+ if b1 == -1.0:
+ BB.append((thisstrain, traitValues[i]))
+ elif b1 == 1.0:
+ BD.append((thisstrain, traitValues[i]))
+ elif a1 == 1.0:
+ if b1 == -1.0:
+ DB.append((thisstrain, traitValues[i]))
+ elif b1 == 1.0:
+ DD.append((thisstrain, traitValues[i]))
+ else:
+ pass
+
+ #print BB, BD, DB, DD, max(iValues), min(iValues)
+
+ plotHeight = 400
+ plotWidth = 600
+ xLeftOffset = 60
+ xRightOffset = 40
+ yTopOffset = 40
+ yBottomOffset = 60
+
+ canvasHeight = plotHeight + yTopOffset + yBottomOffset
+ canvasWidth = plotWidth + xLeftOffset + xRightOffset
+ canvas = pid.PILCanvas(size=(canvasWidth,canvasHeight))
+ XXX = [('Mat/Mat', BB), ('Mat/Pat', BD), ('Pat/Mat', DB), ('Pat/Pat', DD)]
+ XLabel = "Interval 1 / Interval 2"
+
+ if plotType == "Box":
+ Plot.plotBoxPlot(canvas, XXX, offset=(xLeftOffset, xRightOffset, yTopOffset, yBottomOffset), XLabel = XLabel)
+ else:
+ #Could be a separate function, but seems no other uses
+ max_Y = max(iValues)
+ min_Y = min(iValues)
+ scaleY = Plot.detScale(min_Y, max_Y)
+ Yll = scaleY[0]
+ Yur = scaleY[1]
+ nStep = scaleY[2]
+ stepY = (Yur - Yll)/nStep
+ stepYPixel = plotHeight/(nStep)
+ canvas.drawRect(plotWidth+xLeftOffset, plotHeight + yTopOffset, xLeftOffset, yTopOffset)
+
+ ##draw Y Scale
+ YYY = Yll
+ YCoord = plotHeight + yTopOffset
+ scaleFont=pid.Font(ttf="cour",size=11,bold=1)
+ for i in range(nStep+1):
+ strY = Plot.cformat(d=YYY, rank=0)
+ YCoord = max(YCoord, yTopOffset)
+ canvas.drawLine(xLeftOffset,YCoord,xLeftOffset-5,YCoord)
+ canvas.drawString(strY, xLeftOffset -30,YCoord +5,font=scaleFont)
+ YYY += stepY
+ YCoord -= stepYPixel
+
+
+ ##draw X Scale
+ stepX = plotWidth/len(XXX)
+ XCoord = xLeftOffset + 0.5*stepX
+ YCoord = plotHeight + yTopOffset
+ scaleFont = pid.Font(ttf="tahoma",size=12,bold=0)
+ labelFont = pid.Font(ttf="tahoma",size=13,bold=0)
+ for item in XXX:
+ itemname, itemvalue = item
+ canvas.drawLine(XCoord, YCoord,XCoord, YCoord+5, color=pid.black)
+ canvas.drawString(itemname, XCoord - canvas.stringWidth(itemname,font=labelFont)/2.0,YCoord +20,font=labelFont)
+ itemvalue.sort(webqtlUtil.cmpOrder2)
+ j = 0
+ for item2 in itemvalue:
+ tstrain, tvalue = item2
+ canvas.drawCross(XCoord, plotHeight + yTopOffset - (tvalue-Yll)*plotHeight/(Yur - Yll), color=pid.red,size=5)
+ if j % 2 == 0:
+ canvas.drawString(tstrain, XCoord+5, plotHeight + yTopOffset - \
+ (tvalue-Yll)*plotHeight/(Yur - Yll) +5, font=scaleFont, color=pid.blue)
+ else:
+ canvas.drawString(tstrain, XCoord-canvas.stringWidth(tstrain,font=scaleFont)-5, \
+ plotHeight + yTopOffset - (tvalue-Yll)*plotHeight/(Yur - Yll) +5, font=scaleFont, color=pid.blue)
+ j += 1
+ XCoord += stepX
+
+
+ labelFont=pid.Font(ttf="verdana",size=18,bold=0)
+ canvas.drawString(XLabel, xLeftOffset + (plotWidth -canvas.stringWidth(XLabel,font=labelFont))/2.0, YCoord +40, font=labelFont)
+ canvas.drawString("Value",xLeftOffset-40, YCoord-(plotHeight -canvas.stringWidth("Value",font=labelFont))/2.0, font=labelFont, angle =90)
+
+
+ filename= webqtlUtil.genRandStr("Cate_")
+ canvas.save(webqtlConfig.IMGDIR+filename, format='gif')
+ img=HT.Image('/image/'+filename+'.gif',border=0)
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign='top')
+ TD_LR.append(main_title, HT.Center(img))#, traitValues , len(traitValues), traitStrains, len(traitStrains), len(fd.genotype.prgy))
+ #TD_LR.append(main_title, HT.BR(), flanka1, flanka2, chram, HT.BR(), flankb1, flankb2, chrbm)
+ self.dict['body'] = str(TD_LR)
+
+
+
diff --git a/web/webqtl/pairScan/DirectPlotPage.py b/web/webqtl/pairScan/DirectPlotPage.py
new file mode 100755
index 00000000..4c3b9075
--- /dev/null
+++ b/web/webqtl/pairScan/DirectPlotPage.py
@@ -0,0 +1,430 @@
+# 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
+
+import string
+import piddle as pid
+from math import *
+import os
+
+import direct
+from htmlgen import HTMLgen2 as HT
+
+from utility import Plot
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+
+
+class DirectPlotPage(templatePage):
+ def __init__(self, fd):
+
+ LRSFullThresh = 30
+ LRSInteractThresh = 25
+
+ templatePage.__init__(self, fd)
+
+ if not fd.genotype:
+ fd.readData()
+
+ incVars = 0
+ _genotype = fd.genotype_1
+ _strains, _vals, _vars, N = fd.informativeStrains(_genotype.prgy, incVars)
+
+ self.dict['title'] = 'Pair-Scan Plot'
+ if not self.openMysql():
+ return
+
+ iPermuCheck = fd.formdata.getvalue('directPermuCheckbox')
+
+ try:
+ graphtype = int(fd.formdata.getvalue('graphtype'))
+ except:
+ graphtype = 1
+ try:
+ graphsort = int(fd.formdata.getvalue('graphSort'))
+ except:
+ graphsort = 1
+ try:
+ returnIntervalPairNum = int(fd.formdata.getvalue('pairScanReturn'))
+ except:
+ returnIntervalPairNum = 50
+
+ pairIntro = HT.Blockquote("The graph below displays pair-scan results for the trait ",HT.Strong(" %s" % fd.identification))
+ if not graphsort:
+ tblIntro = HT.Blockquote('This table lists LRS scores for the top %d pairs of intervals (Interval 1 on the left and Interval 2 on the right). Pairs are sorted by the "LRS Full" column. Both intervals are defined by proximal and distal markers that flank the single best position.' % returnIntervalPairNum)
+ else:
+ tblIntro = HT.Blockquote('This table lists LRS scores for the top %d pairs of intervals (Interval 1 on the left and Interval 2 on the right). Pairs are sorted by the "LRS Interaction" column. Both intervals are defined by proximal and distal markers that flank the single best position.' % returnIntervalPairNum)
+
+ try:
+ thisTrait = webqtlTrait(fullname=fd.formdata.getvalue("fullname"), cursor=self.cursor)
+ pairIntro.append(' from the database ' , thisTrait.db.genHTML())
+ except:
+ pass
+
+ pairIntro.append('. The upper left half of the plot highlights any epistatic interactions (corresponding to the column labeled "LRS Interact"). In contrast, the lower right half provides a summary of LRS of the full model, representing cumulative effects of linear and non-linear terms (column labeled "LRS Full"). The WebQTL implementation of the scan for 2-locus epistatic interactions is based on the DIRECT global optimization algorithm developed by ',HT.Href(text ="Ljungberg",url='http://user.it.uu.se/~kl/qtl_software.html',target="_blank", Class = "fs14 fwn"),', Holmgren, and Carlborg (',HT.Href(text = "2004",url='http://bioinformatics.oupjournals.org/cgi/content/abstract/bth175?ijkey=21Pp0pgOuBL6Q&keytype=ref', Class = "fs14 fwn"),').')
+
+ main_title = HT.Paragraph("Pair-Scan Results: An Analysis of Epistatic Interactions")
+ main_title.__setattr__("class","title")
+
+ subtitle1 = HT.Paragraph("Pair-Scan Graph")
+ subtitle3 = HT.Paragraph("Pair-Scan Top LRS")
+ subtitle1.__setattr__("class","subtitle")
+ subtitle3.__setattr__("class","subtitle")
+
+ self.identification = "unnamed trait"
+ if fd.identification:
+ self.identification = fd.identification
+ self.dict['title'] = self.identification + ' / '+self.dict['title']
+
+ #####################################
+ #
+ # Remove the Parents & F1 data
+ #
+ #####################################
+
+ if _vals:
+ if len(_vals) > webqtlConfig.KMININFORMATIVE:
+ ResultFull = []
+ ResultInteract = []
+ ResultAdd = []
+
+ #permutation test
+ subtitle2 = ''
+ permuTbl = ''
+ permuIntro = ''
+ if iPermuCheck:
+ subtitle2 = HT.Paragraph("Pair-Scan Permutation Results")
+ subtitle2.__setattr__("class","subtitle")
+ permuIntro = HT.Blockquote("Phenotypes were randomly permuted 500 times among strains or individuals and reanalyzed using the pair-scan algorithm. We extracted the single highest LRS for the full model for each of these permuted data sets. The histograms of these highest LRS values provide an empirical way to estimate the probability of obtaining an LRS above suggestive or significant thresholds.")
+
+ prtmuTblIntro1 = HT.Paragraph("The following table gives threshold values for Suggestive (P=0.63) and Significant associations (P=0.05) defined by Lander & Kruglyak and for the slightly more stringent P=0.01 level. (The Highly Significant level of Lander & Kruglyak corresponds to P=0.001 and cannot be estimated with 500 permutations.)")
+ prtmuTblIntro2 = HT.Paragraph("If the full model exceeds the permutation-based Significant threshold, then different models for those locations can be tested by conventional chi-square tests at P<0.01. Interaction is significant if LRS Interact exceeds 6.64 for RI strains or 13.28 for an F2. If interaction is not significant, the two-QTL model is better than a one-QTL model if LRS Additive exceeds LRS 1 or LRS 2 by 6.64 for RI strains or 9.21 for an F2.")
+ ResultFull, ResultInteract, ResultAdd = direct.permu(webqtlConfig.GENODIR, _vals, _strains, fd.RISet, 500) #XZ, 08/14/2008: add module name webqtlConfig
+ ResultFull.sort()
+ ResultInteract.sort()
+ ResultAdd.sort()
+ nPermuResult = len(ResultFull)
+ # draw Histogram
+ cFull = pid.PILCanvas(size=(400,300))
+ Plot.plotBar(cFull, ResultFull,XLabel='LRS',YLabel='Frequency',title=' Histogram of LRS Full')
+ #plotBar(cFull,10,10,390,290,ResultFull,XLabel='LRS',YLabel='Frequency',title=' Histogram of LRS Full')
+ filename= webqtlUtil.genRandStr("Pair_")
+ cFull.save(webqtlConfig.IMGDIR+filename, format='gif')
+ imgFull=HT.Image('/image/'+filename+'.gif',border=0,alt='Histogram of LRS Full')
+
+
+ superPermuTbl = HT.TableLite(border=0, cellspacing=0, cellpadding=0,bgcolor ='#999999')
+ permuTbl2 = HT.TableLite(border=0, cellspacing= 1, cellpadding=5)
+ permuTbl2.append(HT.TR(HT.TD(HT.Font('LRS', color = '#FFFFFF')), HT.TD(HT.Font('p = 0.63', color = '#FFFFFF'), width = 150, align='Center'), HT.TD(HT.Font('p = 0.05', color = '#FFFFFF'), width = 150, align='Center'), HT.TD(HT.Font('p = 0.01', color = '#FFFFFF'), width = 150, align='Center'),bgColor='royalblue'))
+ permuTbl2.append(HT.TR(HT.TD('Full'), HT.TD('%2.1f' % ResultFull[int(nPermuResult*0.37 -1)], align="Center"), HT.TD('%2.1f' % ResultFull[int(nPermuResult*0.95 -1)], align="Center"), HT.TD('%2.1f' % ResultFull[int(nPermuResult*0.99 -1)], align="Center"),bgColor="#eeeeee"))
+ superPermuTbl.append(HT.TD(HT.TD(permuTbl2)))
+
+ permuTbl1 = HT.TableLite(border=0, cellspacing= 0, cellpadding=5,width='100%')
+ permuTbl1.append(HT.TR(HT.TD(imgFull, align="Center", width = 410), HT.TD(prtmuTblIntro1, superPermuTbl, prtmuTblIntro2, width = 490)))
+
+ permuTbl = HT.Center(permuTbl1, HT.P())
+
+ #permuTbl.append(HT.TR(HT.TD(HT.BR(), 'LRS Full = %2.1f, ' % ResultFull[int(nPermuResult*0.37 -1)], 'LRS Full = %2.1f, ' % ResultFull[int(nPermuResult*0.95 -1)], 'LRS Full highly significant (p=0.001) = %2.1f, ' % ResultFull[int(nPermuResult*0.999 -1)] , HT.BR(), 'LRS Interact suggestive (p=0.63) = %2.1f, ' % ResultInteract[int(nPermuResult*0.37 -1)], 'LRS Interact significant (p=0.05) = %2.1f, ' % ResultInteract[int(nPermuResult*0.95 -1)], 'LRS Interact = %2.1f, ' % ResultInteract[int(nPermuResult*0.999 -1)] , HT.BR(),'LRS Additive suggestive (p=0.63) = %2.1f, ' % ResultAdd[int(nPermuResult*0.37 -1)], 'LRS Additive significant (p=0.05) = %2.1f, ' % ResultAdd[int(nPermuResult*0.95 -1)], 'LRS Additive highly significant (p=0.001) = %2.1f, ' % ResultAdd[int(nPermuResult*0.999 -1)], HT.BR(), 'Total number of permutation is %d' % nPermuResult, HT.BR(), HT.BR(),colspan=2)))
+ #tblIntro.append(HT.P(), HT.Center(permuTbl))
+
+ #print vals, strains, fd.RISet
+ d = direct.direct(webqtlConfig.GENODIR, _vals, _strains, fd.RISet, 8000)#XZ, 08/14/2008: add module name webqtlConfig
+ chrsInfo = d[2]
+ sum = 0
+ offsets = [0]
+ i = 0
+ for item in chrsInfo:
+ if i > 0:
+ offsets.append(sum)
+ sum += item[0]
+ i += 1
+ offsets.append(sum)
+ #print sum,offset,d[2]
+ canvasWidth = 880
+ canvasHeight = 880
+ if graphtype:
+ colorAreaWidth = 230
+ else:
+ colorAreaWidth = 0
+ c = pid.PILCanvas(size=(canvasWidth + colorAreaWidth ,canvasHeight))
+ xoffset = 40
+ yoffset = 40
+ width = canvasWidth - xoffset*2
+ height = canvasHeight - yoffset*2
+
+ xscale = width/sum
+ yscale = height/sum
+
+ rectInfo = d[1]
+ rectInfo.sort(webqtlUtil.cmpLRSFull)
+
+ finecolors = Plot.colorSpectrum(250)
+ finecolors.reverse()
+ regLRS = [0]*height
+ #draw LRS Full
+
+ for item in rectInfo:
+ LRSFull,LRSInteract,LRSa,LRSb,chras,chram,chrae,chrbs,chrbm,chrbe,chra,chrb,flanka,flankb = item
+ if LRSFull > 30:
+ dcolor = pid.red
+ elif LRSFull > 20:
+ dcolor = pid.orange
+ elif LRSFull > 10:
+ dcolor = pid.olivedrab
+ elif LRSFull > 0:
+ dcolor = pid.grey
+ else:
+ LRSFull = 0
+ dcolor = pid.grey
+
+ chras += offsets[chra]
+ chram += offsets[chra]
+ chrae += offsets[chra]
+ chrbs += offsets[chrb]
+ chrbm += offsets[chrb]
+ chrbe += offsets[chrb]
+
+ regLRSD = int(chram*yscale)
+ if regLRS[regLRSD] < LRSa:
+ regLRS[regLRSD] = LRSa
+ regLRSD = int(chrbm*yscale)
+ if regLRS[regLRSD] < LRSb:
+ regLRS[regLRSD] = LRSb
+
+ if graphtype:
+ colorIndex = int(LRSFull *250 /LRSFullThresh)
+ if colorIndex >= 250:
+ colorIndex = 249
+ dcolor = finecolors[colorIndex]
+ if chra != chrb or ((chrbe - chrae) > 10 and (chrbs - chras) > 10):
+ c.drawRect(xoffset+chrbs*xscale,yoffset+height-chras*yscale,xoffset+chrbe*xscale,yoffset+height-chrae*yscale,edgeColor=dcolor,fillColor=dcolor,edgeWidth = 0)
+ else:
+ c.drawPolygon([(xoffset+chrbs*xscale,yoffset+height-chras*yscale),(xoffset+chrbe*xscale,yoffset+height-chras*yscale),(xoffset+chrbe*xscale,yoffset+height-chrae*yscale)],edgeColor=dcolor,fillColor=dcolor,edgeWidth = 0,closed =1)
+ else:
+ c.drawCross(xoffset+chrbm*xscale,yoffset+height-chram*yscale,color=dcolor,size=2)
+ #draw Marker Regression LRS
+ if graphtype:
+ """
+ maxLRS = max(regLRS)
+ pts = []
+ i = 0
+ for item in regLRS:
+ pts.append((xoffset+width+35+item*50/maxLRS, yoffset+height-i))
+ i += 1
+ c.drawPolygon(pts,edgeColor=pid.blue,edgeWidth=1,closed=0)
+ """
+ LRS1Thresh = 16.2
+ i = 0
+ for item in regLRS:
+ colorIndex = int(item *250 /LRS1Thresh)
+ if colorIndex >= 250:
+ colorIndex = 249
+ dcolor = finecolors[colorIndex]
+ c.drawLine(xoffset+width+35,yoffset+height-i,xoffset+width+55,yoffset+height-i,color=dcolor)
+ i += 1
+ labelFont=pid.Font(ttf="arial",size=20,bold=0)
+ c.drawString('Single Locus Regression',xoffset+width+90,yoffset+height, font = labelFont,color=pid.dimgray,angle=90)
+ #draw LRS Interact
+ rectInfo.sort(webqtlUtil.cmpLRSInteract)
+ for item in rectInfo:
+ LRSFull,LRSInteract,LRSa,LRSb,chras,chram,chrae,chrbs,chrbm,chrbe,chra,chrb,flanka,flankb = item
+ if LRSInteract > 30:
+ dcolor = pid.red
+ elif LRSInteract > 20:
+ dcolor = pid.orange
+ elif LRSInteract > 10:
+ dcolor = pid.olivedrab
+ elif LRSInteract > 0:
+ dcolor = pid.grey
+ else:
+ LRSInteract = 0
+ dcolor = pid.grey
+ chras += offsets[chra]
+ chram += offsets[chra]
+ chrae += offsets[chra]
+ chrbs += offsets[chrb]
+ chrbm += offsets[chrb]
+ chrbe += offsets[chrb]
+ if graphtype:
+ colorIndex = int(LRSInteract *250 / LRSInteractThresh )
+ if colorIndex >= 250:
+ colorIndex = 249
+ dcolor = finecolors[colorIndex]
+ if chra != chrb or ((chrbe - chrae) > 10 and (chrbs - chras) > 10):
+ c.drawRect(xoffset+chras*xscale,yoffset+height-chrbs*yscale,xoffset+chrae*xscale,yoffset+height-chrbe*yscale,edgeColor=dcolor,fillColor=dcolor,edgeWidth = 0)
+ else:
+ c.drawPolygon([(xoffset+chras*xscale,yoffset+height-chrbs*yscale),(xoffset+chras*xscale,yoffset+height-chrbe*yscale),(xoffset+chrae*xscale,yoffset+height-chrbe*yscale)],edgeColor=dcolor,fillColor=dcolor,edgeWidth = 0,closed =1)
+ else:
+ c.drawCross(xoffset+chram*xscale,yoffset+height-chrbm*yscale,color=dcolor,size=2)
+ #draw chromosomes label
+ labelFont=pid.Font(ttf="tahoma",size=24,bold=0)
+ i = 0
+ for item in chrsInfo:
+ strWidth = c.stringWidth(item[1],font=labelFont)
+ c.drawString(item[1],xoffset+offsets[i]*xscale +(item[0]*xscale-strWidth)/2,canvasHeight -15,font = labelFont,color=pid.dimgray)
+ c.drawString(item[1],xoffset+offsets[i]*xscale +(item[0]*xscale-strWidth)/2,yoffset-10,font = labelFont,color=pid.dimgray)
+ c.drawString(item[1],xoffset-strWidth-5,yoffset+height - offsets[i]*yscale -(item[0]*yscale-22)/2,font = labelFont,color=pid.dimgray)
+ c.drawString(item[1],canvasWidth-xoffset+5,yoffset+height - offsets[i]*yscale -(item[0]*yscale-22)/2,font = labelFont,color=pid.dimgray)
+ i += 1
+
+
+ c.drawRect(xoffset,yoffset,xoffset+width,yoffset+height)
+ for item in offsets:
+ c.drawLine(xoffset,yoffset+height-item*yscale,xoffset+width,yoffset+height-item*yscale)
+ c.drawLine(xoffset+item*xscale,yoffset,xoffset+item*xscale,yoffset+height)
+
+ #draw pngMap
+ pngMap = HT.Map(name='pairPlotMap')
+ #print offsets, len(offsets)
+ for i in range(len(offsets)-1):
+ for j in range(len(offsets)-1):
+ COORDS = "%d,%d,%d,%d" %(xoffset+offsets[i]*xscale, yoffset+height-offsets[j+1]*yscale, xoffset+offsets[i+1]*xscale, yoffset+height-offsets[j]*yscale)
+ HREF = "javascript:showPairPlot(%d,%d);" % (i,j)
+ Areas = HT.Area(shape='rect',coords=COORDS,href=HREF)
+ pngMap.areas.append(Areas)
+
+ #draw spectrum
+ if graphtype:
+ i = 0
+ labelFont=pid.Font(ttf="tahoma",size=14,bold=0)
+ middleoffsetX = 180
+ for dcolor in finecolors:
+ if i % 50 == 0:
+ c.drawLine(xoffset+ width +middleoffsetX-15 , height + yoffset -i, xoffset+ width +middleoffsetX-20,height + yoffset -i, color=pid.black)
+ c.drawString('%d' % int(LRSInteractThresh*i/250.0),xoffset+ width+ middleoffsetX-40,height + yoffset -i +5, font = labelFont,color=pid.black)
+ c.drawLine(xoffset+ width +middleoffsetX+15 , height + yoffset -i, xoffset+ width +middleoffsetX+20 ,height + yoffset -i, color=pid.black)
+ c.drawString('%d' % int(LRSFullThresh*i/250.0),xoffset+ width + middleoffsetX+25,height + yoffset -i +5, font = labelFont,color=pid.black)
+ c.drawLine(xoffset+ width +middleoffsetX-15 , height + yoffset -i, xoffset+ width +middleoffsetX+15 ,height + yoffset -i, color=dcolor)
+ i += 1
+
+ if i % 50 == 0:
+ i -= 1
+ c.drawLine(xoffset+ width +middleoffsetX-15 , height + yoffset -i, xoffset+ width +middleoffsetX-20,height + yoffset -i, color=pid.black)
+ c.drawString('%d' % ceil(LRSInteractThresh*i/250.0),xoffset+ width + middleoffsetX-40,height + yoffset -i +5, font = labelFont,color=pid.black)
+ c.drawLine(xoffset+ width +middleoffsetX+15 , height + yoffset -i, xoffset+ width +middleoffsetX+20 ,height + yoffset -i, color=pid.black)
+ c.drawString('%d' % ceil(LRSFullThresh*i/250.0),xoffset+ width + middleoffsetX+25,height + yoffset -i +5, font = labelFont,color=pid.black)
+
+ labelFont=pid.Font(ttf="verdana",size=20,bold=0)
+ c.drawString('LRS Interaction',xoffset+ width + middleoffsetX-50,height + yoffset, font = labelFont,color=pid.dimgray,angle=90)
+ c.drawString('LRS Full',xoffset+ width + middleoffsetX+50,height + yoffset, font = labelFont,color=pid.dimgray,angle=90)
+
+ filename= webqtlUtil.genRandStr("Pair_")
+ c.save(webqtlConfig.IMGDIR+filename, format='png')
+ img2=HT.Image('/image/'+filename+'.png',border=0,usemap='#pairPlotMap')
+
+
+ form0 = HT.Form( cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showPairPlot', submit=HT.Input(type='hidden'))
+ hddn0 = {'FormID':'pairPlot','Chr_A':'_','Chr_B':'','idata':string.join(map(str, _vals), ','),'istrain':string.join(_strains, ','),'RISet':fd.RISet}
+ for key in hddn0.keys():
+ form0.append(HT.Input(name=key, value=hddn0[key], type='hidden'))
+
+ form0.append(img2, pngMap)
+
+ mainfmName = webqtlUtil.genRandStr("fm_")
+ txtform = HT.Form( cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name=mainfmName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_','RISet':fd.RISet}
+ #XZ, Aug 11, 2010: The variable traitStrains is not assigned right values before (should not be assigned fd.strainlist).
+ #hddn['traitStrains'] = string.join(fd.strainlist, ',')
+ hddn['traitStrains'] = string.join(_strains, ',')
+ hddn['traitValues'] = string.join(map(str, _vals), ',')
+ hddn['interval1'] = ''
+ hddn['interval2'] = ''
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+ for key in hddn.keys():
+ txtform.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ tbl = HT.TableLite(Class="collap", cellspacing=1, cellpadding=5,width=canvasWidth + colorAreaWidth)
+
+ c1 = HT.TD('Interval 1',colspan=3,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c2 = HT.TD('Interval 2',colspan=3,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c11 = HT.TD('Position',rowspan=2,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c12 = HT.TD('Flanking Markers',colspan=2,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c111 = HT.TD('Proximal',align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c112 = HT.TD('Distal',align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+
+
+ c3 = HT.TD('LRS Full',rowspan=3,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c4 = HT.TD('LRS Additive',rowspan=3,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c5 = HT.TD('LRS Interact',rowspan=3,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c6 = HT.TD('LRS 1',rowspan=3,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+ c7 = HT.TD('LRS 2',rowspan=3,align="Center", Class="fs13 fwb ffl b1 cw cbrb")
+
+
+ tbl.append(HT.TR(c1,c3,c4,c5,c6,c7,c2))
+
+ tbl.append(HT.TR(c11,c12,c11,c12))
+ tbl.append(HT.TR(c111,c112,c111,c112))
+ if not graphsort: #Sort by LRS Full
+ rectInfo.sort(webqtlUtil.cmpLRSFull)
+ rectInfoReturned = rectInfo[len(rectInfo) - returnIntervalPairNum:]
+ rectInfoReturned.reverse()
+
+ for item in rectInfoReturned:
+ LRSFull,LRSInteract,LRSa,LRSb,chras,chram,chrae,chrbs,chrbm,chrbe,chra,chrb,flanka,flankb = item
+ LRSAdditive = LRSFull - LRSInteract
+ flanka1,flanka2 = string.split(flanka)
+ flankb1,flankb2 = string.split(flankb)
+ urla1 = HT.Href(text = flanka1, url = "javascript:showTrait('%s','%s');" % (mainfmName, flanka1),Class= "fs12 fwn")
+ urla2 = HT.Href(text = flanka2, url = "javascript:showTrait('%s','%s');" % (mainfmName, flanka2),Class= "fs12 fwn")
+ urlb1 = HT.Href(text = flankb1, url = "javascript:showTrait('%s','%s');" % (mainfmName, flankb1),Class= "fs12 fwn")
+ urlb2 = HT.Href(text = flankb2, url = "javascript:showTrait('%s','%s');" % (mainfmName, flankb2),Class= "fs12 fwn")
+ urlGenGraph = HT.Href(text = "Plot", url = "javascript:showCateGraph('%s', '%s %s %2.3f', '%s %s %2.3f');" % (mainfmName, flanka1, flanka2, chram, flankb1, flankb2, chrbm),Class= "fs12 fwn")
+ tr1 = HT.TR(
+ HT.TD('Chr %s @ %2.1f cM ' % (chrsInfo[chra][1],chram),Class= "fs12 b1 fwn"),
+ HT.TD(urla1,Class= "fs12 b1 fwn"),
+ HT.TD(urla2,Class= "fs12 b1 fwn"),
+ HT.TD('%2.3f ' % LRSFull, urlGenGraph,Class= "fs12 b1 fwn"),
+ HT.TD('%2.3f' % LRSAdditive,Class= "fs12 b1 fwn"),
+ HT.TD('%2.3f' % LRSInteract,Class= "fs12 b1 fwn"),
+ HT.TD('%2.3f' % LRSa,Class= "fs12 b1 fwn"),
+ HT.TD('%2.3f' % LRSb,Class= "fs12 b1 fwn"),
+ HT.TD('Chr %s @ %2.1f cM' % (chrsInfo[chrb][1],chrbm),Class= "fs12 b1 fwn"),
+ HT.TD(urlb1,Class= "fs12 b1 fwn"),
+ HT.TD(urlb2,Class= "fs12 b1 fwn"))
+ tbl.append(tr1)
+
+ plotType1 = HT.Input(type="radio", name="plotType", value ="Dot", checked=1)
+ plotType2 = HT.Input(type="radio", name="plotType", value ="Box")
+ plotText = HT.Paragraph("Plot Type : ", plotType1, " Dot ", plotType2, " Box", )
+
+ txtform.append(plotText, tbl)
+ TD_LR = HT.TD(colspan=2,height=200,width="100%",bgColor='#eeeeee')
+ TD_LR.append(main_title,HT.Blockquote(subtitle1, pairIntro, HT.P(), HT.Center(form0,HT.P())),HT.Blockquote(subtitle2, permuIntro,HT.P(), HT.Center(permuTbl)), HT.Blockquote(subtitle3, tblIntro, HT.P(),HT.Center(txtform), HT.P()))
+ self.dict['body'] = str(TD_LR)
+ else:
+ heading = "Direct Plot"
+ detail = ['Fewer than %d strain data were entered for %s data set. No statitical analysis has been attempted.' % (webqtlConfig.KMININFORMATIVE, fd.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ heading = "Direct Plot"
+ detail = ['Empty data set, please check your data.']
+ self.error(heading=heading,detail=detail)
+ return
+
diff --git a/web/webqtl/pairScan/PairPlotPage.py b/web/webqtl/pairScan/PairPlotPage.py
new file mode 100755
index 00000000..3f72bd74
--- /dev/null
+++ b/web/webqtl/pairScan/PairPlotPage.py
@@ -0,0 +1,314 @@
+# 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
+
+import string
+import piddle as pid
+import os
+
+from htmlgen import HTMLgen2 as HT
+import direct
+
+from utility import Plot
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+#########################################
+# PairPlotPage
+#########################################
+class PairPlotPage(templatePage):
+ def __init__(self, fd):
+
+ LRSFullThresh = 30
+ LRSInteractThresh = 25
+ maxPlotSize = 1000
+ mainfmName = webqtlUtil.genRandStr("fm_")
+
+ templatePage.__init__(self, fd)
+
+ self.dict['title'] = 'Pair-Scan Plot'
+
+ if not self.openMysql():
+ return
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+ vals = fd.formdata.getvalue('idata')
+ vals = map(float,string.split(vals,','))
+ strains = fd.formdata.getvalue('istrain')
+ strains = string.split(strains,',')
+ Chr_A = int(fd.formdata.getvalue('Chr_A'))
+ Chr_B = int(fd.formdata.getvalue('Chr_B'))
+ if len(vals) > webqtlConfig.KMININFORMATIVE:
+ d = direct.exhaust(webqtlConfig.GENODIR, vals, strains, fd.RISet, Chr_A, Chr_B)#XZ, 08/14/2008: add module name webqtlConfig
+ chrsInfo = d[2]
+ longerChrLen = max(chrsInfo[Chr_A][0], chrsInfo[Chr_B][0])
+ shorterChrlen = min(chrsInfo[Chr_A][0], chrsInfo[Chr_B][0])
+
+ plotHeight = int(chrsInfo[Chr_B][0]*maxPlotSize/longerChrLen)
+ plotWidth = int(chrsInfo[Chr_A][0]*maxPlotSize/longerChrLen)
+
+
+ xLeftOffset = 200
+ xRightOffset = 40
+ yTopOffset = 40
+ yBottomOffset = 200
+ colorAreaWidth = 120
+
+ canvasHeight = plotHeight + yTopOffset + yBottomOffset
+ canvasWidth = plotWidth + xLeftOffset + xRightOffset + colorAreaWidth
+
+
+ canvas = pid.PILCanvas(size=(canvasWidth,canvasHeight))
+ plotScale = plotHeight/chrsInfo[Chr_B][0]
+
+ rectInfo = d[1]
+ finecolors = Plot.colorSpectrum(250)
+ finecolors.reverse()
+ #draw LRS Full
+ for item in rectInfo:
+ LRSFull,LRSInteract,LRSa,LRSb,chras,chram,chrae,chrbs,chrbm,chrbe,chra,chrb,flanka,flankb = item
+ if Chr_A > Chr_B:
+ colorIndex = int(LRSFull *250 /LRSFullThresh)
+ else:
+ colorIndex = int(LRSInteract *250 /LRSInteractThresh)
+ if colorIndex >= 250:
+ colorIndex = 249
+ elif colorIndex < 0:
+ colorIndex = 0
+ dcolor = finecolors[colorIndex]
+ if chra != chrb or (abs(chrbe - chrae) > 10 and abs(chrbs - chras) > 10):
+ canvas.drawRect(xLeftOffset+chras*plotScale,yTopOffset+plotHeight- \
+ chrbs*plotScale,xLeftOffset+chrae*plotScale,yTopOffset+plotHeight- \
+ chrbe*plotScale,edgeColor=dcolor,fillColor=dcolor,edgeWidth = 0)
+ elif chrbs >= chras:
+ canvas.drawPolygon([(xLeftOffset+chras*plotScale,yTopOffset+plotHeight-chrbs*plotScale),\
+ (xLeftOffset+chras*plotScale,yTopOffset+plotHeight-chrbe*plotScale),\
+ (xLeftOffset+chrae*plotScale,yTopOffset+plotHeight-chrbe*plotScale)],\
+ edgeColor=dcolor,fillColor=dcolor,edgeWidth = 0,closed =1)
+ else:
+ canvas.drawPolygon([(xLeftOffset+chras*plotScale,yTopOffset+plotHeight-chrbs*plotScale),\
+ (xLeftOffset+chrae*plotScale,yTopOffset+plotHeight-chrbs*plotScale), \
+ (xLeftOffset+chrae*plotScale,yTopOffset+plotHeight-chrbe*plotScale)], \
+ edgeColor=dcolor,fillColor=dcolor,edgeWidth = 0,closed =1)
+
+ labelFont=pid.Font(ttf="verdana",size=24,bold=0)
+ chrName = "chromosome %s" % chrsInfo[Chr_A][1]
+ canvas.drawString(chrName,xLeftOffset + (plotWidth - canvas.stringWidth(chrName,font=labelFont))/2,\
+ yTopOffset+plotHeight+ 170,font=labelFont)
+ chrName = "chromosome %s" % chrsInfo[Chr_B][1]
+ canvas.drawString(chrName, 30, yTopOffset +(canvas.stringWidth(chrName,font=labelFont) + plotHeight)/2,\
+ font=labelFont, angle = 90)
+ if Chr_A == Chr_B:
+ infoStr = "minimum distance = 10 cM"
+ infoStrWidth = canvas.stringWidth(infoStr,font=labelFont)
+ canvas.drawString(infoStr, xLeftOffset + (plotWidth-infoStrWidth*0.707)/2, yTopOffset + \
+ (plotHeight+infoStrWidth*0.707)/2,font=labelFont, angle = 45, color=pid.red)
+
+ labelFont=pid.Font(ttf="verdana",size=12,bold=0)
+ gifmap = HT.Map(name='markerMap')
+
+ lineColor = pid.lightblue
+ #draw ChrA Loci
+ ChrAInfo = d[3]
+ preLpos = -1
+ i = 0
+ for item in ChrAInfo:
+ Lname,Lpos = item
+ if Lpos != preLpos:
+ i += 1
+ preLpos = Lpos
+ stepA = float(plotWidth)/i
+
+ offsetA = -stepA
+ LRectWidth = 10
+ LRectHeight = 3
+ i = 0
+ preLpos = -1
+ for item in ChrAInfo:
+ Lname,Lpos = item
+ if Lpos != preLpos:
+ offsetA += stepA
+ differ = 1
+ else:
+ differ = 0
+ preLpos = Lpos
+ Lpos *= plotScale
+ Zorder = i % 5
+ """
+ LStrWidth = canvas.stringWidth(Lname,font=labelFont)
+ canvas.drawString(Lname,xLeftOffset+offsetA+4,yTopOffset+plotHeight+140,\
+ font=labelFont,color=pid.blue,angle=90)
+ canvas.drawLine(xLeftOffset+Lpos,yTopOffset+plotHeight,xLeftOffset+offsetA,\
+ yTopOffset+plotHeight+25,color=lineColor)
+ canvas.drawLine(xLeftOffset+offsetA,yTopOffset+plotHeight+25,xLeftOffset+offsetA,\
+ yTopOffset+plotHeight+140-LStrWidth,color=lineColor)
+ COORDS="%d,%d,%d,%d"%(xLeftOffset+offsetA+4,yTopOffset+plotHeight+140,\
+ xLeftOffset+offsetA-6,yTopOffset+plotHeight+140-LStrWidth)
+ """
+ if differ:
+ canvas.drawLine(xLeftOffset+Lpos,yTopOffset+plotHeight,xLeftOffset+offsetA,\
+ yTopOffset+plotHeight+25,color=lineColor)
+ canvas.drawLine(xLeftOffset+offsetA,yTopOffset+plotHeight+25,xLeftOffset+offsetA,\
+ yTopOffset+plotHeight+80+Zorder*(LRectWidth+3),color=lineColor)
+ rectColor = pid.orange
+ else:
+ canvas.drawLine(xLeftOffset+offsetA, yTopOffset+plotHeight+80+Zorder*(LRectWidth+3)-3,\
+ xLeftOffset+offsetA, yTopOffset+plotHeight+80+Zorder*(LRectWidth+3),color=lineColor)
+ rectColor = pid.deeppink
+ canvas.drawRect(xLeftOffset+offsetA, yTopOffset+plotHeight+80+Zorder*(LRectWidth+3),\
+ xLeftOffset+offsetA-LRectHeight,yTopOffset+plotHeight+80+Zorder*(LRectWidth+3)+LRectWidth,\
+ edgeColor=rectColor,fillColor=rectColor,edgeWidth = 0)
+ COORDS="%d,%d,%d,%d"%(xLeftOffset+offsetA, yTopOffset+plotHeight+80+Zorder*(LRectWidth+3),\
+ xLeftOffset+offsetA-LRectHeight,yTopOffset+plotHeight+80+Zorder*(LRectWidth+3)+LRectWidth)
+ HREF="javascript:showTrait('%s','%s');" % (mainfmName, Lname)
+ Areas=HT.Area(shape='rect',coords=COORDS,href=HREF, title="Locus : " + Lname)
+ gifmap.areas.append(Areas)
+ i += 1
+ #print (i , offsetA, Lname, Lpos, preLpos)
+ #print "<BR>"
+
+ #draw ChrB Loci
+ ChrBInfo = d[4]
+ preLpos = -1
+ i = 0
+ for item in ChrBInfo:
+ Lname,Lpos = item
+ if Lpos != preLpos:
+ i += 1
+ preLpos = Lpos
+ stepB = float(plotHeight)/i
+
+ offsetB = -stepB
+ LRectWidth = 10
+ LRectHeight = 3
+ i = 0
+ preLpos = -1
+ for item in ChrBInfo:
+ Lname,Lpos = item
+ if Lpos != preLpos:
+ offsetB += stepB
+ differ = 1
+ else:
+ differ = 0
+ preLpos = Lpos
+ Lpos *= plotScale
+ Zorder = i % 5
+ Lname,Lpos = item
+ Lpos *= plotScale
+ """
+ LStrWidth = canvas.stringWidth(Lname,font=labelFont)
+ canvas.drawString(Lname, 45,yTopOffset+plotHeight-offsetB+4,font=labelFont,color=pid.blue)
+ canvas.drawLine(45+LStrWidth,yTopOffset+plotHeight-offsetB,xLeftOffset-25,\
+ yTopOffset+plotHeight-offsetB,color=lineColor)
+ canvas.drawLine(xLeftOffset-25,yTopOffset+plotHeight-offsetB,xLeftOffset,\
+ yTopOffset+plotHeight-Lpos,color=lineColor)
+ COORDS = "%d,%d,%d,%d" %(45,yTopOffset+plotHeight-offsetB+4,45+LStrWidth,\
+ yTopOffset+plotHeight-offsetB-6)
+ """
+ if differ:
+ canvas.drawLine(xLeftOffset,yTopOffset+plotHeight-Lpos, xLeftOffset-25,\
+ yTopOffset+plotHeight-offsetB,color=lineColor)
+ canvas.drawLine(xLeftOffset -25, yTopOffset+plotHeight-offsetB, \
+ xLeftOffset-80 -Zorder*(LRectWidth+3),yTopOffset+plotHeight-offsetB, color=lineColor)
+ rectColor = pid.orange
+ else:
+ canvas.drawLine(xLeftOffset -80 -Zorder*(LRectWidth+3)+3, yTopOffset+plotHeight-offsetB, \
+ xLeftOffset-80 -Zorder*(LRectWidth+3),yTopOffset+plotHeight-offsetB, color=lineColor)
+ rectColor = pid.deeppink
+ HREF = "javascript:showTrait('%s','%s');" % (mainfmName, Lname)
+ canvas.drawRect(xLeftOffset-80 -Zorder*(LRectWidth+3),yTopOffset+plotHeight-offsetB,\
+ xLeftOffset-80 -Zorder*(LRectWidth+3)-LRectWidth,yTopOffset+plotHeight-offsetB +LRectHeight,\
+ edgeColor=rectColor,fillColor=rectColor,edgeWidth = 0)
+ COORDS="%d,%d,%d,%d"%(xLeftOffset-80 -Zorder*(LRectWidth+3),yTopOffset+plotHeight-offsetB,\
+ xLeftOffset-80 -Zorder*(LRectWidth+3)-LRectWidth,yTopOffset+plotHeight-offsetB +LRectHeight)
+ Areas=HT.Area(shape='rect',coords=COORDS,href=HREF, title="Locus : " + Lname)
+ gifmap.areas.append(Areas)
+ i += 1
+
+ canvas.drawRect(xLeftOffset, yTopOffset, xLeftOffset+plotWidth, yTopOffset+plotHeight,edgeColor=pid.black)
+
+ #draw spectrum
+ i = 0
+ labelFont=pid.Font(ttf="tahoma",size=14,bold=0)
+ middleoffsetX = 80
+ for dcolor in finecolors:
+ canvas.drawLine(xLeftOffset+ plotWidth +middleoffsetX-15 , plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth +middleoffsetX+15 , plotHeight + yTopOffset - i, color=dcolor)
+ if i % 50 == 0:
+ if Chr_A >= Chr_B:
+ canvas.drawLine(xLeftOffset+ plotWidth +middleoffsetX+15 ,plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth +middleoffsetX+20,plotHeight + yTopOffset - i, color=pid.black)
+ canvas.drawString('%d' % int(LRSFullThresh*i/250.0),xLeftOffset+ plotWidth +middleoffsetX+22,\
+ plotHeight + yTopOffset - i +5, font = labelFont,color=pid.black)
+ if Chr_A <= Chr_B:
+ canvas.drawLine(xLeftOffset+ plotWidth +middleoffsetX-15 ,plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth +middleoffsetX-20,plotHeight + yTopOffset - i, color=pid.black)
+ canvas.drawString('%d' % int(LRSInteractThresh*i/250.0),xLeftOffset+plotWidth+middleoffsetX-40,\
+ plotHeight + yTopOffset - i +5, font = labelFont,color=pid.black)
+ i += 1
+ #draw spectrum label
+ labelFont2=pid.Font(ttf="verdana",size=20,bold=0)
+ if i % 50 == 0:
+ i -= 1
+ if Chr_A >= Chr_B:
+ canvas.drawLine(xLeftOffset+ plotWidth +middleoffsetX+15 ,plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth +middleoffsetX+20,plotHeight + yTopOffset - i, color=pid.black)
+ canvas.drawString('%d' % int(LRSFullThresh*(i+1)/250.0),xLeftOffset+ plotWidth +middleoffsetX+22,\
+ plotHeight + yTopOffset - i +5, font = labelFont,color=pid.black)
+ canvas.drawString('LRS Full',xLeftOffset+ plotWidth +middleoffsetX+50,plotHeight + yTopOffset, \
+ font = labelFont2,color=pid.dimgray,angle=90)
+ if Chr_A <= Chr_B:
+ canvas.drawLine(xLeftOffset+ plotWidth +middleoffsetX-15 ,plotHeight + yTopOffset - i, \
+ xLeftOffset+ plotWidth +middleoffsetX-20,plotHeight + yTopOffset - i, color=pid.black)
+ canvas.drawString('%d' % int(LRSInteractThresh*(i+1)/250.0),xLeftOffset+ plotWidth+middleoffsetX-40,\
+ plotHeight + yTopOffset - i +5, font = labelFont,color=pid.black)
+ canvas.drawString('LRS Interaction',xLeftOffset+ plotWidth +middleoffsetX-50,\
+ plotHeight + yTopOffset, font = labelFont2,color=pid.dimgray,angle=90)
+
+ filename= webqtlUtil.genRandStr("Pair_")
+ canvas.save(webqtlConfig.IMGDIR+filename, format='png')
+ img2=HT.Image('/image/'+filename+'.png',border=0,usemap='#markerMap')
+
+ main_title = HT.Paragraph("Pair-Scan Results: Chromosome Pair")
+ main_title.__setattr__("class","title")
+ form = HT.Form(cgi = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', \
+ name=mainfmName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_','RISet':fd.RISet, 'incparentsf1':'on'}
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+ form.append(img2,gifmap)
+ TD_LR.append(main_title, HT.Center(form), HT.P())
+ else:
+ heading = "Direct Plot"
+ detail = ['Fewer than %d strain data were entered for %s data set. No statitical analysis has been attempted.'\
+ % (webqtlConfig.KMININFORMATIVE, fd.RISet)]
+ self.error(heading=heading,detail=detail)
+ return
+ self.dict['body'] = str(TD_LR)
+
+
diff --git a/web/webqtl/pairScan/__init__.py b/web/webqtl/pairScan/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/pairScan/__init__.py
diff --git a/web/webqtl/pubmedsearch/PubmedSearch.py b/web/webqtl/pubmedsearch/PubmedSearch.py
new file mode 100755
index 00000000..8e7b0725
--- /dev/null
+++ b/web/webqtl/pubmedsearch/PubmedSearch.py
@@ -0,0 +1,58 @@
+# 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
+
+#geneWikiPage.py
+#
+#This one's pretty self-evident from the title. If you use the GeneWiki module, this is what's behind it. -KA
+
+# Xiaodong changed the dependancy structure
+
+from htmlgen import HTMLgen2 as HT
+import os
+import string
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+#########################################
+#########################################
+
+class PubmedSearch(templatePage):
+
+ def __init__(self, fd):
+ templatePage.__init__(self, fd)
+ self.content_type = 'text/html'
+ Heading = HT.Paragraph("pubmed search", Class="title")
+ Intro = HT.Blockquote("This is a description.")
+ form = HT.Form(cgi=os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='pubmedsearch', submit=HT.Input(type='hidden'))
+ form.append(HT.Input(type="text", size = 45, maxlength=100, name="symbol"))
+ form.append(HT.Input(type="hidden", name="FormID", value="pubmedsearchre"))
+ form.append(HT.Input(type="submit", name="submit", value="submit", Class="button"))
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
+ TD_LR.append(Heading, Intro, HT.Center(form))
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = "Pubmed Search" \ No newline at end of file
diff --git a/web/webqtl/pubmedsearch/PubmedSearchRe.py b/web/webqtl/pubmedsearch/PubmedSearchRe.py
new file mode 100755
index 00000000..fcbfd941
--- /dev/null
+++ b/web/webqtl/pubmedsearch/PubmedSearchRe.py
@@ -0,0 +1,57 @@
+# 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
+
+#geneWikiPage.py
+#
+#This one's pretty self-evident from the title. If you use the GeneWiki module, this is what's behind it. -KA
+
+# Xiaodong changed the dependancy structure
+
+from htmlgen import HTMLgen2 as HT
+import os
+import string
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+#########################################
+#########################################
+
+class PubmedSearchRe(templatePage):
+
+ def __init__(self, fd):
+ templatePage.__init__(self, fd)
+ self.content_type = 'text/html'
+ Heading = HT.Paragraph("pubmed search", Class="title")
+ Intro = HT.Blockquote("This is a description.")
+
+ table = HT.TableLite(border=0, cellpadding=0, cellspacing=0)
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
+ TD_LR.append(Heading, Intro, HT.Center(form))
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = "Pubmed Search" \ No newline at end of file
diff --git a/web/webqtl/pubmedsearch/__init__.py b/web/webqtl/pubmedsearch/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/pubmedsearch/__init__.py
diff --git a/web/webqtl/qtlminer/GeneUtil.py b/web/webqtl/qtlminer/GeneUtil.py
new file mode 100755
index 00000000..3ae7f3c0
--- /dev/null
+++ b/web/webqtl/qtlminer/GeneUtil.py
@@ -0,0 +1,658 @@
+import string
+import os
+
+
+from base import webqtlConfig
+
+
+#Just return a list of dictionaries
+#each dictionary contains sub-dictionary
+def loadGenes(cursor, chrName, diffCol, startMb, endMb, webqtlDb =None, species='mouse'):
+ #cursor.execute("desc GeneList")
+ #results = cursor.fetchall()
+ #fetchFields = map(lambda X:X[0], results)
+ fetchFields = ['SpeciesId', 'Id', 'GeneSymbol', 'GeneDescription', 'Chromosome', 'TxStart', 'TxEnd',
+ 'Strand', 'GeneID', 'NM_ID', 'kgID', 'GenBankID', 'UnigenID', 'ProteinID', 'AlignID',
+ 'exonCount', 'exonStarts', 'exonEnds', 'cdsStart', 'cdsEnd']
+
+ ##List All Species in the Gene Table
+ speciesDict = {}
+ cursor.execute("select Species.Name, GeneList.SpeciesId from Species, GeneList where \
+ GeneList.SpeciesId = Species.Id group by GeneList.SpeciesId")
+ results = cursor.fetchall()
+ for item in results:
+ speciesDict[item[0]] = item[1]
+
+ ##List current Species and other Species
+ speciesId = speciesDict[species]
+ otherSpecies = map(lambda X: [X, speciesDict[X]], speciesDict.keys())
+ otherSpecies.remove([species, speciesId])
+
+ cursor.execute("""SELECT %s from GeneList
+ where
+ SpeciesId = %d AND Chromosome = '%s' AND
+ ((TxStart > %f and TxStart <= %f) OR (TxEnd > %f and TxEnd <= %f))
+ order by txStart
+ """
+ % (string.join(fetchFields, ", "), speciesId, chrName, startMb, endMb, startMb, endMb))
+ results = cursor.fetchall()
+ GeneList = []
+
+ if results:
+ for result in results:
+ newdict = {}
+ for j, item in enumerate(fetchFields):
+ newdict[item] = result[j]
+ #count SNPs if possible
+ if diffCol and species=='mouse':
+ cursor.execute("""
+ select
+ count(*) from BXDSnpPosition
+ where
+ Chr = '%s' AND Mb >= %2.6f AND Mb < %2.6f AND
+ StrainId1 = %d AND StrainId2 = %d
+ """ % (chrName, newdict["TxStart"], newdict["TxEnd"], diffCol[0], diffCol[1]))
+ newdict["snpCount"] = cursor.fetchone()[0]
+ newdict["snpDensity"] = newdict["snpCount"]/(newdict["TxEnd"]-newdict["TxStart"])/1000.0
+ else:
+ newdict["snpDensity"] = newdict["snpCount"] = 0
+
+ try:
+ newdict['GeneLength'] = 1000.0*(newdict['TxEnd'] - newdict['TxStart'])
+ except:
+ pass
+
+ #load gene from other Species by the same name
+ for item in otherSpecies:
+ othSpec, othSpecId = item
+ newdict2 = {}
+
+ cursor.execute("SELECT %s from GeneList where SpeciesId = %d and geneSymbol= '%s' limit 1" %
+ (string.join(fetchFields, ", "), othSpecId, newdict["GeneSymbol"]))
+ resultsOther = cursor.fetchone()
+ if resultsOther:
+ for j, item in enumerate(fetchFields):
+ newdict2[item] = resultsOther[j]
+
+ #count SNPs if possible, could be a separate function
+ if diffCol and othSpec == 'mouse':
+ cursor.execute("""
+ select
+ count(*) from BXDSnpPosition
+ where
+ Chr = '%s' AND Mb >= %2.6f AND Mb < %2.6f AND
+ StrainId1 = %d AND StrainId2 = %d
+ """ % (chrName, newdict["TxStart"], newdict["TxEnd"], diffCol[0], diffCol[1]))
+
+
+
+ newdict2["snpCount"] = cursor.fetchone()[0]
+ newdict2["snpDensity"] = newdict2["snpCount"]/(newdict2["TxEnd"]-newdict2["TxStart"])/1000.0
+ else:
+ newdict2["snpDensity"] = newdict2["snpCount"] = 0
+
+ try:
+ newdict2['GeneLength'] = 1000.0*(newdict2['TxEnd'] - newdict2['TxStart'])
+ except:
+ pass
+
+ newdict['%sGene' % othSpec] = newdict2
+
+ GeneList.append(newdict)
+
+ return GeneList
+
+
+
+
+
+
+def loadGenesForQTLminer(cursor, chrName, diffCol, startMb, endMb, webqtlDb =None, species='mouse', databaseA='HC_M2_0606_P', databaseB='HC_M2CB_1205_R', databaseC='Illum_LXS_Hipp_loess0807', str1='C57BL/6J', str2='DBA/2J'):
+ #cursor.execute("desc GeneList")
+ #results = cursor.fetchall()
+ #fetchFields = map(lambda X:X[0], results)
+ fetchFields = ['SpeciesId', 'Id', 'GeneSymbol', 'GeneDescription', 'Chromosome', 'TxStart', 'TxEnd',
+ 'Strand', 'GeneID', 'NM_ID', 'kgID', 'GenBankID', 'UnigenID', 'ProteinID', 'AlignID',
+ 'exonCount', 'exonStarts', 'exonEnds', 'cdsStart', 'cdsEnd']
+
+ ##List All Species in the Gene Table
+ speciesDict = {}
+ cursor.execute("select Species.Name, GeneList.SpeciesId from Species, GeneList where \
+ GeneList.SpeciesId = Species.Id group by GeneList.SpeciesId")
+ results = cursor.fetchall()
+ for item in results:
+ speciesDict[item[0]] = item[1]
+
+
+# fpText = open(os.path.join(webqtlConfig.TMPDIR, "strains") + str(j) + '.txt','wb')
+# fpText.write("strain: '%d' \n" % thisone )
+# fpText.close()
+# strainids.append(thisone)
+
+
+
+
+ ##List current Species and other Species
+ speciesId = speciesDict[species]
+ otherSpecies = map(lambda X: [X, speciesDict[X]], speciesDict.keys())
+ otherSpecies.remove([species, speciesId])
+
+ cursor.execute("""SELECT %s from GeneList
+ where
+ SpeciesId = %d AND Chromosome = '%s' AND
+ ((TxStart > %f and TxStart <= %f) OR (TxEnd > %f and TxEnd <= %f))
+ order by txStart
+ """
+ % (string.join(fetchFields, ", "), speciesId, chrName, startMb, endMb, startMb, endMb))
+ results = cursor.fetchall()
+ GeneList = []
+
+ if results:
+ for result in results:
+ newdict = {}
+ for j, item in enumerate(fetchFields):
+ newdict[item] = result[j]
+
+## get pathways
+
+ cursor.execute("""
+ select
+ pathway
+ FROM
+ kegg.mmuflat
+ where
+ gene = '%s'
+ """ % (newdict["GeneID"]) )
+
+ resAAA = cursor.fetchall()
+ if resAAA:
+ myFields = ['pathways']
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resAAA:
+ temp.append(k[j])
+ newdict["pathways"] = temp
+
+ cursor.execute("""
+ select
+ name
+ FROM
+ kegg.mmuflat
+ where
+ gene = '%s'
+ """ % (newdict["GeneID"]) )
+
+ resAAA = cursor.fetchall()
+ if resAAA:
+ myFields = ['pathwaynames']
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resAAA:
+ temp.append(k[j])
+ newdict["pathwaynames"] = temp
+
+## get GO terms
+
+ cursor.execute("""
+ SELECT
+ distinct go.term.name
+ FROM go.gene_product
+ INNER JOIN go.dbxref ON (go.gene_product.dbxref_id=go.dbxref.id)
+ INNER JOIN go.association ON (go.gene_product.id=go.association.gene_product_id)
+ INNER JOIN go.term ON (go.association.term_id=go.term.id)
+ WHERE
+ go.dbxref.xref_key = (select mgi from go.genemgi where gene='%s' limit 1)
+ AND
+ go.dbxref.xref_dbname = 'MGI'
+ AND
+ go.term.term_type='biological_process'
+ """ % (newdict["GeneID"]) )
+
+ resAAA = cursor.fetchall()
+ if resAAA:
+ myFields = ['goterms']
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resAAA:
+ temp.append(k[j])
+ newdict["goterms"] = temp
+
+
+
+
+
+
+ newdict["snpDensity"] = newdict["snpCount"] = newdict["snpCountall"] = newdict["snpCountmis"] = newdict["snpCountBXD"] = newdict["snpCountmissel"] = 0
+
+ #count SNPs if possible
+ if diffCol and species=='mouse':
+ cursor.execute("""
+ select
+ count(*) from BXDSnpPosition
+ where
+ Chr = '%s' AND Mb >= %2.6f AND Mb < %2.6f AND
+ StrainId1 = %d AND StrainId2 = %d
+ """ % (chrName, newdict["TxStart"], newdict["TxEnd"], diffCol[0], diffCol[1]))
+ newdict["snpCount"] = cursor.fetchone()[0]
+ newdict["snpDensity"] = newdict["snpCount"]/(newdict["TxEnd"]-newdict["TxStart"])/1000.0
+ else:
+ newdict["snpDensity"] = newdict["snpCount"] = 0
+
+ try:
+ newdict['GeneLength'] = 1000.0*(newdict['TxEnd'] - newdict['TxStart'])
+ except:
+ pass
+
+
+
+#self.cursor.execute("SELECT geneSymbol, chromosome, txStart, txEnd from GeneList where SpeciesId= 1 and geneSymbol = %s", opt.geneName)
+
+
+
+
+ ## search with gene name... doesnt matter. it changed to start and end position anyway
+ ##self.cursor.execute("SELECT geneSymbol, chromosome, txStart, txEnd from GeneList where SpeciesId= 1 and geneSymbol = %s", newdict["GeneSymbol"])
+
+
+ #count SNPs for all strains
+ cursor.execute("""
+ SELECT
+ distinct SnpAll.Id
+ from
+ SnpAll
+ where
+ SpeciesId = '1' and SnpAll.Chromosome = '%s' AND
+ SnpAll.Position >= %2.6f and SnpAll.Position < %2.6f AND
+ SnpAll.Exon='Y'
+ """ % (newdict["Chromosome"], newdict["TxStart"], newdict["TxEnd"]))
+ snpfetch = cursor.fetchall()
+ newdict["snpCountmis"] = len(snpfetch)
+
+## # count SNPs for selected strains
+
+ sql = """SELECT
+ distinct SnpAll.Id, `%s`, `%s`
+ from
+ SnpAll, SnpPattern
+ where
+ SpeciesId = '1' and SnpAll.Chromosome = '%s' AND
+ SnpAll.Position >= %2.6f and SnpAll.Position < %2.6f and SnpAll.Id = SnpPattern.SnpId AND
+ SnpPattern.`%s` != SnpPattern.`%s` AND
+ SnpAll.Exon='Y'
+ """ % (str1, str2, newdict["Chromosome"], newdict["TxStart"], newdict["TxEnd"], str1, str2)
+ cursor.execute(sql)
+ ressnp = cursor.fetchall()
+ newdict["snpCountmissel"] = len(ressnp)
+ newdict["hassnp"] = 'n'
+ if len(ressnp)>0 :
+ newdict["hassnp"]= 'y'
+## ####################################### NEW NEW NEW
+
+
+
+
+
+
+
+ # count Indels for BXD mice
+ cursor.execute("""
+ SELECT
+ distinct IndelAll.Name, IndelAll.Chromosome, IndelAll.SourceId, IndelAll.Mb_start,
+ IndelAll.Mb_end, IndelAll.Strand, IndelAll.Type, IndelAll.Size, IndelAll.InDelSequence,
+ SnpSource.Name
+ from
+ SnpSource, IndelAll
+ where
+ IndelAll.SpeciesId = '1' and IndelAll.Chromosome = '%s' AND
+ IndelAll.Mb_start >= %2.6f and IndelAll.Mb_start < (%2.6f+.0010) AND
+ SnpSource.Id = IndelAll.SourceId
+ order by IndelAll.Mb_start
+ """ % (newdict["Chromosome"], newdict["TxStart"], newdict["TxEnd"]))
+
+ ressnp = cursor.fetchall()
+ newdict["indelCountBXD"] = len(ressnp)
+ newdict["hasindel"] = 'n'
+ newdict["hasexpr"] = 'n'
+ newdict["hascis"] = 'n'
+ newdict["score"] = 0
+ if len(ressnp)>0 :
+ newdict["hasindel"]= 'y'
+
+## # cursor.execute("""
+## # select
+## # Name from ProbeSet
+## # where
+## # GeneId = '%s' AND ChipId=4 limit 1
+## # """ % (newdict["GeneID"]))
+## # if species=='mouse':
+## # cursor.execute("""
+## # select
+## # Name from ProbeSet
+## # where
+## # GeneId = '%s' AND ChipId=4
+## # """ % (newdict["GeneID"]))
+## # results = cursor.fetchall()
+## # psets = []
+## # for item in results:
+## # psets.append(item)
+## # newdict["probeset"] = psets
+## #
+## # else:
+## # newdict["probeset"] = "empty"
+
+
+
+
+ if species=='mouse':
+ cursor.execute("""
+ select
+ distinct 0,
+ ProbeSet.Name as TNAME,
+ round(ProbeSetXRef.Mean,1) as TMEAN,
+ round(ProbeSetXRef.LRS,1) as TLRS,
+ ProbeSet.Chr_num as TCHR_NUM,
+ ProbeSet.Mb as TMB,
+ ProbeSet.Symbol as TSYMBOL,
+ ProbeSet.name_num as TNAME_NUM
+ FROM ProbeSetXRef, ProbeSetFreeze, ProbeSet
+ where
+ ( MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,
+ alias,GenbankId,UniGeneId, Probe_Target_Description)
+ AGAINST ('%s' IN BOOLEAN MODE) )
+ and ProbeSet.symbol = '%s'
+ and ProbeSet.Id = ProbeSetXRef.ProbeSetId
+ and ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id
+ and ProbeSetFreeze.Id = (select Id from ProbeSetFreeze where Name='%s' limit 1)
+ """ % (newdict["GeneSymbol"],newdict["GeneSymbol"],databaseA))
+ resA = cursor.fetchall()
+
+ if resA:
+ myFields = ['dummyA','probesetA','meanA','newlrsA','probesetchrA','probesetmbA','probesetsymbolA','probesetnamenumA']
+
+# fpText = open(os.path.join(webqtlConfig.TMPDIR, "res") + '.txt','wb')
+ #fpText.write("newdictgeneid '%s' \n" % newdict["GeneId"])
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resA:
+ # fpText.write("j: result: '%s' \n" % k[j])
+ temp.append(k[j])
+ newdict[item] = temp
+ # fpText.close()
+
+
+ # put probesetcisA here
+
+ cursor.execute("""
+ select
+ distinct 0,
+ if( (ProbeSet.Chr = Geno.Chr AND ProbeSetXRef.LRS > 10.0000000 and ABS(ProbeSet.Mb-Geno.Mb) < 10.0000000 ) , concat('yes(',round(ProbeSetXRef.LRS,1),')') , 'no') as cis
+ FROM Geno, ProbeSetXRef, ProbeSetFreeze, ProbeSet
+ where
+ ( MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,
+ alias,GenbankId,UniGeneId, Probe_Target_Description)
+ AGAINST ('%s' IN BOOLEAN MODE) )
+ and ProbeSet.symbol = '%s'
+ and ProbeSet.Id = ProbeSetXRef.ProbeSetId
+ and Geno.SpeciesId=1 #XZ: I add this line to speed up query
+ and ProbeSetXRef.Locus = Geno.name
+ and ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id
+ and ProbeSetFreeze.Id = (select Id from ProbeSetFreeze where Name='%s' limit 1)
+ """ % (newdict["GeneSymbol"],newdict["GeneSymbol"],databaseA))
+
+ resA2 = cursor.fetchall()
+ if resA2:
+ myFields = ['dummyA2','probesetcisA']
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resA2:
+ # fpText.write("j: result: '%s' \n" % k[j])
+ temp.append(k[j])
+ newdict[item] = temp
+ else:
+ newdict['probesetcisA'] = ''
+
+
+
+ # specially for this dataset only
+ newdict["hasexpr"] = 'n'
+ if len(newdict["meanA"])>0:
+ for mym in newdict["meanA"]:
+ if mym>8:
+ newdict["hasexpr"] = 'y'
+
+ # specially for this dataset only
+ newdict["hascis"] = 'n'
+ if len(newdict["probesetcisA"])>0:
+ for mym in newdict["probesetcisA"]:
+ if mym != 'no':
+ newdict["hascis"] = 'y'
+
+ else:
+ myFields = ['dummyA','probesetA,''meanA','newlrsA','probesetchrA','probesetmbA','probesetsymbolA','probesetnamenumA', 'probesetcisA']
+ for j, item in enumerate(myFields):
+ newdict[item] = "--"
+
+ # specially for this dataset only
+ newdict["hasexpr"] = 'n'
+ newdict["hascis"] = 'n'
+ newdict["score"] = 0
+
+########################## FOR B
+
+ newdict["score"] = 0
+ if newdict["hassnp"] == 'y':
+ newdict["score"] = newdict["score"] + 1
+ if newdict["hasexpr"] == 'y':
+ newdict["score"] = newdict["score"] + 1
+ if newdict["hasindel"] == 'y':
+ newdict["score"] = newdict["score"] + 1
+ if newdict["hascis"] == 'y':
+ newdict["score"] = newdict["score"] + 1
+
+
+
+ if species=='mouse':
+ cursor.execute("""
+ select
+ distinct 0,
+ ProbeSet.Name as TNAME,
+ round(ProbeSetXRef.Mean,1) as TMEAN,
+ round(ProbeSetXRef.LRS,1) as TLRS,
+ ProbeSet.Chr_num as TCHR_NUM,
+ ProbeSet.Mb as TMB,
+ ProbeSet.Symbol as TSYMBOL,
+ ProbeSet.name_num as TNAME_NUM
+ FROM ProbeSetXRef, ProbeSetFreeze, ProbeSet
+ where
+ ( MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,
+ alias,GenbankId,UniGeneId, Probe_Target_Description)
+ AGAINST ('%s' IN BOOLEAN MODE) )
+ and ProbeSet.symbol = '%s'
+ and ProbeSet.Id = ProbeSetXRef.ProbeSetId
+ and ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id
+ and ProbeSetFreeze.Id = (select Id from ProbeSetFreeze where Name='%s' limit 1)
+ """ % (newdict["GeneSymbol"],newdict["GeneSymbol"],databaseB))
+
+ resB = cursor.fetchall()
+ if resB:
+ myFields = ['dummyB','probesetB','meanB','newlrsB','probesetchrB','probesetmbB','probesetsymbolB','probesetnamenumB']
+
+# fpText = open(os.path.join(webqtlConfig.TMPDIR, "res") + '.txt','wb')
+ #fpText.write("newdictgeneid '%s' \n" % newdict["GeneId"])
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resB:
+ # fpText.write("j: result: '%s' \n" % k[j])
+ temp.append(k[j])
+ newdict[item] = temp
+ # fpText.close()
+
+
+ # put probesetcisB here
+ cursor.execute("""
+ select
+ distinct 0,
+ if( (ProbeSet.Chr = Geno.Chr AND ProbeSetXRef.LRS > 10.0000000 and ABS(ProbeSet.Mb-Geno.Mb) < 10.0000000 ) , concat('yes(',round(ProbeSetXRef.LRS,1),')') , 'no') as cis
+ FROM Geno, ProbeSetXRef, ProbeSetFreeze, ProbeSet
+ where
+ ( MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,
+ alias,GenbankId,UniGeneId, Probe_Target_Description)
+ AGAINST ('%s' IN BOOLEAN MODE) )
+ and ProbeSet.symbol = '%s'
+ and ProbeSet.Id = ProbeSetXRef.ProbeSetId
+ and Geno.SpeciesId=1 #XZ: I add this line to speed up query
+ and ProbeSetXRef.Locus = Geno.name
+ and ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id
+ and ProbeSetFreeze.Id = (select Id from ProbeSetFreeze where Name='%s' limit 1)
+ """ % (newdict["GeneSymbol"],newdict["GeneSymbol"],databaseB))
+
+ resB2 = cursor.fetchall()
+ if resB2:
+ myFields = ['dummyB2','probesetcisB']
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resB2:
+ # fpText.write("j: result: '%s' \n" % k[j])
+ temp.append(k[j])
+ newdict[item] = temp
+ else:
+ newdict['probesetcisB'] = ''
+
+
+ else:
+ myFields = ['dummyB','probesetB,''meanB','newlrsB','probesetchrB','probesetmbB','probesetsymbolB','probesetnamenumB', 'probesetcisB']
+ for j, item in enumerate(myFields):
+ newdict[item] = "--"
+
+
+
+##########################
+
+
+########################## FOR C
+
+
+ if species=='mouse':
+ cursor.execute("""
+ select
+ distinct 0,
+ ProbeSet.Name as TNAME,
+ round(ProbeSetXRef.Mean,1) as TMEAN,
+ round(ProbeSetXRef.LRS,1) as TLRS,
+ ProbeSet.Chr_num as TCHR_NUM,
+ ProbeSet.Mb as TMB,
+ ProbeSet.Symbol as TSYMBOL,
+ ProbeSet.name_num as TNAME_NUM
+ FROM ProbeSetXRef, ProbeSetFreeze, ProbeSet
+ where
+ ( MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,
+ alias,GenbankId,UniGeneId, Probe_Target_Description)
+ AGAINST ('%s' IN BOOLEAN MODE) )
+ and ProbeSet.symbol = '%s'
+ and ProbeSet.Id = ProbeSetXRef.ProbeSetId
+ and ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id
+ and ProbeSetFreeze.Id = (select Id from ProbeSetFreeze where Name='%s' limit 1)
+ """ % (newdict["GeneSymbol"],newdict["GeneSymbol"],databaseC))
+
+ resC = cursor.fetchall()
+ if resC:
+ myFields = ['dummyC','probesetC','meanC','newlrsC','probesetchrC','probesetmbC','probesetsymbolC','probesetnamenumC']
+
+# fpText = open(os.path.join(webqtlConfig.TMPDIR, "res") + '.txt','wb')
+ #fpText.write("newdictgeneid '%s' \n" % newdict["GeneId"])
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resC:
+ # fpText.write("j: result: '%s' \n" % k[j])
+ temp.append(k[j])
+ newdict[item] = temp
+ # fpText.close()
+
+
+ # put probesetcisC here
+ cursor.execute("""
+ select
+ distinct 0,
+ if( (ProbeSet.Chr = Geno.Chr AND ProbeSetXRef.LRS > 10.0000000 and ABS(ProbeSet.Mb-Geno.Mb) < 10.0000000 ) , concat('yes(',round(ProbeSetXRef.LRS,1),')') , 'no') as cis
+ FROM Geno, ProbeSetXRef, ProbeSetFreeze, ProbeSet
+ where
+ ( MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,
+ alias,GenbankId,UniGeneId, Probe_Target_Description)
+ AGAINST ('%s' IN BOOLEAN MODE) )
+ and ProbeSet.symbol = '%s'
+ and ProbeSet.Id = ProbeSetXRef.ProbeSetId
+ and Geno.SpeciesId=1 #XZ: I add this line to speed up query
+ and ProbeSetXRef.Locus = Geno.name
+ and ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id
+ and ProbeSetFreeze.Id = (select Id from ProbeSetFreeze where Name='%s' limit 1)
+ """ % (newdict["GeneSymbol"],newdict["GeneSymbol"],databaseC))
+
+ resC2 = cursor.fetchall()
+ if resC2:
+ myFields = ['dummyC2','probesetcisC']
+ for j, item in enumerate(myFields):
+ temp = []
+ for k in resC2:
+ # fpText.write("j: result: '%s' \n" % k[j])
+ temp.append(k[j])
+ newdict[item] = temp
+ else:
+ newdict['probesetcisC'] = ''
+
+ else:
+ myFields = ['dummyC','probesetC,''meanC','newlrsC','probesetchrC','probesetmbC','probesetsymbolC','probesetnamenumC', 'probesetcisC']
+ for j, item in enumerate(myFields):
+ newdict[item] = "--"
+
+
+
+
+
+
+
+
+ #load gene from other Species by the same name
+
+
+ for item in otherSpecies:
+ othSpec, othSpecId = item
+ newdict2 = {}
+
+ cursor.execute("SELECT %s from GeneList where SpeciesId = %d and geneSymbol= '%s' limit 1" %
+ (string.join(fetchFields, ", "), othSpecId, newdict["GeneSymbol"]))
+ resultsOther = cursor.fetchone()
+ if resultsOther:
+ for j, item in enumerate(fetchFields):
+ newdict2[item] = resultsOther[j]
+
+ #count SNPs if possible, could be a separate function
+ if diffCol and othSpec == 'mouse':
+ cursor.execute("""
+ select
+ count(*) from BXDSnpPosition
+ where
+ Chr = '%s' AND Mb >= %2.6f AND Mb < %2.6f AND
+ StrainId1 = %d AND StrainId2 = %d
+ """ % (chrName, newdict["TxStart"], newdict["TxEnd"], diffCol[0], diffCol[1]))
+
+
+ newdict2["snpCount"] = cursor.fetchone()[0]
+ newdict2["snpDensity"] = newdict2["snpCount"]/(newdict2["TxEnd"]-newdict2["TxStart"])/1000.0
+ else:
+ newdict2["snpDensity"] = newdict2["snpCount"] = 0
+
+ try:
+ newdict2['GeneLength'] = 1000.0*(newdict2['TxEnd'] - newdict2['TxStart'])
+ except:
+ pass
+
+ newdict['%sGene' % othSpec] = newdict2
+
+ #newdict['RUDI']='hallo allemaal'
+
+ GeneList.append(newdict)
+
+
+ return GeneList
+
+
diff --git a/web/webqtl/qtlminer/QTLminer.py b/web/webqtl/qtlminer/QTLminer.py
new file mode 100755
index 00000000..e565cdd7
--- /dev/null
+++ b/web/webqtl/qtlminer/QTLminer.py
@@ -0,0 +1,1237 @@
+#Note that although this module gets imported a bit, the dict columnNames is never used outside this code.
+#Also note that snpBrowser also defines a columnNames dict; it's different. -KA
+
+from htmlgen import HTMLgen2 as HT
+import os
+import time
+import pyXLWriter as xl
+
+import GeneUtil
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+
+_scriptfile = "main.py?FormID=qtlminerresult"
+
+#A dictionary that lets us map the html form names "txStart_mm6" -> "Mb Start (mm8)"
+#the first item is the short name (column headers) and the second item is the long name (dropdown list)
+# [short name, long name, category]
+columnNames = {"GeneSymbol" : ["Gene", "Gene Name", 'gene'],
+ "GeneDescription" : ["Description", "Gene Description", 'species'],
+# "probeset" : ["ProbeSet", "ProbeSet", 'gene'],
+# "probesetsymbolA" : ["ProbeSet Symbol A", "ProbeSetsymbolA", 'gene'],
+# "probesetchrA" : ["probesetchrA", "probesetchrA", 'gene'],
+ "hassnp" : ["Has nsSNP", "Has nsSNP", 'gene'],
+ "hasindel" : ["Has indel", "Has indel", 'gene'],
+ "hasexpr" : ["Has expr", "Has expression", 'gene'],
+ "hascis" : ["Has cis", "Has cis regulation", 'gene'],
+ "score" : ["Score", "Score", 'gene'],
+ "meanA" : ["Expression A", "Expression in dataset 1", 'gene'],
+ "meanB" : ["Expression B", "Expression in dataset 2", 'gene'],
+ "meanC" : ["Expression C", "Expression in dataset 3", 'gene'],
+ "probesetcisA" : ["Cis A", "Cis regulation in dataset 1", 'gene'],
+ "probesetcisB" : ["Cis B", "Cis regulation in dataset 2", 'gene'],
+ "probesetcisC" : ["Cis C", "Cis regulation in dataset 3", 'gene'],
+ "probesetA" : ["ProbeSet A", "ProbeSet in dataset 1", 'gene'],
+ "probesetB" : ["ProbeSet B", "ProbeSet in dataset 2", 'gene'],
+ "probesetC" : ["ProbeSet C", "ProbeSet in dataset 3", 'gene'],
+ "goterms" : ["GO biological process", "GO biological process", 'gene'],
+ "pathways" : ["KEGG PathwayIDs", "KEGG PathwayIDs", 'gene'],
+ "pathwaynames" : ["KEGG Pathways", "KEGG Pathways", 'gene'],
+# "newlrsA" : ["Lrs A", "lrs A", 'gene'],
+# "probesetchrB" : ["probesetchrB", "probesetchrB", 'gene'],
+# "newlrsB" : ["lrs B", "lrs B", 'gene'],
+# "probesetchrC" : ["probesetchrC", "probesetchrC", 'gene'],
+# "newlrsC" : ["lrs C", "lrs C", 'gene'],
+ 'GeneNeighborsCount' : ["Neighbors", "Gene Neighbors", 'gene'],
+ 'GeneNeighborsRange' : ["Neighborhood", "Gene Neighborhood (Mb)", 'gene'],
+ 'GeneNeighborsDensity' : ["Gene Density", "Gene Density (Neighbors/Mb)", 'gene'],
+ "ProteinID" : ["Prot ID", "Protein ID", 'protein'],
+ "Chromosome" : ["Chr", "Chromosome", 'species'],
+ "TxStart" : ["Start", "Mb Start", 'species'],
+ "TxEnd" : ["End", "Mb End", 'species'],
+ "GeneLength" : ["Length", "Kb Length", 'species'],
+ "cdsStart" : ["CDS Start", "Mb CDS Start", 'species'],
+ "cdsEnd" : ["CDS End", "Mb CDS End", 'species'],
+ "exonCount" : ["Num Exons", "Exon Count", 'species'],
+ "exonStarts" : ["Exon Starts", "Exon Starts", 'species'],
+ "exonEnds" : ["Exon Ends", "Exon Ends", 'species'],
+ "Strand" : ["Strand", "Strand", 'species'],
+ "GeneID" : ["Gene ID", "Gene ID", 'species'],
+ "GenBankID" : ["GenBank", "GenBank ID", 'species'],
+ "UnigenID" : ["Unigen", "Unigen ID", 'species'],
+ "NM_ID" : ["NM ID", "NM ID", 'species'],
+ "kgID" : ["kg ID", "kg ID", 'species'],
+ "snpCountall" : ["SNPs", "SNP Count", 'species'],
+ "snpCountmis": ["nsSNPs all", "nsSNP Count all strains", 'species'],
+ "snpCountmissel": ["nsSNPs selected", "nsSNP Count selected strains", 'species'],
+ "snpDensity" : ["SNP Density", "SNP Density", 'species'],
+ "indelCountBXD" : ["Indels in BXD mice", "Indel Count in BXD mice", 'species'],
+ "lrs" : ["LRS", "Likelihood Ratio Statistic", 'misc'],
+ "lod" : ["LOD", "Likelihood Odds Ratio", 'misc'],
+ "pearson" : ["Pearson", "Pearson Product Moment", 'misc'],
+ "literature" : ["Lit Corr", "Literature Correlation", 'misc'],
+ }
+
+###Species Freeze
+speciesFreeze = {'mouse':'mm9', 'rat':'rn3', 'human':'hg19'}
+for key in speciesFreeze.keys():
+ speciesFreeze[speciesFreeze[key]] = key
+
+class QTLminer (templatePage): ###
+ filename = webqtlUtil.genRandStr("Itan_")
+
+ javascript_content = """
+<SCRIPT language="JAVASCRIPT">
+
+function update4(self,form) {
+ self.database='leeg';
+
+}
+
+
+
+
+</SCRIPT>
+"""
+ def __init__(self, fd):
+ templatePage.__init__(self, fd)
+ if not self.openMysql():
+ return
+
+ self.species = fd.formdata.getvalue("species", "mouse")
+ try:
+ self.startMb = float(fd.formdata.getvalue("startMb"))
+ except:
+ self.startMb = 173
+ try:
+ self.endMb = float(fd.formdata.getvalue("endMb"))
+ except:
+ self.endMb = self.startMb + 1
+
+ self.Chr = fd.formdata.getvalue("chromosome", "1")
+
+
+
+######################################################### FOR A
+ ###### species
+
+ self.cursor.execute("""
+ Select
+ Name, Id from Species
+ Order by
+ Id
+ """ )
+ res = self.cursor.fetchall()
+ self.spA = res
+ self.spAsel = fd.formdata.getvalue("myspeciesA", "mouse")
+
+ if not hasattr(self,"spA"):
+ self.spA = res2
+ self.spAsel = 'mouse'
+
+ ###### group
+
+ self.cursor.execute("""
+ select
+ distinct InbredSet.Name, InbredSet.FullName
+ from InbredSet, Species, ProbeFreeze, GenoFreeze, PublishFreeze
+ where
+ InbredSet.SpeciesId= Species.Id and
+ Species.Name='%s' and InbredSet.Name != 'BXD300' and
+ (PublishFreeze.InbredSetId = InbredSet.Id or GenoFreeze.InbredSetId = InbredSet.Id or ProbeFreeze.InbredSetId = InbredSet.Id)
+ order by
+ InbredSet.Name
+ """ % self.spAsel)
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"grA"):
+ self.grA = res
+ self.grAsel = 'BXD'
+
+ if fd.formdata.getvalue('submitter') == 'a1':
+ self.grA = res
+ self.grAsel = self.grA[0][0]
+ else:
+ self.grAsel = fd.formdata.getvalue("groupA","BXD")
+
+ ###### type
+
+ self.cursor.execute("""
+ select
+ distinct Tissue.Name, concat(Tissue.Name, ' mRNA')
+ from ProbeFreeze, ProbeSetFreeze, InbredSet, Tissue
+ where
+ ProbeFreeze.TissueId = Tissue.Id and
+ ProbeFreeze.InbredSetId = InbredSet.Id and
+ InbredSet.Name in ('%s') and
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and
+ ProbeSetFreeze.public > %d
+ order by Tissue.Name
+ """ % (self.grAsel,webqtlConfig.PUBLICTHRESH))
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"tyA"):
+ self.tyA = res
+ self.tyAsel = 'Hippocampus'
+
+ if fd.formdata.getvalue('submitter') in ['a1','a2'] :
+ self.tyA = res
+ self.tyAsel = self.tyA[0][0]
+ else:
+ self.tyAsel = fd.formdata.getvalue("typeA","Hippocampus")
+
+ ###### database
+
+ self.cursor.execute("""
+ select
+ ProbeSetFreeze.Name, ProbeSetFreeze.FullName
+ from ProbeSetFreeze, ProbeFreeze, InbredSet, Tissue
+ where ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and
+ ProbeFreeze.TissueId = Tissue.Id and
+ ProbeFreeze.InbredSetId = InbredSet.Id and
+ InbredSet.Name in ('%s') and Tissue.name = '%s' and
+ ProbeSetFreeze.public > %d
+ order by ProbeSetFreeze.CreateTime desc
+ """ % (self.grAsel,self.tyAsel,webqtlConfig.PUBLICTHRESH))
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"daA"):
+ self.daA = res
+ self.daAsel = 'HC_M2_0606_P'
+
+ if fd.formdata.getvalue('submitter') in ['a1','a2','a3'] :
+ self.daA = res
+ self.daAsel = self.daA[0][0]
+ else:
+ self.daAsel = fd.formdata.getvalue("databaseA","HC_M2_0606_P")
+
+
+######################################################### FOR B
+ ###### species
+
+ self.cursor.execute("""
+ Select
+ Name, Id from Species
+ Order by
+ Id
+ """ )
+ res = self.cursor.fetchall()
+ self.spB = res
+ self.spBsel = fd.formdata.getvalue("myspeciesB", "mouse")
+
+ if not hasattr(self,"spB"):
+ self.spB = res
+ self.spBsel = 'mouse'
+
+ ###### group
+
+ self.cursor.execute("""
+ select
+ distinct InbredSet.Name, InbredSet.FullName
+ from InbredSet, Species, ProbeFreeze, GenoFreeze, PublishFreeze
+ where
+ InbredSet.SpeciesId= Species.Id and
+ Species.Name='%s' and InbredSet.Name != 'BXD300' and
+ (PublishFreeze.InbredSetId = InbredSet.Id or GenoFreeze.InbredSetId = InbredSet.Id or ProbeFreeze.InbredSetId = InbredSet.Id)
+ order by
+ InbredSet.Name
+ """ % self.spBsel)
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"grB"):
+ self.grB = res
+ self.grBsel = 'CXB'
+
+ if fd.formdata.getvalue('submitter') == 'b1':
+ self.grB = res
+ self.grBsel = self.grB[0][0]
+ else:
+ self.grBsel = fd.formdata.getvalue("groupB","CXB")
+
+ ###### type
+
+ self.cursor.execute("""
+ select
+ distinct Tissue.Name, concat(Tissue.Name, ' mRNA')
+ from ProbeFreeze, ProbeSetFreeze, InbredSet, Tissue
+ where
+ ProbeFreeze.TissueId = Tissue.Id and
+ ProbeFreeze.InbredSetId = InbredSet.Id and
+ InbredSet.Name in ('%s') and
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and
+ ProbeSetFreeze.public > %d
+ order by Tissue.Name
+ """ % (self.grBsel,webqtlConfig.PUBLICTHRESH))
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"tyB"):
+ self.tyB = res
+ self.tyBsel = 'Hippocampus'
+
+ if fd.formdata.getvalue('submitter') in ['b1','b2'] :
+ self.tyB = res
+ self.tyBsel = self.tyB[0][0]
+ else:
+ self.tyBsel = fd.formdata.getvalue("typeB","Hippocampus")
+
+ ###### database
+
+ self.cursor.execute("""
+ select
+ ProbeSetFreeze.Name, ProbeSetFreeze.FullName
+ from ProbeSetFreeze, ProbeFreeze, InbredSet, Tissue
+ where ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and
+ ProbeFreeze.TissueId = Tissue.Id and
+ ProbeFreeze.InbredSetId = InbredSet.Id and
+ InbredSet.Name in ('%s') and Tissue.name = '%s' and
+ ProbeSetFreeze.public > %d
+ order by ProbeSetFreeze.CreateTime desc
+ """ % (self.grBsel,self.tyBsel,webqtlConfig.PUBLICTHRESH))
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"daB"):
+ self.daB = res
+ self.daBsel = 'HC_M2CB_1205_R'
+
+ if fd.formdata.getvalue('submitter') in ['b1','b2','b3'] :
+ self.daB = res
+ self.daBsel = self.daB[0][0]
+ else:
+ self.daBsel = fd.formdata.getvalue("databaseB","HC_M2CB_1205_R")
+
+
+
+######################################################### FOR C
+ ###### species
+
+ self.cursor.execute("""
+ Select
+ Name, Id from Species
+ Order by
+ Id
+ """ )
+ res = self.cursor.fetchall()
+ self.spC = res
+ self.spCsel = fd.formdata.getvalue("myspeciesC", "mouse")
+
+ if not hasattr(self,"spC"):
+ self.spC = res
+ self.spCsel = 'mouse'
+
+ ###### group
+
+ self.cursor.execute("""
+ select
+ distinct InbredSet.Name, InbredSet.FullName
+ from InbredSet, Species, ProbeFreeze, GenoFreeze, PublishFreeze
+ where
+ InbredSet.SpeciesId= Species.Id and
+ Species.Name='%s' and InbredSet.Name != 'BXD300' and
+ (PublishFreeze.InbredSetId = InbredSet.Id or GenoFreeze.InbredSetId = InbredSet.Id or ProbeFreeze.InbredSetId = InbredSet.Id)
+ order by
+ InbredSet.Name
+ """ % self.spCsel)
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"grC"):
+ self.grC = res
+ self.grCsel = 'LXS'
+
+ if fd.formdata.getvalue('submitter') == 'c1':
+ self.grC = res
+ self.grCsel = self.grC[0][0]
+ else:
+ self.grCsel = fd.formdata.getvalue("groupC","LXS")
+
+ ###### type
+
+ self.cursor.execute("""
+ select
+ distinct Tissue.Name, concat(Tissue.Name, ' mRNA')
+ from ProbeFreeze, ProbeSetFreeze, InbredSet, Tissue
+ where
+ ProbeFreeze.TissueId = Tissue.Id and
+ ProbeFreeze.InbredSetId = InbredSet.Id and
+ InbredSet.Name in ('%s') and
+ ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and
+ ProbeSetFreeze.public > %d
+ order by Tissue.Name
+ """ % (self.grCsel,webqtlConfig.PUBLICTHRESH))
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"tyC"):
+ self.tyC = res
+ self.tyCsel = 'Hippocampus'
+
+ if fd.formdata.getvalue('submitter') in ['c1','c2'] :
+ self.tyC = res
+ self.tyCsel = self.tyC[0][0]
+ else:
+ self.tyCsel = fd.formdata.getvalue("typeC","Hippocampus")
+
+ ###### database
+
+
+ self.cursor.execute("""
+ select
+ ProbeSetFreeze.Name, ProbeSetFreeze.FullName
+ from ProbeSetFreeze, ProbeFreeze, InbredSet, Tissue
+ where ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and
+ ProbeFreeze.TissueId = Tissue.Id and
+ ProbeFreeze.InbredSetId = InbredSet.Id and
+ InbredSet.Name in ('%s') and Tissue.name = '%s' and
+ ProbeSetFreeze.public > %d
+ order by ProbeSetFreeze.CreateTime desc
+ """ % (self.grCsel,self.tyCsel,webqtlConfig.PUBLICTHRESH))
+
+ res = self.cursor.fetchall()
+
+ if not hasattr(self,"daC"):
+ self.daC = res
+ self.daCsel = 'Illum_LXS_Hipp_loess0807'
+
+ if fd.formdata.getvalue('submitter') in ['c1','c2','c3'] :
+ self.daC = res
+ self.daCsel = self.daC[0][0]
+ else:
+ self.daCsel = fd.formdata.getvalue("databaseC","Illum_LXS_Hipp_loess0807")
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# self.myspeciesA = fd.formdata.getvalue("myspeciesA", "mouse")
+# self.groupA = fd.formdata.getvalue("groupA", "BXD")
+# self.typeA = fd.formdata.getvalue("typeA", "Spleen")
+# self.databaseA = fd.formdata.getvalue("databaseA", "IoP_SPL_RMA_0509")#
+
+# self.myspeciesB = fd.formdata.getvalue("myspeciesB", "mouse")
+# self.groupB = fd.formdata.getvalue("groupB", "BXD")
+# self.typeB = fd.formdata.getvalue("typeB", "Spleen")
+# self.databaseB = fd.formdata.getvalue("databaseB", "IoP_SPL_RMA_0509")
+
+ self.xls = fd.formdata.getvalue("xls", "1")
+ try:
+ s1 = int(fd.formdata.getvalue("s1"))
+ s2 = int(fd.formdata.getvalue("s2"))
+ self.diffColDefault = self.diffCol = [s1, s2]
+ except:
+ self.diffColDefault = self.diffCol = []
+ if self.species != 'mouse':
+ self.diffColDefault = [2, 3]#default is B6 and D2 for other species
+
+
+
+ self.str1 = fd.formdata.getvalue("str1", "C57BL/6J")
+ self.str2 = fd.formdata.getvalue("str2", "DBA/2J")
+ self.sorton = fd.formdata.getvalue("sorton", "Position")
+
+ controlFrm, dispFields, dispFields2 = self.genControlForm(fd)
+ ## if not fd.formdata.getvalue('submitter') in ['a1','a2','a3''a4'] :
+
+ self.cursor.execute("""select Id from Strain where Name='%s'
+ """ % self.str1 )
+ strain1 = self.cursor.fetchone()[0]
+ self.cursor.execute("""select Id from Strain where Name='%s'
+ """ % self.str2 )
+ strain2 = self.cursor.fetchone()[0]
+
+ filename=''
+ if fd.formdata.getvalue('submitter') in ['refresh'] or not hasattr(self,"daA"):
+ geneTable, filename = self.genGeneTable(fd, dispFields, strain1, strain2)
+
+ infoTD = HT.TD(width=400, valign= "top")
+ infoTD.append(HT.Paragraph("QTLminer : Chr %s" % self.Chr, Class="title"),
+# HT.Strong("Species : "), self.species.title(), HT.BR(),
+
+# HT.Strong("myspeciesA : "), self.myspeciesA, HT.BR(),
+# HT.Strong("groupA : "), self.groupA, HT.BR(),
+# HT.Strong("typeA : "), self.typeA, HT.BR(),
+# HT.Strong("databaseA : "), self.databaseA, HT.BR(),
+
+# HT.Strong("myspeciesB : "), self.myspeciesB, HT.BR(),
+# HT.Strong("groupB : "), self.groupB, HT.BR(),
+# HT.Strong("typeB : "), self.typeB, HT.BR(),
+# HT.Strong("databaseB : "), self.databaseB, HT.BR(),
+
+# HT.Strong("spAsel : "), self.spAsel, HT.BR(),
+# HT.Strong("grAsel : "), self.grAsel, HT.BR(),
+# HT.Strong("tyAsel : "), self.tyAsel, HT.BR(),
+# HT.Strong("daAsel : "), self.daAsel, HT.BR(),
+
+# HT.Strong("spBsel : "), self.spBsel, HT.BR(),
+# HT.Strong("grBsel : "), self.grBsel, HT.BR(),
+# HT.Strong("tyBsel : "), self.tyBsel, HT.BR(),
+# HT.Strong("daBsel : "), self.daBsel, HT.BR(),
+
+# HT.Strong("chr : "), self.Chr, HT.BR(),
+# HT.Strong("formdata.submitter :"), fd.formdata.getvalue("submitter"), HT.BR(),
+# HT.Strong("formdata.myspeciesA : "), fd.formdata.getvalue("myspeciesA"), HT.BR(),
+# HT.Strong("formdata.groupA: "), fd.formdata.getvalue("groupA") , HT.BR(),
+# HT.Strong("formdata.myspeciesB : "), fd.formdata.getvalue("myspeciesB"), HT.BR(),
+# HT.Strong("formdata.groupB: "), fd.formdata.getvalue("groupB") , HT.BR(),
+# HT.Strong("formdata.type: "), fd.formdata.getvalue("type") , HT.BR(),
+# HT.Strong("formdata.database: "), fd.formdata.getvalue("database") , HT.BR(),
+# HT.Strong("Database : "), "UCSC %s" % speciesFreeze[self.species], HT.BR(),
+ HT.Strong("Range : "), "%2.6f Mb - %2.6f Mb" % (self.startMb, self.endMb), HT.BR(),
+ )
+
+ if filename:
+ infoTD.append(HT.BR(), HT.BR(), HT.Href(text="Download", url = "/tmp/" + filename, Class="normalsize")
+ , " output in MS excel format.")
+
+ mainTable = HT.TableLite(HT.TR(infoTD, HT.TD(controlFrm, Class="doubleBorder", width=400), HT.TD("&nbsp;", width="")), cellpadding=10)
+
+ if fd.formdata.getvalue('submitter') in ['refresh'] or not hasattr(self,"daA"):
+ mainTable.append(HT.TR(HT.TD(geneTable, colspan=3)))
+
+ self.dict['body'] = HT.TD(mainTable)
+ self.dict['title'] = "QTLminer"
+
+ self.cursor.close();
+
+ def genGeneTable(self, fd, dispFields, strain1, strain2):
+
+ filename = ""
+ if self.xls:
+ #import pyXLWriter as xl
+ filename = "IntAn_Chr%s_%2.6f-%2.6f" % (self.Chr, self.startMb, self.endMb)
+ filename += ".xls"
+
+ # Create a new Excel workbook
+ workbook = xl.Writer(os.path.join(webqtlConfig.TMPDIR, filename))
+ worksheet = workbook.add_worksheet()
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=18, border = 1, border_color="gray")
+ headingStyle = workbook.add_format(align = 'center', bold = 1, size=13, fg_color = 0x1E, color="white", border = 1, border_color="gray")
+
+ ##Write title Info
+ worksheet.write([0, 0], "GeneNetwork Interval Analyst Table", titleStyle)
+ worksheet.write([1, 0], "%s%s" % (webqtlConfig.PORTADDR, os.path.join(webqtlConfig.CGIDIR, _scriptfile)))
+ #
+ worksheet.write([2, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()))
+ worksheet.write([3, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()))
+ worksheet.write([4, 0], "Search by : %s" % fd.remote_ip)
+ worksheet.write([5, 0], "view region : Chr %s %2.6f - %2.6f Mb" % (self.Chr, self.startMb, self.endMb))
+ nTitleRow = 7
+
+ geneTable = HT.TableLite(Class="collap", cellpadding=5)
+ headerRow = HT.TR(HT.TD(" ", Class="fs13 fwb ffl b1 cw cbrb", width="1"))
+ if self.xls:
+ worksheet.write([nTitleRow, 0], "Index", headingStyle)
+
+ for ncol, column in enumerate(dispFields):
+ if column[0]=='meanA':
+ headerRow.append(HT.TD("Expression in" , HT.BR(), self.grAsel, HT.BR(), self.tyAsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='meanB':
+ headerRow.append(HT.TD("Expression in" , HT.BR(), self.grBsel, HT.BR(), self.tyBsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='meanC':
+ headerRow.append(HT.TD("Expression in" , HT.BR(), self.grCsel, HT.BR(), self.tyCsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='probesetcisA':
+ headerRow.append(HT.TD("Cis regulated in" , HT.BR(), self.grAsel, HT.BR(), self.tyAsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='probesetcisB':
+ headerRow.append(HT.TD("Cis regulated in" , HT.BR(), self.grBsel, HT.BR(), self.tyBsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='probesetcisC':
+ headerRow.append(HT.TD("Cis regulated in" , HT.BR(), self.grCsel, HT.BR(), self.tyCsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='probesetA':
+ headerRow.append(HT.TD("Probeset in" , HT.BR(), self.grAsel, HT.BR(), self.tyAsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='probesetB':
+ headerRow.append(HT.TD("Probeset in" , HT.BR(), self.grBsel, HT.BR(), self.tyBsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='probesetC':
+ headerRow.append(HT.TD("Probeset in" , HT.BR(), self.grCsel, HT.BR(), self.tyCsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='hasexpr':
+ headerRow.append(HT.TD("Has expression in" , HT.BR(), self.grAsel, HT.BR(), self.tyAsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='hascis':
+ headerRow.append(HT.TD("Cis regulated in" , HT.BR(), self.grAsel, HT.BR(), self.tyAsel, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='snpCountmis':
+ headerRow.append(HT.TD("nsSNPs" , HT.BR(), "all strains", HT.BR(), " ", Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ elif column[0]=='snpCountmissel':
+ headerRow.append(HT.TD("nsSNPs" , HT.BR(), self.str1, " vs", HT.BR(), self.str2, Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+
+
+
+
+ elif len(column) == 1:
+ # header
+ headerRow.append(HT.TD(columnNames[column[0]][0], Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1,align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ else:
+ # header
+ headerRow.append(HT.TD(columnNames[column[0]][0], HT.BR(), " (%s)" % speciesFreeze[column[1]],
+ Class="fs13 fwb ffl b1 cw cbrb", NOWRAP=1, align="Center"))
+ if self.xls:
+ colTitle = columnNames[column[0]][0] + " (%s)" % speciesFreeze[column[1]]
+ worksheet.write([nTitleRow, ncol+1], colTitle, headingStyle)
+ worksheet.set_column([ncol+1, ncol+1], 2*len(colTitle))
+ #headerRow.append(HT.TD(columnNames[column[0]][0], HT.BR(),
+ # "(%s %s)" % (column[1].title(), speciesFreeze[column[1]]),
+ # Class="colorBlue", NOWRAP=1, align="Center"))
+ geneTable.append(headerRow)
+
+ geneColnul = GeneUtil.loadGenesForQTLminer(self.cursor, self.Chr, self.diffColDefault, self.startMb, self.endMb, species=self.species, databaseA=self.daAsel, databaseB=self.daBsel, databaseC=self.daCsel, str1=self.str1, str2=self.str2)
+
+ # scores = []
+ # for gIndex, theGO in enumerate(geneCol):
+ # keyValue = ""
+ # fieldName = 'score'
+ # if theGO.has_key(fieldName):
+ # keyValue = theGO[fieldName]
+ # scores.append(keyValue)
+
+ sort_on = "TxStart"
+ myrev = False
+ if self.sorton == "Score":
+ sort_on = "score"
+ myrev = True
+ geneColeen = [(dict_[sort_on], dict_) for dict_ in geneColnul]
+ geneColeen.sort(reverse=myrev)
+ geneCol = [dict_ for (key, dict_) in geneColeen]
+
+
+
+ for gIndex, theGO in enumerate(geneCol):
+ geneRow = HT.TR(HT.TD(gIndex+1, Class="fs12 fwn b1", align="right"))
+ if self.xls:
+ nTitleRow += 1
+ worksheet.write([nTitleRow, 0], gIndex + 1)
+
+ for ncol, column in enumerate(dispFields):
+ if len(column) == 1 or column[1]== self.species:
+ keyValue = ""
+ fieldName = column[0]
+ curSpecies = self.species
+ curGO = theGO
+ if theGO.has_key(fieldName):
+ keyValue = theGO[fieldName]
+ else:
+ fieldName , othSpec = column
+ curSpecies = othSpec
+ subGO = '%sGene' % othSpec
+ keyValue = ""
+ curGO = theGO[subGO]
+ if theGO[subGO].has_key(fieldName):
+ keyValue = theGO[subGO][fieldName]
+
+ if self.xls:
+ worksheet.write([nTitleRow, ncol+1], keyValue)
+ geneRow.append(self.formatTD(keyValue, fieldName, curSpecies, curGO, strain1, strain2))
+
+ geneTable.append(geneRow)
+
+ if self.xls:
+ workbook.close()
+ return geneTable, filename
+
+ def formatTD(self, keyValue, fieldName, Species, theGO, strain1, strain2):
+ if keyValue is None:
+ keyValue = ""
+ if keyValue != "":
+ if fieldName in ("exonStarts", "exonEnds"):
+ keyValue = string.replace(keyValue, ',', ' ')
+ return HT.TD(HT.Span(keyValue, Class="code", Id="green"), width=350, Class="fs12 fwn b1")
+ elif fieldName in ("GeneDescription"):
+ if keyValue == "---":
+ keyValue = ""
+ return HT.TD(keyValue, Class="fs12 fwn b1", width=300)
+ elif fieldName in ("GeneSymbol"):
+ webqtlLink = HT.Href("./%s/%s?cmd=sch&gene=%s&alias=1&species=%s" % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, keyValue, Species),
+ HT.Image("/images/webqtl_search.gif", border=0, valign="top"), target="_blank")
+ if theGO['GeneID']:
+ geneSymbolLink = HT.Href(webqtlConfig.NCBI_LOCUSID % theGO['GeneID'], keyValue, Class="normalsize", target="_blank")
+ else:
+ geneSymbolLink = keyValue
+ return HT.TD(webqtlLink, geneSymbolLink, Class="fs12 fwn b1",NOWRAP=1)
+ elif fieldName == 'UnigenID':
+ try:
+ gurl = HT.Href(webqtlConfig.UNIGEN_ID % tuple(string.split(keyValue,'.')[:2]), keyValue, Class="normalsize", target="_blank")
+ except:
+ gurl = keyValue
+ return HT.TD(gurl, Class="fs12 fwn b1",NOWRAP=1)
+ elif fieldName in ("exonCount", "Chromosome"):
+ return HT.TD(keyValue, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("snpCount"):
+ return HT.TD(keyValue, Class="fs12 fwn b1",NOWRAP=1)
+ elif fieldName in ("snpCountmis"):
+ snpString = HT.Href(url="%s?FormID=SnpBrowserResultPage&submitStatus=1&chr=%s&start=%s&end=%s&domain=Exon&variant=SNP" % (os.path.join(webqtlConfig.CGIDIR, 'main.py'),theGO["Chromosome"], theGO["TxStart"], theGO["TxEnd"] ), text=theGO["snpCountmis"], target="_blank", Class="normalsize")
+ return HT.TD(snpString, Class="fs12 fwn b1",NOWRAP=1)
+ elif fieldName in ("snpCountmissel"):
+ snpString = HT.Href(url="%s?FormID=SnpBrowserResultPage&submitStatus=1&chr=%s&start=%s&end=%s&domain=Exon&variant=SNP&customStrain=1&diffAlleles=1&chosenStrains=%s,%s" % (os.path.join(webqtlConfig.CGIDIR, 'main.py'),theGO["Chromosome"], theGO["TxStart"], theGO["TxEnd"], self.str1, self.str2 ), text=theGO["snpCountmissel"], target="_blank", Class="normalsize")
+ return HT.TD(snpString, Class="fs12 fwn b1",NOWRAP=1)
+
+
+# if keyValue:
+# snpString = HT.Href(url="%s?chr=%s&start=%s&end=%s&geneName=%s&s1=%d&s2=%d" % (os.path.join(webqtlConfig.CGIDIR, 'snpBrowser.py'), theGO["Chromosome"], theGO["TxStart"], theGO["TxEnd"], theGO["GeneSymbol"], self.diffColDefault[0], self.diffColDefault[1]), text=theGO["snpCount"], target="_blank", Class="normalsize")
+# else:
+# snpString = keyValue
+# return HT.TD(snpString, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("snpDensity", "GeneLength"):
+ if keyValue: keyValue = "%2.3f" % keyValue
+ else: keyValue = ""
+ return HT.TD(keyValue, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("TxStart", "TxEnd"):
+ return HT.TD("%2.6f" % keyValue, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("score"):
+ return HT.TD("%1d" % keyValue, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("pathways", "pathwaynames", "goterms"):
+ html = HT.Paragraph(Class="fs12 fwn b1")
+ for kk in keyValue:
+ html.append(kk,HT.BR())
+ return HT.TD(html, Class="fs12 fwn b1",align="right",NOWRAP=1)
+ elif fieldName in ("probesetA", "probesetB", "probesetC"):
+ html = HT.Paragraph(Class="fs12 fwn b1")
+ for kk in keyValue:
+ html.append(kk,HT.BR())
+ return HT.TD(html, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("probesetsymbolA"):
+ html = HT.Paragraph(Class="fs12 fwn b1")
+ for kk in keyValue:
+ html.append(kk,HT.BR())
+ return HT.TD(html, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("meanA", "meanB", "meanC"):
+ html = HT.Paragraph(Class="fs12 fwn b1")
+ for kk in keyValue:
+ html.append(str(round(kk,1)),HT.BR())
+ return HT.TD(html, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("hassnp", "hasindel", "hasexpr","hascis"):
+ html = HT.Paragraph(Class="fs12 fwn b1")
+ for kk in keyValue:
+ html.append(kk,HT.BR())
+ return HT.TD(html, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("newlrsA", "newlrsB", "newlrsC"):
+ html = HT.Paragraph(Class="fs12 fwn b1")
+ for kk in keyValue:
+ html.append(str(round(kk,1)),HT.BR())
+ return HT.TD(html, Class="fs12 fwn b1",align="right")
+ elif fieldName in ("probesetcisA", "probesetcisB", "probesetcisC"):
+ html = HT.Paragraph(Class="fs12 fwn b1")
+ for kk in keyValue:
+ html.append(kk,HT.BR())
+# if kk==0:
+# html.append('no',HT.BR())
+# if kk==1:
+# html.append('yes',HT.BR())
+ return HT.TD(html, Class="fs12 fwn b1",align="right")
+ else:
+ return HT.TD(keyValue, Class="fs12 fwn b1",NOWRAP=1)
+ else:
+ return HT.TD(keyValue, Class="fs12 fwn b1",NOWRAP=1,align="right")
+
+# def getStrainNameList(self, strain_data):
+# return strain_data[1:]
+ def getStrainNamePair(self):
+ strainNamePair=[]
+ query ='SELECT * FROM SnpPattern limit 1'
+ self.cursor.execute(query)
+ num_fields = len(self.cursor.description)
+ field_names = [i[0] for i in self.cursor.description]
+ strainsNameList=field_names[1:]
+ for index, name in enumerate(strainsNameList):
+ strainNamePair.append((name,name))
+ return strainNamePair
+
+ def genControlForm(self, fd):
+ ##desc GeneList
+ self.cursor.execute("Desc GeneList")
+ GeneListFields = self.cursor.fetchall()
+ GeneListFields = map(lambda X: X[0], GeneListFields)
+
+ #group columns by category--used for creating the dropdown list of possible columns
+ categories = {}
+ for item in columnNames.keys():
+ category = columnNames[item]
+ if category[-1] not in categories.keys():
+ categories[category[-1]] = [item ]
+ else:
+ categories[category[-1]] = categories[category[-1]]+[item]
+
+ ##List All Species in the Gene Table
+ speciesDict = {}
+ self.cursor.execute("select Species.Name, GeneList.SpeciesId from Species, GeneList where \
+ GeneList.SpeciesId = Species.Id group by GeneList.SpeciesId order by Species.Id")
+ results = self.cursor.fetchall()
+ speciesField = categories.pop('species', [])
+ categoriesOrder = ['gene', 'protein']
+ for item in results:
+ specName, specId = item
+ categoriesOrder.append(specName)
+ speciesDict[specName] = specId
+ AppliedField = []
+ for item2 in speciesField:
+ if item2 in GeneListFields:
+ self.cursor.execute("select %s from GeneList where SpeciesId = %d and %s is not NULL limit 1 " % (item2, specId, item2))
+ columnApply = self.cursor.fetchone()
+ if not columnApply:
+ continue
+ elif specName != 'mouse' and item2 in ('snpCount', 'snpDensity'):
+ continue
+ else:
+ pass
+ AppliedField.append(item2)
+ categories[specName] = AppliedField
+
+ categoriesOrder += ['misc']
+
+ s1_data = self.getStrainNamePair()
+ self.allStrainNames = s1_data[1:]
+
+
+
+ ############################################################
+ ## Create the list of possible columns for the dropdown list
+ ############################################################
+ allColumnsList = HT.Select(name="allColumns", Class="snpBrowserDropBox")#onChange="addToList(this.form.allColumns.options[this.form.allColumns.selectedIndex].text, this.form.allColumns.options[this.form.allColumns.selectedIndex].value, this.form.columns)")
+
+ for category in categoriesOrder:
+ allFields = categories[category]
+ if allFields:
+ geneOpt = HT.Optgroup(label=category.title())
+ for item in allFields:
+ if category in speciesFreeze.keys():
+ geneOpt.append(("%s (%s %s)" % (columnNames[item][1], category.title(), speciesFreeze[category]),
+ "%s__%s" % (item, speciesFreeze[category])))
+ else:
+ geneOpt.append((columnNames[item][1], item))
+ geneOpt.sort()
+ allColumnsList.append(geneOpt)
+
+ allColumnsList2 = HT.Select(name="allColumns2", Class="snpBrowserDropBox")
+ for item in self.allStrainNames:
+ allColumnsList2.append(item)
+
+ ######################################
+ ## Create the list of selected columns
+ ######################################
+
+ #cols contains the value of all the selected columns
+ submitCols = cols = fd.formdata.getvalue("columns", "default")
+
+ if cols == "default":
+ if self.species=="mouse": #these are the same columns that are shown on intervalPage.py
+ cols = ['GeneSymbol', 'GeneDescription', 'goterms', 'pathwaynames', 'Chromosome', 'TxStart', 'snpCountmis', 'snpCountmissel', 'meanA', 'meanB', 'meanC', 'probesetcisA','probesetcisB','probesetcisC', 'probesetA','probesetB','probesetC', 'indelCountBXD','hassnp','hasindel','hasexpr','hascis','score']
+ elif self.species=="rat":
+ cols = ['GeneSymbol', 'GeneDescription', 'Chromosome', 'TxStart', 'GeneLength', 'Strand', 'GeneID', 'UnigenID']
+ else:
+ #should not happen
+ cols = []
+ else:
+ if type(cols)==type(""):
+ cols = [cols]
+
+ colsLst = []
+ dispFields = []
+ for column in cols:
+ if submitCols == "default" and column not in ('GeneSymbol') and (column in GeneListFields or column in speciesField):
+ colsLst.append(("%s (%s %s)" % (columnNames[column][1], self.species.title(), speciesFreeze[self.species]),
+ "%s__%s" % (column, speciesFreeze[self.species])))
+ dispFields.append([column, self.species])
+ else:
+ column2 = column.split("__")
+ if len(column2) == 1:
+ colsLst.append((columnNames[column2[0]][1], column))
+ dispFields.append([column])
+ else:
+ thisSpecies = speciesFreeze[column2[1]]
+ colsLst.append(("%s (%s %s)" % (columnNames[column2[0]][1], thisSpecies.title(), column2[1]),
+ column))
+ dispFields.append((column2[0], thisSpecies))
+ selectedColumnsList = HT.Select(name="columns", Class="snpBrowserSelectBox", multiple="true", data=colsLst, size=6)
+
+
+
+ ######### now for the strains!!!!!!
+
+ #cols contains the value of all the selected columns
+ submitCols2 = cols2 = fd.formdata.getvalue("columns2", "default")
+
+ if cols2 == "default":
+ if self.species=="mouse": #these are the same columns that are shown on intervalPage.py
+ cols2 = ['C57BL/6J', 'DBA/2J',]
+ else:
+ #should not happen
+ cols2 = []
+ else:
+ if type(cols2)==type(""):
+ cols2 = [cols2]
+
+ colsLst2 = []
+ dispFields2 = []
+ for column2 in cols2:
+# if submitCols2 == "default" and (column in GeneListFields or column in speciesField):
+# colsLst2.append(("%s (%s %s)" % (columnNames[column][1], self.species.title(), speciesFreeze[self.species]),
+# "%s__%s" % (column, speciesFreeze[self.species])))
+# dispFields.append([column, self.species])
+# else:
+# column2 = column.split("__")
+# if len(column2) == 1:
+ colsLst2.append((column2, column2))
+ dispFields2.append([column2])
+ selectedColumnsList2 = HT.Select(name="columns2", Class="snpBrowserSelectBox", multiple="true", data=colsLst2, size=6)
+
+ ######### now for the sorton
+
+ #cols contains the value of all the selected columns
+ submitCols3 = cols3 = fd.formdata.getvalue("columns3", "default")
+
+ if cols3 == "default":
+ if self.species=="mouse": #these are the same columns that are shown on intervalPage.py
+ cols3 = ['Position', 'Score',]
+ else:
+ #should not happen
+ cols3 = []
+ else:
+ if type(cols3)==type(""):
+ cols3 = [cols3]
+
+ colsLst3 = []
+ dispFields3 = []
+ for column3 in cols3:
+ colsLst3.append((column3, column3))
+ dispFields3.append([column3])
+ selectedColumnsList3 = HT.Select(name="columns3", Class="snpBrowserSelectBox", multiple="true", data=colsLst3, size=6)
+
+
+
+
+
+ ##########################
+ ## Create the columns form
+ ##########################
+ columnsForm = HT.Form(name="columnsForm", submit=HT.Input(type='hidden'), cgi=os.path.join(webqtlConfig.CGIDIR, _scriptfile), enctype="multipart/form-data")
+ columnsForm.append(HT.Input(type="hidden", name="fromdatabase", value= fd.formdata.getvalue("fromdatabase", "unknown")))
+ columnsForm.append(HT.Input(type="hidden", name="species", value=self.species))
+ columnsForm.append(HT.Input(type="hidden", name="submitter", value="empty"))
+ if self.diffCol:
+ columnsForm.append(HT.Input(type="hidden", name="s1", value=self.diffCol[0]))
+ columnsForm.append(HT.Input(type="hidden", name="s2", value=self.diffCol[1]))
+ startBox = HT.Input(type="text", name="startMb", value=self.startMb, size=10)
+ endBox = HT.Input(type="text", name="endMb", value=self.endMb, size=10)
+ addButton = HT.Input(type="button", name="add", value="Add", Class="button", onClick="addToList(this.form.allColumns.options[this.form.allColumns.selectedIndex].text, this.form.allColumns.options[this.form.allColumns.selectedIndex].value, this.form.columns)")
+# addButton2 = HT.Input(type="button", name="add", value="Add", Class="button", onClick="addToList(this.form.allColumns2.options[this.form.allColumns2.selectedIndex].text, this.form.allColumns2.options[this.form.allColumns2.selectedIndex].value, this.form.columns2)")
+ removeButton = HT.Input(type="button", name="remove", value="Remove", Class="button", onClick="removeFromList(this.form.columns.selectedIndex, this.form.columns)")
+# removeButton2 = HT.Input(type="button", name="remove", value="Remove", Class="button", onClick="removeFromList(this.form.columns2.selectedIndex, this.form.columns2)")
+ upButton = HT.Input(type="button", name="up", value="Up", Class="button", onClick="swapOptions(this.form.columns.selectedIndex, this.form.columns.selectedIndex-1, this.form.columns)")
+ downButton = HT.Input(type="button", name="down", value="Down", Class="button", onClick="swapOptions(this.form.columns.selectedIndex, this.form.columns.selectedIndex+1, this.form.columns)")
+ clearButton = HT.Input(type="button", name="clear", value="Clear", Class="button", onClick="deleteAllElements(this.form.columns)")
+ submitButton = HT.Input(type="submit", value="Analyze QTL interval", Class="button", onClick="Javascript:this.form.submitter.value='refresh';selectAllElements(this.form.columns)")
+
+
+ selectChrBox = HT.Select(name="chromosome")
+ self.cursor.execute("""
+ Select
+ Chr_Length.Name, Length from Chr_Length, Species
+ where
+ Chr_Length.SpeciesId = Species.Id AND
+ Species.Name = '%s'
+ Order by
+ Chr_Length.OrderId
+ """ % self.species)
+
+ results = self.cursor.fetchall()
+ for chrInfo in results:
+ selectChrBox.append((chrInfo[0], chrInfo[0]))
+ selectChrBox.selected.append(self.Chr)
+
+############################################ 2 strain boxes
+
+ selectstr1 = HT.Select(name="str1")
+ for item in self.allStrainNames:
+ selectstr1.append(item[0])
+ selectstr1.selected.append(self.str1)
+
+ selectstr2 = HT.Select(name="str2")
+ for item in self.allStrainNames:
+ selectstr2.append(item[0])
+ selectstr2.selected.append(self.str2)
+
+############################################ select sort on
+
+ selectsorton = HT.Select(name="sorton")
+ selectsorton.append('Position')
+ selectsorton.append('Score')
+ selectsorton.selected.append('Position')
+
+
+############################################
+ selectSpeciesBoxA = HT.Select(name="myspeciesA",onChange="Javascript:this.form.submitter.value='s2';submit();")
+ for speciesInfo in self.spA:
+ name = ''
+ if speciesInfo[0]=='mouse':
+ name='Mouse'
+ elif speciesInfo[0]=='rat':
+ name='Rat'
+ elif speciesInfo[0]=='arabidopsis':
+ name='Arabidopsis thaliana'
+ elif speciesInfo[0]=='human':
+ name='Human'
+ elif speciesInfo[0]=='barley':
+ name='Barley'
+ elif speciesInfo[0]=='drosophila':
+ name='Drosophila'
+ elif speciesInfo[0]=='macaque monkey':
+ name='Macaque Monkey'
+
+ selectSpeciesBoxA.append((name, speciesInfo[0]))
+ selectSpeciesBoxA.selected.append(self.spAsel)
+
+ selectGroupBoxA = HT.Select(name="groupA",onChange="Javascript:this.form.submitter.value='a2';submit();")
+ for groupInfo in self.grA:
+ selectGroupBoxA.append((groupInfo[1], groupInfo[0]))
+ selectGroupBoxA.selected.append(self.grAsel)
+
+ selectTypeBoxA = HT.Select(name="typeA",onChange="Javascript:this.form.submitter.value='a3';submit();")
+ for typeInfo in self.tyA:
+ selectTypeBoxA.append((typeInfo[0] + ' mRNA', typeInfo[0]))
+ selectTypeBoxA.selected.append(self.tyAsel)
+
+ selectDatabaseBoxA = HT.Select(name="databaseA",onChange="Javascript:this.form.submitter.value='a4';submit();")
+ for databaseInfo in self.daA:
+ selectDatabaseBoxA.append((databaseInfo[1], databaseInfo[0]))
+ selectDatabaseBoxA.selected.append(self.daAsel)
+
+#############################
+############################################
+ selectSpeciesBoxB = HT.Select(name="myspeciesB",onChange="Javascript:this.form.submitter.value='b1';submit();")
+ for speciesInfo in self.spB:
+ name = ''
+ if speciesInfo[0]=='mouse':
+ name='Mouse'
+ elif speciesInfo[0]=='rat':
+ name='Rat'
+ elif speciesInfo[0]=='arabidopsis':
+ name='Arabidopsis thaliana'
+ elif speciesInfo[0]=='human':
+ name='Human'
+ elif speciesInfo[0]=='barley':
+ name='Barley'
+ elif speciesInfo[0]=='drosophila':
+ name='Drosophila'
+ elif speciesInfo[0]=='macaque monkey':
+ name='Macaque Monkey'
+
+ selectSpeciesBoxB.append((name, speciesInfo[0]))
+ selectSpeciesBoxB.selected.append(self.spBsel)
+
+ selectGroupBoxB = HT.Select(name="groupB",onChange="Javascript:this.form.submitter.value='b2';submit();")
+ for groupInfo in self.grB:
+ selectGroupBoxB.append((groupInfo[1], groupInfo[0]))
+ selectGroupBoxB.selected.append(self.grBsel)
+
+ selectTypeBoxB = HT.Select(name="typeB",onChange="Javascript:this.form.submitter.value='b3';submit();")
+ for typeInfo in self.tyB:
+ selectTypeBoxB.append((typeInfo[0] + ' mRNA', typeInfo[0]))
+ selectTypeBoxB.selected.append(self.tyBsel)
+
+ selectDatabaseBoxB = HT.Select(name="databaseB",onChange="Javascript:this.form.submitter.value='b4';submit();")
+ for databaseInfo in self.daB:
+ selectDatabaseBoxB.append((databaseInfo[1], databaseInfo[0]))
+ selectDatabaseBoxB.selected.append(self.daBsel)
+
+############################################
+#############################
+############################################
+ selectSpeciesBoxC = HT.Select(name="myspeciesC",onChange="Javascript:this.form.submitter.value='c1';submit();")
+ for speciesInfo in self.spC:
+ name = ''
+ if speciesInfo[0]=='mouse':
+ name='Mouse'
+ elif speciesInfo[0]=='rat':
+ name='Rat'
+ elif speciesInfo[0]=='arabidopsis':
+ name='Arabidopsis thaliana'
+ elif speciesInfo[0]=='human':
+ name='Human'
+ elif speciesInfo[0]=='barley':
+ name='Barley'
+ elif speciesInfo[0]=='drosophila':
+ name='Drosophila'
+ elif speciesInfo[0]=='macaque monkey':
+ name='Macaque Monkey'
+
+ selectSpeciesBoxC.append((name, speciesInfo[0]))
+ selectSpeciesBoxC.selected.append(self.spCsel)
+
+ selectGroupBoxC = HT.Select(name="groupC",onChange="Javascript:this.form.submitter.value='c2';submit();")
+ for groupInfo in self.grC:
+ selectGroupBoxC.append((groupInfo[1], groupInfo[0]))
+ selectGroupBoxC.selected.append(self.grCsel)
+
+ selectTypeBoxC = HT.Select(name="typeC",onChange="Javascript:this.form.submitter.value='c3';submit();")
+ for typeInfo in self.tyC:
+ selectTypeBoxC.append((typeInfo[0] + ' mRNA', typeInfo[0]))
+ selectTypeBoxC.selected.append(self.tyCsel)
+
+ selectDatabaseBoxC = HT.Select(name="databaseC",onChange="Javascript:this.form.submitter.value='c4';submit();")
+ for databaseInfo in self.daC:
+ selectDatabaseBoxC.append((databaseInfo[1], databaseInfo[0]))
+ selectDatabaseBoxC.selected.append(self.daCsel)
+
+############################################
+
+
+
+
+#############################
+
+
+
+
+ innerColumnsTable = HT.TableLite(border=0, Class="collap", cellpadding = 2)
+ innerColumnsTable.append(HT.TR(HT.TD(selectedColumnsList)),
+ HT.TR(HT.TD(clearButton, removeButton, upButton, downButton)))
+# innerColumnsTable2 = HT.TableLite(border=0, Class="collap", cellpadding = 2)
+# innerColumnsTable2.append(HT.TR(HT.TD(selectedColumnsList2)),
+# HT.TR(HT.TD(removeButton2)))
+ columnsTable = HT.TableLite(border=0, cellpadding=2, cellspacing=0)
+ columnsTable.append(
+ HT.TR(HT.TD(HT.Font("&nbsp;")),
+ HT.TD(HT.Strong("Select the QTL interval"))),
+ HT.TR(HT.TD(HT.Font("Chr: ", size=-1)),
+ HT.TD(selectChrBox)),
+ HT.TR(HT.TD(HT.Font("View: ", size=-1)),
+ HT.TD(startBox, HT.Font("Mb to ", size=-1), endBox, HT.Font("Mb", size=-1))),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD(HT.Font("&nbsp;")),
+ HT.TD(HT.Strong("Select two mouse strains for inclusion of nsSNP count"))),
+ HT.TR(HT.TD(HT.Font("Strains: ", size=-1)),
+ HT.TD(selectstr1,selectstr2)),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD(HT.Font("&nbsp;")),
+ HT.TD(HT.Strong("Select 3 datasets for inclusion of expression and cis-activity data"))),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD("&nbsp;"),
+ HT.TD(HT.Font("Dataset 1", size=-1))),
+ HT.TR(HT.TD(HT.Font("Species: ", size=-1)),
+ HT.TD(selectSpeciesBoxA)),
+ HT.TR(HT.TD(HT.Font("Group: ", size=-1)),
+ HT.TD(selectGroupBoxA)),
+ HT.TR(HT.TD(HT.Font("Type: ", size=-1)),
+ HT.TD(selectTypeBoxA)),
+ HT.TR(HT.TD(HT.Font("Database: ", size=-1)),
+ HT.TD(selectDatabaseBoxA)),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD("&nbsp;"),
+ HT.TD(HT.Font("Dataset 2", size=-1))),
+ HT.TR(HT.TD(HT.Font("Species: ", size=-1)),
+ HT.TD(selectSpeciesBoxB)),
+ HT.TR(HT.TD(HT.Font("Group: ", size=-1)),
+ HT.TD(selectGroupBoxB)),
+ HT.TR(HT.TD(HT.Font("Type: ", size=-1)),
+ HT.TD(selectTypeBoxB)),
+ HT.TR(HT.TD(HT.Font("Database: ", size=-1)),
+ HT.TD(selectDatabaseBoxB)),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD("&nbsp;"),
+ HT.TD(HT.Font("Dataset 3", size=-1))),
+ HT.TR(HT.TD(HT.Font("Species: ", size=-1)),
+ HT.TD(selectSpeciesBoxC)),
+ HT.TR(HT.TD(HT.Font("Group: ", size=-1)),
+ HT.TD(selectGroupBoxC)),
+ HT.TR(HT.TD(HT.Font("Type: ", size=-1)),
+ HT.TD(selectTypeBoxC)),
+ HT.TR(HT.TD(HT.Font("Database: ", size=-1)),
+ HT.TD(selectDatabaseBoxC)),
+# HT.TR(HT.TD(""),
+# HT.TD(innerColumnsTable2)),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD(HT.Font("&nbsp;")),
+ HT.TD(HT.Strong("Optionally, choose additional data to display"))),
+ HT.TR(HT.TD(HT.Font("Show: ", size=-1)),
+ HT.TD(allColumnsList, addButton)),
+ HT.TR(HT.TD(HT.Font("Selected:",size=-1)),
+ HT.TD(innerColumnsTable)),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD(HT.Font("Sort by: ", size=-1)),
+ HT.TD(selectsorton)),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD("&nbsp;")),
+ HT.TR(HT.TD(HT.Font("&nbsp;", size=-1)),
+ HT.TD(submitButton)),
+
+ )
+ columnsForm.append(columnsTable)
+ #columnsForm.append(HT.Input(type="hidden", name="sort", value=diffCol),
+ # HT.Input(type="hidden", name="identification", value=identification),
+ # HT.Input(type="hidden", name="traitInfo", value=traitInfo))
+
+ return columnsForm, dispFields, dispFields2
diff --git a/web/webqtl/qtlminer/__init__.py b/web/webqtl/qtlminer/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/qtlminer/__init__.py
diff --git a/web/webqtl/schema/ShowCommentPage.py b/web/webqtl/schema/ShowCommentPage.py
new file mode 100755
index 00000000..449fd56a
--- /dev/null
+++ b/web/webqtl/schema/ShowCommentPage.py
@@ -0,0 +1,123 @@
+# 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
+
+import sys
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+
+
+
+class ShowCommentPage(templatePage):
+ def __init__(self,fd):
+ sys.stderr = sys.stdout
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ #{
+ print 'Content-type: text/html\n'
+ print 'Can not update the comment of %s' %(TableName)
+ return
+ #}
+
+ Cursor_Comment = self.cursor
+ TableName = fd.formdata.getfirst('TableName')
+
+ SqlCmd = 'select Comment from TableComments where TableName=\'%s\'' %(TableName)
+ Cursor_Comment.execute(SqlCmd)
+ Comment = Cursor_Comment.fetchall()
+ if Comment:
+ Comment = Comment[0][0]
+ if str(Comment)=='None':
+ Comment=''
+ else:
+ Comment = ''
+
+ ##########setup HtmlForm Comment##########
+ HtmlInputHidden_TableName = HT.Input(type='hidden', name='TableName', value=TableName)
+ HtmlInputHidden_ActionID = HT.Input(type='hidden', name='ActionID', value='UpdateComment')
+ HtmlTextarea_Comment = HT.Textarea(name='Comment', text=Comment, rows=8, cols=100)
+
+ HtmlForm_Comment = HT.Form(cgi=webqtlConfig.CGIDIR+'main.py?FormID=schemaUpdateComment')
+ HtmlForm_Comment.append('<B>%s</B><BR><BR>' %(TableName)) #show table's name
+ HtmlForm_Comment.append('<B><I>Comment:</I></B><BR>') #show table's comment
+ HtmlForm_Comment.append(HtmlTextarea_Comment)
+ HtmlForm_Comment.append('<BR>')
+ HtmlForm_Comment.append(HtmlInputHidden_TableName)
+ HtmlForm_Comment.append(HtmlInputHidden_ActionID)
+
+ ###########################
+ #update fields' annotation#
+ ###########################
+ HtmlForm_Comment.append('<BR><BR>')
+
+ try:
+ #{
+ HtmlTR_Annotation = []
+ Cursor_Comment.execute('desc %s' %(TableName))
+ TableDesc = Cursor_Comment.fetchall()
+ for i in range(0, len(TableDesc)):
+ #{
+ TableField = TableName+'.'+str(TableDesc[i][0])
+ TableFieldForeignKey = TableField+'ForeignKey'
+ TableFieldAnnotation = TableField+'Annotation'
+ HtmlText_ForeignKey = HT.Input(type='text', name=TableFieldForeignKey, size=20)
+ HtmlText_Annotation = HT.Input(type='text', name=TableFieldAnnotation, size=80)
+
+
+ Cursor_Comment.execute('select Annotation, Foreign_Key from TableFieldAnnotation where TableField=%s', (TableField))
+ Annotation = Cursor_Comment.fetchone()
+ if Annotation:
+ #{
+ if str(Annotation[1]) != 'None':
+ HtmlText_ForeignKey.value=Annotation[1]
+ if str(Annotation[0]) != 'None':
+ HtmlText_Annotation.value=Annotation[0].replace('"', '&quot;')
+ #}
+ HtmlTD_Annotation = []
+ HtmlTD_Annotation.append(TableField)
+ HtmlTD_Annotation.append(HtmlText_ForeignKey)
+ HtmlTD_Annotation.append(HtmlText_Annotation)
+
+ HtmlTR_Annotation.append(HtmlTD_Annotation)
+ #}
+
+ HtmlTable_Annotation= HT.Table(border=0, width='0%', heading=['Field', 'Foreign_Key', 'Annotation'], body = HtmlTR_Annotation)
+ HtmlForm_Comment.append(HtmlTable_Annotation)
+ #}
+ except:
+ pass
+
+ HtmlForm_Comment.submit.value='submit'
+ HtmlForm_Comment.reset = HT.Input(type='reset', name='reset', value='reset')
+ ##########end of HtmlForm##########
+
+ self.dict['body'] = HtmlForm_Comment
+
+
diff --git a/web/webqtl/schema/ShowSchemaPage.py b/web/webqtl/schema/ShowSchemaPage.py
new file mode 100755
index 00000000..e9ced5a1
--- /dev/null
+++ b/web/webqtl/schema/ShowSchemaPage.py
@@ -0,0 +1,194 @@
+# 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
+
+import sys
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+
+
+###################################################
+#Description: show the schema of webqtl's database#
+#Author: Hongqiang Li #
+#Version: 1.0 #
+###################################################
+
+class ShowSchemaPage(templatePage):
+ def __init__(self,fd):
+ cookies = fd.cookies
+ sys.stderr = sys.stdout
+ templatePage.__init__(self, fd)
+ body = HT.SimpleDocument()
+
+ ###############################################################################
+ #get user's privilege from cookie, if the user doesn't have enough privilege, #
+ #he won't see the update comment icon #
+ ###############################################################################
+ ShowUpdateIcon = False
+
+ if not self.openMysql():
+ return
+
+ Cursor_WebQtl = Cursor_Comment = self.cursor
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+ ShowUpdateIcon = True
+
+ ##################
+ #show description#
+ ##################
+ body.append('<BR>')
+ body.append('<H1>')
+ body.append('Description of Schema')
+ if ShowUpdateIcon:
+ #{
+ # Modified by Hongqiang Li
+ # Image_Update = HT.Image('http://web2qtl.utmem.edu/images/modify.gif')
+ Image_Update = HT.Image('/images/modify.gif')
+ #
+ Href_Update = HT.Href(webqtlConfig.CGIDIR+'main.py?FormID=schemaShowComment&TableName=Description_of_Schema', Image_Update)
+ body.append(Href_Update)
+ #}
+ body.append('</H1>')
+
+ Cursor_WebQtl.execute('select Comment from TableComments where TableName=\'Description_of_Schema\'')
+ Comment = Cursor_WebQtl.fetchone();
+ if Comment:
+ if str(Comment[0])!='None':
+ body.append(Comment[0])
+
+ body.append('<HR WIDTH=100%>')
+ body.append('<H2>Tables</H2>')
+
+ ##################
+ #show table names#
+ ##################
+ Cursor_WebQtl.execute('show tables')
+ Tables=Cursor_WebQtl.fetchall()
+ BlockedTables = ['User', 'TableComments', 'TableFieldAnnotation', 'ProbeSetXRef_TEMP', 'DBList', 'DBType', 'HumanGene', 'LCorr', 'Temp', 'TempData']
+ for i in range(0, len(Tables)):
+ #{
+ TableName = Tables[i][0]
+ if TableName in BlockedTables: #skip the table who is blocked
+ continue
+
+ HrefTable_Schema = HT.Href(webqtlConfig.CGIDIR+'main.py?FormID=schemaShowPage#'+TableName, TableName)
+ body.append(str(HrefTable_Schema)+'<BR>')
+ #}
+ body.append('<hr width=100%>')
+
+ for i in range(0, len(Tables)):
+ #{
+ TableName = Tables[i][0]
+ if TableName in BlockedTables: #skip the table who is blocked
+ continue
+
+ #####################
+ #get table's comment#
+ #####################
+ SqlCmd = 'select Comment from TableComments where TableName=\'%s\'' %(TableName)
+ Cursor_WebQtl.execute(SqlCmd)
+ Comment = Cursor_WebQtl.fetchall()
+
+ ####################################
+ #get the content of a table's schma#
+ ####################################
+ Cursor_WebQtl.execute('desc %s' %(TableName))
+ TableDesc = Cursor_WebQtl.fetchall();
+
+ HtmlTR_Schema = []
+ for row in range(0, len(TableDesc)):
+ #{
+ HtmlTD_Schema = []
+ for col in range(0, len(TableDesc[row])):
+ if str(TableDesc[row][col])=='None' or str(TableDesc[row][col])=='': #just means I don't want show 'None' *_^
+ HtmlTD_Schema.append('&nbsp;')
+ else:
+ HtmlTD_Schema.append(TableDesc[row][col])
+
+ ##############################
+ #get table fileds' annotation#
+ ##############################
+ TableField = TableName+'.'+TableDesc[row][0]
+ Cursor_WebQtl.execute('select Annotation, Foreign_Key from TableFieldAnnotation where TableField=%s', (TableField))
+ Annotation = Cursor_WebQtl.fetchone();
+ if Annotation:
+ #{
+ if str(Annotation[1])=='None' or str(Annotation[1])=='':
+ HtmlTD_Schema.append('&nbsp;')
+ else:
+ HtmlTD_Schema.append(Annotation[1])
+ if str(Annotation[0])=='None' or str(Annotation[0])=='':
+ HtmlTD_Schema.append('&nbsp;')
+ else:
+ HtmlTD_Schema.append(Annotation[0])
+ #}
+ else:
+ #{
+ HtmlTD_Schema.append('&nbsp;')
+ HtmlTD_Schema.append('&nbsp;')
+ #}
+
+ HtmlTR_Schema.append(HtmlTD_Schema)
+ #}
+
+ ###############################
+ #Html code of a table's schema#
+ ###############################
+ body.append(HT.NAME(TableName, TableName))
+ if ShowUpdateIcon:
+ #{
+ # Modified by Hongqiang Li
+ #Image_Update = HT.Image('http://web2qtl.utmem.edu/images/modify.gif')
+ Image_Update = HT.Image('/images/modify.gif')
+ #
+ Href_Update = HT.Href(webqtlConfig.CGIDIR+'main.py?FormID=schemaShowComment&TableName=%s' %(TableName), Image_Update)
+ body.append(Href_Update)
+ #}
+ body.append('<BR><BR>')
+
+ body.append('<B>Comment:</B><BR>')
+ #body.append("<I>")
+ if Comment:
+ if str(Comment[0][0])!='None':
+ for content in Comment[0][0].split('\n'):
+ body.append(content)
+ body.append('<BR>')
+ #body.append("</I>")
+
+ HtmlTable_Schema = HT.Table(width='0%', heading=['Field', 'Type', 'Null', 'Key', 'Default', 'Extra', 'Foreign_Key', 'Annotation'], body = HtmlTR_Schema)
+ body.append(HtmlTable_Schema)
+ body.append('<hr width=100%>')
+ #}
+
+ self.dict['body'] = body
+
+
+
diff --git a/web/webqtl/schema/UpdateCommentPage.py b/web/webqtl/schema/UpdateCommentPage.py
new file mode 100755
index 00000000..eb1dbb67
--- /dev/null
+++ b/web/webqtl/schema/UpdateCommentPage.py
@@ -0,0 +1,101 @@
+# 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
+
+import sys
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+
+
+class UpdateCommentPage(templatePage):
+ def __init__(self,fd):
+ sys.stderr = sys.stdout
+ templatePage.__init__(self, fd)
+ body = HT.SimpleDocument()
+
+ if not self.updMysql():
+ #{
+ print 'Content-type: text/html\n'
+ print 'Can not update the comment of %s' %(TableName)
+ return
+ #}
+
+
+ Cursor_Comment=self.cursor
+ TableName = fd.formdata.getfirst('TableName')
+ Comment = fd.formdata.getfirst('Comment')
+
+ ########################
+ #update table's comment#
+ ########################
+ Cursor_Comment.execute('select * from TableComments where TableName=%s', (TableName))
+ if Cursor_Comment.fetchall():
+ Cursor_Comment.execute('update TableComments set Comment=%s where TableName=%s', (Comment, TableName))
+ else:
+ Cursor_Comment.execute('insert into TableComments values(%s,%s)', (TableName, Comment))
+
+
+ #################################
+ #update table fields' annotation#
+ #################################
+ try:
+ #{
+ Cursor_Comment.execute('desc %s' %(TableName))
+ TableDesc = Cursor_Comment.fetchall()
+ for i in range(0, len(TableDesc)):
+ #{
+ TableField = TableName+'.'+str(TableDesc[i][0])
+ TableFieldForeignKey = TableField+'ForeignKey'
+ TableFieldAnnotation = TableField+'Annotation'
+
+ ForeignKey = fd.formdata.getfirst(TableFieldForeignKey)
+ if ForeignKey == 'None':
+ ForeignKey=''
+ Annotation = fd.formdata.getfirst(TableFieldAnnotation)
+ if Annotation == 'None':
+ Annotation='&nbsp;'
+
+ Cursor_Comment.execute('select * from TableFieldAnnotation where TableField=%s', (TableField))
+ if Cursor_Comment.fetchall():
+ Cursor_Comment.execute('update TableFieldAnnotation set Foreign_Key=%s, Annotation=%s where TableField=%s', (ForeignKey, Annotation, TableField))
+ else:
+ Cursor_Comment.execute('insert into TableFieldAnnotation values(%s,%s,%s)', (TableField, ForeignKey, Annotation))
+ #}
+ #}
+ except:
+ pass
+
+ HtmlHref = HT.Href(webqtlConfig.CGIDIR+'main.py?FormID=schemaShowPage#%s' %(TableName), 'table')
+ HtmlBlock = HT.Blockquote();
+ HtmlBlock.append('This ')
+ HtmlBlock.append(HtmlHref)
+ HtmlBlock.append('\'s comment has been succesfully updated')
+
+ body.append(HtmlBlock)
+ self.dict['body'] = body
+
diff --git a/web/webqtl/schema/__init__.py b/web/webqtl/schema/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/schema/__init__.py
diff --git a/web/webqtl/search/IndexPage.py b/web/webqtl/search/IndexPage.py
new file mode 100755
index 00000000..ddea19f4
--- /dev/null
+++ b/web/webqtl/search/IndexPage.py
@@ -0,0 +1,41 @@
+# 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
+from base import indexBody
+
+#########################################
+# IndexPage
+#########################################
+
+class IndexPage(templatePage):
+
+ def __init__(self, fd):
+ templatePage.__init__(self, fd)
+ self.dict['title'] = 'GeneNetwork'
+ self.dict['body'] = indexBody.index_body_string
+ self.dict['js1'] = '<SCRIPT SRC="/javascript/searchtip.js"></SCRIPT>'
+ self.dict['js2'] = 'onload="javascript:initialDatasetSelection();"'
diff --git a/web/webqtl/search/SearchResultPage.py b/web/webqtl/search/SearchResultPage.py
new file mode 100644
index 00000000..14d10731
--- /dev/null
+++ b/web/webqtl/search/SearchResultPage.py
@@ -0,0 +1,1237 @@
+import string
+import os
+import cPickle
+import re
+from math import *
+import time
+import pyXLWriter as xl
+import pp
+import math
+import datetime
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+from base.webqtlDataset import webqtlDataset
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from dbFunction import webqtlDatabaseFunction
+
+import logging
+logging.basicConfig(filename="/tmp/gn_log", level=logging.INFO)
+_log = logging.getLogger("search")
+
+class SearchResultPage(templatePage):
+
+ maxReturn = 3000
+# NPerPage = 100
+ nkeywords = 0
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ self.dict['title'] = 'Search Results'
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
+ self.database = fd.formdata.getfirst('database', '')
+ if not self.database or self.database == 'spacer':
+ #Error, No database selected
+ heading = "Search Result"
+ detail = ['''No database was selected for this search, please
+ go back and SELECT at least one database.''']
+ self.error(heading=heading,detail=detail,error="No Database Selected")
+ return
+ elif type(self.database) == type(""):
+ #convert database into a database list
+ #was used for multiple databases search, this
+ #feature has been abandoned,
+ self.database = string.split(self.database,',')
+ else:
+ pass
+
+ ###########################################
+ # Names and IDs of RISet / F2 set
+ ###########################################
+ if self.database == ['_allPublish']:
+ self.cursor.execute("""select PublishFreeze.Name, InbredSet.Name, InbredSet.Id from PublishFreeze,
+ InbredSet where PublishFreeze.Name not like 'BXD300%' and InbredSet.Id =
+ PublishFreeze.InbredSetId""")
+ results = self.cursor.fetchall()
+ self.database = map(lambda x: webqtlDataset(x[0], self.cursor), results)
+ self.databaseCrosses = map(lambda x: x[1], results)
+ self.databaseCrossIds = map(lambda x: x[2], results)
+ self.singleCross = False
+ else:
+ self.database = map(lambda x: webqtlDataset(x, self.cursor), self.database)
+ #currently, webqtl wouldn't allow multiple crosses
+ #for other than multiple publish db search
+ #so we can use the first database as example
+ if self.database[0].type=="Publish":
+ pass
+ elif self.database[0].type in ("Geno", "ProbeSet"):
+
+ #userExist = None
+
+ for individualDB in self.database:
+ self.cursor.execute('SELECT Id, Name, FullName, confidentiality, AuthorisedUsers FROM %sFreeze WHERE Name = "%s"' % (self.database[0].type, individualDB))
+ indId, indName, indFullName, confidential, AuthorisedUsers = self.cursor.fetchall()[0]
+
+ if confidential == 1:
+ access_to_confidential_dataset = 0
+
+ #for the dataset that confidentiality is 1
+ #1. 'admin' and 'root' can see all of the dataset
+ #2. 'user' can see the dataset that AuthorisedUsers contains his id(stored in the Id field of User table)
+ if webqtlConfig.USERDICT[self.privilege] > webqtlConfig.USERDICT['user']:
+ access_to_confidential_dataset = 1
+ else:
+ AuthorisedUsersList=AuthorisedUsers.split(',')
+ if AuthorisedUsersList.__contains__(self.userName):
+ access_to_confidential_dataset = 1
+
+ if not access_to_confidential_dataset:
+ #Error, No database selected
+ heading = "Search Result"
+ detail = ["The %s database you selected is not open to the public at this time, please go back and SELECT other database." % indFullName]
+ self.error(heading=heading,detail=detail,error="Confidential Database")
+ return
+ else:
+ heading = "Search Result"
+ detail = ['''The database has not been established yet, please
+ go back and SELECT at least one database.''']
+ self.error(heading=heading,detail=detail,error="No Database Selected")
+ return
+
+ self.database[0].getRISet()
+ self.databaseCrosses = [self.database[0].riset]
+ self.databaseCrossIds = [self.database[0].risetid]
+ self.singleCross = True
+ #XZ, August 24,2010: Since self.singleCross = True, it's safe to assign one species Id.
+ self.speciesId = webqtlDatabaseFunction.retrieveSpeciesId(self.cursor, self.database[0].riset)
+
+ ###########################################
+ # make sure search from same type of databases
+ ###########################################
+ dbTypes = map(lambda X: X.type, self.database)
+ self.dbType = dbTypes[0]
+ for item in dbTypes:
+ if item != self.dbType:
+ heading = "Search Result"
+ detail = ["Search can only be performed among the same type of databases"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ if self.dbType == "Publish":
+ self.searchField = ['Phenotype.Post_publication_description', 'Phenotype.Pre_publication_description', 'Phenotype.Pre_publication_abbreviation', 'Phenotype.Post_publication_abbreviation', 'Phenotype.Lab_code', 'Publication.PubMed_ID', 'Publication.Abstract', 'Publication.Title', 'Publication.Authors', 'PublishXRef.Id']
+
+ elif self.dbType == "ProbeSet":
+ self.searchField = ['Name','Description','Probe_Target_Description','Symbol','Alias','GenbankId', 'UniGeneId','RefSeq_TranscriptId']
+ elif self.dbType == "Geno":
+ self.searchField = ['Name','Chr']
+
+ ###########################################
+ # Search Options
+ ###########################################
+ self.matchwhole = fd.formdata.getfirst('matchwhole')
+ #split result into pages
+ self.pageNumber = fd.formdata.getfirst('pageno', '0')
+ try:
+ self.pageNumber = int(self.pageNumber)
+ except:
+ self.pageNumber = 0
+
+
+ ###########################################
+ # Generate Mysql Query
+ ###########################################
+ geneIdListQuery = fd.formdata.getfirst('geneId', '')
+ if geneIdListQuery:
+ geneIdListQuery = string.replace(geneIdListQuery, ",", " ")
+ geneIdListQuery = " geneId=%s" % string.join(string.split(geneIdListQuery), "-")
+
+ self.ANDkeyword = fd.formdata.getfirst('ANDkeyword', "")
+ self.ORkeyword = fd.formdata.getfirst('ORkeyword', "")
+
+ self.ORkeyword += geneIdListQuery
+
+ self.ANDkeyword = self.ANDkeyword.replace("\\", "").strip()
+ self.ORkeyword = self.ORkeyword.replace("\\", "").strip()
+ #user defined sort option
+ self.orderByUserInput = fd.formdata.getfirst('orderByUserInput', "").strip()
+ #default sort option if user have not defined
+ self.orderByDefalut = ""
+
+ #XZ, Dec/16/2010: I add examples to help understand this block of code. See details in function pattersearch.
+
+ #XZ: self._1mPattern examples: WIKI=xxx, RIF=xxx, GO:0045202
+ self._1mPattern = re.compile('\s*(\S+)\s*[:=]\s*([a-zA-Z-\+\d\.]+)\s*')
+
+ #XZ: self._2mPattern examples: Mean=(15.0 16.0), Range=(10 100), LRS=(Low_LRS_limit, High_LRS_limit), pvalue=(Low_limit, High_limit), Range=(10 100)
+ self._2mPattern = re.compile('\s*(\S+)\s*[=in]{1,2}\s*\(\s*([-\d\.]+)[, \t]+([-\d\.]+)[, \t]*([-\d\.]*)\s*\)')
+
+ #XZ: self._3mPattern examples: Position=(Chr1 98 104), Pos=(Chr1 98 104), Mb=(Chr1 98 104), CisLRS=(Low_LRS_limit, High_LRS_limit, Mb_buffer), TransLRS=(Low_LRS_limit, High_LRS_limit, Mb_buffer)
+ self._3mPattern = re.compile('\s*(\S+)\s*[=in]{1,2}\s*\(\s*[Cc][Hh][Rr]([^, \t]+)[, \t]+([-\d\.]+)[, \t]+([-\d\.]+)\s*\)')
+
+ #XZ: self._5mPattern examples: LRS=(Low_LRS_limit, High_LRS_limit, ChrNN, Mb_Low_Limit, Mb_High_Limit)
+ self._5mPattern = re.compile('\s*(\S+)\s*[=in]{1,2}\s*\(\s*([-\d\.]+)[, \t]+([-\d\.]+)[, \t]+[Cc][Hh][Rr]([^, \t]+)[, \t]+([-\d\.]+)[, \t]+([-\d\.]+)\s*\)')
+
+ #Error, No keyword input
+ if not (self.ORkeyword or self.ANDkeyword):
+ heading = "Search Result"
+ detail = ["Please make sure to enter either your search terms (genes, traits, markers), or advanced search commands."]
+ self.error(heading=heading,detail=detail,error="No search terms were entered")
+ return
+
+ #query clauses
+ self.ANDQuery = []
+ self.ORQuery = []
+ #descriptions, one for OR search, one for AND search
+ self.ANDDescriptionText = []
+ self.ORDescriptionText = []
+
+ if not self.normalSearch():
+ return
+ if not self.patternSearch():
+ return
+ if not self.assembleQuery():
+ return
+ self.nresults = self.executeQuery()
+
+ if len(self.database) > 1:
+ dbUrl = "Multiple phenotype databases"
+ dbUrlLink = " were"
+ else:
+ dbUrl = self.database[0].genHTML()
+ dbUrlLink = " was"
+
+ SearchText = HT.Blockquote('GeneNetwork searched the ', dbUrl, ' for all records ')
+ if self.ORkeyword2:
+ NNN = len(self.ORkeyword2)
+ if NNN > 1:
+ SearchText.append(' that match the terms ')
+ else:
+ SearchText.append(' that match the term ')
+ for j, term in enumerate(self.ORkeyword2):
+ SearchText.append(HT.U(term))
+ if NNN > 1 and j < NNN-2:
+ SearchText.append(", ")
+ elif j == NNN-2:
+ SearchText.append(", or ")
+ else:
+ pass
+ if self.ORDescriptionText:
+ if self.ORkeyword2:
+ SearchText.append("; ")
+ else:
+ SearchText.append(" ")
+ for j, item in enumerate(self.ORDescriptionText):
+ SearchText.append(item)
+ if j < len(self.ORDescriptionText) -1:
+ SearchText.append(";")
+
+ if (self.ORkeyword2 or self.ORDescriptionText) and (self.ANDkeyword2 or self.ANDDescriptionText):
+ SearchText.append("; ")
+ if self.ANDkeyword2:
+ if (self.ORkeyword2 or self.ORDescriptionText):
+ SearchText.append(' records')
+ NNN = len(self.ANDkeyword2)
+ if NNN > 1:
+ SearchText.append(' that match the terms ')
+ else:
+ SearchText.append(' that match the term ')
+ for j, term in enumerate(self.ANDkeyword2):
+ SearchText.append(HT.U(term))
+ if NNN > 1 and j < NNN-2:
+ SearchText.append(", ")
+ elif j == NNN-2:
+ SearchText.append(", and ")
+ else:
+ pass
+ if self.ANDDescriptionText:
+ if self.ANDkeyword2:
+ SearchText.append(" and ")
+ else:
+ SearchText.append(" ")
+ for j, item in enumerate(self.ANDDescriptionText):
+ SearchText.append(item)
+ if j < len(self.ANDDescriptionText) -1:
+ SearchText.append(" and ")
+
+ SearchText.append(". ")
+ if self.nresults == 0:
+ heading = "Search Result"
+ detail = ["Sorry, GeneNetwork did not find any records matching your request. Please check the syntax or try the ANY rather than the ALL field."]
+ self.error(heading=heading,intro = SearchText.contents,detail=detail,error="Not Found")
+ return
+ elif self.nresults == 1:
+ SearchText.append(HT.P(), 'GeneNetwork found one record that matches your request. To study this record, click on its text below. To add this record to your Selection window, use the checkbox and then click the ', HT.Strong('Add to Collection'),' button. ')
+ elif self.nresults >= 1 and self.nresults <= self.maxReturn:
+ SearchText.append(HT.P(), 'GeneNetwork found a total of ', HT.Span(self.nresults, Class='fwb cr'), ' records. To study any one of these records, click on its ID below. To add one or more records to your Selection window, use the checkbox and then click the ' , HT.Strong('Add to Collection'),' button. ')
+ else:
+ SearchText.append(' A total of ',HT.Span(self.nresults, Class='fwb cr'), ' records were found.')
+ heading = "Search Result"
+ # Modified by Hongqiang Li
+ # detail = ["The terms you entered match %d records. Please modify your search to generate %d or fewer matches, or review " % (self.nresults, self.maxReturn), HT.Href(text='Search Help', target='_blank', url='http://web2qtl.utmem.edu/searchHelp.html', Class='fs14'), " to learn more about syntax and the use of wildcard characters."]
+ detail = ["The terms you entered match %d records. Please modify your search to generate %d or fewer matches, or review " % (self.nresults, self.maxReturn), HT.Href(text='Search Help', target='_blank', url='%s/searchHelp.html' % webqtlConfig.PORTADDR, Class='fs14'), " to learn more about syntax and the use of wildcard characters."]
+ #
+ self.error(heading=heading,intro = SearchText.contents,detail=detail,error="Over %d" % self.maxReturn)
+ return
+
+
+ TD_LR.append(HT.Paragraph('Search Results', Class="title"), SearchText)
+ self.genSearchResultTable(TD_LR)
+ self.dict['body'] = str(TD_LR)
+ self.dict['js1'] = ''
+ self.dict['js2'] = 'onLoad="pageOffset()"'
+ self.dict['layer'] = self.generateWarningLayer()
+
+ def genSearchResultTable(self, TD_LR):
+
+ pageTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="100%",border=0)
+
+ lastone = False
+ for i, item in enumerate(self.results):
+ if not item:
+ continue
+ lastone = False
+
+ traitList = []
+ for k, item2 in enumerate(item):
+ j, ProbeSetID = item2[:2]
+ thisTrait = webqtlTrait(db=self.database[j], name=ProbeSetID, cursor=self.cursor)
+ traitList.append(thisTrait)
+
+ ##############
+ # Excel file #
+ ##############
+ filename= webqtlUtil.genRandStr("Search_")
+ xlsUrl = HT.Input(type='button', value = 'Download Table', onClick= "location.href='/tmp/%s.xls'" % filename, Class='button')
+ # Create a new Excel workbook
+ workbook = xl.Writer('%s.xls' % (webqtlConfig.TMPDIR+filename))
+ headingStyle = workbook.add_format(align = 'center', bold = 1, border = 1, size=13, fg_color = 0x1E, color="white")
+
+ #XZ, 3/18/2010: pay attention to the line number of header in this file. As of today, there are 7 lines.
+ worksheet = self.createExcelFileWithTitleAndFooter(workbook=workbook, db=thisTrait.db, returnNumber=len(traitList))
+ newrow = 7
+
+ tbl = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+ #seq = self.pageNumber*self.NPerPage+1 //Edited out because we show all results in one page now - Zach 2/22/11
+ seq = 1
+ RISet = self.databaseCrosses[i]
+ thisFormName = 'showDatabase'+RISet
+ selectall = HT.Href(url="#", onClick="checkAll(document.getElementsByName('%s')[0]);" % thisFormName)
+ selectall_img = HT.Image("/images/select_all2_final.jpg", name="selectall", alt="Select All", title="Select All", style="border:none;")
+ selectall.append(selectall_img)
+ reset = HT.Href(url="#", onClick="checkNone(document.getElementsByName('%s')[0]);" % thisFormName)
+ reset_img = HT.Image("/images/select_none2_final.jpg", alt="Select None", title="Select None", style="border:none;")
+ reset.append(reset_img)
+ selectinvert = HT.Href(url="#", onClick="checkInvert(document.getElementsByName('%s')[0]);" % thisFormName)
+ selectinvert_img = HT.Image("/images/invert_selection2_final.jpg", name="selectinvert", alt="Invert Selection", title="Invert Selection", style="border:none;")
+ selectinvert.append(selectinvert_img)
+ addselect = HT.Href(url="#")
+ addselect_img = HT.Image("/images/add_collection1_final.jpg", name="addselect", alt="Add To Collection", title="Add To Collection", style="border:none;")
+ addselect.append(addselect_img)
+
+ optionsTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="20%",border=0)
+ optionsRow = HT.TR(HT.TD(selectall, width="25%"), HT.TD(reset, width="25%"), HT.TD(selectinvert, width="25%"), HT.TD(addselect, width="25%"))
+ labelsRow = HT.TR(HT.TD("&nbsp;"*2,"Select", width="25%"), HT.TD("&nbsp;","Deselect", width="255"), HT.TD("&nbsp;"*3,"Invert", width="25%"), HT.TD("&nbsp;"*4,"Add", width="25%"))
+ optionsTable.append(optionsRow, labelsRow)
+
+ pageTable.append(HT.TR(HT.TD(optionsTable)), HT.TR(HT.TD(xlsUrl, height=40)))
+
+ tblobj = {}
+ mainfmName = thisFormName
+ species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=RISet)
+
+ if thisTrait.db.type=="Geno":
+ tblobj['header'] = self.getTableHeaderForGeno(worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+
+ newrow += 1
+
+ sortby = self.getSortByValue(datasetType="Geno")
+
+ tblobj['body'] = self.getTableBodyForGeno(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow)
+
+ workbook.close()
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ div = HT.Div(webqtlUtil.genTableObj(tblobj, filename, sortby), Id="sortable")
+
+ pageTable.append(HT.TR(HT.TD(div)))
+
+ elif thisTrait.db.type=="Publish":
+ tblobj['header'] = self.getTableHeaderForPublish(worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+
+ newrow += 1
+
+ sortby = self.getSortByValue(datasetType="Publish")
+
+ tblobj['body'] = self.getTableBodyForPublish(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, species=species)
+
+ workbook.close()
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ div = HT.Div(webqtlUtil.genTableObj(tblobj, filename, sortby), Id="sortable")
+
+ pageTable.append(HT.TR(HT.TD(div)))
+
+ elif thisTrait.db.type=="ProbeSet":
+ tblobj['header'] = self.getTableHeaderForProbeSet(worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
+
+ newrow += 1
+
+ sortby = self.getSortByValue(datasetType="ProbeSet")
+
+ tblobj['body'] = self.getTableBodyForProbeSet(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, species=species)
+
+ workbook.close()
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ div = HT.Div(webqtlUtil.genTableObj(tblobj, filename, sortby), Id="sortable")
+
+ pageTable.append(HT.TR(HT.TD(div)))
+
+
+ traitForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name=thisFormName, submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':'_','CellID':'_','RISet':RISet}
+ hddn['incparentsf1']='ON'
+ for key in hddn.keys():
+ traitForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ traitForm.append(HT.P(),pageTable)
+
+ TD_LR.append(traitForm)
+ if len(self.results) > 1 and i < len(self.results) - 1:
+ lastone = True
+ if lastone:
+ TD_LR.contents.pop()
+
+ def executeQuery(self):
+
+ ##construct sorting
+ if self.dbType == "Publish":
+ sortQuery = " order by Publication_PubMed_ID desc, Phenotype_Name, thistable"
+ elif self.dbType == "Geno":
+ if not self.orderByUserInput:
+ if self.orderByDefalut:
+ self.orderByUserInput = self.orderByDefalut
+ else:
+ self.orderByUserInput = "POSITION"
+ if self.orderByUserInput.upper() in ["POS", "POSITION", "MB"]:
+ self.orderByUserInput = "POSITION"
+ else:
+ pass
+ self.orderByUserInput = self.orderByUserInput.upper()
+ self.orderByUserInputOrig = self.orderByUserInput[:]
+ if self.orderByUserInput == "NAME":
+ sortQuery = " order by Geno_Name, Geno_chr_num, Geno_Mb"
+ elif self.orderByUserInput == "SOURCE":
+ sortQuery = " order by Geno_Source2, Geno_chr_num, Geno_Mb"
+ else:
+ sortQuery = " order by Geno_chr_num, Geno_Mb"
+ #ProbeSet
+ else:
+ if not self.orderByUserInput:
+ if self.orderByDefalut:
+ self.orderByUserInput = self.orderByDefalut
+ else:
+ self.orderByUserInput = "POSITION"
+
+ self.orderByUserInput = self.orderByUserInput.upper()
+ self.orderByUserInputOrig = self.orderByUserInput[:]
+ #XZ: 8/18/2009: "POSITION-"
+ if self.orderByUserInput[-1] == '-':
+ self.orderByUserInput = self.orderByUserInput[:-1]
+ sortDesc = 'desc'
+ else:
+ sortDesc = ''
+
+ if self.orderByUserInput in ["MEAN", "LRS", "PVALUE"]:
+ #sortQuery = " order by T%s %s, TNAME, thistable desc" % (self.orderByUserInput, sortDesc)
+ sortQuery = " order by T%s desc, TNAME, thistable desc" % self.orderByUserInput
+ elif self.orderByUserInput in ["POS", "POSITION", "MB"]:
+ sortQuery = " order by TCHR_NUM %s, TMB %s, TNAME, thistable desc" % (sortDesc, sortDesc)
+ elif self.orderByUserInput == 'SYMBOL':
+ sortQuery = " order by TSYMBOL, thistable desc"
+ else:
+ sortQuery = " order by TNAME_NUM, thistable desc"
+
+ if self.singleCross:
+ if len(self.query) > 1:
+ searchQuery = map(lambda X:'(%s)' % X, self.query)
+ searchQuery = string.join(searchQuery, ' UNION ALL ')
+ else:
+ searchQuery = self.query[0]
+ searchQuery += sortQuery
+ #searchCountQuery retrieve all the results
+ searchCountQuery = [searchQuery]
+ #searchQuery = searchQuery + " limit %d,%d" % (self.pageNumber*self.NPerPage, self.NPerPage) // We removed the page limit - Zach 2/22/11
+ searchQuery = [searchQuery]
+ else:
+ searchCountQuery = searchQuery = map(lambda X: X+sortQuery, self.query)
+
+ allResults = []
+ self.results = []
+ for item in searchCountQuery:
+ start_time = datetime.datetime.now()
+ _log.info("Executing query: %s"%(item))
+ self.cursor.execute(item)
+ allResults.append(self.cursor.fetchall())
+ end_time = datetime.datetime.now()
+ _log.info("Total time: %s"%(end_time-start_time))
+
+ _log.info("Done executing queries")
+
+
+ #searchCountQuery retrieve all the results, for counting use only
+ if searchCountQuery != searchQuery:
+ for item in searchQuery:
+ self.cursor.execute(item)
+ self.results.append(self.cursor.fetchall())
+ else:
+ self.results = allResults
+
+ nresults = reduce(lambda Y,X:len(X)+Y, allResults, 0)
+ return nresults
+
+
+
+ def assembleQuery(self):
+ self.query = []
+ if self.ANDQuery or self.ORQuery:
+ clause = self.ORQuery[:]
+
+ for j, database in enumerate(self.database):
+ if self.ANDQuery:
+ clause.append(" (%s) " % string.join(self.ANDQuery, " AND "))
+
+ newclause = []
+
+ for item in clause:
+ ##need to retrieve additional field which won't be used
+ ##in the future, for sorting purpose only
+ if self.dbType == "Publish":
+ if item.find("Geno.name") < 0:
+ incGenoTbl = ""
+ else:
+ incGenoTbl = " Geno, "
+ newclause.append("SELECT %d, PublishXRef.Id, PublishFreeze.createtime as thistable, Publication.PubMed_ID as Publication_PubMed_ID, Phenotype.Post_publication_description as Phenotype_Name FROM %s PublishFreeze, Publication, PublishXRef, Phenotype WHERE PublishXRef.InbredSetId = %d and %s and PublishXRef.PhenotypeId = Phenotype.Id and PublishXRef.PublicationId = Publication.Id and PublishFreeze.Id = %d" % (j, incGenoTbl, self.databaseCrossIds[j], item, database.id))
+ elif self.dbType == "ProbeSet":
+ if item.find("GOgene") < 0:
+ incGoTbl = ""
+ else:
+ incGoTbl = " ,db_GeneOntology.term as GOterm, db_GeneOntology.association as GOassociation, db_GeneOntology.gene_product as GOgene_product "
+ if item.find("Geno.name") < 0:
+ incGenoTbl = ""
+ else:
+ incGenoTbl = " Geno, "
+ if item.find("GeneRIF_BASIC.") < 0:
+ incGeneRIFTbl = ""
+ else:
+ incGeneRIFTbl = " GeneRIF_BASIC, "
+ if item.find("GeneRIF.") < 0:
+ incGeneRIFTbl += ""
+ else:
+ incGeneRIFTbl += " GeneRIF, "
+ newclause.append("""SELECT distinct %d, ProbeSet.Name as TNAME, 0 as thistable,
+ ProbeSetXRef.Mean as TMEAN, ProbeSetXRef.LRS as TLRS, ProbeSetXRef.PVALUE as TPVALUE,
+ ProbeSet.Chr_num as TCHR_NUM, ProbeSet.Mb as TMB, ProbeSet.Symbol as TSYMBOL,
+ ProbeSet.name_num as TNAME_NUM FROM %s%s ProbeSetXRef, ProbeSet %s
+ WHERE %s and ProbeSet.Id = ProbeSetXRef.ProbeSetId and ProbeSetXRef.ProbeSetFreezeId = %d
+ """ % (j, incGeneRIFTbl, incGenoTbl, incGoTbl, item, database.id))
+ elif self.dbType == "Geno":
+ newclause.append("SELECT %d, Geno.Name, GenoFreeze.createtime as thistable, Geno.Name as Geno_Name, Geno.Source2 as Geno_Source2, Geno.chr_num as Geno_chr_num, Geno.Mb as Geno_Mb FROM GenoXRef, GenoFreeze, Geno WHERE %s and Geno.Id = GenoXRef.GenoId and GenoXRef.GenoFreezeId = GenoFreeze.Id and GenoFreeze.Id = %d"% (j, item, database.id))
+ else:
+ pass
+
+ searchQuery = map(lambda X:'(%s)' % X, newclause)
+ searchQuery = string.join(searchQuery, ' UNION ')
+ self.query.append(searchQuery)
+ return 1
+ else:
+ heading = "Search Result"
+ detail = ["No keyword was entered for this search, please go back and enter your keyword."]
+ self.error(heading=heading,detail=detail,error="No Keyword")
+ return 0
+
+
+
+ def normalSearch(self):
+ self.ANDkeyword2 = re.sub(self._1mPattern, '', self.ANDkeyword)
+ self.ANDkeyword2 = re.sub(self._2mPattern, '', self.ANDkeyword2)
+ self.ANDkeyword2 = re.sub(self._3mPattern, '', self.ANDkeyword2)
+ self.ANDkeyword2 = re.sub(self._5mPattern, '', self.ANDkeyword2)
+ ##remove remain parethesis, could be input with syntax error
+ self.ANDkeyword2 = re.sub(re.compile('\s*\([\s\S]*\)'), '', self.ANDkeyword2)
+ self.ANDkeyword2 = self.encregexp(self.ANDkeyword2)
+
+ self.ORkeyword2 = re.sub(self._1mPattern, '', self.ORkeyword)
+ self.ORkeyword2 = re.sub(self._2mPattern, '', self.ORkeyword2)
+ self.ORkeyword2 = re.sub(self._3mPattern, '', self.ORkeyword2)
+ self.ORkeyword2 = re.sub(self._5mPattern, '', self.ORkeyword2)
+ ##remove remain parethesis, could be input with syntax error
+ self.ORkeyword2 = re.sub(re.compile('\s*\([\s\S]*\)'), '', self.ORkeyword2)
+ self.ORkeyword2 = self.encregexp(self.ORkeyword2)
+
+ if self.ORkeyword2 or self.ANDkeyword2:
+ ANDFulltext = []
+ ORFulltext = []
+ for k, item in enumerate(self.ORkeyword2 + self.ANDkeyword2):
+ self.nkeywords += 1
+ if k >=len(self.ORkeyword2):
+ query = self.ANDQuery
+ DescriptionText = self.ANDDescriptionText
+ clausejoin = ' OR '
+ fulltext = ANDFulltext
+ else:
+ query = self.ORQuery
+ DescriptionText = self.ORDescriptionText
+ clausejoin = ' OR '
+ fulltext = ORFulltext
+
+ if self.dbType == "ProbeSet" and item.find('.') < 0 and item.find('\'') < 0:
+ fulltext.append(item)
+ else:
+ if self.matchwhole and item.find("'") < 0:
+ item = "[[:<:]]"+ item+"[[:>:]]"
+ clause2 = []
+ for field in self.searchField:
+ if self.dbType == "Publish":
+ clause2.append("%s REGEXP \"%s\"" % (field,item))
+ else:
+ clause2.append("%s REGEXP \"%s\"" % ("%s.%s" % (self.dbType,field),item))
+ clauseItem = "(%s)" % string.join(clause2, clausejoin)
+ query.append(" (%s) " % clauseItem)
+ if ANDFulltext:
+ clauseItem = " MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,alias,GenbankId, UniGeneId, Probe_Target_Description) AGAINST ('+%s' IN BOOLEAN MODE) " % string.join(ANDFulltext, " +")
+ self.ANDQuery.append(" (%s) " % clauseItem)
+ if ORFulltext:
+ clauseItem = " MATCH (ProbeSet.Name,ProbeSet.description,ProbeSet.symbol,alias,GenbankId, UniGeneId, Probe_Target_Description) AGAINST ('%s' IN BOOLEAN MODE) " % string.join(ORFulltext, " ")
+ self.ORQuery.append(" (%s) " % clauseItem)
+ else:
+ pass
+ return 1
+
+
+
+ def encregexp(self,str):
+ if not str:
+ return []
+ else:
+ wildcardkeyword = str.strip()
+ wildcardkeyword = string.replace(wildcardkeyword,',',' ')
+ wildcardkeyword = string.replace(wildcardkeyword,';',' ')
+ wildcardkeyword = wildcardkeyword.split()
+ NNN = len(wildcardkeyword)
+ for i in range(NNN):
+ keyword = wildcardkeyword[i]
+ keyword = string.replace(keyword,"*",".*")
+ keyword = string.replace(keyword,"?",".")
+ wildcardkeyword[i] = keyword#'[[:<:]]'+ keyword+'[[:>:]]'
+ return wildcardkeyword
+
+
+
+ def patternSearch(self):
+ # Lei Yan
+ ##Process Inputs
+ m1_AND = self._1mPattern.findall(self.ANDkeyword)
+ m2_AND = self._2mPattern.findall(self.ANDkeyword)
+ m3_AND = self._3mPattern.findall(self.ANDkeyword)
+ m5_AND = self._5mPattern.findall(self.ANDkeyword)
+ m1_OR = self._1mPattern.findall(self.ORkeyword)
+ m2_OR = self._2mPattern.findall(self.ORkeyword)
+ m3_OR = self._3mPattern.findall(self.ORkeyword)
+ m5_OR = self._5mPattern.findall(self.ORkeyword)
+
+ #pattern search
+ if m1_AND or m1_OR or m2_AND or m2_OR or m3_AND or m3_OR or m5_AND or m5_OR:
+
+ self.orderByDefalut = 'PROBESETID'
+
+ _1Cmds = map(string.upper, map(lambda x:x[0], m1_AND + m1_OR))
+ _2Cmds = map(string.upper, map(lambda x:x[0], m2_AND + m2_OR))
+ _3Cmds = map(string.upper, map(lambda x:x[0], m3_AND + m3_OR))
+ _5Cmds = map(string.upper, map(lambda x:x[0], m5_AND + m5_OR))
+
+ self.nkeywords += len(_1Cmds) + len(_2Cmds) + len(_3Cmds)
+
+ if self.dbType == "Publish" and \
+ ( (_2Cmds and reduce(lambda x, y: (y not in ["LRS"]) or x, _2Cmds, False))\
+ or (_5Cmds and reduce(lambda x, y: (y not in ["LRS"]) or x, _5Cmds, False)) ):
+ heading = "Search Result"
+ detail = ["Pattern search is not available for phenotype databases at this time."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return 0
+ elif self.dbType == "ProbeSet" and \
+ ((_2Cmds and reduce(lambda x, y: (y not in ["MEAN", "LRS", "PVALUE", "TRANSLRS", "CISLRS", "RANGE", "H2"]) or x, _2Cmds, False))\
+ or (_3Cmds and reduce(lambda x, y: (y not in ["POS", "POSITION", "MB"]) or x, _3Cmds, False))\
+ or (_5Cmds and reduce(lambda x, y: (y not in ["LRS"]) or x, _5Cmds, False))\
+ or (_1Cmds and reduce(lambda x, y: (y not in ["FLAG", "STRAND_PROBE", "STRAND_GENE", "GO", "WIKI", "RIF", "GENEID"]) or x, _1Cmds, False))):
+ heading = "Search Result"
+ detail = ["You entered at least one incorrect search command."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return 0
+ elif self.dbType == "Geno" and (_1Cmds or _2Cmds or _5Cmds or (_3Cmds and reduce(lambda x, y: (y not in ["POS", "POSITION", "MB"]) or x, _3Cmds, False)) ):
+ heading = "Search Result"
+ detail = ["You entered at least one incorrect search command."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return 0
+ else:
+ for k, item in enumerate(m1_OR+m1_AND):
+ if k >=len(m1_OR):
+ query = self.ANDQuery
+ DescriptionText = self.ANDDescriptionText
+ else:
+ query = self.ORQuery
+ DescriptionText = self.ORDescriptionText
+
+ if item[1] == '-':
+ strandName = 'minus'
+ elif item[1] == '+':
+ strandName = 'plus'
+ else:
+ strandName = item[1]
+
+ if item[0].upper() in ("FLAG"):
+ clauseItem = " %s.%s = %s " % (self.dbType, item[0], item[1])
+ DescriptionText.append(HT.Span(' with ', HT.U('FLAG'), ' equal to ', item[1]))
+ elif item[0].upper() in ("WIKI"):
+ clauseItem = " %s.symbol = GeneRIF.symbol and GeneRIF.versionId=0 and GeneRIF.display>0 and (GeneRIF.comment REGEXP \"%s\" or GeneRIF.initial = \"%s\") " % (self.dbType, "[[:<:]]"+ item[1]+"[[:>:]]", item[1])
+ DescriptionText.append(HT.Span(' with GeneWiki contains ', HT.U(item[1])))
+ elif item[0].upper() in ("RIF"):
+ clauseItem = " %s.symbol = GeneRIF_BASIC.symbol and MATCH (GeneRIF_BASIC.comment) AGAINST ('+%s' IN BOOLEAN MODE) " % (self.dbType, item[1])
+ DescriptionText.append(HT.Span(' with GeneRIF contains ', HT.U(item[1])))
+ elif item[0].upper() in ("GENEID"):
+ clauseItem = " %s.GeneId in ( %s ) " % (self.dbType, string.replace(item[1], '-', ', '))
+ DescriptionText.append(HT.Span(' with Entrez Gene ID in ', HT.U(string.replace(item[1], '-', ', '))))
+ elif item[0].upper() in ("GO"):
+ Field = 'GOterm.acc'
+ Id = 'GO:'+('0000000'+item[1])[-7:]
+ Statements = '%s.symbol=GOgene_product.symbol and GOassociation.gene_product_id=GOgene_product.id and GOterm.id=GOassociation.term_id' % (self.dbType);
+ clauseItem = " %s = '%s' and %s " % (Field, Id, Statements)
+ #self.incGoTbl = " ,db_GeneOntology.term as GOterm, db_GeneOntology.association as GOassociation, db_GeneOntology.gene_product as GOgene_product "
+ DescriptionText.append(HT.Span(' with ', HT.U('GO'), ' ID equal to ', Id))
+ else:
+ clauseItem = " %s.%s = '%s' " % (self.dbType, item[0], item[1])
+ if item[0].upper() in ["STRAND_PROBE"]:
+ DescriptionText.append(' with probe on the %s strand' % strandName)
+ elif item[0].upper() in ["STRAND_GENE"]:
+ DescriptionText.append(' with gene on the %s strand' % strandName)
+ else:
+ pass
+ query.append(" (%s) " % clauseItem)
+
+ for k, item in enumerate(m2_OR+m2_AND):
+ if k >=len(m2_OR):
+ query = self.ANDQuery
+ DescriptionText = self.ANDDescriptionText
+ else:
+ query = self.ORQuery
+ DescriptionText = self.ORDescriptionText
+
+ itemCmd = item[0]
+ lowerLimit = float(item[1])
+ upperLimit = float(item[2])
+
+ if itemCmd.upper() in ("TRANSLRS", "CISLRS"):
+ if item[3]:
+ mthresh = float(item[3])
+ clauseItem = " %sXRef.LRS > %2.7f and %sXRef.LRS < %2.7f " % \
+ (self.dbType, min(lowerLimit, upperLimit), self.dbType, max(lowerLimit, upperLimit))
+ if itemCmd.upper() == "CISLRS":
+ clauseItem += """ and %sXRef.Locus = Geno.name and Geno.SpeciesId = %s and %s.Chr = Geno.Chr and ABS(%s.Mb-Geno.Mb) < %2.7f """ % (self.dbType, self.speciesId, self.dbType, self.dbType, mthresh)
+ DescriptionText.append(HT.Span(' with a ', HT.U('cis-QTL'), ' having an LRS between %g and %g using a %g Mb exclusion buffer' % (min(lowerLimit, upperLimit), max(lowerLimit, upperLimit), mthresh)))
+ else:
+ clauseItem += """ and %sXRef.Locus = Geno.name and Geno.SpeciesId = %s and (%s.Chr != Geno.Chr or (%s.Chr != Geno.Chr and ABS(%s.Mb-Geno.Mb) > %2.7f)) """ % (self.dbType, self.speciesId, self.dbType, self.dbType, self.dbType, mthresh)
+ DescriptionText.append(HT.Span(' with a ', HT.U('trans-QTL'), ' having an LRS between %g and %g using a %g Mb exclusion buffer' % (min(lowerLimit, upperLimit), max(lowerLimit, upperLimit), mthresh)))
+ query.append(" (%s) " % clauseItem)
+ self.orderByDefalut = "LRS"
+ else:
+ pass
+ elif itemCmd.upper() in ("RANGE"):
+ #XZ, 03/05/2009: Xiaodong changed Data to ProbeSetData
+ clauseItem = " (select Pow(2, max(value) -min(value)) from ProbeSetData where Id = ProbeSetXRef.dataId) > %2.7f and (select Pow(2, max(value) -min(value)) from ProbeSetData where Id = ProbeSetXRef.dataId) < %2.7f " % (min(lowerLimit, upperLimit), max(lowerLimit, upperLimit))
+ query.append(" (%s) " % clauseItem)
+ DescriptionText.append(HT.Span(' with a range of expression that varied between %g and %g' % (min(lowerLimit, upperLimit), max(lowerLimit, upperLimit)), " (fold difference)"))
+ else:
+ clauseItem = " %sXRef.%s > %2.7f and %sXRef.%s < %2.7f " % \
+ (self.dbType, itemCmd, min(lowerLimit, upperLimit), self.dbType, itemCmd, max(lowerLimit, upperLimit))
+ query.append(" (%s) " % clauseItem)
+ self.orderByDefalut = itemCmd
+ DescriptionText.append(HT.Span(' with ', HT.U(itemCmd), ' between %g and %g' % (min(lowerLimit, upperLimit), max(lowerLimit, upperLimit))))
+
+ for k, item in enumerate(m3_OR+m3_AND):
+ if k >=len(m3_OR):
+ query = self.ANDQuery
+ DescriptionText = self.ANDDescriptionText
+ else:
+ query = self.ORQuery
+ DescriptionText = self.ORDescriptionText
+ itemCmd = item[0]
+ chrsch = item[1]
+ lowerLimit = float(item[2])
+ upperLimit = float(item[3])
+ fname = 'target genes'
+ if self.dbType == "ProbeSet":
+ clauseItem = " %s.Chr = '%s' and %s.Mb > %2.7f and %s.Mb < %2.7f " % \
+ (self.dbType, chrsch, self.dbType, min(lowerLimit, upperLimit), self.dbType, max(lowerLimit, upperLimit))
+ elif self.dbType == "Geno":
+ fname = 'loci'
+ clauseItem = " %s.Chr = '%s' and %s.Mb > %2.7f and %s.Mb < %2.7f " % \
+ (self.dbType, chrsch, self.dbType, min(lowerLimit, upperLimit), self.dbType, max(lowerLimit, upperLimit))
+ else:
+ continue
+ query.append(" (%s) " % clauseItem)
+ self.orderByDefalut = itemCmd
+ DescriptionText.append(HT.Span(' with ', HT.U('target genes'), ' on chromosome %s between %g and %g Mb' % \
+ (chrsch, min(lowerLimit, upperLimit), max(lowerLimit, upperLimit))))
+
+ for k, item in enumerate(m5_OR+m5_AND):
+ if k >=len(m5_OR):
+ query = self.ANDQuery
+ DescriptionText = self.ANDDescriptionText
+ else:
+ query = self.ORQuery
+ DescriptionText = self.ORDescriptionText
+ itemCmd = item[0]
+ lowerLimit = float(item[1])
+ upperLimit = float(item[2])
+ chrsch = item[3]
+ MblowerLimit = float(item[4])
+ MbupperLimit = float(item[5])
+ if self.dbType == "ProbeSet" or self.dbType == "Publish":
+ clauseItem = " %sXRef.LRS > %2.7f and %sXRef.LRS < %2.7f " % \
+ (self.dbType, min(lowerLimit, upperLimit), self.dbType, max(lowerLimit, upperLimit))
+ clauseItem += " and %sXRef.Locus = Geno.name and Geno.SpeciesId = %s and Geno.Chr = '%s' and Geno.Mb > %2.7f and Geno.Mb < %2.7f" \
+ % (self.dbType, self.speciesId, chrsch, min(MblowerLimit, MbupperLimit), max(MblowerLimit, MbupperLimit))
+ query.append(" (%s) " % clauseItem)
+ self.orderByDefalut = "MB"
+ DescriptionText.append(HT.Span(' with ', HT.U('LRS'), ' between %g and %g' % \
+ (min(lowerLimit, upperLimit), max(lowerLimit, upperLimit)), \
+ ' on chromosome %s between %g and %g Mb' % \
+ (chrsch, min(MblowerLimit, MbupperLimit), max(MblowerLimit, MbupperLimit))))
+ pass
+
+ return 1
+
+ def generateWarningLayer(self):
+
+ layerString = """
+ <!-- BEGIN FLOATING LAYER CODE //-->
+ <div id="warningLayer" style="padding:3px; border: 1px solid #222;
+ background-color: #fff; position:absolute;width:250px;left:100;top:100;visibility:hidden">
+ <table border="0" width="250" class="cbrb" cellspacing="0" cellpadding="5">
+ <tr>
+ <td width="100%">
+ <table border="0" width="100%" cellspacing="0" cellpadding="0" height="36">
+ <tr>
+ <td class="cbrb cw ff15 fwb" align="Center" width="100%" style="padding:4px">
+ Sort Table
+ </td>
+ </tr>
+ <tr>
+ <td width="100%" bgcolor="#eeeeee" align="Center" style="padding:4px">
+ <!-- PLACE YOUR CONTENT HERE //-->
+ Resorting this table <br>
+ <!-- END OF CONTENT AREA //-->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <!-- END FLOATING LAYER CODE //-->
+
+ """
+
+ return layerString
+
+ def getTableHeaderForGeno(self, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ className = "fs13 fwb ffl b1 cw cbrb"
+
+ tblobj_header = [[THCell(HT.TD(' ', Class=className), sort=0),
+ THCell(HT.TD('Record', HT.BR(), 'ID', HT.BR(), Class=className), text='record_id', idx=1),
+ THCell(HT.TD('Location', HT.BR(), 'Chr and Mb', HT.BR(), Class=className), text='location', idx=2)]]
+
+ for ncol, item in enumerate(['Record ID', 'Location (Chr, Mb)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ return tblobj_header
+
+
+ def getTableBodyForGeno(self, traitList, formName=None, worksheet=None, newrow=None):
+
+ tblobj_body = []
+
+ className = "fs12 fwn ffl b1 c222"
+
+ for thisTrait in traitList:
+ tr = []
+
+ if not thisTrait.haveinfo:
+ thisTrait.retrieveInfo()
+
+ trId = str(thisTrait)
+
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class=className), text=trId))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showDatabase3('%s','%s','%s','')" % (formName, thisTrait.db.name, thisTrait.name), Class="fs12 fwn ffl"),align="left", Class=className), text=thisTrait.name, val=thisTrait.name.upper()))
+
+ #XZ: trait_location_value is used for sorting
+ trait_location_repr = 'N/A'
+ trait_location_value = 1000000
+
+ if thisTrait.chr and thisTrait.mb:
+ try:
+ trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if thisTrait.chr.upper() == 'X':
+ trait_location_value = 20*1000 + thisTrait.mb
+ else:
+ trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ trait_location_repr = 'Chr%s: %.6f' % (thisTrait.chr, float(thisTrait.mb) )
+
+ tr.append(TDCell(HT.TD(trait_location_repr, Class="fs12 fwn b1 c222", nowrap="on"), trait_location_repr, trait_location_value))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, trait_location_repr]):
+ worksheet.write([newrow, ncol], item)
+
+ newrow += 1
+
+ return tblobj_body
+
+ def getTableHeaderForPublish(self, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ className = "fs13 fwb ffl b1 cw cbrb"
+
+ tblobj_header = [[THCell(HT.TD(' ', Class=className, nowrap="on"), sort=0),
+ THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class=className, nowrap="on"), text="recond_id", idx=1),
+ THCell(HT.TD('Phenotype',HT.BR(),HT.BR(), Class=className, nowrap="on"), text="pheno", idx=2),
+ THCell(HT.TD('Authors',HT.BR(),HT.BR(), Class=className, nowrap="on"), text="auth", idx=3),
+ THCell(HT.TD('Year',HT.BR(),HT.BR(), Class=className, nowrap="on"), text="year", idx=4),
+ THCell(HT.TD('Max',HT.BR(), 'LRS', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="lrs", idx=5),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="lrs_location", idx=6)]]
+
+ for ncol, item in enumerate(["Record", "Phenotype", "Authors", "Year", "Pubmed Id", "Max LRS", "Max LRS Location (Chr: Mb)"]):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ return tblobj_header
+
+ def getTableBodyForPublish(self, traitList, formName=None, worksheet=None, newrow=None, species=''):
+
+ tblobj_body = []
+
+ className = "fs12 fwn b1 c222"
+
+ for thisTrait in traitList:
+ tr = []
+
+ if not thisTrait.haveinfo:
+ thisTrait.retrieveInfo(QTL=1)
+
+ trId = str(thisTrait)
+
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class=className), text=trId))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showDatabase3('%s','%s','%s','')" % (formName, thisTrait.db.name, thisTrait.name), Class="fs12 fwn"), nowrap="yes",align="center", Class=className),str(thisTrait.name), thisTrait.name))
+
+ PhenotypeString = thisTrait.post_publication_description
+ if thisTrait.confidential:
+ if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ PhenotypeString = thisTrait.pre_publication_description
+ tr.append(TDCell(HT.TD(PhenotypeString, Class=className), PhenotypeString, PhenotypeString.upper()))
+
+ tr.append(TDCell(HT.TD(thisTrait.authors, Class="fs12 fwn b1 c222 fsI"),thisTrait.authors, thisTrait.authors.strip().upper()))
+
+ try:
+ PubMedLinkText = myear = repr = int(thisTrait.year)
+ except:
+ PubMedLinkText = repr = "N/A"
+ myear = 0
+
+ if thisTrait.pubmed_id:
+ PubMedLink = HT.Href(text= repr,url= webqtlConfig.PUBMEDLINK_URL % thisTrait.pubmed_id,target='_blank', Class="fs12 fwn")
+ else:
+ PubMedLink = repr
+
+ tr.append(TDCell(HT.TD(PubMedLink, Class=className, align='center'), repr, myear))
+
+ #LRS and its location
+ LRS_score_repr = 'N/A'
+ LRS_score_value = 0
+ LRS_location_repr = 'N/A'
+ LRS_location_value = 1000000
+ LRS_flag = 1
+
+
+ if thisTrait.lrs:
+ LRS_score_repr = '%3.1f' % thisTrait.lrs
+ LRS_score_value = thisTrait.lrs
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class=className), LRS_score_repr, LRS_score_value))
+
+ self.cursor.execute("""
+ select Geno.Chr, Geno.Mb from Geno, Species
+ where Species.Name = '%s' and
+ Geno.Name = '%s' and
+ Geno.SpeciesId = Species.Id
+ """ % (species, thisTrait.locus))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ LRS_Chr = result[0]
+ LRS_Mb = result[1]
+
+ #XZ: LRS_location_value is used for sorting
+ try:
+ LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
+ except:
+ if LRS_Chr.upper() == 'X':
+ LRS_location_value = 20*1000 + float(LRS_Mb)
+ else:
+ LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
+
+ LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
+ LRS_flag = 0
+
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class=className, nowrap="on"), LRS_location_repr, LRS_location_value))
+
+ else:
+ tr.append(TDCell(HT.TD("N/A", Class=className), "N/A", "N/A"))
+ tr.append(TDCell(HT.TD("N/A", Class=className), "N/A", "N/A"))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, PhenotypeString, thisTrait.authors, thisTrait.year, thisTrait.pubmed_id, LRS_score_repr, LRS_location_repr]):
+ worksheet.write([newrow, ncol], item)
+
+ newrow += 1
+
+ return tblobj_body
+
+ def getTableHeaderForProbeSet(self, worksheet=None, newrow=None, headingStyle=None):
+
+ tblobj_header = []
+
+ className = "fs13 fwb ffl b1 cw cbrb"
+
+ tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
+ THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="record_id", idx=1),
+ THCell(HT.TD('Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="symbol", idx=2),
+ THCell(HT.TD('Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="desc", idx=3),
+ THCell(HT.TD('Location',HT.BR(), 'Chr and Mb', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="location", idx=4),
+ THCell(HT.TD('Mean',HT.BR(),'Expr',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="mean", idx=5),
+ THCell(HT.TD('Max',HT.BR(),'LRS',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="lrs", idx=6),
+ THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="lrs_location", idx=7)]]
+
+ for ncol, item in enumerate(['Record', 'Gene ID', 'Homologene ID', 'Symbol', 'Description', 'Location (Chr, Mb)', 'Mean Expr', 'Max LRS', 'Max LRS Location (Chr: Mb)']):
+ worksheet.write([newrow, ncol], item, headingStyle)
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ return tblobj_header
+
+ def getTableBodyForProbeSet(self, traitList=[], primaryTrait=None, formName=None, worksheet=None, newrow=None, species=''):
+
+ tblobj_body = []
+
+ className = "fs12 fwn b1 c222"
+
+ for thisTrait in traitList:
+
+ if not thisTrait.haveinfo:
+ thisTrait.retrieveInfo(QTL=1)
+
+ if thisTrait.symbol:
+ pass
+ else:
+ thisTrait.symbol = "N/A"
+
+ tr = []
+
+ trId = str(thisTrait)
+
+ #XZ, 12/08/2008: checkbox
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
+
+ #XZ, 12/08/2008: probeset name
+ if thisTrait.cellid:
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name, url="javascript:showDatabase3('%s','%s','%s','%s')" % (formName, thisTrait.db.name,thisTrait.name,thisTrait.cellid), Class="fs12 fwn"), Class=className), thisTrait.name, thisTrait.name.upper()))
+ else:
+ tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name, url="javascript:showDatabase3('%s','%s','%s','')" % (formName, thisTrait.db.name,thisTrait.name), Class="fs12 fwn"), Class=className), thisTrait.name, thisTrait.name.upper()))
+
+ if thisTrait.geneid:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % thisTrait.geneid, Class="font_black fs12 fwn")
+ else:
+ symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % thisTrait.symbol, Class="font_black fs12 fwn")
+
+ #XZ, 12/08/2008: gene symbol
+ tr.append(TDCell(HT.TD(symbolurl, Class="fs12 fwn b1 c222 fsI"),thisTrait.symbol, thisTrait.symbol.upper()))
+
+ #XZ, 12/08/2008: description
+ #XZ, 06/05/2009: Rob asked to add probe target description
+ description_string = str(thisTrait.description).strip()
+ target_string = str(thisTrait.probe_target_description).strip()
+
+ description_display = ''
+
+ if len(description_string) > 1 and description_string != 'None':
+ description_display = description_string
+ else:
+ description_display = thisTrait.symbol
+
+ if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ description_display = description_display + '; ' + target_string.strip()
+
+ tr.append(TDCell(HT.TD(description_display, Class=className), description_display, description_display))
+
+ #XZ: trait_location_value is used for sorting
+ trait_location_repr = 'N/A'
+ trait_location_value = 1000000
+
+ if thisTrait.chr and thisTrait.mb:
+ try:
+ trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if thisTrait.chr.upper() == 'X':
+ trait_location_value = 20*1000 + thisTrait.mb
+ else:
+ trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ trait_location_repr = 'Chr%s: %.6f' % (thisTrait.chr, float(thisTrait.mb) )
+
+ tr.append(TDCell(HT.TD(trait_location_repr, Class=className, nowrap="on"), trait_location_repr, trait_location_value))
+
+ #XZ, 01/12/08: This SQL query is much faster.
+ self.cursor.execute("""
+ select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %d and
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId and
+ ProbeSet.Name = '%s'
+ """ % (thisTrait.db.id, thisTrait.name))
+ result = self.cursor.fetchone()
+ if result:
+ if result[0]:
+ mean = result[0]
+ else:
+ mean=0
+ else:
+ mean = 0
+
+ #XZ, 06/05/2009: It is neccessary to turn on nowrap
+ repr = "%2.3f" % mean
+ tr.append(TDCell(HT.TD(repr, Class=className, align='right', nowrap='ON'),repr, mean))
+
+ #LRS and its location
+ LRS_score_repr = 'N/A'
+ LRS_score_value = 0
+ LRS_location_repr = 'N/A'
+ LRS_location_value = 1000000
+ LRS_flag = 1
+
+ #Max LRS and its Locus location
+ if thisTrait.lrs and thisTrait.locus:
+ self.cursor.execute("""
+ select Geno.Chr, Geno.Mb from Geno, Species
+ where Species.Name = '%s' and
+ Geno.Name = '%s' and
+ Geno.SpeciesId = Species.Id
+ """ % (species, thisTrait.locus))
+ result = self.cursor.fetchone()
+
+ if result:
+ if result[0] and result[1]:
+ LRS_Chr = result[0]
+ LRS_Mb = result[1]
+
+ #XZ: LRS_location_value is used for sorting
+ try:
+ LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
+ except:
+ if LRS_Chr.upper() == 'X':
+ LRS_location_value = 20*1000 + float(LRS_Mb)
+ else:
+ LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
+
+ LRS_score_repr = '%3.1f' % thisTrait.lrs
+ LRS_score_value = thisTrait.lrs
+ LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
+ LRS_flag = 0
+
+ #tr.append(TDCell(HT.TD(HT.Href(text=LRS_score_repr,url="javascript:showIntervalMapping('%s', '%s : %s')" % (formName, thisTrait.db.shortname, thisTrait.name), Class="fs12 fwn"), Class=className, align='right', nowrap="on"),LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class=className, align='right', nowrap="on"), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class=className, nowrap="on"), LRS_location_repr, LRS_location_value))
+
+ if LRS_flag:
+ tr.append(TDCell(HT.TD(LRS_score_repr, Class=className), LRS_score_repr, LRS_score_value))
+ tr.append(TDCell(HT.TD(LRS_location_repr, Class=className), LRS_location_repr, LRS_location_value))
+
+ else:
+ tr.append(TDCell(HT.TD("N/A", Class=className), "N/A", "N/A"))
+ tr.append(TDCell(HT.TD("N/A", Class=className), "N/A", "N/A"))
+
+ tblobj_body.append(tr)
+
+ for ncol, item in enumerate([thisTrait.name, thisTrait.geneid, thisTrait.homologeneid, thisTrait.symbol, description_display, trait_location_repr, mean, LRS_score_repr, LRS_location_repr]):
+ worksheet.write([newrow, ncol], item)
+
+
+ newrow += 1
+
+ return tblobj_body
+
+ def createExcelFileWithTitleAndFooter(self, workbook=None, identification=None, db=None, returnNumber=None):
+
+ worksheet = workbook.add_worksheet()
+
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=14, border = 1, border_color="gray")
+
+ ##Write title Info
+ # Modified by Hongqiang Li
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([2, 0], "Trait : %s" % identification, titleStyle)
+ worksheet.write([3, 0], "Database : %s" % db.fullname, titleStyle)
+ worksheet.write([4, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([5, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+ worksheet.write([6, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+ #Write footer info
+ worksheet.write([9 + returnNumber, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA21131), NCI MMHCC (U01CA105417), and NCRR (U01NR 105417)", titleStyle)
+ worksheet.write([10 + returnNumber, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+
+ return worksheet
+
+ def getSortByValue(self, datasetType=''):
+
+ if datasetType == 'Geno':
+ sortby = ("location", "up")
+ elif datasetType == 'ProbeSet':
+ sortby = ("symbol", "up")
+ else: #Phenotype
+ sortby = ("record_id", "down")
+
+ return sortby
+
+
diff --git a/web/webqtl/search/TextSearchPage.py b/web/webqtl/search/TextSearchPage.py
new file mode 100755
index 00000000..42ff72c4
--- /dev/null
+++ b/web/webqtl/search/TextSearchPage.py
@@ -0,0 +1,536 @@
+# 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
+
+import string
+import os
+import cPickle
+from math import *
+
+import reaper
+from htmlgen import HTMLgen2 as HT
+
+from base import admin
+from base import webqtlConfig
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base.webqtlDataset import webqtlDataset
+from base.webqtlTrait import webqtlTrait
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+from utility import webqtlUtil
+
+
+
+class TextSearchPage(templatePage):
+ maxReturn = 200
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ # updated by NL, deleted jquery here, move it to dhtml.js
+ self.dict['js1'] = ''
+
+ species_list = [] #List of species (mouse, rat, human), with the selected species listed first
+
+ input_species = string.strip(string.lower(fd.formdata.getfirst('species', "mouse"))) #XZ, Oct 28, 2009: I changed the default species to mouse.
+ species_list.append(input_species)
+ #Create list of species (mouse, rat, human) with the species the user selected first
+ for species in ["mouse","rat","human"]:
+ if species not in species_list:
+ species_list.append(species)
+
+ ADMIN_tissue_alias = admin.ADMIN_tissue_alias
+
+ tissue = string.strip(string.lower(fd.formdata.getfirst('tissue', "")))
+ if tissue:
+ try:
+ rev_ADMIN_tissue_alias = {}
+ for key in ADMIN_tissue_alias.keys():
+ rev_ADMIN_tissue_alias[key] = key
+ for alias in ADMIN_tissue_alias[key]:
+ rev_ADMIN_tissue_alias[alias.upper()] = key
+ tissue = rev_ADMIN_tissue_alias[tissue.upper()]
+ except:
+ tissue = "UNKNOWN"
+
+ #possibly text output
+ txtOutput = [] #ZS: if format=text
+ all_species_dataset_count = 0 #XZ: count of datasets across all species; used in the opening text of the page
+ all_species_trait_count = 0 #XZ: count of records across all species; used in opening text of the page and text file (if format = text)
+
+ #div containing the tabs (species_container), the tabs themselves (species_tab_list, which is inserted into species_tabs), and the table (species_table) containing both the tissue and results tables for each tab
+ species_container = HT.Div(id="species_tabs", Class="tab_container") #Div that will contain tabs for mouse/rat/human species; each tab contains a table with the result count for each tissue group
+ species_tab_list = [HT.Href(text="%s" % species_list[0].capitalize(), url="#species1"), HT.Href(text="%s" % species_list[1].capitalize(), url="#species2"), HT.Href(text="%s" % species_list[2].capitalize(), url="#species3")]
+ species_tabs = HT.List(species_tab_list, Class="tabs")
+ species_table = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%",border=0, align="Left")
+
+ for i in range(len(species_list)):
+ species_container_table = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%",border=0, align="Left") #ZS: Table containing both the tissue record count and trait record tables as cells; this fixes a display issue in some browsers that places the tables side by side instead of top/bottom
+
+ species = species_list[i]
+ ADMIN_search_dbs = admin.ADMIN_search_dbs[species]
+ this_species_dataset_count = 0 #XZ: count of the datasets containing results for this species
+ this_species_trait_count = 0 #XZ: count of the trait records for this species
+
+ div = HT.Div(id="species%s" % (i+1), Class="tab_content")
+ tab_container = HT.Span() #ZS: Contains species_container_table within the species' tab
+
+ tissuePageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%",border=0, align="Left")
+ tissue_tblobj = {} # object used to create the table listing the results for each tissue
+ tissue_tblobj['header'] = self.getTissueTableHeader() # creates header for table listing results for selected tissue
+
+ traitPageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%",border=0, align="Left")
+ trait_tblobj = {} # object used to create the table listing the trait results for each tissue
+ trait_tblobj['header'] = self.getTraitTableHeader() # creates header for table listing trait results for selected tissue
+
+ tissue_tblobj['body'], trait_tblobj['body'], this_species_dataset_count, this_species_trait_count, this_species_txtOutput = self.createTableBodies(fd, species, tissue, ADMIN_search_dbs)
+
+ if species == input_species:
+ txtOutput = this_species_txtOutput
+
+ filename1 = webqtlUtil.genRandStr("Search_") #filename for tissue table object
+ tissue_objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename1), 'wb')
+ cPickle.dump(tissue_tblobj, tissue_objfile)
+ tissue_objfile.close()
+
+ tissue_sortby = self.getTissueSortByValue() # sets how the tissue table should be sorted by default
+ tissue_div = HT.Div(webqtlUtil.genTableObj(tblobj=tissue_tblobj, file=filename1, sortby=tissue_sortby, tableID = "tissue_sort%s" % (i+1), addIndex = "1"), Id="tissue_sort%s" % (i+1))
+
+ tissuePageTable.append(HT.TR(HT.TD("&nbsp;")))
+ tissuePageTable.append(HT.TR(HT.TD(tissue_div)))
+ tissuePageTable.append(HT.TR(HT.TD("&nbsp;")))
+ species_container_table.append(HT.TR(HT.TD(tissuePageTable)), HT.TR(HT.TD("&nbsp;")))
+
+
+ filename2 = webqtlUtil.genRandStr("Search_") #filename for trait table object
+ trait_objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename2), 'wb')
+ cPickle.dump(trait_tblobj, trait_objfile)
+ trait_objfile.close()
+
+ trait_sortby = self.getTraitSortByValue() # sets how the trait table should be sorted by default
+ trait_div = HT.Div(webqtlUtil.genTableObj(tblobj=trait_tblobj, file=filename2, sortby=trait_sortby, tableID = "results_sort%s" % (i+1), addIndex = "0"), Id="results_sort%s" % (i+1))
+
+ traitPageTable.append(HT.TR(HT.TD("&nbsp;")))
+ traitPageTable.append(HT.TR(HT.TD(trait_div)))
+ traitPageTable.append(HT.TR(HT.TD("&nbsp;")))
+ species_container_table.append(HT.TR(HT.TD(traitPageTable)), HT.TR(HT.TD("&nbsp;")))
+
+ if this_species_trait_count == 0:
+ tab_container.append(HT.Div("No records retrieved for this species.", align="left", valign="top", style="font-size:42"))
+ else:
+ tab_container.append(species_container_table)
+
+ all_species_dataset_count += this_species_dataset_count
+ all_species_trait_count += this_species_trait_count
+
+ div.append(tab_container)
+ species_table.append(HT.TR(HT.TD(div)))
+
+ species_container.append(species_table)
+
+
+
+
+ if fd.returnFmt != 'text': #if the format is not 'text'
+ self.dict['title'] = 'Search Results'
+ TD_LR = HT.TD(height=100,width="100%",bgColor='#fafafa',valign="top")
+ pageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%",border=0, align="Left") # Table containing all of the page's elements (opening text, form); in some browers the elements arrange themselves horizontally if you don't put them into a table, so this fixes that problem
+
+ formTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="100%",border=0) # Table containing all of the form's elements (tabs, option buttons); used to correct the same issue mentioned in pageTable's comment
+
+ mainForm = HT.Form( cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':'_','CellID':'_','RISet':fd.RISet}
+ hddn['incparentsf1']='ON'
+ for key in hddn.keys():
+ mainForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ #Add to collection, select all, invert selection, and deselect all ("reset") buttons
+ addselect = HT.Href(url="#redirect", Class="add_traits")
+ addselect_img = HT.Image("/images/add_collection1_final.jpg", name="addselect", alt="Add To Collection", title="Add To Collection", style="border:none;")
+ addselect.append(addselect_img)
+ selectall = HT.Href(url="#redirect", onClick="checkAll(document.getElementsByName('showDatabase')[0]);")
+ selectall_img = HT.Image("/images/select_all2_final.jpg", name="selectall", alt="Select All", title="Select All", style="border:none;")
+ selectall.append(selectall_img)
+ selectinvert = HT.Href(url="#redirect", onClick="checkInvert(document.getElementsByName('showDatabase')[0];")
+ selectinvert_img = HT.Image("/images/invert_selection2_final.jpg", name="selectinvert", alt="Invert Selection", title="Invert Selection", style="border:none;")
+ selectinvert.append(selectinvert_img)
+ reset = HT.Href(url="#redirect", onClick="checkNone(document.getElementsByName('showDatabase')[0]); return false;")
+ reset_img = HT.Image("/images/select_none2_final.jpg", alt="Select None", title="Select None", style="border:none;")
+ reset.append(reset_img)
+
+ #Table with select, deselect, invert, etc. It is used for the results table.
+ optionsTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="20%",border=0)
+ optionsRow = HT.TR(HT.TD(selectall, width="25%"), HT.TD(reset, width="25%"), HT.TD(selectinvert, width="25%"), HT.TD(addselect, width="25%"))
+ labelsRow = HT.TR(HT.TD("&nbsp;"*2,"Select", width="25%"), HT.TD("&nbsp;","Deselect", width="25%"), HT.TD("&nbsp;"*3,"Invert", width="25%"), HT.TD("&nbsp;"*4,"Add", width="25%"))
+ optionsTable.append(HT.TR(HT.TD("&nbsp;")), optionsRow, labelsRow)
+
+ if fd.geneName:
+ searchType = "gene name " + fd.geneName
+ elif fd.refseq:
+ searchType = "RefSeq accession number " + fd.refseq
+ elif fd.genbankid:
+ searchType = "Genbank ID " + fd.genbankid
+ elif fd.geneid:
+ searchType = "Gene ID " + fd.geneid
+ else:
+ searchType = ""
+
+ SearchText = HT.Span("You searched for the %s in GeneNetwork." % searchType, HT.BR(),
+ "We queried %s expression datasets across %s species and listed the results" % (all_species_dataset_count, len(species_list)), HT.BR(),
+ "below. A total of %s records that may be of interest to you were found. The" % all_species_trait_count, HT.BR(),
+ "top table lists the number of results found for each relevant tissue, and the", HT.BR(),
+ "bottom gives a basic summary of each result. To study one of the results, click", HT.BR(),
+ "its Record ID. More detailed information is also available for each result's group", HT.BR() ,
+ "and dataset. To switch between species, click the tab with the corresponding", HT.BR(),
+ "label.", HT.BR(), HT.BR(),
+ "Please visit the links to the right to learn more about the variety of features", HT.BR(),
+ "available within GeneNetwork.")
+
+ LinkText = HT.Span()
+
+ mainLink = HT.Href(url="/webqtl/main.py", text = "Main Search Page", target="_blank")
+ homeLink = HT.Href(url="/home.html", text = "What is GeneNetwork?", target="_blank")
+ tourLink = HT.Href(url="/tutorial/WebQTLTour/", text = "Tour of GeneNetwork (20-40 min)", target="_blank")
+ faqLink = HT.Href(url="/faq.html", text = "Frequently Asked Questions", target="_blank")
+ glossaryLink = HT.Href(url="/glossary.html", text = "Glossary of terms used throughout GeneNetwork", target="_blank")
+
+ LinkText.append(mainLink, HT.BR(), homeLink, HT.BR(), tourLink, HT.BR(), faqLink, HT.BR(), glossaryLink)
+
+ formTable.append(HT.TR(HT.TD(species_tabs, species_container)), HT.TR(HT.TD(optionsTable)))
+ mainForm.append(formTable)
+
+
+ if fd.geneName:
+ SearchHeading = HT.Paragraph('Search Results for gene name ', fd.geneName)
+ elif fd.refseq:
+ SearchHeading = HT.Paragraph('Search Results for RefSeq accession number ', fd.refseq)
+ elif fd.genbankid:
+ SearchHeading = HT.Paragraph('Search Results for Genbank ID ', fd.genbankid)
+ elif fd.geneid:
+ SearchHeading = HT.Paragraph('Search Results for Gene ID ', fd.geneid)
+ else:
+ SearchHeading = HT.Paragraph('')
+
+ SearchHeading.__setattr__("class","title")
+
+ pageTable.append(HT.TR(HT.TD(SearchText, width=600), HT.TD(LinkText, align="left", valign="top")), HT.TR(HT.TD("&nbsp;", colspan=2)), HT.TR(HT.TD(mainForm, colspan=2)))
+ TD_LR.append(SearchHeading, pageTable)
+ self.dict['body'] = TD_LR
+ else:
+ if len(txtOutput) == 0:
+ self.output = "##No records were found for this species. \n"
+ else:
+ self.output = "##A total of %d records were returned. \n" % all_species_trait_count
+ newOutput = []
+ strainLists = {}
+ for item in txtOutput:
+ tissueGrp, thisTrait = item
+ RISet = thisTrait.riset
+ if strainLists.has_key(RISet):
+ thisStrainlist = strainLists[RISet]
+ else:
+ thisGenotype = reaper.Dataset()
+ thisGenotype.read(os.path.join(webqtlConfig.GENODIR, RISet + '.geno'))
+ if thisGenotype.type == "riset":
+ _f1, _f12, _mat, _pat = webqtlUtil.ParInfo[RISet]
+ thisGenotype = thisGenotype.add(Mat=_mat, Pat=_pat, F1=_f1)
+ thisStrainlist = list(thisGenotype.prgy)
+ strainLists[RISet] = thisStrainlist
+ thisTrait.retrieveData(strainlist=thisStrainlist)
+ thisData = []
+ for item in thisStrainlist:
+ if thisTrait.data.has_key(item): thisData.append(thisTrait.data[item].val)
+ else: thisData.append(None)
+ newOutput.append(["Structure", "Database", "ProbeSetID", "Cross"] + thisStrainlist)
+ newOutput.append([tissueGrp, '"%s"' % thisTrait.db.fullname, thisTrait.name, RISet]+map(str,thisData))
+ newOutput = webqtlUtil.asymTranspose(newOutput)
+ for item in newOutput:
+ self.output += string.join(item, "\t") + "\n"
+
+
+ def createTableBodies(self, fd, species, tissue, ADMIN_search_dbs):
+
+ this_species_txtOutput = []
+
+ #priority GeneName > refseq > genbankid
+ this_species_trait_count = 0 #count of all traits in this species
+ this_species_dataset_count = 0 #Number of datasets in this species
+ row_count = 0 #Index number used in the first row of the trait table
+ trait_tblobj_body = [] #body of table with the results themselves;
+ tissue_tblobj_body = [] #body of table with the number of results for each tissue group
+ className = "fs12 fwn b1 c222"
+
+ for i, tissueGrp in enumerate(ADMIN_search_dbs.keys()):
+ if tissue and tissue.upper() != tissueGrp.upper():
+ continue
+ dbNames = ADMIN_search_dbs[tissueGrp]
+
+ tissue_tr = [] #Table row for tissue group
+ tissue_tr.append(TDCell(HT.TD('', Class=className)))
+ tissue_tr.append(TDCell(HT.TD(tissueGrp.capitalize(), Class=className), tissueGrp, tissueGrp)) #Append cell with tissue name to row
+
+ this_tissue_record_count = 0 #Count of the results for each tissue
+ for dbName in dbNames:
+ this_species_dataset_count += 1
+ thisDB = webqtlDataset(dbName, self.cursor)
+
+ if fd.geneName:
+ if fd.searchAlias:
+ self.cursor.execute("""SELECT ProbeSet.Name
+ FROM
+ ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSetFreeze.Name = "%s" AND
+ ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId AND
+ MATCH (ProbeSet.symbol, alias) AGAINST ("+%s" IN BOOLEAN MODE) AND
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId""" % (dbName, fd.geneName))
+ else:
+ self.cursor.execute("""SELECT ProbeSet.Name
+ FROM
+ ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSetFreeze.Name = "%s" AND
+ ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId AND
+ ProbeSet.symbol = "%s" AND
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId""" % (dbName, fd.geneName))
+ elif fd.refseq:
+
+ # XZ, Oct/08/2009: Search for RefSeq ID is kind of tricky. One probeset can have multiple RefseqIDs that are delimited by ' /// ' (currently).
+ # So I have to use 'like' instead of '=' in SQL query. But user search with one short string, for example 'NM_1', it will return thousands of results.
+ # To prevent this, I set the restriction that the length of input Refseq ID must be at least 9 characters. Otherwise, do NOT start searching.
+ # Even with the restriction of input RefSeqID, I'm still worried about the 'like' in SQL query. My concern is in future, there might be RefSeqIDs with
+ # 10 characters whose first 9 characters are the same as the existing ones. So I decide to further check the result. We should also consider that the
+ # RefSeqID in database may have version number such as "NM_177938.2". If the input RefSeqID is 'NM_177938', it should be matched. I think we should get rid of the version number in database.
+
+ if len(fd.refseq) < 9:
+ if fd.returnFmt != 'text':
+ heading = "Search Result"
+ detail = ["The RefSeq ID that you inputed is less than 9 characters. GeneNetwork thinks it is not a legitimate RefSeq ID and did not do the search. Please try to use a RefSeq ID with at least 9 characters."]
+ self.error(heading=heading,detail=detail,error="Not Found")
+ else:
+ self.output = "#The gene name or IDs you submitted did not match any record in the databases available. You may try different gene names or tissue type."
+ return
+ else:
+ sqlString = """SELECT ProbeSet.Id, ProbeSet.RefSeq_TranscriptId
+ FROM
+ ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSetFreeze.Name = "%s" AND
+ ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId AND
+ MATCH(ProbeSet.RefSeq_TranscriptId) AGAINST ("+%s" IN BOOLEAN MODE) AND
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId""" % (dbName, fd.refseq)
+
+ self.cursor.execute(sqlString)
+
+ results = self.cursor.fetchall()
+ if results:
+ Id_of_really_matched_probeset = []
+
+ for one_result in results:
+ ProbeSet_Id, ProbeSet_RefSeq_TranscriptId = one_result
+ multiple_RefSeqId = string.split(string.strip(ProbeSet_RefSeq_TranscriptId), '///')
+ for one_RefSeqId in multiple_RefSeqId:
+ tokens = string.split( one_RefSeqId, '.' )
+ one_RefSeqId_without_versionNum = string.strip(tokens[0])
+ if one_RefSeqId_without_versionNum == fd.refseq:
+ Id_of_really_matched_probeset.append( ProbeSet_Id )
+ break
+
+ if Id_of_really_matched_probeset:
+ condition_string = " or ".join(["Id = %s" % one_ID for one_ID in Id_of_really_matched_probeset])
+ sqlString = """SELECT ProbeSet.Name from ProbeSet where (%s)""" % condition_string
+
+ self.cursor.execute(sqlString)
+ else:
+ pass
+
+ elif fd.genbankid:
+ self.cursor.execute("""SELECT ProbeSet.Name
+ FROM
+ ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSetFreeze.Name = "%s" AND
+ ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId AND
+ ProbeSet.GenbankId = "%s" AND
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId""" % (dbName, fd.genbankid))
+ elif fd.geneid:
+ self.cursor.execute("""SELECT ProbeSet.Name
+ FROM
+ ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE
+ ProbeSetFreeze.Name = "%s" AND
+ ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId AND
+ ProbeSet.GeneId = "%s" AND
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId""" % (dbName, fd.geneid))
+ else:
+ continue
+
+ results = self.cursor.fetchall()
+ if len(results) > 0:
+ this_tissue_record_count += len(results)
+ this_species_trait_count += this_tissue_record_count
+
+ for result in results:
+ _ProbeSetID = result[0]
+ thisTrait = webqtlTrait(db=thisDB, name=_ProbeSetID, cursor=self.cursor)
+ results_tr = []
+ trId = str(thisTrait)
+ _traitUrl = thisTrait.genHTML(dispFromDatabase=1)
+ _traitName = str(thisTrait)
+
+ #ZS: check box column
+ results_tr.append(TDCell(HT.TD(str(row_count+1), HT.Input(type="checkbox", Class="checkallbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", align="right", Class=className), str(row_count+1), row_count+1))
+ row_count += 1
+
+ #ZS: Tissue column
+ results_tr.append(TDCell(HT.TD(tissueGrp.capitalize(), Class=className), tissueGrp, tissueGrp))
+
+ #ZS: Group column
+ risetUrl = HT.Href(text=thisTrait.riset, url="http://www.genenetwork.org/%sCross.html#%s" % (species, thisTrait.riset), target="_blank", Class=className)
+ results_tr.append(TDCell(HT.TD(risetUrl, Class=className), thisTrait.riset, thisTrait.riset))
+
+ #ZS: Dataset column
+ results_tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.db.fullname, url = webqtlConfig.INFOPAGEHREF % thisTrait.db.name,
+ target='_blank', Class="fs13 fwn non_bold"), Class=className), thisTrait.db.name.upper(), thisTrait.db.name.upper()))
+
+ #ZS: Trait ID column
+ results_tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.getGivenName(),url="javascript:showDatabase3('%s','%s','%s','')" % ('showDatabase', thisTrait.db.name, thisTrait.name), Class="fs12 fwn"), nowrap="yes",align="left", Class=className),str(thisTrait.name), thisTrait.name))
+
+ #ZS: Symbol column and Description column
+ description_string = str(thisTrait.description).strip()
+ if (thisTrait.db.type == "ProbeSet"):
+ target_string = str(thisTrait.probe_target_description).strip()
+
+ description_display = ''
+
+ if len(description_string) > 1 and description_string != 'None':
+ description_display = description_string
+ else:
+ description_display = thisTrait.symbol
+
+ if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ description_display = description_display + '; ' + target_string.strip()
+
+ description_string = description_display
+ else:
+ results_tr.append(TDCell(HT.TD("--", align="left", Class=className), "--", "Zz"))
+
+ results_tr.append(TDCell(HT.TD(description_string, Class=className), description_string, description_string))
+
+ #XZ: trait_location_value is used for sorting
+ trait_location_repr = "--"
+ trait_location_value = 1000000
+
+ if hasattr(thisTrait, 'chr') and hasattr(thisTrait, 'mb') and thisTrait.chr and thisTrait.mb:
+ try:
+ trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
+ except:
+ if thisTrait.chr.upper() == "X":
+ trait_location_value = 20*1000 + thisTrait.mb
+ else:
+ trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
+
+ trait_location_repr = "Chr%s: %.6f" % (thisTrait.chr, float(thisTrait.mb) )
+
+ results_tr.append(TDCell(HT.TD(trait_location_repr, nowrap='ON', Class=className), trait_location_repr, trait_location_value))
+
+ #ZS: Mean column
+ self.cursor.execute("""
+ select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %d and
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId and
+ ProbeSet.Name = '%s'
+ """ % (thisTrait.db.id, thisTrait.name))
+ result = self.cursor.fetchone()
+ if result:
+ if result[0]:
+ mean = result[0]
+ else:
+ mean=0
+ else:
+ mean = 0
+
+ repr = "%2.3f" % mean
+ results_tr.append(TDCell(HT.TD(repr, Class=className, align='right', nowrap='ON'),repr, mean))
+ trait_tblobj_body.append(results_tr)
+
+ this_species_txtOutput.append([tissueGrp, thisTrait])
+
+
+ tissue_tr.append(TDCell(HT.TD(str(this_tissue_record_count), Class=className), str(this_tissue_record_count), this_tissue_record_count))
+ tissue_tblobj_body.append(tissue_tr)
+
+ self.output = "self.output"
+
+ return tissue_tblobj_body, trait_tblobj_body, this_species_dataset_count, this_species_trait_count, this_species_txtOutput
+
+
+ def getTissueSortByValue(self):
+
+ sortby = ("tissue_group", "up")
+
+ return sortby
+
+
+ def getTraitSortByValue(self):
+
+ sortby = ("tissue", "up")
+
+ return sortby
+
+
+ def getTissueTableHeader(self):
+
+ tblobj_header = []
+
+ className = "fs13 fwb ffl b1 cw cbrb"
+
+ tblobj_header = [[THCell(HT.TD(' ', Class=className, nowrap="on"), sort=0),
+ THCell(HT.TD('Tissue',HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="tissue_group", idx=1),
+ THCell(HT.TD('Results', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="results", idx=2)]]
+
+ return tblobj_header
+
+ def getTraitTableHeader(self):
+
+ tblobj_header = []
+
+ className = "fs13 fwb ffl b1 cw cbrb"
+
+ tblobj_header = [[THCell(HT.TD('Index',HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="index", idx=0),
+ THCell(HT.TD('Tissue',HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="tissue", idx=1),
+ THCell(HT.TD('Group',HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="group", idx=2),
+ THCell(HT.TD('Dataset', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="dataset", idx=3),
+ THCell(HT.TD('Record ID', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="name", idx=4),
+ THCell(HT.TD('Description', HT.BR(), HT.BR(), valign="top", Class=className, nowrap="on"), text="desc", idx=5),
+ THCell(HT.TD('Location', HT.BR(), 'Chr and Mb', HT.BR(), valign="top", Class=className, nowrap="on"), text="location", idx=6),
+ THCell(HT.TD('Mean', HT.BR(), 'Expr', HT.BR(), valign="top", Class=className, nowrap="on"), text="mean", idx=7)]]
+
+ return tblobj_header
diff --git a/web/webqtl/search/__init__.py b/web/webqtl/search/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/search/__init__.py
diff --git a/web/webqtl/search/pubmedsearch.py b/web/webqtl/search/pubmedsearch.py
new file mode 100755
index 00000000..d0d18ff5
--- /dev/null
+++ b/web/webqtl/search/pubmedsearch.py
@@ -0,0 +1,12 @@
+import sys
+import os
+import MySQLdb
+import time
+
+db='db_webqtl_leiyan'
+author="megan memphis"
+
+con = MySQLdb.Connect(db=db,user='webqtlupd',passwd='webqtl', host="localhost")
+cursor = con.cursor()
+cursor.execute('select PhenotypeId, Locus, DataId, Phenotype.Post_publication_description from PublishXRef, Phenotype where PublishXRef.PhenotypeId = Phenotype.Id and InbredSetId=%s'%InbredSetId)
+PublishXRefInfos = cursor.fetchall()
diff --git a/web/webqtl/showTrait/DataEditingPage.py b/web/webqtl/showTrait/DataEditingPage.py
new file mode 100644
index 00000000..f38b9880
--- /dev/null
+++ b/web/webqtl/showTrait/DataEditingPage.py
@@ -0,0 +1,1883 @@
+import string
+import os
+import cPickle
+import pyXLWriter as xl
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility import webqtlUtil, Plot
+from base.webqtlTrait import webqtlTrait
+from dbFunction import webqtlDatabaseFunction
+from base.templatePage import templatePage
+from basicStatistics import BasicStatisticsFunctions
+
+
+#########################################
+# DataEditingPage
+#########################################
+class DataEditingPage(templatePage):
+
+ def __init__(self, fd, thisTrait=None):
+
+ templatePage.__init__(self, fd)
+
+ self.dict['title'] = 'Data Editing'
+ TD_LR = HT.TD(valign="top",width="100%",bgcolor="#fafafa")
+
+ if not self.openMysql():
+ return
+ if not fd.genotype:
+ fd.readData(incf1=1)
+
+ #############################
+ # determine data editing page format
+ #############################
+ varianceDataPage = 0
+ if fd.formID == 'varianceChoice':
+ varianceDataPage = 1
+
+ if varianceDataPage:
+ fmID='dataEditing'
+ nCols = 6
+ else:
+ if fd.enablevariance:
+ fmID='pre_dataEditing'
+ nCols = 4
+ else:
+ fmID='dataEditing'
+ nCols = 4
+
+ #############################
+ ## titles, etc.
+ #############################
+
+ titleTop = HT.Div()
+
+ title1 = HT.Paragraph("&nbsp;&nbsp;Details and Links", style="border-radius: 5px;", Id="title1", Class="sectionheader")
+ title1Body = HT.Paragraph(Id="sectionbody1")
+
+ if fd.enablevariance and not varianceDataPage:
+ title2 = HT.Paragraph("&nbsp;&nbsp;Submit Variance", style="border-radius: 5px;", Id="title2", Class="sectionheader")
+ else:
+ title2 = HT.Paragraph("&nbsp;&nbsp;Basic Statistics", style="border-radius: 5px;", Id="title2", Class="sectionheader")
+ title2Body = HT.Paragraph(Id="sectionbody2")
+
+ title3 = HT.Paragraph("&nbsp;&nbsp;Calculate Correlations", style="border-radius: 5px;", Id="title3", Class="sectionheader")
+ title3Body = HT.Paragraph(Id="sectionbody3")
+
+ title4 = HT.Paragraph("&nbsp;&nbsp;Mapping Tools", style="border-radius: 5px;", Id="title4", Class="sectionheader")
+ title4Body = HT.Paragraph(Id="sectionbody4")
+
+ title5 = HT.Paragraph("&nbsp;&nbsp;Review and Edit Data", style="border-radius: 5px;", Id="title5", Class="sectionheader")
+ title5Body = HT.Paragraph(Id="sectionbody5")
+
+ #############################
+ ## Hidden field
+ #############################
+
+ # Some fields, like method, are defaulted to None; otherwise in IE the field can't be changed using jquery
+ hddn = {'FormID':fmID, 'RISet':fd.RISet, 'submitID':'', 'scale':'physic', 'additiveCheck':'ON', 'showSNP':'ON', 'showGenes':'ON', 'method':None,\
+ 'parentsf14regression':'OFF', 'stats_method':'1', 'chromosomes':'-1', 'topten':'', 'viewLegend':'ON', 'intervalAnalystCheck':'ON', 'valsHidden':'OFF',\
+ 'database':'', 'criteria':None, 'MDPChoice':None, 'bootCheck':None, 'permCheck':None, 'applyVarianceSE':None, 'strainNames':'_', 'strainVals':'_',\
+ 'strainVars':'_', 'otherStrainNames':'_', 'otherStrainVals':'_', 'otherStrainVars':'_', 'extra_attributes':'_', 'other_extra_attributes':'_'}
+
+ if fd.enablevariance:
+ hddn['enablevariance']='ON'
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+
+ if thisTrait:
+ hddn['fullname'] = str(thisTrait)
+ try:
+ hddn['normalPlotTitle'] = thisTrait.symbol
+ hddn['normalPlotTitle'] += ": "
+ hddn['normalPlotTitle'] += thisTrait.name
+ except:
+ hddn['normalPlotTitle'] = str(thisTrait.name)
+ hddn['fromDataEditingPage'] = 1
+ if thisTrait.db and thisTrait.db.type and thisTrait.db.type == 'ProbeSet':
+ hddn['trait_type'] = thisTrait.db.type
+ if thisTrait.cellid:
+ hddn['cellid'] = thisTrait.cellid
+ else:
+ self.cursor.execute("SELECT h2 from ProbeSetXRef WHERE DataId = %d" % thisTrait.mysqlid)
+ heritability = self.cursor.fetchone()
+ hddn['heritability'] = heritability
+
+ hddn['attribute_names'] = ""
+
+ hddn['mappingMethodId'] = webqtlDatabaseFunction.getMappingMethod (cursor=self.cursor, groupName=fd.RISet)
+
+ #############################
+ ## Display Trait Information
+ #############################
+
+ headSpan = self.dispHeader(fd,thisTrait) #Draw header
+
+ titleTop.append(headSpan)
+
+ if fd.identification:
+ hddn['identification'] = fd.identification
+
+ else:
+ hddn['identification'] = "Un-named trait" #If no identification, set identification to un-named
+
+ self.dispTraitInformation(fd, title1Body, hddn, thisTrait) #Display trait information + function buttons
+
+ #############################
+ ## Generate form and buttons
+ #############################
+
+ mainForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE),
+ name='dataInput', submit=HT.Input(type='hidden'))
+
+ next=HT.Input(type='submit', name='submit',value='Next',Class="button")
+ reset=HT.Input(type='Reset',name='',value=' Reset ',Class="button")
+ correlationMenus = []
+
+ if thisTrait == None:
+ thisTrait = webqtlTrait(data=fd.allTraitData, db=None)
+
+ # Variance submit page only
+ if fd.enablevariance and not varianceDataPage:
+ title2Body.append("Click the next button to go to the variance submission form.",
+ HT.Center(next,reset))
+ else:
+ self.dispBasicStatistics(fd, title2Body, thisTrait)
+ self.dispCorrelationTools(fd, title3Body, thisTrait)
+ self.dispMappingTools(fd, title4Body, thisTrait)
+
+ #############################
+ ## Trait Value Table
+ #############################
+
+ self.dispTraitValues(fd, title5Body, varianceDataPage, nCols, mainForm, thisTrait)
+
+ if fd.allstrainlist:
+ hddn['allstrainlist'] = string.join(fd.allstrainlist, ' ')
+ for key in hddn.keys():
+ mainForm.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ if fd.enablevariance and not varianceDataPage:
+ #pre dataediting page, need to submit variance
+ mainForm.append(titleTop, title1,title1Body,title2,title2Body,title3,title3Body,title4,title4Body,title5,title5Body)
+ else:
+ mainForm.append(titleTop, title1,title1Body,title2,title2Body,title3,title3Body,title4,title4Body,title5,title5Body)
+ TD_LR.append(HT.Paragraph(mainForm))
+ self.dict['body'] = str(TD_LR)
+
+ ##########################################
+ ## Function to display header
+ ##########################################
+ def dispHeader(self, fd, thisTrait):
+ headSpan = HT.Div(style="font-size:14px;")
+
+ #If trait, use trait name; otherwise, use identification value
+ if thisTrait:
+ if thisTrait.cellid:
+ headSpan.append(HT.Strong('Trait Data and Analysis&nbsp;', style='font-size:16px;'),' for Probe ID ', thisTrait.cellid)
+ else:
+ headSpan.append(HT.Strong('Trait Data and Analysis&nbsp;', style='font-size:16px;'),' for Record ID ', thisTrait.name)
+ else:
+ if fd.identification:
+ headSpan.append(HT.Strong('Trait ID ', style='font-size:16px;'),fd.identification)
+ else:
+ headSpan.append(HT.Strong('Un-named Trait', style='font-size:16px;'))
+
+ return headSpan
+
+ ##########################################
+ ## Function to display trait infos
+ ##########################################
+ def dispTraitInformation(self, fd, title1Body, hddn, thisTrait):
+
+ _Species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+
+ tbl = HT.TableLite(cellpadding=2, Class="collap", style="margin-left:20px;", width="840", valign="top", id="target1")
+
+ reset=HT.Input(type='Reset',name='',value=' Reset ',Class="button")
+
+ #XZ, August 02, 2011: The display of icons is decided by the trait type (if trait exists), along with user log-in status. Note that the new submitted trait might not be trait object.
+ addSelectionButton = ""
+ verifyButton = ""
+ rnaseqButton = ""
+ geneWikiButton = ""
+ probeButton = ""
+ similarButton = ""
+ snpBrowserButton = ""
+ updateButton = ""
+
+ addSelectionText = ""
+ verifyText = ""
+ rnaseqText = ""
+ geneWikiText = ""
+ probeText = ""
+ similarText = ""
+ snpBrowserText = ""
+ updateText = ""
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+
+ if thisTrait==None or thisTrait.db.type=='Temp':
+ updateButton = HT.Href(url="#redirect", onClick="dataEditingFunc(document.getElementsByName('dataInput')[0],'addPublish');")
+ updateButton_img = HT.Image("/images/edit_icon.jpg", name="addnew", alt="Add To Publish", title="Add To Publish", style="border:none;")
+ updateButton.append(updateButton_img)
+ updateText = "Edit"
+ elif thisTrait.db.type != 'Temp':
+ if thisTrait.db.type == 'Publish' and thisTrait.confidential: #XZ: confidential phenotype trait
+ if webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ updateButton = HT.Href(url="#redirect", onClick="dataEditingFunc(document.getElementsByName('dataInput')[0],'updateRecord');")
+ updateButton_img = HT.Image("/images/edit_icon.jpg", name="update", alt="Edit", title="Edit", style="border:none;")
+ updateButton.append(updateButton_img)
+ updateText = "Edit"
+ else:
+ updateButton = HT.Href(url="#redirect", onClick="dataEditingFunc(document.getElementsByName('dataInput')[0],'updateRecord');")
+ updateButton_img = HT.Image("/images/edit_icon.jpg", name="update", alt="Edit", title="Edit", style="border:none;")
+ updateButton.append(updateButton_img)
+ updateText = "Edit"
+ else:
+ pass
+
+ self.cursor.execute('SELECT Name FROM InbredSet WHERE Name="%s"' % fd.RISet)
+ if thisTrait:
+ addSelectionButton = HT.Href(url="#redirect", onClick="addRmvSelection('%s', document.getElementsByName('%s')[0], 'addToSelection');" % (fd.RISet, 'dataInput'))
+ addSelectionButton_img = HT.Image("/images/add_icon.jpg", name="addselect", alt="Add To Collection", title="Add To Collection", style="border:none;")
+ addSelectionButton.append(addSelectionButton_img)
+ addSelectionText = "Add"
+ elif self.cursor.fetchall():
+ addSelectionButton = HT.Href(url="#redirect", onClick="dataEditingFunc(document.getElementsByName('%s')[0], 'addRecord');" % ('dataInput'))
+ addSelectionButton_img = HT.Image("/images/add_icon.jpg", name="", alt="Add To Collection", title="Add To Collection", style="border:none;")
+ addSelectionButton.append(addSelectionButton_img)
+ addSelectionText = "Add"
+ else:
+ pass
+
+
+ # Microarray database information to display
+ if thisTrait and thisTrait.db and thisTrait.db.type == 'ProbeSet': #before, this line was only reached if thisTrait != 0, but now we need to check
+ try:
+ hddn['GeneId'] = int(string.strip(thisTrait.geneid))
+ except:
+ pass
+
+ Info2Disp = HT.Paragraph()
+
+ #XZ: Gene Symbol
+ if thisTrait.symbol:
+ #XZ: Show SNP Browser only for mouse
+ if _Species == 'mouse':
+ self.cursor.execute("select geneSymbol from GeneList where geneSymbol = %s", thisTrait.symbol)
+ geneName = self.cursor.fetchone()
+ if geneName:
+ snpurl = os.path.join(webqtlConfig.CGIDIR, "main.py?FormID=SnpBrowserResultPage&submitStatus=1&diffAlleles=True&customStrain=True") + "&geneName=%s" % geneName[0]
+ else:
+ if thisTrait.chr and thisTrait.mb:
+ snpurl = os.path.join(webqtlConfig.CGIDIR, "main.py?FormID=SnpBrowserResultPage&submitStatus=1&diffAlleles=True&customStrain=True") + \
+ "&chr=%s&start=%2.6f&end=%2.6f" % (thisTrait.chr, thisTrait.mb-0.002, thisTrait.mb+0.002)
+ else:
+ snpurl = ""
+
+ if snpurl:
+ snpBrowserButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % snpurl)
+ snpBrowserButton_img = HT.Image("/images/snp_icon.jpg", name="addselect", alt=" View SNPs and Indels ", title=" View SNPs and Indels ", style="border:none;")
+ snpBrowserButton.append(snpBrowserButton_img)
+ snpBrowserText = "SNPs"
+
+ #XZ: Show GeneWiki for all species
+ geneWikiButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % (os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE) + "?FormID=geneWiki&symbol=%s" % thisTrait.symbol))
+ geneWikiButton_img = HT.Image("/images/genewiki_icon.jpg", name="addselect", alt=" Write or review comments about this gene ", title=" Write or review comments about this gene ", style="border:none;")
+ geneWikiButton.append(geneWikiButton_img)
+ geneWikiText = 'GeneWiki'
+
+ #XZ: display similar traits in other selected datasets
+ if thisTrait and thisTrait.db and thisTrait.db.type=="ProbeSet" and thisTrait.symbol:
+ if _Species in ("mouse", "rat", "human"):
+ similarUrl = "%s?cmd=sch&gene=%s&alias=1&species=%s" % (os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), thisTrait.symbol, _Species)
+ similarButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % similarUrl)
+ similarButton_img = HT.Image("/images/find_icon.jpg", name="addselect", alt=" Find similar expression data ", title=" Find similar expression data ", style="border:none;")
+ similarButton.append(similarButton_img)
+ similarText = "Find"
+ else:
+ pass
+ tbl.append(HT.TR(
+ HT.TD('Gene Symbol: ', Class="fwb fs13", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span('%s' % thisTrait.symbol, valign="top", Class="fs13 fsI"), valign="top", width=740)
+ ))
+ else:
+ tbl.append(HT.TR(
+ HT.TD('Gene Symbol: ', Class="fwb fs13", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span('Not available', Class="fs13 fsI"), valign="top")
+ ))
+
+ #XZ: Gene Alias
+ if thisTrait.alias:
+ alias = string.replace(thisTrait.alias, ";", " ")
+ alias = string.join(string.split(alias), ", ")
+ tbl.append(HT.TR(
+ HT.TD('Aliases: ', Class="fwb fs13", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(alias, Class="fs13 fsI"), valign="top")
+ ))
+
+ #XZ: Description
+ if thisTrait.description:
+ tSpan = HT.Span(thisTrait.description, Class="fs13")
+ if thisTrait.probe_target_description:
+ tSpan.append('; ', thisTrait.probe_target_description)
+ else:
+ tSpan = HT.Span('Not available', Class="fs13")
+ tbl.append(HT.TR(
+ HT.TD('Description: ', Class="fwb fs13", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(tSpan, valign="top")
+ ))
+
+ #XZ: Location
+
+ #XZ: deal with Chr and Mb
+ if thisTrait.chr and thisTrait.mb:
+ tSpan = HT.Span('Chr %s @ %s Mb' % (thisTrait.chr,thisTrait.mb),Class="fs13")
+ elif (thisTrait.chr):
+ tSpan = HT.Span('Chr %s @ Unknown position' % (thisTrait.chr), Class="fs13")
+ else:
+ tSpan = HT.Span('Not available', Class="fs13")
+
+ #XZ: deal with direction
+ if thisTrait.strand_probe == '+':
+ tSpan.append(' on the plus strand ')
+ elif thisTrait.strand_probe == '-':
+ tSpan.append(' on the minus strand ')
+ else:
+ pass
+
+ tbl.append(HT.TR(
+ HT.TD('Location: ', Class="fwb fs13", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(tSpan, valign="top")
+ ))
+
+ ##display Verify Location button
+ try:
+ blatsequence = thisTrait.blatseq
+ if not blatsequence:
+ #XZ, 06/03/2009: ProbeSet name is not unique among platforms. We should use ProbeSet Id instead.
+ self.cursor.execute("""SELECT Probe.Sequence, Probe.Name
+ FROM Probe, ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetFreeze.Name = '%s' AND
+ ProbeSet.Name = '%s' AND
+ Probe.ProbeSetId = ProbeSet.Id order by Probe.SerialOrder""" % (thisTrait.db.name, thisTrait.name) )
+ seqs = self.cursor.fetchall()
+ if not seqs:
+ raise ValueError
+ else:
+ blatsequence = ''
+ for seqt in seqs:
+ if int(seqt[1][-1]) % 2 == 1:
+ blatsequence += string.strip(seqt[0])
+
+ #--------Hongqiang add this part in order to not only blat ProbeSet, but also blat Probe
+ blatsequence = '%3E'+thisTrait.name+'%0A'+blatsequence+'%0A'
+ #XZ, 06/03/2009: ProbeSet name is not unique among platforms. We should use ProbeSet Id instead.
+ self.cursor.execute("""SELECT Probe.Sequence, Probe.Name
+ FROM Probe, ProbeSet, ProbeSetFreeze, ProbeSetXRef
+ WHERE ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSetFreeze.Name = '%s' AND
+ ProbeSet.Name = '%s' AND
+ Probe.ProbeSetId = ProbeSet.Id order by Probe.SerialOrder""" % (thisTrait.db.name, thisTrait.name) )
+
+ seqs = self.cursor.fetchall()
+ for seqt in seqs:
+ if int(seqt[1][-1]) %2 == 1:
+ blatsequence += '%3EProbe_'+string.strip(seqt[1])+'%0A'+string.strip(seqt[0])+'%0A'
+ #--------
+ #XZ, 07/16/2009: targetsequence is not used, so I comment out this block
+ #targetsequence = thisTrait.targetseq
+ #if targetsequence==None:
+ # targetsequence = ""
+
+ #XZ: Pay attention to the parameter of version (rn, mm, hg). They need to be changed if necessary.
+ if _Species == "rat":
+ UCSC_BLAT_URL = webqtlConfig.UCSC_BLAT % ('rat', 'rn3', blatsequence)
+ UTHSC_BLAT_URL = ""
+ elif _Species == "mouse":
+ UCSC_BLAT_URL = webqtlConfig.UCSC_BLAT % ('mouse', 'mm9', blatsequence)
+ UTHSC_BLAT_URL = webqtlConfig.UTHSC_BLAT % ('mouse', 'mm9', blatsequence)
+ elif _Species == "human":
+ UCSC_BLAT_URL = webqtlConfig.UCSC_BLAT % ('human', 'hg19', blatsequence)
+ UTHSC_BLAT_URL = ""
+ else:
+ UCSC_BLAT_URL = ""
+ UTHSC_BLAT_URL = ""
+
+ if UCSC_BLAT_URL:
+ verifyButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % UCSC_BLAT_URL)
+ verifyButtonImg = HT.Image("/images/verify_icon.jpg", name="addselect", alt=" Check probe locations at UCSC ", title=" Check probe locations at UCSC ", style="border:none;")
+ verifyButton.append(verifyButtonImg)
+ verifyText = 'Verify'
+ if UTHSC_BLAT_URL:
+ rnaseqButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % UTHSC_BLAT_URL)
+ rnaseqButtonImg = HT.Image("/images/rnaseq_icon.jpg", name="addselect", alt=" View probes, SNPs, and RNA-seq at UTHSC ", title=" View probes, SNPs, and RNA-seq at UTHSC ", style="border:none;")
+ rnaseqButton.append(rnaseqButtonImg)
+ rnaseqText = 'RNA-seq'
+ tSpan.append(HT.BR())
+ except:
+ pass
+
+ #Display probe information (if any)
+ if thisTrait.db.name.find('Liver') >= 0 and thisTrait.db.name.find('F2') < 0:
+ pass
+ else:
+ #query database for number of probes associated with trait; if count > 0, set probe tool button and text
+ self.cursor.execute("""SELECT count(*)
+ FROM Probe, ProbeSet
+ WHERE ProbeSet.Name = '%s' AND Probe.ProbeSetId = ProbeSet.Id""" % (thisTrait.name))
+
+ probeResult = self.cursor.fetchone()
+ if probeResult[0] > 0:
+ probeurl = "%s?FormID=showProbeInfo&database=%s&ProbeSetID=%s&CellID=%s&RISet=%s&incparentsf1=ON" \
+ % (os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), thisTrait.db, thisTrait.name, thisTrait.cellid, fd.RISet)
+ probeButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % probeurl)
+ probeButton_img = HT.Image("/images/probe_icon.jpg", name="addselect", alt=" Check sequence of probes ", title=" Check sequence of probes ", style="border:none;")
+ probeButton.append(probeButton_img)
+ probeText = "Probes"
+
+ tSpan = HT.Span(Class="fs13")
+
+ #XZ: deal with blat score and blat specificity.
+ if thisTrait.probe_set_specificity or thisTrait.probe_set_blat_score:
+ if thisTrait.probe_set_specificity:
+ tSpan.append(HT.Href(url="/blatInfo.html", target="_blank", title="Values higher than 2 for the specificity are good", text="BLAT specificity", Class="non_bold"),": %.1f" % float(thisTrait.probe_set_specificity), "&nbsp;"*3)
+ if thisTrait.probe_set_blat_score:
+ tSpan.append("Score: %s" % int(thisTrait.probe_set_blat_score), "&nbsp;"*2)
+
+ onClick="openNewWin('/blatInfo.html')"
+
+ tbl.append(HT.TR(
+ HT.TD('Target Score: ', Class="fwb fs13", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(tSpan, valign="top")
+ ))
+
+ tSpan = HT.Span(Class="fs13")
+ tSpan.append(str(_Species).capitalize(), ", ", fd.RISet)
+
+ tbl.append(HT.TR(
+ HT.TD('Species and Group: ', Class="fwb fs13", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(tSpan, valign="top")
+ ))
+
+ if thisTrait.cellid:
+ self.cursor.execute("""
+ select ProbeFreeze.Name from ProbeFreeze, ProbeSetFreeze
+ where
+ ProbeFreeze.Id = ProbeSetFreeze.ProbeFreezeId AND
+ ProbeSetFreeze.Id = %d""" % thisTrait.db.id)
+ probeDBName = self.cursor.fetchone()[0]
+ tbl.append(HT.TR(
+ HT.TD('Database: ', Class="fs13 fwb", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span('%s' % probeDBName, Class="non_bold"), valign="top")
+ ))
+ else:
+ tbl.append(HT.TR(
+ HT.TD('Database: ', Class="fs13 fwb", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Href(text=thisTrait.db.fullname, url = webqtlConfig.INFOPAGEHREF % thisTrait.db.name,
+ target='_blank', Class="fs13 fwn non_bold"), valign="top")
+ ))
+
+ #XZ: ID links
+ if thisTrait.genbankid or thisTrait.geneid or thisTrait.unigeneid or thisTrait.omim or thisTrait.homologeneid:
+ idStyle = "background:#dddddd;padding:2"
+ tSpan = HT.Span(Class="fs13")
+ if thisTrait.geneid:
+ gurl = HT.Href(text= 'Gene', target='_blank',\
+ url=webqtlConfig.NCBI_LOCUSID % thisTrait.geneid, Class="fs14 fwn", title="Info from NCBI Entrez Gene")
+ tSpan.append(HT.Span(gurl, style=idStyle), "&nbsp;"*2)
+ if thisTrait.omim:
+ gurl = HT.Href(text= 'OMIM', target='_blank', \
+ url= webqtlConfig.OMIM_ID % thisTrait.omim,Class="fs14 fwn", title="Summary from On Mendelian Inheritance in Man")
+ tSpan.append(HT.Span(gurl, style=idStyle), "&nbsp;"*2)
+ if thisTrait.unigeneid:
+ try:
+ gurl = HT.Href(text= 'UniGene',target='_blank',\
+ url= webqtlConfig.UNIGEN_ID % tuple(string.split(thisTrait.unigeneid,'.')[:2]),Class="fs14 fwn", title="UniGene ID")
+ tSpan.append(HT.Span(gurl, style=idStyle), "&nbsp;"*2)
+ except:
+ pass
+ if thisTrait.genbankid:
+ thisTrait.genbankid = '|'.join(thisTrait.genbankid.split('|')[0:10])
+ if thisTrait.genbankid[-1]=='|':
+ thisTrait.genbankid=thisTrait.genbankid[0:-1]
+ gurl = HT.Href(text= 'GenBank', target='_blank', \
+ url= webqtlConfig.GENBANK_ID % thisTrait.genbankid,Class="fs14 fwn", title="Find the original GenBank sequence used to design the probes")
+ tSpan.append(HT.Span(gurl, style=idStyle), "&nbsp;"*2)
+ if thisTrait.homologeneid:
+ hurl = HT.Href(text= 'HomoloGene', target='_blank',\
+ url=webqtlConfig.HOMOLOGENE_ID % thisTrait.homologeneid, Class="fs14 fwn", title="Find similar genes in other species")
+ tSpan.append(HT.Span(hurl, style=idStyle), "&nbsp;"*2)
+
+ tbl.append(
+ HT.TR(HT.TD(colspan=3,height=6)),
+ HT.TR(
+ HT.TD('Resource Links: ', Class="fwb fs13", valign="top", nowrap="on"),
+ HT.TD(width=10, valign="top"),
+ HT.TD(tSpan, valign="top")
+ ))
+
+ #XZ: Resource Links:
+ if thisTrait.symbol:
+ linkStyle = "background:#dddddd;padding:2"
+ tSpan = HT.Span(style="font-family:verdana,serif;font-size:13px")
+
+ #XZ,12/26/2008: Gene symbol may contain single quotation mark.
+ #For example, Affymetrix, mouse430v2, 1440338_at, the symbol is 2'-Pde (geneid 211948)
+ #I debug this by using double quotation marks.
+ if _Species == "rat":
+
+ #XZ, 7/16/2009: The url for SymAtlas (renamed as BioGPS) has changed. We don't need this any more
+ #symatlas_species = "Rattus norvegicus"
+
+ #self.cursor.execute("SELECT kgID, chromosome,txStart,txEnd FROM GeneList_rn33 WHERE geneSymbol = '%s'" % thisTrait.symbol)
+ self.cursor.execute('SELECT kgID, chromosome,txStart,txEnd FROM GeneList_rn33 WHERE geneSymbol = "%s"' % thisTrait.symbol)
+ try:
+ kgId, chr, txst, txen = self.cursor.fetchall()[0]
+ if chr and txst and txen and kgId:
+ txst = int(txst*1000000)
+ txen = int(txen*1000000)
+ tSpan.append(HT.Span(HT.Href(text= 'UCSC',target="mainFrame",\
+ title= 'Info from UCSC Genome Browser', url = webqtlConfig.UCSC_REFSEQ % ('rn3',kgId,chr,txst,txen),Class="fs14 fwn"), style=linkStyle)
+ , "&nbsp;"*2)
+ except:
+ pass
+ if _Species == "mouse":
+
+ #XZ, 7/16/2009: The url for SymAtlas (renamed as BioGPS) has changed. We don't need this any more
+ #symatlas_species = "Mus musculus"
+
+ #self.cursor.execute("SELECT chromosome,txStart,txEnd FROM GeneList WHERE geneSymbol = '%s'" % thisTrait.symbol)
+ self.cursor.execute('SELECT chromosome,txStart,txEnd FROM GeneList WHERE geneSymbol = "%s"' % thisTrait.symbol)
+ try:
+ chr, txst, txen = self.cursor.fetchall()[0]
+ if chr and txst and txen and thisTrait.refseq_transcriptid :
+ txst = int(txst*1000000)
+ txen = int(txen*1000000)
+ tSpan.append(HT.Span(HT.Href(text= 'UCSC',target="mainFrame",\
+ title= 'Info from UCSC Genome Browser', url = webqtlConfig.UCSC_REFSEQ % ('mm9',thisTrait.refseq_transcriptid,chr,txst,txen),
+ Class="fs14 fwn"), style=linkStyle)
+ , "&nbsp;"*2)
+ except:
+ pass
+
+ #XZ, 7/16/2009: The url for SymAtlas (renamed as BioGPS) has changed. We don't need this any more
+ #tSpan.append(HT.Span(HT.Href(text= 'SymAtlas',target="mainFrame",\
+ # url="http://symatlas.gnf.org/SymAtlas/bioentry?querytext=%s&query=14&species=%s&type=Expression" \
+ # % (thisTrait.symbol,symatlas_species),Class="fs14 fwn", \
+ # title="Expression across many tissues and cell types"), style=linkStyle), "&nbsp;"*2)
+ if thisTrait.geneid and (_Species == "mouse" or _Species == "rat" or _Species == "human"):
+ tSpan.append(HT.Span(HT.Href(text= 'BioGPS',target="mainFrame",\
+ url="http://biogps.gnf.org/?org=%s#goto=genereport&id=%s" \
+ % (_Species, thisTrait.geneid),Class="fs14 fwn", \
+ title="Expression across many tissues and cell types"), style=linkStyle), "&nbsp;"*2)
+ tSpan.append(HT.Span(HT.Href(text= 'STRING',target="mainFrame",\
+ url="http://string.embl.de/newstring_cgi/show_link_summary.pl?identifier=%s" \
+ % thisTrait.symbol,Class="fs14 fwn", \
+ title="Protein interactions: known and inferred"), style=linkStyle), "&nbsp;"*2)
+ if thisTrait.geneid:
+ tSpan.append(HT.Span(HT.Href(text= 'PANTHER',target="mainFrame", \
+ url="http://www.pantherdb.org/genes/gene.do?acc=%s" \
+ % thisTrait.geneid,Class="fs14 fwn", \
+ title="Gene and protein data resources from Celera-ABI"), style=linkStyle), "&nbsp;"*2)
+ else:
+ pass
+ #tSpan.append(HT.Span(HT.Href(text= 'BIND',target="mainFrame",\
+ # url="http://bind.ca/?textquery=%s" \
+ # % thisTrait.symbol,Class="fs14 fwn", \
+ # title="Protein interactions"), style=linkStyle), "&nbsp;"*2)
+ if thisTrait.geneid and (_Species == "mouse" or _Species == "rat" or _Species == "human"):
+ tSpan.append(HT.Span(HT.Href(text= 'Gemma',target="mainFrame",\
+ url="http://www.chibi.ubc.ca/Gemma/gene/showGene.html?ncbiid=%s" \
+ % thisTrait.geneid, Class="fs14 fwn", \
+ title="Meta-analysis of gene expression data"), style=linkStyle), "&nbsp;"*2)
+ tSpan.append(HT.Span(HT.Href(text= 'SynDB',target="mainFrame",\
+ url="http://lily.uthsc.edu:8080/20091027_GNInterfaces/20091027_redirectSynDB.jsp?query=%s" \
+ % thisTrait.symbol, Class="fs14 fwn", \
+ title="Brain synapse database"), style=linkStyle), "&nbsp;"*2)
+ if _Species == "mouse":
+ tSpan.append(HT.Span(HT.Href(text= 'ABA',target="mainFrame",\
+ url="http://mouse.brain-map.org/brain/%s.html" \
+ % thisTrait.symbol, Class="fs14 fwn", \
+ title="Allen Brain Atlas"), style=linkStyle), "&nbsp;"*2)
+
+ if thisTrait.geneid:
+ #if _Species == "mouse":
+ # tSpan.append(HT.Span(HT.Href(text= 'ABA',target="mainFrame",\
+ # url="http://www.brain-map.org/search.do?queryText=egeneid=%s" \
+ # % thisTrait.geneid, Class="fs14 fwn", \
+ # title="Allen Brain Atlas"), style=linkStyle), "&nbsp;"*2)
+ if _Species == "human":
+ tSpan.append(HT.Span(HT.Href(text= 'ABA',target="mainFrame",\
+ url="http://humancortex.alleninstitute.org/has/human/imageseries/search/1.html?searchSym=t&searchAlt=t&searchName=t&gene_term=&entrez_term=%s" \
+ % thisTrait.geneid, Class="fs14 fwn", \
+ title="Allen Brain Atlas"), style=linkStyle), "&nbsp;"*2)
+ tbl.append(
+ HT.TR(HT.TD(colspan=3,height=6)),
+ HT.TR(
+ HT.TD(' '),
+ HT.TD(width=10, valign="top"),
+ HT.TD(tSpan, valign="top")))
+
+ menuTable = HT.TableLite(cellpadding=2, Class="collap", width="620", id="target1")
+ menuTable.append(HT.TR(HT.TD(addSelectionButton, align="center"),HT.TD(similarButton, align="center"),HT.TD(verifyButton, align="center"),HT.TD(geneWikiButton, align="center"),HT.TD(snpBrowserButton, align="center"),HT.TD(rnaseqButton, align="center"),HT.TD(probeButton, align="center"),HT.TD(updateButton, align="center"), colspan=3, height=50, style="vertical-align:bottom;"))
+ menuTable.append(HT.TR(HT.TD(addSelectionText, align="center"),HT.TD(similarText, align="center"),HT.TD(verifyText, align="center"),HT.TD(geneWikiText, align="center"),HT.TD(snpBrowserText, align="center"),HT.TD(rnaseqText, align="center"),HT.TD(probeText, align="center"),HT.TD(updateText, align="center"), colspan=3, height=50, style="vertical-align:bottom;"))
+
+
+ #for zhou mi's cliques, need to be removed
+ #if self.database[:6] == 'BXDMic' and self.ProbeSetID in cliqueID:
+ # Info2Disp.append(HT.Strong('Clique Search: '),HT.Href(text='Search',\
+ # url ="http://compbio1.utmem.edu/clique_go/results.php?pid=%s&pval_1=0&pval_2=0.001" \
+ # % self.ProbeSetID,target='_blank',Class="normalsize"),HT.BR())
+
+ #linkTable.append(HT.TR(linkTD))
+ #Info2Disp.append(linkTable)
+ title1Body.append(tbl, HT.BR(), menuTable)
+
+ elif thisTrait and thisTrait.db and thisTrait.db.type =='Publish': #Check if trait is phenotype
+
+ if thisTrait.confidential:
+ tbl.append(HT.TR(
+ HT.TD('Pre-publication Phenotype: ', Class="fs13 fwb", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.pre_publication_description, Class="fs13"), valign="top", width=740)
+ ))
+ if webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
+ tbl.append(HT.TR(
+ HT.TD('Post-publication Phenotype: ', Class="fs13 fwb", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.post_publication_description, Class="fs13"), valign="top", width=740)
+ ))
+ tbl.append(HT.TR(
+ HT.TD('Pre-publication Abbreviation: ', Class="fs13 fwb", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.pre_publication_abbreviation, Class="fs13"), valign="top", width=740)
+ ))
+ tbl.append(HT.TR(
+ HT.TD('Post-publication Abbreviation: ', Class="fs13 fwb", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.post_publication_abbreviation, Class="fs13"), valign="top", width=740)
+ ))
+ tbl.append(HT.TR(
+ HT.TD('Lab code: ', Class="fs13 fwb", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.lab_code, Class="fs13"), valign="top", width=740)
+ ))
+ tbl.append(HT.TR(
+ HT.TD('Owner: ', Class="fs13 fwb", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.owner, Class="fs13"), valign="top", width=740)
+ ))
+ else:
+ tbl.append(HT.TR(
+ HT.TD('Phenotype: ', Class="fs13 fwb", valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.post_publication_description, Class="fs13"), valign="top", width=740)
+ ))
+ tbl.append(HT.TR(
+ HT.TD('Authors: ', Class="fs13 fwb",
+ valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.authors, Class="fs13"),
+ valign="top", width=740)
+ ))
+ tbl.append(HT.TR(
+ HT.TD('Title: ', Class="fs13 fwb",
+ valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(thisTrait.title, Class="fs13"),
+ valign="top", width=740)
+ ))
+ if thisTrait.journal:
+ journal = thisTrait.journal
+ if thisTrait.year:
+ journal = thisTrait.journal + " (%s)" % thisTrait.year
+
+ tbl.append(HT.TR(
+ HT.TD('Journal: ', Class="fs13 fwb",
+ valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(journal, Class="fs13"),
+ valign="top", width=740)
+ ))
+ PubMedLink = ""
+ if thisTrait.pubmed_id:
+ PubMedLink = webqtlConfig.PUBMEDLINK_URL % thisTrait.pubmed_id
+ if PubMedLink:
+ tbl.append(HT.TR(
+ HT.TD('Link: ', Class="fs13 fwb",
+ valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(HT.Href(url=PubMedLink, text="PubMed",target='_blank',Class="fs14 fwn"),
+ style = "background:#cddcff;padding:2"), valign="top", width=740)
+ ))
+
+ menuTable = HT.TableLite(cellpadding=2, Class="collap", width="150", id="target1")
+ menuTable.append(HT.TR(HT.TD(addSelectionButton, align="center"),HT.TD(updateButton, align="center"), colspan=3, height=50, style="vertical-align:bottom;"))
+ menuTable.append(HT.TR(HT.TD(addSelectionText, align="center"),HT.TD(updateText, align="center"), colspan=3, height=50, style="vertical-align:bottom;"))
+
+ title1Body.append(tbl, HT.BR(), menuTable)
+
+ elif thisTrait and thisTrait.db and thisTrait.db.type == 'Geno': #Check if trait is genotype
+
+ GenoInfo = HT.Paragraph()
+ if thisTrait.chr and thisTrait.mb:
+ location = ' Chr %s @ %s Mb' % (thisTrait.chr,thisTrait.mb)
+ else:
+ location = "not available"
+
+ if thisTrait.sequence and len(thisTrait.sequence) > 100:
+ if _Species == "rat":
+ UCSC_BLAT_URL = webqtlConfig.UCSC_BLAT % ('rat', 'rn3', thisTrait.sequence)
+ UTHSC_BLAT_URL = webqtlConfig.UTHSC_BLAT % ('rat', 'rn3', thisTrait.sequence)
+ elif _Species == "mouse":
+ UCSC_BLAT_URL = webqtlConfig.UCSC_BLAT % ('mouse', 'mm9', thisTrait.sequence)
+ UTHSC_BLAT_URL = webqtlConfig.UTHSC_BLAT % ('mouse', 'mm9', thisTrait.sequence)
+ elif _Species == "human":
+ UCSC_BLAT_URL = webqtlConfig.UCSC_BLAT % ('human', 'hg19', blatsequence)
+ UTHSC_BLAT_URL = webqtlConfig.UTHSC_BLAT % ('human', 'hg19', thisTrait.sequence)
+ else:
+ UCSC_BLAT_URL = ""
+ UTHSC_BLAT_URL = ""
+ if UCSC_BLAT_URL:
+ verifyButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % UCSC_BLAT_URL)
+ verifyButtonImg = HT.Image("/images/verify_icon.jpg", name="addselect", alt=" Check probe locations at UCSC ", title=" Check probe locations at UCSC ", style="border:none;")
+ verifyButton.append(verifyButtonImg)
+ verifyText = "Verify"
+ rnaseqButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % UTHSC_BLAT_URL)
+ rnaseqButtonImg = HT.Image("/images/rnaseq_icon.jpg", name="addselect", alt=" View probes, SNPs, and RNA-seq at UTHSC ", title=" View probes, SNPs, and RNA-seq at UTHSC ", style="border:none;")
+ rnaseqButton.append(rnaseqButtonImg)
+ rnaseqText = "RNA-seq"
+
+ tbl.append(HT.TR(
+ HT.TD('Location: ', Class="fs13 fwb",
+ valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Span(location, Class="fs13"), valign="top", width=740)
+ ),
+ HT.TR(
+ HT.TD('SNP Search: ', Class="fs13 fwb",
+ valign="top", nowrap="on", width=90),
+ HT.TD(width=10, valign="top"),
+ HT.TD(HT.Href("http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=snp&cmd=search&term=%s" % thisTrait.name, 'NCBI',Class="fs13"),
+ valign="top", width=740)
+ ))
+
+ menuTable = HT.TableLite(cellpadding=2, Class="collap", width="275", id="target1")
+ menuTable.append(HT.TR(HT.TD(addSelectionButton, align="center"),HT.TD(verifyButton, align="center"),HT.TD(rnaseqButton, align="center"), HT.TD(updateButton, align="center"), colspan=3, height=50, style="vertical-align:bottom;"))
+ menuTable.append(HT.TR(HT.TD(addSelectionText, align="center"),HT.TD(verifyText, align="center"),HT.TD(rnaseqText, align="center"), HT.TD(updateText, align="center"), colspan=3, height=50, style="vertical-align:bottom;"))
+
+ title1Body.append(tbl, HT.BR(), menuTable)
+
+ elif (thisTrait == None or thisTrait.db.type == 'Temp'): #if temporary trait (user-submitted trait or PCA trait)
+
+ TempInfo = HT.Paragraph()
+ if thisTrait != None:
+ if thisTrait.description:
+ tbl.append(HT.TR(HT.TD(HT.Strong('Description: '),' %s ' % thisTrait.description,HT.BR()), colspan=3, height=15))
+ else:
+ tbl.append(HT.TR(HT.TD(HT.Strong('Description: '),'not available',HT.BR(),HT.BR()), colspan=3, height=15))
+
+ if (updateText == "Edit"):
+ menuTable = HT.TableLite(cellpadding=2, Class="collap", width="150", id="target1")
+ else:
+ menuTable = HT.TableLite(cellpadding=2, Class="collap", width="80", id="target1")
+
+ menuTable.append(HT.TR(HT.TD(addSelectionButton, align="right"),HT.TD(updateButton, align="right"), colspan=3, height=50, style="vertical-align:bottom;") )
+ menuTable.append(HT.TR(HT.TD(addSelectionText, align="center"),HT.TD(updateText, align="center"), colspan=3, height=50, style="vertical-align:bottom;"))
+
+ title1Body.append(tbl, HT.BR(), menuTable)
+
+ else:
+ pass
+
+
+ ##########################################
+ ## Function to display analysis tools
+ ##########################################
+ def dispBasicStatistics(self, fd, title2Body, thisTrait):
+
+ #XZ, June 22, 2011: The definition and usage of primary_strains, other_strains, specialStrains, all_strains are not clear and hard to understand. But since they are only used in this function for draw graph purpose, they will not hurt the business logic outside. As of June 21, 2011, this function seems work fine, so no hurry to clean up. These parameters and code in this function should be cleaned along with fd.f1list, fd.parlist, fd.strainlist later.
+ stats_row = HT.TR()
+ stats_cell = HT.TD()
+
+ if fd.genotype.type == "riset":
+ strainlist = fd.f1list + fd.strainlist
+ else:
+ strainlist = fd.f1list + fd.parlist + fd.strainlist
+
+ other_strains = [] #XZ: strain that is not of primary group
+ specialStrains = [] #XZ: This might be replaced by other_strains / ZS: It is just other strains without parent/f1 strains.
+ all_strains = []
+ primary_strains = [] #XZ: strain of primary group, e.g., BXD, LXS
+
+ MDP_menu = HT.Select(name='stats_mdp', Class='stats_mdp')
+
+ for strain in thisTrait.data.keys():
+ strainName = strain.replace("_2nd_", "")
+ if strain not in strainlist:
+ if (thisTrait.data[strainName].val != None):
+ if strain.find('F1') < 0:
+ specialStrains.append(strain)
+ if (thisTrait.data[strainName].val != None) and (strain not in (fd.f1list + fd.parlist)):
+ other_strains.append(strain) #XZ: at current stage, other_strains doesn't include parent strains and F1 strains of primary group
+ else:
+ if (thisTrait.data[strainName].val != None) and (strain not in (fd.f1list + fd.parlist)):
+ primary_strains.append(strain) #XZ: at current stage, the primary_strains is the same as fd.strainlist / ZS: I tried defining primary_strains as fd.strainlist instead, but in some cases it ended up including the parent strains (1436869_at BXD)
+
+ if len(other_strains) > 3:
+ other_strains.sort(key=webqtlUtil.natsort_key)
+ primary_strains.sort(key=webqtlUtil.natsort_key)
+ primary_strains = map(lambda X:"_2nd_"+X, fd.f1list + fd.parlist) + primary_strains #XZ: note that fd.f1list and fd.parlist are added.
+ all_strains = primary_strains + other_strains
+ other_strains = map(lambda X:"_2nd_"+X, fd.f1list + fd.parlist) + other_strains #XZ: note that fd.f1list and fd.parlist are added.
+ MDP_menu.append(('All Cases','0'))
+ MDP_menu.append(('%s Only' % fd.RISet,'1'))
+ MDP_menu.append(('Non-%s Only' % fd.RISet,'2'))
+ stats_row.append("Include: ", MDP_menu, HT.BR(), HT.BR())
+ else:
+ if (len(other_strains) > 0) and (len(primary_strains) + len(other_strains) > 3):
+ MDP_menu.append(('All Cases','0'))
+ MDP_menu.append(('%s Only' % fd.RISet,'1'))
+ MDP_menu.append(('Non-%s Only' % fd.RISet,'2'))
+ stats_row.append("Include: ", MDP_menu, "&nbsp;"*3)
+ all_strains = primary_strains
+ all_strains.sort(key=webqtlUtil.natsort_key)
+ all_strains = map(lambda X:"_2nd_"+X, fd.f1list + fd.parlist) + all_strains
+ primary_strains = map(lambda X:"_2nd_"+X, fd.f1list + fd.parlist) + primary_strains
+ else:
+ all_strains = strainlist
+
+ other_strains.sort(key=webqtlUtil.natsort_key)
+ all_strains = all_strains + other_strains
+ pass
+
+ update_button = HT.Input(type='button',value=' Update Figures ', Class="button update") #This is used to reload the page and update the Basic Statistics figures with user-edited data
+ stats_row.append(update_button, HT.BR(), HT.BR())
+
+ if (len(other_strains)) > 0 and (len(primary_strains) + len(other_strains) > 4):
+ #One set of vals for all, selected strain only, and non-selected only
+ vals1 = []
+ vals2 = []
+ vals3 = []
+
+ #Using all strains/cases for values
+ for i, strainNameOrig in enumerate(all_strains):
+ strainName = strainNameOrig.replace("_2nd_", "")
+
+ try:
+ thisval = thisTrait.data[strainName].val
+ thisvar = thisTrait.data[strainName].var
+ thisValFull = [strainName,thisval,thisvar]
+ except:
+ continue
+
+ vals1.append(thisValFull)
+
+ #Using just the RISet strain
+ for i, strainNameOrig in enumerate(primary_strains):
+ strainName = strainNameOrig.replace("_2nd_", "")
+
+ try:
+ thisval = thisTrait.data[strainName].val
+ thisvar = thisTrait.data[strainName].var
+ thisValFull = [strainName,thisval,thisvar]
+ except:
+ continue
+
+ vals2.append(thisValFull)
+
+ #Using all non-RISet strains only
+ for i, strainNameOrig in enumerate(other_strains):
+ strainName = strainNameOrig.replace("_2nd_", "")
+
+ try:
+ thisval = thisTrait.data[strainName].val
+ thisvar = thisTrait.data[strainName].var
+ thisValFull = [strainName,thisval,thisvar]
+ except:
+ continue
+
+ vals3.append(thisValFull)
+
+ vals_set = [vals1,vals2,vals3]
+
+ else:
+ vals = []
+
+ #Using all strains/cases for values
+ for i, strainNameOrig in enumerate(all_strains):
+ strainName = strainNameOrig.replace("_2nd_", "")
+
+ try:
+ thisval = thisTrait.data[strainName].val
+ thisvar = thisTrait.data[strainName].var
+ thisValFull = [strainName,thisval,thisvar]
+ except:
+ continue
+
+ vals.append(thisValFull)
+
+ vals_set = [vals]
+
+ stats_script = HT.Script(language="Javascript") #script needed for tabs
+
+ for i, vals in enumerate(vals_set):
+ if i == 0 and len(vals) < 4:
+ stats_container = HT.Div(id="stats_tabs", style="padding:10px;", Class="ui-tabs") #Needed for tabs; notice the "stats_script_text" below referring to this element
+ stats_container.append(HT.Div(HT.Italic("Fewer than 4 case data were entered. No statistical analysis has been attempted.")))
+ stats_script_text = """$(function() { $("#stats_tabs").tabs();});"""
+ stats_cell.append(stats_container)
+ break
+ elif (i == 1 and len(primary_strains) < 4):
+ stats_container = HT.Div(id="stats_tabs%s" % i, Class="ui-tabs")
+ stats_container.append(HT.Div(HT.Italic("Fewer than 4 " + fd.RISet + " case data were entered. No statistical analysis has been attempted.")))
+ elif (i == 2 and len(other_strains) < 4):
+ stats_container = HT.Div(id="stats_tabs%s" % i, Class="ui-tabs")
+ stats_container.append(HT.Div(HT.Italic("Fewer than 4 non-" + fd.RISet + " case data were entered. No statistical analysis has been attempted.")))
+ stats_script_text = """$(function() { $("#stats_tabs0").tabs(); $("#stats_tabs1").tabs(); $("#stats_tabs2").tabs();});"""
+ else:
+ stats_container = HT.Div(id="stats_tabs%s" % i, Class="ui-tabs")
+ stats_script_text = """$(function() { $("#stats_tabs0").tabs(); $("#stats_tabs1").tabs(); $("#stats_tabs2").tabs();});"""
+ if len(vals) > 4:
+ stats_tab_list = [HT.Href(text="Basic Table", url="#statstabs-1", Class="stats_tab"),HT.Href(text="Probability Plot", url="#statstabs-5", Class="stats_tab"),
+ HT.Href(text="Bar Graph (by name)", url="#statstabs-3", Class="stats_tab"), HT.Href(text="Bar Graph (by rank)", url="#statstabs-4", Class="stats_tab"),
+ HT.Href(text="Box Plot", url="#statstabs-2", Class="stats_tab")]
+ stats_tabs = HT.List(stats_tab_list)
+ stats_container.append(stats_tabs)
+
+ table_div = HT.Div(id="statstabs-1")
+ table_container = HT.Paragraph()
+
+ statsTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+
+ if thisTrait.db:
+ if thisTrait.cellid:
+ statsTableCell = BasicStatisticsFunctions.basicStatsTable(vals=vals, trait_type=thisTrait.db.type, cellid=thisTrait.cellid)
+ else:
+ statsTableCell = BasicStatisticsFunctions.basicStatsTable(vals=vals, trait_type=thisTrait.db.type)
+ else:
+ statsTableCell = BasicStatisticsFunctions.basicStatsTable(vals=vals)
+
+ statsTable.append(HT.TR(HT.TD(statsTableCell)))
+
+ table_container.append(statsTable)
+ table_div.append(table_container)
+ stats_container.append(table_div)
+
+ normalplot_div = HT.Div(id="statstabs-5")
+ normalplot_container = HT.Paragraph()
+ normalplot = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+
+ try:
+ plotTitle = thisTrait.symbol
+ plotTitle += ": "
+ plotTitle += thisTrait.name
+ except:
+ plotTitle = str(thisTrait.name)
+
+ normalplot_img = BasicStatisticsFunctions.plotNormalProbability(vals=vals, RISet=fd.RISet, title=plotTitle, specialStrains=specialStrains)
+ normalplot.append(HT.TR(HT.TD(normalplot_img)))
+ normalplot.append(HT.TR(HT.TD(HT.BR(),HT.BR(),"This plot evaluates whether data are \
+ normally distributed. Different symbols represent different groups.",HT.BR(),HT.BR(),
+ "More about ", HT.Href(url="http://en.wikipedia.org/wiki/Normal_probability_plot",
+ target="_blank", text="Normal Probability Plots"), " and more about interpreting these plots from the ", HT.Href(url="/glossary.html#normal_probability", target="_blank", text="glossary"))))
+ normalplot_container.append(normalplot)
+ normalplot_div.append(normalplot_container)
+ stats_container.append(normalplot_div)
+
+ boxplot_div = HT.Div(id="statstabs-2")
+ boxplot_container = HT.Paragraph()
+ boxplot = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ boxplot_img, boxplot_link = BasicStatisticsFunctions.plotBoxPlot(vals)
+ boxplot.append(HT.TR(HT.TD(boxplot_img, HT.P(), boxplot_link, align="left")))
+ boxplot_container.append(boxplot)
+ boxplot_div.append(boxplot_container)
+ stats_container.append(boxplot_div)
+
+
+ barName_div = HT.Div(id="statstabs-3")
+ barName_container = HT.Paragraph()
+ barName = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ barName_img = BasicStatisticsFunctions.plotBarGraph(identification=fd.identification, RISet=fd.RISet, vals=vals, type="name")
+ barName.append(HT.TR(HT.TD(barName_img)))
+ barName_container.append(barName)
+ barName_div.append(barName_container)
+ stats_container.append(barName_div)
+
+ barRank_div = HT.Div(id="statstabs-4")
+ barRank_container = HT.Paragraph()
+ barRank = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ barRank_img = BasicStatisticsFunctions.plotBarGraph(identification=fd.identification, RISet=fd.RISet, vals=vals, type="rank")
+ barRank.append(HT.TR(HT.TD(barRank_img)))
+ barRank_container.append(barRank)
+ barRank_div.append(barRank_container)
+ stats_container.append(barRank_div)
+
+ stats_cell.append(stats_container)
+
+ stats_script.append(stats_script_text)
+
+ submitTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%", Class="target2")
+ stats_row.append(stats_cell)
+
+ submitTable.append(stats_row)
+ submitTable.append(stats_script)
+
+ title2Body.append(submitTable)
+
+
+ def dispCorrelationTools(self, fd, title3Body, thisTrait):
+
+ _Species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+
+ RISetgp = fd.RISet
+ if RISetgp[:3] == 'BXD':
+ RISetgp = 'BXD'
+
+ if RISetgp:
+ sample_correlation = HT.Input(type='button',name='sample_corr', value=' Compute ', Class="button sample_corr")
+ lit_correlation = HT.Input(type='button',name='lit_corr', value=' Compute ', Class="button lit_corr")
+ tissue_correlation = HT.Input(type='button',name='tiss_corr', value=' Compute ', Class="button tiss_corr")
+ methodText = HT.Span("Calculate:", Class="ffl fwb fs12")
+
+ databaseText = HT.Span("Database:", Class="ffl fwb fs12")
+ databaseMenu1 = HT.Select(name='database1')
+ databaseMenu2 = HT.Select(name='database2')
+ databaseMenu3 = HT.Select(name='database3')
+
+ nmenu = 0
+ self.cursor.execute('SELECT PublishFreeze.FullName,PublishFreeze.Name FROM \
+ PublishFreeze,InbredSet WHERE PublishFreeze.InbredSetId = InbredSet.Id \
+ and InbredSet.Name = "%s" and PublishFreeze.public > %d' % \
+ (RISetgp,webqtlConfig.PUBLICTHRESH))
+ for item in self.cursor.fetchall():
+ databaseMenu1.append(item)
+ databaseMenu2.append(item)
+ databaseMenu3.append(item)
+ nmenu += 1
+ self.cursor.execute('SELECT GenoFreeze.FullName,GenoFreeze.Name FROM GenoFreeze,\
+ InbredSet WHERE GenoFreeze.InbredSetId = InbredSet.Id and InbredSet.Name = \
+ "%s" and GenoFreeze.public > %d' % (RISetgp,webqtlConfig.PUBLICTHRESH))
+ for item in self.cursor.fetchall():
+ databaseMenu1.append(item)
+ databaseMenu2.append(item)
+ databaseMenu3.append(item)
+ nmenu += 1
+ #03/09/2009: Xiaodong changed the SQL query to order by Name as requested by Rob.
+ self.cursor.execute('SELECT Id, Name FROM Tissue order by Name')
+ for item in self.cursor.fetchall():
+ TId, TName = item
+ databaseMenuSub = HT.Optgroup(label = '%s ------' % TName)
+ self.cursor.execute('SELECT ProbeSetFreeze.FullName,ProbeSetFreeze.Name FROM ProbeSetFreeze, ProbeFreeze, \
+ InbredSet WHERE ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeFreeze.TissueId = %d and \
+ ProbeSetFreeze.public > %d and ProbeFreeze.InbredSetId = InbredSet.Id and InbredSet.Name like "%s%%" \
+ order by ProbeSetFreeze.CreateTime desc, ProbeSetFreeze.AvgId ' % (TId,webqtlConfig.PUBLICTHRESH, RISetgp))
+ for item2 in self.cursor.fetchall():
+ databaseMenuSub.append(item2)
+ nmenu += 1
+ databaseMenu1.append(databaseMenuSub)
+ databaseMenu2.append(databaseMenuSub)
+ databaseMenu3.append(databaseMenuSub)
+ if nmenu:
+ if thisTrait and thisTrait.db != None:
+ databaseMenu1.selected.append(thisTrait.db.fullname)
+ databaseMenu2.selected.append(thisTrait.db.fullname)
+ databaseMenu3.selected.append(thisTrait.db.fullname)
+
+ criteriaText = HT.Span("Return:", Class="ffl fwb fs12")
+
+ criteriaMenu1 = HT.Select(name='criteria1', selected='500', onMouseOver="if (NS4 || IE4) activateEl('criterias', event);")
+ criteriaMenu1.append(('top 100','100'))
+ criteriaMenu1.append(('top 200','200'))
+ criteriaMenu1.append(('top 500','500'))
+ criteriaMenu1.append(('top 1000','1000'))
+ criteriaMenu1.append(('top 2000','2000'))
+ criteriaMenu1.append(('top 5000','5000'))
+ criteriaMenu1.append(('top 10000','10000'))
+ criteriaMenu1.append(('top 15000','15000'))
+ criteriaMenu1.append(('top 20000','20000'))
+
+ criteriaMenu2 = HT.Select(name='criteria2', selected='500', onMouseOver="if (NS4 || IE4) activateEl('criterias', event);")
+ criteriaMenu2.append(('top 100','100'))
+ criteriaMenu2.append(('top 200','200'))
+ criteriaMenu2.append(('top 500','500'))
+ criteriaMenu2.append(('top 1000','1000'))
+ criteriaMenu2.append(('top 2000','2000'))
+ criteriaMenu2.append(('top 5000','5000'))
+ criteriaMenu2.append(('top 10000','10000'))
+ criteriaMenu2.append(('top 15000','15000'))
+ criteriaMenu2.append(('top 20000','20000'))
+
+ criteriaMenu3 = HT.Select(name='criteria3', selected='500', onMouseOver="if (NS4 || IE4) activateEl('criterias', event);")
+ criteriaMenu3.append(('top 100','100'))
+ criteriaMenu3.append(('top 200','200'))
+ criteriaMenu3.append(('top 500','500'))
+ criteriaMenu3.append(('top 1000','1000'))
+ criteriaMenu3.append(('top 2000','2000'))
+ criteriaMenu3.append(('top 5000','5000'))
+ criteriaMenu3.append(('top 10000','10000'))
+ criteriaMenu3.append(('top 15000','15000'))
+ criteriaMenu3.append(('top 20000','20000'))
+
+
+ self.MDPRow1 = HT.TR(Class='mdp1')
+ self.MDPRow2 = HT.TR(Class='mdp2')
+ self.MDPRow3 = HT.TR(Class='mdp3')
+
+ correlationMenus1 = HT.TableLite(
+ HT.TR(HT.TD(databaseText), HT.TD(databaseMenu1, colspan="3")),
+ HT.TR(HT.TD(criteriaText), HT.TD(criteriaMenu1)),
+ self.MDPRow1, cellspacing=0, width="619px", cellpadding=2)
+ correlationMenus1.append(HT.Input(name='orderBy', value='2', type='hidden')) # to replace the orderBy menu
+ correlationMenus2 = HT.TableLite(
+ HT.TR(HT.TD(databaseText), HT.TD(databaseMenu2, colspan="3")),
+ HT.TR(HT.TD(criteriaText), HT.TD(criteriaMenu2)),
+ self.MDPRow2, cellspacing=0, width="619px", cellpadding=2)
+ correlationMenus2.append(HT.Input(name='orderBy', value='2', type='hidden'))
+ correlationMenus3 = HT.TableLite(
+ HT.TR(HT.TD(databaseText), HT.TD(databaseMenu3, colspan="3")),
+ HT.TR(HT.TD(criteriaText), HT.TD(criteriaMenu3)),
+ self.MDPRow3, cellspacing=0, width="619px", cellpadding=2)
+ correlationMenus3.append(HT.Input(name='orderBy', value='2', type='hidden'))
+
+ else:
+ correlationMenus = ""
+
+
+ corr_row = HT.TR()
+ corr_container = HT.Div(id="corr_tabs", Class="ui-tabs")
+
+ if (thisTrait.db != None and thisTrait.db.type =='ProbeSet'):
+ corr_tab_list = [HT.Href(text='Sample r', url="#corrtabs-1"), HT.Href(text='Literature r', url="#corrtabs-2"), HT.Href(text='Tissue r', url="#corrtabs-3")]
+ else:
+ corr_tab_list = [HT.Href(text='Sample r', url="#corrtabs-1")]
+
+ corr_tabs = HT.List(corr_tab_list)
+ corr_container.append(corr_tabs)
+
+ if correlationMenus1 or correlationMenus2 or correlationMenus3:
+ sample_div = HT.Div(id="corrtabs-1")
+ sample_container = HT.Span()
+
+ sample_type = HT.Input(type="radio", name="sample_method", value="1", checked="checked")
+ sample_type2 = HT.Input(type="radio", name="sample_method", value="2")
+
+ sampleTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ sampleTD = HT.TD(correlationMenus1, HT.BR(),
+ "Pearson", sample_type, "&nbsp;"*3, "Spearman Rank", sample_type2, HT.BR(), HT.BR(),
+ sample_correlation, HT.BR(), HT.BR())
+
+ sampleTD.append(HT.Span("The ",HT.Href(url="/correlationAnnotation.html#sample_r", target="_blank", text="Sample Correlation")," is computed between trait data and",
+ " any ",HT.BR()," other traits in the sample database selected above. Use ",
+ HT.Href(url="/glossary.html#Correlations", target="_blank", text="Spearman Rank"),
+ HT.BR(),"when the sample size is small (<20) or when there are influential \
+ outliers.", HT.BR(),Class="fs12"))
+
+ sampleTable.append(sampleTD)
+
+ sample_container.append(sampleTable)
+ sample_div.append(sample_container)
+ corr_container.append(sample_div)
+
+ literature_div = HT.Div(id="corrtabs-2")
+ literature_container = HT.Span()
+
+ literatureTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ literatureTD = HT.TD(correlationMenus2,HT.BR(),lit_correlation, HT.BR(), HT.BR())
+ literatureTD.append(HT.Span("The ", HT.Href(url="/correlationAnnotation.html", target="_blank",text="Literature Correlation"), " (Lit r) between this gene and all other genes is computed",HT.BR(),
+ "using the ", HT.Href(url="https://grits.eecs.utk.edu/sgo/sgo.html", target="_blank", text="Semantic Gene Organizer"),
+ " and human, rat, and mouse data from PubMed. ", HT.BR(),"Values are ranked by Lit r, \
+ but Sample r and Tissue r are also displayed.", HT.BR(), HT.BR(),
+ HT.Href(url="/glossary.html#Literature", target="_blank", text="More on using Lit r"), Class="fs12"))
+ literatureTable.append(literatureTD)
+
+ literature_container.append(literatureTable)
+ literature_div.append(literature_container)
+
+ if thisTrait.db != None:
+ if (thisTrait.db.type =='ProbeSet'):
+ corr_container.append(literature_div)
+
+ tissue_div = HT.Div(id="corrtabs-3")
+ tissue_container = HT.Span()
+
+ tissue_type = HT.Input(type="radio", name="tissue_method", value="4", checked="checked")
+ tissue_type2 = HT.Input(type="radio", name="tissue_method", value="5")
+
+ tissueTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ tissueTD = HT.TD(correlationMenus3,HT.BR(),
+ "Pearson", tissue_type, "&nbsp;"*3, "Spearman Rank", tissue_type2, HT.BR(), HT.BR(),
+ tissue_correlation, HT.BR(), HT.BR())
+ tissueTD.append(HT.Span("The ", HT.Href(url="/webqtl/main.py?FormID=tissueCorrelation", target="_blank", text="Tissue Correlation"),
+ " (Tissue r) estimates the similarity of expression of two genes",HT.BR()," or \
+ transcripts across different cells, tissues, or organs (",HT.Href(url="/correlationAnnotation.html#tissue_r", target="_blank", text="glossary"),"). \
+ Tissue correlations",HT.BR()," are generated by analyzing expression in multiple samples usually taken from \
+ single cases.",HT.BR(),HT.Bold("Pearson")," and ",HT.Bold("Spearman Rank")," correlations have been computed for all pairs \
+ of genes",HT.BR()," using data from mouse samples.",
+ HT.BR(), Class="fs12"))
+ tissueTable.append(tissueTD)
+
+ tissue_container.append(tissueTable)
+ tissue_div.append(tissue_container)
+ if thisTrait.db != None:
+ if (thisTrait.db.type =='ProbeSet'):
+ corr_container.append(tissue_div)
+
+ corr_row.append(HT.TD(corr_container))
+
+ corr_script = HT.Script(language="Javascript")
+ corr_script_text = """$(function() { $("#corr_tabs").tabs(); });"""
+ corr_script.append(corr_script_text)
+
+ submitTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%", Class="target4")
+ submitTable.append(corr_row)
+ submitTable.append(corr_script)
+
+ title3Body.append(submitTable)
+
+
+ def dispMappingTools(self, fd, title4Body, thisTrait):
+
+ _Species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+
+ RISetgp = fd.RISet
+ if RISetgp[:3] == 'BXD':
+ RISetgp = 'BXD'
+
+ #check boxes - one for regular interval mapping, the other for composite
+ permCheck1= HT.Input(type='checkbox', Class='checkbox', name='permCheck1',checked="on")
+ bootCheck1= HT.Input(type='checkbox', Class='checkbox', name='bootCheck1',checked=0)
+ permCheck2= HT.Input(type='checkbox', Class='checkbox', name='permCheck2',checked="on")
+ bootCheck2= HT.Input(type='checkbox', Class='checkbox', name='bootCheck2',checked=0)
+ optionbox1 = HT.Input(type='checkbox', Class='checkbox', name='parentsf14regression1',checked=0)
+ optionbox2 = HT.Input(type='checkbox', Class='checkbox', name='parentsf14regression2',checked=0)
+ optionbox3 = HT.Input(type='checkbox', Class='checkbox', name='parentsf14regression3',checked=0)
+ applyVariance1 = HT.Input(name='applyVarianceSE1',type='checkbox', Class='checkbox')
+ applyVariance2 = HT.Input(name='applyVarianceSE2',type='checkbox', Class='checkbox')
+
+ IntervalMappingButton=HT.Input(type='button' ,name='interval',value=' Compute ', Class="button")
+ CompositeMappingButton=HT.Input(type='button' ,name='composite',value=' Compute ', Class="button")
+ MarkerRegressionButton=HT.Input(type='button',name='marker', value=' Compute ', Class="button")
+
+ chrText = HT.Span("Chromosome:", Class="ffl fwb fs12")
+
+ # updated by NL 5-28-2010
+ # Interval Mapping
+ chrMenu = HT.Select(name='chromosomes1')
+ chrMenu.append(tuple(["All",-1]))
+ for i in range(len(fd.genotype)):
+ if len(fd.genotype[i]) > 1:
+ chrMenu.append(tuple([fd.genotype[i].name,i]))
+
+ #Menu for Composite Interval Mapping
+ chrMenu2 = HT.Select(name='chromosomes2')
+ chrMenu2.append(tuple(["All",-1]))
+ for i in range(len(fd.genotype)):
+ if len(fd.genotype[i]) > 1:
+ chrMenu2.append(tuple([fd.genotype[i].name,i]))
+
+ if fd.genotype.Mbmap:
+ scaleText = HT.Span("Mapping Scale:", Class="ffl fwb fs12")
+ scaleMenu1 = HT.Select(name='scale1', onChange="checkUncheck(window.document.dataInput.scale1.value, window.document.dataInput.permCheck1, window.document.dataInput.bootCheck1)")
+ scaleMenu1.append(("Megabase",'physic'))
+ scaleMenu1.append(("Centimorgan",'morgan'))
+ scaleMenu2 = HT.Select(name='scale2', onChange="checkUncheck(window.document.dataInput.scale2.value, window.document.dataInput.permCheck2, window.document.dataInput.bootCheck2)")
+ scaleMenu2.append(("Megabase",'physic'))
+ scaleMenu2.append(("Centimorgan",'morgan'))
+
+ controlText = HT.Span("Control Locus:", Class="ffl fwb fs12")
+ controlMenu = HT.Input(type="text", name="controlLocus", Class="controlLocus")
+
+ if fd.genotype.Mbmap:
+ intMappingMenu = HT.TableLite(
+ HT.TR(HT.TD(chrText), HT.TD(chrMenu, colspan="3")),
+ HT.TR(HT.TD(scaleText), HT.TD(scaleMenu1)),
+ cellspacing=0, width="263px", cellpadding=2)
+ compMappingMenu = HT.TableLite(
+ HT.TR(HT.TD(chrText), HT.TD(chrMenu2, colspan="3")),
+ HT.TR(HT.TD(scaleText), HT.TD(scaleMenu2)),
+ HT.TR(HT.TD(controlText), HT.TD(controlMenu)),
+ cellspacing=0, width="325px", cellpadding=2)
+ else:
+ intMappingMenu = HT.TableLite(
+ HT.TR(HT.TD(chrText), HT.TD(chrMenu, colspan="3")),
+ cellspacing=0, width="263px", cellpadding=2)
+ compMappingMenu = HT.TableLite(
+ HT.TR(HT.TD(chrText), HT.TD(chrMenu2, colspan="3")),
+ HT.TR(HT.TD(controlText), HT.TD(controlMenu)),
+ cellspacing=0, width="325px", cellpadding=2)
+
+ directPlotButton = ""
+ directPlotButton = HT.Input(type='button',name='', value=' Compute ',\
+ onClick="dataEditingFunc(this.form,'directPlot');",Class="button")
+ directPlotSortText = HT.Span(HT.Bold("Sort by: "), Class="ffl fwb fs12")
+ directPlotSortMenu = HT.Select(name='graphSort')
+ directPlotSortMenu.append(('LRS Full',0))
+ directPlotSortMenu.append(('LRS Interact',1))
+ directPlotPermuText = HT.Span("Permutation Test (n=500)", Class="ffl fs12")
+ directPlotPermu = HT.Input(type='checkbox', Class='checkbox',name='directPermuCheckbox', checked="on")
+ pairScanReturnText = HT.Span(HT.Bold("Return: "), Class="ffl fwb fs12")
+ pairScanReturnMenu = HT.Select(name='pairScanReturn')
+ pairScanReturnMenu.append(('top 50','50'))
+ pairScanReturnMenu.append(('top 100','100'))
+ pairScanReturnMenu.append(('top 200','200'))
+ pairScanReturnMenu.append(('top 500','500'))
+
+ pairScanMenus = HT.TableLite(
+ HT.TR(HT.TD(directPlotSortText), HT.TD(directPlotSortMenu)),
+ HT.TR(HT.TD(pairScanReturnText), HT.TD(pairScanReturnMenu)),
+ cellspacing=0, width="232px", cellpadding=2)
+
+ markerSuggestiveText = HT.Span(HT.Bold("Display LRS greater than:"), Class="ffl fwb fs12")
+ markerSuggestive = HT.Input(name='suggestive', size=5, maxlength=8)
+ displayAllText = HT.Span(" Display all LRS ", Class="ffl fs12")
+ displayAll = HT.Input(name='displayAllLRS', type="checkbox", Class='checkbox')
+ useParentsText = HT.Span(" Use Parents ", Class="ffl fs12")
+ useParents = optionbox2
+ applyVarianceText = HT.Span(" Use Weighted ", Class="ffl fs12")
+
+ markerMenu = HT.TableLite(
+ HT.TR(HT.TD(markerSuggestiveText), HT.TD(markerSuggestive)),
+ HT.TR(HT.TD(displayAll,displayAllText)),
+ HT.TR(HT.TD(useParents,useParentsText)),
+ HT.TR(HT.TD(applyVariance2,applyVarianceText)),
+ cellspacing=0, width="263px", cellpadding=2)
+
+
+ mapping_row = HT.TR()
+ mapping_container = HT.Div(id="mapping_tabs", Class="ui-tabs")
+
+ mapping_tab_list = [HT.Href(text="Interval", url="#mappingtabs-1"), HT.Href(text="Marker Regression", url="#mappingtabs-2"), HT.Href(text="Composite", url="#mappingtabs-3"), HT.Href(text="Pair-Scan", url="#mappingtabs-4")]
+ mapping_tabs = HT.List(mapping_tab_list)
+ mapping_container.append(mapping_tabs)
+
+ interval_div = HT.Div(id="mappingtabs-1")
+ interval_container = HT.Span()
+
+ intervalTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ intTD = HT.TD(valign="top",NOWRAP='ON', Class="fs12 fwn")
+ intTD.append(intMappingMenu,HT.BR())
+
+ intTD.append(permCheck1,'Permutation Test (n=2000)',HT.BR(),
+ bootCheck1,'Bootstrap Test (n=2000)', HT.BR(), optionbox1, 'Use Parents', HT.BR(),
+ applyVariance1,'Use Weighted', HT.BR(), HT.BR(),IntervalMappingButton, HT.BR(), HT.BR())
+ intervalTable.append(HT.TR(intTD), HT.TR(HT.TD(HT.Span(HT.Href(url='/glossary.html#intmap', target='_blank', text='Interval Mapping'),
+ ' computes linkage maps for the entire genome or single',HT.BR(),' chromosomes.',
+ ' The ',HT.Href(url='/glossary.html#permutation', target='_blank', text='Permutation Test'),' estimates suggestive and significant ',HT.BR(),' linkage scores. \
+ The ',HT.Href(url='/glossary.html#bootstrap', target='_blank', text='Bootstrap Test'), ' estimates the precision of the QTL location.'
+ ,Class="fs12"), HT.BR(), valign="top")))
+
+ interval_container.append(intervalTable)
+ interval_div.append(interval_container)
+ mapping_container.append(interval_div)
+
+ # Marker Regression
+
+ marker_div = HT.Div(id="mappingtabs-2")
+ marker_container = HT.Span()
+
+ markerTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ markerTD = HT.TD(valign="top",NOWRAP='ON', Class="fs12 fwn")
+ markerTD.append(markerMenu,HT.BR())
+
+ markerTD.append(MarkerRegressionButton,HT.BR(),HT.BR())
+
+ markerTable.append(HT.TR(markerTD),HT.TR(HT.TD(HT.Span(HT.Href(url='/glossary.html#',target='_blank',text='Marker regression'),
+ ' computes and displays LRS values for individual markers.',HT.BR(),
+ 'This function also lists additive effects (phenotype units per allele) and', HT.BR(),
+ 'dominance deviations for some datasets.', HT.BR(),Class="fs12"), HT.BR(), valign="top")))
+
+ marker_container.append(markerTable)
+ marker_div.append(marker_container)
+ mapping_container.append(marker_div)
+
+ # Composite interval mapping
+ composite_div = HT.Div(id="mappingtabs-3")
+ composite_container = HT.Span()
+
+ compositeTable = HT.TableLite(cellspacing=0, cellpadding=3, width="100%")
+ compTD = HT.TD(valign="top",NOWRAP='ON', Class="fs12 fwn")
+ compTD.append(compMappingMenu,HT.BR())
+
+ compTD.append(permCheck2, 'Permutation Test (n=2000)',HT.BR(),
+ bootCheck2,'Bootstrap Test (n=2000)', HT.BR(),
+ optionbox3, 'Use Parents', HT.BR(), HT.BR(), CompositeMappingButton, HT.BR(), HT.BR())
+ compositeTable.append(HT.TR(compTD), HT.TR(HT.TD(HT.Span(HT.Href(url='/glossary.html#Composite',target='_blank',text='Composite Interval Mapping'),
+ " allows you to control for a single marker as",HT.BR()," a cofactor. ",
+ "To find a control marker, run the ",HT.Bold("Marker Regression")," function."),
+ HT.BR(), valign="top")))
+
+ composite_container.append(compositeTable)
+ composite_div.append(composite_container)
+ mapping_container.append(composite_div)
+
+ # Pair Scan
+
+ pairscan_div = HT.Div(id="mappingtabs-4")
+ pairscan_container = HT.Span()
+
+ pairScanTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ pairScanTD = HT.TD(NOWRAP='ON', Class="fs12 fwn")
+ pairScanTD.append(pairScanMenus,HT.BR())
+ pairScanTD.append(directPlotPermu, directPlotPermuText, HT.BR(), HT.BR(),
+ directPlotButton,HT.BR(),HT.BR())
+ pairScanTable.append(HT.TR(pairScanTD), HT.TR(HT.TD(HT.Span(HT.Href(url='/glossary.html#Pair_Scan', target="_blank", text='Pair-Scan'),
+ ' searches for pairs of chromosomal regions that are',HT.BR(),
+ 'involved in two-locus epistatic interactions.'), HT.BR(), valign="top")))
+
+ pairscan_container.append(pairScanTable)
+ pairscan_div.append(pairscan_container)
+ mapping_container.append(pairscan_div)
+
+ mapping_row.append(HT.TD(mapping_container))
+
+ # Treat Interval Mapping and Marker Regression and Pair Scan as a group for displaying
+ #disable Interval Mapping and Marker Regression and Pair Scan for human and the dataset doesn't have genotype file
+ mappingMethodId = webqtlDatabaseFunction.getMappingMethod(cursor=self.cursor, groupName=RISetgp)
+
+ mapping_script = HT.Script(language="Javascript")
+ mapping_script_text = """$(function() { $("#mapping_tabs").tabs(); });"""
+ mapping_script.append(mapping_script_text)
+
+ submitTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%", Class="target2")
+
+ if mappingMethodId != None:
+ if int(mappingMethodId) == 1:
+ submitTable.append(mapping_row)
+ submitTable.append(mapping_script)
+ elif int(mappingMethodId) == 4:
+ # NL; 09-26-2011 testing for Human Genome Association function
+ mapping_row=HT.TR()
+ mapping_container = HT.Div(id="mapping_tabs", Class="ui-tabs")
+
+ mapping_tab_list = [HT.Href(text="Genome Association", url="#mappingtabs-1")]
+ mapping_tabs = HT.List(mapping_tab_list)
+ mapping_container.append(mapping_tabs)
+
+ # Genome Association
+ markerSuggestiveText = HT.Span(HT.Bold("P Value:"), Class="ffl fwb fs12")
+
+ markerSuggestive = HT.Input(name='pValue', value='0.001', size=10, maxlength=20,onClick="this.value='';",onBlur="if(this.value==''){this.value='0.001'};")
+ markerMenu = HT.TableLite(HT.TR(HT.TD(markerSuggestiveText), HT.TD(markerSuggestive),HT.TD(HT.Italic('&nbsp;&nbsp;&nbsp;(e.g. 0.001 or 1e-3 or 1E-3 or 3)'))),cellspacing=0, width="400px", cellpadding=2)
+ MarkerRegressionButton=HT.Input(type='button',name='computePlink', value='&nbsp;&nbsp;Compute Using PLINK&nbsp;&nbsp;', onClick= "validatePvalue(this.form);", Class="button")
+
+ marker_div = HT.Div(id="mappingtabs-1")
+ marker_container = HT.Span()
+ markerTable = HT.TableLite(cellspacing=0, cellpadding=0, width="100%")
+ markerTD = HT.TD(valign="top",NOWRAP='ON', Class="fs12 fwn")
+ markerTD.append(markerMenu,HT.BR())
+ markerTD.append(MarkerRegressionButton,HT.BR(),HT.BR())
+ markerTable.append(HT.TR(markerTD))
+
+ marker_container.append(markerTable)
+ marker_div.append(marker_container)
+
+ mapping_container.append(marker_div)
+ mapping_row.append(HT.TD(mapping_container))
+ submitTable.append(mapping_row)
+ submitTable.append(mapping_script)
+ else:
+ submitTable.append(HT.TR(HT.TD(HT.Div(HT.Italic("mappingMethodId %s has not been implemented for this dataset yet." % mappingMethodId), id="mapping_tabs", Class="ui-tabs"))))
+ submitTable.append(mapping_script)
+
+ else:
+ submitTable.append(HT.TR(HT.TD(HT.Div(HT.Italic("Mapping options are disabled for data not matched with genotypes."), id="mapping_tabs", Class="ui-tabs"))))
+ submitTable.append(mapping_script)
+
+ title4Body.append(submitTable)
+
+
+ def natural_sort(strain_list):
+
+ sorted = []
+ for strain in strain_list:
+ try:
+ strain = int(strain)
+ try: sorted[-1] = sorted[-1] * 10 + strain
+ except: sorted.append(strain)
+ except:
+ sorted.append(strain)
+ return sorted
+
+ ##########################################
+ ## Function to display trait tables
+ ##########################################
+ def dispTraitValues(self, fd , title5Body, varianceDataPage, nCols, mainForm, thisTrait):
+ traitTableOptions = HT.Div(style="border: 3px solid #EEEEEE; -moz-border-radius: 10px; -webkit-border-radius: 10px; width: 625px; padding: 5px 5px 10px 8px; font-size: 12px; background: #DDDDDD;")
+ resetButton = HT.Input(type='button',name='resetButton',value=' Reset ',Class="button")
+ blockSamplesField = HT.Input(type="text",style="background-color:white;border: 1px solid black;font-size: 14px;", name="removeField")
+ blockSamplesButton = HT.Input(type='button',value=' Block ', name='blockSamples', Class="button")
+ showHideNoValue = HT.Input(type='button', name='showHideNoValue', value=' Hide No Value ',Class='button')
+ blockMenuSpan = HT.Span(Id="blockMenuSpan")
+ blockMenu = HT.Select(name='block_method')
+
+ if fd.genotype.type == "riset":
+ allstrainlist_neworder = fd.f1list + fd.strainlist
+ else:
+ allstrainlist_neworder = fd.f1list + fd.parlist + fd.strainlist
+
+ attribute_ids = []
+ attribute_names = []
+ try:
+ #ZS: Id values for this trait's extra attributes; used to create "Exclude" dropdown and query for attribute values and create
+ self.cursor.execute("""SELECT CaseAttribute.Id, CaseAttribute.Name
+ FROM CaseAttribute, CaseAttributeXRef
+ WHERE CaseAttributeXRef.ProbeSetFreezeId = '%s' AND
+ CaseAttribute.Id = CaseAttributeXRef.CaseAttributeId
+ group by CaseAttributeXRef.CaseAttributeId""" % (str(thisTrait.db.id)))
+
+ exclude_menu = HT.Select(name="exclude_menu")
+ dropdown_menus = [] #ZS: list of dropdown menus with the distinct values of each attribute (contained in DIVs so the style parameter can be edited and they can be hidden)
+
+ for attribute in self.cursor.fetchall():
+ attribute_ids.append(attribute[0])
+ attribute_names.append(attribute[1])
+ for this_attr_name in attribute_names:
+ exclude_menu.append((this_attr_name.capitalize(), this_attr_name))
+ self.cursor.execute("""SELECT DISTINCT CaseAttributeXRef.Value
+ FROM CaseAttribute, CaseAttributeXRef
+ WHERE CaseAttribute.Name = '%s' AND
+ CaseAttributeXRef.CaseAttributeId = CaseAttribute.Id""" % (this_attr_name))
+ try:
+ distinct_values = self.cursor.fetchall()
+ attr_value_menu_div = HT.Div(style="display:none;", Class="attribute_values") #container used to show/hide dropdown menus
+ attr_value_menu = HT.Select(name=this_attr_name)
+ attr_value_menu.append(("None", "show_all"))
+ for value in distinct_values:
+ attr_value_menu.append((str(value[0]), value[0]))
+ attr_value_menu_div.append(attr_value_menu)
+ dropdown_menus.append(attr_value_menu_div)
+ except:
+ pass
+ except:
+ pass
+
+ other_strains = []
+ for strain in thisTrait.data.keys():
+ if strain not in allstrainlist_neworder:
+ other_strains.append(strain)
+
+ if other_strains:
+ blockMenu.append(('%s Only' % fd.RISet,'1'))
+ blockMenu.append(('Non-%s Only' % fd.RISet,'0'))
+ blockMenuSpan.append(blockMenu)
+ else:
+ pass
+
+ showHideOutliers = HT.Input(type='button', name='showHideOutliers', value=' Hide Outliers ', Class='button')
+ showHideMenuOptions = HT.Span(Id="showHideOptions", style="line-height:225%;")
+ if other_strains:
+ showHideMenuOptions.append(HT.Bold("&nbsp;&nbsp;Block samples by index:&nbsp;&nbsp;&nbsp;&nbsp;"), blockSamplesField, "&nbsp;&nbsp;&nbsp;", blockMenuSpan, "&nbsp;&nbsp;&nbsp;", blockSamplesButton, HT.BR())
+ else:
+ showHideMenuOptions.append(HT.Bold("&nbsp;&nbsp;Block samples by index:&nbsp;&nbsp;&nbsp;&nbsp;"), blockSamplesField, "&nbsp;&nbsp;&nbsp;", blockSamplesButton, HT.BR())
+
+ exportButton = HT.Input(type='button', name='export', value=' Export ', Class='button')
+ if len(attribute_names) > 0:
+ excludeButton = HT.Input(type='button', name='excludeGroup', value=' Block ', Class='button')
+ showHideMenuOptions.append(HT.Bold("&nbsp;&nbsp;Block samples by group:"), "&nbsp;"*5, exclude_menu, "&nbsp;"*5)
+ for menu in dropdown_menus:
+ showHideMenuOptions.append(menu)
+ showHideMenuOptions.append("&nbsp;"*5, excludeButton, HT.BR())
+ showHideMenuOptions.append(HT.Bold("&nbsp;&nbsp;Options:"), "&nbsp;"*5, showHideNoValue, "&nbsp;"*5, showHideOutliers, "&nbsp;"*5, resetButton, "&nbsp;"*5, exportButton)
+
+ traitTableOptions.append(showHideMenuOptions,HT.BR(),HT.BR())
+ traitTableOptions.append(HT.Span("&nbsp;&nbsp;Outliers highlighted in ", HT.Bold("&nbsp;yellow&nbsp;", style="background-color:yellow;"), " can be hidden using the ",
+ HT.Strong(" Hide Outliers "), " button,",HT.BR(),"&nbsp;&nbsp;and samples with no value (x) can be hidden by clicking ",
+ HT.Strong(" Hide No Value "), "."), HT.BR())
+
+
+ dispintro = HT.Paragraph("Edit or delete values in the Trait Data boxes, and use the ", HT.Strong("Reset"), " option as needed.",Class="fs12", style="margin-left:20px;")
+
+ table = HT.TableLite(cellspacing=0, cellpadding=0, width="100%", Class="target5") #Everything needs to be inside this table object in order for the toggle to work
+ container = HT.Div() #This will contain everything and be put into a cell of the table defined above
+
+ container.append(dispintro, traitTableOptions, HT.BR())
+
+ primary_table = HT.TableLite(cellspacing=0, cellpadding=0, Id="sortable1", Class="tablesorter")
+ primary_header = self.getTableHeader(fd=fd, thisTrait=thisTrait, nCols=nCols, attribute_names=attribute_names) #Generate header for primary table object
+
+ other_strainsExist = False
+ for strain in thisTrait.data.keys():
+ if strain not in allstrainlist_neworder:
+ other_strainsExist = True
+ break
+
+ primary_body = self.addTrait2Table(fd=fd, varianceDataPage=varianceDataPage, strainlist=allstrainlist_neworder, mainForm=mainForm, thisTrait=thisTrait, other_strainsExist=other_strainsExist, attribute_ids=attribute_ids, attribute_names=attribute_names, strains='primary')
+
+ primary_table.append(primary_header)
+ for i in range(len(primary_body)):
+ primary_table.append(primary_body[i])
+
+ other_strains = []
+ for strain in thisTrait.data.keys():
+ if strain not in allstrainlist_neworder:
+ allstrainlist_neworder.append(strain)
+ other_strains.append(strain)
+
+ if other_strains:
+ other_table = HT.TableLite(cellspacing=0, cellpadding=0, Id="sortable2", Class="tablesorter") #Table object with other (for example, non-BXD / MDP) traits
+ other_header = self.getTableHeader(fd=fd, thisTrait=thisTrait, nCols=nCols, attribute_names=attribute_names) #Generate header for other table object; same function is used as the one used for the primary table, since the header is the same
+ other_strains.sort() #Sort other strains
+ other_strains = map(lambda X:"_2nd_"+X, fd.f1list + fd.parlist) + other_strains #Append F1 and parent strains to the beginning of the sorted list of other strains
+
+ MDPText = HT.Span("Samples:", Class="ffl fwb fs12")
+ MDPMenu1 = HT.Select(name='MDPChoice1')
+ MDPMenu2 = HT.Select(name='MDPChoice2')
+ MDPMenu3 = HT.Select(name='MDPChoice3')
+ MDPMenu1.append(('%s Only' % fd.RISet,'1'))
+ MDPMenu2.append(('%s Only' % fd.RISet,'1'))
+ MDPMenu3.append(('%s Only' % fd.RISet,'1'))
+ MDPMenu1.append(('Non-%s Only' % fd.RISet,'2'))
+ MDPMenu2.append(('Non-%s Only' % fd.RISet,'2'))
+ MDPMenu3.append(('Non-%s Only' % fd.RISet,'2'))
+ MDPMenu1.append(('All Cases','0'))
+ MDPMenu2.append(('All Cases','0'))
+ MDPMenu3.append(('All Cases','0'))
+ self.MDPRow1.append(HT.TD(MDPText),HT.TD(MDPMenu1))
+ self.MDPRow2.append(HT.TD(MDPText),HT.TD(MDPMenu2))
+ self.MDPRow3.append(HT.TD(MDPText),HT.TD(MDPMenu3))
+
+ other_body = self.addTrait2Table(fd=fd, varianceDataPage=varianceDataPage, strainlist=other_strains, mainForm=mainForm, thisTrait=thisTrait, attribute_ids=attribute_ids, attribute_names=attribute_names, strains='other')
+
+ other_table.append(other_header)
+ for i in range(len(other_body)):
+ other_table.append(other_body[i])
+ else:
+ pass
+
+ if other_strains or (fd.f1list and thisTrait.data.has_key(fd.f1list[0])) \
+ or (fd.f1list and thisTrait.data.has_key(fd.f1list[1])):
+ fd.allstrainlist = allstrainlist_neworder
+
+ if nCols == 6 and fd.varianceDispName != 'Variance':
+ mainForm.append(HT.Input(name='isSE', value="yes", type='hidden'))
+
+ primary_div = HT.Div(primary_table, Id="primary") #Container for table with primary (for example, BXD) strain values
+ container.append(primary_div)
+
+ if other_strains:
+ other_div = HT.Div(other_table, Id="other") #Container for table with other (for example, Non-BXD/MDP) strain values
+ container.append(HT.Div('&nbsp;', height=30))
+ container.append(other_div)
+
+ table.append(HT.TR(HT.TD(container)))
+ title5Body.append(table)
+
+ def addTrait2Table(self, fd, varianceDataPage, strainlist, mainForm, thisTrait, other_strainsExist=None, attribute_ids=[], attribute_names=[], strains='primary'):
+ #XZ, Aug 23, 2010: I commented the code related to the display of animal case
+ #strainInfo = thisTrait.has_key('strainInfo') and thisTrait.strainInfo
+
+ table_body = []
+ vals = []
+
+ for i, strainNameOrig in enumerate(strainlist):
+ strainName = strainNameOrig.replace("_2nd_", "")
+
+ try:
+ thisval = thisTrait.data[strainName].val
+ thisvar = thisTrait.data[strainName].var
+ thisValFull = [strainName,thisval,thisvar]
+ except:
+ continue
+
+ vals.append(thisValFull)
+
+ upperBound, lowerBound = Plot.findOutliers(vals) # ZS: Values greater than upperBound or less than lowerBound are considered outliers.
+
+ for i, strainNameOrig in enumerate(strainlist):
+
+ trId = strainNameOrig
+ selectCheck = HT.Input(type="checkbox", name="selectCheck", value=trId, Class="checkbox", onClick="highlight(this)")
+
+ strainName = strainNameOrig.replace("_2nd_", "")
+ strainNameAdd = ''
+ if fd.RISet == 'AXBXA' and strainName in ('AXB18/19/20','AXB13/14','BXA8/17'):
+ strainNameAdd = HT.Href(url='/mouseCross.html#AXB/BXA', text=HT.Sup('#'), Class='fs12', target="_blank")
+
+ try:
+ thisval, thisvar, thisNP = thisTrait.data[strainName].val, thisTrait.data[strainName].var, thisTrait.data[strainName].N
+ if thisNP:
+ mainForm.append(HT.Input(name='N'+strainName, value=thisNP, type='hidden'))
+ else:
+ pass
+ except:
+ thisval = thisvar = 'x'
+
+ try:
+ traitVal = thisval
+ dispVal = "%2.3f" % thisval
+ except:
+ traitVal = ''
+ dispVal = 'x'
+
+ strainNameDisp = HT.Span(strainName, Class='fs14 fwn ffl')
+
+ if varianceDataPage:
+ try:
+ traitVar = thisvar
+ dispVar = "%2.3f" % thisvar
+ except:
+ traitVar = ''
+ dispVar = 'x'
+
+ if thisval == 'x':
+ traitVar = '' #ZS: Used to be 0, but it doesn't seem like a good idea for values of 0 to *always* be at the bottom when you sort; it makes more sense to put "nothing"
+
+ className = 'fs13 b1 c222 '
+ valueClassName = 'fs13 b1 c222 valueField '
+ rowClassName = 'novalue '
+ else:
+ if (thisval >= upperBound) or (thisval <= lowerBound):
+ className = 'fs13 b1 c222 outlier '
+ valueClassName = 'fs13 b1 c222 valueField '
+ rowClassName = 'outlier'
+ else:
+ className = 'fs13 b1 c222 '
+ valueClassName = 'fs13 b1 c222 valueField '
+ rowClassName = ' '
+
+ if varianceDataPage:
+ varClassName = valueClassName + str(traitVar)
+ valueClassName += str(traitVal)
+
+ if strainNameOrig == strainName:
+ if other_strainsExist and strainNameOrig in (fd.parlist + fd.f1list):
+ ########################################################################################################################################################
+ # ZS: Append value and variance to the value and variance input fields' list of classes; this is so the javascript can update the value when the user
+ # changes it. The updated value is then used when the table is sorted (tablesorter.js). This needs to be done because the "value" attribute is immutable.
+ #########################################################################################################################################################
+
+ valueField = HT.Input(name=strainNameOrig, size=8, maxlength=8, style="text-align:right; background-color:#FFFFFF;", value=dispVal,
+ onChange= "javascript:this.form['_2nd_%s'].value=this.form['%s'].value;" % (strainNameOrig.replace("/", ""), strainNameOrig.replace("/", "")), Class=valueClassName)
+ if varianceDataPage:
+ seField = HT.Input(name='V'+strainNameOrig, size=8, maxlength=8, style="text-align:right", value=dispVar,
+ onChange= "javascript:this.form['V_2nd_%s'].value=this.form['V%s'].value;" % (strainNameOrig.replace("/", ""), strainNameOrig.replace("/", "")), Class=varClassName)
+ else:
+ valueField = HT.Input(name=strainNameOrig, size=8, maxlength=8, style="text-align:right; background-color:#FFFFFF;", value=dispVal, Class=valueClassName)
+ if varianceDataPage:
+ seField = HT.Input(name='V'+strainNameOrig, size=8, maxlength=8, style="text-align:right", value=dispVar, Class=varClassName)
+ else:
+ valueField = HT.Input(name=strainNameOrig, size=8, maxlength=8, style="text-align:right", value=dispVal,
+ onChange= "javascript:this.form['%s'].value=this.form['%s'].value;" % (strainNameOrig.replace("/", ""), strainNameOrig.replace("/", "")), Class=valueClassName)
+ if varianceDataPage:
+ seField = HT.Input(name='V'+strainNameOrig, size=8, maxlength=8, style="text-align:right", value=dispVar,
+ onChange= "javascript:this.form['V%s'].value=this.form['V%s'].value;" % (strainNameOrig.replace("/", ""), strainNameOrig.replace("/", "")), Class=varClassName)
+
+ if (strains == 'primary'):
+ table_row = HT.TR(Id="Primary_"+str(i+1), Class=rowClassName)
+ else:
+ table_row = HT.TR(Id="Other_"+str(i+1), Class=rowClassName)
+
+ if varianceDataPage:
+ table_row.append(HT.TD(str(i+1), selectCheck, width=45, align='right', Class=className))
+ table_row.append(HT.TD(strainNameDisp, strainNameAdd, align='right', width=100, Class=className))
+ table_row.append(HT.TD(valueField, width=70, align='right', Id="value_"+str(i)+"_"+strains, Class=className))
+ table_row.append(HT.TD("&plusmn;", width=20, align='center', Class=className))
+ table_row.append(HT.TD(seField, width=80, align='right', Id="SE_"+str(i)+"_"+strains, Class=className))
+ else:
+ table_row.append(HT.TD(str(i+1), selectCheck, width=45, align='right', Class=className))
+ table_row.append(HT.TD(strainNameDisp, strainNameAdd, align='right', width=100, Class=className))
+ table_row.append(HT.TD(valueField, width=70, align='right', Id="value_"+str(i)+"_"+strains, Class=className))
+
+ if thisTrait and thisTrait.db and thisTrait.db.type =='ProbeSet':
+ if len(attribute_ids) > 0:
+
+ #ZS: Get StrainId value for the next query
+ self.cursor.execute("""SELECT Strain.Id
+ FROM Strain, StrainXRef, InbredSet
+ WHERE Strain.Name = '%s' and
+ StrainXRef.StrainId = Strain.Id and
+ InbredSet.Id = StrainXRef.InbredSetId and
+ InbredSet.Name = '%s'""" % (strainName, fd.RISet))
+
+ strain_id = self.cursor.fetchone()[0]
+
+ attr_counter = 1 # This is needed so the javascript can know which attribute type to associate this value with for the exported excel sheet (each attribute type being a column).
+ for attribute_id in attribute_ids:
+
+ #ZS: Add extra case attribute values (if any)
+ self.cursor.execute("""SELECT Value
+ FROM CaseAttributeXRef
+ WHERE ProbeSetFreezeId = '%s' AND
+ StrainId = '%s' AND
+ CaseAttributeId = '%s'
+ group by CaseAttributeXRef.CaseAttributeId""" % (thisTrait.db.id, strain_id, str(attribute_id)))
+
+ attributeValue = self.cursor.fetchone()[0] #Trait-specific attributes, if any
+
+ #ZS: If it's an int, turn it into one for sorting (for example, 101 would be lower than 80 if they're strings instead of ints)
+ try:
+ attributeValue = int(attributeValue)
+ except:
+ pass
+
+ span_Id = strains+"_attribute"+str(attr_counter)+"_sample"+str(i+1)
+ attr_container = HT.Span(attributeValue, Id=span_Id)
+ attr_className = str(attributeValue) + "&nbsp;" + className
+ table_row.append(HT.TD(attr_container, align='right', Class=attr_className))
+ attr_counter += 1
+
+ table_body.append(table_row)
+ return table_body
+
+ def getTableHeader(self, fd, thisTrait, nCols, attribute_names):
+
+ table_header = HT.TR()
+
+ col_class = "fs13 fwb ff1 b1 cw cbrb"
+
+ if nCols == 6:
+ try:
+ if fd.varianceDispName:
+ pass
+ except:
+ fd.varianceDispName = 'Variance'
+
+ table_header.append(HT.TH('Index', align='right', width=60, Class=col_class),
+ HT.TH('Sample', align='right', width=100, Class=col_class),
+ HT.TH('Value', align='right', width=70, Class=col_class),
+ HT.TH('&nbsp;', width=20, Class=col_class),
+ HT.TH(fd.varianceDispName, align='right', width=80, Class=col_class))
+
+ elif nCols == 4:
+ table_header.append(HT.TH('Index', align='right', width=60, Class=col_class),
+ HT.TH('Sample', align='right', width=100, Class=col_class),
+ HT.TH('Value', align='right', width=70, Class=col_class))
+
+ else:
+ pass
+
+ if len(attribute_names) > 0:
+ i=0
+ for attribute in attribute_names:
+ char_count = len(attribute)
+ cell_width = char_count * 14
+ table_header.append(HT.TH(attribute, align='right', width=cell_width, Class="attribute_name " + col_class))
+ i+=1
+
+ return table_header
+
+
+ def getSortByValue(self):
+
+ sortby = ("", "")
+
+ return sortby
+
+
diff --git a/web/webqtl/showTrait/ShowBestTrait.py b/web/webqtl/showTrait/ShowBestTrait.py
new file mode 100755
index 00000000..9eb42923
--- /dev/null
+++ b/web/webqtl/showTrait/ShowBestTrait.py
@@ -0,0 +1,195 @@
+# 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
+
+import string
+
+#from base.templatePage import templatePage
+#from basicStatistics.BasicStatisticsPage import BasicStatisticsPage
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility import webqtlUtil
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from DataEditingPage import DataEditingPage
+
+
+#class ShowBestTrait(BasicStatisticsPage, templatePage):
+
+class ShowBestTrait(DataEditingPage):
+ def __init__(self,fd):
+
+ ########## geneName means symbol ##########
+ geneName = fd.formdata.getvalue('gene')
+ if geneName:
+ geneName = string.strip(geneName)
+
+ refseq = fd.formdata.getvalue('refseq')
+ if refseq:
+ refseq = string.strip(refseq)
+
+ genbankid = fd.formdata.getvalue('genbankid')
+ if genbankid:
+ genbankid = string.strip(genbankid)
+
+ geneid = fd.formdata.getvalue('geneid')
+ if geneid:
+ geneid = string.strip(geneid)
+
+ species = fd.formdata.getvalue('species')
+ tissue = fd.formdata.getvalue('tissue')
+ database = fd.formdata.getvalue('database')
+
+ ########## searchAlias is just a singal, so it doesn't need be stripped ##########
+ searchAlias = fd.formdata.getvalue('searchAlias')
+
+ if not self.openMysql():
+ return
+
+ if database:
+ if geneName:
+ if searchAlias:
+ self.cursor.execute(""" SELECT ProbeSetXRef.*
+ FROM
+ ProbeSet, ProbeSetXRef, DBList
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = DBList.FreezeId AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ (DBList.Name=%s or DBList.Code=%s) AND
+ MATCH (ProbeSet.symbol, alias) AGAINST ("+%s" IN BOOLEAN MODE)
+ ORDER BY ProbeSetXRef.mean DESC
+ """ , (database, database, geneName))
+ else:
+ self.cursor.execute(""" SELECT ProbeSetXRef.*
+ FROM
+ ProbeSet, ProbeSetXRef, DBList
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = DBList.FreezeId AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ (DBList.Name=%s or DBList.Code=%s) AND
+ ProbeSet.symbol = %s
+ ORDER BY ProbeSetXRef.mean DESC
+ """ , (database, database, geneName))
+ elif refseq:
+ self.cursor.execute(""" SELECT ProbeSetXRef.*
+ FROM
+ ProbeSet, ProbeSetXRef, DBList
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = DBList.FreezeId AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ (DBList.Name=%s or DBList.Code=%s) AND
+ ProbeSet.RefSeq_TranscriptId = %s
+ ORDER BY ProbeSetXRef.mean DESC
+ """ , (database, database, refseq))
+ elif genbankid:
+ self.cursor.execute(""" SELECT ProbeSetXRef.*
+ FROM
+ ProbeSet, ProbeSetXRef, DBList
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = DBList.FreezeId AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ (DBList.Name=%s or DBList.Code=%s) AND
+ ProbeSet.GenbankId = %s
+ ORDER BY ProbeSetXRef.mean DESC
+ """ , (database, database, genbankid))
+ elif geneid:
+ self.cursor.execute(""" SELECT ProbeSetXRef.*
+ FROM
+ ProbeSet, ProbeSetXRef, DBList
+ WHERE
+ ProbeSetXRef.ProbeSetFreezeId = DBList.FreezeId AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ (DBList.Name=%s or DBList.Code=%s) AND
+ ProbeSet.GeneId = %s
+ ORDER BY ProbeSetXRef.mean DESC
+ """ , (database, database, geneid))
+
+ Results = self.cursor.fetchone()
+
+
+
+ ########## select the Data that match the selection(currently, only max mean available) ##########
+ if Results:
+ ProbeSetFreezeId = Results[0]
+ ProbeSetId = Results[1]
+ DataId = Results[2]
+
+ self.cursor.execute("""
+ select
+ InbredSet.Name
+ from
+ InbredSet, ProbeFreeze, ProbeSetFreeze
+ where
+ InbredSet.Id=ProbeFreeze.InbredSetId and
+ ProbeFreeze.Id=ProbeSetFreeze.ProbeFreezeId and
+ ProbeSetFreeze.Id=%s
+ """, ProbeSetFreezeId)
+ fd.RISet = self.cursor.fetchone()[0]
+ #fd.RISet = Results[0]
+
+ self.cursor.execute("select Name, FullName from ProbeSetFreeze where Id=%s", ProbeSetFreezeId)
+ fd.database, fd.identification = self.cursor.fetchone()
+
+ self.cursor.execute("select Name, symbol, description from ProbeSet where Id=%s", ProbeSetId)
+ fd.ProbeSetID, fd.symbol, fd.description = self.cursor.fetchone()
+
+ fd.identification += ' : '+fd.ProbeSetID
+ fd.formdata['fullname'] = fd.database+'::'+fd.ProbeSetID
+
+ #XZ, 03/03/2009: Xiaodong changed Data to ProbeSetData
+ self.cursor.execute("select Strain.Name, ProbeSetData.Value from Strain, ProbeSetData where Strain.Id=ProbeSetData.StrainId and ProbeSetData.Id=%s", DataId)
+ Results = self.cursor.fetchall()
+
+ fd.allstrainlist = []
+ for item in Results:
+ fd.formdata[item[0]] = item[1]
+ fd.allstrainlist.append(item[0])
+
+ #XZ, 03/12/2009: Xiaodong changed SE to ProbeSetSE
+ self.cursor.execute("select Strain.Name, ProbeSetSE.error from Strain, ProbeSetSE where Strain.Id = ProbeSetSE.StrainId and ProbeSetSE.DataId=%s", DataId)
+ Results = self.cursor.fetchall()
+ for item in Results:
+ fd.formdata['V'+item[0]] = item[1]
+ else:
+ fd.RISet = 'BXD'
+ fd.database = 'KI_2A_0405_Rz'
+ fd.ProbeSetID = '1367452_at'
+ else:
+ fd.RISet = 'BXD'
+ fd.database = 'KI_2A_0405_Rz'
+ fd.ProbeSetID = '1367452_at'
+
+
+ #BasicStatisticsPage.__init__(self, fd)
+
+
+ thisTrait = webqtlTrait(db=fd.database, name=fd.ProbeSetID, cursor=self.cursor)
+ thisTrait.retrieveInfo()
+ thisTrait.retrieveData()
+ DataEditingPage.__init__(self, fd, thisTrait)
+ self.dict['title'] = '%s: Display Trait' % fd.identification
+
+
diff --git a/web/webqtl/showTrait/ShowProbeInfoPage.py b/web/webqtl/showTrait/ShowProbeInfoPage.py
new file mode 100755
index 00000000..989238b4
--- /dev/null
+++ b/web/webqtl/showTrait/ShowProbeInfoPage.py
@@ -0,0 +1,486 @@
+# 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
+
+import string
+import sys,os
+
+import cPickle
+
+import reaper
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility import webqtlUtil
+from dbFunction import webqtlDatabaseFunction
+from base.templatePage import templatePage
+from base.webqtlDataset import webqtlDataset
+from base.webqtlTrait import webqtlTrait
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+
+#########################################
+# Probe Infomation Page
+#########################################
+
+class ShowProbeInfoPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ fd.readGenotype()
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+ self.database = fd.formdata.getfirst('database')
+ self.ProbeSetID = fd.formdata.getfirst('ProbeSetID')
+ self.CellID = fd.formdata.getfirst('CellID')
+
+ self.db = webqtlDataset(self.database, self.cursor)
+ thisTrait = webqtlTrait(db= self.db, cursor=self.cursor, name=self.ProbeSetID) #, cellid=CellID)
+ thisTrait.retrieveInfo()
+
+ try:
+ self.cursor.execute('SELECT ProbeFreeze.Name FROM ProbeFreeze,ProbeSetFreeze WHERE ProbeFreeze.Id = ProbeSetFreeze.ProbeFreezeId and ProbeSetFreeze.Name = "%s"' % self.db.name)
+ self.probeDatabase = self.cursor.fetchall()[0][0]
+ self.probeInfoDatabase = 'Probe'
+ except:
+ heading = 'Probe Information'
+ intro = ['Trying to retrieve the probe information for ProbeSet ',HT.Span('%s' % self.ProbeSetID, Class="fwb cdg"),' in Database ',HT.Href(text='%s' % self.db.fullname,url=webqtlConfig.infopagehref % self.database)]
+ detail = ['The information you just requested is not available at this time.']
+ self.error(heading=heading,intro=intro,detail=detail)
+ return
+
+
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':'_','CellID':'_','RISet':fd.RISet, 'incparentsf1':'on'}
+ if fd.RISet == 'BXD':
+ hddn['parentsf1']='ON'
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+
+ #Buttons on search page
+ linkinfo ="%s/probeInfo.html" % webqtlConfig.PORTADDR
+ mintmap = ""
+ probeinfo = HT.Input(type='button' ,name='mintmap',value='Info', onClick="openNewWin('%s');" % linkinfo, Class="button")
+ cormatrix = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('showDatabase')[0], 'corMatrix');")
+ cormatrix_img = HT.Image("/images/correlation_matrix1_final.jpg", alt="Correlation Matrix and PCA", title="Correlation Matrix and PCA", style="border:none;")
+ cormatrix.append(cormatrix_img)
+ heatmap = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('showDatabase')[0], 'heatmap');")
+ heatmap_img = HT.Image("/images/heatmap2_final.jpg", name='mintmap', alt="QTL Heat Map and Clustering", title="QTL Heatmap and Clustering", style="border:none;")
+ heatmap.append(heatmap_img)
+ if self.ProbeSetID[-2:] in ('_A', '_B'):
+ thisProbeSetID = self.ProbeSetID[:-2]
+ else:
+ thisProbeSetID = self.ProbeSetID
+ thisurl = 'http://www.ensembl.org/Mus_musculus/featureview?type=AffyProbe&id=%s' % thisProbeSetID
+ verifyButton = HT.Input(type="button",value="Verify Ensembl",onClick= "openNewWin('%s')" % thisurl, Class="button")
+
+ addselect = HT.Input(type='button' ,name='addselect',value='Add to Collection', onClick="addRmvSelection('%s', this.form, 'addToSelection');" % fd.RISet,Class="button")
+ selectall = HT.Input(type='button' ,name='selectall',value='Select All', onClick="checkAll(this.form);",Class="button")
+ selectpm = HT.Input(type='button' ,name='selectall',value='Select PM', onClick="checkPM(this.form);",Class="button")
+ selectmm = HT.Input(type='button' ,name='selectall',value='Select MM', onClick="checkMM(this.form);",Class="button")
+ selectinvert = HT.Input(type='button' ,name='selectinvert',value='Select Invert', onClick="checkInvert(this.form);",Class="button")
+ reset = HT.Input(type='reset',name='',value='Select None',Class="button")
+ chrMenu = HT.Input(type='hidden',name='chromosomes',value='all')
+ probedata = HT.Input(type='hidden',name='probedata',value='all')
+
+ url_rudi_track = self.getProbeTrackURL(self.probeDatabase, self.ProbeSetID)
+ if url_rudi_track:
+ rudi_track = HT.Input(type='button', name='ruditrack', value='Probe Track', onClick="openNewWin('%s')"%url_rudi_track, Class="button")
+ else: rudi_track = None
+
+ pinfopage = "/probeInfo.html"
+
+ #updated by NL: 07-22-2011 get chosenStrains
+ _f1, _f12, _mat, _pat = webqtlUtil.ParInfo[fd.RISet]
+ chosenStrains="%s,%s"%(_mat,_pat)
+ tblobj = {}
+ tblobj['header']=[]
+
+ tblobj['header'].append([
+ THCell(HT.TD("", Class="cbrb cw fwb fs13 b1", rowspan=2,nowrap='ON'), sort=0),
+ THCell(HT.TD(HT.Href(target="_PROBEINFO", url=pinfopage+"#probe", text=HT.Span('Probe', Class="cw fwb fs13")), HT.Sup(HT.Italic('1')), Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,nowrap='ON'), text="probe", idx=1),
+ THCell(HT.TD(HT.Href(text=HT.Span('Sequence', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#Sequence"),HT.Sup(HT.Italic('2')), Class="cbrb cw fwb fs13 b1", align='center',rowspan=2,nowrap='ON'), text="seq", idx=2),
+ THCell(HT.TD(HT.Href(text=HT.Span('bl2seq', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#bl2seq"),HT.Sup(HT.Italic('3')), Class="cbrb cw fwb fs13 b1", align='center',rowspan=2,nowrap='ON'), sort=0),
+ THCell(HT.TD(HT.Href(text=HT.Span('Exons', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#Exon"),HT.Sup(HT.Italic('4')), Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,nowrap='ON'), sort=0),
+ THCell(HT.TD(HT.Href(text=HT.Span('Tm &deg;C', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#Tm"),HT.Sup(HT.Italic('5')), Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,nowrap='ON'), text="tm", idx=5),
+ THCell(HT.TD(HT.Href(text=HT.Span('Stacking Energy K', HT.Sub('B'),'T', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#KBT"),HT.Sup(HT.Italic('6')), Class="cbrb cw fwb fs13 b1",align='center',colspan=2,NOWRAP="yes",nowrap='ON'), sort=0),
+ THCell(HT.TD(HT.Href(text=HT.Span('Mean', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#Mean"),HT.Sup(HT.Italic('7')), Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,nowrap='ON'), text="mean", idx=8),
+ THCell(HT.TD(HT.Href(text=HT.Span('Stdev', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#Stdev"),HT.Sup(HT.Italic('8')), Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,nowrap='ON'), text="std", idx=9),
+ THCell(HT.TD(HT.Href(text=HT.Span('Probe h2', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#h2"),HT.Sup(HT.Italic('9')), Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,NOWRAP="yes"), text="h2", idx=10),
+ THCell(HT.TD(HT.Href(text=HT.Span('Probe Location', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#location"), HT.Sup(HT.Italic('10')),Class="cbrb cw fwb fs13 b1",align='center',colspan=3)),
+ THCell(HT.TD(HT.Href(text=HT.Span('SNPs', HT.BR(), '(Across all strains)', Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#snps"), HT.Sup(HT.Italic('11')),Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,NOWRAP="yes")),
+ THCell(HT.TD(HT.Href(text=HT.Span('SNPs', HT.BR(),'(Different alleles only between %s and %s)'%(_mat,_pat), Class="cw fwb fs13"), target="_PROBEINFO", url=pinfopage+"#snps"), HT.Sup(HT.Italic('11')),Class="cbrb cw fwb fs13 b1",align='center',rowspan=2,NOWRAP="yes"))
+
+ ])
+
+ tblobj['header'].append([
+ THCell(HT.TD(HT.Span('GSB', Class="cw fwb fs13"),align='center', Class="cbrb ffl fwb fs13 b1",), text="gsb", idx=6),
+ THCell(HT.TD(HT.Span('NSB', Class="cw fwb fs13"),align='center', Class="cbrb ffl fwb fs13 b1",), text="nsb", idx=7),
+ THCell(HT.TD(HT.Span('Chr', Class="cw fwb fs13"), align='center', Class="cbrb ffl2 fwb fs13 b1",)),
+ THCell(HT.TD(HT.Span('Start', Class="cw fwb fs13"),align='center', Class="cbrb ffl fwb fs13 b1",)),
+ THCell(HT.TD(HT.Span('End', Class="cw fwb fs13"),align='center', Class="cbrb ffl fwb fs13 b1",)),
+ ])
+
+ tblobj['body'] = []
+
+ blatbutton = ''
+
+ fetchField = ['Probe.Name','Probe.Sequence','Probe.ExonNo','Probe.Tm', 'Probe.E_GSB','Probe.E_NSB', 'ProbeH2.h2', 'ProbeH2.weight']
+
+ query = "SELECT %s FROM (Probe, ProbeSet, ProbeFreeze) left join ProbeH2 on ProbeH2.ProbeId = Probe.Id and ProbeH2.ProbeFreezeId = ProbeFreeze.Id WHERE ProbeSet.Name = '%s' and Probe.ProbeSetId = ProbeSet.Id and ProbeFreeze.Name = '%s' order by Probe.SerialOrder" % (string.join(fetchField,','), self.ProbeSetID, self.probeDatabase)
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+
+ blatsequence = ""
+
+ # add by NL: get strains' name in SnpPattern database table
+ strainsInSnpPatternDBtable=self.getStrainNameIndexPair() # after snpBrowserPage.py change to MVC, this function can be removed in this class and called from other class;
+ allStrainNameList=[v[0] for v in strainsInSnpPatternDBtable]
+
+ speciesid = webqtlDatabaseFunction.retrieveSpeciesId(cursor=self.cursor,RISet=fd.RISet)
+ for result in results:
+ """
+ ProbeId, CellID,Sequence,ExonNo,Tm, E_GSB,E_NSB = map(self.nullRecord,result)
+ h2 = ''
+ query = "SELECT h2 FROM ProbeH2 WHERE ProbeFreezeId = '%s' and ProbeId=%s" % (self.probeDatabase, ProbeId)
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+ """
+
+ CellID,Sequence,ExonNo,Tm, E_GSB,E_NSB,h2, weight = map(self.nullRecord,result)
+
+
+ Average = ''
+ STDEV = ''
+ mean = -10000.0
+ stdev = -10000.0
+ try:
+ thisTrait.cellid = CellID
+ thisTrait.retrieveData()
+
+ mean, median, var, stdev, sem, N = reaper.anova(thisTrait.exportInformative()[1])
+
+ if mean:
+ Average = '%2.2f' % mean
+ if stdev:
+ STDEV = '%2.2f' % stdev
+ except:
+ pass
+
+ if CellID == self.CellID:
+ bkColor = "cbrdull fs11 b1"
+ else:
+ bkColor = "fs11 b1"
+ seqcolor= ''
+
+ if thisTrait.blatseq:
+ blatsequence = thisTrait.blatseq
+ if int(CellID[-1]) % 2 == 1:
+ seqcolor= 'cdg'
+ else:
+ if int(CellID[-1]) % 2 == 1:
+ seqcolor= 'cdg'
+ blatsequence += string.strip(Sequence)
+
+ if thisTrait.genbankid and (int(CellID[-1]) % 2 == 1):
+ probeurl = 'http://www.ncbi.nlm.nih.gov/blast/bl2seq/wblast2.cgi?one=%s&sseq=%s' % (thisTrait.genbankid, Sequence)
+ probefy1 = HT.Input(type="button",value="Blast",onClick= "openNewWin('%s')" % probeurl, Class="buttonsmaller")
+ else:
+ probefy1 = ''
+
+ traitName = str(thisTrait)
+
+ #XZ, Aug 08, 2011: Note that probesets on some affy chips are not name as "xxx_at" (i.e., Affy Mouse Gene 1.0 ST (GPL6246)).
+ #EnsemblProbeSetID = self.ProbeSetID[0:self.ProbeSetID.index('_at')+3]
+ EnsemblProbeSetID = self.ProbeSetID
+ if '_at' in self.ProbeSetID:
+ EnsemblProbeSetID = self.ProbeSetID[0:self.ProbeSetID.index('_at')+3]
+
+ self.cursor.execute('''
+ SELECT EnsemblProbeLocation.*
+ FROM EnsemblProbeLocation, EnsemblProbe, EnsemblChip, GeneChipEnsemblXRef, ProbeFreeze
+ WHERE EnsemblProbeLocation.ProbeId=EnsemblProbe.Id and EnsemblProbe.ChipId=GeneChipEnsemblXRef.EnsemblChipId and
+ GeneChipEnsemblXRef.GeneChipId=ProbeFreeze.ChipId and EnsemblProbe.Name=%s and EnsemblProbe.ProbeSet=%s and
+ ProbeFreeze.Name=%s group by Chr, Start, End'''
+ ,(CellID, EnsemblProbeSetID, self.probeDatabase))
+ LocationFields = self.cursor.fetchall()
+
+ Chr=''
+ Start=''
+ End=''
+ if (len(LocationFields)>=1):
+ Chr,Start,End,Strand,MisMatch,ProbeId = map(self.nullRecord,LocationFields[0])
+ Start /= 1000000.0
+ End /= 1000000.0
+ if (len(LocationFields)>1):
+ self.cursor.execute('''
+ SELECT ProbeSet.Chr, ProbeSet.Mb FROM ProbeSet, ProbeFreeze
+ WHERE ProbeSet.ChipId=ProbeFreeze.ChipId and ProbeSet.Name=%s and ProbeFreeze.Name=%s'''
+ ,(self.ProbeSetID, self.probeDatabase))
+ ProbeSetChr, ProbeSetMb = map(self.nullRecord,self.cursor.fetchall()[0])
+
+ self.cursor.execute('''
+ SELECT EnsemblProbeLocation.*, ABS(EnsemblProbeLocation.Start/1000000-%s) as Mb
+ FROM EnsemblProbeLocation, EnsemblProbe, EnsemblChip, GeneChipEnsemblXRef, ProbeFreeze
+ WHERE EnsemblProbeLocation.ProbeId=EnsemblProbe.Id and EnsemblProbe.ChipId=GeneChipEnsemblXRef.EnsemblChipId and
+ GeneChipEnsemblXRef.GeneChipId=ProbeFreeze.ChipId and EnsemblProbe.Name=%s and EnsemblProbe.ProbeSet=%s and
+ EnsemblProbeLocation.Chr=%s and ProbeFreeze.Name=%s order by Mb limit 1'''
+ ,(ProbeSetMb, CellID, EnsemblProbeSetID, ProbeSetChr, self.probeDatabase))
+ NewLocationFields = self.cursor.fetchall()
+ if (len(NewLocationFields)>0):
+ Chr,Start,End,Strand,MisMatch,ProbeId,Mb = map(self.nullRecord,NewLocationFields[0])
+ Start /= 1000000.0
+ End /= 1000000.0
+
+ snp_collection = []
+ snpDiff_collection=[]
+
+ startIndex=3
+ if Chr != '' and Start != '' and End != '' and speciesid != None:
+
+ self.cursor.execute('''
+ SELECT a.SnpName, a.Id, b.* FROM SnpAll a, SnpPattern b
+ WHERE a.Chromosome=%s and a.Position>=%s and a.Position<=%s
+ and a.SpeciesId=%s and a.Id=b.SnpId'''
+ ,(Chr, Start, End, speciesid)) #chr,Start, End, 1))
+ snpresults = self.cursor.fetchall()
+
+ index1=allStrainNameList.index(_mat) #_mat index in results
+ index2=allStrainNameList.index(_pat) #_pat index in results
+
+ for v in snpresults:
+ #updated by NL: 07-22-2011 check 'limit to' to get snpBrowser snpresults
+ snp_collection.append(HT.Href(text=v[0], url=os.path.join(webqtlConfig.CGIDIR,
+ "main.py?FormID=SnpBrowserResultPage&submitStatus=1&customStrain=1")+ "&geneName=%s" % v[0], Class="fs12 fwn", target="_blank"))
+ snp_collection.append(HT.BR())
+ #updated by NL: 07-27-2011 link snp info for different allele only
+ strain1_allele=v[startIndex+index1]
+ strain2_allele=v[startIndex+index2]
+
+ if strain1_allele!=strain2_allele:
+ snpDiff_collection.append(HT.Href(text=v[0], url=os.path.join(webqtlConfig.CGIDIR,
+ "main.py?FormID=SnpBrowserResultPage&submitStatus=1&customStrain=1&diffAlleles=1&chosenStrains=%s"%chosenStrains)+ "&geneName=%s" % v[0], Class="fs12 fwn", target="_blank"))
+ snpDiff_collection.append(HT.BR())
+
+
+ tr = []
+ tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class='checkbox', name="searchResult",value=traitName, onClick="highlight(this)"), align="right", Class=bkColor, nowrap="on"), text=traitName))
+
+ tr.append(TDCell(HT.TD(HT.Href(text=CellID, url = "javascript:showDatabase2('%s','%s','%s');" % (self.database,self.ProbeSetID,CellID),Class="fs12 fwn"),Class=bkColor), traitName, traitName.upper()))
+
+ tr.append(TDCell(HT.TD(Sequence, Class=bkColor + " %s ffmono fs14" % seqcolor),Sequence,Sequence.upper()))
+ tr.append(TDCell(HT.TD(probefy1,align='center',Class=bkColor)))
+ tr.append(TDCell(HT.TD(ExonNo,align='center',Class=bkColor)))
+
+ try:
+ TmValue = float(Tm)
+ except:
+ TmValue = 0.0
+ tr.append(TDCell(HT.TD(Tm,align='center',Class=bkColor), Tm, TmValue))
+
+ try:
+ E_GSBValue = float(E_GSB)
+ except:
+ E_GSBValue = -10000.0
+ tr.append(TDCell(HT.TD(E_GSB,align='center',Class=bkColor), E_GSB, E_GSBValue))
+
+ try:
+ E_NSBValue = float(E_NSB)
+ except:
+ E_NSBValue = -10000.0
+ tr.append(TDCell(HT.TD(E_NSB,align='center',Class=bkColor), E_NSB, E_NSBValue))
+
+ tr.append(TDCell(HT.TD(Average,align='center',Class=bkColor), Average, mean))
+ tr.append(TDCell(HT.TD(STDEV,align='center',Class=bkColor), STDEV, stdev))
+
+ try:
+ h2Value = float(h2)
+ except:
+ h2Value = -10000.0
+ tr.append(TDCell(HT.TD(h2,align='center',Class=bkColor), h2, h2Value))
+
+ tr.append(TDCell(HT.TD(Chr,align='left',Class=bkColor)))
+ tr.append(TDCell(HT.TD(Start,align='left',Class=bkColor)))
+ tr.append(TDCell(HT.TD(End,align='left',Class=bkColor)))
+
+ snp_td = HT.TD(align='left',Class=bkColor)
+ for one_snp_href in snp_collection:
+ snp_td.append(one_snp_href)
+
+ tr.append(TDCell(snp_td))
+
+ #07-27-2011:add by NL: show SNP results for different allele only
+ snpDiff_td= HT.TD(align='left', valign='top', Class=bkColor)
+ for one_snpDiff_href in snpDiff_collection:
+ snpDiff_td.append(one_snpDiff_href)
+ tr.append(TDCell(snpDiff_td))
+
+ tblobj['body'].append(tr)
+
+ # import cPickle
+ filename = webqtlUtil.genRandStr("Probe_")
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+ # NL, 07/27/2010. genTableObj function has been moved from templatePage.py to webqtlUtil.py;
+ div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=("", ""), tableID = "sortable", addIndex = "1"), Id="sortable")
+
+ #UCSC
+ _Species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=fd.RISet)
+ if _Species == "rat":
+ thisurl = webqtlConfig.UCSC_BLAT % ('rat', 'rn3', blatsequence)
+ elif _Species == "mouse":
+ thisurl = webqtlConfig.UCSC_BLAT % ('mouse', 'mm9', blatsequence)
+ else:
+ thisurl = ""
+ if thisurl:
+ blatbutton = HT.Input(type='button' ,name='blatPM',value='Verify UCSC', onClick="window.open('%s','_blank')" % thisurl,Class="button")
+ else:
+ blatbutton = ""
+
+ #GenBank
+ genbankSeq = ""
+ if thisTrait.genbankid:
+ self.cursor.execute("SELECT Sequence FROM Genbank WHERE Id = '%s'" % thisTrait.genbankid )
+ genbankSeq = self.cursor.fetchone()
+ if genbankSeq:
+ genbankSeq = genbankSeq[0]
+
+ if genbankSeq:
+ if _Species == "rat":
+ thisurl2 = webqtlConfig.UCSC_BLAT % ('rat', 'rn3', genbankSeq)
+ if _Species == "mouse":
+ thisurl2 = webqtlConfig.UCSC_BLAT % ('mouse', 'mm9', genbankSeq)
+ else:
+ thisurl2 = ''
+ if thisurl2:
+ blatbutton2 = HT.Input(type='button' ,name='blatPM',value='Verify GenBank', onClick="window.open('%s','_blank')" % thisurl2,Class="button")
+ else:
+ blatbutton2 = ""
+
+ #Snp
+ snpBrowser = ""
+ if thisTrait.symbol and _Species == 'mouse':
+ self.cursor.execute("select geneSymbol from GeneList where geneSymbol = %s", thisTrait.symbol)
+ geneName = self.cursor.fetchone()
+ if geneName:
+ snpurl = os.path.join(webqtlConfig.CGIDIR, "main.py?FormID=snpBrowser") + "&geneName=%s" % geneName[0]
+ else:
+ if thisTrait.chr and thisTrait.mb:
+ snpurl = os.path.join(webqtlConfig.CGIDIR, "main.py?FormID=snpBrowser") + \
+ "&chr=%s&start=%2.6f&end=%2.6f" % (thisTrait.chr, thisTrait.mb-0.002, thisTrait.mb+0.002)
+ else:
+ snpurl = ""
+
+ if snpurl:
+ snpBrowser = HT.Input(type="button",value="SNP Browser",onClick= \
+ "openNewWin('%s')" % snpurl, Class="button")
+
+ else:
+ snpBrowser = ""
+ #end if
+
+ heading = HT.Paragraph('Probe Information', Class="title")
+ intro = HT.Paragraph('The table below lists information of all probes of probe set ',HT.Span(self.ProbeSetID, Class="fwb fs13"),' from database ', HT.Span(self.probeDatabase, Class="fwb fs13"), ".")
+ buttons = HT.Paragraph(probedata,probeinfo,heatmap,cormatrix,blatbutton,blatbutton2,verifyButton,snpBrowser, HT.P(),selectall,selectpm,selectmm,selectinvert,reset,addselect)
+ if rudi_track:
+ buttons.append(rudi_track)
+ form.append(buttons,div,HT.P())
+
+ TD_LR.append(heading,intro,form, HT.P())
+ self.dict['basehref'] = ''
+ self.dict['body'] = str(TD_LR)
+ self.dict['title'] = self.db.shortname + ' : ' + self.ProbeSetID +' / Probe Information'
+ # updated by NL, javascript function xmlhttpPost(strURL, div, querystring) and function updatepage(Id, str)
+ # have been moved to dhtml.js
+ self.dict['js1'] = ''
+
+ def nullRecord(self,x):
+ if x or x == 0:
+ return x
+ else:
+ return ""
+
+##########################
+# UCSC Probe track by Ridi Albert
+##########################
+ def convertChipName2Rudi(self, officialName):
+ rudiName = None
+ if officialName == 'Hu6800':
+ rudiName = "ANHuGeneFL"
+ else:
+ rudiName = officialName.replace('_','')
+ rudiName = rudiName.replace('-','')
+ rudiName = "AN%s"%rudiName
+ return rudiName
+
+ def getProbeTrackURL(self, probesetfreeze_id, probeset_id):
+ try:
+ self.cursor.execute('SELECT GeneChip.Name, GeneChip.SpeciesId FROM ProbeFreeze,GeneChip WHERE ProbeFreeze.ChipId = GeneChip.Id and ProbeFreeze.Name = "%s"' % probesetfreeze_id)
+ chipname, species = self.cursor.fetchall()[0]
+ except:
+ return None
+
+ if not species:
+ return None
+
+ chipname_in_url = self.convertChipName2Rudi(chipname)
+ orgs = {1:"mouse", 2:"rat"}
+ dbs = {1:"mm8", 2:"mm6"}
+
+ try:
+ url = webqtlConfig.UCSC_RUDI_TRACK_URL%(orgs[species], dbs[species],chipname_in_url, probeset_id)
+ except:
+ url = ''
+
+ return url
+
+
+ #NL 05-13-2011: get field_names in query
+ def getStrainNameIndexPair(self):
+
+ strainNameIndexPair=[]
+ query ='SELECT * FROM SnpPattern limit 1'
+ self.cursor.execute(query)
+
+ num_fields = len(self.cursor.description)
+ field_names = [i[0] for i in self.cursor.description]
+ strainsNameList=field_names[1:]
+
+ # index for strain name starts from 1
+ for index, name in enumerate(strainsNameList):
+ index=index+1
+ strainNameIndexPair.append((name,index))
+
+ return strainNameIndexPair
+
+
+
diff --git a/web/webqtl/showTrait/ShowTraitPage.py b/web/webqtl/showTrait/ShowTraitPage.py
new file mode 100755
index 00000000..82511228
--- /dev/null
+++ b/web/webqtl/showTrait/ShowTraitPage.py
@@ -0,0 +1,170 @@
+# 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 htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from utility import webqtlUtil
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from DataEditingPage import DataEditingPage
+
+
+
+class ShowTraitPage(DataEditingPage):
+
+ def __init__(self, fd, traitInfos = []):
+
+ templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
+
+ if traitInfos:
+ database,ProbeSetID,CellID = traitInfos
+ else:
+ database = fd.formdata.getfirst('database')
+ ProbeSetID = fd.formdata.getfirst('ProbeSetID')
+ CellID = fd.formdata.getfirst('CellID')
+ try:
+ thisTrait = webqtlTrait(db=database, name=ProbeSetID, cellid= CellID, cursor=self.cursor)
+ except:
+ heading = "Trait Data and Analysis Form"
+ detail = ["The trait isn't available currently."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ if thisTrait.db.type == "ProbeSet":
+
+ self.cursor.execute('''SELECT Id, Name, FullName, confidentiality, AuthorisedUsers
+ FROM ProbeSetFreeze WHERE Name = "%s"''' % database)
+
+ indId, indName, indFullName, confidential, AuthorisedUsers = self.cursor.fetchall()[0]
+
+ if confidential == 1:
+ access_to_confidential_dataset = 0
+
+ #for the dataset that confidentiality is 1
+ #1. 'admin' and 'root' can see all of the dataset
+ #2. 'user' can see the dataset that AuthorisedUsers contains his id(stored in the Id field of User table)
+ if webqtlConfig.USERDICT[self.privilege] > webqtlConfig.USERDICT['user']:
+ access_to_confidential_dataset = 1
+ else:
+ AuthorisedUsersList=AuthorisedUsers.split(',')
+ if AuthorisedUsersList.__contains__(self.userName):
+ access_to_confidential_dataset = 1
+
+ if not access_to_confidential_dataset:
+ #Error, Confidential Database
+ heading = "Show Database"
+ detail = ["The %s database you selected is not open to the public \
+ at this time, please go back and select other database." % indFullName]
+ self.error(heading=heading,detail=detail,error="Confidential Database")
+ return
+
+ user_ip = fd.remote_ip
+ query = "SELECT count(id) FROM AccessLog WHERE ip_address = %s and \
+ UNIX_TIMESTAMP()-UNIX_TIMESTAMP(accesstime)<86400"
+ self.cursor.execute(query,user_ip)
+ daycount = self.cursor.fetchall()
+ if daycount:
+ daycount = daycount[0][0]
+ if daycount > webqtlConfig.DAILYMAXIMUM:
+ heading = "Retrieve Data"
+ detail = ['For security reasons, the maximum access to a database is \
+ %d times per day per ip address. You have reached the limit, please \
+ try it again tomorrow.' % webqtlConfig.DAILYMAXIMUM]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ pass
+ else:
+ pass
+
+ if thisTrait.db.type != 'ProbeSet' and thisTrait.cellid:
+ heading = "Retrieve Data"
+ detail = ['The Record you requested doesn\'t exist!']
+ self.error(heading=heading,detail=detail)
+ return
+
+ #XZ: Aug 23, 2010: I commented out this block because this feature is not used anymore
+ # check if animal information are available
+ """
+ self.cursor.execute('''
+ SELECT
+ SampleXRef.ProbeFreezeId
+ FROM
+ SampleXRef, ProbeSetFreeze
+ WHERE
+ SampleXRef.ProbeFreezeId = ProbeSetFreeze.ProbeFreezeId AND
+ ProbeSetFreeze.Name = "%s"
+ ''' % thisTrait.db.name)
+
+ sampleId = self.cursor.fetchall()
+ if sampleId:
+ thisTrait.strainInfo = 1
+ else:
+ thisTrait.strainInfo = None
+ """
+
+ ##identification, etc.
+ fd.identification = '%s : %s'%(thisTrait.db.shortname,ProbeSetID)
+ thisTrait.returnURL = webqtlConfig.CGIDIR + webqtlConfig.SCRIPTFILE + '?FormID=showDatabase&database=%s\
+ &ProbeSetID=%s&RISet=%s&parentsf1=on' %(database,ProbeSetID,fd.RISet)
+
+ if CellID:
+ fd.identification = '%s/%s'%(fd.identification, CellID)
+ thisTrait.returnURL = '%s&CellID=%s' % (thisTrait.returnURL, CellID)
+
+ #retrieve trait information
+ try:
+ thisTrait.retrieveInfo()
+ thisTrait.retrieveData()
+ self.updMysql()
+ self.cursor.execute("insert into AccessLog(accesstime,ip_address) values(Now(),%s)" ,user_ip)
+ self.openMysql()
+ except:
+ heading = "Retrieve Data"
+ detail = ["The information you requested is not avaiable at this time."]
+ self.error(heading=heading,detail=detail)
+ return
+
+ ##read genotype file
+ fd.RISet = thisTrait.riset
+ fd.readGenotype()
+
+ if webqtlUtil.ListNotNull(map(lambda x:x.var, thisTrait.data.values())):
+ fd.displayVariance = 1
+ fd.varianceDispName = 'SE'
+ fd.formID = 'varianceChoice'
+
+ self.dict['body']= thisTrait
+ DataEditingPage.__init__(self, fd, thisTrait)
+ self.dict['title'] = '%s: Display Trait' % fd.identification
+
+
diff --git a/web/webqtl/showTrait/__init__.py b/web/webqtl/showTrait/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/showTrait/__init__.py
diff --git a/web/webqtl/showTrait/exportPage.py b/web/webqtl/showTrait/exportPage.py
new file mode 100755
index 00000000..ff3f12a1
--- /dev/null
+++ b/web/webqtl/showTrait/exportPage.py
@@ -0,0 +1,141 @@
+import string
+import os
+import re
+import cPickle
+import pyXLWriter as xl
+
+from base import webqtlConfig
+from utility import webqtlUtil
+from base.templatePage import templatePage
+
+class ExportPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ filename = webqtlUtil.genRandStr("Export_")
+ workbook = xl.Writer('%s.xls' % (webqtlConfig.TMPDIR+filename))
+ style_formats = [] #Array with Excel style formats - Zach 9/2/2011
+ heading = workbook.add_format(align = 'center', bold = 1, border = 1, size=13, fg_color = 0x1E, color="white") #Style for the header cells
+ right = workbook.add_format(align = 'right') #Style to align cell contents to the right
+ style_formats.append(heading)
+ style_formats.append(right)
+ worksheet = workbook.add_worksheet()
+
+ primaryStrainNames = fd.formdata.getvalue('strainNames', '').split(',')
+ primaryVals = fd.formdata.getvalue('strainVals', '').split(',')
+ primaryVars = fd.formdata.getvalue('strainVars', '').split(',')
+ otherStrainNames = fd.formdata.getvalue('otherStrainNames', '').split(',')
+ otherVals = fd.formdata.getvalue('otherStrainVals', '').split(',')
+ otherVars = fd.formdata.getvalue('otherStrainVars', '').split(',')
+ attributeData = fd.formdata.getvalue('extra_attributes', '')
+ otherAttributeData = fd.formdata.getvalue('other_extra_attributes', '')
+
+ #ZS: This section is to parse the attribute formdata string
+ attributeTypes = attributeData.split('/')
+ otherAttributeTypes = otherAttributeData.split('/')
+
+ attributeNames = []
+ attributeVals = []
+ for i in range(len(attributeTypes)):
+ if i < len(attributeTypes) - 1:
+ attributeNames.append(attributeTypes[i].split(':')[0])
+ attributeVals.append(attributeTypes[i].split(':')[1].split(','))
+ else:
+ break
+
+ otherAttributeNames = []
+ otherAttributeVals = []
+ for i in range(len(otherAttributeTypes)):
+ if i < len(otherAttributeTypes) - 1:
+ otherAttributeNames.append(otherAttributeTypes[i].split(':')[0])
+ otherAttributeVals.append(otherAttributeTypes[i].split(':')[1].split(','))
+ else:
+ break
+
+ varsExist = 0 #ZS: Even if there are no variances "primaryVars" would still be populated with empty values, so we need to check if there really are any
+ for i in range(len(primaryVars)):
+ if primaryVars[i] != '':
+ varsExist = 1
+ break
+
+ otherStrainsExist = 0 #ZS: Same as above; checking to see if there's a set of "other" (non-primary) strains
+ for i in range(len(otherStrainNames)):
+ if otherStrainNames[i] != '':
+ otherStrainsExist = 1
+ break
+
+ if varsExist == 1:
+ column_headers = ["Sample", "Value", " SE "] #ZS: Names of the header for each column in the excel worksheet
+ else:
+ column_headers = ["Sample", "Value"]
+
+
+ for attr_name in attributeNames:
+ column_headers.append(attr_name)
+
+ start_line = 0 #Gets last line of "primary" strain values to define a start-point for "other" strain values
+ for ncol, item in enumerate(column_headers):
+ worksheet.write([start_line, ncol], item, style_formats[0])
+ worksheet.set_column([ncol, ncol], 2*len(item))
+
+ start_line += 1
+ last_line = start_line
+
+ for i in range(len(primaryStrainNames)):
+ ncol = 0
+ if varsExist == 1:
+ for ncol, item in enumerate([primaryStrainNames[i], primaryVals[i], primaryVars[i]]):
+ worksheet.write([start_line + i, ncol], item, style_formats[1])
+ ncol += 1
+ else:
+ for ncol, item in enumerate([primaryStrainNames[i], primaryVals[i]]):
+ worksheet.write([start_line + i, ncol], item, style_formats[1])
+ ncol += 1
+
+ for attribute_type in attributeVals:
+ worksheet.write([start_line + i, ncol], attribute_type[i], style_formats[1])
+ ncol += 1
+
+ last_line += 1
+
+ if otherStrainsExist == 1:
+ start_line = last_line + 2
+
+ for ncol, item in enumerate(column_headers):
+ worksheet.write([start_line, ncol], item, style_formats[0])
+ worksheet.set_column([ncol, ncol], 2*len(item))
+ start_line += 1
+
+ for i in range(len(otherStrainNames)):
+ ncol = 0
+ if varsExist == 1:
+ for ncol, item in enumerate([otherStrainNames[i], otherVals[i], otherVars[i]]):
+ worksheet.write([start_line + i, ncol], item, style_formats[1])
+ ncol += 1
+ else:
+ for ncol, item in enumerate([otherStrainNames[i], otherVals[i]]):
+ worksheet.write([start_line + i, ncol], item, style_formats[1])
+
+ for attribute_type in otherAttributeVals:
+ worksheet.write([start_line + i, ncol], attribute_type[i], style_formats[1])
+ ncol += 1
+
+ workbook.close()
+
+ full_filename = os.path.join(webqtlConfig.TMPDIR, '%s.xls' % filename)
+ fp = open(full_filename, 'rb')
+ text = fp.read()
+ fp.close()
+
+ self.content_type = 'application/xls'
+ self.content_disposition = 'attachment; filename=%s' % ('%s.xls' % filename)
+ self.attachment = text
+
+
+
+
+
+
+
diff --git a/web/webqtl/showTrait/testTraitPage.py b/web/webqtl/showTrait/testTraitPage.py
new file mode 100755
index 00000000..322bf3dc
--- /dev/null
+++ b/web/webqtl/showTrait/testTraitPage.py
@@ -0,0 +1,36 @@
+# 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.webqtlFormData import webqtlFormData
+from DataEditingPage import DataEditingPage
+
+def testTraitPage():
+ fd = webqtlFormData()
+ fd.Sample()
+ page = DataEditingPage(fd)
+ return page
+
+
diff --git a/web/webqtl/snpBrowser/GeneAnnot.py b/web/webqtl/snpBrowser/GeneAnnot.py
new file mode 100755
index 00000000..5a889253
--- /dev/null
+++ b/web/webqtl/snpBrowser/GeneAnnot.py
@@ -0,0 +1,124 @@
+# 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
+
+#########################################
+# A class for the information of a gene
+# An instance of this will be a gene
+# it is used by GeneListAnnot class
+#########################################
+
+
+class GeneAnnot:
+ geneSymbol = None # Initialize variables
+ txStart = -1
+ txEnd = -1
+ Strand = ''
+ exon_start = []
+ exon_end = []
+ cdsStart = -1
+ cdsEnd = -1
+ def __init__(self, query_result):
+ self.geneSymbol, self.txStart, self.txEnd, self.Strand, exonStart, exonEnd, self.cdsStart, self.cdsEnd = query_result
+ if exonStart and exonEnd:
+ exon_s= exonStart.split(',')
+ exon_e = exonEnd.split(',')
+ self.exon_start = [int(s) for s in exon_s[:-1]]
+ self.exon_end = [int(s) for s in exon_e[:-1]]
+ #debug.appendoutFile("%d %d"%(self.exon_start[0], self.exon_end[0]))
+
+ def matchTranscript(self, pos):
+ ''' 1: cds; 2: 2k upstream; 3: 2k downstream; -1: outside; -2: no data'''
+ locus_type = -1
+ distance = 0
+
+ if (not self.txStart) or (not self.txEnd): # no data
+ locus_type = -2
+ elif (pos >= self.txStart) and (pos <=self.txEnd):
+ locus_type = 1
+ elif (pos <self.txStart) and (pos > self.txStart - 0.002):
+ locus_type = 2
+ distance = self.txStart - pos
+ elif (pos > self.txEnd) and (pos < self.txEnd + 0.002):
+ locus_type = 3
+ distance = pos - self.txEnd
+
+ return [locus_type, distance]
+
+ def matchDomain(self, pos):
+ domain_type = None
+ function = None
+
+ num = len(self.exon_start)
+ if not domain_type: #not UTR
+ bp = pos * 1000000
+ for i in range(0, num):
+ if (bp >= self.exon_start[i]) and (bp <= self.exon_end[i]):
+ num_index = i +1
+ if self.Strand == '-':
+ num_index = num - i
+ domain_type = "Exon %d"% (num_index)
+ if self.cdsStart and self.cdsEnd: # then this site in exon can be UTR or stop codon, given cds
+ if self.Strand == '+':
+ if pos < self.cdsStart:
+ domain_type = "5' UTR"
+ elif pos > self.cdsEnd:
+ domain_type = "3' UTR"
+ elif (pos <= self.cdsEnd) and (pos > self.cdsEnd-0.000003):
+ function = "Stop Codon"
+ elif self.Strand == '-':
+ if pos < self.cdsStart:
+ domain_type = "3' UTR"
+ elif pos > self.cdsEnd:
+ domain_type = "5' UTR"
+ elif (pos >= self.cdsStart) and (pos < self.cdsStart+0.000003):
+ function = "Stop Codon"
+
+ if not domain_type:
+ for j in range (0, len(self.exon_start) -1) : # not the last exon
+ num_index = j +1
+ if self.Strand == '-':
+ num_index = num - j-1
+ if (bp <= self.exon_end[j] + 2) and (bp > self.exon_end[j]) :
+ domain_type = "Intron %d; Splice"% (num_index) #start splice
+
+ if not domain_type:
+ for k in range (1, len(self.exon_start)): # not the first exon
+ num_index = k +1
+ if self.Strand == '-':
+ num_index = num - k -1
+ if (bp >= self.exon_start[k] -2) and (bp < self.exon_start[k]):
+ domain_type = "Intron %d; Splice"% (num_index) # end splice
+
+ if not domain_type:
+ for i in range (1, len(self.exon_start)):
+ num_index = i
+ if self.Strand == '-':
+ num_index = num - i
+ if (bp > self.exon_end[i-1]) and (bp < self.exon_start[i]):
+ domain_type = "Intron %d"%num_index
+
+ return [domain_type, function]
+
diff --git a/web/webqtl/snpBrowser/GeneListAnnot.py b/web/webqtl/snpBrowser/GeneListAnnot.py
new file mode 100755
index 00000000..59941a6a
--- /dev/null
+++ b/web/webqtl/snpBrowser/GeneListAnnot.py
@@ -0,0 +1,90 @@
+# 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
+
+####################################################################
+## Extracting Annotation using GeneList table
+## using transcript start and end, cds start and end
+## and exon starts and ednds
+####################################################################
+
+from base.templatePage import templatePage
+from GeneAnnot import GeneAnnot
+
+
+class GeneListAnnot (templatePage):
+ geneAnnot_list = []
+ def __init__(self, species, chr, start, end, strand):
+ end = "%f"%(float(end)+0.002) # extend a little bit
+ start = "%f"%(float(start)-0.002)
+ query_genelist = '''
+ SELECT GeneSymbol, TxStart, TxEnd, Strand, exonStarts, exonEnds, cdsStart, cdsEnd
+ From GeneList
+ Where SpeciesId=%d and Chromosome="%s"
+ and not (TxStart<%s and TxEnd<%s) and not (TxStart>%s and TxEnd>%s)
+ ''' % (species, chr, start, start, end, end)
+ #debug.printoutFile(query_genelist) # old condition: TxStart<=%s and TxEnd>=%s
+ self.openMysql()
+ self.cursor.execute(query_genelist)
+ gene_results = self.cursor.fetchall();
+ for oneresult in gene_results:
+ oneGeneAnnot = GeneAnnot(oneresult)
+ self.geneAnnot_list.append(oneGeneAnnot)
+
+ def getAnnot4Pos(self, pos):
+ #if not self.geneAnnot_list:
+ # return [None, None, None]
+ annot_gene = None
+ annot_domain = None
+ annot_func = None
+ min_dist = 99999
+ for oneAnnot in self.geneAnnot_list:
+ in_transcript, dist = oneAnnot.matchTranscript(pos)
+ #debug.printoutFile(in_transcript)
+ if in_transcript == 1:
+ annot_gene = oneAnnot.geneSymbol
+ annot_domain, annot_func = oneAnnot.matchDomain(pos)
+ #annot_domain, annot_func = annots
+ min_dist = 0
+ elif in_transcript == 2:
+ # putative promoter
+ if dist < min_dist:
+ annot_gene = oneAnnot.geneSymbol
+ if oneAnnot.Strand == '+':
+ annot_domain = "Intergenic;possible promoter"
+ elif oneAnnot.Strand == '-':
+ annot_domain = "Intergenic;possible terminator"
+ min_dist = dist
+ elif in_transcript == 3:
+ # putative terminator:
+ if dist < min_dist:
+ annot_gene = oneAnnot.geneSymbol
+ if oneAnnot.Strand == '+':
+ annot_domain = "Intergenic;possible terminator"
+ if oneAnnot.Strand == '-':
+ annot_domain = "Intergenic;possible promoter"
+ min_dist = dist
+
+ return [annot_gene, annot_domain, annot_func]
diff --git a/web/webqtl/snpBrowser/__init__.py b/web/webqtl/snpBrowser/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/snpBrowser/__init__.py
diff --git a/web/webqtl/snpBrowser/snpBrowserPage.py b/web/webqtl/snpBrowser/snpBrowserPage.py
new file mode 100755
index 00000000..51132e0d
--- /dev/null
+++ b/web/webqtl/snpBrowser/snpBrowserPage.py
@@ -0,0 +1,1259 @@
+# 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
+
+# FUTURE PLANS:
+# 1. Make the search species independent. Right now, it is fairly hard-coded to work with mouse only. Although it would not be too much trouble to add another species, at the time of writing, we have no
+# variant data for anything except mice, so spending time fixing the code with respect to species independence is unnecessary. However, if you expand on the code, you should keep this in mind.
+# 2. There needs to be some way to display mutliple strains in the InDel browser.
+# 3. We need CNV and Transposon data. This should mostly come from Xusheng, at least for B vs. D, and it should be included in the Variants browser, which may have to either be restructured, or
+# maybe just have columns added to it (if we're lucky).
+
+#Code for the Variant Browser module. It's somewhat commented.
+
+from mod_python import Cookie
+from htmlgen import HTMLgen2 as HT
+
+import string
+import os
+import piddle as pid
+import time
+import pyXLWriter as xl
+from types import ListType
+import re
+import cPickle
+
+#import snpBrowserUtils
+from base import webqtlConfig
+from base.GeneralObject import GeneralObject
+from utility import Plot
+from base.templatePage import templatePage
+#from GeneListAnnot import GeneListAnnot
+from utility import webqtlUtil
+from utility.THCell import THCell
+from utility.TDCell import TDCell
+####################################################################
+## SNP Browser
+## Prints information about every SNP that lies in a specified range
+####################################################################
+
+#get current file path
+current_file_name = __file__
+pathname = os.path.dirname( current_file_name )
+abs_path = os.path.abspath(pathname)
+class snpBrowserPage(templatePage):
+
+ MAXSNPRETURN = 5000 # This can take an awful long time to load. If there are more than 5000 SNPs, then it loads the SNP density graph instead (which is much faster, but doesn't show the exact data).
+ MAXMB = 50 # Clips the graph to (Start Mb through Start+50 Mb) if someone searches for a larger region than that
+ _scriptfile = "main.py?FormID=SnpBrowserResultPage"
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self,fd)
+ if not self.openMysql():
+ return
+
+ self.remote_ip = fd.remote_ip
+ self.formdata = fd.formdata # This is for passing the VARIANT TYPE to the table creation process
+ self.snp_list = None
+ submitStatus = self.formdata.getfirst("submitStatus", "")
+ opt = GeneralObject()
+ self.initializeDisplayParameters(fd,opt)
+ info_line=""
+ snpTable=""
+
+ if submitStatus: # For SnpBrowser result page
+ opt.xls = 1
+ try:
+ # for sortable columns, need to build dict for genTableObj function
+ tblobj = {}
+ filename= webqtlUtil.genRandStr("snpBrowser_")
+ snpMatches, tblobj = self.genSnpTable(opt)
+
+ if snpMatches >0 and snpMatches <=self.MAXSNPRETURN:
+ # creat object for result table for sort function
+ objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+
+ sortby = ("Index", "down")
+ snpTable = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), Id="sortable")
+ else:
+ #updated by NL 07-11-2011: density map can not be cPickled
+ snpTable=tblobj
+
+ # This writes the info at top above the search criteria.
+ strainText = " - among all available strains in the group"
+ info_line = HT.Paragraph("%d %s(s) on Chr %s: %0.6f - %0.6f (Mb, mm9" % (snpMatches, opt.variant,opt.chromosome, opt.startMb, opt.endMb),
+ Class="fs14 fwb ffl black")
+ if self.snp_list:
+ info_line.contents[0]+= ", SNP: %s)" % opt.geneName
+ elif opt.geneName:
+ info_line.contents[0]+= ", Gene: %s)" % opt.geneName
+ else:
+ info_line.contents[0]+= ")"
+ except:
+ heading = "Variant Browser"
+ detail = ["No gene or %s record was found that matches %s." % (opt.variant,opt.geneName)]
+ self.error(heading=heading,detail=detail)
+ return
+ else:
+ opt.use_custom = True
+ opt.diffAlleles=True
+
+ # SnpBrowser default display part
+ info_link = HT.Input(type="button", value="Info", Class="button", onClick="javascript:openNewWin('/snpbrowser.html');")
+ if opt.xslFilename:
+ xlsDownloadButton= HT.Input(type="button", name="submitStatus",value=" Download Table ",onClick= "location.href='/tmp/%s'" % opt.xslFilename, Class='button')
+ title = HT.Paragraph("Variant Browser ", info_link, "&nbsp;&nbsp;",xlsDownloadButton, Class="title")
+ else:
+ title = HT.Paragraph("Variant Browser ", info_link, Class="title")
+ newPaddingForm = self.genBrowserForm(opt)
+ descriptionTable = HT.TableLite(border=0, cellpadding=0, cellspacing=0)
+
+ descriptionTable.append(HT.TR(HT.TD(info_line, colspan=3)),
+ HT.TR(HT.TD("", height="20", colspan=3)),
+ HT.TR(HT.TD(newPaddingForm,Class="doubleBorder", valign="top", colspan=3)),
+ HT.TR(HT.TD("", height="20", colspan=3)),
+ HT.TR(HT.TD(snpTable, colspan=3)))
+
+ self.dict['body'] = HT.TD(title, HT.Blockquote(descriptionTable, HT.P()),valign="top",height="200", width="100%")
+ self.dict['title'] = "Variant Browser"
+ pass
+
+ ################################################################
+ # Initializes all of the snpBrowserPage class parameters,
+ # acquiring most values from the formdata (fd)
+ ################################################################
+ def initializeDisplayParameters(self, fd,opt):
+
+ # COLUMN 1: items in paddingTab1
+ opt.variant = self.formdata.getfirst("variant","SNP")
+ opt.geneName = string.strip(self.formdata.getfirst("geneName", ""))
+ opt.chromosome = self.formdata.getfirst("chr", "19")
+ startMb, endMb =self.initialMb()
+ opt.startMb = startMb
+ opt.endMb = endMb
+ # COLUMN 2: items in paddingTab2
+ opt.allStrainNamesPair = self.getStrainNamePair()
+ opt.allStrainNameList=[v[0] for v in opt.allStrainNamesPair]
+ opt.customStrain = self.formdata.getfirst("customStrain",None)
+ if opt.customStrain:
+ opt.use_custom = True
+ else:
+ opt.use_custom = False
+
+ chosenStrains = self.formdata.getfirst("chosenStrains")
+ strainList=[]
+ # chosen strain selectbox incudes all strains that will be displayed in the search results if the "Limit to" checkbox is checked.
+ # by default, chosen strain selectbox includes 9 strains.
+ # All strains in chosen strain selectbox will be saved into cookie after clicking 'Search' button.
+ # chosen strain selectbox is set as single choice.
+ # The original chosenStrains parameter is string type (chosenStrains = self.formdata.getfirst("chosenStrains")),
+ # then we split it into list if it is not empty ( chosenStrains = list(string.split(chosenStrains,',')) )
+ # Case 1, no item is in selected status in chosen strain selectbox. chosenStrains is None. No converting to list.
+ # Case 2, user might have added one strain into chosen strain selectbox or clicked one item in chosen strain selectbox.
+ # After converting to list type, the chosenStrains list has one item.
+ # Case 3, other classes might have called snpBrowserPage, such as from ProbeInfoPage,the strains will be passed via 'chosenStrains' parameter.
+ # After converting to list type, the chosenStrains list has two items.
+
+ # In case 1 and 2, we will get the chosen strains from cookie or by using default value of 'chosenStrains'.
+ opt.chosenStrains = self.retrieveCustomStrains(fd)
+
+ # in case 3, get strain names from 'chosenStrains' parameter
+ if chosenStrains:
+ if (not (type(chosenStrains) is ListType)):
+ chosenStrains = list(string.split(chosenStrains,','))
+ if len(chosenStrains)>1 :
+ for item in chosenStrains:
+ strainList.append((item,item))
+ opt.chosenStrains=strainList
+
+ opt.diffAlleles =self.formdata.getfirst("diffAlleles", None)
+ if opt.diffAlleles:
+ opt.diffAlleles = True
+ else:
+ opt.diffAlleles = False
+
+ # COLUMN 3: items in paddingTab3
+ opt.domain = self.formdata.getfirst("domain")
+ if opt.domain == None or len(opt.domain) == 0:
+ opt.domain = [""]
+ elif not type(opt.domain) is ListType:
+ opt.domain = [opt.domain]
+ opt.function = self.formdata.getfirst("exonfunction")
+ if opt.function == None or len(opt.function) == 0:
+ opt.function = [""]
+ elif not type(opt.function) is ListType:
+ opt.function = [opt.function]
+
+ opt.chosenSource=self.getSource()
+ opt.source = self.formdata.getfirst("source")
+ if opt.source == None or len(opt.source) == 0:
+ opt.source = [""]
+ elif not type(opt.source) is ListType:
+ opt.source = [opt.source]
+
+ opt.conservationCriteria = self.formdata.getfirst("criteria",">=")
+ opt.score = self.formdata.getfirst("score","0.0")
+ opt.redundant = self.formdata.getfirst("redundant", None)
+ if opt.redundant:
+ opt.redundant_checked = True
+ else:
+ opt.redundant_checked = False
+
+ # initial xsl file name
+ opt.xslFilename=""
+ opt.alleleValueList=[]
+
+ # SnpBrowser page top part
+ def genBrowserForm(self, opt):
+ # COLUMN 1: items in paddingTab1
+ variantSelect = HT.Select(name="variant", Class="typeDropdownWidth",data=[("SNP", "SNP"), ("InDel", "InDel")], selected=[opt.variant])
+ geneBox = HT.Input(type="text", Class="typeDropdownWidth",name="geneName", value=opt.geneName, size="12")
+ selectChrBox = HT.Select(name="chr",Class="typeDropdownWidth", data=[(1,'1'), (2,'2'), (3,'3'), (4,'4'), (5,'5'), (6,'6'), (7,'7'), (8,'8'), (9,'9'), (10,'10'), (11,'11'), (12,'12'), (13,'13'), (14,'14'), (15,'15'), (16,'16'), (17,'17'), (18,'18'), (19,'19'), ('X', 'X')], selected=[opt.chromosome], onChange = "Javascript:this.form.geneName.value=''")
+ mbStartBox = HT.Input(type="text", Class="typeDropdownWidth",name="start", size="10", value=opt.startMb, onChange = "Javascript:this.form.geneName.value=''")
+ mbEndBox = HT.Input(type="text", Class="typeDropdownWidth",name="end", value=opt.endMb, size="10", onChange = "Javascript:this.form.geneName.value=''")
+ submitButton = HT.Input(type="submit", name="submitStatus",value="&nbsp;Search&nbsp;", Class="button")
+
+ # COLUMN 2: items in paddingTab2
+ div4 = HT.Div(Id='menu_s3')
+ strainBox3 = HT.Select(name="s3", data=opt.allStrainNamesPair, Class="customBoxWidth")
+ div4.append(strainBox3)
+ addStrainButton = HT.Input(type="button", value="Add", Class="button", onClick="addToList(this.form.s3.options[this.form.s3.selectedIndex].text, this.form.s3.options[this.form.s3.selectedIndex].value, this.form.chosenStrains); this.form.chosenStrains.selectedIndex++")
+ customStrainBox = HT.Input(type="checkbox", name="customStrain", checked=opt.use_custom, size="100")
+ customStrainSelect = HT.Select(name="chosenStrains",data=opt.chosenStrains, multiple=False, Class="customBoxWidth", size=11)
+ removeStrainButton = HT.Input(type="button", value=" Cut ", Class="button", onClick="removeFromList(this.form.chosenStrains.selectedIndex, this.form.chosenStrains)")
+ diffAlleles = HT.Input(type="checkbox", name="diffAlleles", checked=opt.diffAlleles)
+
+
+ # COLUMN 3: items in paddingTab3
+ domainBox = HT.Select(name="domain", Class="domainDropdownWidth",data=[("All", ""),("Exon","Exon"),("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5' UTR","5' UTR"),
+ ("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Coding Region","Coding"),("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3' UTR","3' UTR"),
+ ("Intron", "Intron"), ("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Splice Site", "Splice Site"),("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nonsplice Site", "Nonsplice Site"),
+ ("Upstream","Upstream"),("Downstream","Downstream"), ("Intergenic","Intergenic")], selected=opt.domain,
+ multiple=True,size=4,onChange = "Javascript:snpbrowser_function_refresh()")
+ functionBox = HT.Select(name="exonfunction", data=[("All", ""),("Nonsynonymous","Nonsynonymous"),("Synonymous","Synonymous"),("Start Gained", "Start Gained"),("Start Lost", "Start Lost"),("Stop Gained", "Stop Gained"),("Stop Lost", "Stop Lost")],
+ selected=opt.function,multiple=True, size=3, Class="domainDropdownWidth",
+ onChange="Javascript:snpbrowser_domain_refresh()")
+ filterBox = HT.Select(name="criteria", data=[(">=", ">="), ("=", "=="), ("<=","<=")], selected=[opt.conservationCriteria])
+ sourceBox = HT.Select(name="source", data=opt.chosenSource, selected=opt.source,Class="domainDropdownWidth")
+ scoreBox = HT.Input(type="text", name="score", value=opt.score, size="5")
+ redundantBox = HT.Input(type="checkbox", name="redundant", checked=opt.redundant_checked)
+
+ # This is where the actual table is structured, and it displays the variables initialized above
+ paddingTable = HT.TableLite(border=0)
+ paddingTab1 = HT.TableLite(border=0)
+ paddingTab2 = HT.TableLite(border=0)
+ paddingTab3 = HT.TableLite(border=0)
+
+ # COLUMN 1
+ paddingTab1.append(
+ HT.TR(HT.TD("Type :", Class="fwb", align="right", NOWRAP=1), HT.TD(variantSelect, NOWRAP=1)),
+ HT.TR(HT.TD("Gene or ID :", Class="fwb", align="right", NOWRAP=1),HT.TD(geneBox, NOWRAP=1)),
+ HT.TR(HT.TD("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Or select", Class="fwb cr", colspan=3, align="LEFT")),
+ HT.TR(HT.TD("Chr :", Class="fwb", align="right", NOWRAP=1), HT.TD(selectChrBox, NOWRAP=1)),HT.TR(HT.TD("Mb :", Class="fwb", align="right", NOWRAP=1), HT.TD(mbStartBox)),
+ HT.TR(HT.TD(HT.Font("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to", size=-1,),HT.TD(mbEndBox, NOWRAP=1))),
+ HT.TR(HT.TD(HT.HR(width="99%"), colspan=3, height=10)),
+ HT.TR(HT.TD(HT.TD(submitButton, NOWRAP=1)))
+ )
+ # COLUMN 2
+ paddingTab2.append(
+ HT.TR(HT.TD("Strains:", Class="fwb", align="right", NOWRAP=1), HT.TD(width=10),HT.TD(div4),HT.TD(addStrainButton)),
+ HT.TR(HT.TD("Limit to:", customStrainBox, Class="fwb cr", align="right", NOWRAP=1),HT.TD(width=0),HT.TD(customStrainSelect),HT.TD(removeStrainButton))
+ )
+ # COLUMN 3
+ paddingTab3.append(
+ HT.TR(HT.TD("Domain:", Class="fwb", align="right", NOWRAP=1),
+ HT.TD(width=10), HT.TD(domainBox, NOWRAP=1)),
+ HT.TR(HT.TD("Function:", Class="fwb", align="right", NOWRAP=1),
+ HT.TD(width=10), HT.TD(functionBox, NOWRAP=1)),
+ HT.TR(HT.TD("Source:", Class="fwb", align="right", NOWRAP=1),
+ HT.TD(width=4), HT.TD(sourceBox, NOWRAP=1)),
+ HT.TR(HT.TD("ConScore:", Class="fwb", align="right", NOWRAP=1),
+ HT.TD(width=4), HT.TD(filterBox, scoreBox, NOWRAP=1)),
+ HT.TR(HT.TD(redundantBox, align="right", NOWRAP=1), HT.TD(width=10), HT.TD("Non-redundant SNP Only", NOWRAP=1)),
+ HT.TR(HT.TD(diffAlleles, align="right", NOWRAP=1),HT.TD(width=10), HT.TD("Different Alleles Only", NOWRAP=1))
+ )
+
+ paddingTable.append(
+ HT.TR(HT.TD(paddingTab1), HT.TD("", width="0"), HT.TD(paddingTab2),HT.TD(width=0), HT.TD(paddingTab3), valign="top")
+ )
+ newPaddingForm = HT.Form(cgi=os.path.join(webqtlConfig.CGIDIR, self._scriptfile), enctype="multipart/form-data", name="newSNPPadding", submit=HT.Input(type="hidden"), onSubmit="Javascript:set_customStrains_cookie();")
+ newPaddingForm.append(paddingTable)
+
+ return newPaddingForm
+
+ # This grabs the data from MySQL for display in the table, allowing different sorting options based on the options chosen by the user.
+ # The base option is what kind of variant the user is looking for; the other options are nested within that base option here.
+ def genSnpTable(self, opt):
+ # Grabs the Gene info, regardless of the variant type searched. This means you can display it for InDels, Snps, Etc.
+ # initialize variables
+ tblobj={} # build dict for genTableObj function; keys include header and body
+ tblobj_header = [] # value of key 'header'
+ tblobj_body=[] # value of key 'body'
+ snpHeaderRow=[] # header row list for tblobj_header (html part)
+ headerList=[] # includes all headers' name except for strain's value
+ strainNameRow=[] # header row list for strain names
+ strainList=[] # includes all strains' value
+ strainNameList0=[]
+ strainNameList=[]
+ geneNameList=[] # for SNP's Gene column
+ geneIdNameDict={}
+ domain2=''
+
+ headerStyle="fs13 fwb ffl b1 cw cbrb"# style of the header
+ cellColorStyle = "fs13 b1 fwn c222" # style of the cells
+
+ if opt.geneName:
+ self.cursor.execute("SELECT geneSymbol, chromosome, txStart, txEnd from GeneList where SpeciesId= 1 and geneSymbol = %s", opt.geneName)
+ result = self.cursor.fetchone()
+ if result:
+ opt.geneName, opt.chromosome, opt.startMb, opt.endMb = result
+ else:
+ # If GeneName doesn't turn up results, then we'll start looking through SnpAll or Variants to check for other search types (e.g. Rs#, SnpName, or InDel Name)
+ if opt.variant == "SNP":
+ if opt.geneName[:2] == 'rs':
+ self.cursor.execute("SELECT Id, Chromosome, Position, Position+0.000001 from SnpAll where Rs = %s", opt.geneName)
+ else:
+ self.cursor.execute("SELECT Id, Chromosome, Position, Position+0.000001 from SnpAll where SpeciesId= 1 and SnpName=%s",opt.geneName)
+ result_snp = self.cursor.fetchall()
+ if result_snp:
+ self.snp_list = [v[0] for v in result_snp]
+ opt.chromosome = result_snp[0][1];
+ opt.startMb = result_snp[0][2]
+ opt.endMb = result_snp[0][3]
+ else:
+ return
+
+ # Searches through indels by the InDel name.
+ elif opt.variant == "InDel":
+ if opt.geneName[0] == 'I':
+ self.cursor.execute("SELECT Id, Chromosome, Mb_start, Mb_end FROM IndelAll WHERE SpeciesId=1 AND Name=%s", opt.geneName)
+ result_snp = self.cursor.fetchall()
+ if result_snp:
+ self.snp_list = [v[0] for v in result_snp]
+ opt.chromosome = result_snp[0][1];
+ opt.startMb = result_snp[0][2]
+ opt.endMb = result_snp[0][3]
+ else:
+ return
+
+ if (opt.variant == "SNP"):
+ #NL 05/13/2010: update query based on new db structure in SnpAll and SnpPattern
+ query1 = """
+ SELECT
+ a.*,b.*
+ from
+ SnpAll a, SnpPattern b
+ where
+ a.SpeciesId = 1 and a.Chromosome = '%s' AND
+ a.Position >= %.6f and a.Position < %.6f AND
+ a.Id = b.SnpId
+ order by a.Position
+ """
+
+ elif (opt.variant == "InDel"):
+ query1 = """
+ SELECT
+ distinct a.Name, a.Chromosome, a.SourceId, a.Mb_start, a.Mb_end, a.Strand, a.Type, a.Size, a.InDelSequence, b.Name
+ from
+ IndelAll a, SnpSource b
+ where
+ a.SpeciesId = '1' and a.Chromosome = '%s' AND
+ a.Mb_start >= %2.6f and a.Mb_start < (%2.6f+.0010) AND
+ b.Id = a.SourceId
+ order by a.Mb_start
+ """
+
+ self.cursor.execute(query1 % (opt.chromosome, opt.startMb, opt.endMb))
+ results_all = self.cursor.fetchall()
+
+ # This executes the query if CHR, MB_START, MB_END are chosen as the search terms and Gene/SNP is not used
+ results = self.filterResults(results_all, opt)
+ # output xls file's name
+ opt.xslFilename = "SNP_Chr%s_%2.6f-%2.6f" % (opt.chromosome, opt.startMb, opt.endMb)
+
+ nnn = len(results)
+ if nnn == 0:
+ return nnn, ""
+ elif nnn > self.MAXSNPRETURN:
+ gifmap=self.snpDensityMap(opt,query1,results_all)
+ #07-28-2011 updated by NL: added info part for snp density map
+ Info="Because the number of results exceeds the limit of 5000, the selected region could not be displayed. "
+ Info2="Please select a smaller region by clicking the rectangle corresponding with its location in the map below."
+ densityMap =HT.Span(Info,HT.BR(),Info2,HT.BR(),HT.BR(),gifmap, HT.Image('/image/'+opt.xslFilename+'.png', border=0, usemap='#SNPImageMap'),Class='fwb fs14')
+
+ return nnn, densityMap
+ else:
+ pass
+
+
+ ##############
+ # Excel file #
+ ##############
+ # This code is for making the excel output file
+ if opt.xls:
+
+ opt.xslFilename += ".xls"
+ # Create a new Excel workbook
+ workbook = xl.Writer(os.path.join(webqtlConfig.TMPDIR, opt.xslFilename))
+ worksheet = workbook.add_worksheet()
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=18, border = 1, border_color="gray")
+ headingStyle = workbook.add_format(align = 'center', bold = 1, size=13, fg_color = 0x1E, color="white", border = 1, border_color="gray")
+ headingStyle2 = workbook.add_format(align = 'center', bold = 1, size=13, fg_color = 0x1E, color="white", rotation = 2, border = 1, border_color="gray")
+ XLSBASECOLORS0 = {"A": "red", "C": 0x18,
+ "T": 0x22, "G": "green",
+ "-": 0x21, "":0x2F}
+ XLSBASECOLORS = {}
+ for key in XLSBASECOLORS0.keys():
+ XLSBASECOLORS[key] = workbook.add_format(align = 'center', size=12, fg_color = XLSBASECOLORS0[key], border = 1, border_color="gray")
+
+ ##Write xls's title Info
+ worksheet.write([0, 0], "GeneNetwork Variant Browser", titleStyle)
+ worksheet.write([1, 0], "%s%s" % (webqtlConfig.PORTADDR, os.path.join(webqtlConfig.CGIDIR, self._scriptfile)))
+ worksheet.write([2, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()))
+ worksheet.write([3, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()))
+ worksheet.write([4, 0], "Search by : %s" % self.remote_ip)
+ if opt.geneName:
+ worksheet.write([5, 0], "Search term : %s" % opt.geneName)
+ else:
+ worksheet.write([5, 0], "view region : Chr %s %2.6f - %2.6f Mb" % (opt.chromosome, opt.startMb, opt.endMb))
+ nTitleRow = 7
+
+ #NL: new way to get header info for each variant
+ # The next line determines which columns HEADERS show up in the table, depending on which Variant is selected to search the table for. This is for the column HEADERS ONLY; not the data displayed (that comes later).
+ if (opt.variant == "SNP"):
+ headerList=['Index','SNP ID','Chr','Mb','Alleles','Source','ConScore','Gene','Transcript','Exon','Domain 1','Domain 2','Function','Details']
+ elif (opt.variant == "InDel"):
+ headerList=['Index','ID','Type','InDel Chr','Mb Start','Mb End','Strand','Size','Sequence','Source']
+
+ if headerList:
+ for ncol, item in enumerate(headerList):
+ if ncol==0:
+ snpHeaderRow.append(THCell(HT.TD(item, Class=headerStyle, valign='bottom',nowrap='ON'),sort=0))
+ elif item=="Details" or item=="Function" :
+ snpHeaderRow.append(THCell(HT.TD(HT.Href(text = HT.Span(item, HT.Sup(' ?', style="color:#f00"),Class=headerStyle),
+ target = '_blank',url = "/snpbrowser.html#%s"%item),
+ Class=headerStyle, valign='bottom',nowrap='ON'), text=item, idx=ncol))
+ else:
+ snpHeaderRow.append(THCell(HT.TD(item, Class=headerStyle, valign='bottom',nowrap='ON'),text=item, idx=ncol))
+ #excel file for table headers' names
+ worksheet.write([nTitleRow, ncol], item, headingStyle)
+
+ # This writes the strain column names for the SNPs. The other variants only have data for C57BL6 and DBA2J, so they don't need this information.
+ if (opt.variant == "SNP"):
+ if opt.customStrain:
+ strainNameList = [v for v in opt.chosenStrains]
+ strainNameList = filter((lambda x: x[0]>=0),strainNameList)
+ else:
+ strainNameList=opt.allStrainNamesPair
+
+ for j, item in enumerate(strainNameList):
+ _contents = []
+ for char in item[0]:
+ _contents += [char, HT.BR()]
+
+ if j % 5 == 0:
+ strainNameRow.append(THCell(HT.TD(contents =_contents, Class="fs12 fwn ffl b1 cw cbrb", width=2, align="Center", valign="bottom", style="border-left:2px solid black"),sort=0))
+ else:
+ strainNameRow.append(THCell(HT.TD(contents =_contents, Class="fs12 fwn ffl b1 cw cbrb", width=2, align="Center", valign="bottom"),sort=0))
+
+ #excel file
+ ncol += 1
+ worksheet.write([nTitleRow, ncol], item[0], headingStyle2)
+ worksheet.set_column([ncol, ncol], 3)
+
+ snpHeaderRow.extend(strainNameRow)
+
+ tblobj_header.append(snpHeaderRow)
+ tblobj['header']=tblobj_header
+
+ #Changes text color of SNP label background. The colors here (e.g. cbgdull) are defined in ../css/general.css
+ BASECOLORS = {"A": "cbrdull", "C": "cbbdull", "T": "cbydull", "G": "cbgdull", "-": "cbpdull", "":"cbccc","t": "cbg22t", "c": "cbg22c", "a": "cbg22a", "g": "cbg22g"}
+
+ # # Code for determining if SNPs are identical (if the location of one SNP is the same as the SNP after it)
+ try:
+ self.cursor.execute(query1 % (opt.chromosome, 0, opt.startMb) + " desc limit 1")
+ firstMb = self.cursor.fetchone()
+ except:
+ firstMb =0
+
+ if firstMb:
+ lastMb = firstMb[5]
+ else:
+ lastMb = 0
+
+ # get geneId Name pair for SNP result
+ if opt.variant == "SNP":
+ for item in results:
+ if item[5]:
+ geneName=item[5][1]
+ # eliminate the duplicate geneName
+ if geneName and (geneName not in geneNameList):
+ geneNameList.append(geneName)
+ if len(geneNameList)>0:
+ geneIdNameDict=self.getGeneIdNameDict(geneNameList)
+
+ # This pulls out the 'results' variable and splits it into the sequence of results.
+ for seq, result in enumerate(results):
+ result = list(result)
+
+ if opt.variant == "SNP":
+ SnpName, Rs, Chromosome, Mb, Alleles, gene, transcript, exon, domainList, function, functionDetails,SnpSource,ConScore,SnpId = result[:14]
+ strainNameList=result[14:]
+ #if domain is intergenic, there's no gene, transcript,exon,function,functionDetails info
+ if Rs:
+ SnpHref = HT.Href(text=Rs, url=webqtlConfig.DBSNP % (Rs), target="_blank")
+ SnpName = Rs
+ else:
+ startBp=int(Mb*1000000 -100)
+ endBp=int(Mb*1000000 +100)
+ positionInfo="chr%s:%d-%d"%(Chromosome,startBp,endBp)
+ SnpHref = HT.Href(text=SnpName,url=webqtlConfig.GENOMEBROWSER_URL % (positionInfo), Class="fs12 fwn",target="_blank")
+
+ Mb=float(Mb)
+ MbFormatted = "%2.6f" % Mb
+
+ if SnpSource=='Sanger/UCLA':
+ sourceURL1="http://www.sanger.ac.uk/resources/mouse/genomes/"
+ sourceURL2="http://mouse.cs.ucla.edu/mousehapmap/beta/wellcome.html"
+ SnpSourceLink=HT.Href(text="Sanger", url=sourceURL1, Class="fs12 fwn",target="_blank")
+ SnpSourceLink1= HT.Href(text="UCLA", url=sourceURL2, Class="fs12 fwn",target="_blank")
+ else:
+ SnpSourceLink=""
+
+ if not ConScore:
+ ConScore=''
+
+ if gene:
+ geneName=gene[1]
+ # if geneName has related geneId, then use geneId for NCBI search
+ if geneIdNameDict.has_key(geneName) and geneIdNameDict[geneName]:
+ geneId=geneIdNameDict[gene[1]]
+ ncbiUrl = HT.Href(text="NCBI",target='_blank',url=webqtlConfig.NCBI_LOCUSID % geneId, Class="fs10 fwn")
+ else:# if geneName can not find related geneId, then use geneName for NCBI search
+ ncbiUrl = HT.Href(text="NCBI",target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % geneName, Class="fs10 fwn")
+
+ #GN similar trait link
+ _Species="mouse"
+ similarTraitUrl = "%s?cmd=sch&gene=%s&alias=1&species=%s" % (os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), geneName, _Species)
+ gnUrl = HT.Href(text="GN",target='_blank',url=similarTraitUrl, Class="fs10 fwn")
+ else:
+ geneName=''
+ ncbiUrl=''
+ gnUrl=''
+
+ if geneName:
+ geneNameCol=HT.TD(HT.Italic(geneName), HT.BR(),gnUrl,"&nbsp;|&nbsp;", ncbiUrl, Class=cellColorStyle,nowrap='ON')
+ else:
+ geneNameCol=HT.TD(Class=cellColorStyle,nowrap='ON')
+
+ if transcript:
+ transcriptHref=HT.Href(text=transcript, url=webqtlConfig.ENSEMBLETRANSCRIPT_URL % (transcript), Class="fs12 fwn",target="_blank")
+ else:
+ transcriptHref=transcript
+
+ if exon:
+ exon=exon[1]#exon[0] is exonId;exon[1] is exonRank
+ else:
+ exon=''
+
+ if domainList:
+ domain=domainList[0]
+ domain2=domainList[1]
+ if domain=='Exon':
+ domain=domain+" "+exon
+
+
+ funcList=[]
+ if functionDetails:
+ funcList=string.split(string.strip(functionDetails),',')
+ funcList=map(string.strip,funcList)
+ funcList[0]=funcList[0].title()
+ functionDetails=', '.join(item for item in funcList)
+ functionDetails=functionDetails.replace("_", " ");
+ functionDetails=functionDetails.replace("/", " -> ");
+ if functionDetails=="Biotype: Protein Coding":
+ functionDetails =functionDetails+", Coding Region Unknown"
+
+ # build SnpRow for SNP basic information\
+ SnpRow=[]
+ # first column of table
+ SnpRow.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="index",value=seq+1, onClick="highlight(this)"), align='right',Class=cellColorStyle,nowrap='ON'),text=seq+1))
+ SnpRow.append(TDCell(HT.TD(SnpHref, Class=cellColorStyle,nowrap='ON'),SnpName, SnpName))
+ SnpRow.append(TDCell(HT.TD(Chromosome, Class=cellColorStyle, align="center",nowrap='ON'),Chromosome, Chromosome))
+ SnpRow.append(TDCell(HT.TD(MbFormatted, Class=cellColorStyle, align="center",nowrap='ON'),MbFormatted, MbFormatted))
+ SnpRow.append(TDCell(HT.TD(Alleles, Class=cellColorStyle, align="center",nowrap='ON'),Alleles, Alleles))
+ if SnpSource=='Sanger/UCLA':
+ SnpRow.append(TDCell(HT.TD(SnpSourceLink,'/',SnpSourceLink1, Class=cellColorStyle,nowrap='ON'),SnpSource, SnpSource))
+ else:
+ SnpRow.append(TDCell(HT.TD(SnpSource, Class=cellColorStyle,nowrap='ON'),SnpSource, SnpSource))
+
+
+ SnpRow.append(TDCell(HT.TD(ConScore, Class=cellColorStyle,align="center",nowrap='ON'),ConScore, ConScore))
+ SnpRow.append(TDCell(geneNameCol,geneName, geneName))
+ SnpRow.append(TDCell(HT.TD(transcriptHref, Class=cellColorStyle,nowrap='ON'),transcript, transcript))
+ SnpRow.append(TDCell(HT.TD(exon, Class=cellColorStyle,align="center",nowrap='ON'),exon, exon))
+ SnpRow.append(TDCell(HT.TD(domain, Class=cellColorStyle, align="center",nowrap='ON'),domain, domain))
+ SnpRow.append(TDCell(HT.TD(domain2, Class=cellColorStyle, align="center",nowrap='ON'),domain2, domain2))
+ SnpRow.append(TDCell(HT.TD(function, Class=cellColorStyle,nowrap='ON'),function, function))
+ SnpRow.append(TDCell(HT.TD(functionDetails, Class=cellColorStyle,nowrap='ON'),functionDetails, functionDetails))
+
+ # excel file
+ worksheet.write([nTitleRow+seq+1, 0], seq+1)
+ worksheet.write([nTitleRow+seq+1, 1], SnpName)
+ worksheet.write([nTitleRow+seq+1, 2], Chromosome)
+ worksheet.write([nTitleRow+seq+1, 3], MbFormatted)
+ worksheet.write([nTitleRow+seq+1, 4], Alleles)
+ worksheet.write([nTitleRow+seq+1, 5], SnpSource)
+ worksheet.write([nTitleRow+seq+1, 6], ConScore)
+ worksheet.write([nTitleRow+seq+1, 7], geneName)
+ worksheet.write([nTitleRow+seq+1, 8], transcript)
+ worksheet.write([nTitleRow+seq+1, 9], exon)
+ worksheet.write([nTitleRow+seq+1, 10], domain)
+ worksheet.write([nTitleRow+seq+1, 11], domain2)
+ worksheet.write([nTitleRow+seq+1, 12], function)
+ worksheet.write([nTitleRow+seq+1, 13], functionDetails)
+ #ncol here should be the last ncol + 1
+ ncol = 14
+
+ # This puts the Allele data into the table if SNP is selected
+ BASE=""
+ bcolor = 'fs13 b1 cbw c222'
+ for j , item in enumerate(strainNameList):
+ if item:
+ BASE =item
+ bcolor = BASECOLORS[BASE] + " b1"
+ else:
+ BASE = ""
+ bcolor = 'fs13 b1 cbeee c222' #This changes text color of SNPs
+
+ if j % 5 == 0:
+ SnpRow.append(TDCell(HT.TD(BASE, Class=bcolor, align="center", style="border-left:2px solid black"),BASE,BASE))
+ else:
+ SnpRow.append(TDCell(HT.TD(BASE, Class=bcolor, align="center"),BASE,BASE))
+
+ # #excel for strains' value
+ if BASE in XLSBASECOLORS.keys():
+ xbcolor = XLSBASECOLORS[BASE]
+ else:
+ xbcolor = XLSBASECOLORS[""]
+ worksheet.write([nTitleRow+seq+1, ncol], BASE, xbcolor)
+ ncol += 1
+
+ tblobj_body.append(SnpRow)
+ lastMb = Mb
+
+ elif opt.variant == "InDel":
+ indelName, indelChr, indelMb_s, indelMb_e, indelStrand, indelType, indelSize, indelSequence, sourceName = result
+
+ # build SnpRow for Indel basic information\
+ SnpRow=[]
+ # first column of table
+ SnpRow.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="index",value=seq+1, onClick="highlight(this)"), align='right',Class=cellColorStyle,nowrap='ON'),text=seq+1))
+ SnpRow.append(TDCell(HT.TD(indelName, Class=cellColorStyle,nowrap='ON'),indelName, indelName))# Name of the InDel (e.g. Indel_1350)
+ SnpRow.append(TDCell(HT.TD(indelType, Class=cellColorStyle, align="center",nowrap='ON'),indelType, indelType))# E.g. Insertion or Deletion
+ SnpRow.append(TDCell(HT.TD(indelChr, Class=cellColorStyle, align="center",nowrap='ON'),indelChr, indelChr))# Indel Chromosome (e.g. 1)
+ SnpRow.append(TDCell(HT.TD(indelMb_s, Class=cellColorStyle, align="center",nowrap='ON'),indelMb_s, indelMb_s))
+ SnpRow.append(TDCell(HT.TD(indelMb_e, Class=cellColorStyle, align="center",nowrap='ON'),indelMb_e, indelMb_e))
+ SnpRow.append(TDCell(HT.TD(indelStrand, Class=cellColorStyle, align="center",nowrap='ON'),indelStrand, indelStrand))
+ SnpRow.append(TDCell(HT.TD(indelSize, Class=cellColorStyle,align="center",nowrap='ON'),indelSize, indelSize))
+ SnpRow.append(TDCell(HT.TD(indelSequence, Class=cellColorStyle,align="center",nowrap='ON'),indelSequence, indelSequence))
+ SnpRow.append(TDCell(HT.TD(sourceName, Class=cellColorStyle,nowrap='ON'),sourceName, sourceName))
+
+ if opt.xls:
+ worksheet.write([nTitleRow+seq+1,0], seq+1)
+ worksheet.write([nTitleRow+seq+1,1], indelName)
+ worksheet.write([nTitleRow+seq+1,2], indelType)
+ worksheet.write([nTitleRow+seq+1,3], indelChr)
+ worksheet.write([nTitleRow+seq+1,4], indelMb_s)
+ worksheet.write([nTitleRow+seq+1,5], indelMb_e)
+ worksheet.write([nTitleRow+seq+1,6], indelStrand)
+ worksheet.write([nTitleRow+seq+1,7], indelSize)
+ worksheet.write([nTitleRow+seq+1,8], indelSequence)
+ worksheet.write([nTitleRow+seq+1,9], sourceName)
+
+ tblobj_body.append(SnpRow)
+ else:
+ pass
+
+
+ tblobj['body']=tblobj_body
+ workbook.close() # close here is important, otherwise xls file will not be generated
+
+ return len(results), tblobj
+
+ # initialize the value of start Mb and end Mb
+ def initialMb(self):
+ try:
+ startMb = abs(float(self.formdata.getfirst("start", "30.1")))
+ endMb = abs(float(self.formdata.getfirst("end", "30.12")))
+ except:
+ startMb = endMb = 30.0
+
+ if startMb > endMb:
+ temp = endMb
+ endMb = startMb
+ startMb = temp
+ if startMb == endMb:
+ endMb = startMb + 2 # DO NOT MAKE THIS LESS THAN 2 MB. YOU WILL BREAK EVERYTHING BECAUSE NO DEFAULT VARIANT IS SELECTED
+
+ if endMb - startMb > self.MAXMB:
+ endMb = self.MAXMB + startMb
+
+ return startMb,endMb
+
+ # get customStrains from cookie
+ def retrieveCustomStrains(self,fd):
+ cookie = fd.cookies
+
+ custom_strains = []
+ if cookie.has_key('customstrains1') and cookie['customstrains1']:
+ strain_cookie = cookie['customstrains1']
+ alloptions = string.split(strain_cookie,',')
+ for one in alloptions:
+ sname_value = string.split(one,':')
+ if len(sname_value) == 2:
+ custom_strains.append( (sname_value[0],sname_value[0]))
+ else:
+ custom_strains=[('C57BL/6J', 'C57BL/6J'),('DBA/2J','DBA/2J'),('A/J','A/J'),('129S1/SvImJ','129S1/SvImJ'),('NOD/ShiLtJ','NOD/ShiLtJ'),('NZO/HlLtJ','NZO/HlLtJ'),('WSB/EiJ','WSB/EiJ'),('PWK/PhJ','PWK/PhJ'),('CAST/EiJ','CAST/EiJ')]
+
+ return custom_strains
+
+ # get geneId Name pair, key is geneName, value is geneId
+ def getGeneIdNameDict(self, geneNameList):
+ geneIdNameDict={}
+ if len(geneNameList)==0:
+ return ""
+ geneNameStrList =["'"+geneName+"'" for geneName in geneNameList]
+ geneNameStr=string.join(geneNameStrList,',')
+
+ query = """
+ SELECT geneId, geneSymbol from GeneList
+ where SpeciesId=1 and geneSymbol in (%s)
+ """ % geneNameStr
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+
+ if len(results)>0:
+ for item in results:
+ geneIdNameDict[item[1]]=item[0]
+ else:
+ pass
+
+ return geneIdNameDict
+
+ # This grabs the mySQL query results and filters them for use when SNP Variants are searched for.
+ def filterResults(self, results, opt):
+
+ filtered = []
+ strainIdexList=[]
+ last_mb = -1
+
+ if opt.customStrain and opt.chosenStrains:
+ for item in opt.chosenStrains:
+ index =opt.allStrainNameList.index(item[0])
+ strainIdexList.append(index)
+
+ for seq, result in enumerate(results):
+ result = list(result)
+
+ if opt.variant == "SNP":
+ displayStains=[]
+ # The order of variables here is the order they are selected from in genSnpTable
+ SnpId,SpeciesId,SnpName, Rs, Chromosome, Mb, Alleles, SnpSource,ConservationScore = result[:9]
+
+ effct =result[9:25]
+ #result[25] is SnpId;
+ opt.alleleValueList =result[26:]
+
+ if opt.customStrain and opt.chosenStrains:
+ for index in strainIdexList:
+ displayStains.append(result[26+index])
+ opt.alleleValueList =displayStains
+
+ effectInfoDict=self.getEffectInfo(effct)
+ codingDomainList=['Start Gained','Start Lost','Stop Gained','Stop Lost','Nonsynonymous','Synonymous']
+ intronDomainList=['Splice Site','Nonsplice Site']
+
+
+ for key in effectInfoDict:
+ if key in codingDomainList:
+ domain=['Exon','Coding']
+ elif key in ['3\' UTR','5\' UTR']:
+ domain=['Exon',key]
+ elif key in ['Unknown Effect In Exon']:
+ domain=['Exon','']
+ elif key in intronDomainList:
+ domain=['Intron',key]
+ else:
+ domain =[key,'']
+
+ if 'Intergenic' in domain:
+ gene=''
+ transcript=''
+ exon=''
+ function=''
+ functionDetails=''
+
+ if not opt.redundant or last_mb != Mb: # filter redundant or not
+ if self.filterIn(domain, function,SnpSource, ConservationScore,opt):
+ generalInfoList =[SnpName, Rs, Chromosome, Mb, Alleles, gene,transcript,exon,domain,function,functionDetails,SnpSource,ConservationScore,SnpId]
+ generalInfoList.extend(opt.alleleValueList)
+ filtered.append(generalInfoList)
+ last_mb = Mb
+ else:
+ geneList,transcriptList,exonList,functionList,functionDetailsList=effectInfoDict[key]
+ for index, item in enumerate(geneList):
+ gene=item
+ transcript=transcriptList[index]
+ if exonList:
+ exon=exonList[index]
+ else:
+ exon=""
+
+ if functionList:
+ function=functionList[index]
+ if function=='Unknown Effect In Exon':
+ function="Unknown"
+ else:
+ function=""
+
+ if functionDetailsList:
+ functionDetails='Biotype: '+functionDetailsList[index]
+ else:
+ functionDetails=""
+
+ if not opt.redundant or last_mb != Mb: # filter redundant or not
+ if self.filterIn(domain, function,SnpSource, ConservationScore,opt):
+ generalInfoList =[SnpName, Rs, Chromosome, Mb, Alleles, gene,transcript,exon,domain,function,functionDetails,SnpSource,ConservationScore,SnpId]
+ generalInfoList.extend(opt.alleleValueList)
+ filtered.append(generalInfoList)
+ last_mb = Mb
+
+
+ elif opt.variant =="InDel":
+ # The ORDER of variables here IS IMPORTANT.
+ # THIS IS FOR ANYTHING YOU BRING OUT OF THE VARIANT TABLE USING InDel
+ indelName, indelChr, sourceId, indelMb_s, indelMb_e, indelStrand, indelType, indelSize, indelSequence, sourceName = result
+
+ indelType=indelType.title()
+ if not opt.redundant or last_mb != indelMb_s: # filter redundant or not
+ gene = "No Gene"
+ domain = ConservationScore = SnpId = SnpName = Rs = flank3 =flank5 = ncbi =function = ''
+ if self.filterIn(domain, function,sourceName , ConservationScore, opt):
+ filtered.append([indelName, indelChr, indelMb_s, indelMb_e, indelStrand, indelType, indelSize, indelSequence, sourceName])
+ last_mb = indelMb_s
+ else:
+ filtered.append(result)
+
+ return filtered
+
+ # decide whether need to add this record or not
+ def filterIn(self, domain, function, SnpSource,ConservationScore,opt):
+ domainSatisfied = True
+ functionSatisfied = True
+ differentAllelesSatisfied = True
+ sourceSatisfied= True
+
+ if domain:
+ if len(domain) == 0:
+ if opt.domain[0] != "": # unknown and not searching for "All"
+ domainSatisfied = False #True
+ else:
+ domainSatisfied = False
+ for onechoice in opt.domain:
+ if domain[0].startswith(onechoice) or domain[1].startswith(onechoice):
+ domainSatisfied = True
+ else:
+ if opt.domain[0] != "": # when the info is unknown but the users is not searching for "All"
+ domainSatisfied = False
+
+ if SnpSource:
+ if len(SnpSource) ==0: # not available
+ if len(opt.source[0]) > 0: # and not searching for "All"
+ sourceSatisfied = False #True
+ else:
+ sourceSatisfied = False
+ for choice in opt.source:
+ if SnpSource.startswith(choice):
+ sourceSatisfied = True
+ else:
+ if len(opt.source[0]) > 0: # when the source is unknown but the users is not searching for "All"
+ sourceSatisfied = False
+
+ if function:
+ if len(function) ==0: # not available
+ if len(opt.function[0]) > 0: # and not searching for "All"
+ functionSatisfied = False #True
+ else:
+ functionSatisfied = False
+ for choice in opt.function:
+ if function.startswith(choice):
+ functionSatisfied = True
+ else:
+ if len(opt.function[0]) > 0: # when the function is unknown but the users is not searching for "All"
+ functionSatisfied = False
+
+
+ if ConservationScore:
+ con_score = float(ConservationScore)
+ if len(opt.score) > 0:
+ opt_score_float = float(opt.score)
+ else:
+ opt_score_float = 0.0
+ if opt.conservationCriteria == '>=':
+ if con_score >= opt_score_float:
+ scoreSatisfied = True
+ else:
+ scoreSatisfied = False
+ elif opt.conservationCriteria == '==':
+ if con_score == opt_score_float:
+ scoreSatisfied = True
+ else:
+ scoreSatisfied = False
+ elif opt.conservationCriteria == '<=':
+ if con_score <= opt_score_float:
+ scoreSatisfied = True
+ else:
+ scoreSatisfied = False
+ else:
+ if float(opt.score)>0:
+ scoreSatisfied = False
+ else:
+ scoreSatisfied = True # allow null value
+
+ # when diffAlleles function has been chose;
+ # decide whether need to show this record based on strains' allele value
+ if opt.variant == "SNP" and opt.diffAlleles:
+ totalCount =0
+ aList=[]
+
+ for x in opt.alleleValueList:
+ if x and (x.lower() not in aList) and ( x != "-"):
+ aList.append(x.lower())
+
+ totalCount= len(aList)
+ if totalCount <= 1:
+ differentAllelesSatisfied= False
+ else:
+ differentAllelesSatisfied= True
+ else:
+ differentAllelesSatisfied = True
+
+ return domainSatisfied and functionSatisfied and sourceSatisfied and scoreSatisfied and differentAllelesSatisfied
+
+ #snpDensityMap will display when the max return is greater than default value
+ # pay attention to the order of drawing canvas, the latter one will overlap the former one
+ def snpDensityMap(self,opt,query,results):
+
+ snpCanvas = pid.PILCanvas(size=(900,200))
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = (30, 30, 40, 50)
+ cWidth = snpCanvas.size[0]
+ cHeight = snpCanvas.size[1]
+ plotWidth = cWidth - xLeftOffset - xRightOffset
+ plotHeight = cHeight - yTopOffset - yBottomOffset
+ yZero = yTopOffset + plotHeight/2
+
+ plotXScale = plotWidth/(opt.endMb - opt.startMb)
+
+ #draw clickable map
+ #Image map
+ gifmap = HT.Map(name='SNPImageMap')
+ NCLICK = 80.0
+ clickStep = plotWidth/NCLICK
+ clickMbStep = (opt.endMb - opt.startMb)/NCLICK
+
+ for i in range(NCLICK):
+ #updated by NL 07-11-2011: change the parameters to make clickable function work properly.
+ HREF = os.path.join(webqtlConfig.CGIDIR, "%s&submitStatus=1&diffAlleles=True&customStrain=True"%self._scriptfile) + \
+ "&chr=%s&start=%2.6f&end=%2.6f" % (opt.chromosome, opt.startMb+i*clickMbStep, opt.startMb+(i+1)*clickMbStep)
+
+ COORDS0 = (xLeftOffset+i*clickStep, yTopOffset-18, xLeftOffset+(i+1)*clickStep-2, yTopOffset+plotHeight)
+ snpCanvas.drawRect(COORDS0[0],COORDS0[1],COORDS0[2],COORDS0[3], edgeColor=pid.white)
+ COORDS0 = "%d,%d,%d,%d" % COORDS0
+ Areas1 = HT.Area(shape='rect',coords=COORDS0,href=HREF)
+ gifmap.areas.append(Areas1)
+
+ COORDS = (xLeftOffset+i*clickStep, yTopOffset-18, xLeftOffset+(i+1)*clickStep-2, yTopOffset-10)
+ snpCanvas.drawRect(COORDS[0],COORDS[1],COORDS[2],COORDS[3]+5, edgeColor=pid.wheat, fillColor=pid.wheat)
+ COORDS = "%d,%d,%d,%d" % COORDS
+
+ Areas = HT.Area(shape='rect',coords=COORDS)
+
+ gifmap.areas.append(Areas)
+
+ snpCanvas.drawString("Click to view the corresponding section of the SNP map",
+ xLeftOffset, yTopOffset-25, font=pid.Font(ttf="verdana", size=14, bold=0), color=pid.black)
+
+
+ ###draw SNPs
+ snpCounts = []
+ stepMb = 1.0/plotXScale
+ startMb = opt.startMb
+
+ for i in range(plotWidth):
+
+ self.cursor.execute(query % (opt.chromosome, startMb, startMb + stepMb))
+ snpCounts.append(len(self.cursor.fetchall()))
+ startMb += stepMb
+
+ maxCounts = max(snpCounts)
+ sfactor = plotHeight/(2.0*maxCounts)
+ for i in range(plotWidth):
+ sheight = sfactor*snpCounts[i]
+ snpCanvas.drawLine(i+xLeftOffset, yZero-sheight, i+xLeftOffset, yZero+sheight, color = pid.orange)
+
+ ###draw X axis
+ snpCanvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.black)
+
+ XScale = Plot.detScale(opt.startMb, opt.endMb)
+ XStart, XEnd, XStep = XScale
+ if XStep < 8:
+ XStep *= 2
+ spacingAmtX = spacingAmt = (XEnd-XStart)/XStep
+ j = 0
+ while abs(spacingAmtX -int(spacingAmtX)) >= spacingAmtX/100.0 and j < 6:
+ j += 1
+ spacingAmtX *= 10
+ formatStr = '%%2.%df' % j
+
+ MBLabelFont = pid.Font(ttf="verdana", size=12, bold=0)
+ NUM_MINOR_TICKS = 5
+ xMinorTickHeight = 4
+ xMajorTickHeight = 5
+ for counter, _Mb in enumerate(Plot.frange(XStart, XEnd, spacingAmt / NUM_MINOR_TICKS)):
+ if _Mb < opt.startMb or _Mb > opt.endMb:
+ continue
+ Xc = xLeftOffset + plotXScale*(_Mb - opt.startMb)
+ if counter % NUM_MINOR_TICKS == 0: # Draw a MAJOR mark, not just a minor tick mark
+ snpCanvas.drawLine(Xc, yZero, Xc, yZero+xMajorTickHeight, width=2, color=pid.black) # Draw the MAJOR tick mark
+ labelStr = str(formatStr % _Mb) # What Mbase location to put on the label
+ strWidth = snpCanvas.stringWidth(labelStr, font=MBLabelFont)
+ drawStringXc = (Xc - (strWidth / 2.0))
+ snpCanvas.drawString(labelStr, drawStringXc, yZero +20, font=MBLabelFont, angle=0, color=pid.black)
+ else:
+ snpCanvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=pid.black) # Draw the MINOR tick mark
+ # end else
+
+ xLabelFont = pid.Font(ttf="verdana", size=20, bold=0)
+ xLabel = "SNP Density Map : Chr%s %2.6f-%2.6f Mb" % (opt.chromosome, opt.startMb, opt.endMb)
+ snpCanvas.drawString(xLabel, xLeftOffset + (plotWidth -snpCanvas.stringWidth(xLabel, font=xLabelFont))/2,
+ yTopOffset +plotHeight +30, font=xLabelFont, color=pid.black)
+
+ snpCanvas.save(os.path.join(webqtlConfig.IMGDIR, opt.xslFilename), format='png')
+ return gifmap
+
+
+ #NL 05-13-2011: rewrite to get field_names in query
+ def getStrainNamePair(self):
+ # add by NL ^-^ 05-13/2011
+ # get field_names in query
+ strainNamePair=[]
+ query ='SELECT * FROM SnpPattern limit 1'
+ self.cursor.execute(query)
+
+ num_fields = len(self.cursor.description)
+ field_names = [i[0] for i in self.cursor.description]
+ strainsNameList=field_names[1:]
+
+ # index for strain name starts from 1
+ for index, name in enumerate(strainsNameList):
+ strainNamePair.append((name,name))
+
+ return strainNamePair
+
+ def getEffectDetailsByCategory(self, effectName=None, effectValue=None):
+ geneList=[]
+ transcriptList=[]
+ exonList=[]
+ funcList=[]
+ funcDetailList=[]
+ tmpList=[]
+
+ geneGroupList =['Upstream','Downstream','Splice Site','Nonsplice Site','3\' UTR']
+ biotypeGroupList=['Unknown Effect In Exon','Start Gained','Start Lost','Stop Gained','Stop Lost','Nonsynonymous','Synonymous']
+ newCodonGroupList=['Start Gained']
+ codonEffectGroupList=['Start Lost','Stop Gained','Stop Lost','Nonsynonymous','Synonymous']
+
+ # split data in effect by using '|' into groups
+ effectDetailList = string.split(string.strip(effectValue),'|')
+ effectDetailList = map(string.strip, effectDetailList)
+
+ # if there are more than one group of data, then traversing each group and retrieve each item in the group
+ for index, item in enumerate(effectDetailList):
+ itemList =string.split(string.strip(item),',')
+ itemList = map(string.strip, itemList)
+
+ geneId=itemList[0]
+ geneName=itemList[1]
+ geneList.append([geneId,geneName])
+ transcriptList.append(itemList[2])
+
+ if effectName not in geneGroupList:
+ exonId=itemList[3]
+ exonRank=itemList[4]
+ exonList.append([exonId,exonRank])
+
+ if effectName in biotypeGroupList:
+ biotype=itemList[5]
+ funcList.append(effectName)
+
+ if effectName in newCodonGroupList:
+ newCodon=itemList[6]
+ tmpList=[biotype,newCodon]
+ funcDetailList.append(string.join(tmpList, ", "))
+
+ elif effectName in codonEffectGroupList:
+ old_new_AA=itemList[6]
+ old_new_Codon=itemList[7]
+ codon_num=itemList[8]
+ tmpList=[biotype,old_new_AA,old_new_Codon,codon_num]
+ funcDetailList.append(string.join(tmpList, ", "))
+ else:
+ funcDetailList.append(biotype)
+
+ return [geneList,transcriptList,exonList,funcList,funcDetailList]
+
+ def getEffectInfo(self, effectList):
+ Domain=''
+ effectDetailList=[]
+ effectInfoDict={}
+
+ Prime3_UTR,Prime5_UTR,Upstream,Downstream,Intron,Nonsplice_Site,Splice_Site,Intergenic=effectList[:8]
+ Exon,Non_Synonymous_Coding,Synonymous_Coding,Start_Gained,Start_Lost,Stop_Gained,Stop_Lost,Unknown_Effect_In_Exon=effectList[8:]
+
+ if Intergenic:
+ Domain='Intergenic'
+ effectInfoDict[Domain]=''
+ else:
+ # if not Exon:
+ # get geneList, transcriptList info.
+ if Upstream:
+ Domain='Upstream'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Upstream', effectValue=Upstream)
+ effectInfoDict[Domain]=effectDetailList
+ if Downstream:
+ Domain='Downstream'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Downstream', effectValue=Downstream)
+ effectInfoDict[Domain]=effectDetailList
+ if Intron:
+ if Splice_Site:
+ Domain='Splice Site'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Splice Site', effectValue=Splice_Site)
+ effectInfoDict[Domain]=effectDetailList
+ if Nonsplice_Site:
+ Domain='Nonsplice Site'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Nonsplice Site', effectValue=Nonsplice_Site)
+ effectInfoDict[Domain]=effectDetailList
+ # get gene, transcriptList and exon info.
+ if Prime3_UTR:
+ Domain='3\' UTR'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='3\' UTR', effectValue=Prime3_UTR)
+ effectInfoDict[Domain]=effectDetailList
+ if Prime5_UTR:
+ Domain='5\' UTR'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='5\' UTR', effectValue=Prime5_UTR)
+ effectInfoDict[Domain]=effectDetailList
+
+ if Start_Gained:
+ Domain='5\' UTR'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Start Gained', effectValue=Start_Gained)
+ effectInfoDict[Domain]=effectDetailList
+
+ if Unknown_Effect_In_Exon:
+ Domain='Unknown Effect In Exon'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Unknown Effect In Exon', effectValue=Unknown_Effect_In_Exon)
+ effectInfoDict[Domain]=effectDetailList
+ if Start_Lost:
+ Domain='Start Lost'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Start Lost', effectValue=Start_Lost)
+ effectInfoDict[Domain]=effectDetailList
+ if Stop_Gained:
+ Domain='Stop Gained'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Stop Gained', effectValue=Stop_Gained)
+ effectInfoDict[Domain]=effectDetailList
+ if Stop_Lost:
+ Domain='Stop Lost'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Stop Lost', effectValue=Stop_Lost)
+ effectInfoDict[Domain]=effectDetailList
+
+ if Non_Synonymous_Coding:
+ Domain='Nonsynonymous'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Nonsynonymous', effectValue=Non_Synonymous_Coding)
+ effectInfoDict[Domain]=effectDetailList
+ if Synonymous_Coding:
+ Domain='Synonymous'
+ effectDetailList=self.getEffectDetailsByCategory(effectName='Synonymous', effectValue=Synonymous_Coding)
+ effectInfoDict[Domain]=effectDetailList
+
+ return effectInfoDict
+
+
+ def getSortedStrainList(self, strainList):
+ sortedStrainList=[]
+ removeList=['C57BL/6J','DBA/2J']
+ for item in removeList:
+ strainList.remove(item)
+
+ sortedStrainList=removeList+strainList
+ return sortedStrainList
+
+ # build header and footer parts for export excel file
+ def createExcelFileWithTitleAndFooter(self, workbook=None, datasetName=None,returnNumber=None):
+
+ worksheet = workbook.add_worksheet()
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=14, border = 1, border_color="gray")
+
+ ##Write title Info
+ worksheet.write([1, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([2, 0], "Dataset : %s" % datasetName, titleStyle)
+ worksheet.write([3, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([4, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+ worksheet.write([5, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+ #Write footer info
+ worksheet.write([8 + returnNumber, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA21131), NCI MMHCC (U01CA105417), and NCRR (U01NR 105417)", titleStyle)
+ worksheet.write([9 + returnNumber, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+
+ return worksheet
+
+ def getSource(self):
+ sourceQuery ="select distinct Source from SnpAll"
+ self.cursor.execute(sourceQuery)
+ result =self.cursor.fetchall()
+ sourceList=[("All", "")]
+
+ try:
+ for item in result:
+ item=item[0]
+ sourceList.append((item,item))
+
+ except:
+ sourceList=[]
+
+ return sourceList
+
+
diff --git a/web/webqtl/snpBrowser/snpBrowserUtils.py b/web/webqtl/snpBrowser/snpBrowserUtils.py
new file mode 100755
index 00000000..4da5c9cb
--- /dev/null
+++ b/web/webqtl/snpBrowser/snpBrowserUtils.py
@@ -0,0 +1,71 @@
+# 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
+
+ # The columns that are to be displayed are chosen at the line about 1000, with categories["info"]; this initializes the columns and assigns a 'variable_name' :and: "Display Name"
+columnNames = {
+ # The following are for ALL VARIANTS
+ 'variant':"Variant Type",
+ 'snpname':"SNP ID", # SnpAll.Id
+ 'chromosome':"Chromosome",
+ 'mb':"Mb",
+ 'sourceName':"Source",
+ 'sourceCreated':"Source Created",
+ 'sourceAdded':"Source Added",
+ 'sourceId':"Source",
+ 'gene':'Gene',
+ # The following are for SNP VARIANTS
+ 'source':'Source',
+ 'chr':'Chr',
+ 'snpId':"Submitter ID", #SnpAll.SnpName
+ 'mbCelera':"Mb (CDS)",
+ 'rs':"ID",
+ 'function':"Function",
+ 'type':"Type",
+ 'majorCount':"Major Count",
+ 'minorCount':"Minor Count",
+ 'missingCount':"Missing Count",
+ 'class':"Class",
+ 'flanking5':"Flanking 5'",
+ 'flanking3':"Flanking 3'",
+ 'blatScore':"BLAT Score",
+ 'majorAllele':"Major Allele",
+ 'minorAllele':"Minor Allele",
+ 'shortAlleles':'Reference',
+ "Proximal_Gap_bp":"Gap",
+ 'domain':'Domain',
+ 'ncbi':'NCBI Annotation',
+ 'conservation':'ConScore',
+ # The following are for INDEL VARIANTS
+ 'indelId':"ID", # Indel.Id Indel
+ 'indelName':"ID", # Indel.Name
+ 'indelType':"Type", # Indel.Type
+ 'indelChr':"InDel Chr", # Indel.Chromosome
+ 'indelMb_s':"Mb Start", # Indel.Mb_start
+ 'indelMb_e':"Mb End", # IndelAll.Mb_end
+ 'indelStrand':"Strand", # IndelAll.Strand
+ 'indelSize':"Size", # IndelAll.Size
+ 'indelSeq':"Sequence", # IndelAll.Sequence
+} \ No newline at end of file
diff --git a/web/webqtl/snpBrowser/snpDetails.py b/web/webqtl/snpBrowser/snpDetails.py
new file mode 100755
index 00000000..43100ba9
--- /dev/null
+++ b/web/webqtl/snpBrowser/snpDetails.py
@@ -0,0 +1,101 @@
+# 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
+
+#########################################
+# A class for the information of SNPs ONLY. This is for the 'extra' page when you click on a SNP that doesn't have an RS#
+# This is where the information populating
+# The table is gathered. This is where you determine what variables you will display in the table
+#########################################
+
+import string
+from htmlgen import HTMLgen2 as HT
+
+import snpBrowserUtils
+from base.templatePage import templatePage
+from snpBrowserPage import snpBrowserPage
+
+class snpDetails(templatePage):
+
+ def __init__(self, fd, snpId):
+
+ templatePage.__init__(self, fd)
+
+ snpCols = "snpname, chromosome, mb, domain, rs, function, type, majorAllele, majorCount, minorAllele, minorCount, class, flanking5, flanking3, blatScore, sourceId, gene, ncbi".split(", ")
+ #get the details from the database if search the SNP variants by the "gene/snp" field
+ if snpId:
+ self.openMysql()
+
+ mysqlField = ['snpname','rs', 'chromosome', 'mb', 'function', 'type', 'class', 'flanking5', 'flanking3', 'blatscore', 'domain', 'gene', 'ncbi']
+ query = """
+ SELECT
+ %s, c.Name,b.*
+ from
+ SnpAll a, SnpPattern b, SnpSource c
+ where
+ a.Id =%s AND a.Id = b.SnpId AND a.SourceId =c.Id
+ """ % (string.join(mysqlField, ", "), snpId)
+
+ self.cursor.execute(query)
+ results = self.cursor.fetchone()
+ result =results[:14]
+ mysqlField.append('sourceName')
+ snpDict = {}
+
+ for i, item in enumerate(result):
+ snpDict[mysqlField[i]] = item
+ alleleList =results[15:]
+ objSnpBrowserPage =snpBrowserPage(fd)
+ flag =0
+ majAllele,minAllele,majAlleleCount,minAlleleCount= objSnpBrowserPage.getMajMinAlleles(alleleList,flag)
+ snpDict['majorAllele'] = majAllele
+ snpDict['minorAllele'] = minAllele
+ snpDict['majorCount'] = majAlleleCount
+ snpDict['minorCount'] = minAlleleCount
+ else:
+ return
+
+ # Creates the table for the SNP data
+ snpTable = HT.TableLite(border=0, cellspacing=5, cellpadding=3, Class="collap")
+ for item in snpCols:
+ thisTR = HT.TR(HT.TD(snpBrowserUtils.columnNames[item], Class="fs14 fwb ffl b1 cw cbrb", NOWRAP = 1))
+ if item in ('flanking5', 'flanking3'):
+ seq0 = snpDict[item]
+ seq = ""
+ i = 0
+ if seq0:
+ while i < len(seq0):
+ seq += seq0[i:i+5] + " "
+ i += 5
+ thisTR.append(HT.TD(HT.Span(seq, Class="code", Id="green"), Class='fs13 b1 cbw c222'))
+ elif item in snpDict.keys() and snpDict[item]:
+ thisTR.append(HT.TD(snpDict[item], Class='fs13 b1 cbw c222'))
+ else:
+ thisTR.append(HT.TD("", Class='fs13 b1 cbw c222'))
+
+ snpTable.append(thisTR)
+
+ self.dict['body'] = HT.TD(HT.Paragraph("Details for %s" % snpDict['snpname'], Class="title"), HT.Blockquote(snpTable))
+ self.dict['title'] = "Details for %s" % snpDict['snpname'] \ No newline at end of file
diff --git a/web/webqtl/submitTrait/AddUserInputToPublishPage.py b/web/webqtl/submitTrait/AddUserInputToPublishPage.py
new file mode 100755
index 00000000..f8154266
--- /dev/null
+++ b/web/webqtl/submitTrait/AddUserInputToPublishPage.py
@@ -0,0 +1,523 @@
+# 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
+
+#AddUserInputToPublishPage.py
+#
+#Classes:
+#AddUserInputToPublishPage
+#-KA
+
+import string
+from htmlgen import HTMLgen2 as HT
+import os
+import time
+
+from base.webqtlTrait import webqtlTrait
+from base.webqtlDataset import webqtlDataset
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+
+
+#########################################
+# AddUserInputToPublishPage
+#########################################
+
+class AddUserInputToPublishPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.updMysql():
+ return
+ fd.incparentsf1 = 1
+ if not fd.genotype:
+ fd.readGenotype()
+ fd.strainlist = fd.f1list + fd.strainlist
+ fd.readData()
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+ pass
+ else:
+ heading = "Add to Published Database"
+ detail = ["You don't have the permission to modify this database"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ self.cursor.execute("""
+ SelecT
+ PublishFreeze.Name
+ from
+ PublishFreeze, InbredSet
+ where
+ PublishFreeze.InbredSetId = InbredSet.Id AND
+ InbredSet.Name = '%s'""" % fd.RISet)
+
+ try:
+ self.db = webqtlDataset(self.cursor.fetchone()[0], self.cursor)
+ except:
+ heading = "Add to Published Database"
+ detail = ["The published database you requested has not been established"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ status = fd.formdata.getvalue('curStatus')
+ if status == 'insertResult':
+ newRecord = self.readForm(fd)
+ if not newRecord:
+ return
+ else:
+ self.insertResultPage(fd, newRecord)
+ elif status == 'insertCheck':
+ newRecord = self.readForm(fd)
+ if not newRecord:
+ return
+ else:
+ self.insertCheckPage(fd, newRecord)
+ else:
+ self.dispFormPage(fd)
+
+ def readForm(self, fd):
+ newRecord = {}
+ for field in self.db.disfield:
+ fieldValue = fd.formdata.getvalue(field)
+ if field == 'name' or field == 'sequence':
+ fieldValue = None
+ elif (not fieldValue) and (field == 'post_publication_description' or field == 'authors' or field == 'title' or field=='year'):
+ heading = "Add to Published Database"
+ detail = ["You did not enter information for %s." % webqtlUtil.formatField(field)]
+ self.error(heading=heading,detail=detail,error="Error")
+ return {}
+ elif fieldValue and field == 'pubmed_id':
+ try:
+ fieldValue = int(fieldValue)
+ except:
+ fieldValue = None
+ else:
+ pass
+ newRecord[field] = fieldValue
+ return newRecord
+
+ def insertResultPage(self, fd, newRecord):
+ #generate html
+ if 1:
+
+ #XZ: Create new publication record if necessary
+ PublicationId = None
+ if newRecord['pubmed_id']:
+ self.cursor.execute('SelecT Id from Publication where PubMed_ID = %d' % newRecord['pubmed_id'])
+ results = self.cursor.fetchall()
+ if not results:
+ pass
+ else:
+ PublicationId = results[0][0]
+
+ if not PublicationId:
+ insertFields = ['Id']
+ self.cursor.execute('SelecT max(Id) from Publication')
+ maxId = self.cursor.fetchall()[0][0] + 1
+ insertValues = [maxId]
+ for field in self.db.disfield:
+ if field in ('authors', 'title', 'abstract', 'journal','volume','pages','month','year') and newRecord[field]:
+ insertFields.append(field)
+ insertValues.append(newRecord[field])
+ NFields = ['%s'] * len(insertFields)
+ query = "insert into Publication (%s) Values (%s)" % (string.join(insertFields, ','), string.join(NFields, ','))
+
+ self.cursor.execute(query, tuple(insertValues))
+ PublicationId = maxId
+
+
+ #XZ: Create new phenotype
+ self.cursor.execute('SelecT max(Id) from Phenotype')
+ maxId = self.cursor.fetchall()[0][0] + 1
+ PhenotypeId = maxId
+ if not newRecord['units']:
+ newRecord['units'] = "Unknown"
+
+ insertFields = ['Id']
+ insertValues = [PhenotypeId]
+ insertFields.append( 'Post_publication_description' )
+ insertValues.append( newRecord['post_publication_description'] )
+ insertFields.append( 'Units' )
+ insertValues.append( newRecord['units'] )
+ insertFields.append( 'Post_publication_abbreviation' )
+ insertValues.append( newRecord['post_publication_abbreviation'] )
+
+ insertFields.append( 'Submitter' )
+ insertValues.append( self.userName )
+ insertFields.append( 'Authorized_Users' )
+ insertValues.append( self.userName )
+
+ if newRecord['pre_publication_description']:
+ insertFields.append( 'Pre_publication_description' )
+ insertValues.append( newRecord['pre_publication_description'] )
+
+ insertFields.append( 'Original_description' )
+ original_desc_string = 'Original post publication description: ' + newRecord['post_publication_description']
+ if newRecord['pre_publication_description']:
+ original_desc_string = original_desc_string + '\n\nOriginal pre publication description: ' + newRecord['pre_publication_description']
+ insertValues.append( original_desc_string )
+
+ if newRecord['pre_publication_abbreviation']:
+ insertFields.append( 'Pre_publication_abbreviation' )
+ insertValues.append( newRecord['pre_publication_abbreviation'] )
+
+ if newRecord['lab_code']:
+ insertFields.append( 'Lab_code' )
+ insertValues.append( newRecord['lab_code'] )
+
+ if newRecord['owner']:
+ insertFields.append( 'Owner' )
+ insertValues.append( newRecord['owner'] )
+
+
+ NFields = ['%s'] * len(insertFields)
+ query = "insert into Phenotype (%s) Values (%s)" % (string.join(insertFields, ','), string.join(NFields, ','))
+ self.cursor.execute(query, tuple(insertValues))
+
+
+
+
+ #XZ: Insert data into PublishData, PublishSE and NStrain tables.
+ self.cursor.execute('SelecT max(Id) from PublishData')
+ DataId = self.cursor.fetchall()[0][0] + 1
+
+ self.db.getRISet()
+ InbredSetId = self.db.risetid
+
+ self.cursor.execute('Select SpeciesId from InbredSet where Id=%s' % InbredSetId)
+ SpeciesId = self.cursor.fetchone()[0]
+
+ StrainIds = []
+ for item in fd.strainlist:
+ self.cursor.execute('Select Id from Strain where SpeciesId=%s and Name = "%s"' % (SpeciesId, item) )
+ StrainId = self.cursor.fetchall()
+ if not StrainId:
+ raise ValueError
+ else:
+ StrainIds.append(StrainId[0][0])
+
+ for i, strainName in enumerate(fd.strainlist):
+ if fd.allTraitData.has_key(strainName):
+ tdata = fd.allTraitData[strainName]
+ traitVal, traitVar, traitNP = tdata.val, tdata.var, tdata.N
+ else:
+ continue
+
+ if traitVal != None:
+ #print 'insert into Data values(%d, %d, %s)' % (DataId, StrainIds[i], traitVal), "<BR>"
+ #XZ, 03/05/2009: Xiaodong changed Data to PublishData
+ self.cursor.execute('insert into PublishData values(%d, %d, %s)' % (DataId, StrainIds[i], traitVal))
+ if traitVar != None:
+ #print 'insert into SE values(%d, %d, %s)' % (DataId, StrainIds[i], traitVar), "<BR>"
+ #XZ, 03/13/2009: Xiaodong changed SE to PublishSE
+ self.cursor.execute('insert into PublishSE values(%d, %d, %s)' % (DataId, StrainIds[i], traitVar))
+ if traitNP != None:
+ #print 'insert into NStrain values(%d, %d, %s)' % (DataId, StrainIds[i], traitNP), "<BR>"
+ self.cursor.execute('insert into NStrain values(%d, %d, %d)' % (DataId, StrainIds[i], traitNP))
+
+
+ self.cursor.execute('SelecT max(Sequence) from PublishXRef where InbredSetId = %d and PhenotypeId = %d and PublicationId = %d' % (InbredSetId,PhenotypeId,PublicationId))
+ Sequence = self.cursor.fetchall()
+ if not Sequence or not Sequence[0][0]:
+ Sequence = 1
+ else:
+ Sequence = Sequence[0][0] + 1
+
+ self.cursor.execute('SelecT max(Id) from PublishXRef where InbredSetId = %d' % InbredSetId)
+ try:
+ InsertId = self.cursor.fetchall()[0][0] + 1
+ except:
+ InsertId = 10001
+
+ ctime = time.ctime()
+ comments = "Inserted by %s at %s\n" % (self.userName, ctime)
+ #print 'insert into PublishXRef(Id, PublicationId, InbredSetId, PhenotypeId, DataId, Sequence, comments) values(%s, %s, %s, %s, %s, %s, %s)' % (InsertId , PublicationId, InbredSetId, PhenotypeId, DataId, Sequence, comments)
+ self.cursor.execute('insert into PublishXRef(Id, PublicationId, InbredSetId, PhenotypeId, DataId, Sequence, comments) values(%s, %s, %s, %s, %s, %s, %s)', (InsertId , PublicationId, InbredSetId, PhenotypeId, DataId, Sequence, comments))
+
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#ffffff", height=200)
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', name='showDatabase', submit=HT.Input(type='hidden'))
+ hddn = {'FormID':'showDatabase','ProbeSetID':'_','database':'_','CellID':'_','RISet':fd.RISet, 'incparentsf1':'on'}
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ mainTitle = HT.Paragraph("Add Trait to Published Database", Class="title")
+
+ info = HT.Paragraph("Your Trait has been succesfully added to ", self.db.genHTML(), ".")
+
+ thisTrait = webqtlTrait(db=self.db, cursor=self.cursor, name=InsertId)
+ thisTrait.retrieveInfo()
+
+ tbl = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+
+ checkBox = HT.Input(type="checkbox",name="searchResult",value="%s" % thisTrait)
+ tbl.append(HT.TR(HT.TD(width=30), HT.TD(thisTrait.genHTML(dispFromDatabase=1, privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users))))
+ form.append(info, HT.P(), tbl)
+ TD_LR.append(mainTitle, HT.Blockquote(form))
+
+ self.dict['body'] = TD_LR
+ else:
+ heading = "Add to Published Database"
+ detail = ["Error occured while adding the data."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ def insertCheckPage(self, fd, newRecord):
+ #generate html
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='dataInput',submit=HT.Input(type='hidden'))
+ hddn = {'database':self.db.name, 'curStatus':'insertResult', 'FormID':'dataEditing', 'submitID':'addPublish', 'RISet':fd.RISet}
+
+ recordTable = HT.TableLite(border=0, align="left")
+ title1 = HT.Paragraph("Trait Information:", Class="subtitle")
+ title2 = HT.Paragraph("Trait Data:", Class="subtitle")
+ recordInfoContainer = HT.Div(align="left")
+ recordDataContainer = HT.Div(align="left")
+ addButton = HT.Input(type='submit',name='submit', value='Add to Publish',Class="button")
+ resetButton = HT.Input(type='reset',Class="button")
+
+ recordInfoTable = HT.TableLite(border=0, cellspacing=1, cellpadding=5, align="left")
+ for field in self.db.disfield:
+ if newRecord[field]:
+ recordInfoTable.append(HT.TR(
+ HT.TD("%s :" % webqtlUtil.formatField(field), Class="fs12 fwb ff1", valign="top",align="right"),
+ HT.TD(width=20),HT.TD(newRecord[field])))
+ hddn[field] = newRecord[field]
+
+ recordInfoContainer.append(addButton, resetButton, HT.P(), title1, HT.BR(), recordInfoTable)
+
+ recordDataTable = HT.TableLite(border=0, width = "80%",cellspacing=3, cellpadding=2)
+ recordDataTable.append(HT.TR(HT.TD('Strain Name',Class="fs12 ffl fwb",align="left"),
+ HT.TD('TraitData',Class="fs12 ffl fwb",align="right"),
+ HT.TD('SE',Class="fs12 ffl fwb",align="right"),
+ HT.TD('N Per Strain',Class="fs12 ffl fwb",align="right"),
+ HT.TD('&nbsp'*8,Class="fs12 ffl fwb",align="center"),
+ HT.TD('Strain Name',Class="fs12 ffl fwb",align="left"),
+ HT.TD('TraitData',Class="fs12 ffl fwb",align="right"),
+ HT.TD('SE',Class="fs12 ffl fwb",align="right"),
+ HT.TD('N Per Strain',Class="fs12 ffl fwb",align="right")))
+
+ tempTR = HT.TR(align="Center")
+ for i, strainName in enumerate(fd.strainlist):
+ if fd.allTraitData.has_key(strainName):
+ tdata = fd.allTraitData[strainName]
+ traitVal, traitVar, traitNP = tdata.val, tdata.var, tdata.N
+ else:
+ traitVal, traitVar, traitNP = None, None, None
+
+ if traitVal != None:
+ traitVal = "%2.3f" % traitVal
+ else:
+ traitVal = 'x'
+ if traitVar != None:
+ traitVar = "%2.3f" % traitVar
+ else:
+ traitVar = 'x'
+ if traitNP != None:
+ traitNP = "%d" % traitNP
+ else:
+ traitNP = 'x'
+
+ tempTR.append(HT.TD(HT.Paragraph(strainName),align='left'),
+ HT.TD(traitVal,align='right'),
+ HT.TD(traitVar,align='right'),
+ HT.TD(traitNP,align='right'),
+ HT.TD('',align='center'))
+ if i % 2:
+ recordDataTable.append(tempTR)
+ tempTR = HT.TR(align="Center")
+
+ if (i+1) % 2:
+ tempTR.append(HT.TD(''))
+ tempTR.append(HT.TD(''))
+ recordDataTable.append(tempTR)
+
+ info = HT.Paragraph("Please review the trait information and data in the text below. Check the values for errors. If no error is found, please click the \"Add to Publish\" button to submit it.")
+ recordDataContainer.append(title2, HT.BR(), info, HT.P(), recordDataTable, HT.P(), addButton, resetButton, HT.P())
+
+ recordTable.append(HT.TR(HT.TD(recordInfoContainer)), HT.TR(HT.TD(recordDataContainer)))
+
+ webqtlUtil.exportData(hddn, fd.allTraitData, 1)
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+
+ #############################
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#ffffff")
+
+ mainTitle = HT.Paragraph("Add Trait to Published Database", Class="title")
+
+ form.append(recordTable)
+
+ TD_LR.append(mainTitle, HT.Blockquote(form))
+
+ self.dict['body'] = TD_LR
+
+ def dispFormPage(self, fd):
+ ###specical care, temporary trait data
+ fullname = fd.formdata.getvalue('fullname')
+ if fullname:
+ thisTrait = webqtlTrait(fullname=fullname, data= fd.allTraitData, cursor=self.cursor)
+ thisTrait.retrieveInfo()
+ PhenotypeValue = thisTrait.description
+ else:
+ thisTrait = webqtlTrait(data= fd.allTraitData)
+ PhenotypeValue = thisTrait.identification
+
+ self.dict['title'] = 'Add to Published Database'
+
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='dataInput',submit=HT.Input(type='hidden'))
+
+ recordTable = HT.TableLite(border=0, align="left")
+ recordInfoContainer = HT.Div(align="left")
+ recordDataContainer = HT.Div(align="left")
+ title1 = HT.Paragraph("&nbsp;Trait Information:", align="left", Class="subtitle")
+ title2 = HT.Paragraph("&nbsp;Trait Data:", align="left", Class="subtitle")
+ addButton = HT.Input(type='submit',name='submit', value='Submit Trait',Class="button")
+ resetButton = HT.Input(type='reset',Class="button")
+
+ recordInfoTable = HT.TableLite(border=0, cellspacing=1, cellpadding=5,align="left")
+ for field in self.db.disfield:
+ fieldValue = ""
+
+ if field == 'comments':
+ continue
+ elif field == 'name' or field == 'sequence' or field == 'original_description' or field == 'submitter' or field == 'authorized_users':
+ form.append(HT.Input(type="hidden",name=field,value=fieldValue))
+ continue
+ elif field == 'post_publication_description':
+ inputBox = HT.Textarea(name=field, cols=60, rows=6,text=PhenotypeValue)
+ elif field == 'abstract' or field == 'pre_publication_description' or field == 'owner':
+ inputBox = HT.Textarea(name=field, cols=60, rows=6,text=fieldValue)
+ elif field == 'post_publication_abbreviation' or field == 'pre_publication_abbreviation':
+ inputBox = HT.Input(type="text",name=field,size=60, maxlength=30,value=fieldValue)
+ else:
+ inputBox = HT.Input(type="text",name=field,size=60, maxlength=255,value=fieldValue)
+ if field in ('post_publication_description', 'authors', 'title', 'year'):
+ requiredSign = HT.Span('*', Class="cr")
+ else:
+ requiredSign = ''
+
+ recordInfoTable.append(HT.TR(
+ HT.TD(requiredSign, "%s :" % webqtlUtil.formatField(field), Class="fs12 fwb ff1", valign="top",align="right"),
+ HT.TD(width=20),HT.TD(inputBox)))
+
+ if field == 'pubmed_id':
+ recordInfoTable.append(HT.TR(
+ HT.TD(), HT.TD(width=20),
+ HT.TD("Do not enter PubMed_ID if this trait has not been Published.",
+ HT.BR(), "If the PubMed_ID you entered is alreday stored in our database, ",
+ HT.BR(), "all the following fields except Post Publication Description will be ignored.",
+ HT.BR(), "Do not enter any non-digit character in this field.", Class="fs11 cr")
+ ))
+ if field == 'pre_publication_description':
+ recordInfoTable.append(HT.TR(
+ HT.TD(), HT.TD(width=20),
+ HT.TD("If the PubMed ID is entered, the Post Publication Description will be shown to all",
+ HT.BR(), " users. If there is no PubMed ID, and the Pre Publication Description is entered,",
+ HT.BR(), "only you and authorized users can see the Post Publication Description.", Class="fs11 cr")
+ ))
+ if field == 'owner':
+ recordInfoTable.append(HT.TR(
+ HT.TD(), HT.TD(width=20),
+ HT.TD("Please provide detailed owner contact information including full name, title,",
+ HT.BR(), " institution, address, email etc", Class="fs11 cr")
+ ))
+
+ recordInfoTable.append(HT.TR(HT.TD(HT.Span('*', Class="cr"), " Required field", align="center", colspan=3)))
+ recordInfoContainer.append(addButton, resetButton, HT.P(), title1, HT.BR(), recordInfoTable)
+
+ recordDataTable = HT.TableLite(border=0, width = "90%",cellspacing=2, cellpadding=2)
+ recordDataTable.append(HT.TR(HT.TD('Strain Name',Class="fs12 ffl fwb",align="left"),
+ HT.TD('Trait Data',Class="fs12 ffl fwb",align="right"),
+ HT.TD('SE',Class="fs12 ffl fwb",align="right"),
+ HT.TD('N Per Strain',Class="fs12 ffl fwb",align="right"),
+ HT.TD('&nbsp'*8,Class="fs12 ffl fwb",align="center"),
+ HT.TD('Strain Name',Class="fs12 ffl fwb",align="left"),
+ HT.TD('Trait Data',Class="fs12 ffl fwb",align="right"),
+ HT.TD('SE',Class="fs12 ffl fwb",align="right"),
+ HT.TD('N Per Strain',Class="fs12 ffl fwb",align="right")))
+
+ tempTR = HT.TR(align="right")
+ for i, strainName in enumerate(fd.strainlist):
+ if thisTrait.data.has_key(strainName):
+ tdata = thisTrait.data[strainName]
+ traitVal, traitVar, traitNP = tdata.val, tdata.var, tdata.N
+ else:
+ traitVal, traitVar, traitNP = None, None, None
+
+ if traitVal != None:
+ traitVal = "%2.3f" % traitVal
+ else:
+ traitVal = 'x'
+ if traitVar != None:
+ traitVar = "%2.3f" % traitVar
+ else:
+ traitVar = 'x'
+ if traitNP != None:
+ traitNP = "%d" % traitNP
+ else:
+ traitNP = 'x'
+
+ tempTR.append(HT.TD(HT.Paragraph(strainName), width="120px", align='left'), \
+ HT.TD(HT.Input(name=fd.strainlist[i], size=8, maxlength=8, value=traitVal, align="right"), width="100px", align='right'),
+ HT.TD(HT.Input(name='V'+fd.strainlist[i], size=8, maxlength=8, value=traitVar, align="right"), width="100px", align='right'),
+ HT.TD(HT.Input(name='N'+fd.strainlist[i], size=8, maxlength=8, value=traitNP, align="right"), width="120px", align='right'),
+ HT.TD('', align='center'))
+ if i % 2:
+ recordDataTable.append(tempTR)
+ tempTR = HT.TR(align="Center")
+
+ if (i+1) % 2:
+ tempTR.append(HT.TD(''))
+ tempTR.append(HT.TD(''))
+ tempTR.append(HT.TD(''))
+ recordDataTable.append(tempTR)
+
+ recordDataContainer.append(title2, HT.BR(), recordDataTable, HT.P(), addButton, resetButton, HT.P())
+
+ recordTable.append(HT.TR(HT.TD(recordInfoContainer)), HT.TR(HT.TD(recordDataContainer)))
+
+ """
+ """
+
+ hddn = {'database':self.db.name, 'curStatus':'insertCheck', 'FormID':'dataEditing', 'submitID':'addPublish', 'RISet':fd.RISet}
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+
+ #############################
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#ffffff")
+
+ mainTitle = HT.Paragraph("Add Trait to Published Database", Class="title")
+
+ form.append(recordTable)
+
+ TD_LR.append(mainTitle, form)
+
+ self.dict['body'] = TD_LR
+
diff --git a/web/webqtl/submitTrait/BatchSubmitPage.py b/web/webqtl/submitTrait/BatchSubmitPage.py
new file mode 100755
index 00000000..1c0be1ed
--- /dev/null
+++ b/web/webqtl/submitTrait/BatchSubmitPage.py
@@ -0,0 +1,142 @@
+# 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
+
+import glob
+from htmlgen import HTMLgen2 as HT
+import os
+
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+
+# XZ, 09/09/2008: From home, click "Batch Submission".
+# XZ, 09/09/2008: This class generate what you see
+#########################################
+# BatchSubmitPage
+#########################################
+
+class BatchSubmitPage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ self.dict['title'] = 'Batch Submission'
+
+ TD_LEFT = """
+ <TD vAlign=top width="40%" bgColor=#eeeeee>
+ <P class="title">Introduction</P>
+ <BLOCKQUOTE>
+ <P>The batch submission utility enables users to submit multiple
+ traits at the same time for analysis by the GeneNetwork and
+ WebQTL. The data will be stored on our server for no more than
+ 24 hours. None of the submitted data are stored or copied
+ elsewhere.</P>
+ <P>The file to be uploaded should follow correct format shown
+ in the <A Href="/sample.txt" class="normalsize" target="_blank">
+ Sample</A>, <A Href="/sample2.txt" class="normalsize"
+ target="_blank">Sample2</A> text file.</P>
+ <P>Please follow the <A href="http://www.genenetwork.org/faq.html#Q-22" class="normalsize" target="_blank">guide</A> for naming your traits.</P>
+ </BLOCKQUOTE>
+ </TD>
+ """
+ TD_RIGHT = HT.TD(valign="top",width="60%",bgcolor="#eeeeee")
+ main_title = HT.Paragraph("Batch Trait Submission Utility")
+ main_title.__setattr__("class","title")
+
+ #############################
+
+ title1 = HT.Paragraph("1. Choose cross or RI set:")
+ title1.__setattr__("class","subtitle")
+
+ STEP1 = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+ crossMenu = HT.Select(name='RISet', onChange='xchange()')
+ allRISets = map(lambda x: x[:-5], glob.glob1(webqtlConfig.GENODIR, '*.geno'))
+ allRISets.sort()
+ allRISets.remove("BayXSha")
+ allRISets.remove("ColXBur")
+ allRISets.remove("ColXCvi")
+ specMenuSub1 = HT.Optgroup(label = 'MOUSE')
+ specMenuSub2 = HT.Optgroup(label = 'RAT')
+ for item in allRISets:
+ if item != 'HXBBXH':
+ specMenuSub1.append(tuple([item,item]))
+ else:
+ specMenuSub2.append(tuple(['HXB/BXH', 'HXBBXH']))
+ crossMenu.append(specMenuSub1)
+ crossMenu.append(specMenuSub2)
+ crossMenu.selected.append('BXD')
+ crossMenuText = HT.Paragraph('Select the cross or recombinant inbred \
+ set from the menu below. ')
+ infoButton = HT.Input(type="button",Class="button",value="Info",\
+ onClick="crossinfo2();")
+ # NL, 07/27/2010. variable 'IMGSTEP1' has been moved from templatePage.py to webqtlUtil.py;
+ TD1 = HT.TD(webqtlUtil.IMGSTEP1,width=58)
+ TD2 = HT.TD()
+ TD2.append(crossMenuText,crossMenu, infoButton)
+ STEP1.append(HT.TR(TD1,TD2),HT.TR(HT.TD(colspan=2,height=20)))
+
+ #############################
+ title2 = HT.Paragraph("&nbsp;&nbsp;2. Enter Trait Data:")
+ title2.__setattr__("class","subtitle")
+
+ STEP2 = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+ Para1 = HT.Paragraph()
+ Para1.append('You can submit traits by entering a file name here. The \
+ file should contain a number of no more than 100 traits. The file \
+ should follow the file format described in this ', HT.Href(url=\
+ "/sample.txt",Class="normalsize", target="_blank", \
+ text= 'Sample'), ' text.')
+
+ filebox = HT.Paragraph(HT.Input(type='file', name='batchdatafile', size=20))
+
+ # NL, 07/27/2010. variable 'IMGSTEP2' has been moved from templatePage.py to webqtlUtil.py;
+ TD1 = HT.TD(webqtlUtil.IMGSTEP2,width=58)
+ TD2 = HT.TD()
+ TD2.append(Para1,filebox)
+ STEP2.append(HT.TR(TD1,TD2),HT.TR(HT.TD(colspan=2,height=20)))
+
+ #########################################
+ hddn = {'FormID':'batSubmitResult'}
+
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), \
+ enctype='multipart/form-data', name='crossChoice', submit=HT.Input(type='hidden'))
+
+ submit = HT.Input(type='button' ,name='next', value='Next',onClick=\
+ 'batchSelection(this.form);',Class="button")
+ reset = HT.Input(type='reset' ,name='reset' ,value='Reset',Class="button")
+ # NL, 07/27/2010. variable 'IMGNEXT' has been moved from templatePage.py to webqtlUtil.py;
+ form.append(HT.Blockquote(title1,HT.Center(STEP1,webqtlUtil.IMGNEXT),title2,\
+ HT.Center(STEP2,webqtlUtil.IMGNEXT)),HT.Center(HT.P(),submit,reset))
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ TD_RIGHT.append(main_title,form)
+
+ self.dict['body'] = TD_LEFT + str(TD_RIGHT)
+
diff --git a/web/webqtl/submitTrait/CrossChoicePage.py b/web/webqtl/submitTrait/CrossChoicePage.py
new file mode 100755
index 00000000..fd919e5b
--- /dev/null
+++ b/web/webqtl/submitTrait/CrossChoicePage.py
@@ -0,0 +1,233 @@
+# 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
+
+import glob
+from htmlgen import HTMLgen2 as HT
+import os
+
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+# XZ, 08/28/2008: From home, click "Enter Trait Data".
+# XZ, 08/28/2008: This class generate what you see
+#########################################
+# CrossChoicePage
+#########################################
+
+class CrossChoicePage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ self.dict['title'] = 'Trait Submission'
+
+ if not self.openMysql():
+ return
+
+ authorized = 0
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+ authorized = 1
+
+ TD_LEFT = """
+ <TD vAlign=top width="45%" bgColor=#eeeeee>
+ <P class="title">Introduction</P>
+ <BLOCKQUOTE>
+ <P>The trait values that you enter are statistically compared
+ with verified genotypes collected at a set of microsatellite
+ markers in each RI set. The markers are drawn from a set of
+ over 750, but for each set redundant markers have been removed,
+ preferentially retaining those that are most informative. </P>
+
+ <P>These error-checked RI mapping data match theoretical
+ expectations for RI strain sets. The cumulative adjusted length
+ of the RI maps are approximately 1400 cM, a value that matches
+ those of both MIT maps and Chromosome Committee Report maps.
+ See our <a Href="http://www.nervenet.org/papers/BXN.html"
+ class="normalsize"> full description</a> of the genetic data
+ collected as part of the WebQTL project. </P>
+
+ </BLOCKQUOTE>
+ <P class="title">About Your Data</P>
+ <BLOCKQUOTE>
+ <P>You can open a separate <a Href="RIsample.html" target="_blank"
+ class="normalsize"> window </a> giving the number of strains
+ for each data set and sample data. </P>
+ <P>None of your submitted data is copied or stored by this
+ system except during the actual processing of your submission.
+ By the time the reply page displays in your browser, your
+ submission has been cleared from this system. </P>
+ </BLOCKQUOTE>
+ </TD>
+ """
+ TD_RIGHT = HT.TD(valign="top",width="55%",bgcolor="#eeeeee")
+ main_title = HT.Paragraph(" Trait Submission Form")
+ main_title.__setattr__("class","title")
+
+ #############################
+
+ title1 = HT.Paragraph("&nbsp;&nbsp;1. Choose cross or RI set:")
+ title1.__setattr__("class","subtitle")
+
+ STEP1 = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+ crossMenu = HT.Select(name='RISet', onChange='xchange()')
+ allRISets = map(lambda x: x[:-5], glob.glob1(webqtlConfig.GENODIR, '*.geno'))
+ allRISets.sort()
+ if authorized:
+ self.cursor.execute("select Name from InbredSet")
+ else:
+ self.cursor.execute("select Name from InbredSet where public > %d" % webqtlConfig.PUBLICTHRESH)
+ results = map(lambda X:X[0], self.cursor.fetchall())
+ allRISets = filter(lambda X:X in results, allRISets)
+
+ specMenuSub1 = HT.Optgroup(label = 'MOUSE')
+ specMenuSub2 = HT.Optgroup(label = 'RAT')
+ specMenuSub3 = HT.Optgroup(label = 'ARABIDOPSIS')
+ specMenuSub4 = HT.Optgroup(label = 'BARLEY')
+ for item in allRISets:
+ if item == 'HXBBXH':
+ specMenuSub2.append(('HXB/BXH', 'HXBBXH'))
+ elif item in ('BayXSha', 'ColXCvi', 'ColXBur'):
+ specMenuSub3.append((item, item))
+ elif item in ('SXM'):
+ specMenuSub4.append((item, item))
+ elif item == 'AXBXA':
+ specMenuSub1.append(('AXB/BXA', 'AXBXA'))
+ else:
+ specMenuSub1.append(tuple([item,item]))
+ crossMenu.append(specMenuSub1)
+ crossMenu.append(specMenuSub2)
+ crossMenu.append(specMenuSub3)
+ crossMenu.append(specMenuSub4)
+ crossMenu.selected.append('BXD')
+ crossMenuText = HT.Paragraph('Select the cross or recombinant inbred \
+ set from the menu below. If you wish, paste data or select a data \
+ file in the next sections')
+ infoButton = HT.Input(type="button",Class="button",value="Info",\
+ onClick="crossinfo2();")
+ # NL, 07/27/2010. variable 'IMGSTEP1' has been moved from templatePage.py to webqtlUtil.py;
+ TD1 = HT.TD(webqtlUtil.IMGSTEP1,width=58)
+ TD2 = HT.TD()
+ TD2.append(crossMenuText,crossMenu, infoButton)
+ STEP1.append(HT.TR(TD1,TD2),HT.TR(HT.TD(colspan=2,height=20)))
+
+ #############################
+ title2 = HT.Paragraph("&nbsp;&nbsp;2. Enter Trait Data:")
+ title2.__setattr__("class","subtitle")
+
+ STEP2 = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+ Para1 = HT.Paragraph()
+ Para1.append(HT.Strong("From a File: "))
+ Para1.append('You can enter data by entering a file name here. The file\
+ should contain a series of numbers representing trait values. The \
+ values can be on one line separated by spaces or tabs, or they can \
+ be on separate lines. Include one value for each progeny individual\
+ or recombinant inbred line. Represent missing values with a \
+ non-numeric character such as "x". If you have chosen a recombinant\
+ inbred set, when you submit your data will be displayed in a form \
+ where you can confirm and/or edit them. If you enter a file name \
+ here, any data that you paste into the next section will be ignored.')
+
+ filebox = HT.Paragraph(HT.Input(type='file', name='traitfile', size=20))
+
+ OR = HT.Paragraph(HT.Center(HT.Font(HT.Strong('OR'),color="red")))
+
+ Para2 = HT.Paragraph()
+ Para2.append(HT.Strong("By Pasting or Typing Multiple Values:"))
+ Para2.append('You can enter data by pasting a series of numbers \
+ representing trait values into this area. The values can be on one\
+ line separated by spaces or tabs, or they can be on separate lines.\
+ Include one value for each progeny individual or recombinant inbred\
+ line. Represent missing values with a non-numeric character such \
+ as "x". If you have chosen a recombinant inbred set, when you submit\
+ your data will be displayed in a form where you can confirm and/or\
+ edit them. If you enter a file name in the previous section, any \
+ data that you paste here will be ignored. Check ',
+ HT.Href(url="/RIsample.html", text="sample data", target="_blank", Class="normalsize"),
+ ' for the correct format.')
+
+ pastebox = HT.Paragraph(HT.Textarea(name='traitpaste', cols=45, rows=6))
+ # NL, 07/27/2010. variable 'IMGSTEP2' has been moved from templatePage.py to webqtlUtil.py;
+ TD1 = HT.TD(webqtlUtil.IMGSTEP2,width=58)
+ TD2 = HT.TD()
+ TD2.append(Para1,filebox,OR,Para2,pastebox)
+ STEP2.append(HT.TR(TD1,TD2),HT.TR(HT.TD(colspan=2,height=20)))
+
+ #############################
+ title3 = HT.Paragraph("&nbsp;&nbsp;3. Options:")
+ title3.__setattr__("class","subtitle")
+
+ STEP3 = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+
+ ########
+ opt1 = HT.Paragraph(HT.Strong('Enable Use of Trait Variance: '))
+ opt1.append(HT.Input(type='checkbox', Class='checkbox', name=\
+ 'enablevariance', value='ON', onClick='xchange()'))
+ opt1.append(HT.BR(),'You may use your trait variance data in WebQTL,\
+ if you check this box, you will be asked to submit your trait \
+ variance data later')
+
+ ########
+ opt2 = HT.Paragraph(HT.Strong('Enable Use of Parents/F1: '))
+ opt2.append(HT.Input(type='checkbox', name='parentsf1', value='ON'))
+ opt2.append(HT.BR(),'Check this box if you wish to use Parents and F1 \
+ data in WebQTL')
+
+ ########
+ opt3 = HT.Paragraph(HT.Strong("Name Your Trait ",HT.Font("(optional) ",\
+ color="red")))
+ opt3.append(HT.Input(name='identification', size=12, maxlength=30))
+ # NL, 07/27/2010. variable 'IMGSTEP3' has been moved from templatePage.py to webqtlUtil.py;
+ TD1 = HT.TD(webqtlUtil.IMGSTEP3,width=58)
+ TD2 = HT.TD()
+ TD2.append(opt1,opt3)
+ STEP3.append(HT.TR(TD1,TD2),HT.TR(HT.TD(colspan=2,height=20)))
+
+ #########################################
+ hddn = {'FormID':'crossChoice','submitID':'next', 'incparentsf1':'yes'}
+
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), \
+ enctype= 'multipart/form-data', name='crossChoice', submit=\
+ HT.Input(type='hidden'))
+
+ submit = HT.Input(type='button' ,name='next', value='Next',onClick=\
+ 'showNext(this.form);', Class="button")
+ reset = HT.Input(type='reset' ,name='reset' ,value='Reset',Class="button")
+
+ sample = HT.Input(type='button' ,name='sample' ,value='Sample Data', \
+ onClick='showSample(this.form);',Class="button")
+ # NL, 07/27/2010. variable 'IMGNEXT' has been moved from templatePage.py to webqtlUtil.py;
+ form.append(title1,HT.Center(STEP1,webqtlUtil.IMGNEXT),title2,HT.Center(STEP2,\
+ webqtlUtil.IMGNEXT),title3,HT.Center(STEP3,webqtlUtil.IMGNEXT,HT.P(),submit,reset,sample))
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ TD_RIGHT.append(main_title,form)
+ self.dict['body'] = TD_LEFT + str(TD_RIGHT)
+
+
diff --git a/web/webqtl/submitTrait/VarianceChoicePage.py b/web/webqtl/submitTrait/VarianceChoicePage.py
new file mode 100755
index 00000000..bdbc47f9
--- /dev/null
+++ b/web/webqtl/submitTrait/VarianceChoicePage.py
@@ -0,0 +1,174 @@
+# 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 htmlgen import HTMLgen2 as HT
+import os
+
+from base.templatePage import templatePage
+from utility import webqtlUtil
+from base import webqtlConfig
+
+
+# XZ, 09/09/2008: From home, click "Enter Trait Data".
+# XZ, 09/09/2008: If user check "Enable Use of Trait Variance",
+# XZ, 09/09/2008: this class generate what you see
+#########################################
+# VarianceChoicePage
+#########################################
+
+class VarianceChoicePage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ self.dict['title'] = 'Variance Submission'
+
+ if not fd.genotype:
+ fd.readData(incf1=1)
+
+ TD_LEFT = """
+ <TD vAlign=top width="45%" bgColor=#eeeeee>
+ <P class="title">Introduction</P>
+ <BLOCKQUOTE>
+ <P>The variance values that you enter are statistically compared\
+ with verified genotypes collected at a set of microsatellite \
+ markers in each RI set. The markers are drawn from a set of \
+ over 750, but for each set redundant markers have been removed,\
+ preferentially retaining those that are most informative. </P>
+
+ <P>These error-checked RI mapping data match theoretical \
+ expectations for RI strain sets. The cumulative adjusted length\
+ of the RI maps are approximately 1400 cM, a value that matches\
+ those of both MIT maps and Chromosome Committee Report maps. \
+ See our <a Href="http://www.nervenet.org/papers/BXN.html" \
+ class="normalsize">full description</a> of the genetic data \
+ collected as part of the WebQTL project. </P>
+
+ </BLOCKQUOTE>
+ <P class="title">About Your Data</P>
+ <BLOCKQUOTE>
+ <P>You can open a separate <a target="_blank" Href=\
+ "RIsample.html" class="normalsize">window</a> giving the number\
+ of strains for each data set and sample data. </P>
+
+ <P>None of your submitted data is copied or stored by this \
+ system except during the actual processing of your submission. \
+ By the time the reply page displays in your browser, your \
+ submission has been cleared from this system. </P>
+ </BLOCKQUOTE>
+ </TD>
+ """
+ TD_RIGHT = HT.TD(valign="top",width="55%",bgcolor="#eeeeee")
+ main_title = HT.Paragraph(" Variance Submission Form")
+ main_title.__setattr__("class","title")
+
+ #############################
+ title2 = HT.Paragraph("&nbsp;&nbsp;1. Enter variance Data:")
+ title2.__setattr__("class","subtitle")
+
+ STEP2 = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+ Para1 = HT.Paragraph()
+ Para1.append(HT.Strong("From a File: "))
+ Para1.append('You can enter data by entering a file name here. The file\
+ should contain a series of numbers representing variance values. The \
+ values can be on one line separated by spaces or tabs, or they can be \
+ on separate lines. Include one value for each progeny individual or \
+ recombinant inbred line. Represent missing values with a non-numeric \
+ character such as "x". If you have chosen a recombinant inbred set, \
+ when you submit your data will be displayed in a form where you can \
+ confirm and/or edit them. If you enter a file name here, any data \
+ that you paste into the next section will be ignored.')
+
+ filebox = HT.Paragraph(HT.Input(type='file', name='variancefile', size=20))
+
+ OR = HT.Paragraph(HT.Center(HT.Font(HT.Strong('OR'),color="red")))
+
+ Para2 = HT.Paragraph()
+ Para2.append(HT.Strong("By Pasting or Typing Multiple Values:"))
+ Para2.append('You can enter data by pasting a series of numbers \
+ representing variance values into this area. The values can be on one \
+ line separated by spaces or tabs, or they can be on separate lines. \
+ Include one value for each progeny individual or recombinant inbred \
+ line. Represent missing values with a non-numeric character such as \
+ "x". If you have chosen a recombinant inbred set, when you submit \
+ your data will be displayed in a form where you can confirm and/or \
+ edit them. If you enter a file name in the previous section, any data\
+ that you paste here will be ignored.')
+
+ pastebox = HT.Paragraph(HT.Textarea(name='variancepaste', cols=45, rows=6))
+ # NL, 07/27/2010. variable 'IMGSTEP1' has been moved from templatePage.py to webqtlUtil.py;
+ TD1 = HT.TD(webqtlUtil.IMGSTEP1,width=58)
+ TD2 = HT.TD()
+ TD2.append(Para1,filebox,OR,Para2,pastebox)
+ STEP2.append(HT.TR(TD1,TD2),HT.TR(HT.TD(colspan=2,height=20)))
+ #########################################
+
+ hddn = {'FormID':'varianceChoice','submitID':'next','RISet':fd.RISet}
+ if fd.identification:
+ hddn['identification'] = fd.identification
+ if fd.enablevariance:
+ hddn['enablevariance']='ON'
+
+ if fd.incparentsf1:
+ hddn['incparentsf1']='ON'
+
+ for item, value in fd.allTraitData.items():
+ if value.val:
+ hddn[item] = value.val
+
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), \
+ enctype='multipart/form-data', name='crossChoice', submit=HT.Input(type=\
+ 'hidden'))
+
+ submit = HT.Input(type='button' ,name='next', value='Next',onClick=\
+ 'showNext(this.form);',Class="button")
+ reset = HT.Input(type='reset' ,name='reset' ,value='Reset',Class="button")
+
+ #########################################
+ title3 = HT.Paragraph("&nbsp;&nbsp;2. Submit:")
+ title3.__setattr__("class","subtitle")
+
+ STEP3 = HT.TableLite(cellSpacing=2,cellPadding=0,width="90%",border=0)
+
+ # NL, 07/27/2010. variable 'IMGSTEP2' has been moved from templatePage.py to webqtlUtil.py;
+ TD1 = HT.TD(webqtlUtil.IMGSTEP2,width=58)
+ TD2 = HT.TD()
+ TD2.append(HT.Blockquote("Click the next button to submit your variance\
+ data for editing and mapping."),HT.Center(submit,reset))
+ STEP3.append(HT.TR(TD1,TD2),HT.TR(HT.TD(colspan=2,height=20)))
+
+ #########################################
+
+ # NL, 07/27/2010. variable 'IMGNEXT' has been moved from templatePage.py to webqtlUtil.py;
+ form.append(title2,HT.Center(STEP2,webqtlUtil.IMGNEXT),title3,HT.Center(STEP3))
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ TD_RIGHT.append(main_title,form)
+
+ self.dict['body'] = TD_LEFT + str(TD_RIGHT)
diff --git a/web/webqtl/submitTrait/__init__.py b/web/webqtl/submitTrait/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/submitTrait/__init__.py
diff --git a/web/webqtl/textUI/__init__.py b/web/webqtl/textUI/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/textUI/__init__.py
diff --git a/web/webqtl/textUI/cmdClass.py b/web/webqtl/textUI/cmdClass.py
new file mode 100755
index 00000000..e394218e
--- /dev/null
+++ b/web/webqtl/textUI/cmdClass.py
@@ -0,0 +1,224 @@
+import string
+import os
+import MySQLdb
+
+from base import webqtlConfig
+
+#########################################
+# Basic Class
+#########################################
+class cmdClass:
+ def __init__(self,fd):
+ self.contents = []
+ self.accessError = 0
+ self.error = 0
+ self.accessCode = '###Database Code : <a href="%s%s?cmd=help">%s%s?cmd=help</a>' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)
+ self.data = fd.formdata
+ self.cmdID = self.data.getvalue('cmd')
+ self.showurl = self.data.getvalue('url')
+ self.cursor = None
+ self.user_ip = fd.remote_ip
+
+ try:
+ if not self.openMysql():
+ self.accessError = 1
+ self.contents = ['###Error: Database is not ready']
+ return
+
+ if not self.accessCount():
+ self.accessError = 1
+ self.contents = ['###Error: You have reached maximum access today ']
+ return
+ self.accessRecord()
+ except:
+ self.accessError = 1
+ self.contents = ['###Error: Database is not ready']
+ return
+
+
+ self.probeset = self.data.getvalue('probeset')
+ self.database = self.data.getvalue('db')
+ self.probe = self.data.getvalue('probe')
+
+ self.sourcedata = []
+
+
+ try:
+ self.format = self.data.getvalue('format')[:3]
+ except:
+ self.format = 'row'
+ if not self.probeset or not self.database:
+ self.error = 1
+ return
+
+ def openMysql(self):
+ try:
+ # con = MySQLdb.Connect(db='db_webqtl', host = webqtlConfig.MYSQL_SERVER)
+ # Modified by Fan Zhang
+ con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+ self.cursor = con.cursor()
+ return 1
+ except:
+ return 0
+
+ #XZ, 03/23/2009: The function name is confusing. This function is to get the database type(ProbeSet, Publish, Geno) id.
+ def getDBId(self,code):
+ self.cursor.execute('SELECT DBType.Name, DBList.FreezeId from DBType, DBList WHERE DBType.Id = DBList.DBTypeId and DBList.code= "%s"' % code)
+ result = self.cursor.fetchall()
+ if not result:
+ return (None, None)
+ else:
+ return result[0]
+
+ #XZ, 03/23/2009: This is to get the inbredset name.
+ def getRISet(self,prefix, DbId):
+ if prefix == 'ProbeSet':
+ self.cursor.execute('SELECT InbredSet.Name from InbredSet, ProbeSetFreeze, ProbeFreeze WHERE ProbeFreeze.InbredSetId = InbredSet.Id and ProbeFreeze.Id = ProbeSetFreeze.ProbeFreezeId and ProbeSetFreeze.Id = %d' % DbId)
+ else:
+ self.cursor.execute('SELECT InbredSet.Name from %sFreeze, InbredSet WHERE %sFreeze.InbredSetId = InbredSet.Id and %sFreeze.Id = %d' % (prefix, prefix, prefix, DbId))
+ result = self.cursor.fetchall()
+ if result:
+ if result[0][0] == "BXD300":
+ return "BXD"
+ else:
+ return result[0][0]
+ else:
+ return None
+
+ def accessCount(self):
+ try:
+ user_ip = self.user_ip
+ query = """SELECT count(id) FROM AccessLog WHERE ip_address = %s AND UNIX_TIMESTAMP()-UNIX_TIMESTAMP(accesstime)<86400"""
+ self.cursor.execute(query,user_ip)
+ daycount = self.cursor.fetchall()
+ if daycount:
+ daycount = daycount[0][0]
+ if daycount > webqtlConfig.DAILYMAXIMUM:
+ return 0
+ else:
+ return 1
+ else:
+ return 1
+ except:
+ return 0
+
+ def accessRecord(self):
+ try:
+ user_ip = self.user_ip
+ self.updMysql()
+ query = """INSERT INTO AccessLog(accesstime,ip_address) values(Now(),%s)"""
+ self.cursor.execute(query,user_ip)
+ self.openMysql()
+ except:
+ pass
+
+ def __str__(self):
+ text = map(str,self.contents)
+ if self.showurl:
+ text.append('http://%s%s?%s' % (os.environ['HTTP_HOST'],os.environ['SCRIPT_NAME'],os.environ['QUERY_STRING'][:-8]))
+ text += self.sourcedata
+ return string.join(text,'\n')
+
+ def write(self):
+ if self.cursor:
+ self.cursor.close()
+ try:
+ browser = os.environ['HTTP_USER_AGENT']
+ return '<pre>%s</pre>' % str(self)
+ except:
+ return str(self)
+
+ def write2(self):
+ print str(self)
+
+ def getTraitData(self, prefix, dbId, probeset, probe = None):
+ headerDict = {'ProbeSet':'ProbeSetID', 'Publish':'RecordID', 'Geno':'Locus'}
+ if prefix == None or dbId == None:
+ return None, None
+ if probe and prefix=='ProbeSet':
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=get&probeset=98332_at&db=bra08-03MAS5&probe=pm&format=col
+ if string.lower(probe) in ("all","mm","pm"):
+ query = "SELECT Probe.Name from Probe, ProbeSet WHERE Probe.ProbeSetId = ProbeSet.Id and ProbeSet.Name = '%s' order by Probe.Name" % probeset
+ self.cursor.execute(query)
+ allprobes = self.cursor.fetchall()
+ if not allprobes:
+ return None, None
+
+ fetchprobes = []
+ for item in allprobes:
+ if probe == 'all':
+ fetchprobes.append(item[0])
+ else:
+ try:
+ taildigit = int(item[0][-1]) % 2
+ if probe == "pm" and taildigit == 1:
+ fetchprobes.append(item[0])
+ if probe == "mm" and taildigit == 0:
+ fetchprobes.append(item[0])
+ except:
+ pass
+ if not fetchprobes:
+ return None, None
+ #XZ, 03/05/2009: Xiaodong changed Data to ProbeData
+ query = "SELECT Strain.Name, ProbeData.value, Probe.Name from ProbeData, ProbeFreeze, ProbeSetFreeze, ProbeXRef, Strain, Probe, ProbeSet WHERE ProbeSet.Name = '%s' and Probe.ProbeSetId = ProbeSet.Id and ProbeXRef.ProbeId = Probe.Id and ProbeXRef.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Id = %d and ProbeXRef.DataId = ProbeData.Id and ProbeData.StrainId = Strain.Id and Probe.Name in (%s) order by Strain.Id, Probe.Name " % (probeset,dbId, "'" + string.join(fetchprobes, "', '") +"'")
+ self.cursor.execute(query)
+ traitdata = self.cursor.fetchall()
+ if not traitdata:
+ pass
+ else:
+ nfield = len(fetchprobes)
+ heads = [['ProbeSet'] + [probeset]*nfield]
+ heads.append(['probe'] + fetchprobes)
+ posdict = {}
+ i = 0
+ for item in fetchprobes:
+ posdict[item] = i
+ i += 1
+ prevStrain = ''
+ traitdata2 = []
+ i = -1
+ for item in traitdata:
+ if item[0] != prevStrain:
+ prevStrain = item[0]
+ i += 1
+ traitdata2.append([item[0]] + [None] * nfield)
+ else:
+ pass
+ traitdata2[i][posdict[item[-1]]+1] = item[1]
+
+ traitdata = traitdata2
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=get&probeset=98332_at&db=bra08-03MAS5&probe=119637&format=col
+ else:
+ heads = [('ProbeSetId', probeset), ('ProbeId',probe)]
+ #XZ, 03/05/2009: Xiaodong changed Data to ProbeData
+ query = "SELECT Strain.Name, ProbeData.value from ProbeData, ProbeFreeze, ProbeSetFreeze, ProbeXRef, Strain, Probe, ProbeSet WHERE Probe.Name = '%s' and ProbeSet.Name = '%s' and Probe.ProbeSetId = ProbeSet.Id and ProbeXRef.ProbeId = Probe.Id and ProbeXRef.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Id = %d and ProbeXRef.DataId = ProbeData.Id and ProbeData.StrainId = Strain.Id" % (probe,probeset,dbId)
+ #print 'Content-type: text/html\n'
+ self.cursor.execute(query)
+ traitdata = self.cursor.fetchall()
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=get&probeset=98332_at&db=bra08-03MAS5&format=col
+ elif prefix=='ProbeSet': #XZ: probeset data
+ heads = [(headerDict[prefix], probeset)]
+ query = "SELECT Strain.Name, %sData.value from %sData, Strain, %s, %sXRef WHERE %s.Name = '%s' and %sXRef.%sId = %s.Id and %sXRef.%sFreezeId = %d and %sXRef.DataId = %sData.Id and %sData.StrainId = Strain.Id order by Strain.Id" % (prefix, prefix, prefix, prefix, prefix, probeset,prefix, prefix, prefix, prefix, prefix, dbId, prefix, prefix, prefix)
+ self.cursor.execute(query)
+ traitdata = self.cursor.fetchall()
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=get&probeset=10834&db=BXDPublish&format=col
+ elif prefix=='Publish':
+ heads = [(headerDict[prefix], probeset)]
+ #XZ, 03/05/2009: Xiaodong changed Data to PublishData
+ query = "SELECT Strain.Name, PublishData.value from PublishData, Strain, PublishXRef, PublishFreeze WHERE PublishXRef.InbredSetId = PublishFreeze.InbredSetId and PublishData.Id = PublishXRef.DataId and PublishXRef.Id = %s and PublishFreeze.Id = %d and PublishData.StrainId = Strain.Id" % (probeset, dbId)
+ self.cursor.execute(query)
+ traitdata = self.cursor.fetchall()
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=get&probeset=rs13475701&db=BXDGeno&format=col
+ else: #XZ: genotype data
+ heads = [(headerDict[prefix], probeset)]
+ RISet = self.getRISet(prefix, dbId)
+ self.cursor.execute("select SpeciesId from InbredSet where Name = '%s'" % RISet)
+ speciesId = self.cursor.fetchone()[0]
+ #XZ, 03/05/2009: Xiaodong changed Data to %sData
+ query = "SELECT Strain.Name, %sData.value from %sData, Strain, %s, %sXRef WHERE %s.SpeciesId=%s and %s.Name = '%s' and %sXRef.%sId = %s.Id and %sXRef.%sFreezeId = %d and %sXRef.DataId = %sData.Id and %sData.StrainId = Strain.Id order by Strain.Id" % (prefix, prefix, prefix, prefix, prefix, speciesId, prefix, probeset,prefix, prefix, prefix, prefix, prefix, dbId, prefix, prefix, prefix)
+ self.cursor.execute(query)
+ traitdata = self.cursor.fetchall()
+ if traitdata:
+ return traitdata, heads
+ else:
+ return None, None
diff --git a/web/webqtl/textUI/cmdCorrelation.py b/web/webqtl/textUI/cmdCorrelation.py
new file mode 100755
index 00000000..04595fc5
--- /dev/null
+++ b/web/webqtl/textUI/cmdCorrelation.py
@@ -0,0 +1,325 @@
+# 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
+
+import os
+import string
+from math import *
+import time
+
+import reaper
+
+from base import webqtlConfig
+from utility import webqtlUtil
+from cmdClass import cmdClass
+
+
+#########################################
+# Correlation Class
+#########################################
+class cmdCorrelation(cmdClass):
+
+ calFunction = 'webqtlUtil.calCorrelation'
+
+ def __init__(self,fd=None):
+
+ cmdClass.__init__(self,fd)
+
+ if not webqtlConfig.TEXTUI:
+ self.contents.append("Please send your request to http://robot.genenetwork.org")
+ return
+
+
+ self.example = '###Example : <a href="%s%s?cmd=%s&probeset=100001_at&probe=136415&db=bra03-03Mas5&searchdb=BXDPublish&return=500&sort=pvalue">%s%s?cmd=%s&probeset=100001_at&probe=136415&db=bra03-03Mas5&searchdb=BXDPublish&return=500&sort=pvalue</a>' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID, webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID)
+
+ if self.accessError:
+ return
+
+ self.searchDB = self.data.getvalue('searchdb')
+ if not self.searchDB or self.error:
+ self.contents.append("###Error: source trait doesn't exist or no target database was given")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+
+ try:
+ self.returnNumber = int(self.data.getvalue('return'))
+ except:
+ self.returnNumber = None
+
+ self.sort = self.data.getvalue('sort')
+
+ prefix, dbId = self.getDBId(self.database)
+ if not prefix or not dbId or (self.probe and string.lower(self.probe) in ("all","mm","pm")):
+ self.contents.append("###Error: source trait doesn't exist or SELECT more than one trait.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+ RISet = self.getRISet(prefix, dbId)
+ prefix2, dbId2 = self.getDBId(self.searchDB)
+ if not prefix2 or not dbId2:
+ self.contents.append("###Error: target database doesn't exist.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+ RISet2 = self.getRISet(prefix2, dbId2)
+ if RISet2 != RISet:
+ self.contents.append("###Error: target database has different Mouse InbredSet.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+
+ traitdata, heads = self.getTraitData(prefix, dbId, self.probeset, self.probe)
+ if not traitdata:
+ self.contents.append("###Error: source trait doesn't exist.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+
+ StrainNames = []
+ sourceTrait = []
+ StrainIds = []
+
+ #XZ, Jan 27, 2011: Only the strains that are of the same inbredset are used to calculate correlation.
+ for item in traitdata:
+ one_strain_name = item[0]
+ one_strain_value = item[1]
+
+ self.cursor.execute('SELECT Strain.Id from Strain,StrainXRef, InbredSet WHERE Strain.Name="%s" and Strain.Id = StrainXRef.StrainId and StrainXRef.InbredSetId = InbredSet.Id and InbredSet.Name = "%s"' % (one_strain_name, RISet2))
+ Results = self.cursor.fetchall()
+ if Results:
+ StrainIds.append('%d' % Results[0][0])
+ StrainNames.append( one_strain_name )
+ sourceTrait.append( one_strain_value )
+
+ correlationArray = []
+
+ useFastMethod = False
+ if prefix2 == "ProbeSet":
+ DatabaseFileName = self.getFileName( target_db_id=dbId2 )
+ DirectoryList = os.listdir(webqtlConfig.TEXTDIR) ### List of existing text files. Used to check if a text file already exists
+ if DatabaseFileName in DirectoryList:
+ useFastMethod = True
+
+ if useFastMethod:
+ datasetFile = open(webqtlConfig.TEXTDIR+DatabaseFileName,'r')
+
+ #XZ, 01/08/2009: read the first line
+ line = datasetFile.readline()
+ dataset_strains = webqtlUtil.readLineCSV(line)[1:]
+
+ #XZ, 01/08/2009: This step is critical. It is necessary for this new method.
+ _newvals = []
+ for item in dataset_strains:
+ if item in StrainNames:
+ _newvals.append(sourceTrait[StrainNames.index(item)])
+ else:
+ _newvals.append('None')
+
+ nnCorr = len(_newvals)
+
+
+ for line in datasetFile:
+ traitdata=webqtlUtil.readLineCSV(line)
+ traitdataName = traitdata[0]
+ traitvals = traitdata[1:]
+
+ corr,nOverlap = webqtlUtil.calCorrelationText(traitvals,_newvals,nnCorr)
+ traitinfo = [traitdataName,corr,nOverlap]
+ correlationArray.append( traitinfo )
+
+ #calculate correlation with slow method
+ else:
+ correlationArray = self.calCorrelation(sourceTrait, self.readDB(StrainIds, prefix2, dbId2) )
+
+ correlationArray.sort(self.cmpCorr) #XZ: Do not forget the sort step
+
+ if not self.returnNumber:
+ correlationArray = correlationArray[:100]
+ else:
+ if self.returnNumber < len(correlationArray):
+ correlationArray = correlationArray[:self.returnNumber]
+ NN = len(correlationArray)
+ for i in range(NN):
+ nOverlap = correlationArray[i][-1]
+ corr = correlationArray[i][-2]
+ if nOverlap < 3:
+ corrPValue = 1.0
+ else:
+ if abs(corr) >= 1.0:
+ corrPValue = 0.0
+ else:
+ ZValue = 0.5*log((1.0+corr)/(1.0-corr))
+ ZValue = ZValue*sqrt(nOverlap-3)
+ corrPValue = 2.0*(1.0 - reaper.normp(abs(ZValue)))
+ correlationArray[i].append(corrPValue)
+ if self.sort == 'pvalue':
+ correlationArray.sort(self.cmpPValue)
+
+ if prefix2 == 'Publish':
+ self.contents.append("RecordID\tCorrelation\t#Strains\tp-value")
+ elif prefix2 == 'Geno':
+ self.contents.append("Locus\tCorrelation\t#Strains\tp-value")
+ else:
+ pass
+
+ if prefix2 == 'Publish' or prefix2 == 'Geno':
+ for item in correlationArray:
+ self.contents.append("%s\t%2.6f\t%d\t%2.6f" % tuple(item))
+ else:
+ id = self.data.getvalue('id')
+ if id == 'yes':
+ self.contents.append("ProbesetID\tCorrelation\t#Strains\tp-value\tGeneID")
+ for item in correlationArray:
+ query = """SELECT GeneID from %s WHERE Name = '%s'""" % (prefix2,item[0])
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+ if not results:
+ item = item + [None]
+ else:
+ item = item + list(results[0])
+ self.contents.append("%s\t%2.6f\t%d\t%2.6f\t%s" % tuple(item))
+ elif id == 'only':
+ self.contents.append("GenID")
+ for item in correlationArray:
+ query = """SELECT GeneID from %s WHERE Name = '%s'""" % (prefix2,item[0])
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+ if not results:
+ self.contents.append('None')
+ else:
+ self.contents.append(results[0][0])
+ else:
+ self.contents.append("ProbesetID\tCorrelation\t#Strains\tp-value")
+ for item in correlationArray:
+ self.contents.append("%s\t%2.6f\t%d\t%2.6f" % tuple(item))
+
+
+
+
+ def getFileName(self, target_db_id):
+
+ query = 'SELECT Id, FullName FROM ProbeSetFreeze WHERE Id = %s' % target_db_id
+ self.cursor.execute(query)
+ result = self.cursor.fetchone()
+ Id = result[0]
+ FullName = result[1]
+ FullName = FullName.replace(' ','_')
+ FullName = FullName.replace('/','_')
+
+ FileName = 'ProbeSetFreezeId_' + str(Id) + '_FullName_' + FullName + '.txt'
+
+ return FileName
+
+
+
+ def calCorrelation(self,source,target):
+ allcorrelations = []
+ NN = len(source)
+
+ if len(source) != len(target[0]) - 1:
+ return allcorrelations
+ else:
+ for traitData in target:
+ corr,nOverlap = eval("%s(traitData[1:],source,NN)" % self.calFunction)
+ traitinfo = [traitData[0],corr,nOverlap]
+ allcorrelations.append(traitinfo)
+
+ return allcorrelations
+
+ def cmpCorr(self,A,B):
+ try:
+ if abs(A[1]) < abs(B[1]):
+ return 1
+ elif abs(A[1]) == abs(B[1]):
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+ def cmpPValue(self,A,B):
+ try:
+ if A[-1] > B[-1]:
+ return 1
+ elif A[-1] == B[-1]:
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+
+ def readDB(self, StrainIds=[], prefix2='', dbId2=''):
+
+ #retrieve data from target database
+ nnn = len(StrainIds) / 25
+ if len(StrainIds) % 25:
+ nnn += 1
+ oridata = []
+ for step in range(nnn):
+ temp = []
+ StrainIdstep = StrainIds[step*25:min(len(StrainIds), (step+1)*25)]
+ for item in StrainIdstep:
+ temp.append('T%s.value' % item)
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=cor&probeset=100001_at&probe=136415&db=bra08-03MAS5&searchdb=BXDPublish&return=500&sort=pvalue
+ if prefix2 == "Publish":
+ query = "SELECT PublishXRef.Id, "
+ dataStartPos = 1
+ query += string.join(temp,', ')
+ query += ' from (PublishXRef, PublishFreeze)\n'
+ #XZ, 03/05/2009: Xiaodong changed Data to PublishData
+ for item in StrainIdstep:
+ query += 'left join PublishData as T%s on T%s.Id = PublishXRef.DataId and T%s.StrainId=%s\n' %(item,item,item,item)
+ query += "WHERE PublishXRef.InbredSetId = PublishFreeze.InbredSetId and PublishFreeze.Id = %d" % (dbId2, )
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=cor&probeset=100001_at&probe=136415&db=bra08-03MAS5&searchdb=HC_M2_1005_M&return=500&sort=pvalue
+ #XZ, 03/05/2009: test http://www.genenetwork.org/webqtl/WebQTL.py?cmd=cor&probeset=100001_at&probe=136415&db=bra08-03MAS5&searchdb=BXDGeno&return=500&sort=pvalue
+ else:
+ query = "SELECT %s.Name," % prefix2
+ query += string.join(temp,', ')
+ query += ' from (%s, %sXRef, %sFreeze) \n' % (prefix2,prefix2,prefix2)
+ #XZ, 03/05/2009: Xiaodong changed Data to %sData
+ for item in StrainIdstep:
+ query += 'left join %sData as T%s on T%s.Id = %sXRef.DataId and T%s.StrainId=%s\n' %(prefix2,item,item,prefix2,item,item)
+ query += "WHERE %sXRef.%sFreezeId = %sFreeze.Id and %sFreeze.Id = %d and %s.Id = %sXRef.%sId" % (prefix2, prefix2, prefix2, prefix2, dbId2, prefix2, prefix2, prefix2)
+ self.cursor.execute(query)
+ results = self.cursor.fetchall()
+ if not results:
+ self.contents.append("###Error: target database doesn't exist.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+ oridata.append(results)
+
+ datasize = len(oridata[0])
+ targetTrait = []
+ for j in range(datasize):
+ traitdata = list(oridata[0][j])
+ for i in range(1,nnn):
+ traitdata += list(oridata[i][j][1:])
+ targetTrait.append(traitdata)
+
+ return targetTrait
+
diff --git a/web/webqtl/textUI/cmdGeno.py b/web/webqtl/textUI/cmdGeno.py
new file mode 100755
index 00000000..8dd0f924
--- /dev/null
+++ b/web/webqtl/textUI/cmdGeno.py
@@ -0,0 +1,118 @@
+# 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
+
+import string
+import os
+
+import reaper
+
+from base import webqtlConfig
+from cmdClass import cmdClass
+
+#########################################
+# Geno Class
+#########################################
+class cmdGeno(cmdClass):
+
+ def __init__(self,fd=None):
+
+ cmdClass.__init__(self,fd)
+
+ if not webqtlConfig.TEXTUI:
+ self.contents.append("Please send your request to http://robot.genenetwork.org")
+ return
+
+ if self.accessError:
+ return
+ self.error = 0
+ self.RISet = None
+ self.chr = None
+ self.dataset = None
+ self.strainList = []
+ try:
+ self.RISet = self.data.getvalue('riset')
+ if not self.RISet:
+ raise ValueError
+ except:
+ self.error = 1
+ self.contents.append('###Example : http://www.genenetwork.org%s%s?cmd=%s&riset=BXD&chr=1' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID))
+ return
+ try:
+ self.format = self.data.getvalue('format')[:3]
+ except:
+ self.format = 'row'
+
+ try:
+ self.dataset = reaper.Dataset()
+ try:
+ self.dataset.read(os.path.join(webqtlConfig.GENODIR, self.RISet + '.geno'))
+ except:
+ self.dataset.read(os.path.join(webqtlConfig.GENODIR, self.RISet.upper() + '.geno'))
+ self.strainList = list(self.dataset.prgy)
+ except:
+ self.error = 1
+ #traceback.print_exc()
+ self.contents.append('###The name of RISet is incorrect')
+ return
+
+ try:
+ self.chr = self.data.getvalue('chr')
+ if self.chr:
+ if self.chr == 'X' or self.chr == 'x':
+ self.chr = '20'
+ self.chr = int(self.chr)
+ except:
+ pass
+
+ self.readGeno()
+
+ def readGeno(self):
+ try:
+ table = [['Chr'] + ['Locus'] + self.strainList]
+ if self.chr:
+ chr = self.dataset[self.chr-1]
+ for locus in chr:
+ items = string.split(string.join(locus.genotext, " "))
+ items = [chr.name] + [locus.name] + items
+ table += [items]
+ else:
+ for chr in self.dataset:
+ for locus in chr:
+ items = string.split(string.join(locus.genotext, " "))
+ items = [chr.name] + [locus.name] + items
+ table += [items]
+ if self.format == 'col':
+ table = [[r[col] for r in table] for col in range(1, len(table[0]))]
+ table[0][0] = 'Line'
+ lines = string.join(map(lambda x: string.join(x, '\t'), table), '\n')
+ self.contents.append(lines)
+ except:
+ self.contents =['###Error: Read file error or name of chromosome is incorrect']
+ #traceback.print_exc()
+ return
+
+
+
diff --git a/web/webqtl/textUI/cmdGet.py b/web/webqtl/textUI/cmdGet.py
new file mode 100755
index 00000000..a11c97a3
--- /dev/null
+++ b/web/webqtl/textUI/cmdGet.py
@@ -0,0 +1,86 @@
+# 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
+
+import string
+
+from base import webqtlConfig
+from cmdClass import cmdClass
+
+#########################################
+# Get trait value Class
+#########################################
+class cmdGet(cmdClass):
+ def __init__(self,fd=None):
+
+ cmdClass.__init__(self,fd)
+
+ if not webqtlConfig.TEXTUI:
+ self.contents.append("Please send your request to http://robot.genenetwork.org")
+ return
+
+ self.example = '###Example : <a href="%s%s?cmd=%s&probeset=100001_at&db=bra03-03Mas5&probe=all">%s%s?cmd=%s&probeset=100001_at&db=bra03-03Mas5&probe=all</a>' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID, webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID)
+ if self.accessError:
+ return
+ if not self.error:
+ self.readDB()
+ else:
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+
+ def readDB(self):
+ prefix, dbId = self.getDBId(self.database)
+
+ traitdata, heads = self.getTraitData(prefix, dbId, self.probeset, self.probe)
+ try:
+ if not traitdata:
+ raise ValueError
+ traitdata = heads + list(traitdata)
+ if self.format == 'col':
+ self.formatCols(traitdata)
+ else:
+ self.formatRows(traitdata)
+ except:
+ self.contents.append('Error: no record was found')
+ self.contents.append(self.accessCode)
+ return
+
+ def formatCols(self, traitdata):
+ for item in traitdata:
+ lines = []
+ for item2 in item:
+ lines.append(item2)
+ lines = string.join(map(str,lines), '\t')
+ self.contents.append(lines)
+
+ def formatRows(self, traitdata):
+ for i in range(len(traitdata[0])):
+ lines = []
+ for j in range(len(traitdata)):
+ lines.append(traitdata[j][i])
+ lines = string.join(map(str,lines), '\t')
+ self.contents.append(lines)
+
+
diff --git a/web/webqtl/textUI/cmdHelp.py b/web/webqtl/textUI/cmdHelp.py
new file mode 100755
index 00000000..754ff5b5
--- /dev/null
+++ b/web/webqtl/textUI/cmdHelp.py
@@ -0,0 +1,105 @@
+# 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
+
+import string
+
+from base import webqtlConfig
+from base.admin import ADMIN_tissue_alias
+from cmdClass import cmdClass
+
+#########################################
+# Help Class
+#########################################
+
+#XZ, 03/23/2009: There are several issues need attention.
+#1. Some probeset datasets are not added into DBList.
+#2. Do NOT show confidential datasets.
+#3. Get rid of ADMIN_tissue_alias. We should use info from database instead.
+
+class cmdHelp(cmdClass):
+ def __init__(self,fd=None):
+
+ cmdClass.__init__(self,fd)
+
+ if not webqtlConfig.TEXTUI:
+ self.contents.append("Please send your request to http://robot.genenetwork.org")
+ return
+
+
+ machineParse = self.data.getvalue('parse')
+ topic = self.data.getvalue('topic')
+ if topic:
+ topic = topic.lower()
+ if topic == 'tissue':
+ self.contents.append("%s%s| %s" %("Tissue", ' '*(50-len("Tissue")), "Tissue Abbreviations"))
+ self.contents.append("%s%s| %s" %("", ' '*50, "(Separated by space, case insensitive)"))
+ self.contents.append("%s|%s" %('_'*50, '_'*40))
+
+ keys = ADMIN_tissue_alias.keys()
+ keys.sort()
+ for key in keys:
+ self.contents.append("%s%s| %s" % (key , ' '*(50-len(key)), string.join(ADMIN_tissue_alias[key], " ")))
+ self.contents.append("%s|%s" %('_'*50, '_'*40))
+ else:
+ pass
+ else:
+ self.contents = ["#Use database code table below to access data", "#For machine parse friendly output please use",
+ "#http://www.genenetwork.org%s%s?cmd=help&parse=machine" % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)]
+ self.cursor.execute("""(SELECT DBType.Name, DBList.FreezeId, DBList.Code, ProbeSetFreeze.CreateTime as Time
+ from ProbeSetFreeze, DBType, DBList WHERE DBType.Id = DBList.DBTypeId and
+ DBType.Name = 'ProbeSet' and DBList.FreezeId = ProbeSetFreeze.Id and
+ ProbeSetFreeze.public > %d order by ProbeSetFreeze.CreateTime ,DBList.Name, DBList.Id)
+ UNION
+ (SELECT DBType.Name, DBList.FreezeId, DBList.Code, PublishFreeze.CreateTime as Time
+ from PublishFreeze, DBType, DBList WHERE DBType.Id = DBList.DBTypeId and
+ DBType.Name = 'Publish' and DBList.FreezeId = PublishFreeze.Id order by
+ PublishFreeze.CreateTime ,DBList.Name, DBList.Id)
+ UNION
+ (SELECT DBType.Name, DBList.FreezeId, DBList.Code, GenoFreeze.CreateTime
+ from GenoFreeze, DBType, DBList WHERE DBType.Id = DBList.DBTypeId and
+ DBType.Name = 'Geno' and DBList.FreezeId = GenoFreeze.Id order by
+ GenoFreeze.CreateTime ,DBList.Name, DBList.Id)""" % webqtlConfig.PUBLICTHRESH)
+ dbs = self.cursor.fetchall()
+ if machineParse =="machine":
+ pass
+ else:
+ self.contents.append("\n")
+ self.contents.append("%s%s| %s" %("Database_Name", ' '*(50-len("Database_Name")), "Database_Access_Code_Name"))
+ self.contents.append("%s|%s" %('_'*50, '_'*40))
+ for dbInfo in dbs:
+ self.cursor.execute('SELECT FullName from %sFreeze WHERE Id = %d and public > %d' % (dbInfo[0], dbInfo[1],webqtlConfig.PUBLICTHRESH))
+ results = self.cursor.fetchall()
+ if not results:
+ pass
+ else:
+ if machineParse =="machine":
+ self.contents.append(results[0][0]+ ',' +dbInfo[2])
+ else:
+ self.contents.append("%s%s| %s" %(results[0][0], ' '*(50-len(results[0][0])), dbInfo[2]))
+ self.contents.append("%s|%s" %('_'*50, '_'*40))
+
+
+
diff --git a/web/webqtl/textUI/cmdInterval.py b/web/webqtl/textUI/cmdInterval.py
new file mode 100755
index 00000000..0b97c7c3
--- /dev/null
+++ b/web/webqtl/textUI/cmdInterval.py
@@ -0,0 +1,174 @@
+# 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
+
+import string
+import os
+
+import reaper
+
+from base import webqtlConfig
+from cmdClass import cmdClass
+
+#########################################
+# Interval Mapping Class
+#########################################
+class cmdInterval(cmdClass):
+
+ def __init__(self,fd=None):
+
+ cmdClass.__init__(self,fd)
+
+ if not webqtlConfig.TEXTUI:
+ self.contents.append("Please send your request to http://robot.genenetwork.org")
+ return
+
+
+ self.example = '###Example : <a href="%s%s?cmd=%s&probeset=100001_at&probe=136415&db=bra03-03Mas5&sort=pos&return=100&chr=12">%s%s?cmd=%s&probeset=100001_at&probe=136415&db=bra03-03Mas5&sort=pos&return=100&chr=12</a>' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID, webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID)
+ if self.accessError:
+ return
+ self.sort = None
+ self.step = 0.01
+ self.peak = 1
+ self.chr = None
+ self.sort = None
+ self.returnnumber = 20
+ if self.error:
+ self.error = 1
+ self.contents.append(self.example)
+ return
+ else:
+ try:
+ self.sort = self.data.getvalue('sort')
+ if string.lower(self.sort) == 'pos':
+ self.sort = 'pos'
+ else:
+ self.sort = 'lrs'
+ except:
+ self.sort = None
+
+ try:
+ self.returnnumber = int(self.data.getvalue('return'))
+ except:
+ self.returnnumber = 20
+ try:
+ self.chr = self.data.getvalue('chr')
+ except:
+ self.chr = None
+
+ self.readDB()
+
+ def readDB(self):
+ prefix, dbId = self.getDBId(self.database)
+ if not prefix or not dbId or (self.probe and string.lower(self.probe) in ("all","mm","pm")):
+ self.contents.append("###Error: source trait doesn't exist or SELECT more than one trait.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+ RISet = self.getRISet(prefix, dbId)
+ traitdata, heads = self.getTraitData(prefix, dbId, self.probeset, self.probe)
+ if not traitdata:
+ self.contents.append("###Error: source trait doesn't exist or SELECT more than one trait.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+
+ dataset0 = reaper.Dataset()
+ dataset0.read(os.path.join(webqtlConfig.GENODIR, RISet + '.geno'))
+ strainList = list(dataset0.prgy)
+ dataset = dataset0.addinterval()
+ if self.chr != None:
+ for _chr in dataset:
+ if string.lower(_chr.name) == string.lower(self.chr):
+ dataset.chromosome = [_chr]
+ break
+
+ strains = []
+ trait = []
+ _prgy = dataset.prgy
+ for item in traitdata:
+ if item[0] in _prgy:
+ strains.append(item[0])
+ trait.append(item[1])
+
+ qtlscan = dataset.regression(strains, trait)
+ LRS = dataset.permutation(strains, trait)
+ nperm = len(LRS)
+
+ #print inter1[0]
+ returnPeak = []
+ nqtl = len(qtlscan)
+ if self.peak:
+ for i in range(nqtl):
+ if i == 0 or qtlscan[i].locus.chr != qtlscan[i-1].locus.chr:
+ if qtlscan[i].lrs < qtlscan[i+1].lrs:
+ continue
+ elif i == nqtl-1 or qtlscan[i].locus.chr != qtlscan[i+1].locus.chr:
+ if qtlscan[i].lrs < qtlscan[i-1].lrs:
+ continue
+ else:
+ if qtlscan[i].lrs < qtlscan[i+1].lrs or qtlscan[i].lrs < qtlscan[i-1].lrs:
+ continue
+ returnPeak.append(qtlscan[i])
+ else:
+ returnPeak = qtlscan[:]
+
+ if returnPeak:
+ self.contents.append("Locus\tLRS\tChr\tAdditive\tp-value\tcM")
+ qtlresult = []
+ for item in returnPeak:
+ p_value = reaper.pvalue(item.lrs,LRS)
+ qtlresult.append((item.locus.name,item.lrs,item.locus.chr,item.additive,p_value, item.locus.cM))
+ if self.sort == 'lrs':
+ qtlresult.sort(self.cmpLRS2)
+ for item in qtlresult:
+ self.contents.append("%s\t%2.4f\t%s\t%2.4f\t%1.4f\t%s" % item)
+ else:
+ self.contents.append("###Error: Error occurs while regression.")
+ return
+
+ def cmpPValue(self,A,B):
+ try:
+ if A[-1] > B[-1]:
+ return 1
+ elif A[-1] == B[-1]:
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+ def cmpLRS2(self,A,B):
+ try:
+ if A[1] < B[1]:
+ return 1
+ elif A[1] == B[1]:
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+
diff --git a/web/webqtl/textUI/cmdMap.py b/web/webqtl/textUI/cmdMap.py
new file mode 100755
index 00000000..1fbff5a5
--- /dev/null
+++ b/web/webqtl/textUI/cmdMap.py
@@ -0,0 +1,144 @@
+# 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
+
+import string
+import os
+
+import reaper
+
+from base import webqtlConfig
+from cmdClass import cmdClass
+
+
+#########################################
+# Mapping Class
+#########################################
+class cmdMap(cmdClass):
+
+ def __init__(self,fd=None):
+
+ cmdClass.__init__(self,fd)
+
+ if not webqtlConfig.TEXTUI:
+ self.contents.append("Please send your request to http://robot.genenetwork.org")
+ return
+
+ self.example = '###Example : <a href="%s%s?cmd=%s&probeset=100001_at&probe=136415&db=bra03-03Mas5&sort=lrs&return=20">%s%s?cmd=%s&probeset=100001_at&probe=136415&db=bra03-03Mas5&sort=lrs&return=20</a>' % (webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID, webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE, self.cmdID)
+ if self.accessError:
+ return
+ try:
+ self.returnnumber = int(self.data.getvalue('return'))
+ except:
+ self.returnnumber = None
+
+ if self.error:
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ else:
+ self.sort = self.data.getvalue('sort')
+ self.readDB()
+
+ def readDB(self):
+ prefix, dbId = self.getDBId(self.database)
+ if not prefix or not dbId or (self.probe and string.lower(self.probe) in ("all","mm","pm")):
+ self.contents.append("###Error: source trait doesn't exist or SELECT more than one trait.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+ RISet = self.getRISet(prefix, dbId)
+ traitdata, heads = self.getTraitData(prefix, dbId, self.probeset, self.probe)
+ if not traitdata:
+ self.contents.append("###Error: source trait doesn't exist or SELECT more than one trait.")
+ self.contents.append(self.example)
+ self.contents.append(self.accessCode)
+ return
+
+ dataset = reaper.Dataset()
+ dataset.read(os.path.join(webqtlConfig.GENODIR, RISet + '.geno'))
+ strainList = list(dataset.prgy)
+
+ strains = []
+ trait = []
+ _prgy = dataset.prgy
+ for item in traitdata:
+ if item[0] in _prgy:
+ strains.append(item[0])
+ trait.append(item[1])
+
+ qtlscan = dataset.regression(strains, trait)
+ LRS = dataset.permutation(strains, trait)
+ nperm = len(LRS)
+ if qtlscan:
+ self.contents.append("Locus\tLRS\tChr\tAdditive\tp-value")
+ qtlresult = []
+ if self.returnnumber:
+ self.returnnumber = min(self.returnnumber,len(qtlscan))
+ if self.sort == 'lrs':
+ qtlscan.sort(self.cmpLRS)
+ for item in qtlscan[:self.returnnumber]:
+ p_value = reaper.pvalue(item.lrs,LRS)
+ qtlresult.append((item.locus.name,item.lrs,item.locus.chr,item.additive,p_value))
+ else:#sort by position
+ qtlscan2 = qtlscan[:]
+ qtlscan2.sort(self.cmpLRS)
+ LRSthresh = qtlscan2[self.returnnumber].lrs
+ for item in qtlscan:
+ if item.lrs >= LRSthresh:
+ p_value = reaper.pvalue(item.lrs,LRS)
+ qtlresult.append((item.locus.name,item.lrs,item.locus.chr,item.additive,p_value))
+ else:
+ for item in qtlscan:
+ p_value = reaper.pvalue(item.lrs,LRS)
+ qtlresult.append((item.locus.name,item.lrs,item.locus.chr,item.additive,p_value))
+ if self.sort == 'lrs':
+ qtlresult.sort(self.cmpLRS2)
+ for item in qtlresult:
+ self.contents.append("%s\t%2.5f\t%s\t%2.5f\t%1.5f" % item)
+ else:
+ self.contents.append("###Error: Error occurs while regression.")
+ return
+
+ def cmpLRS(self,A,B):
+ try:
+ if A.lrs < B.lrs:
+ return 1
+ elif A.lrs == B.lrs:
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+ def cmpLRS2(self,A,B):
+ try:
+ if A[1] < B[1]:
+ return 1
+ elif A[1] == B[1]:
+ return 0
+ else:
+ return -1
+ except:
+ return 0
diff --git a/web/webqtl/textUI/cmdSearchGene.py b/web/webqtl/textUI/cmdSearchGene.py
new file mode 100755
index 00000000..c2c71815
--- /dev/null
+++ b/web/webqtl/textUI/cmdSearchGene.py
@@ -0,0 +1,70 @@
+# 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
+
+import string
+
+from cmdClass import cmdClass
+from search.TextSearchPage import TextSearchPage
+
+#########################################
+# Search Gene Symbol PAGE
+#########################################
+class cmdSearchGene(cmdClass):
+ def __init__(self,fd):
+ #example
+ cmdClass.__init__(self,fd)
+ self.page = None
+ self.text = ""
+ fd.geneName = fd.formdata.getvalue('gene')
+ fd.returnFmt = fd.formdata.getvalue('format', 'html')
+ if fd.geneName:
+ fd.geneName = string.strip(fd.geneName)
+ fd.refseq = fd.formdata.getvalue('refseq')
+ if fd.refseq:
+ fd.refseq = string.strip(fd.refseq)
+ fd.genbankid = fd.formdata.getvalue('genbankid')
+ if fd.genbankid:
+ fd.genbankid = string.strip(fd.genbankid)
+ fd.geneid = fd.formdata.getvalue('geneid')
+ if fd.geneid:
+ fd.geneid = string.strip(fd.geneid)
+ if 1:
+ if not (fd.geneName or fd.refseq or fd.genbankid or fd.geneid):
+ raise "ValueError"
+ fd.searchAlias = fd.formdata.getvalue('alias')
+ if fd.searchAlias != '1':
+ fd.searchAlias = None
+ self.page = TextSearchPage(fd)
+ if fd.returnFmt != 'text':
+ pass
+ else:
+ self.text = self.page.output
+ self.page = None
+ elif "ValueError":
+ self.text = "You need to submit a Gene name, a Refseq ID, or a GenBank ID"
+ else:
+ self.text = "Error occurs while searching the database"
+
diff --git a/web/webqtl/textUI/cmdShowEditing.py b/web/webqtl/textUI/cmdShowEditing.py
new file mode 100755
index 00000000..918e83a7
--- /dev/null
+++ b/web/webqtl/textUI/cmdShowEditing.py
@@ -0,0 +1,50 @@
+# 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 cmdClass import cmdClass
+from showTrait.ShowTraitPage import ShowTraitPage
+
+
+#########################################
+# SHOW DATA-EDITING PAGE
+#########################################
+class cmdShowEditing(cmdClass):
+ def __init__(self,fd):
+ ###example = http://www.webqtl.org/cgi-bin/beta/WebQTL?cmd=snp&chr=1&start=0&end=21345677
+ cmdClass.__init__(self,fd)
+ self.page = None
+ prefix, dbId = self.getDBId(self.database)
+ try:
+ if not prefix or not dbId:
+ raise ValueError
+ self.cursor.execute('SELECT Name from %sFreeze WHERE Id=%d' % (prefix, dbId))
+ database = self.cursor.fetchall()[0][0]
+ traitInfos = (database,self.probeset,self.probe)
+ self.page = ShowTraitPage(fd,traitInfos)
+ #self = page
+ except:
+ print "Database Name Incorrect"
+
diff --git a/web/webqtl/updateTrait/DataUpdatePage.py b/web/webqtl/updateTrait/DataUpdatePage.py
new file mode 100755
index 00000000..a43f8367
--- /dev/null
+++ b/web/webqtl/updateTrait/DataUpdatePage.py
@@ -0,0 +1,738 @@
+# 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 2011/04/20
+
+
+
+#DataUpdatePage.py
+#
+#Classes:
+#DataUpagePage
+#-KA
+
+
+import string
+from htmlgen import HTMLgen2 as HT
+import os
+import time
+
+from base.webqtlTrait import webqtlTrait
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+from dbFunction import webqtlDatabaseFunction
+
+#########################################
+# Update Trait
+#########################################
+
+class DataUpdatePage(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.updMysql():
+ return
+
+ if not fd.genotype:
+ fd.readGenotype()
+ fd.strainlist = fd.f1list + fd.strainlist
+
+ fd.readData()
+
+ self.formdata = fd.formdata
+ self.dict['title'] = 'Data Updating'
+
+ try:
+ thisTrait = webqtlTrait(fullname=self.formdata.getvalue('fullname'), cursor=self.cursor)
+ thisTrait.retrieveInfo()
+ except:
+ heading = "Updating Database"
+ detail = ["The trait doesn't exist."]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+ if webqtlConfig.USERDICT[self.privilege] >= webqtlConfig.USERDICT['user']:
+ pass
+ else:
+ heading = "Updating Database"
+ detail = ["You don't have the permission to modify this trait"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+
+
+ status = self.formdata.getvalue('curStatus')
+ if status == 'updateCheck': #XZhou: Check the change
+ self.updateCheckPage(fd, thisTrait)
+ elif status == 'updateResult': #XZhou: make the changes to database
+ self.updateResultPage(fd, thisTrait)
+ else: #XZhou: show info retrieved from database
+ self.dispTraitPage(fd, thisTrait)
+
+
+ def dispTraitPage(self, fd, thisTrait):
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='dataInput',submit=HT.Input(type='hidden'))
+
+ #XZhou: This is to show trait info.
+ recordInfoTable = HT.TableLite(border=0, cellspacing=1, cellpadding=5,align="left")
+
+ for field in thisTrait.db.disfield:
+ fieldValue = getattr(thisTrait, field)
+ if not fieldValue:
+ fieldValue = ""
+ #fields to be ignored
+ if field in ("chipid", "genbankid"):
+ continue
+ elif field == "comments":
+ if fieldValue:
+ comments = string.split(fieldValue, '\n')
+ title0 = HT.Paragraph("Update History: ", Class="subtitle")
+ form.append(title0)
+ history = HT.Blockquote()
+ for item in comments:
+ if item:
+ history.append(item, HT.BR())
+ form.append(history)
+ continue
+ else:
+ pass
+
+ if field == 'name' or field == 'units':
+ form.append(HT.Input(type="hidden",name=field,value=fieldValue))
+ if field == 'name':
+ inputBox = HT.Strong(fieldValue)
+ else:
+ continue
+ elif field == 'pubmed_id':
+ inputBox = HT.Span(HT.Input(type="text",name=field,size=60, maxlength=255,value=fieldValue))
+ warning = HT.Paragraph(Class="fs11 cr")
+ warning.append('1. Please enter only the PubMed ID integer value into the field above.', HT.BR(), '&nbsp;&nbsp;&nbsp;&nbsp;Don\'t enter',
+ ' other characters.', HT.BR())
+ warning.append('2. If you modify an existing PubMed ID, changes will affect other records with', HT.BR(), \
+ '&nbsp;&nbsp;&nbsp;&nbsp;the same ID but will NOT affect the phenotype description or trait data.', HT.BR())
+ warning.append('3. If your delete an existing PubMed ID, this will not affect any other traits,', HT.BR(), \
+ '&nbsp;&nbsp;&nbsp;&nbsp;including those with the same PubMed ID.', HT.BR())
+ warning.append('4. If you enter publication data for a PubMed ID that is already in the database,', HT.BR(), \
+ '&nbsp;&nbsp;&nbsp;&nbsp;then all fields except Phenotype and Trait Data will be ignored.')
+ inputBox.append(warning)
+ elif field == 'pre_publication_description' or field == 'post_publication_description' or field == 'original_description' or field == 'owner' or field == 'abstract' or field == 'blatseq' or field == 'targetseq' or field == 'description' or field == 'authors' or field == 'sequence' or field == 'alias' or field == 'probe_target_description':
+ inputBox = HT.Textarea(name=field, cols=60, rows=4,text=fieldValue)
+ elif field == 'post_publication_abbreviation' or field == 'pre_publication_abbreviation':
+ inputBox = HT.Input(type="text",name=field,size=60, maxlength=30,value=fieldValue)
+ elif field == 'geneid':
+ inputBox = HT.Input(type="text",name=field,size=60, maxlength=255,value=fieldValue)
+ recordInfoTable.append(HT.TR(
+ HT.TD("%s :" % webqtlUtil.formatField(field), Class="fs12 fwb ff1", align="right"),
+ HT.TD(width=20),HT.TD(inputBox)))
+ #XZ: homologene is not in thisTrait.db.disfield, so have to do in this way
+ field = 'homologeneid'
+ inputBox = HT.Input(type="text",name=field,size=60, maxlength=255,value=thisTrait.homologeneid)
+ else:
+ inputBox = HT.Input(type="text",name=field,size=60, maxlength=255,value=fieldValue)
+
+ #XZ: For existing non-confidential phenotype trait, pre_publication_description and pre_publication_abbreviation are not shown to anybody except submitter or admistrator to prevent the trait being set to confidential one.
+ if thisTrait.db.type == 'Publish' and field == 'pre_publication_description' or field == 'pre_publication_abbreviation':
+ if not thisTrait.confidential and webqtlConfig.USERDICT[self.privilege] < webqtlConfig.USERDICT['admin'] and self.userName != thisTrait.submitter:
+ continue
+
+ #XZ and Rob, April 20, 2011: This is to add field and inputBox to table. Note that the change of format to each field(Capitalize) by webqtlUtil.formatField function.
+ recordInfoTable.append(HT.TR(
+ HT.TD("%s :" % webqtlUtil.formatField(field), Class="fs12 fwb ff1", align="right", valign="top"),
+ HT.TD(width=5),HT.TD(inputBox)))
+
+ #XZhou: This is to show trait data.
+ recordDataTable = HT.Text('Trait data updating is disabled')
+
+ if thisTrait.db.type == 'Publish':
+ thisTrait.retrieveData()
+ recordDataTable = HT.TableLite(border=0, width = "90%",cellspacing=2, cellpadding=2)
+ recordDataTable.append(HT.TR(HT.TD('Strain Name',Class="fs12 ffl fwb",align="Center"),
+ HT.TD('TraitData',Class="fs12 ffl fwb",align="Center"),
+ HT.TD('SE',Class="fs12 ffl fwb",align="Center"),
+ HT.TD('N Per Strain',Class="fs12 ffl fwb",align="Center"),
+ HT.TD('Strain Name',Class="fs12 ffl fwb",align="Center"),
+ HT.TD('TraitData',Class="fs12 ffl fwb",align="Center"),
+ HT.TD('SE',Class="fs12 ffl fwb",align="Center"),
+ HT.TD('N Per Strain',Class="fs12 ffl fwb",align="Center")))
+ tempTR = HT.TR(align="Center")
+ for i, strainName in enumerate(fd.strainlist):
+ if thisTrait.data.has_key(strainName):
+ tdata = thisTrait.data[strainName]
+ traitVal, traitVar, traitNP = tdata.val, tdata.var, tdata.N
+ else:
+ traitVal, traitVar, traitNP = None, None, None
+
+ if traitVal != None:
+ traitVal = "%2.3f" % traitVal
+ else:
+ traitVal = 'x'
+ if traitVar != None:
+ traitVar = "%2.3f" % traitVar
+ else:
+ traitVar = 'x'
+ if traitNP != None:
+ traitNP = "%d" % traitNP
+ else:
+ traitNP = 'x'
+
+ tempTR.append(HT.TD(HT.Paragraph(strainName),align='CENTER'),
+ HT.TD(HT.Input(name=strainName, size=8, maxlength=8, value=traitVal),align='CENTER'),
+ HT.TD(HT.Input(name='V'+strainName, size=8, maxlength=8, value=traitVar),align='CENTER'),
+ HT.TD(HT.Input(name='N'+strainName, size=8, maxlength=8, value=traitNP),align='CENTER'))
+ if i % 2:
+ recordDataTable.append(tempTR)
+ tempTR = HT.TR(align="Center")
+
+ if (i+1) % 2:
+ tempTR.append(HT.TD(''))
+ tempTR.append(HT.TD(''))
+ tempTR.append(HT.TD(''))
+ recordDataTable.append(tempTR)
+
+ updateButton = HT.Input(type='submit',name='submit', value='Submit Change',Class="button")
+ resetButton = HT.Input(type='reset',Class="button")
+
+ hddn = {'fullname':str(thisTrait), 'FormID':'updateRecord', 'curStatus':'updateCheck', 'RISet':fd.RISet, "incparentsf1":1}
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+
+ #############################
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#eeeeee")
+
+ containerTable = HT.TableLite(border=0, width = "90%",cellspacing=0, cellpadding=0)
+
+ mainTitle = HT.Paragraph("Update Info and Data", Class="title")
+
+ title1 = HT.Paragraph("Trait Information: ", Class="subtitle")
+
+ title2 = HT.Paragraph("Trait Data:", Class="subtitle")
+
+ containerTable.append(HT.TR(HT.TD(title1)), HT.TR(HT.TD(HT.BR(),updateButton,resetButton,HT.BR(),HT.BR())),
+ HT.TR(HT.TD(recordInfoTable)), HT.TR(HT.TD(title2)), HT.TR(HT.TD(HT.BR(),recordDataTable, HT.BR(), HT.BR())),
+ HT.TR(HT.TD(updateButton,resetButton)))
+
+ form.append(containerTable)
+
+ TD_LR.append(mainTitle, form)
+
+ self.dict['body'] = TD_LR
+
+ def updateCheckPage(self, fd, thisTrait):
+ form = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), name='updateCheck',submit=HT.Input(type='hidden'))
+ hddn = {'fullname':str(thisTrait), 'FormID':'updateRecord', 'curStatus':'updateResult', 'RISet':fd.RISet, "incparentsf1":1}
+
+ recordInfoTable = HT.TableLite(border=0, cellspacing=1, cellpadding=5,align="left",width="90%")
+ infoChanges = []
+ for field in thisTrait.db.disfield:
+ #fields to be ignored
+ #XZ: The stupid htmlgen can not set readonly for input and textarea. This is the only way I can prevent displayed items such as 'original_description', 'submitter' being changed.
+ if field in ("chipid", "genbankid", "comments", "original_description", "submitter"):
+ continue
+ oldValue = getattr(thisTrait, field)
+ if not oldValue:
+ oldValue = ''
+ oldValue = str(oldValue)
+ modifiedValue = self.formdata.getvalue(field)
+ if not modifiedValue:
+ modifiedValue = ""
+ modifiedValue.strip()
+ oldValue.strip()
+ if oldValue == modifiedValue:
+ form.append(HT.Input(type="hidden",name=field,value=oldValue))
+ continue
+
+ oldValue = HT.Paragraph(oldValue, Class="cr")
+ warning = ''
+ if field == 'PubMed_ID':
+ if modifiedValue != "":
+ try:
+ modifiedValue = int(modifiedValue)
+ except:
+ continue
+
+ #whether new PMID already exists
+ newPMIDExist = None
+ if modifiedValue:
+ self.cursor.execute("SelecT Id from Publication where PubMed_ID = %d" % modifiedValue)
+ results = self.cursor.fetchall()
+ if results:
+ newPMIDExist = results[0][0]
+ if newPMIDExist:
+ warning = HT.Paragraph(Class="fs11 cr")
+ warning.append('This new PubMed_ID already exists in our database. If you still want to change to this very PubMed_ID, the publication information (title, author, journal, etc.) will be replaced by those linked to this new PubMed_ID. That means, all the fields below (if any, except phenotype info and trait value) will be ignored.')
+
+ infoChanges.append(field)
+ inputBox = HT.Textarea(name=field, cols=50, rows=3,text=modifiedValue, onChange = "Javascript:this.form.curStatus.value='updateCheck';")
+ recordInfoTable.append(
+ HT.TR(HT.TD("%s :" % webqtlUtil.formatField(field), Class="fs12 fwb ff1", colspan = 3, valign="top")),
+ HT.TR(HT.TD(oldValue, valign="top"),HT.TD(width=20),HT.TD( inputBox, warning)))
+
+ #XZ: homologeneid is not in thisTrait.db.disfield
+ if thisTrait.db.type == "ProbeSet":
+ field = 'homologeneid'
+ oldValue = getattr(thisTrait, field)
+ if not oldValue:
+ oldValue = ''
+ oldValue = str(oldValue)
+ modifiedValue = self.formdata.getvalue(field)
+ if not modifiedValue:
+ modifiedValue = ""
+ modifiedValue.strip()
+ oldValue.strip()
+
+ if oldValue == modifiedValue:
+ form.append(HT.Input(type="hidden",name=field,value=oldValue))
+ else:
+ oldValue = HT.Paragraph(oldValue, Class="cr")
+ warning = ''
+ infoChanges.append(field)
+ inputBox = HT.Textarea(name=field, cols=50, rows=3,text=modifiedValue, onChange = "Javascript:this.form.curStatus.value='updateCheck';")
+ recordInfoTable.append(
+ HT.TR(HT.TD("%s :" % webqtlUtil.formatField(field), Class="fs12 fwb ff1", colspan = 3, valign="top")),
+ HT.TR(HT.TD(oldValue, valign="top"),HT.TD(width=20),HT.TD( inputBox, warning)))
+
+
+ if infoChanges == []:
+ recordInfoTable = ""
+ recordInfoChange = HT.Blockquote('No change has been made.')
+ else:
+ hddn['modifiedField'] = string.join(infoChanges, '::')
+ recordInfoChange = ''
+
+ recordDataChange = HT.Blockquote('Trait data updating is disabled')
+ recordDataTable = ""
+
+ modifiedVals = []
+ modifiedVars = []
+ modifiedNps = []
+ numDataChanges = 0
+ if thisTrait.db.type == 'Publish':
+ thisTrait.retrieveData()
+ recordDataTable = HT.TableLite(border=0, width = "90%",cellspacing=2, cellpadding=2)
+ for i, strainName in enumerate(fd.strainlist):
+ if thisTrait.data.has_key(strainName):
+ tdata = thisTrait.data[strainName]
+ traitVal, traitVar, traitNP = tdata.val, tdata.var, tdata.N
+ else:
+ traitVal, traitVar, traitNP = None, None, None
+
+ if traitVal != None:
+ traitVal = "%2.3f" % traitVal
+ else:
+ traitVal = 'x'
+ if traitVar != None:
+ traitVar = "%2.3f" % traitVar
+ else:
+ traitVar = 'x'
+ if traitNP != None:
+ traitNP = "%d" % traitNP
+ else:
+ traitNP = 'x'
+
+ try:
+ modifiedVal = "%2.3f" % fd.allTraitData[strainName].val
+ except:
+ modifiedVal = 'x'
+ try:
+ modifiedVar = "%2.3f" % fd.allTraitData[strainName].var
+ except:
+ modifiedVar = 'x'
+ try:
+ modifiedNp = "%d" % fd.allTraitData[strainName].N
+ except:
+ modifiedNp = 'x'
+
+ if modifiedVal != traitVal:
+ recordDataTable.append(HT.TR(HT.TD(HT.Paragraph(strainName + " Value")),
+ HT.TD(HT.Paragraph(traitVal, Class="cr")),
+ HT.TD(HT.Input(name=strainName, size=8, maxlength=8, value=modifiedVal, onChange = "Javascript:this.form.curStatus.value='updateCheck';"))))
+ numDataChanges += 1
+ modifiedVals.append(modifiedVal)
+ else:
+ form.append(HT.Input(type="hidden",name=strainName,value=traitVal))
+ modifiedVals.append(traitVal)
+
+ if modifiedVar != traitVar:
+ recordDataTable.append(HT.TR(HT.TD(HT.Paragraph(strainName + " SE")),
+ HT.TD(HT.Paragraph(traitVar, Class="cr")),
+ HT.TD(HT.Input(name='V'+strainName, size=8, maxlength=8, value=modifiedVar, onChange = "Javascript:this.form.curStatus.value='updateCheck';"))))
+ numDataChanges += 1
+ modifiedVars.append(modifiedVar)
+ else:
+ form.append(HT.Input(type="hidden",name='V'+strainName,value=traitVar))
+ modifiedVars.append(traitVar)
+
+ if modifiedNp != traitNP:
+ recordDataTable.append(HT.TR(HT.TD(HT.Paragraph(strainName + " N Per Strain")),
+ HT.TD(HT.Paragraph(traitNP, Class="cr")),
+ HT.TD(HT.Input(name='N'+strainName, size=8, maxlength=8, value=modifiedNp, onChange = "Javascript:this.form.curStatus.value='updateCheck';"))))
+ numDataChanges += 1
+ modifiedNps.append(modifiedNp)
+ else:
+ form.append(HT.Input(type="hidden",name='N'+strainName,value=traitNP))
+ modifiedNps.append(traitNP)
+
+
+ if numDataChanges == 0:
+ recordDataChange = HT.Blockquote('No change has been made.')
+ recordDataTable = ""
+ else:
+ hddn['modifiedDataField'] = 1
+ recordDataChange = ""
+
+ #if numDataChanges:
+ # hddn['val'] = string.join(modifiedVals, ',')
+ # hddn['var'] = string.join(modifiedVars, ',')
+ # hddn['np'] = string.join(modifiedNps, ',')
+
+ for key in hddn.keys():
+ form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
+
+ #############################
+ TD_LR = HT.TD(valign="top",colspan=2,bgcolor="#eeeeee", height=200)
+
+ mainTitle = HT.Paragraph("Update Info and Data", Class="title")
+
+ title1 = HT.Paragraph("Trait Information:", Class="subtitle")
+
+ title2 = HT.Paragraph("Trait Data:", Class="subtitle")
+
+ if numDataChanges or infoChanges:
+ recordChange = HT.Blockquote('The table below lists all the changes made. The texts in red are the original information stored on the server, the texts to the right are the modified version. ')
+ updateButton = HT.Input(type='submit',name='submit', value='Update Data',Class="button")
+ resetButton = HT.Input(type='reset',Class="button")
+ form.append(title1, HT.Center(updateButton,resetButton), recordInfoChange, recordInfoTable,title2, recordDataChange, HT.Center(recordDataTable,HT.P(),updateButton,resetButton),HT.P())
+ TD_LR.append(mainTitle, recordChange, HT.Blockquote(form))
+ else:
+ recordInfoChange = HT.Blockquote("No change has been made")
+ TD_LR.append(mainTitle, recordInfoChange)
+
+ self.dict['body'] = TD_LR
+ #self.dict['js1'] = webqtlConfig.resetFieldScript
+ return
+
+ def updateResultPage(self, fd, thisTrait):
+
+ comments = []
+ ctime = time.ctime()
+ ##Start Updating
+ dataID = -1
+ if thisTrait.db.type == 'Publish':
+ self.cursor.execute("SelecT PublishXRef.InbredSetId, PublishXRef.DataId, PublishXRef.PublicationId, PublishXRef.PhenotypeId, PublishXRef.Sequence from PublishXRef, PublishFreeze where PublishXRef.InbredSetId= PublishFreeze.InbredSetId and PublishFreeze.Name = '%s' and PublishXRef.Id = %s" % (thisTrait.db.name, thisTrait.name))
+ PInbredSetId, dataID, PublicationId, PhenotypeId, Sequence = self.cursor.fetchall()[0]
+
+ modifyField = self.formdata.getvalue('modifiedField')
+ ###Modify Trait Informations
+ if modifyField:
+ modifyField = string.split(modifyField, '::')
+ comments += modifyField
+ updateHomologeneid = False
+
+ if thisTrait.db.type == 'Publish':
+ PhenotypeItemUpdate = []
+ PhenotypeItemValues = []
+ PublicationItemUpdate = []
+ PublicationItemValues = []
+
+ for item in modifyField:
+ itemvalue = self.formdata.getvalue(item)
+
+ #XZ: identify Phenotype items
+ if item in ['pre_publication_description', 'post_publication_description', 'original_description', 'pre_publication_abbreviation', 'post_publication_abbreviation', 'lab_code', 'submitter', 'owner', 'authorized_users', 'units']:
+ if itemvalue != None: #XZ: the problem is that the item value can not be deleted
+ PhenotypeItemUpdate.append('%s=%%s' % item)
+ PhenotypeItemValues.append(itemvalue)
+
+ continue #XZ: this is important to distinguish Phenotype item and Publication item
+
+ elif item == "pubmed_id":
+ #Only integer allowed in this field
+ try:
+ itemvalue = int(itemvalue)
+ except:
+ itemvalue = None
+
+ #whether old PMID exists
+ self.cursor.execute("SelecT PubMed_ID from Publication where Id = %d" % PublicationId)
+ oldPMID = self.cursor.fetchone()
+ if oldPMID:
+ oldPMID = oldPMID[0]
+
+ #whether new PMID already exists
+ newPMID = None
+ self.cursor.execute("SelecT Id from Publication where PubMed_ID = %d" % itemvalue)
+ newPMID = self.cursor.fetchone()
+ if newPMID:
+ newPMID = newPMID[0]
+
+ ##the logic is still not very clear here
+ if newPMID:
+ #new PMID in record
+ self.cursor.execute("Update PublishXRef set PublicationId = %d where InbredSetId=%d and PhenotypeId=%d and PublicationId=%d and Sequence=%d" % (newPMID, PInbredSetId, PhenotypeId, PublicationId, Sequence))
+ #no need to update other fields
+ PublicationItemUpdate = []
+ break
+ elif itemvalue:
+ #have new PMID, but not in record or need to change
+ self.cursor.execute("Update Publication set pubmed_id=%d where Id = %s" % (itemvalue,PublicationId))
+ else:
+ #no new PMID
+ if oldPMID:
+ #remove a pubmed_id, don't know if this ever gonna happen
+ self.cursor.execute("SelecT max(Id) from Publication")
+ maxId = self.cursor.fetchone()[0] + 1
+ self.cursor.execute("SelecT * from Publication where Id = %d" % PublicationId)
+ oldRecs = list(self.cursor.fetchone())
+ oldRecs[0] = maxId
+ oldRecs[1] = None
+ NFields = ['%s'] * len(oldRecs)
+ query = "insert into Publication Values (%s)" % string.join(NFields, ',')
+ self.cursor.execute(query, tuple(oldRecs))
+ self.cursor.execute("Update PublishXRef set PublicationId = %d where InbredSetId=%d and PhenotypeId=%d and PublicationId=%d and Sequence=%d" % (maxId, PInbredSetId, PhenotypeId, PublicationId, Sequence))
+ PublicationId = maxId
+ pass
+ else:
+ pass
+ continue
+ else:
+ pass
+
+ if itemvalue:
+ PublicationItemUpdate.append('%s=%%s' % item)
+ PublicationItemValues.append(itemvalue)
+
+ if PhenotypeItemUpdate:
+ updateStr= string.join(PhenotypeItemUpdate,',')
+ query = "Update Phenotype set %s where Id = %s" % (updateStr, PhenotypeId)
+ self.cursor.execute(query,tuple(PhenotypeItemValues))
+
+ if PublicationItemUpdate:
+ updateStr= string.join(PublicationItemUpdate,',')
+ query = "Update Publication set %s where Id = %s" % (updateStr, PublicationId)
+ self.cursor.execute(query,tuple(PublicationItemValues))
+
+ else: #ProbeSet or Genotype Data
+ itemValues = []
+ itemUpdate = []
+
+ for item in modifyField:
+ itemvalue = self.formdata.getvalue(item)
+ if itemvalue != None:
+ itemvalue = string.strip(itemvalue)
+ else:
+ pass
+ if item == 'homologeneid':
+ updateHomologeneid = True
+ new_homologeneid = 0
+
+ if itemvalue and len(itemvalue) > 0:
+ try:
+ new_homologeneid = int(itemvalue)
+ except:
+ heading = "Record Updating Result"
+ detail = ["Can't update database. Homologeneid must be integer!"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ else:
+ itemUpdate.append('%s=%%s' % item) #XZ: Use %% to put a % in the output string
+ itemValues.append(itemvalue)
+
+ if itemUpdate:
+ updateStr= string.join(itemUpdate,', ')
+ comments = "%s modified %s at %s\n" % (self.userName, string.join(comments, ', '), ctime)
+ if thisTrait.db.type == "ProbeSet":#XZ, June 29, 2010: The algorithm is not good. Need to fix it later.
+ if thisTrait.chipid in (2,4):
+ if thisTrait.name[-2:] == '_A':
+ thisTrait.name = string.replace(thisTrait.name, '_A', '')
+ elif thisTrait.name[-2:] == '_B':
+ thisTrait.name = string.replace(thisTrait.name, '_B', '')
+ else:
+ pass
+ query = "Update %s set %s where Name like '%s%%%%'" % (thisTrait.db.type,updateStr,thisTrait.name)
+ self.cursor.execute(query,tuple(itemValues))
+ self.cursor.execute("Update %s set comments = CONCAT(comments,'%s') where Name like '%s%%%%'" % (thisTrait.db.type, comments, thisTrait.name))
+ elif thisTrait.sequence:
+ query = "Update %s set %s where BlatSeq='%s'" % (thisTrait.db.type,updateStr,thisTrait.sequence)
+ self.cursor.execute(query,tuple(itemValues))
+ self.cursor.execute("Update %s set comments = CONCAT(comments,'%s') where BlatSeq='%s'" % (thisTrait.db.type, comments, thisTrait.sequence))
+ else:
+ query = "Update %s set %s where Name='%s'" % (thisTrait.db.type,updateStr,thisTrait.name)
+ self.cursor.execute(query,tuple(itemValues))
+ self.cursor.execute("Update %s set comments = CONCAT(comments,'%s') where Name='%s'" % (thisTrait.db.type, comments, thisTrait.name))
+ else: #XZ: Genotype
+ query = "Update %s set %s where SpeciesId=%s and Name='%s'" % (thisTrait.db.type,updateStr, webqtlDatabaseFunction.retrieveSpeciesId(self.cursor, thisTrait.db.riset), thisTrait.name)
+ self.cursor.execute(query,tuple(itemValues))
+
+ if updateHomologeneid: #XZ: to update homologene id must be after updating geneid.
+ #XZ: In one species, one homologeneid can have multiple geneid. One geneid only can have one homologeneid.
+ #XZ: In Homologene table, GeneId is unique.
+ #XZ: Geneid might just being updated.
+ thisTrait = webqtlTrait(fullname=self.formdata.getvalue('fullname'), cursor=self.cursor)
+ thisTrait.retrieveInfo()
+
+ if not thisTrait.geneid:
+ heading = "Record Updating Result"
+ detail = ["There is no geneid associated with this trait. Can't update homologeneid info"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ else:
+ query = """
+ SELECT Species.TaxonomyId
+ FROM Species, InbredSet
+ WHERE InbredSet.Name = '%s' and InbredSet.SpeciesId = Species.Id
+ """ % thisTrait.db.riset
+ self.cursor.execute(query)
+ taxonomyId = self.cursor.fetchone()[0]
+
+ if not new_homologeneid:
+ query = """DELETE FROM Homologene WHERE GeneId=%s""" % thisTrait.geneid
+ self.cursor.execute(query)
+ else:
+ query = """SELECT GeneId FROM Homologene WHERE GeneId=%s""" % thisTrait.geneid
+ self.cursor.execute(query)
+ result = self.cursor.fetchone()
+
+ if not result:
+ query = """INSERT into Homologene (HomologeneId, GeneId, TaxonomyId) VALUES (%s, %s, %s)""" % (new_homologeneid, thisTrait.geneid, taxonomyId)
+ self.cursor.execute(query)
+ else:
+ query = """UPDATE Homologene SET HomologeneId=%s WHERE GeneId=%s""" % (new_homologeneid, thisTrait.geneid)
+ self.cursor.execute(query)
+
+
+ #XZ: It's critical to get lasted info first, then update gene level info across traits by geneid.
+ #XZ: Need to build index on GeneId. Otherwise, it's too slow.
+ if thisTrait.db.type == 'ProbeSet':
+ thisTrait = webqtlTrait(fullname=self.formdata.getvalue('fullname'), cursor=self.cursor)
+ thisTrait.retrieveInfo()
+
+ if thisTrait.geneid:
+ if 'symbol' in modifyField:
+ if thisTrait.symbol:
+ query = """UPDATE ProbeSet SET Symbol='%s' WHERE GeneId=%s""" % (thisTrait.symbol, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET Symbol=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+ if 'alias' in modifyField:
+ if thisTrait.alias:
+ query = """UPDATE ProbeSet SET alias='%s' WHERE GeneId=%s""" % (thisTrait.alias, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET alias=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+ if 'description' in modifyField:
+ if thisTrait.description: #XZ: Attention, we must use "%s" instead of '%s'. Otherwise, to insert 3'UTR will generate error.
+ query = """UPDATE ProbeSet SET description="%s" WHERE GeneId=%s""" % (thisTrait.description, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET description=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+ if 'strand_gene' in modifyField:
+ if thisTrait.strand_gene:
+ query = """UPDATE ProbeSet SET Strand_Gene='%s' WHERE GeneId=%s""" % (thisTrait.strand_gene, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET Strand_Gene=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+ if 'unigeneid' in modifyField:
+ if thisTrait.unigeneid:
+ query = """UPDATE ProbeSet SET UniGeneId='%s' WHERE GeneId=%s""" % (thisTrait.unigeneid, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET UniGeneId=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+ if 'refseq_transcriptid' in modifyField:
+ if thisTrait.refseq_transcriptid:
+ query = """UPDATE ProbeSet SET RefSeq_TranscriptId='%s' WHERE GeneId=%s""" % (thisTrait.refseq_transcriptid, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET RefSeq_TranscriptId=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+ if 'genbankid' in modifyField:
+ if thisTrait.genbankid:
+ query = """UPDATE ProbeSet SET GenbankId='%s' WHERE GeneId=%s""" % (thisTrait.genbankid, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET GenbankId=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+ if 'omim' in modifyField:
+ if thisTrait.omim:
+ query = """UPDATE ProbeSet SET OMIM='%s' WHERE GeneId=%s""" % (thisTrait.omim, thisTrait.geneid)
+ else:
+ query = """UPDATE ProbeSet SET OMIM=NULL WHERE GeneId=%s""" % (thisTrait.geneid)
+ self.cursor.execute(query)
+
+
+ ###Modify Trait Data
+ if thisTrait.db.type == 'Publish' and dataID > 0 and fd.formdata.getvalue("modifiedDataField"):
+ StrainIds = []
+ for item in fd.strainlist:
+ self.cursor.execute('SelecT Id from Strain where Name = "%s"' % item)
+ StrainId = self.cursor.fetchone()
+ if not StrainId:
+ raise ValueError
+ else:
+ StrainIds.append(StrainId[0])
+ comments.append('Trait Value')
+ #XZ, 03/05/2009: Xiaodong changed Data to PublishData, SE to PublishSE
+ self.cursor.execute('delete from PublishData where Id = %d' % dataID)
+ self.cursor.execute('delete from PublishSE where DataId = %d' % dataID)
+ self.cursor.execute('delete from NStrain where DataId = %d' % dataID)
+
+ for i, strain in enumerate(fd.strainlist):
+ sId = StrainIds[i]
+ if fd.allTraitData.has_key(strain):
+ tdata = fd.allTraitData[strain]
+ _val, _var, _N = tdata.val, tdata.var, tdata.N
+ if _val != None:
+ #XZ, 03/05/2009: Xiaodong changed Data to PublishData, SE to PublishSE
+ self.cursor.execute('insert into PublishData values(%d, %d, %s)' % (dataID, sId, _val))
+ if _var != None:
+ self.cursor.execute('insert into PublishSE values(%d, %d, %s)' % (dataID, sId, _var))
+ if _N != None:
+ self.cursor.execute('insert into NStrain values(%d, %d, %s)' % (dataID, sId, _N))
+ else:
+ pass
+ #end for
+ else:
+ pass
+ TD_LR = HT.TD(valign="top", bgcolor="#eeeeee",height=200,width="100%")
+ main_title = HT.Paragraph(" Record Updating Result", Class="title")
+
+ TD_LR.append(main_title,HT.Blockquote('Successfully updated record %s in database ' % thisTrait.name, thisTrait.db.genHTML(), '.'))
+ if thisTrait.db.type == 'Publish':
+ comments = "%s modified %s at %s\n" % (self.userName, string.join(comments, ', '), ctime)
+ self.cursor.execute("Update PublishXRef set comments = CONCAT(comments,'%s') where InbredSetId=%d and PhenotypeId=%d and PublicationId=%d and Sequence=%d" % (comments, PInbredSetId, PhenotypeId, PublicationId, Sequence))
+
+ if 0:
+ heading = "Record Updating Result"
+ detail = ["Can't update database. The server may be down at this time or you don't have the permission"]
+ self.error(heading=heading,detail=detail,error="Error")
+ return
+ self.dict['body'] = str(TD_LR)
+
diff --git a/web/webqtl/updateTrait/__init__.py b/web/webqtl/updateTrait/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/updateTrait/__init__.py
diff --git a/web/webqtl/user/__init__.py b/web/webqtl/user/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/user/__init__.py
diff --git a/web/webqtl/user/userLogin.py b/web/webqtl/user/userLogin.py
new file mode 100755
index 00000000..145af03e
--- /dev/null
+++ b/web/webqtl/user/userLogin.py
@@ -0,0 +1,84 @@
+# 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
+
+#Xiaodong changed the independancy structure
+
+from htmlgen import HTMLgen2 as HT
+import os
+
+from base.templatePage import templatePage
+from base import webqtlConfig
+from utility import webqtlUtil
+from search import IndexPage
+from base.myCookie import myCookie
+
+class userLogin(templatePage):
+
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.updMysql():
+ return
+
+ try:
+ user = fd.formdata.getvalue('user').strip()
+ password = fd.formdata.getvalue('password').strip()
+ except:
+ user = password = ''
+
+ if user and password:
+ try:
+ if user == password:
+ raise 'identError'
+ privilege, id, account_name, encrypt_password, grpName = webqtlUtil.authUser(user, password, self.cursor)
+
+ if encrypt_password:
+ self.session_data_changed['user'] = user
+ self.session_data_changed['privilege'] = privilege
+
+ self.cursor.execute("""update User set user_ip=%s,lastlogin=Now() where name=%s""",(fd.remote_ip,user))
+
+ myPage = IndexPage.IndexPage(fd)
+ self.dict['title'] = myPage.dict['title']
+ self.dict['body'] = myPage.dict['body']
+ self.dict['js1'] = myPage.dict['js1']
+ self.dict['js2'] = myPage.dict['js2']
+ return
+ else:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('You entered wrong user name or password. Please try it again.',color='black'))
+ except 'identError':
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('User name and password are the same, modify you password before login.',color='black'))
+ except:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('User database is not ready yet. Try again later.',color='black'))
+ else:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('No user name or password was entered, Please try it again.',color='black'))
+
+ result.__setattr__("class","subtitle")
+ self.dict['title'] = 'User Login Result'
+ self.dict['body'] = HT.TD(result,colspan=2,height=200,width="100%",bgColor='#eeeeee')
+ LOGOUT = HT.Href(text = "Logout",Class="small", target="_blank",url=os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE) + "?FormID=userLogoff")
+ self.dict['login'] = LOGOUT
diff --git a/web/webqtl/user/userLogoff.py b/web/webqtl/user/userLogoff.py
new file mode 100755
index 00000000..203ac69c
--- /dev/null
+++ b/web/webqtl/user/userLogoff.py
@@ -0,0 +1,54 @@
+# 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
+
+#Xiaodong changed the independancy structure
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from base.myCookie import myCookie
+
+#########################################
+# User Logoff Page
+#########################################
+
+class userLogoff(templatePage):
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ self.session_data_changed['user'] = 'Guest'
+ self.session_data_changed['privilege'] = 'guest'
+
+ #self.cookie.append(myCookie('user',' ',0))
+ #self.cookie.append(myCookie('password',' ',0))
+ result = HT.Blockquote(HT.Font('Logout Result: ',color='green'),HT.Font('You have been succesfully logged out. ',color='black'))
+ result.__setattr__("class","subtitle")
+ self.dict['title'] = 'User Logoff Result'
+ self.dict['body'] = HT.TD(result,colspan=2,height=200,width="100%",bgColor='#eeeeee')
+ LOGIN = HT.Href(text = "Login",Class="small", target="_blank",url="account.html")
+ self.dict['login'] = LOGIN
+
diff --git a/web/webqtl/user/userPasswd.py b/web/webqtl/user/userPasswd.py
new file mode 100755
index 00000000..58c9bbc9
--- /dev/null
+++ b/web/webqtl/user/userPasswd.py
@@ -0,0 +1,73 @@
+# 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
+
+#Xiaodong changed the independancy structure
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# User Password Page
+#########################################
+
+class userPasswd(templatePage):
+ def __init__(self, fd):
+
+ templatePage.__init__(self, fd)
+
+ if not self.updMysql():
+ return
+
+ try:
+ user = fd.formdata.getvalue('user')
+ password = fd.formdata.getvalue('password')
+ newpassword = fd.formdata.getvalue('newpassword')
+ retypepassword = fd.formdata.getvalue('retypepassword')
+ except:
+ user = ''
+
+ if newpassword != retypepassword:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('The new passwords you just entered are inconsistent. Please try it again',color='black'))
+ elif user and password and newpassword:
+ try:
+ encrypt_password = webqtlUtil.authUser(user,password,self.cursor)[3]
+ if encrypt_password:
+ self.cursor.execute("""update User set password=SHA(%s) where name=%s""",(newpassword,user))
+ result = HT.Blockquote(HT.Font('Change Result: ',color='green'),HT.Font('You have succesfully changed your password. You may continue to use WebQTL.',color='black'))
+ else:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('You entered wrong user name or password. Please try it again.',color='black'))
+ except:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('User database is not ready yet. Try again later.',color='black'))
+ else:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('No user name or password or new password was entered, Please try it again.',color='black'))
+
+ result.__setattr__("class","subtitle")
+ self.dict['title'] = 'Change Password Result'
+ self.dict['body'] = HT.TD(result,colspan=2,height=200,width="100%",bgColor='#eeeeee')
+
diff --git a/web/webqtl/user/userPasswdPage.py b/web/webqtl/user/userPasswdPage.py
new file mode 100755
index 00000000..2c9135f1
--- /dev/null
+++ b/web/webqtl/user/userPasswdPage.py
@@ -0,0 +1,70 @@
+# 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
+
+#Xiaodong changed the independancy structure
+
+from htmlgen import HTMLgen2 as HT
+
+from base.templatePage import templatePage
+from utility import webqtlUtil
+
+
+#########################################
+# User Password Page
+#########################################
+
+class userPasswdPage(templatePage):
+ def __init__(self, fd):
+ templatePage.__init__(self)
+ if not self.updMysql():
+ return
+ try:
+ user = fd.formdata.getvalue('user')
+ password = fd.formdata.getvalue('password')
+ newpassword = fd.formdata.getvalue('newpassword')
+ retypepassword = fd.formdata.getvalue('retypepassword')
+ except:
+ user = ''
+
+ if newpassword != retypepassword:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('The new passwords you just entered are inconsistent. Please try it again',color='black'))
+ elif user and password and newpassword:
+ try:
+ encrypt_password = webqtlUtil.authUser(user,password,self.cursor)[3]
+ if encrypt_password:
+ self.cursor.execute("""update User set password=SHA(%s) where name=%s""",(newpassword,user))
+ result = HT.Blockquote(HT.Font('Change Result: ',color='green'),HT.Font('You have succesfully changed your password. You may continue to use WebQTL.',color='black'))
+ else:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('You entered wrong user name or password. Please try it again.',color='black'))
+ except:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('User database is not ready yet. Try again later.',color='black'))
+ else:
+ result = HT.Blockquote(HT.Font('Error: ',color='red'),HT.Font('No user name or password or new password was entered, Please try it again.',color='black'))
+
+ result.__setattr__("class","subtitle")
+ self.dict['title'] = 'Change Password Result'
+ self.dict['body'] = HT.TD(result,colspan=2,height=200,width="100%",bgColor='#eeeeee')
+
diff --git a/web/webqtl/utility/AJAX_table.py b/web/webqtl/utility/AJAX_table.py
new file mode 100755
index 00000000..963a530e
--- /dev/null
+++ b/web/webqtl/utility/AJAX_table.py
@@ -0,0 +1,153 @@
+# 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
+
+import cPickle
+import os
+import MySQLdb
+import time
+import pyXLWriter as xl
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+from THCell import THCell
+from TDCell import TDCell
+import webqtlUtil
+
+
+class AJAX_table:
+ def __init__(self, fd):
+ file = fd.formdata.getfirst("file", "")
+ sort = fd.formdata.getfirst("sort", "")
+ order = fd.formdata.getfirst("order", "up")
+ cmd = fd.formdata.getfirst("cmd", "")
+ tableID = fd.formdata.getfirst("tableID", "")
+ addIndex = fd.formdata.getfirst("addIndex", "1")
+ hiddenColumnsString = fd.formdata.getfirst("hiddenColumns", "")
+ hiddenColumns = hiddenColumnsString.split(',')
+
+ try:
+ fp = open(os.path.join(webqtlConfig.TMPDIR, file + '.obj'), 'rb')
+ tblobj = cPickle.load(fp)
+ fp.close()
+
+ if cmd == 'addCorr':
+ dbId = int(fd.formdata.getfirst("db"))
+ dbFullName = fd.formdata.getfirst("dbname")
+ trait = fd.formdata.getfirst("trait")
+ form = fd.formdata.getfirst("form")
+ ids = fd.formdata.getfirst("ids")
+ vals = fd.formdata.getfirst("vals")
+ ids = eval(ids)
+ nnCorr = len(ids)
+ vals = eval(vals)
+
+ workbook = xl.Writer('%s.xls' % (webqtlConfig.TMPDIR+file))
+ worksheet = workbook.add_worksheet()
+
+ con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+ cursor = con.cursor()
+
+ cursor.execute("Select name, ShortName from ProbeSetFreeze where Id = %s", dbId)
+ dbName, dbShortName = cursor.fetchone()
+
+ tblobj['header'][0].append(
+ THCell(HT.TD(dbShortName, Class="fs11 ffl b1 cw cbrb"),
+ text="%s" % dbShortName, idx=tblobj['header'][0][-1].idx + 1),
+ )
+
+ headingStyle = workbook.add_format(align = 'center', bold = 1, border = 1, size=13, fg_color = 0x1E, color="white")
+ for i, item in enumerate(tblobj['header'][0]):
+ if (i > 0):
+ worksheet.write([8, i-1], item.text, headingStyle)
+ worksheet.set_column([i-1, i-1], 2*len(item.text))
+
+ for i, row in enumerate(tblobj['body']):
+ ProbeSetId = row[1].text
+ #XZ, 03/02/2009: Xiaodong changed Data to ProbeSetData
+ cursor.execute("""
+ Select ProbeSetData.StrainId, ProbeSetData.Value
+ From ProbeSetData, ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %d AND
+ ProbeSetXRef.DataId = ProbeSetData.Id AND
+ ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+ ProbeSet.Name = '%s'
+ """ % (dbId, ProbeSetId))
+ results = cursor.fetchall()
+ vdict = {}
+ for item in results:
+ vdict[item[0]] = item[1]
+ newvals = []
+ for id in ids:
+ if vdict.has_key(id):
+ newvals.append(vdict[id])
+ else:
+ newvals.append(None)
+ corr,nOverlap= webqtlUtil.calCorrelation(newvals,vals,nnCorr)
+ repr = '%0.4f' % corr
+ row.append(
+ TDCell(HT.TD(HT.Href(text=repr, url="javascript:showCorrPlotThird('%s', '%s', '%s')" % (form, dbName, ProbeSetId), Class="fs11 fwn ffl"), " / ", nOverlap, Class="fs11 fwn ffl b1 c222", align="middle"),repr,abs(corr))
+ )
+
+ last_row=0
+ for j, item in enumerate(tblobj['body'][i]):
+ if (j > 0):
+ worksheet.write([9+i, j-1], item.text)
+ last_row = 9+i
+ last_row += 1
+
+ titleStyle = workbook.add_format(align = 'left', bold = 0, size=14, border = 1, border_color="gray")
+ ##Write title Info
+ # Modified by Hongqiang Li
+ worksheet.write([0, 0], "Citations: Please see %s/reference.html" % webqtlConfig.PORTADDR, titleStyle)
+ worksheet.write([1, 0], "Trait : %s" % trait, titleStyle)
+ worksheet.write([2, 0], "Database : %s" % dbFullName, titleStyle)
+ worksheet.write([3, 0], "Date : %s" % time.strftime("%B %d, %Y", time.gmtime()), titleStyle)
+ worksheet.write([4, 0], "Time : %s GMT" % time.strftime("%H:%M ", time.gmtime()), titleStyle)
+ worksheet.write([5, 0], "Status of data ownership: Possibly unpublished data; please see %s/statusandContact.html for details on sources, ownership, and usage of these data." % webqtlConfig.PORTADDR, titleStyle)
+ #Write footer info
+ worksheet.write([1 + last_row, 0], "Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA21131), NCI MMHCC (U01CA105417), and NCRR (U01NR 105417)", titleStyle)
+ worksheet.write([2 + last_row, 0], "PLEASE RETAIN DATA SOURCE INFORMATION WHENEVER POSSIBLE", titleStyle)
+
+ cursor.close()
+ workbook.close()
+
+ objfile = open(os.path.join(webqtlConfig.TMPDIR, file + '.obj'), 'wb')
+ cPickle.dump(tblobj, objfile)
+ objfile.close()
+ else:
+ pass
+
+ self.value = str(webqtlUtil.genTableObj(tblobj=tblobj, file=file, sortby=(sort, order), tableID = tableID, addIndex = addIndex, hiddenColumns = hiddenColumns))
+
+ except:
+ self.value = "<span class='fs16 fwb cr ffl'>The table is no longer available on this server</span>"
+
+ def __str__(self):
+ return self.value
+
+ def write(self):
+ return str(self)
diff --git a/web/webqtl/utility/Plot.py b/web/webqtl/utility/Plot.py
new file mode 100755
index 00000000..2401c85c
--- /dev/null
+++ b/web/webqtl/utility/Plot.py
@@ -0,0 +1,1283 @@
+# 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
+
+import piddle as pid
+from math import *
+import random
+import sys, os
+from numarray import linear_algebra as la
+from numarray import ones, array, dot, swapaxes
+
+import reaper
+
+import svg
+import webqtlUtil
+from base import webqtlConfig
+
+
+def cformat(d, rank=0):
+ 'custom string format'
+ strD = "%2.6f" % d
+
+ if rank == 0:
+ while strD[-1] in ('0','.'):
+ if strD[-1] == '0' and strD[-2] == '.' and len(strD) <= 4:
+ break
+ elif strD[-1] == '.':
+ strD = strD[:-1]
+ break
+ else:
+ strD = strD[:-1]
+
+ else:
+ strD = strD.split(".")[0]
+
+ if strD == '-0.0':
+ strD = '0.0'
+ return strD
+
+def frange(start, end=None, inc=1.0):
+ "A faster range-like function that does accept float increments..."
+ if end == None:
+ end = start + 0.0
+ start = 0.0
+ else:
+ start += 0.0 # force it to be a float
+ count = int((end - start) / inc)
+ if start + count * inc != end:
+ # Need to adjust the count. AFAICT, it always comes up one short.
+ count += 1
+ L = [start] * count
+ for i in xrange(1, count):
+ L[i] = start + i * inc
+ return L
+
+
+def gammln(xx):
+ cof=[76.18009173,-86.50532033,24.01409822,-1.231739516,0.120858003e-2,-0.536382e-5]
+ x=xx-1.0
+ tmp=x+5.5
+ tmp -=(x+0.5)*log(tmp)
+ ser=1.0
+ for item in cof:
+ x+=1.0
+ ser+=item/x
+
+ return -tmp+log(2.50662827465*ser)
+
+
+def gser(a,x):
+ gln=gammln(a)
+ ITMAX=100
+ EPS=3.0e-7
+
+ if x<=0.0:
+ gamser=0.0
+ return [gamser,gln]
+ else:
+ ap=a
+ sum=1.0/a
+ dele=sum
+ for i in range(1,ITMAX+1):
+ ap+=1.0
+ dele*=x/ap
+ sum+=dele
+ if abs(dele)<abs(sum)*EPS:
+ gamser=sum*exp(-x+a*log(x)-gln)
+ return [gamser,gln]
+ return None
+
+def gcf(a,x):
+ ITMAX=100
+ EPS=3.0e-7
+ gold=0.0
+ fac=1
+ b1=1.0
+ b0=0.0
+ a0=1.0
+ gln=gammln(a)
+
+ a1=x
+ for n in range(1,ITMAX+1):
+ an=n+0.0
+ ana=an-a
+ a0=(a1+a0*ana)*fac
+ b0=(b1+b0*ana)*fac
+ anf=an*fac
+ a1=x*a0+anf*a1
+ b1=x*b0+anf*b1
+ if (a1):
+ fac=1.0/a1
+ g=b1*fac
+ if abs((g-gold)/g)<EPS:
+ gammcf=exp(-x+a*log(x)-gln)*g
+ return [gammcf,gln]
+ gold=g
+ return None
+
+def gammp(a,x):
+ if x<0.0 or a<=0.0:
+ return None
+ if x<(a+1.0):
+ a=gser(a,x)[0]
+ return a
+ else:
+ a=gcf(a,x)[0]
+ return 1.0-a
+def U(n):
+ x=pow(0.5,1.0/n)
+ m=[1-x]
+ for i in range(2,n):
+ a=(i-0.3175)/(n+0.365)
+ m.append(a)
+ m.append(x)
+ return m
+
+def erf(x):
+ if x<0.0:
+ return -gammp(0.5,x*x)
+ else:
+ return gammp(0.5,x*x)
+
+def erfcc(x):
+ z=abs(x)
+ t=1.0/(1.0+0.5*z)
+ ans=t*exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+t*(-0.82215223+t*0.17087277)))))))))
+ if x>=0.0:
+ return ans
+ else:
+ return 2.0-ans
+
+def calMeanVar(data):
+ n=len(data)
+ if n<2:
+ return None
+ else:
+ sum=reduce(lambda x,y:x+y,data,0.0)
+ mean=sum/n
+ z=data[:]
+ for i in range(n):
+ z[i]=z[i]-mean
+ variance=reduce(lambda x,y:x+y*y,z,0.0)
+ variance /= n-1
+ variance =sqrt(variance)
+ for i in range(n):
+ z[i]=z[i]/variance
+ return z
+
+def inverseCumul(p):
+ #Coefficients in rational approximations.
+ a = [-3.969683028665376e+01,2.209460984245205e+02,-2.759285104469687e+02,1.383577518672690e+02,-3.066479806614716e+01,2.506628277459239e+00]
+
+ b = [-5.447609879822406e+01,1.615858368580409e+02,-1.556989798598866e+02,6.680131188771972e+01,-1.328068155288572e+01]
+
+ c = [-7.784894002430293e-03,-3.223964580411365e-01,-2.400758277161838e+00,-2.549732539343734e+00,4.374664141464968e+00,2.938163982698783e+00]
+
+ d = [7.784695709041462e-03,3.224671290700398e-01,2.445134137142996e+00,3.754408661907416e+00]
+
+ #Define break-points.
+
+ p_low = 0.02425
+ p_high = 1 - p_low
+
+ #Rational approximation for lower region.
+
+ if p > 0 and p < p_low:
+ q = sqrt(-2*log(p))
+ x = (((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1)
+
+
+ #Rational approximation for central region.
+
+ elif p>= p_low and p <= p_high:
+ q = p - 0.5
+ r = q*q
+ x = (((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q /(((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1)
+
+ #Rational approximation for upper region.
+
+ elif p>p_high and p < 1:
+ q = sqrt(-2*log(1-p))
+ x = -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1)
+
+ else:
+ return None
+
+ if p>0 and p < 1:
+ e = 0.5 * erfcc(-x/sqrt(2)) - p
+ u = e * sqrt(2*pi) * exp(x*x/2)
+ x = x - u/(1 + x*u/2)
+ return x
+ else:
+ return None
+
+def gmean(lst):
+ N = len(lst)
+ if N == 0:
+ return 0
+ else:
+ return (reduce(lambda x,y: x+y, lst, 0.0))/N
+
+def gmedian(lst2):
+ lst = lst2[:]
+ N = len(lst)
+ if N == 0:
+ return 0
+ else:
+ lst.sort()
+ if N % 2 == 0:
+ return (lst[N/2]+lst[(N-2)/2])/2.0
+ else:
+ return lst[(N-1)/2]
+
+def gpercentile(lst2, np):
+ lst = lst2[:]
+ N = len(lst)
+ if N == 0 or np > 100 or np < 0:
+ return None
+ else:
+ lst.sort()
+ pNadd1 = (np/100.0)*N
+ k = int(pNadd1)
+ d = pNadd1 - k
+ if k == 0:
+ return lst[0]
+ elif k >= N-1:
+ return lst[N-1]
+ else:
+ return lst[k-1] + d*(lst[k] - lst[k-1])
+
+def findOutliers(vals):
+
+ valsOnly = []
+ dataXZ = vals[:]
+ for i in range(len(dataXZ)):
+ valsOnly.append(dataXZ[i][1])
+
+ data = [('', valsOnly[:])]
+
+ for item in data:
+ itemvalue = item[1]
+ nValue = len(itemvalue)
+ catValue = []
+
+ for item2 in itemvalue:
+ try:
+ tstrain, tvalue = item2
+ except:
+ tvalue = item2
+ if nValue <= 4:
+ continue
+ else:
+ catValue.append(tvalue)
+
+ if catValue != []:
+ lowHinge = gpercentile(catValue, 25)
+ upHinge = gpercentile(catValue, 75)
+ Hstep = 1.5*(upHinge - lowHinge)
+
+ outlier = []
+ extreme = []
+
+ upperBound = upHinge + Hstep
+ lowerBound = lowHinge - Hstep
+
+ for item in catValue:
+ if item >= upHinge + 2*Hstep:
+ extreme.append(item)
+ elif item >= upHinge + Hstep:
+ outlier.append(item)
+ else:
+ pass
+
+ for item in catValue:
+ if item <= lowHinge - 2*Hstep:
+ extreme.append(item)
+ elif item <= lowHinge - Hstep:
+ outlier.append(item)
+ else:
+ pass
+ else:
+ upperBound = 1000
+ lowerBound = -1000
+
+ return upperBound, lowerBound
+
+
+def plotBoxPlot(canvas, data, offset= (40, 40, 40, 40), XLabel="Category", YLabel="Value"):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ iValues = []
+ for item in data:
+ for item2 in item[1]:
+ try:
+ iValues.append(item2[1])
+ except:
+ iValues.append(item2)
+
+ #draw frame
+ max_Y = max(iValues)
+ min_Y = min(iValues)
+ scaleY = detScale(min_Y, max_Y)
+ Yll = scaleY[0]
+ Yur = scaleY[1]
+ nStep = scaleY[2]
+ stepY = (Yur - Yll)/nStep
+ stepYPixel = plotHeight/(nStep)
+ canvas.drawRect(plotWidth+xLeftOffset, plotHeight + yTopOffset, xLeftOffset, yTopOffset)
+
+ ##draw Y Scale
+ YYY = Yll
+ YCoord = plotHeight + yTopOffset
+ scaleFont=pid.Font(ttf="cour",size=11,bold=1)
+ for i in range(nStep+1):
+ strY = cformat(d=YYY, rank=0)
+ YCoord = max(YCoord, yTopOffset)
+ canvas.drawLine(xLeftOffset,YCoord,xLeftOffset-5,YCoord)
+ canvas.drawString(strY, xLeftOffset -30,YCoord +5,font=scaleFont)
+ YYY += stepY
+ YCoord -= stepYPixel
+
+ ##draw X Scale
+ stepX = plotWidth/len(data)
+ XCoord = xLeftOffset + 0.5*stepX
+ YCoord = plotHeight + yTopOffset
+ scaleFont = pid.Font(ttf="tahoma",size=12,bold=0)
+ labelFont = pid.Font(ttf="tahoma",size=13,bold=0)
+ for item in data:
+ itemname, itemvalue = item
+ canvas.drawLine(XCoord, YCoord,XCoord, YCoord+5, color=pid.black)
+ canvas.drawString(itemname, XCoord - canvas.stringWidth(itemname,font=labelFont)/2.0,\
+ YCoord +20,font=labelFont)
+
+ nValue = len(itemvalue)
+ catValue = []
+ for item2 in itemvalue:
+ try:
+ tstrain, tvalue = item2
+ except:
+ tvalue = item2
+ if nValue <= 4:
+ canvas.drawCross(XCoord, plotHeight + yTopOffset - (tvalue-Yll)*plotHeight/(Yur - Yll), color=pid.red,size=5)
+ else:
+ catValue.append(tvalue)
+ if catValue != []:
+ catMean = gmean(catValue)
+ catMedian = gmedian(catValue)
+ lowHinge = gpercentile(catValue, 25)
+ upHinge = gpercentile(catValue, 75)
+ Hstep = 1.5*(upHinge - lowHinge)
+
+ outlier = []
+ extrem = []
+
+ upperAdj = None
+ for item in catValue:
+ if item >= upHinge + 2*Hstep:
+ extrem.append(item)
+ elif item >= upHinge + Hstep:
+ outlier.append(item)
+ elif item > upHinge and item < upHinge + Hstep:
+ if upperAdj == None or item > upperAdj:
+ upperAdj = item
+ else:
+ pass
+ lowerAdj = None
+ for item in catValue:
+ if item <= lowHinge - 2*Hstep:
+ extrem.append(item)
+ elif item <= lowHinge - Hstep:
+ outlier.append(item)
+ if item < lowHinge and item > lowHinge - Hstep:
+ if lowerAdj == None or item < lowerAdj:
+ lowerAdj = item
+ else:
+ pass
+ canvas.drawRect(XCoord-20, plotHeight + yTopOffset - (lowHinge-Yll)*plotHeight/(Yur - Yll), \
+ XCoord+20, plotHeight + yTopOffset - (upHinge-Yll)*plotHeight/(Yur - Yll))
+ canvas.drawLine(XCoord-20, plotHeight + yTopOffset - (catMedian-Yll)*plotHeight/(Yur - Yll), \
+ XCoord+20, plotHeight + yTopOffset - (catMedian-Yll)*plotHeight/(Yur - Yll))
+ if upperAdj != None:
+ canvas.drawLine(XCoord, plotHeight + yTopOffset - (upHinge-Yll)*plotHeight/(Yur - Yll), \
+ XCoord, plotHeight + yTopOffset - (upperAdj-Yll)*plotHeight/(Yur - Yll))
+ canvas.drawLine(XCoord-20, plotHeight + yTopOffset - (upperAdj-Yll)*plotHeight/(Yur - Yll), \
+ XCoord+20, plotHeight + yTopOffset - (upperAdj-Yll)*plotHeight/(Yur - Yll))
+ if lowerAdj != None:
+ canvas.drawLine(XCoord, plotHeight + yTopOffset - (lowHinge-Yll)*plotHeight/(Yur - Yll), \
+ XCoord, plotHeight + yTopOffset - (lowerAdj-Yll)*plotHeight/(Yur - Yll))
+ canvas.drawLine(XCoord-20, plotHeight + yTopOffset - (lowerAdj-Yll)*plotHeight/(Yur - Yll), \
+ XCoord+20, plotHeight + yTopOffset - (lowerAdj-Yll)*plotHeight/(Yur - Yll))
+
+ outlierFont = pid.Font(ttf="cour",size=12,bold=0)
+ if outlier != []:
+ for item in outlier:
+ yc = plotHeight + yTopOffset - (item-Yll)*plotHeight/(Yur - Yll)
+ #canvas.drawEllipse(XCoord-3, yc-3, XCoord+3, yc+3)
+ canvas.drawString('o', XCoord-3, yc+5, font=outlierFont, color=pid.orange)
+ if extrem != []:
+ for item in extrem:
+ yc = plotHeight + yTopOffset - (item-Yll)*plotHeight/(Yur - Yll)
+ #canvas.drawEllipse(XCoord-3, yc-3, XCoord+3, yc+3)
+ canvas.drawString('*', XCoord-3, yc+6, font=outlierFont, color=pid.red)
+
+ canvas.drawCross(XCoord, plotHeight + yTopOffset - (catMean-Yll)*plotHeight/(Yur - Yll), \
+ color=pid.blue,size=3)
+ #print (catMean, catMedian, cat25per, cat75per)
+ pass
+
+ XCoord += stepX
+
+ labelFont=pid.Font(ttf="verdana",size=18,bold=0)
+ canvas.drawString(XLabel, xLeftOffset + (plotWidth -canvas.stringWidth(XLabel,font=labelFont))/2.0, \
+ YCoord +40, font=labelFont)
+ canvas.drawString(YLabel,xLeftOffset-40, YCoord-(plotHeight -canvas.stringWidth(YLabel,font=labelFont))/2.0,\
+ font=labelFont, angle =90)
+
+def plotSecurity(canvas, text="12345"):
+ if not text:
+ return
+
+ plotWidth = canvas.size[0]
+ plotHeight = canvas.size[1]
+ if plotHeight<=0 or plotWidth<=0:
+ return
+
+ bgColor = pid.Color(0.6+0.4*random.random(), 0.6+0.4*random.random(), 0.6+0.4*random.random())
+ canvas.drawRect(0,0,plotWidth,plotHeight, edgeColor=bgColor, fillColor=bgColor)
+
+ for i in range(30):
+ randomColor = pid.Color(0.6+0.4*random.random(), 0.6+0.4*random.random(), 0.6+0.4*random.random())
+ scaleFont=pid.Font(ttf="cour",size=random.choice(range(20, 50)))
+ canvas.drawString(random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+ int(random.random()*plotWidth), int(random.random()*plotHeight), font=scaleFont,
+ color=randomColor, angle=random.choice(range(-45, 50)))
+
+ step = (plotWidth-20)/len(text)
+ startX = 20
+ for item in text:
+ randomColor = pid.Color(0.6*random.random(),0.6*random.random(), 0.6*random.random())
+ scaleFont=pid.Font(ttf="verdana",size=random.choice(range(50, 60)),bold=1)
+ canvas.drawString(item, startX, plotHeight/2-10, font=scaleFont,
+ color=randomColor, angle=random.choice(range(-45, 50)))
+ startX += step
+
+# parameter: data is either object returned by reaper permutation function (called by MarkerRegressionPage.py)
+# or the first object returned by direct (pair-scan) permu function (called by DirectPlotPage.py)
+def plotBar(canvas, data, barColor=pid.blue, axesColor=pid.black, labelColor=pid.black, XLabel=None, YLabel=None, title=None, offset= (60, 20, 40, 40), zoom = 1):
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ if plotHeight<=0 or plotWidth<=0:
+ return
+
+ if len(data) < 2:
+ return
+
+ max_D = max(data)
+ min_D = min(data)
+ #add by NL 06-20-2011: fix the error: when max_D is infinite, log function in detScale will go wrong
+ if max_D == float('inf') or max_D>webqtlConfig.MAXLRS:
+ max_D=webqtlConfig.MAXLRS #maximum LRS value
+
+ xLow, xTop, stepX = detScale(min_D, max_D)
+
+ #reduce data
+ step = ceil((xTop-xLow)/50.0)
+ j = xLow
+ dataXY = []
+ Count = []
+ while j <= xTop:
+ dataXY.append(j)
+ Count.append(0)
+ j += step
+
+ for i, item in enumerate(data):
+ if item == float('inf') or item>webqtlConfig.MAXLRS:
+ item = webqtlConfig.MAXLRS #maximum LRS value
+ j = int((item-xLow)/step)
+ Count[j] += 1
+
+ yLow, yTop, stepY=detScale(0,max(Count))
+
+ #draw data
+ xScale = plotWidth/(xTop-xLow)
+ yScale = plotHeight/(yTop-yLow)
+ barWidth = xScale*step
+
+ for i, count in enumerate(Count):
+ if count:
+ xc = (dataXY[i]-xLow)*xScale+xLeftOffset
+ yc =-(count-yLow)*yScale+yTopOffset+plotHeight
+ canvas.drawRect(xc+2,yc,xc+barWidth-2,yTopOffset+plotHeight,edgeColor=barColor,fillColor=barColor)
+
+ #draw drawing region
+ canvas.drawRect(xLeftOffset, yTopOffset, xLeftOffset+plotWidth, yTopOffset+plotHeight)
+
+ #draw scale
+ scaleFont=pid.Font(ttf="cour",size=11,bold=1)
+ x=xLow
+ for i in range(stepX+1):
+ xc=xLeftOffset+(x-xLow)*xScale
+ canvas.drawLine(xc,yTopOffset+plotHeight,xc,yTopOffset+plotHeight+5, color=axesColor)
+ strX = cformat(d=x, rank=0)
+ canvas.drawString(strX,xc-canvas.stringWidth(strX,font=scaleFont)/2,yTopOffset+plotHeight+14,font=scaleFont)
+ x+= (xTop - xLow)/stepX
+
+ y=yLow
+ for i in range(stepY+1):
+ yc=yTopOffset+plotHeight-(y-yLow)*yScale
+ canvas.drawLine(xLeftOffset,yc,xLeftOffset-5,yc, color=axesColor)
+ strY = "%d" %y
+ canvas.drawString(strY,xLeftOffset-canvas.stringWidth(strY,font=scaleFont)-6,yc+5,font=scaleFont)
+ y+= (yTop - yLow)/stepY
+
+ #draw label
+ labelFont=pid.Font(ttf="tahoma",size=17,bold=0)
+ if XLabel:
+ canvas.drawString(XLabel,xLeftOffset+(plotWidth-canvas.stringWidth(XLabel,font=labelFont))/2.0,
+ yTopOffset+plotHeight+yBottomOffset-10,font=labelFont,color=labelColor)
+
+ if YLabel:
+ canvas.drawString(YLabel, 19, yTopOffset+plotHeight-(plotHeight-canvas.stringWidth(YLabel,font=labelFont))/2.0,
+ font=labelFont,color=labelColor,angle=90)
+
+ labelFont=pid.Font(ttf="verdana",size=16,bold=0)
+ if title:
+ canvas.drawString(title,xLeftOffset+(plotWidth-canvas.stringWidth(title,font=labelFont))/2.0,
+ 20,font=labelFont,color=labelColor)
+
+def plotBarText(canvas, data, label, variance=None, barColor=pid.blue, axesColor=pid.black, labelColor=pid.black, XLabel=None, YLabel=None, title=None, sLabel = None, offset= (80, 20, 40, 100), barSpace = 2, zoom = 1):
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ if plotHeight<=0 or plotWidth<=0:
+ return
+
+ NNN = len(data)
+ if NNN < 2 or NNN != len(label):
+ return
+ if variance and len(variance)!=NNN:
+ variance = []
+
+ Y2 = data[:]
+ if variance:
+ for i in range(NNN):
+ if variance[i]:
+ Y2 += [data[i]-variance[i]]
+
+ #Y axis
+ YLow, YTop, stepY = detScale(min(Y2), max(Y2))
+ YScale = plotHeight/(YTop - YLow)
+
+ if YLow < 0 and YTop > 0:
+ drawZero = 1
+ else:
+ drawZero = 0
+
+ #X axis
+ X = range(NNN)
+ Xll= 0
+ Xur= NNN-1
+
+
+ if drawZero:
+ YZero = yTopOffset+plotHeight-YScale*(0-YLow)
+ canvas.drawLine(xLeftOffset, YZero, xLeftOffset+plotWidth, YZero)
+ else:
+ YZero = yTopOffset+plotHeight
+ #draw data
+ spaceWidth = barSpace
+ if spaceWidth < 1:
+ spaceWidth = 1
+ barWidth = int((plotWidth - (NNN-1.0)*spaceWidth)/NNN)
+
+ xc= xLeftOffset
+ scaleFont=pid.Font(ttf="verdana",size=11,bold=0)
+ for i in range(NNN):
+ yc = yTopOffset+plotHeight-(data[i]-YLow)*YScale
+ canvas.drawRect(xc,YZero,xc+barWidth-1, yc, edgeColor=barColor,fillColor=barColor)
+ if variance and variance[i]:
+ varlen = variance[i]*YScale
+ if yc-varlen < yTopOffset:
+ topYd = yTopOffset
+ else:
+ topYd = yc-varlen
+ canvas.drawLine(xc+barWidth/2-2,yc-varlen,xc+barWidth/2+2,yc-varlen,color=pid.red)
+ canvas.drawLine(xc+barWidth/2,yc+varlen,xc+barWidth/2,topYd,color=pid.red)
+ canvas.drawLine(xc+barWidth/2-2,yc+varlen,xc+barWidth/2+2,yc+varlen,color=pid.red)
+ strX = label[i]
+ canvas.drawString(strX,xc+barWidth/2.0+2,yTopOffset+plotHeight+2+canvas.stringWidth(strX,font=scaleFont),font=scaleFont,angle=90)
+ xc += barWidth + spaceWidth
+
+ #draw drawing region
+ canvas.drawRect(xLeftOffset, yTopOffset, xLeftOffset+plotWidth, yTopOffset+plotHeight)
+
+ #draw Y scale
+ scaleFont=pid.Font(ttf="cour",size=16,bold=1)
+ y=YLow
+ for i in range(stepY+1):
+ yc=yTopOffset+plotHeight-(y-YLow)*YScale
+ canvas.drawLine(xLeftOffset,yc,xLeftOffset-5,yc, color=axesColor)
+ strY = cformat(d=y, rank=0)
+ canvas.drawString(strY,xLeftOffset-canvas.stringWidth(strY,font=scaleFont)-6,yc+5,font=scaleFont)
+ y+= (YTop - YLow)/stepY
+
+ #draw label
+ labelFont=pid.Font(ttf="verdana",size=17,bold=0)
+ if XLabel:
+ canvas.drawString(XLabel,xLeftOffset+(plotWidth-canvas.stringWidth(XLabel,font=labelFont))/2.0,yTopOffset+plotHeight+65,font=labelFont,color=labelColor)
+
+ if YLabel:
+ canvas.drawString(YLabel,xLeftOffset-50, yTopOffset+plotHeight-(plotHeight-canvas.stringWidth(YLabel,font=labelFont))/2.0,font=labelFont,color=labelColor,angle=90)
+
+ labelFont=pid.Font(ttf="verdana",size=18,bold=0)
+ if title:
+ canvas.drawString(title,xLeftOffset,yTopOffset-15,font=labelFont,color=labelColor)
+
+ return
+
+def plotXY(canvas, dataX, dataY, rank=0, dataLabel=[], plotColor = pid.black, axesColor=pid.black, labelColor=pid.black, lineSize="thin", lineColor=pid.grey, idFont="arial", idColor=pid.blue, idSize="14", symbolColor=pid.black, symbolType="circle", filled="yes", symbolSize="tiny", XLabel=None, YLabel=None, title=None, fitcurve=None, connectdot=1, displayR=None, loadingPlot = 0, offset= (80, 20, 40, 60), zoom = 1, specialCases=[], showLabel = 1, bufferSpace = 15):
+ 'displayR : correlation scatter plot, loadings : loading plot'
+
+ dataXRanked, dataYRanked = webqtlUtil.calRank(dataX, dataY, len(dataX))
+
+ #get ID font size
+ idFontSize = int(idSize)
+
+ #If filled is yes, set fill color
+ if filled == "yes":
+ fillColor = symbolColor
+ else:
+ fillColor = None
+
+ if symbolSize == "large":
+ sizeModifier = 7
+ fontModifier = 12
+ elif symbolSize == "medium":
+ sizeModifier = 5
+ fontModifier = 8
+ elif symbolSize == "small":
+ sizeModifier = 3
+ fontModifier = 3
+ else:
+ sizeModifier = 1
+ fontModifier = -1
+
+ if rank == 0: # Pearson correlation
+ bufferSpace = 0
+ dataXPrimary = dataX
+ dataYPrimary = dataY
+ dataXAlt = dataXRanked #Values used just for printing the other corr type to the graph image
+ dataYAlt = dataYRanked #Values used just for printing the other corr type to the graph image
+ else: # Spearman correlation: Switching Ranked and Unranked X and Y values
+ dataXPrimary = dataXRanked
+ dataYPrimary = dataYRanked
+ dataXAlt = dataX #Values used just for printing the other corr type to the graph image
+ dataYAlt = dataY #Values used just for printing the other corr type to the graph image
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
+ plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
+ if plotHeight<=0 or plotWidth<=0:
+ return
+ if len(dataXPrimary) < 1 or len(dataXPrimary) != len(dataYPrimary) or (dataLabel and len(dataXPrimary) != len(dataLabel)):
+ return
+
+ max_X=max(dataXPrimary)
+ min_X=min(dataXPrimary)
+ max_Y=max(dataYPrimary)
+ min_Y=min(dataYPrimary)
+
+ #for some reason I forgot why I need to do this
+ if loadingPlot:
+ min_X = min(-0.1,min_X)
+ max_X = max(0.1,max_X)
+ min_Y = min(-0.1,min_Y)
+ max_Y = max(0.1,max_Y)
+
+ xLow, xTop, stepX=detScale(min_X,max_X)
+ yLow, yTop, stepY=detScale(min_Y,max_Y)
+ xScale = plotWidth/(xTop-xLow)
+ yScale = plotHeight/(yTop-yLow)
+
+ #draw drawing region
+ canvas.drawRect(xLeftOffset-bufferSpace, yTopOffset, xLeftOffset+plotWidth, yTopOffset+plotHeight+bufferSpace)
+ canvas.drawRect(xLeftOffset-bufferSpace+1, yTopOffset, xLeftOffset+plotWidth, yTopOffset+plotHeight+bufferSpace-1)
+
+ #calculate data points
+ data = map(lambda X, Y: (X, Y), dataXPrimary, dataYPrimary)
+ xCoord = map(lambda X, Y: ((X-xLow)*xScale + xLeftOffset, yTopOffset+plotHeight-(Y-yLow)*yScale), dataXPrimary, dataYPrimary)
+
+ labelFont=pid.Font(ttf=idFont,size=idFontSize,bold=0)
+
+ if loadingPlot:
+ xZero = -xLow*xScale+xLeftOffset
+ yZero = yTopOffset+plotHeight+yLow*yScale
+ for point in xCoord:
+ canvas.drawLine(xZero,yZero,point[0],point[1],color=pid.red)
+ else:
+ if connectdot:
+ canvas.drawPolygon(xCoord,edgeColor=plotColor,closed=0)
+ else:
+ pass
+
+ symbolFont = pid.Font(ttf="fnt_bs", size=12+fontModifier,bold=0)
+
+ for i, item in enumerate(xCoord):
+ if dataLabel and dataLabel[i] in specialCases:
+ canvas.drawRect(item[0]-3, item[1]-3, item[0]+3, item[1]+3, edgeColor=pid.green)
+ #canvas.drawCross(item[0],item[1],color=pid.blue,size=5)
+ else:
+ if symbolType == "vertRect":
+ canvas.drawRect(x1=item[0]-sizeModifier+2,y1=item[1]-sizeModifier-2, x2=item[0]+sizeModifier-1,y2=item[1]+sizeModifier+2, edgeColor=symbolColor, edgeWidth=1, fillColor=fillColor)
+ elif (symbolType == "circle" and filled != "yes"):
+ canvas.drawString(":", item[0]-canvas.stringWidth(":",font=symbolFont)/2+1,item[1]+2,color=symbolColor, font=symbolFont)
+ elif (symbolType == "circle" and filled == "yes"):
+ canvas.drawString("5", item[0]-canvas.stringWidth("5",font=symbolFont)/2+1,item[1]+2,color=symbolColor, font=symbolFont)
+ elif symbolType == "horiRect":
+ canvas.drawRect(x1=item[0]-sizeModifier-1,y1=item[1]-sizeModifier+3, x2=item[0]+sizeModifier+3,y2=item[1]+sizeModifier-2, edgeColor=symbolColor, edgeWidth=1, fillColor=fillColor)
+ elif (symbolType == "square"):
+ canvas.drawRect(x1=item[0]-sizeModifier+1,y1=item[1]-sizeModifier-4, x2=item[0]+sizeModifier+2,y2=item[1]+sizeModifier-3, edgeColor=symbolColor, edgeWidth=1, fillColor=fillColor)
+ elif (symbolType == "diamond" and filled != "yes"):
+ canvas.drawString(",", item[0]-canvas.stringWidth(",",font=symbolFont)/2+2, item[1]+6, font=symbolFont, color=symbolColor)
+ elif (symbolType == "diamond" and filled == "yes"):
+ canvas.drawString("D", item[0]-canvas.stringWidth("D",font=symbolFont)/2+2, item[1]+6, font=symbolFont, color=symbolColor)
+ elif symbolType == "4-star":
+ canvas.drawString("l", item[0]-canvas.stringWidth("l",font=symbolFont)/2+1, item[1]+3, font=symbolFont, color=symbolColor)
+ elif symbolType == "3-star":
+ canvas.drawString("k", item[0]-canvas.stringWidth("k",font=symbolFont)/2+1, item[1]+3, font=symbolFont, color=symbolColor)
+ else:
+ canvas.drawCross(item[0],item[1]-2,color=symbolColor, size=sizeModifier+2)
+
+ if showLabel and dataLabel:
+ if (symbolType == "vertRect" or symbolType == "diamond"):
+ labelGap = 15
+ elif (symbolType == "4-star" or symbolType == "3-star"):
+ labelGap = 12
+ else:
+ labelGap = 11
+ canvas.drawString(dataLabel[i], item[0]- canvas.stringWidth(dataLabel[i],
+ font=labelFont)/2 + 1, item[1]+(labelGap+sizeModifier+(idFontSize-12)), font=labelFont, color=idColor)
+
+ #draw scale
+ scaleFont=pid.Font(ttf="cour",size=16,bold=1)
+
+
+ x=xLow
+ for i in range(stepX+1):
+ xc=xLeftOffset+(x-xLow)*xScale
+ if ((x == 0) & (rank == 1)):
+ pass
+ else:
+ canvas.drawLine(xc,yTopOffset+plotHeight + bufferSpace,xc,yTopOffset+plotHeight+5 + bufferSpace, color=axesColor)
+ strX = cformat(d=x, rank=rank)
+ if ((strX == "0") & (rank == 1)):
+ pass
+ else:
+ canvas.drawString(strX,xc-canvas.stringWidth(strX,font=scaleFont)/2,yTopOffset+plotHeight+20 + bufferSpace,font=scaleFont)
+ x+= (xTop - xLow)/stepX
+
+ y=yLow
+ for i in range(stepY+1):
+ yc=yTopOffset+plotHeight-(y-yLow)*yScale
+ if ((y == 0) & (rank == 1)):
+ pass
+ else:
+ canvas.drawLine(xLeftOffset - bufferSpace,yc,xLeftOffset-5 - bufferSpace,yc, color=axesColor)
+ strY = cformat(d=y, rank=rank)
+ if ((strY == "0") & (rank == 1)):
+ pass
+ else:
+ canvas.drawString(strY,xLeftOffset-canvas.stringWidth(strY,font=scaleFont)- 10 - bufferSpace,yc+4,font=scaleFont)
+ y+= (yTop - yLow)/stepY
+
+ #draw label
+
+ labelFont=pid.Font(ttf="verdana",size=canvas.size[0]/45,bold=0)
+ titleFont=pid.Font(ttf="verdana",size=canvas.size[0]/40,bold=0)
+
+ if (rank == 1 and not title):
+ canvas.drawString("Spearman Rank Correlation", xLeftOffset-canvas.size[0]*.025+(plotWidth-canvas.stringWidth("Spearman Rank Correlation",font=titleFont))/2.0,
+ 25,font=titleFont,color=labelColor)
+ elif (rank == 0 and not title):
+ canvas.drawString("Pearson Correlation", xLeftOffset-canvas.size[0]*.025+(plotWidth-canvas.stringWidth("Pearson Correlation",font=titleFont))/2.0,
+ 25,font=titleFont,color=labelColor)
+
+ if XLabel:
+ canvas.drawString(XLabel,xLeftOffset+(plotWidth-canvas.stringWidth(XLabel,font=labelFont))/2.0,
+ yTopOffset+plotHeight+yBottomOffset-25,font=labelFont,color=labelColor)
+
+ if YLabel:
+ canvas.drawString(YLabel, xLeftOffset-65, yTopOffset+plotHeight- (plotHeight-canvas.stringWidth(YLabel,font=labelFont))/2.0,
+ font=labelFont,color=labelColor,angle=90)
+
+ labelFont=pid.Font(ttf="verdana",size=20,bold=0)
+ if title:
+ canvas.drawString(title,xLeftOffset+(plotWidth-canvas.stringWidth(title,font=labelFont))/2.0,
+ 20,font=labelFont,color=labelColor)
+
+ if fitcurve:
+ import sys
+ sys.argv = [ "mod_python" ]
+ #from numarray import linear_algebra as la
+ #from numarray import ones, array, dot, swapaxes
+ fitYY = array(dataYPrimary)
+ fitXX = array([ones(len(dataXPrimary)),dataXPrimary])
+ AA = dot(fitXX,swapaxes(fitXX,0,1))
+ BB = dot(fitXX,fitYY)
+ bb = la.linear_least_squares(AA,BB)[0]
+
+ xc1 = xLeftOffset
+ yc1 = yTopOffset+plotHeight-(bb[0]+bb[1]*xLow-yLow)*yScale
+ if yc1 > yTopOffset+plotHeight:
+ yc1 = yTopOffset+plotHeight
+ xc1 = (yLow-bb[0])/bb[1]
+ xc1=(xc1-xLow)*xScale+xLeftOffset
+ elif yc1 < yTopOffset:
+ yc1 = yTopOffset
+ xc1 = (yTop-bb[0])/bb[1]
+ xc1=(xc1-xLow)*xScale+xLeftOffset
+ else:
+ pass
+
+ xc2 = xLeftOffset + plotWidth
+ yc2 = yTopOffset+plotHeight-(bb[0]+bb[1]*xTop-yLow)*yScale
+ if yc2 > yTopOffset+plotHeight:
+ yc2 = yTopOffset+plotHeight
+ xc2 = (yLow-bb[0])/bb[1]
+ xc2=(xc2-xLow)*xScale+xLeftOffset
+ elif yc2 < yTopOffset:
+ yc2 = yTopOffset
+ xc2 = (yTop-bb[0])/bb[1]
+ xc2=(xc2-xLow)*xScale+xLeftOffset
+ else:
+ pass
+
+ canvas.drawLine(xc1 - bufferSpace,yc1 + bufferSpace,xc2,yc2,color=lineColor)
+ if lineSize == "medium":
+ canvas.drawLine(xc1 - bufferSpace,yc1 + bufferSpace+1,xc2,yc2+1,color=lineColor)
+ if lineSize == "thick":
+ canvas.drawLine(xc1 - bufferSpace,yc1 + bufferSpace+1,xc2,yc2+1,color=lineColor)
+ canvas.drawLine(xc1 - bufferSpace,yc1 + bufferSpace-1,xc2,yc2-1,color=lineColor)
+
+
+ if displayR:
+ labelFont=pid.Font(ttf="trebuc",size=canvas.size[0]/60,bold=0)
+ NNN = len(dataX)
+ corr = webqtlUtil.calCorrelation(dataXPrimary,dataYPrimary,NNN)[0]
+
+ if NNN < 3:
+ corrPValue = 1.0
+ else:
+ if abs(corr) >= 1.0:
+ corrPValue = 0.0
+ else:
+ ZValue = 0.5*log((1.0+corr)/(1.0-corr))
+ ZValue = ZValue*sqrt(NNN-3)
+ corrPValue = 2.0*(1.0 - reaper.normp(abs(ZValue)))
+
+ NStr = "N = %d" % NNN
+ strLenN = canvas.stringWidth(NStr,font=labelFont)
+
+ if rank == 1:
+ if corrPValue < 0.0000000000000001:
+ corrStr = "Rho = %1.3f P < 1.00 E-16" % (corr)
+ else:
+ corrStr = "Rho = %1.3f P = %3.2E" % (corr, corrPValue)
+ else:
+ if corrPValue < 0.0000000000000001:
+ corrStr = "r = %1.3f P < 1.00 E-16" % (corr)
+ else:
+ corrStr = "r = %1.3f P = %3.2E" % (corr, corrPValue)
+ strLen = canvas.stringWidth(corrStr,font=labelFont)
+
+ canvas.drawString(NStr,xLeftOffset,yTopOffset-10,font=labelFont,color=labelColor)
+ canvas.drawString(corrStr,xLeftOffset+plotWidth-strLen,yTopOffset-10,font=labelFont,color=labelColor)
+
+ return xCoord
+
+def plotXYSVG(drawSpace, dataX, dataY, rank=0, dataLabel=[], plotColor = "black", axesColor="black", labelColor="black", symbolColor="red", XLabel=None, YLabel=None, title=None, fitcurve=None, connectdot=1, displayR=None, loadingPlot = 0, offset= (80, 20, 40, 60), zoom = 1, specialCases=[], showLabel = 1):
+ 'displayR : correlation scatter plot, loadings : loading plot'
+
+ dataXRanked, dataYRanked = webqtlUtil.calRank(dataX, dataY, len(dataX))
+
+ # Switching Ranked and Unranked X and Y values if a Spearman Rank Correlation
+ if rank == 0:
+ dataXPrimary = dataX
+ dataYPrimary = dataY
+ dataXAlt = dataXRanked
+ dataYAlt = dataYRanked
+
+ else:
+ dataXPrimary = dataXRanked
+ dataYPrimary = dataYRanked
+ dataXAlt = dataX
+ dataYAlt = dataY
+
+
+
+ xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
+ plotWidth = drawSpace.attributes['width'] - xLeftOffset - xRightOffset
+ plotHeight = drawSpace.attributes['height'] - yTopOffset - yBottomOffset
+ if plotHeight<=0 or plotWidth<=0:
+ return
+ if len(dataXPrimary) < 1 or len(dataXPrimary) != len(dataYPrimary) or (dataLabel and len(dataXPrimary) != len(dataLabel)):
+ return
+
+ max_X=max(dataXPrimary)
+ min_X=min(dataXPrimary)
+ max_Y=max(dataYPrimary)
+ min_Y=min(dataYPrimary)
+
+ #for some reason I forgot why I need to do this
+ if loadingPlot:
+ min_X = min(-0.1,min_X)
+ max_X = max(0.1,max_X)
+ min_Y = min(-0.1,min_Y)
+ max_Y = max(0.1,max_Y)
+
+ xLow, xTop, stepX=detScale(min_X,max_X)
+ yLow, yTop, stepY=detScale(min_Y,max_Y)
+ xScale = plotWidth/(xTop-xLow)
+ yScale = plotHeight/(yTop-yLow)
+
+ #draw drawing region
+ r = svg.rect(xLeftOffset, yTopOffset, plotWidth, plotHeight, 'none', axesColor, 1)
+ drawSpace.addElement(r)
+
+ #calculate data points
+ data = map(lambda X, Y: (X, Y), dataXPrimary, dataYPrimary)
+ xCoord = map(lambda X, Y: ((X-xLow)*xScale + xLeftOffset, yTopOffset+plotHeight-(Y-yLow)*yScale), dataXPrimary, dataYPrimary)
+ labelFontF = "verdana"
+ labelFontS = 11
+
+ if loadingPlot:
+ xZero = -xLow*xScale+xLeftOffset
+ yZero = yTopOffset+plotHeight+yLow*yScale
+ for point in xCoord:
+ drawSpace.addElement(svg.line(xZero,yZero,point[0],point[1], "red", 1))
+ else:
+ if connectdot:
+ pass
+ #drawSpace.drawPolygon(xCoord,edgeColor=plotColor,closed=0)
+ else:
+ pass
+
+ for i, item in enumerate(xCoord):
+ if dataLabel and dataLabel[i] in specialCases:
+ drawSpace.addElement(svg.rect(item[0]-3, item[1]-3, 6, 6, "none", "green", 0.5))
+ #drawSpace.drawCross(item[0],item[1],color=pid.blue,size=5)
+ else:
+ drawSpace.addElement(svg.line(item[0],item[1]+5,item[0],item[1]-5,symbolColor,1))
+ drawSpace.addElement(svg.line(item[0]+5,item[1],item[0]-5,item[1],symbolColor,1))
+ if showLabel and dataLabel:
+ pass
+ drawSpace.addElement(svg.text(item[0], item[1]+14, dataLabel[i], labelFontS,
+ labelFontF, text_anchor="middle", style="stroke:blue;stroke-width:0.5;"))
+ #canvas.drawString(, item[0]- canvas.stringWidth(dataLabel[i],
+ # font=labelFont)/2, item[1]+14, font=labelFont, color=pid.blue)
+
+ #draw scale
+ #scaleFont=pid.Font(ttf="cour",size=14,bold=1)
+ x=xLow
+ for i in range(stepX+1):
+ xc=xLeftOffset+(x-xLow)*xScale
+ drawSpace.addElement(svg.line(xc,yTopOffset+plotHeight,xc,yTopOffset+plotHeight+5, axesColor, 1))
+ strX = cformat(d=x, rank=rank)
+ drawSpace.addElement(svg.text(xc,yTopOffset+plotHeight+20,strX,13, "courier", text_anchor="middle"))
+ x+= (xTop - xLow)/stepX
+
+ y=yLow
+ for i in range(stepY+1):
+ yc=yTopOffset+plotHeight-(y-yLow)*yScale
+ drawSpace.addElement(svg.line(xLeftOffset,yc,xLeftOffset-5,yc, axesColor, 1))
+ strY = cformat(d=y, rank=rank)
+ drawSpace.addElement(svg.text(xLeftOffset-10,yc+5,strY,13, "courier", text_anchor="end"))
+ y+= (yTop - yLow)/stepY
+
+ #draw label
+ labelFontF = "verdana"
+ labelFontS = 17
+ if XLabel:
+ drawSpace.addElement(svg.text(xLeftOffset+plotWidth/2.0,
+ yTopOffset+plotHeight+yBottomOffset-10,XLabel,
+ labelFontS, labelFontF, text_anchor="middle"))
+
+ if YLabel:
+ drawSpace.addElement(svg.text(xLeftOffset-50,
+ yTopOffset+plotHeight/2,YLabel,
+ labelFontS, labelFontF, text_anchor="middle", style="writing-mode:tb-rl", transform="rotate(270 %d %d)" % (xLeftOffset-50, yTopOffset+plotHeight/2)))
+ #drawSpace.drawString(YLabel, xLeftOffset-50, yTopOffset+plotHeight- (plotHeight-drawSpace.stringWidth(YLabel,font=labelFont))/2.0,
+ # font=labelFont,color=labelColor,angle=90)
+
+
+ if fitcurve:
+ sys.argv = [ "mod_python" ]
+ #from numarray import linear_algebra as la
+ #from numarray import ones, array, dot, swapaxes
+ fitYY = array(dataYPrimary)
+ fitXX = array([ones(len(dataXPrimary)),dataXPrimary])
+ AA = dot(fitXX,swapaxes(fitXX,0,1))
+ BB = dot(fitXX,fitYY)
+ bb = la.linear_least_squares(AA,BB)[0]
+
+ xc1 = xLeftOffset
+ yc1 = yTopOffset+plotHeight-(bb[0]+bb[1]*xLow-yLow)*yScale
+ if yc1 > yTopOffset+plotHeight:
+ yc1 = yTopOffset+plotHeight
+ xc1 = (yLow-bb[0])/bb[1]
+ xc1=(xc1-xLow)*xScale+xLeftOffset
+ elif yc1 < yTopOffset:
+ yc1 = yTopOffset
+ xc1 = (yTop-bb[0])/bb[1]
+ xc1=(xc1-xLow)*xScale+xLeftOffset
+ else:
+ pass
+
+ xc2 = xLeftOffset + plotWidth
+ yc2 = yTopOffset+plotHeight-(bb[0]+bb[1]*xTop-yLow)*yScale
+ if yc2 > yTopOffset+plotHeight:
+ yc2 = yTopOffset+plotHeight
+ xc2 = (yLow-bb[0])/bb[1]
+ xc2=(xc2-xLow)*xScale+xLeftOffset
+ elif yc2 < yTopOffset:
+ yc2 = yTopOffset
+ xc2 = (yTop-bb[0])/bb[1]
+ xc2=(xc2-xLow)*xScale+xLeftOffset
+ else:
+ pass
+
+ drawSpace.addElement(svg.line(xc1,yc1,xc2,yc2,"green", 1))
+
+ if displayR:
+ labelFontF = "trebuc"
+ labelFontS = 14
+ NNN = len(dataX)
+
+ corr = webqtlUtil.calCorrelation(dataXPrimary,dataYPrimary,NNN)[0]
+
+ if NNN < 3:
+ corrPValue = 1.0
+ else:
+ if abs(corr) >= 1.0:
+ corrPValue = 0.0
+ else:
+ ZValue = 0.5*log((1.0+corr)/(1.0-corr))
+ ZValue = ZValue*sqrt(NNN-3)
+ corrPValue = 2.0*(1.0 - reaper.normp(abs(ZValue)))
+
+ NStr = "N of Cases=%d" % NNN
+
+ if rank == 1:
+ corrStr = "Spearman's r=%1.3f P=%3.2E" % (corr, corrPValue)
+ else:
+ corrStr = "Pearson's r=%1.3f P=%3.2E" % (corr, corrPValue)
+
+ drawSpace.addElement(svg.text(xLeftOffset,yTopOffset-10,NStr,
+ labelFontS, labelFontF, text_anchor="start"))
+ drawSpace.addElement(svg.text(xLeftOffset+plotWidth,yTopOffset-25,corrStr,
+ labelFontS, labelFontF, text_anchor="end"))
+ """
+ """
+ return
+
+
+# This function determines the scale of the plot
+def detScaleOld(min,max):
+ if min>=max:
+ return None
+ elif min == -1.0 and max == 1.0:
+ return [-1.2,1.2,12]
+ else:
+ a=max-min
+ b=floor(log10(a))
+ c=pow(10.0,b)
+ if a < c*5.0:
+ c/=2.0
+ #print a,b,c
+ low=c*floor(min/c)
+ high=c*ceil(max/c)
+ return [low,high,round((high-low)/c)]
+
+def detScale(min=0,max=0,bufferSpace=3):
+
+ if min>=max:
+ return None
+ elif min == -1.0 and max == 1.0:
+ return [-1.2,1.2,12]
+ else:
+ a=max-min
+ if max != 0:
+ max += 0.1*a
+ if min != 0:
+ if min > 0 and min < 0.1*a:
+ min = 0.0
+ else:
+ min -= 0.1*a
+ a=max-min
+ b=floor(log10(a))
+ c=pow(10.0,b)
+ low=c*floor(min/c)
+ high=c*ceil(max/c)
+ n = round((high-low)/c)
+ div = 2.0
+ while n < 5 or n > 15:
+ if n < 5:
+ c /= div
+ else:
+ c *= div
+ if div == 2.0:
+ div =5.0
+ else:
+ div =2.0
+ low=c*floor(min/c)
+ high=c*ceil(max/c)
+ n = round((high-low)/c)
+
+ return [low,high,n]
+
+
+
+def colorSpectrumOld(n):
+ if n == 1:
+ return [pid.Color(1,0,0)]
+ elif n == 2:
+ return [pid.Color(1,0,0),pid.Color(0,0,1)]
+ elif n == 3:
+ return [pid.Color(1,0,0),pid.Color(0,1,0),pid.Color(0,0,1)]
+ else:
+ step = 2.0/(n-1)
+ red = 1.0
+ green = 0.0
+ blue = 0.0
+ colors = [pid.Color(red,green,blue)]
+ i = 1
+ greenpeak = 0
+ while i < n:
+ if red >= step:
+ red -= step
+ green += step
+ if green >= 1.0:
+ greenpeak = 1
+ blue += green -1.0
+ green = 1.0
+ else:
+ red = 0.0
+ if greenpeak:
+ green -= step
+ blue += step
+ else:
+ green += step
+ if green >= 1.0:
+ greenpeak = 1
+ blue += green -1.0
+ green = 2.0 -green
+ elif green < 0.0:
+ green = 0.0
+ else:
+ pass
+ colors.append(pid.Color(red,green,blue))
+ i += 1
+ return colors
+
+
+
+
+def bluefunc(x):
+ return 1.0 / (1.0 + exp(-10*(x-0.6)))
+
+
+def redfunc(x):
+ return 1.0 / (1.0 + exp(10*(x-0.5)))
+
+def greenfunc(x):
+ return 1 - pow(redfunc(x+0.2),2) - bluefunc(x-0.3)
+
+def colorSpectrum(n=100):
+ multiple = 10
+ if n == 1:
+ return [pid.Color(1,0,0)]
+ elif n == 2:
+ return [pid.Color(1,0,0),pid.Color(0,0,1)]
+ elif n == 3:
+ return [pid.Color(1,0,0),pid.Color(0,1,0),pid.Color(0,0,1)]
+ N = n*multiple
+ out = [None]*N;
+ for i in range(N):
+ x = float(i)/N
+ out[i] = pid.Color(redfunc(x), greenfunc(x), bluefunc(x));
+ out2 = [out[0]]
+ step = N/float(n-1)
+ j = 0
+ for i in range(n-2):
+ j += step
+ out2.append(out[int(j)])
+ out2.append(out[-1])
+ return out2
+
+
+def colorSpectrumSVG(n=100):
+ multiple = 10
+ if n == 1:
+ return ["rgb(255,0,0)"]
+ elif n == 2:
+ return ["rgb(255,0,0)","rgb(0,0,255)"]
+ elif n == 3:
+ return ["rgb(255,0,0)","rgb(0,255,0)","rgb(0,0,255)"]
+ N = n*multiple
+ out = [None]*N;
+ for i in range(N):
+ x = float(i)/N
+ out[i] = "rgb(%d, %d, %d)" % (redfunc(x)*255, greenfunc(x)*255, bluefunc(x)*255);
+ out2 = [out[0]]
+ step = N/float(n-1)
+ j = 0
+ for i in range(n-2):
+ j += step
+ out2.append(out[int(j)])
+ out2.append(out[-1])
+ return out2
+
+
+def BWSpectrum(n=100):
+ multiple = 10
+ if n == 1:
+ return [pid.Color(0,0,0)]
+ elif n == 2:
+ return [pid.Color(0,0,0),pid.Color(1,1,1)]
+ elif n == 3:
+ return [pid.Color(0,0,0),pid.Color(0.5,0.5,0.5),pid.Color(1,1,1)]
+
+ step = 1.0/n
+ x = 0.0
+ out = []
+ for i in range(n):
+ out.append(pid.Color(x,x,x));
+ x += step
+ return out
diff --git a/web/webqtl/utility/TDCell.py b/web/webqtl/utility/TDCell.py
new file mode 100755
index 00000000..76b9c5db
--- /dev/null
+++ b/web/webqtl/utility/TDCell.py
@@ -0,0 +1,42 @@
+# 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
+
+##########################################################
+#
+# Table Cell Class
+#
+##########################################################
+
+
+class TDCell:
+ def __init__(self, html="", text="", val=0.0):
+ self.html = html #html, for web page
+ self.text = text #text value, for output to a text file
+ self.val = val #sort by value
+
+ def __str__(self):
+ return self.text
+
diff --git a/web/webqtl/utility/THCell.py b/web/webqtl/utility/THCell.py
new file mode 100755
index 00000000..a96b9e49
--- /dev/null
+++ b/web/webqtl/utility/THCell.py
@@ -0,0 +1,44 @@
+# 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
+
+##########################################################
+#
+# Table Header Class
+#
+##########################################################
+
+
+class THCell:
+ def __init__(self, html="", text="", sort=1, idx=-1):
+ self.html = html #html, for web page
+ self.text = text #Column text value
+ self.sort = sort #0: not sortable, 1: yes
+ self.idx = idx #sort by value
+
+ def __str__(self):
+ return self.text
+
+
diff --git a/web/webqtl/utility/__init__.py b/web/webqtl/utility/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/utility/__init__.py
diff --git a/web/webqtl/utility/svg.py b/web/webqtl/utility/svg.py
new file mode 100755
index 00000000..e49a6c3c
--- /dev/null
+++ b/web/webqtl/utility/svg.py
@@ -0,0 +1,1069 @@
+# 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
+
+#!/usr/bin/env python
+##Copyright (c) 2002, Fedor Baart & Hans de Wit (Stichting Farmaceutische Kengetallen)
+##All rights reserved.
+##
+##Redistribution and use in source and binary forms, with or without modification,
+##are permitted provided that the following conditions are met:
+##
+##Redistributions of source code must retain the above copyright notice, this
+##list of conditions and the following disclaimer.
+##
+##Redistributions in binary form must reproduce the above copyright notice,
+##this list of conditions and the following disclaimer in the documentation and/or
+##other materials provided with the distribution.
+##
+##Neither the name of the Stichting Farmaceutische Kengetallen nor the names of
+##its contributors may be used to endorse or promote products derived from this
+##software without specific prior written permission.
+##
+##THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+##AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+##IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+##DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+##FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+##DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+##SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+##CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+##OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+##OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+##Thanks to Gerald Rosennfellner for his help and useful comments.
+
+__doc__="""Use SVGdraw to generate your SVGdrawings.
+
+SVGdraw uses an object model drawing and a method toXML to create SVG graphics
+by using easy to use classes and methods usualy you start by creating a drawing eg
+
+ d=drawing()
+ #then you create a SVG root element
+ s=svg()
+ #then you add some elements eg a circle and add it to the svg root element
+ c=circle()
+ #you can supply attributes by using named arguments.
+ c=circle(fill='red',stroke='blue')
+ #or by updating the attributes attribute:
+ c.attributes['stroke-width']=1
+ s.addElement(c)
+ #then you add the svg root element to the drawing
+ d.setSVG(s)
+ #and finaly you xmlify the drawing
+ d.toXml()
+
+
+this results in the svg source of the drawing, which consists of a circle
+on a white background. Its as easy as that;)
+This module was created using the SVG specification of www.w3c.org and the
+O'Reilly (www.oreilly.com) python books as information sources. A svg viewer
+is available from www.adobe.com"""
+
+__version__="1.0"
+
+# there are two possibilities to generate svg:
+# via a dom implementation and directly using <element>text</element> strings
+# the latter is way faster (and shorter in coding)
+# the former is only used in debugging svg programs
+# maybe it will be removed alltogether after a while
+# with the following variable you indicate whether to use the dom implementation
+# Note that PyXML is required for using the dom implementation.
+# It is also possible to use the standard minidom. But I didn't try that one.
+# Anyway the text based approach is about 60 times faster than using the full dom implementation.
+use_dom_implementation=0
+
+
+import exceptions
+if use_dom_implementation<>0:
+ try:
+ from xml.dom import implementation
+ from xml.dom.ext import PrettyPrint
+ except:
+ raise exceptions.ImportError, "PyXML is required for using the dom implementation"
+#The implementation is used for the creating the XML document.
+#The prettyprint module is used for converting the xml document object to a xml file
+
+import sys
+assert sys.version_info[0]>=2
+if sys.version_info[1]<2:
+ True=1
+ False=0
+ file=open
+
+sys.setrecursionlimit=50
+#The recursion limit is set conservative so mistakes like s=svg() s.addElement(s)
+#won't eat up too much processor time.
+
+#the following code is pasted form xml.sax.saxutils
+#it makes it possible to run the code without the xml sax package installed
+#To make it possible to have <rubbish> in your text elements, it is necessary to escape the texts
+def _escape(data, entities={}):
+ """Escape &, <, and > in a string of data.
+
+ You can escape other strings of data by passing a dictionary as
+ the optional entities parameter. The keys and values must all be
+ strings; each key will be replaced with its corresponding value.
+ """
+ #data = data.replace("&", "&amp;")
+ data = data.replace("<", "&lt;")
+ data = data.replace(">", "&gt;")
+ for chars, entity in entities.items():
+ data = data.replace(chars, entity)
+ return data
+
+def _quoteattr(data, entities={}):
+ """Escape and quote an attribute value.
+
+ Escape &, <, and > in a string of data, then quote it for use as
+ an attribute value. The \" character will be escaped as well, if
+ necessary.
+
+ You can escape other strings of data by passing a dictionary as
+ the optional entities parameter. The keys and values must all be
+ strings; each key will be replaced with its corresponding value.
+ """
+ data = _escape(data, entities)
+ if '"' in data:
+ if "'" in data:
+ data = '"%s"' % data.replace('"', "&quot;")
+ else:
+ data = "'%s'" % data
+ else:
+ data = '"%s"' % data
+ return data
+
+
+
+def _xypointlist(a):
+ """formats a list of xy pairs"""
+ s=''
+ for e in a: #this could be done more elegant
+ s+=str(e)[1:-1] +' '
+ return s
+
+def _viewboxlist(a):
+ """formats a tuple"""
+ s=''
+ for e in a:
+ s+=str(e)+' '
+ return s
+
+def _pointlist(a):
+ """formats a list of numbers"""
+ return str(a)[1:-1]
+
+class pathdata:
+ """class used to create a pathdata object which can be used for a path.
+ although most methods are pretty straightforward it might be useful to look at the SVG specification."""
+ #I didn't test the methods below.
+ def __init__(self,x=None,y=None):
+ self.path=[]
+ if x is not None and y is not None:
+ self.path.append('M '+str(x)+' '+str(y))
+ def closepath(self):
+ """ends the path"""
+ self.path.append('z')
+ def move(self,x,y):
+ """move to absolute"""
+ self.path.append('M '+str(x)+' '+str(y))
+ def relmove(self,x,y):
+ """move to relative"""
+ self.path.append('m '+str(x)+' '+str(y))
+ def line(self,x,y):
+ """line to absolute"""
+ self.path.append('L '+str(x)+' '+str(y))
+ def relline(self,x,y):
+ """line to relative"""
+ self.path.append('l '+str(x)+' '+str(y))
+ def hline(self,x):
+ """horizontal line to absolute"""
+ self.path.append('H'+str(x))
+ def relhline(self,x):
+ """horizontal line to relative"""
+ self.path.append('h'+str(x))
+ def vline(self,y):
+ """verical line to absolute"""
+ self.path.append('V'+str(y))
+ def relvline(self,y):
+ """vertical line to relative"""
+ self.path.append('v'+str(y))
+ def bezier(self,x1,y1,x2,y2,x,y):
+ """bezier with xy1 and xy2 to xy absolut"""
+ self.path.append('C'+str(x1)+','+str(y1)+' '+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
+ def relbezier(self,x1,y1,x2,y2,x,y):
+ """bezier with xy1 and xy2 to xy relative"""
+ self.path.append('c'+str(x1)+','+str(y1)+' '+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
+ def smbezier(self,x2,y2,x,y):
+ """smooth bezier with xy2 to xy absolut"""
+ self.path.append('S'+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
+ def relsmbezier(self,x2,y2,x,y):
+ """smooth bezier with xy2 to xy relative"""
+ self.path.append('s'+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
+ def qbezier(self,x1,y1,x,y):
+ """quadratic bezier with xy1 to xy absolut"""
+ self.path.append('Q'+str(x1)+','+str(y1)+' '+str(x)+','+str(y))
+ def relqbezier(self,x1,y1,x,y):
+ """quadratic bezier with xy1 to xy relative"""
+ self.path.append('q'+str(x1)+','+str(y1)+' '+str(x)+','+str(y))
+ def smqbezier(self,x,y):
+ """smooth quadratic bezier to xy absolut"""
+ self.path.append('T'+str(x)+','+str(y))
+ def relsmqbezier(self,x,y):
+ """smooth quadratic bezier to xy relative"""
+ self.path.append('t'+str(x)+','+str(y))
+ def ellarc(self,rx,ry,xrot,laf,sf,x,y):
+ """elliptival arc with rx and ry rotating with xrot using large-arc-flag and sweep-flag to xy absolut"""
+ self.path.append('A'+str(rx)+','+str(ry)+' '+str(xrot)+' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y))
+ def relellarc(self,rx,ry,xrot,laf,sf,x,y):
+ """elliptival arc with rx and ry rotating with xrot using large-arc-flag and sweep-flag to xy relative"""
+ self.path.append('a'+str(rx)+','+str(ry)+' '+str(xrot)+' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y))
+ def __repr__(self):
+ return ' '.join(self.path)
+
+
+
+
+class SVGelement:
+ """SVGelement(type,attributes,elements,text,namespace,**args)
+ Creates a arbitrary svg element and is intended to be subclassed not used on its own.
+ This element is the base of every svg element it defines a class which resembles
+ a xml-element. The main advantage of this kind of implementation is that you don't
+ have to create a toXML method for every different graph object. Every element
+ consists of a type, attribute, optional subelements, optional text and an optional
+ namespace. Note the elements==None, if elements = None:self.elements=[] construction.
+ This is done because if you default to elements=[] every object has a reference
+ to the same empty list."""
+ def __init__(self,type='',attributes=None,elements=None,text='',namespace='',cdata=None, **args):
+ self.type=type
+ if attributes==None:
+ self.attributes={}
+ else:
+ self.attributes=attributes
+ if elements==None:
+ self.elements=[]
+ else:
+ self.elements=elements
+ self.text=text
+ self.namespace=namespace
+ self.cdata=cdata
+ for arg in args.keys():
+ arg2 = arg.replace("__", ":")
+ arg2 = arg2.replace("_", "-")
+ self.attributes[arg2]=args[arg]
+ def addElement(self,SVGelement):
+ """adds an element to a SVGelement
+
+ SVGelement.addElement(SVGelement)
+ """
+ self.elements.append(SVGelement)
+
+ def toXml(self,level,f):
+ f.write('\t'*level)
+ f.write('<'+self.type)
+ for attkey in self.attributes.keys():
+ f.write(' '+_escape(str(attkey))+'='+_quoteattr(str(self.attributes[attkey])))
+ if self.namespace:
+ f.write(' xmlns="'+ _escape(str(self.namespace))+'" xmlns:xlink="http://www.w3.org/1999/xlink"')
+ if self.elements or self.text or self.cdata:
+ f.write('>')
+ if self.elements:
+ f.write('\n')
+ for element in self.elements:
+ element.toXml(level+1,f)
+ if self.cdata:
+ f.write('\n'+'\t'*(level+1)+'<![CDATA[')
+ for line in self.cdata.splitlines():
+ f.write('\n'+'\t'*(level+2)+line)
+ f.write('\n'+'\t'*(level+1)+']]>\n')
+ if self.text:
+ if type(self.text)==type(''): #If the text is only text
+ f.write(_escape(str(self.text)))
+ else: #If the text is a spannedtext class
+ f.write(str(self.text))
+ if self.elements:
+ f.write('\t'*level+'</'+self.type+'>\n')
+ elif self.text:
+ f.write('</'+self.type+'>\n')
+ elif self.cdata:
+ f.write('\t'*level+'</'+self.type+'>\n')
+ else:
+ f.write('/>\n')
+
+class tspan(SVGelement):
+ """ts=tspan(text='',**args)
+
+ a tspan element can be used for applying formatting to a textsection
+ usage:
+ ts=tspan('this text is bold')
+ ts.attributes['font-weight']='bold'
+ st=spannedtext()
+ st.addtspan(ts)
+ t=text(3,5,st)
+ """
+ def __init__(self,text=None,**args):
+ SVGelement.__init__(self,'tspan',**args)
+ if self.text<>None:
+ self.text=text
+ def __repr__(self):
+ s="<tspan"
+ for key,value in self.attributes.items():
+ s+= ' %s="%s"' % (key,value)
+ s+='>'
+ s+=self.text
+ s+='</tspan>'
+ return s
+
+class tref(SVGelement):
+ """tr=tref(link='',**args)
+
+ a tref element can be used for referencing text by a link to its id.
+ usage:
+ tr=tref('#linktotext')
+ st=spannedtext()
+ st.addtref(tr)
+ t=text(3,5,st)
+ """
+ def __init__(self,link,**args):
+ SVGelement.__init__(self,'tref',{'xlink:href':link},**args)
+ def __repr__(self):
+ s="<tref"
+
+ for key,value in self.attributes.items():
+ s+= ' %s="%s"' % (key,value)
+ s+='/>'
+ return s
+
+class spannedtext:
+ """st=spannedtext(textlist=[])
+
+ a spannedtext can be used for text which consists of text, tspan's and tref's
+ You can use it to add to a text element or path element. Don't add it directly
+ to a svg or a group element.
+ usage:
+
+ ts=tspan('this text is bold')
+ ts.attributes['font-weight']='bold'
+ tr=tref('#linktotext')
+ tr.attributes['fill']='red'
+ st=spannedtext()
+ st.addtspan(ts)
+ st.addtref(tr)
+ st.addtext('This text is not bold')
+ t=text(3,5,st)
+ """
+ def __init__(self,textlist=None):
+ if textlist==None:
+ self.textlist=[]
+ else:
+ self.textlist=textlist
+ def addtext(self,text=''):
+ self.textlist.append(text)
+ def addtspan(self,tspan):
+ self.textlist.append(tspan)
+ def addtref(self,tref):
+ self.textlist.append(tref)
+ def __repr__(self):
+ s=""
+ for element in self.textlist:
+ s+=str(element)
+ return s
+
+class rect(SVGelement):
+ """r=rect(width,height,x,y,fill,stroke,stroke_width,**args)
+
+ a rectangle is defined by a width and height and a xy pair
+ """
+ def __init__(self,x=None,y=None,width=None,height=None,fill=None,stroke=None,stroke_width=None,**args):
+ if width==None or height==None:
+ if width<>None:
+ raise ValueError, 'height is required'
+ if height<>None:
+ raise ValueError, 'width is required'
+ else:
+ raise ValueError, 'both height and width are required'
+ SVGelement.__init__(self,'rect',{'width':width,'height':height},**args)
+ if x<>None:
+ self.attributes['x']=x
+ if y<>None:
+ self.attributes['y']=y
+ if fill<>None:
+ self.attributes['fill']=fill
+ if stroke<>None:
+ self.attributes['stroke']=stroke
+ if stroke_width<>None:
+ self.attributes['stroke-width']=stroke_width
+
+class ellipse(SVGelement):
+ """e=ellipse(rx,ry,x,y,fill,stroke,stroke_width,**args)
+
+ an ellipse is defined as a center and a x and y radius.
+ """
+ def __init__(self,cx=None,cy=None,rx=None,ry=None,fill=None,stroke=None,stroke_width=None,**args):
+ if rx==None or ry== None:
+ if rx<>None:
+ raise ValueError, 'rx is required'
+ if ry<>None:
+ raise ValueError, 'ry is required'
+ else:
+ raise ValueError, 'both rx and ry are required'
+ SVGelement.__init__(self,'ellipse',{'rx':rx,'ry':ry},**args)
+ if cx<>None:
+ self.attributes['cx']=cx
+ if cy<>None:
+ self.attributes['cy']=cy
+ if fill<>None:
+ self.attributes['fill']=fill
+ if stroke<>None:
+ self.attributes['stroke']=stroke
+ if stroke_width<>None:
+ self.attributes['stroke-width']=stroke_width
+
+
+class circle(SVGelement):
+ """c=circle(x,y,radius,fill,stroke,stroke_width,**args)
+
+ The circle creates an element using a x, y and radius values eg
+ """
+ def __init__(self,cx=None,cy=None,r=None,fill=None,stroke=None,stroke_width=None,**args):
+ if r==None:
+ raise ValueError, 'r is required'
+ SVGelement.__init__(self,'circle',{'r':r},**args)
+ if cx<>None:
+ self.attributes['cx']=cx
+ if cy<>None:
+ self.attributes['cy']=cy
+ if fill<>None:
+ self.attributes['fill']=fill
+ if stroke<>None:
+ self.attributes['stroke']=stroke
+ if stroke_width<>None:
+ self.attributes['stroke-width']=stroke_width
+
+class point(circle):
+ """p=point(x,y,color)
+
+ A point is defined as a circle with a size 1 radius. It may be more efficient to use a
+ very small rectangle if you use many points because a circle is difficult to render.
+ """
+ def __init__(self,x,y,fill='black',**args):
+ circle.__init__(self,x,y,1,fill,**args)
+
+class line(SVGelement):
+ """l=line(x1,y1,x2,y2,stroke,stroke_width,**args)
+
+ A line is defined by a begin x,y pair and an end x,y pair
+ """
+ def __init__(self,x1=None,y1=None,x2=None,y2=None,stroke=None,stroke_width=None,**args):
+ SVGelement.__init__(self,'line',**args)
+ if x1<>None:
+ self.attributes['x1']=x1
+ if y1<>None:
+ self.attributes['y1']=y1
+ if x2<>None:
+ self.attributes['x2']=x2
+ if y2<>None:
+ self.attributes['y2']=y2
+ if stroke_width<>None:
+ self.attributes['stroke-width']=stroke_width
+ if stroke<>None:
+ self.attributes['stroke']=stroke
+
+class polyline(SVGelement):
+ """pl=polyline([[x1,y1],[x2,y2],...],fill,stroke,stroke_width,**args)
+
+ a polyline is defined by a list of xy pairs
+ """
+ def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args):
+ SVGelement.__init__(self,'polyline',{'points':_xypointlist(points)},**args)
+ if fill<>None:
+ self.attributes['fill']=fill
+ if stroke_width<>None:
+ self.attributes['stroke-width']=stroke_width
+ if stroke<>None:
+ self.attributes['stroke']=stroke
+
+class polygon(SVGelement):
+ """pl=polyline([[x1,y1],[x2,y2],...],fill,stroke,stroke_width,**args)
+
+ a polygon is defined by a list of xy pairs
+ """
+ def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args):
+ SVGelement.__init__(self,'polygon',{'points':_xypointlist(points)},**args)
+ if fill<>None:
+ self.attributes['fill']=fill
+ if stroke_width<>None:
+ self.attributes['stroke-width']=stroke_width
+ if stroke<>None:
+ self.attributes['stroke']=stroke
+
+class path(SVGelement):
+ """p=path(path,fill,stroke,stroke_width,**args)
+
+ a path is defined by a path object and optional width, stroke and fillcolor
+ """
+ def __init__(self,pathdata,fill=None,stroke=None,stroke_width=None,id=None,**args):
+ SVGelement.__init__(self,'path',{'d':str(pathdata)},**args)
+ if stroke<>None:
+ self.attributes['stroke']=stroke
+ if fill<>None:
+ self.attributes['fill']=fill
+ if stroke_width<>None:
+ self.attributes['stroke-width']=stroke_width
+ if id<>None:
+ self.attributes['id']=id
+
+
+class text(SVGelement):
+ """t=text(x,y,text,font_size,font_family,**args)
+
+ a text element can bge used for displaying text on the screen
+ """
+ def __init__(self,x=None,y=None,text=None,font_size=None,font_family=None,text_anchor=None,**args):
+ SVGelement.__init__(self,'text',**args)
+ if x<>None:
+ self.attributes['x']=x
+ if y<>None:
+ self.attributes['y']=y
+ if font_size<>None:
+ self.attributes['font-size']=font_size
+ if font_family<>None:
+ self.attributes['font-family']=font_family
+ if text<>None:
+ self.text=text
+ if text_anchor<>None:
+ self.attributes['text-anchor']=text_anchor
+
+
+class textpath(SVGelement):
+ """tp=textpath(text,link,**args)
+
+ a textpath places a text on a path which is referenced by a link.
+ """
+ def __init__(self,link,text=None,**args):
+ SVGelement.__init__(self,'textPath',{'xlink:href':link},**args)
+ if text<>None:
+ self.text=text
+
+class pattern(SVGelement):
+ """p=pattern(x,y,width,height,patternUnits,**args)
+
+ A pattern is used to fill or stroke an object using a pre-defined
+ graphic object which can be replicated ("tiled") at fixed intervals
+ in x and y to cover the areas to be painted.
+ """
+ def __init__(self,x=None,y=None,width=None,height=None,patternUnits=None,**args):
+ SVGelement.__init__(self,'pattern',**args)
+ if x<>None:
+ self.attributes['x']=x
+ if y<>None:
+ self.attributes['y']=y
+ if width<>None:
+ self.attributes['width']=width
+ if height<>None:
+ self.attributes['height']=height
+ if patternUnits<>None:
+ self.attributes['patternUnits']=patternUnits
+
+class title(SVGelement):
+ """t=title(text,**args)
+
+ a title is a text element. The text is displayed in the title bar
+ add at least one to the root svg element
+ """
+ def __init__(self,text=None,**args):
+ SVGelement.__init__(self,'title',**args)
+ if text<>None:
+ self.text=text
+
+class description(SVGelement):
+ """d=description(text,**args)
+
+ a description can be added to any element and is used for a tooltip
+ Add this element before adding other elements.
+ """
+ def __init__(self,text=None,**args):
+ SVGelement.__init__(self,'desc',**args)
+ if text<>None:
+ self.text=text
+
+class lineargradient(SVGelement):
+ """lg=lineargradient(x1,y1,x2,y2,id,**args)
+
+ defines a lineargradient using two xy pairs.
+ stop elements van be added to define the gradient colors.
+ """
+ def __init__(self,x1=None,y1=None,x2=None,y2=None,id=None,**args):
+ SVGelement.__init__(self,'linearGradient',**args)
+ if x1<>None:
+ self.attributes['x1']=x1
+ if y1<>None:
+ self.attributes['y1']=y1
+ if x2<>None:
+ self.attributes['x2']=x2
+ if y2<>None:
+ self.attributes['y2']=y2
+ if id<>None:
+ self.attributes['id']=id
+
+class radialgradient(SVGelement):
+ """rg=radialgradient(cx,cy,r,fx,fy,id,**args)
+
+ defines a radial gradient using a outer circle which are defined by a cx,cy and r and by using a focalpoint.
+ stop elements van be added to define the gradient colors.
+ """
+ def __init__(self,cx=None,cy=None,r=None,fx=None,fy=None,id=None,**args):
+ SVGelement.__init__(self,'radialGradient',**args)
+ if cx<>None:
+ self.attributes['cx']=cx
+ if cy<>None:
+ self.attributes['cy']=cy
+ if r<>None:
+ self.attributes['r']=r
+ if fx<>None:
+ self.attributes['fx']=fx
+ if fy<>None:
+ self.attributes['fy']=fy
+ if id<>None:
+ self.attributes['id']=id
+
+class stop(SVGelement):
+ """st=stop(offset,stop_color,**args)
+
+ Puts a stop color at the specified radius
+ """
+ def __init__(self,offset,stop_color=None,**args):
+ SVGelement.__init__(self,'stop',{'offset':offset},**args)
+ if stop_color<>None:
+ self.attributes['stop-color']=stop_color
+
+class style(SVGelement):
+ """st=style(type,cdata=None,**args)
+
+ Add a CDATA element to this element for defing in line stylesheets etc..
+ """
+ def __init__(self,type,cdata=None,**args):
+ SVGelement.__init__(self,'style',{'type':type},cdata=cdata, **args)
+
+
+class image(SVGelement):
+ """im=image(url,width,height,x,y,**args)
+
+ adds an image to the drawing. Supported formats are .png, .jpg and .svg.
+ """
+ def __init__(self,url,x=None,y=None,width=None,height=None,**args):
+ if width==None or height==None:
+ if width<>None:
+ raise ValueError, 'height is required'
+ if height<>None:
+ raise ValueError, 'width is required'
+ else:
+ raise ValueError, 'both height and width are required'
+ SVGelement.__init__(self,'image',{'xlink:href':url,'width':width,'height':height},**args)
+ if x<>None:
+ self.attributes['x']=x
+ if y<>None:
+ self.attributes['y']=y
+
+class cursor(SVGelement):
+ """c=cursor(url,**args)
+
+ defines a custom cursor for a element or a drawing
+ """
+ def __init__(self,url,**args):
+ SVGelement.__init__(self,'cursor',{'xlink:href':url},**args)
+
+
+class marker(SVGelement):
+ """m=marker(id,viewbox,refX,refY,markerWidth,markerHeight,**args)
+
+ defines a marker which can be used as an endpoint for a line or other pathtypes
+ add an element to it which should be used as a marker.
+ """
+ def __init__(self,id=None,viewBox=None,refx=None,refy=None,markerWidth=None,markerHeight=None,**args):
+ SVGelement.__init__(self,'marker',**args)
+ if id<>None:
+ self.attributes['id']=id
+ if viewBox<>None:
+ self.attributes['viewBox']=_viewboxlist(viewBox)
+ if refx<>None:
+ self.attributes['refX']=refx
+ if refy<>None:
+ self.attributes['refY']=refy
+ if markerWidth<>None:
+ self.attributes['markerWidth']=markerWidth
+ if markerHeight<>None:
+ self.attributes['markerHeight']=markerHeight
+
+class group(SVGelement):
+ """g=group(id,**args)
+
+ a group is defined by an id and is used to contain elements
+ g.addElement(SVGelement)
+ """
+ def __init__(self,id=None,**args):
+ SVGelement.__init__(self,'g',**args)
+ if id<>None:
+ self.attributes['id']=id
+
+class symbol(SVGelement):
+ """sy=symbol(id,viewbox,**args)
+
+ defines a symbol which can be used on different places in your graph using
+ the use element. A symbol is not rendered but you can use 'use' elements to
+ display it by referencing its id.
+ sy.addElement(SVGelement)
+ """
+
+ def __init__(self,id=None,viewBox=None,**args):
+ SVGelement.__init__(self,'symbol',**args)
+ if id<>None:
+ self.attributes['id']=id
+ if viewBox<>None:
+ self.attributes['viewBox']=_viewboxlist(viewBox)
+
+class defs(SVGelement):
+ """d=defs(**args)
+
+ container for defining elements
+ """
+ def __init__(self,**args):
+ SVGelement.__init__(self,'defs',**args)
+
+class switch(SVGelement):
+ """sw=switch(**args)
+
+ Elements added to a switch element which are "switched" by the attributes
+ requiredFeatures, requiredExtensions and systemLanguage.
+ Refer to the SVG specification for details.
+ """
+ def __init__(self,**args):
+ SVGelement.__init__(self,'switch',**args)
+
+
+class use(SVGelement):
+ """u=use(link,x,y,width,height,**args)
+
+ references a symbol by linking to its id and its position, height and width
+ """
+ def __init__(self,link,x=None,y=None,width=None,height=None,**args):
+ SVGelement.__init__(self,'use',{'xlink:href':link},**args)
+ if x<>None:
+ self.attributes['x']=x
+ if y<>None:
+ self.attributes['y']=y
+
+ if width<>None:
+ self.attributes['width']=width
+ if height<>None:
+ self.attributes['height']=height
+
+
+class link(SVGelement):
+ """a=link(url,**args)
+
+ a link is defined by a hyperlink. add elements which have to be linked
+ a.addElement(SVGelement)
+ """
+ def __init__(self,link='',**args):
+ SVGelement.__init__(self,'a',{'xlink:href':link},**args)
+
+class view(SVGelement):
+ """v=view(id,**args)
+
+ a view can be used to create a view with different attributes"""
+ def __init__(self,id=None,**args):
+ SVGelement.__init__(self,'view',**args)
+ if id<>None:
+ self.attributes['id']=id
+
+class script(SVGelement):
+ """sc=script(type,type,cdata,**args)
+
+ adds a script element which contains CDATA to the SVG drawing
+
+ """
+ def __init__(self,type,cdata=None,**args):
+ SVGelement.__init__(self,'script',{'type':type},cdata=cdata,**args)
+
+class animate(SVGelement):
+ """an=animate(attribute,from,to,during,**args)
+
+ animates an attribute.
+ """
+ def __init__(self,attribute,fr=None,to=None,dur=None,**args):
+ SVGelement.__init__(self,'animate',{'attributeName':attribute},**args)
+ if fr<>None:
+ self.attributes['from']=fr
+ if to<>None:
+ self.attributes['to']=to
+ if dur<>None:
+ self.attributes['dur']=dur
+
+class animateMotion(SVGelement):
+ """an=animateMotion(pathdata,dur,**args)
+
+ animates a SVGelement over the given path in dur seconds
+ """
+ def __init__(self,pathdata,dur,**args):
+ SVGelement.__init__(self,'animateMotion',**args)
+ if pathdata<>None:
+ self.attributes['path']=str(pathdata)
+ if dur<>None:
+ self.attributes['dur']=dur
+
+class animateTransform(SVGelement):
+ """antr=animateTransform(type,from,to,dur,**args)
+
+ transform an element from and to a value.
+ """
+ def __init__(self,type=None,fr=None,to=None,dur=None,**args):
+ SVGelement.__init__(self,'animateTransform',{'attributeName':'transform'},**args)
+ #As far as I know the attributeName is always transform
+ if type<>None:
+ self.attributes['type']=type
+ if fr<>None:
+ self.attributes['from']=fr
+ if to<>None:
+ self.attributes['to']=to
+ if dur<>None:
+ self.attributes['dur']=dur
+class animateColor(SVGelement):
+ """ac=animateColor(attribute,type,from,to,dur,**args)
+
+ Animates the color of a element
+ """
+ def __init__(self,attribute,type=None,fr=None,to=None,dur=None,**args):
+ SVGelement.__init__(self,'animateColor',{'attributeName':attribute},**args)
+ if type<>None:
+ self.attributes['type']=type
+ if fr<>None:
+ self.attributes['from']=fr
+ if to<>None:
+ self.attributes['to']=to
+ if dur<>None:
+ self.attributes['dur']=dur
+class set(SVGelement):
+ """st=set(attribute,to,during,**args)
+
+ sets an attribute to a value for a
+ """
+ def __init__(self,attribute,to=None,dur=None,**args):
+ SVGelement.__init__(self,'set',{'attributeName':attribute},**args)
+ if to<>None:
+ self.attributes['to']=to
+ if dur<>None:
+ self.attributes['dur']=dur
+
+
+
+class svg(SVGelement):
+ """s=svg(viewbox,width,height,**args)
+
+ a svg or element is the root of a drawing add all elements to a svg element.
+ You can have different svg elements in one svg file
+ s.addElement(SVGelement)
+
+ eg
+ d=drawing()
+ s=svg((0,0,100,100),'100%','100%')
+ c=circle(50,50,20)
+ s.addElement(c)
+ d.setSVG(s)
+ d.toXml()
+ """
+ def __init__(self,viewBox=None, width=None, height=None,**args):
+ SVGelement.__init__(self,'svg',**args)
+ if viewBox<>None:
+ self.attributes['viewBox']=_viewboxlist(viewBox)
+ if width<>None:
+ self.attributes['width']=width
+ if height<>None:
+ self.attributes['height']=height
+ self.namespace="http://www.w3.org/2000/svg"
+
+class drawing:
+ """d=drawing()
+
+ this is the actual SVG document. It needs a svg element as a root.
+ Use the addSVG method to set the svg to the root. Use the toXml method to write the SVG
+ source to the screen or to a file
+ d=drawing()
+ d.addSVG(svg)
+ d.toXml(optionalfilename)
+ """
+
+ def __init__(self, entity={}):
+ self.svg=None
+ self.entity = entity
+ def setSVG(self,svg):
+ self.svg=svg
+ #Voeg een element toe aan de grafiek toe.
+ if use_dom_implementation==0:
+ def toXml(self, filename='',compress=False):
+ import cStringIO
+ xml=cStringIO.StringIO()
+ xml.write("<?xml version='1.0' encoding='UTF-8'?>\n")
+ xml.write("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"")
+ if self.entity:
+ xml.write(" [\n")
+ for item in self.entity.keys():
+ xml.write("<!ENTITY %s \"%s\">\n" % (item, self.entity[item]))
+ xml.write("]")
+ xml.write(">\n")
+ self.svg.toXml(0,xml)
+ if not filename:
+ if compress:
+ import gzip
+ f=cStringIO.StringIO()
+ zf=gzip.GzipFile(fileobj=f,mode='wb')
+ zf.write(xml.getvalue())
+ zf.close()
+ f.seek(0)
+ return f.read()
+ else:
+ return xml.getvalue()
+ else:
+ if filename[-4:]=='svgz':
+ import gzip
+ f=gzip.GzipFile(filename=filename,mode="wb", compresslevel=9)
+ f.write(xml.getvalue())
+ f.close()
+ else:
+ f=file(filename,'w')
+ f.write(xml.getvalue())
+ f.close()
+
+ else:
+ def toXml(self,filename='',compress=False):
+ """drawing.toXml() ---->to the screen
+ drawing.toXml(filename)---->to the file
+ writes a svg drawing to the screen or to a file
+ compresses if filename ends with svgz or if compress is true
+ """
+ doctype = implementation.createDocumentType('svg',"-//W3C//DTD SVG 1.0//EN""",'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd ')
+
+ global root
+ #root is defined global so it can be used by the appender. Its also possible to use it as an arugument but
+ #that is a bit messy.
+ root=implementation.createDocument(None,None,doctype)
+ #Create the xml document.
+ global appender
+ def appender(element,elementroot):
+ """This recursive function appends elements to an element and sets the attributes
+ and type. It stops when alle elements have been appended"""
+ if element.namespace:
+ e=root.createElementNS(element.namespace,element.type)
+ else:
+ e=root.createElement(element.type)
+ if element.text:
+ textnode=root.createTextNode(element.text)
+ e.appendChild(textnode)
+ for attribute in element.attributes.keys(): #in element.attributes is supported from python 2.2
+ e.setAttribute(attribute,str(element.attributes[attribute]))
+ if element.elements:
+ for el in element.elements:
+ e=appender(el,e)
+ elementroot.appendChild(e)
+ return elementroot
+ root=appender(self.svg,root)
+ if not filename:
+ import cStringIO
+ xml=cStringIO.StringIO()
+ PrettyPrint(root,xml)
+ if compress:
+ import gzip
+ f=cStringIO.StringIO()
+ zf=gzip.GzipFile(fileobj=f,mode='wb')
+ zf.write(xml.getvalue())
+ zf.close()
+ f.seek(0)
+ return f.read()
+ else:
+ return xml.getvalue()
+ else:
+ try:
+ if filename[-4:]=='svgz':
+ import gzip
+ import cStringIO
+ xml=cStringIO.StringIO()
+ PrettyPrint(root,xml)
+ f=gzip.GzipFile(filename=filename,mode='wb',compresslevel=9)
+ f.write(xml.getvalue())
+ f.close()
+ else:
+ f=open(filename,'w')
+ PrettyPrint(root,f)
+ f.close()
+ except:
+ print "Cannot write SVG file: " + filename
+ def validate(self):
+ try:
+ import xml.parsers.xmlproc.xmlval
+ except:
+ raise exceptions.ImportError,'PyXml is required for validating SVG'
+ svg=self.toXml()
+ xv=xml.parsers.xmlproc.xmlval.XMLValidator()
+ try:
+ xv.feed(svg)
+ except:
+ raise "SVG is not well formed, see messages above"
+ else:
+ print "SVG well formed"
+if __name__=='__main__':
+
+
+ d=drawing()
+ s=svg((0,0,100,100))
+ r=rect(-100,-100,300,300,'cyan')
+ s.addElement(r)
+
+ t=title('SVGdraw Demo')
+ s.addElement(t)
+ g=group('animations')
+ e=ellipse(0,0,5,2)
+ g.addElement(e)
+ c=circle(0,0,1,'red')
+ g.addElement(c)
+ pd=pathdata(0,-10)
+ for i in range(6):
+ pd.relsmbezier(10,5,0,10)
+ pd.relsmbezier(-10,5,0,10)
+ an=animateMotion(pd,10)
+ an.attributes['rotate']='auto-reverse'
+ an.attributes['repeatCount']="indefinite"
+ g.addElement(an)
+ s.addElement(g)
+ for i in range(20,120,20):
+ u=use('#animations',i,0)
+ s.addElement(u)
+ for i in range(0,120,20):
+ for j in range(5,105,10):
+ c=circle(i,j,1,'red','black',.5)
+ s.addElement(c)
+ d.setSVG(s)
+
+ print d.toXml()
+
diff --git a/web/webqtl/utility/webqtlUtil.py b/web/webqtl/utility/webqtlUtil.py
new file mode 100755
index 00000000..6af7f846
--- /dev/null
+++ b/web/webqtl/utility/webqtlUtil.py
@@ -0,0 +1,977 @@
+# 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
+
+import string
+import time
+import re
+import math
+from math import *
+
+from htmlgen import HTMLgen2 as HT
+
+from base import webqtlConfig
+
+
+
+
+# NL, 07/27/2010. moved from webqtlForm.py
+#Dict of Parents and F1 information, In the order of [F1, Mat, Pat]
+ParInfo ={
+'BXH':['BHF1', 'HBF1', 'C57BL/6J', 'C3H/HeJ'],
+'AKXD':['AKF1', 'KAF1', 'AKR/J', 'DBA/2J'],
+'BXD':['B6D2F1', 'D2B6F1', 'C57BL/6J', 'DBA/2J'],
+'BXD300':['B6D2F1', 'D2B6F1', 'C57BL/6J', 'DBA/2J'],
+'B6BTBRF2':['B6BTBRF1', 'BTBRB6F1', 'C57BL/6J', 'BTBRT<+>tf/J'],
+'BHHBF2':['B6HF2','HB6F2','C57BL/6J','C3H/HeJ'],
+'BHF2':['B6HF2','HB6F2','C57BL/6J','C3H/HeJ'],
+'B6D2F2':['B6D2F1', 'D2B6F1', 'C57BL/6J', 'DBA/2J'],
+'BDF2-1999':['B6D2F2', 'D2B6F2', 'C57BL/6J', 'DBA/2J'],
+'BDF2-2005':['B6D2F1', 'D2B6F1', 'C57BL/6J', 'DBA/2J'],
+'CTB6F2':['CTB6F2','B6CTF2','C57BL/6J','Castaneous'],
+'CXB':['CBF1', 'BCF1', 'C57BL/6ByJ', 'BALB/cByJ'],
+'AXBXA':['ABF1', 'BAF1', 'C57BL/6J', 'A/J'],
+'AXB':['ABF1', 'BAF1', 'C57BL/6J', 'A/J'],
+'BXA':['BAF1', 'ABF1', 'C57BL/6J', 'A/J'],
+'LXS':['LSF1', 'SLF1', 'ISS', 'ILS'],
+'HXBBXH':['HSRBNF1', 'BNHSRF1', 'BN', 'HSR'],
+'BayXSha':['BayXShaF1', 'ShaXBayF1', 'Bay-0','Shahdara'],
+'ColXBur':['ColXBurF1', 'BurXColF1', 'Col-0','Bur-0'],
+'ColXCvi':['ColXCviF1', 'CviXColF1', 'Col-0','Cvi'],
+'SXM':['SMF1', 'MSF1', 'Steptoe','Morex']
+}
+
+
+# NL, 07/27/2010. moved from template.py
+IMGSTEP1 = HT.Image('/images/step1.gif', alt='STEP 1',border=0) #XZ, Only be used in inputPage.py
+IMGSTEP2 = HT.Image('/images/step2.gif', alt='STEP 2',border=0) #XZ, Only be used in inputPage.py
+IMGSTEP3 = HT.Image('/images/step3.gif', alt='STEP 3',border=0) #XZ, Only be used in inputPage.py
+IMGNEXT = HT.Image('/images/arrowdown.gif', alt='NEXT',border=0) #XZ, Only be used in inputPage.py
+
+IMGASC = HT.Image("/images/sortup.gif", border=0)
+IMGASCON = HT.Image("/images/sortupon.gif", border=0)
+IMGDESC = HT.Image("/images/sortdown.gif", border=0)
+IMGDESCON = HT.Image("/images/sortdownon.gif", border=0)
+
+"""
+IMGASC = HT.Image("/images/sortup_icon.gif", border=0)
+IMGASCON = HT.Image("/images/sortupon.gif", border=0)
+IMGDESC = HT.Image("/images/sortdown_icon.gif", border=0)
+IMGDESCON = HT.Image("/images/sortdownon.gif", border=0)
+IMG_UNSORTED = HT.Image("/images/unsorted_icon.gif", border=0)
+"""
+
+PROGRESSBAR = HT.Image('/images/waitAnima2.gif', alt='checkblue',align="middle",border=0)
+
+#########################################
+# Accessory Functions
+#########################################
+
+def decodeEscape(str):
+ a = str
+ pattern = re.compile('(%[0-9A-Fa-f][0-9A-Fa-f])')
+ match = pattern.findall(a)
+ matched = []
+ for item in match:
+ if item not in matched:
+ a = a.replace(item, '%c' % eval("0x"+item[-2:]))
+ matched.append(item)
+ return a
+
+def exportData(hddn, tdata, NP = None):
+ for key in tdata.keys():
+ _val, _var, _N = tdata[key].val, tdata[key].var, tdata[key].N
+ if _val != None:
+ hddn[key] = _val
+ if _var != None:
+ hddn['V'+key] = _var
+ if NP and _N != None:
+ hddn['N'+key] = _N
+
+def genShortStrainName(RISet='', input_strainName=''):
+ #aliasStrainDict = {'C57BL/6J':'B6','DBA/2J':'D2'}
+ strainName = input_strainName
+ if RISet != 'AXBXA':
+ if RISet == 'BXD300':
+ this_RISet = 'BXD'
+ elif RISet == 'BDF2-2005':
+ this_RISet = 'CASE05_'
+ else:
+ this_RISet = RISet
+ strainName = string.replace(strainName,this_RISet,'')
+ strainName = string.replace(strainName,'CASE','')
+ try:
+ strainName = "%02d" % int(strainName)
+ except:
+ pass
+ else:
+ strainName = string.replace(strainName,'AXB','A')
+ strainName = string.replace(strainName,'BXA','B')
+ try:
+ strainName = strainName[0] + "%02d" % int(strainName[1:])
+ except:
+ pass
+ return strainName
+
+def toInt(in_str):
+ "Converts an arbitrary string to an unsigned integer"
+ start = -1
+ end = -1
+ for i, char in enumerate(in_str):
+ if char >= '0' and char <= '9':
+ if start < 0:
+ start = i
+ end = i+1
+ else:
+ if start >= 0:
+ break
+ if start < end:
+ return int(in_str[start:end])
+ else:
+ return -1
+
+def transpose(m):
+ 'transpose a matrix'
+ n = len(m)
+ return [[m[j][i] for i in range(len(m[0])) for j in range(n)][k*n:k*n+n] for k in range(len(m[0]))]
+
+def asymTranspose(m):
+ 'transpose a matrix'
+ t = max(map(len, m))
+ n = len(m)
+ m2 = [["-"]]*n
+ for i in range(n):
+ m2[i] = m[i] + [""]*(t- len(m[i]))
+ return [[m2[j][i] for i in range(len(m2[0])) for j in range(n)][k*n:k*n+n] for k in range(len(m2[0]))]
+
+def genRandStr(prefix = "", length=8, chars=string.letters+string.digits):
+ from random import choice
+ _str = prefix[:]
+ for i in range(length):
+ _str += choice(chars)
+ return _str
+
+def generate_session():
+ import sha
+ return sha.new(str(time.time())).hexdigest()
+
+def cvt2Dict(x):
+ tmp = {}
+ for key in x.keys():
+ tmp[key] = x[key]
+ return tmp
+
+def dump_session(session_obj, filename):
+ "It seems mod python can only cPickle most basic data type"
+ import cPickle
+ session_file = open(filename, 'wb')
+ #try:
+ # pass
+ #except:
+ # pass
+ cPickle.dump(session_obj, session_file)
+ session_file.close()
+
+def StringAsFloat(str):
+ 'Converts string to float but catches any exception and returns None'
+ try:
+ return float(str)
+ except:
+ return None
+
+def IntAsFloat(str):
+ 'Converts string to Int but catches any exception and returns None'
+ try:
+ return int(str)
+ except:
+ return None
+
+def FloatAsFloat(flt):
+ 'Converts float to string but catches any exception and returns None'
+ try:
+ return float("%2.3f" % flt)
+ except:
+ return None
+
+def RemoveZero(flt):
+ 'Converts string to float but catches any exception and returns None'
+ try:
+ if abs(flt) < 1e-6:
+ return None
+ else:
+ return flt
+ except:
+ return None
+
+
+def SciFloat(d):
+ 'Converts string to float but catches any exception and returns None'
+
+ try:
+ if abs(d) <= 1.0e-4:
+ return "%1.2e" % d
+ else:
+ return "%1.5f" % d
+ except:
+ return None
+
+###To be removed
+def FloatList2String(lst):
+ 'Converts float list to string but catches any exception and returns None'
+ tt=''
+ try:
+ for item in lst:
+ if item == None:
+ tt += 'X '
+ else:
+ tt += '%f ' % item
+ return tt
+ except:
+ return ""
+
+def ListNotNull(lst):
+ 'Determine if the elements in a list are all null'
+ for item in lst:
+ if item is not None:
+ return 1
+ return None
+
+###To be removed
+def FileDataProcess(str):
+ 'Remove the description text from the input file if theres any'
+ i=0
+ while i<len(str):
+ if str[i]<'\x7f' and str[i]>'\x20':
+ break
+ else:
+ i+=1
+ str=str[i:]
+ str=string.join(string.split(str,'\000'),'')
+ i=string.find(str,"*****")
+ if i>-1:
+ return str[i+5:]
+ else:
+ return str
+
+def rank(a,lst,offset=0):
+ """Calculate the integer rank of a number in an array, can be used to calculate p-value"""
+ n = len(lst)
+ if n == 2:
+ if a <lst[0]:
+ return offset
+ elif a > lst[1]:
+ return offset + 2
+ else:
+ return offset +1
+ elif n == 1:
+ if a <lst[0]:
+ return offset
+ else:
+ return offset +1
+ elif n== 0:
+ return offset
+ else:
+ mid = n/2
+ if a < lst[mid]:
+ return rank(a,lst[:mid-1],offset)
+ else:
+ return rank(a,lst[mid:],offset+mid)
+
+def cmpScanResult(A,B):
+ try:
+ if A.LRS > B.LRS:
+ return 1
+ elif A.LRS == B.LRS:
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+
+def cmpScanResult2(A,B):
+ try:
+ if A.LRS < B.LRS:
+ return 1
+ elif A.LRS == B.LRS:
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+def cmpOrder(A,B):
+ try:
+ if A[1] < B[1]:
+ return -1
+ elif A[1] == B[1]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+def cmpOrder2(A,B):
+ try:
+ if A[-1] < B[-1]:
+ return -1
+ elif A[-1] == B[-1]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+
+
+
+def calRank(xVals, yVals, N): ### Zach Sloan, February 4 2010
+ """
+ Returns a ranked set of X and Y values. These are used when generating
+ a Spearman scatterplot. Bear in mind that this sets values equal to each
+ other as the same rank.
+ """
+ XX = []
+ YY = []
+ X = [0]*len(xVals)
+ Y = [0]*len(yVals)
+ j = 0
+
+ for i in range(len(xVals)):
+
+ if xVals[i] != None and yVals[i] != None:
+ XX.append((j, xVals[i]))
+ YY.append((j, yVals[i]))
+ j = j + 1
+
+ NN = len(XX)
+
+ XX.sort(cmpOrder2)
+ YY.sort(cmpOrder2)
+
+ j = 1
+ rank = 0.0
+
+ while j < NN:
+
+ if XX[j][1] != XX[j-1][1]:
+ X[XX[j-1][0]] = j
+ j = j+1
+
+ else:
+ jt = j+1
+ ji = j
+ for jt in range(j+1, NN):
+ if (XX[jt][1] != XX[j-1][1]):
+ break
+ rank = 0.5*(j+jt)
+ for ji in range(j-1, jt):
+ X[XX[ji][0]] = rank
+ if (jt == NN-1):
+ if (XX[jt][1] == XX[j-1][1]):
+ X[XX[NN-1][0]] = rank
+ j = jt+1
+
+ if j == NN:
+ if X[XX[NN-1][0]] == 0:
+ X[XX[NN-1][0]] = NN
+
+ j = 1
+ rank = 0.0
+
+ while j < NN:
+
+ if YY[j][1] != YY[j-1][1]:
+ Y[YY[j-1][0]] = j
+ j = j+1
+ else:
+ jt = j+1
+ ji = j
+ for jt in range(j+1, NN):
+ if (YY[jt][1] != YY[j-1][1]):
+ break
+ rank = 0.5*(j+jt)
+ for ji in range(j-1, jt):
+ Y[YY[ji][0]] = rank
+ if (jt == NN-1):
+ if (YY[jt][1] == YY[j-1][1]):
+ Y[YY[NN-1][0]] = rank
+ j = jt+1
+
+ if j == NN:
+ if Y[YY[NN-1][0]] == 0:
+ Y[YY[NN-1][0]] = NN
+
+ return (X,Y)
+
+def calCorrelationRank(xVals,yVals,N):
+ """
+ Calculated Spearman Ranked Correlation. The algorithm works
+ by setting all tied ranks to the average of those ranks (for
+ example, if ranks 5-10 all have the same value, each will be set
+ to rank 7.5).
+ """
+
+ XX = []
+ YY = []
+ j = 0
+
+ for i in range(len(xVals)):
+ if xVals[i]!= None and yVals[i]!= None:
+ XX.append((j,xVals[i]))
+ YY.append((j,yVals[i]))
+ j = j+1
+
+ NN = len(XX)
+ if NN <6:
+ return (0.0,NN)
+ XX.sort(cmpOrder2)
+ YY.sort(cmpOrder2)
+ X = [0]*NN
+ Y = [0]*NN
+
+ j = 1
+ rank = 0.0
+ t = 0.0
+ sx = 0.0
+
+ while j < NN:
+
+ if XX[j][1] != XX[j-1][1]:
+ X[XX[j-1][0]] = j
+ j = j+1
+
+ else:
+ jt = j+1
+ ji = j
+ for jt in range(j+1, NN):
+ if (XX[jt][1] != XX[j-1][1]):
+ break
+ rank = 0.5*(j+jt)
+ for ji in range(j-1, jt):
+ X[XX[ji][0]] = rank
+ t = jt-j
+ sx = sx + (t*t*t-t)
+ if (jt == NN-1):
+ if (XX[jt][1] == XX[j-1][1]):
+ X[XX[NN-1][0]] = rank
+ j = jt+1
+
+ if j == NN:
+ if X[XX[NN-1][0]] == 0:
+ X[XX[NN-1][0]] = NN
+
+ j = 1
+ rank = 0.0
+ t = 0.0
+ sy = 0.0
+
+ while j < NN:
+
+ if YY[j][1] != YY[j-1][1]:
+ Y[YY[j-1][0]] = j
+ j = j+1
+ else:
+ jt = j+1
+ ji = j
+ for jt in range(j+1, NN):
+ if (YY[jt][1] != YY[j-1][1]):
+ break
+ rank = 0.5*(j+jt)
+ for ji in range(j-1, jt):
+ Y[YY[ji][0]] = rank
+ t = jt - j
+ sy = sy + (t*t*t-t)
+ if (jt == NN-1):
+ if (YY[jt][1] == YY[j-1][1]):
+ Y[YY[NN-1][0]] = rank
+ j = jt+1
+
+ if j == NN:
+ if Y[YY[NN-1][0]] == 0:
+ Y[YY[NN-1][0]] = NN
+
+ D = 0.0
+
+ for i in range(NN):
+ D += (X[i]-Y[i])*(X[i]-Y[i])
+
+ fac = (1.0 -sx/(NN*NN*NN-NN))*(1.0-sy/(NN*NN*NN-NN))
+
+ return ((1-(6.0/(NN*NN*NN-NN))*(D+(sx+sy)/12.0))/math.sqrt(fac),NN)
+
+
+def calCorrelationRankText(dbdata,userdata,N): ### dcrowell = David Crowell, July 2008
+ """Calculates correlation ranks with data formatted from the text file.
+ dbdata, userdata are lists of strings. N is an int. Returns a float.
+ Used by correlationPage"""
+ XX = []
+ YY = []
+ j = 0
+ for i in range(N):
+ if (dbdata[i]!= None and userdata[i]!=None) and (dbdata[i]!= 'None' and userdata[i]!='None'):
+ XX.append((j,float(dbdata[i])))
+ YY.append((j,float(userdata[i])))
+ j += 1
+ NN = len(XX)
+ if NN <6:
+ return (0.0,NN)
+ XX.sort(cmpOrder2)
+ YY.sort(cmpOrder2)
+ X = [0]*NN
+ Y = [0]*NN
+
+ j = 1
+ rank = 0.0
+ t = 0.0
+ sx = 0.0
+
+ while j < NN:
+
+ if XX[j][1] != XX[j-1][1]:
+ X[XX[j-1][0]] = j
+ j = j+1
+
+ else:
+ jt = j+1
+ ji = j
+ for jt in range(j+1, NN):
+ if (XX[jt][1] != XX[j-1][1]):
+ break
+ rank = 0.5*(j+jt)
+ for ji in range(j-1, jt):
+ X[XX[ji][0]] = rank
+ t = jt-j
+ sx = sx + (t*t*t-t)
+ if (jt == NN-1):
+ if (XX[jt][1] == XX[j-1][1]):
+ X[XX[NN-1][0]] = rank
+ j = jt+1
+
+ if j == NN:
+ if X[XX[NN-1][0]] == 0:
+ X[XX[NN-1][0]] = NN
+
+ j = 1
+ rank = 0.0
+ t = 0.0
+ sy = 0.0
+
+ while j < NN:
+
+ if YY[j][1] != YY[j-1][1]:
+ Y[YY[j-1][0]] = j
+ j = j+1
+ else:
+ jt = j+1
+ ji = j
+ for jt in range(j+1, NN):
+ if (YY[jt][1] != YY[j-1][1]):
+ break
+ rank = 0.5*(j+jt)
+ for ji in range(j-1, jt):
+ Y[YY[ji][0]] = rank
+ t = jt - j
+ sy = sy + (t*t*t-t)
+ if (jt == NN-1):
+ if (YY[jt][1] == YY[j-1][1]):
+ Y[YY[NN-1][0]] = rank
+ j = jt+1
+
+ if j == NN:
+ if Y[YY[NN-1][0]] == 0:
+ Y[YY[NN-1][0]] = NN
+
+ D = 0.0
+
+ for i in range(NN):
+ D += (X[i]-Y[i])*(X[i]-Y[i])
+
+ fac = (1.0 -sx/(NN*NN*NN-NN))*(1.0-sy/(NN*NN*NN-NN))
+
+ return ((1-(6.0/(NN*NN*NN-NN))*(D+(sx+sy)/12.0))/math.sqrt(fac),NN)
+
+
+
+def calCorrelation(dbdata,userdata,N):
+ X = []
+ Y = []
+ for i in range(N):
+ if dbdata[i]!= None and userdata[i]!= None:
+ X.append(dbdata[i])
+ Y.append(userdata[i])
+ NN = len(X)
+ if NN <6:
+ return (0.0,NN)
+ sx = reduce(lambda x,y:x+y,X,0.0)
+ sy = reduce(lambda x,y:x+y,Y,0.0)
+ meanx = sx/NN
+ meany = sy/NN
+ xyd = 0.0
+ sxd = 0.0
+ syd = 0.0
+ for i in range(NN):
+ xyd += (X[i] - meanx)*(Y[i]-meany)
+ sxd += (X[i] - meanx)*(X[i] - meanx)
+ syd += (Y[i] - meany)*(Y[i] - meany)
+ try:
+ corr = xyd/(sqrt(sxd)*sqrt(syd))
+ except:
+ corr = 0
+ return (corr,NN)
+
+def calCorrelationText(dbdata,userdata,N): ### dcrowell July 2008
+ """Calculates correlation coefficients with values formatted from text files. dbdata, userdata are lists of strings. N is an int. Returns a float
+ Used by correlationPage"""
+ X = []
+ Y = []
+ for i in range(N):
+ #if (dbdata[i]!= None and userdata[i]!= None) and (dbdata[i]!= 'None' and userdata[i]!= 'None'):
+ # X.append(float(dbdata[i]))
+ # Y.append(float(userdata[i]))
+ if dbdata[i] == None or dbdata[i] == 'None' or userdata[i] == None or userdata[i] == 'None':
+ continue
+ else:
+ X.append(float(dbdata[i]))
+ Y.append(float(userdata[i]))
+ NN = len(X)
+ if NN <6:
+ return (0.0,NN)
+ sx = sum(X)
+ sy = sum(Y)
+ meanx = sx/float(NN)
+ meany = sy/float(NN)
+ xyd = 0.0
+ sxd = 0.0
+ syd = 0.0
+ for i in range(NN):
+ x1 = X[i]-meanx
+ y1 = Y[i]-meany
+ xyd += x1*y1
+ sxd += x1**2
+ syd += y1**2
+ try:
+ corr = xyd/(sqrt(sxd)*sqrt(syd))
+ except:
+ corr = 0
+ return (corr,NN)
+
+
+def readLineCSV(line): ### dcrowell July 2008
+ """Parses a CSV string of text and returns a list containing each element as a string.
+ Used by correlationPage"""
+ returnList = line.split('","')
+ returnList[-1]=returnList[-1][:-2]
+ returnList[0]=returnList[0][1:]
+ return returnList
+
+
+def cmpCorr(A,B):
+ try:
+ if abs(A[1]) < abs(B[1]):
+ return 1
+ elif abs(A[1]) == abs(B[1]):
+ return 0
+ else:
+ return -1
+ except:
+ return 0
+
+def cmpLitCorr(A,B):
+ try:
+ if abs(A[3]) < abs(B[3]): return 1
+ elif abs(A[3]) == abs(B[3]):
+ if abs(A[1]) < abs(B[1]): return 1
+ elif abs(A[1]) == abs(B[1]): return 0
+ else: return -1
+ else: return -1
+ except:
+ return 0
+
+def cmpPValue(A,B):
+ try:
+ if A.corrPValue < B.corrPValue:
+ return -1
+ elif A.corrPValue == B.corrPValue:
+ if abs(A.corr) > abs(B.corr):
+ return -1
+ elif abs(A.corr) < abs(B.corr):
+ return 1
+ else:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+def cmpEigenValue(A,B):
+ try:
+ if A[0] > B[0]:
+ return -1
+ elif A[0] == B[0]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+
+def cmpLRSFull(A,B):
+ try:
+ if A[0] < B[0]:
+ return -1
+ elif A[0] == B[0]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+def cmpLRSInteract(A,B):
+ try:
+ if A[1] < B[1]:
+ return -1
+ elif A[1] == B[1]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
+
+def cmpPos(A,B):
+ try:
+ try:
+ AChr = int(A.chr)
+ except:
+ AChr = 20
+ try:
+ BChr = int(B.chr)
+ except:
+ BChr = 20
+ if AChr > BChr:
+ return 1
+ elif AChr == BChr:
+ if A.mb > B.mb:
+ return 1
+ if A.mb == B.mb:
+ return 0
+ else:
+ return -1
+ else:
+ return -1
+ except:
+ return 0
+
+def cmpGenoPos(A,B):
+ try:
+ A1 = A.chr
+ B1 = B.chr
+ try:
+ A1 = int(A1)
+ except:
+ A1 = 25
+ try:
+ B1 = int(B1)
+ except:
+ B1 = 25
+ if A1 > B1:
+ return 1
+ elif A1 == B1:
+ if A.mb > B.mb:
+ return 1
+ if A.mb == B.mb:
+ return 0
+ else:
+ return -1
+ else:
+ return -1
+ except:
+ return 0
+
+#XZhou: Must use "BINARY" to enable case sensitive comparison.
+def authUser(name,password,db, encrypt=None):
+ try:
+ if encrypt:
+ query = 'SELECT privilege, id,name,password, grpName FROM User WHERE name= BINARY \'%s\' and password= BINARY \'%s\'' % (name,password)
+ else:
+ query = 'SELECT privilege, id,name,password, grpName FROM User WHERE name= BINARY \'%s\' and password= BINARY SHA(\'%s\')' % (name,password)
+ db.execute(query)
+ records = db.fetchone()
+ if not records:
+ raise ValueError
+ return records#(privilege,id,name,password,grpName)
+ except:
+ return (None, None, None, None, None)
+
+
+def hasAccessToConfidentialPhenotypeTrait(privilege, userName, authorized_users):
+ access_to_confidential_phenotype_trait = 0
+ if webqtlConfig.USERDICT[privilege] > webqtlConfig.USERDICT['user']:
+ access_to_confidential_phenotype_trait = 1
+ else:
+ AuthorizedUsersList=map(string.strip, string.split(authorized_users, ','))
+ if AuthorizedUsersList.__contains__(userName):
+ access_to_confidential_phenotype_trait = 1
+ return access_to_confidential_phenotype_trait
+
+
+class VisualizeException(Exception):
+ def __init__(self, message):
+ self.message = message
+ def __str__(self):
+ return self.message
+
+# safeConvert : (string -> A) -> A -> A
+# to convert a string to type A, using the supplied default value
+# if the given conversion function doesn't work
+def safeConvert(f, value, default):
+ try:
+ return f(value)
+ except:
+ return default
+
+# safeFloat : string -> float -> float
+# to convert a string to a float safely
+def safeFloat(value, default):
+ return safeConvert(float, value, default)
+
+# safeInt: string -> int -> int
+# to convert a string to an int safely
+def safeInt(value, default):
+ return safeConvert(int, value, default)
+
+# safeString : string -> (arrayof string) -> string -> string
+# if a string is not in a list of strings to pick a default value
+# for that string
+def safeString(value, validChoices, default):
+ if value in validChoices:
+ return value
+ else:
+ return default
+
+# yesNoToInt: string -> int
+# map "yes" -> 1 and "no" -> 0
+def yesNoToInt(value):
+ if value == "yes":
+ return 1
+ elif value == "no":
+ return 0
+ else:
+ return None
+
+# IntToYesNo: int -> string
+# map 1 -> "yes" and 0 -> "no"
+def intToYesNo(value):
+ if value == 1:
+ return "yes"
+ elif value == 0:
+ return "no"
+ else:
+ return None
+
+def formatField(name):
+ name = name.replace("_", " ")
+ name = name.title()
+ #name = name.replace("Mb Mm6", "Mb");
+ return name.replace("Id", "ID")
+
+#XZ, 03/27/2009: This function is very specific.
+#It is used by AJAX_table.py, correlationPage.py and dataPage.py
+
+
+def genTableObj(tblobj=None, file="", sortby = ("", ""), tableID = "sortable", addIndex = "1", hiddenColumns=[]):
+ header = tblobj['header']
+ body = tblobj['body']
+ field, order = sortby
+
+ #ZAS 9/12/2011 - The hiddenColumns array needs to be converted into a string so they can be placed into the javascript of each up/down button
+ hiddenColumnsString = ",".join(hiddenColumns)
+
+ tbl = HT.TableLite(Class="collap b2", cellspacing=1, cellpadding=5)
+
+ hiddenColumnIdx = [] #indices of columns to hide
+ idx = -1
+ last_idx = 0 #ZS: This is the index of the last item in the regular table header (without any extra parameters). It is used to determine the index of each extra parameter.
+ for row in header:
+ hr = HT.TR()
+ for i, item in enumerate(row):
+ if (item.text == '') or (item.text not in hiddenColumns):
+ if item.sort and item.text:
+ down = HT.Href("javascript:xmlhttpPost('%smain.py?FormID=AJAX_table', '%s', 'sort=%s&order=down&file=%s&tableID=%s&addIndex=%s&hiddenColumns=%s')" % (webqtlConfig.CGIDIR, tableID, item.text, file, tableID, addIndex, hiddenColumnsString),IMGDESC)
+ up = HT.Href("javascript:xmlhttpPost('%smain.py?FormID=AJAX_table', '%s', 'sort=%s&order=up&file=%s&tableID=%s&addIndex=%s&hiddenColumns=%s')" % (webqtlConfig.CGIDIR, tableID, item.text, file, tableID, addIndex, hiddenColumnsString),IMGASC)
+ if item.text == field:
+ idx = item.idx
+ last_idx = idx
+ if order == 'up':
+ up = IMGASCON
+ elif order == 'down':
+ down = IMGDESCON
+ item.html.append(HT.Div(up, down, style="float: bottom;"))
+ hr.append(item.html)
+ else:
+ hiddenColumnIdx.append(i)
+ tbl.append(hr)
+
+ for i, row in enumerate(body):
+ for j, item in enumerate(row):
+ if order == 'down':
+ if (item.val == '' or item.val == 'x' or item.val == 'None'):
+ item.val = 0
+ if order == 'up':
+ if (item.val == '' or item.val == 'x' or item.val == 'None'):
+ item.val = 'zzzzz'
+
+ if idx >= 0:
+ if order == 'down':
+ body.sort(lambda A, B: cmp(B[idx].val, A[idx].val), key=natsort_key)
+ elif order == 'up':
+ body.sort(lambda A, B: cmp(A[idx].val, B[idx].val), key=natsort_key)
+ else:
+ pass
+
+ for i, row in enumerate(body):
+ hr = HT.TR(Id = row[0].text)
+ for j, item in enumerate(row):
+ if (j not in hiddenColumnIdx):
+ if j == 0:
+ if addIndex == "1":
+ item.html.contents = [i+1] + item.html.contents
+ hr.append(item.html)
+ tbl.append(hr)
+
+ return tbl
+
+def natsort_key(string):
+ r = []
+ for c in string:
+ try:
+ c = int(c)
+ try: r[-1] = r[-1] * 10 + c
+ except: r.append(c)
+ except:
+ r.append(c)
+ return r
+