From 527bb0459cf488e5021696e326dc10d28ecdd74c Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Thu, 24 May 2012 02:18:20 -0400
Subject: Trying to get stuff working under new structure
---
wqflask/base/GeneralObject.py | 71 ++
wqflask/base/JinjaPage.py | 28 +
wqflask/base/__init__.py | 0
wqflask/base/admin.py | 88 ++
wqflask/base/cgiData.py | 70 ++
wqflask/base/cookieData.py | 52 +
wqflask/base/footer.py | 6 +
wqflask/base/header.py | 6 +
wqflask/base/indexBody.py | 290 +++++
wqflask/base/myCookie.py | 55 +
wqflask/base/sessionData.py | 53 +
wqflask/base/template.py | 123 ++
wqflask/base/templatePage.py | 222 ++++
wqflask/base/webqtlCaseData.py | 54 +
wqflask/base/webqtlConfig.py | 73 ++
wqflask/base/webqtlConfigLocal.py | 19 +
wqflask/base/webqtlDataset.py | 160 +++
wqflask/base/webqtlFormData.py | 289 +++++
wqflask/base/webqtlTrait.py | 581 ++++++++++
wqflask/dbFunction/__init__.py | 0
wqflask/dbFunction/webqtlDatabaseFunction.py | 265 +++++
wqflask/htmlgen.py | 14 +
wqflask/requirements.txt | 6 +
wqflask/runserver.py | 15 +
wqflask/utility/AJAX_table.py | 153 +++
wqflask/utility/Plot.py | 1283 ++++++++++++++++++++
wqflask/utility/TDCell.py | 42 +
wqflask/utility/THCell.py | 44 +
wqflask/utility/__init__.py | 0
wqflask/utility/formatting.py | 109 ++
wqflask/utility/svg.py | 1069 +++++++++++++++++
wqflask/utility/webqtlUtil.py | 977 ++++++++++++++++
wqflask/wqflask/__init__.py | 13 +
wqflask/wqflask/search_results.py | 1288 +++++++++++++++++++++
wqflask/wqflask/static/css | 1 +
wqflask/wqflask/static/images | 1 +
wqflask/wqflask/static/javascript | 1 +
wqflask/wqflask/templates/base.html | 215 ++++
wqflask/wqflask/templates/index_page.html | 313 +++++
wqflask/wqflask/templates/search_result_page.html | 203 ++++
wqflask/wqflask/views.py | 23 +
41 files changed, 8275 insertions(+)
create mode 100755 wqflask/base/GeneralObject.py
create mode 100644 wqflask/base/JinjaPage.py
create mode 100755 wqflask/base/__init__.py
create mode 100755 wqflask/base/admin.py
create mode 100755 wqflask/base/cgiData.py
create mode 100755 wqflask/base/cookieData.py
create mode 100755 wqflask/base/footer.py
create mode 100755 wqflask/base/header.py
create mode 100755 wqflask/base/indexBody.py
create mode 100755 wqflask/base/myCookie.py
create mode 100755 wqflask/base/sessionData.py
create mode 100755 wqflask/base/template.py
create mode 100755 wqflask/base/templatePage.py
create mode 100755 wqflask/base/webqtlCaseData.py
create mode 100755 wqflask/base/webqtlConfig.py
create mode 100755 wqflask/base/webqtlConfigLocal.py
create mode 100755 wqflask/base/webqtlDataset.py
create mode 100755 wqflask/base/webqtlFormData.py
create mode 100755 wqflask/base/webqtlTrait.py
create mode 100755 wqflask/dbFunction/__init__.py
create mode 100755 wqflask/dbFunction/webqtlDatabaseFunction.py
create mode 100644 wqflask/htmlgen.py
create mode 100644 wqflask/requirements.txt
create mode 100644 wqflask/runserver.py
create mode 100755 wqflask/utility/AJAX_table.py
create mode 100755 wqflask/utility/Plot.py
create mode 100755 wqflask/utility/TDCell.py
create mode 100755 wqflask/utility/THCell.py
create mode 100755 wqflask/utility/__init__.py
create mode 100644 wqflask/utility/formatting.py
create mode 100755 wqflask/utility/svg.py
create mode 100755 wqflask/utility/webqtlUtil.py
create mode 100644 wqflask/wqflask/__init__.py
create mode 100644 wqflask/wqflask/search_results.py
create mode 120000 wqflask/wqflask/static/css
create mode 120000 wqflask/wqflask/static/images
create mode 120000 wqflask/wqflask/static/javascript
create mode 100644 wqflask/wqflask/templates/base.html
create mode 100644 wqflask/wqflask/templates/index_page.html
create mode 100644 wqflask/wqflask/templates/search_result_page.html
create mode 100644 wqflask/wqflask/views.py
diff --git a/wqflask/base/GeneralObject.py b/wqflask/base/GeneralObject.py
new file mode 100755
index 00000000..311c9e22
--- /dev/null
+++ b/wqflask/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/wqflask/base/JinjaPage.py b/wqflask/base/JinjaPage.py
new file mode 100644
index 00000000..07e485b1
--- /dev/null
+++ b/wqflask/base/JinjaPage.py
@@ -0,0 +1,28 @@
+import logging
+logging.basicConfig(filename="/tmp/gn_log", level=logging.INFO)
+_log = logging.getLogger("search")
+
+from pprint import pformat as pf
+
+import templatePage
+
+from utility import formatting
+
+import jinja2
+JinjaEnv = jinja2.Environment(loader=jinja2.FileSystemLoader('/gnshare/gn/web/webqtl/templates'))
+JinjaEnv.globals['numify'] = formatting.numify
+
+
+class JinjaPage(templatePage.templatePage):
+ """Class derived from our regular templatePage, but uses Jinja2 instead.
+
+ When converting pages from Python generated templates, change the base class from templatePage
+ to JinjaPage
+
+ """
+
+
+ def write(self):
+ """We override the base template write so we can use Jinja2."""
+ _log.info(pf(self.__dict__))
+ return self.jtemplate.render(**self.__dict__)
diff --git a/wqflask/base/__init__.py b/wqflask/base/__init__.py
new file mode 100755
index 00000000..e69de29b
diff --git a/wqflask/base/admin.py b/wqflask/base/admin.py
new file mode 100755
index 00000000..a04df2da
--- /dev/null
+++ b/wqflask/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/wqflask/base/cgiData.py b/wqflask/base/cgiData.py
new file mode 100755
index 00000000..57416060
--- /dev/null
+++ b/wqflask/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/wqflask/base/cookieData.py b/wqflask/base/cookieData.py
new file mode 100755
index 00000000..4b7c9046
--- /dev/null
+++ b/wqflask/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/wqflask/base/footer.py b/wqflask/base/footer.py
new file mode 100755
index 00000000..6f92fdf8
--- /dev/null
+++ b/wqflask/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')
diff --git a/wqflask/base/header.py b/wqflask/base/header.py
new file mode 100755
index 00000000..b6136b51
--- /dev/null
+++ b/wqflask/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')
\ No newline at end of file
diff --git a/wqflask/base/indexBody.py b/wqflask/base/indexBody.py
new file mode 100755
index 00000000..aa67dffa
--- /dev/null
+++ b/wqflask/base/indexBody.py
@@ -0,0 +1,290 @@
+index_body_string = """
+
+
+
+ You can also use advanced commands. Copy these simple examples
+ into the Get Any or Combined search fields:
+
+
+
POSITION=(chr1 25 30) finds genes, markers, or transcripts on chromosome 1 between 25 and 30 Mb.
+
+
MEAN=(15 16) LRS=(23 46) in the Combined field finds highly expressed genes (15 to 16 log2 units) AND with peak LRS linkage between 23 and 46.
+
+
+
RIF=mitochondrial searches RNA databases for GeneRIF links.
+
+
WIKI=nicotine searches GeneWiki for genes that you or other users have annotated with the word nicotine.
+
+
GO:0045202 searches for synapse-associated genes listed in the Gene Ontology.
+
+
+
GO:0045202 LRS=(9 99 Chr4 122 155) cisLRS=(9 999 10) in Combined finds synapse-associated genes with cis eQTL on Chr 4 from 122 and 155 Mb with LRS scores between 9 and 999.
+
+
RIF=diabetes LRS=(9 999 Chr2 100 105) transLRS=(9 999 10) in Combined finds diabetes-associated transcripts with peak trans eQTLs on Chr 2 between 100 and 105 Mb with LRS scores between 9 and 999.
+
+
+
GeneNetwork's Time Machine links to earlier versions that correspond to specific publication dates.
+
+
+
+
+
+
+"""
diff --git a/wqflask/base/myCookie.py b/wqflask/base/myCookie.py
new file mode 100755
index 00000000..db5320df
--- /dev/null
+++ b/wqflask/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/wqflask/base/sessionData.py b/wqflask/base/sessionData.py
new file mode 100755
index 00000000..01555f87
--- /dev/null
+++ b/wqflask/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/wqflask/base/template.py b/wqflask/base/template.py
new file mode 100755
index 00000000..85bd86df
--- /dev/null
+++ b/wqflask/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 = """
+
+
+
+
+%s
+
+
+
+
+
+
+
+%s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+%s
+
+
+
+
+%s
+
+
+
+
+ %s
+
+
+
+
+
+
+
+
+ %s
+
+
+
+
+
+
+
+
+
+
%s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
diff --git a/wqflask/base/templatePage.py b/wqflask/base/templatePage.py
new file mode 100755
index 00000000..4dece24a
--- /dev/null
+++ b/wqflask/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! Login'
+ else:
+ userInfo = 'Hi, %s! Logout' % 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/wqflask/base/webqtlCaseData.py b/wqflask/base/webqtlCaseData.py
new file mode 100755
index 00000000..4df32ca4
--- /dev/null
+++ b/wqflask/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/wqflask/base/webqtlConfig.py b/wqflask/base/webqtlConfig.py
new file mode 100755
index 00000000..755595e0
--- /dev/null
+++ b/wqflask/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 = '/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 = ''
+INFOPAGEHREF = '/dbdoc/%s.html'
+GLOSSARYFILE = "/glossary.html"
+CGIDIR = '/webqtl/' #XZ: The variable name 'CGIDIR' should be changed to 'PYTHONDIR'
+SCRIPTFILE = 'main.py'
+REFRESHSTR = ''
+REFRESHDIR = '%s' + SCRIPTFILE +'?sid=%s'
diff --git a/wqflask/base/webqtlConfigLocal.py b/wqflask/base/webqtlConfigLocal.py
new file mode 100755
index 00000000..35da73c2
--- /dev/null
+++ b/wqflask/base/webqtlConfigLocal.py
@@ -0,0 +1,19 @@
+#########################################'
+# Environment Variables - private
+#########################################
+
+MYSQL_SERVER = 'localhost'
+DB_NAME = 'db_webqtl'
+DB_USER = 'webqtlupd'
+DB_PASSWD = 'zhou&yan@ut'
+
+MYSQL_UPDSERVER = 'localhost'
+DB_UPDNAME = 'db_webqtl'
+DB_UPDUSER = 'webqtlupd'
+DB_UPDPASSWD = 'zhou&yan@ut'
+
+GNROOT = '/gnshare/gn/'
+PythonPath = '/usr/bin/python'
+PIDDLE_FONT_PATH = '/usr/lib/python2.4/site-packages/piddle/truetypefonts/'
+
+TEXTUI=1 # XZ: This is to protect GN production server. If set to 0, no text UI is allowed.
diff --git a/wqflask/base/webqtlDataset.py b/wqflask/base/webqtlDataset.py
new file mode 100755
index 00000000..da1b8601
--- /dev/null
+++ b/wqflask/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/wqflask/base/webqtlFormData.py b/wqflask/base/webqtlFormData.py
new file mode 100755
index 00000000..84e41cae
--- /dev/null
+++ b/wqflask/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/wqflask/base/webqtlTrait.py b/wqflask/base/webqtlTrait.py
new file mode 100755
index 00000000..f5051e45
--- /dev/null
+++ b/wqflask/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/wqflask/dbFunction/__init__.py b/wqflask/dbFunction/__init__.py
new file mode 100755
index 00000000..e69de29b
diff --git a/wqflask/dbFunction/webqtlDatabaseFunction.py b/wqflask/dbFunction/webqtlDatabaseFunction.py
new file mode 100755
index 00000000..772e0526
--- /dev/null
+++ b/wqflask/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/wqflask/htmlgen.py b/wqflask/htmlgen.py
new file mode 100644
index 00000000..8406d925
--- /dev/null
+++ b/wqflask/htmlgen.py
@@ -0,0 +1,14 @@
+from __future__ import absolute_import, division, print_function
+
+class HTMLgen(object):
+ """A redefined HT until we manage to completely eliminate it"""
+ def __getattr__(self, name):
+ return ""
+
+ def Item(self, *args, **kw):
+ print("This way of generating html is obsolete!")
+ return "foo"
+
+ Href = Span = TD = Blockquote = Image = Item
+
+HTMLgen2 = HTMLgen()
diff --git a/wqflask/requirements.txt b/wqflask/requirements.txt
new file mode 100644
index 00000000..caa5d61e
--- /dev/null
+++ b/wqflask/requirements.txt
@@ -0,0 +1,6 @@
+Flask==0.8
+Jinja2==2.6
+MySQL-python==1.2.3
+Werkzeug==0.8.3
+pyXLWriter==0.4a3
+wsgiref==0.1.2
diff --git a/wqflask/runserver.py b/wqflask/runserver.py
new file mode 100644
index 00000000..bf73ed37
--- /dev/null
+++ b/wqflask/runserver.py
@@ -0,0 +1,15 @@
+from wqflask import app
+
+# Please note, running with host set externally below combined with debug mode
+# is a big security no-no
+# Unless you have a firewall setup
+#
+# Something like /sbin/iptables -A INPUT -p tcp -i eth0 -s ! 71.236.239.43 --dport 5000 -j DROP
+# should do the trick
+#
+# You'll probably have to firewall the main port and the
+#
+# For more info see: http://www.cyberciti.biz/faq/iptables-block-port/
+
+
+app.run(host='0.0.0.0')
diff --git a/wqflask/utility/AJAX_table.py b/wqflask/utility/AJAX_table.py
new file mode 100755
index 00000000..963a530e
--- /dev/null
+++ b/wqflask/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 = "The table is no longer available on this server"
+
+ def __str__(self):
+ return self.value
+
+ def write(self):
+ return str(self)
diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py
new file mode 100755
index 00000000..2401c85c
--- /dev/null
+++ b/wqflask/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)=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/wqflask/utility/TDCell.py b/wqflask/utility/TDCell.py
new file mode 100755
index 00000000..76b9c5db
--- /dev/null
+++ b/wqflask/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/wqflask/utility/THCell.py b/wqflask/utility/THCell.py
new file mode 100755
index 00000000..a96b9e49
--- /dev/null
+++ b/wqflask/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/wqflask/utility/__init__.py b/wqflask/utility/__init__.py
new file mode 100755
index 00000000..e69de29b
diff --git a/wqflask/utility/formatting.py b/wqflask/utility/formatting.py
new file mode 100644
index 00000000..52173417
--- /dev/null
+++ b/wqflask/utility/formatting.py
@@ -0,0 +1,109 @@
+def numify(number, singular=None, plural=None):
+ """Turn a number into a word if less than 13 and optionally add a singular or plural word
+
+ >>> numify(3)
+ 'three'
+
+ >>> numify(1, 'item', 'items')
+ 'one item'
+
+ >>> numify(9, 'book', 'books')
+ 'nine books'
+
+ >>> numify(15)
+ '15'
+
+ >>> numify(0)
+ '0'
+
+ >>> numify(12334, 'hippopotamus', 'hippopotami')
+ '12,334 hippopotami'
+
+ """
+ num_repr = {1 : "one",
+ 2 : "two",
+ 3 : "three",
+ 4 : "four",
+ 5 : "five",
+ 6 : "six",
+ 7 : "seven",
+ 8 : "eight",
+ 9 : "nine",
+ 10 : "ten",
+ 11 : "eleven",
+ 12 : "twelve"}
+
+ #Below line commented out cause doesn't work in Python 2.4
+ #assert all((singular, plural)) or not any((singular, plural)), "Need to pass two words or none"
+ if number == 1:
+ word = singular
+ else:
+ word = plural
+
+ if number in num_repr:
+ number = num_repr[number]
+ elif number > 9999:
+ number = commify(number)
+
+ if word:
+ return "%s %s" % (number, word)
+ else:
+ return str(number)
+
+
+def commify(n):
+ """Add commas to an integer n.
+
+ See http://stackoverflow.com/questions/3909457/whats-the-easiest-way-to-add-commas-to-an-integer-in-python
+ But I (Sam) made some small changes based on http://www.grammarbook.com/numbers/numbers.asp
+
+ >>> commify(1)
+ '1'
+ >>> commify(123)
+ '123'
+ >>> commify(1234)
+ '1234'
+ >>> commify(12345)
+ '12,345'
+ >>> commify(1234567890)
+ '1,234,567,890'
+ >>> commify(123.0)
+ '123.0'
+ >>> commify(1234.5)
+ '1234.5'
+ >>> commify(1234.56789)
+ '1234.56789'
+ >>> commify(123456.789)
+ '123,456.789'
+ >>> commify('%.2f' % 1234.5)
+ '1234.50'
+ >>> commify(None)
+ >>>
+
+ """
+ if n is None:
+ return None
+
+ n = str(n)
+
+ if len(n) <= 4: # Might as well do this early
+ return n
+
+ if '.' in n:
+ dollars, cents = n.split('.')
+ else:
+ dollars, cents = n, None
+
+ # Don't commify numbers less than 10000
+ if len(dollars) <= 4:
+ return n
+
+ r = []
+ for i, c in enumerate(reversed(str(dollars))):
+ if i and (not (i % 3)):
+ r.insert(0, ',')
+ r.insert(0, c)
+ out = ''.join(r)
+ if cents:
+ out += '.' + cents
+ return out
diff --git a/wqflask/utility/svg.py b/wqflask/utility/svg.py
new file mode 100755
index 00000000..e49a6c3c
--- /dev/null
+++ b/wqflask/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 text 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 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("&", "&")
+ data = data.replace("<", "<")
+ data = data.replace(">", ">")
+ 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('"', """)
+ 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)+'\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="'
+ s+=self.text
+ s+=''
+ 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="'
+ 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("\n")
+ xml.write("\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/wqflask/utility/webqtlUtil.py b/wqflask/utility/webqtlUtil.py
new file mode 100755
index 00000000..6af7f846
--- /dev/null
+++ b/wqflask/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'\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[1]:
+ return offset + 2
+ else:
+ return offset +1
+ elif n == 1:
+ if a 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
+
diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py
new file mode 100644
index 00000000..d0484c83
--- /dev/null
+++ b/wqflask/wqflask/__init__.py
@@ -0,0 +1,13 @@
+from __future__ import absolute_import, division, print_function
+
+from flask import Flask
+
+from utility import formatting
+
+app = Flask(__name__)
+
+app.jinja_env.globals.update(
+ numify = formatting.numify
+)
+
+import wqflask.views
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
new file mode 100644
index 00000000..c100645e
--- /dev/null
+++ b/wqflask/wqflask/search_results.py
@@ -0,0 +1,1288 @@
+from __future__ import absolute_import, division, print_function
+
+from wqflask import app
+
+from flask import render_template
+
+###################################################
+#
+# This file uses only spaces for indentation #
+#
+###################################################
+
+import string
+import os
+import cPickle
+import re
+from math import *
+import time
+import pyXLWriter as xl
+#import pp - Note from Sam: is this used?
+import math
+import datetime
+
+from pprint import pformat as pf
+
+# Instead of importing HT we're going to build a class below until we can eliminate it
+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")
+_ch = logging.StreamHandler()
+_log.addHandler(_ch)
+
+from utility import formatting
+
+import sys
+_log.info("sys.path is: %s" % (sys.path))
+
+
+#from base.JinjaPage import JinjaEnv, JinjaPage
+
+
+
+class SearchResultPage(templatePage):
+
+ maxReturn = 3000
+ #NPerPage = 100
+ nkeywords = 0
+
+ def __init__(self, fd):
+ _log.info("Got here - xerxes2")
+ _log.info("sys.path: %s" % (sys.path))
+ #_log.info(causeanerror)
+ _log.info("xerxesc")
+ #self.jtemplate = JinjaEnv.get_template('SearchResultPage.html')
+ #templatePage.__init__(self, fd)
+
+ if not self.openMysql():
+ return
+
+ _log.info("xerxesd")
+
+ #self.dict['title'] = 'Search Results'
+ #TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
+ print("e2.8")
+ self.database = [fd['database']]
+ print("e2.9")
+ if not self.database or self.database == 'spacer':
+ print("e3")
+ #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(""):
+ print("e3.2")
+ #convert database into a database list
+ #was used for multiple databases search, this
+ #feature has been abandoned,
+ self.database = string.split(self.database,',')
+ else:
+ print("e3.4")
+ pass
+
+ print("e4")
+ ###########################################
+ # 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)
+
+ print("e4.5")
+ ###########################################
+ # 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']
+
+ print("e4.6")
+ ###########################################
+ # Search Options
+ ###########################################
+ self.matchwhole = fd['matchwhole']
+ print("e4.65")
+ #split result into pages
+ self.pageNumber = fd.get('pageno', 0)
+ print("e4.7")
+ try:
+ self.pageNumber = int(self.pageNumber)
+ except Exception as why:
+ print(why)
+ self.pageNumber = 0
+
+ print("e5")
+ ###########################################
+ # Generate Mysql Query
+ ###########################################
+ geneIdListQuery = fd.get('geneId', '')
+ if geneIdListQuery:
+ geneIdListQuery = string.replace(geneIdListQuery, ",", " ")
+ geneIdListQuery = " geneId=%s" % string.join(string.split(geneIdListQuery), "-")
+
+ self.ANDkeyword = fd.get('ANDkeyword', "")
+ self.ORkeyword = fd.get('ORkeyword', "")
+
+ self.ORkeyword += geneIdListQuery
+
+ self.ANDkeyword = self.ANDkeyword.replace("\\", "").strip()
+ self.ORkeyword = self.ORkeyword.replace("\\", "").strip()
+ #user defined sort option
+ self.orderByUserInput = fd.get('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()
+ print("glasses:", dbUrl)
+ 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(". ")
+ _log.info("fweep")
+ #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)
+ _log.info("flop")
+ self.genSearchResultTable()
+ #self.dict['body'] = str(TD_LR)
+ #self.dict['js1'] = ''
+ #self.dict['js2'] = 'onLoad="pageOffset()"'
+ #self.dict['layer'] = self.generateWarningLayer()
+
+ def genSearchResultTable(self):
+
+ #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
+
+ self.traitList = []
+ for k, item2 in enumerate(item):
+ j, ProbeSetID = item2[:2]
+ thisTrait = webqtlTrait(db=self.database[j], name=ProbeSetID, cursor=self.cursor)
+ self.traitList.append(thisTrait)
+
+ ##############
+ # Excel file #
+ ##############
+
+ # Todo: Replace this with official Python temp file naming functions?
+ 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(self.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]
+ self.thisFormName = 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(" "*2,"Select", width="25%"), HT.TD(" ","Deselect", width="255"), HT.TD(" "*3,"Invert", width="25%"), HT.TD(" "*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)
+ _log.info("flap trait is: %s" % (thisTrait.db.type))
+ 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=self.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=self.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=self.traitList, formName=mainfmName, 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("foo - 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 = """
+
+
+
+
+ You can also use advanced commands. Copy these simple examples
+ into the Get Any or Combined search fields:
+
+
+
POSITION=(chr1 25 30) finds genes, markers, or transcripts on chromosome 1 between 25 and 30 Mb.
+
+
MEAN=(15 16) LRS=(23 46) in the Combined field finds highly expressed genes (15 to 16 log2 units) AND with peak LRS linkage between 23 and 46.
+
+
+
RIF=mitochondrial searches RNA databases for GeneRIF links.
+
+
WIKI=nicotine searches GeneWiki for genes that you or other users have annotated with the word nicotine.
+
+
GO:0045202 searches for synapse-associated genes listed in the Gene Ontology.
+
+
+
GO:0045202 LRS=(9 99 Chr4 122 155) cisLRS=(9 999 10) in Combined finds synapse-associated genes with cis eQTL on Chr 4 from 122 and 155 Mb with LRS scores between 9 and 999.
+
+
RIF=diabetes LRS=(9 999 Chr2 100 105) transLRS=(9 999 10) in Combined finds diabetes-associated transcripts with peak trans eQTLs on Chr 2 between 100 and 105 Mb with LRS scores between 9 and 999.
+
+
+
+ {% for word in ORkeyword2 %}
+ {{word}} {% if not loop.last %} or {% endif %}
+ {% endfor %}
+
+ {% endif %}
+ {% if ANDkeyword2 %}
+
+ {% for word in ANDkeyword2 %}
+ {{word}} {% if not loop.last %} and {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+
+
GeneNetwork found {{ numify(nresults, "record", "records") }}.
+
+
To study a record, click on its ID below.
+
+
To add one or more records to your Selection window, use the checkbox and then click the Add to Collection button.
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
new file mode 100644
index 00000000..2f686432
--- /dev/null
+++ b/wqflask/wqflask/views.py
@@ -0,0 +1,23 @@
+from __future__ import absolute_import, division, print_function
+
+from wqflask import app
+
+from flask import render_template, request
+
+from wqflask import search_results
+
+from pprint import pformat as pf
+
+@app.route("/")
+def index_page():
+ return render_template("index_page.html")
+
+
+@app.route("/search")
+def search():
+ print("request is:", request.args)
+ the_search = search_results.SearchResultPage(request.args)
+ print("At rendering...")
+ print(pf(the_search.__dict__))
+ print("yack:", the_search.database[0].genHTML())
+ return render_template("search_result_page.html", **the_search.__dict__)
--
cgit v1.2.3
From 26663ce7a4bb75d2602261ed957bf3c1cdc4ebc6 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Thu, 24 May 2012 03:10:30 -0400
Subject: Added README, modified requirements
---
README-wqflask.txt | 31 ++++++++++++
wqflask/other_config/nginx.conf | 104 ++++++++++++++++++++++++++++++++++++++
wqflask/requirements.txt | 1 -
wqflask/wqflask/__init__.py | 3 ++
wqflask/wqflask/search_results.py | 2 +-
5 files changed, 139 insertions(+), 2 deletions(-)
create mode 100644 README-wqflask.txt
create mode 100644 wqflask/other_config/nginx.conf
diff --git a/README-wqflask.txt b/README-wqflask.txt
new file mode 100644
index 00000000..fdade7fa
--- /dev/null
+++ b/README-wqflask.txt
@@ -0,0 +1,31 @@
+This readme concerns the directory wqflask - an officially sanctioned fork of the main GeneNetwork
+code. It's still very early in the process - but we eventually want to port all of the code
+in GeneNetwork to Flask and Jinja2. For more information about the project in general, see
+the file README.md.
+
+For more information about the port to Flask, please keep reading.
+
+*************************
+
+Requirements:
+
+* Python 2.7
+
+* virtualenv 1.7.1.2 or later
+
+* Other python dependencies are listed in the file wqflask/requirements.txt
+
+**************************
+
+Installation:
+
+We highly recommend you create a virtual enviornment called ve27 in your home directory.
+
+> cd ~
+
+> virtualenv ve27
+
+> source ~/ve27/bin/activate
+
+> pip install -r ~/gene/wqflask/requirements.txt
+(Or replace gene with the name of the directory holding your repository)
diff --git a/wqflask/other_config/nginx.conf b/wqflask/other_config/nginx.conf
new file mode 100644
index 00000000..93e6af10
--- /dev/null
+++ b/wqflask/other_config/nginx.conf
@@ -0,0 +1,104 @@
+
+#user nobody;
+worker_processes 1;
+
+#error_log logs/error.log;
+#error_log logs/error.log notice;
+#error_log logs/error.log info;
+
+#pid logs/nginx.pid;
+
+
+events {
+ worker_connections 1024;
+}
+
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ # '$status $body_bytes_sent "$http_referer" '
+ # '"$http_user_agent" "$http_x_forwarded_for"';
+
+ #access_log logs/access.log main;
+
+ sendfile on;
+ #tcp_nopush on;
+
+ #keepalive_timeout 0;
+ keepalive_timeout 65;
+
+ gzip on;
+
+ server {
+ # Modeled after http://flask.pocoo.org/docs/deploying/wsgi-standalone/
+ listen 80;
+
+ server_name _;
+
+ access_log /var/log/nginx/access.log;
+ error_log /var/log/nginx/error.log;
+
+ location ^~ /css/ {
+ root /home/sam/gene/wqflask/wqflask/static/;
+ }
+
+ location ^~ /javascript/ {
+ root /home/sam/gene/wqflask/wqflask/static/;
+ }
+
+ location ^~ /images/ {
+ root /home/sam/gene/wqflask/wqflask/static/;
+ }
+
+ location / {
+ proxy_pass http://127.0.0.1:5000/;
+ proxy_redirect off;
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+
+ }
+
+
+ # another virtual host using mix of IP-, name-, and port-based configuration
+ #
+ #server {
+ # listen 8000;
+ # listen somename:8080;
+ # server_name somename alias another.alias;
+
+ # location / {
+ # root html;
+ # index index.html index.htm;
+ # }
+ #}
+
+
+ # HTTPS server
+ #
+ #server {
+ # listen 443;
+ # server_name localhost;
+
+ # ssl on;
+ # ssl_certificate cert.pem;
+ # ssl_certificate_key cert.key;
+
+ # ssl_session_timeout 5m;
+
+ # ssl_protocols SSLv2 SSLv3 TLSv1;
+ # ssl_ciphers HIGH:!aNULL:!MD5;
+ # ssl_prefer_server_ciphers on;
+
+ # location / {
+ # root html;
+ # index index.html index.htm;
+ # }
+ #}
+
+}
diff --git a/wqflask/requirements.txt b/wqflask/requirements.txt
index caa5d61e..684722aa 100644
--- a/wqflask/requirements.txt
+++ b/wqflask/requirements.txt
@@ -2,5 +2,4 @@ Flask==0.8
Jinja2==2.6
MySQL-python==1.2.3
Werkzeug==0.8.3
-pyXLWriter==0.4a3
wsgiref==0.1.2
diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py
index d0484c83..a6119dcc 100644
--- a/wqflask/wqflask/__init__.py
+++ b/wqflask/wqflask/__init__.py
@@ -1,5 +1,8 @@
from __future__ import absolute_import, division, print_function
+import sys
+print("sys.path is:", sys.path)
+
from flask import Flask
from utility import formatting
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
index c100645e..9ec676b8 100644
--- a/wqflask/wqflask/search_results.py
+++ b/wqflask/wqflask/search_results.py
@@ -16,7 +16,7 @@ import cPickle
import re
from math import *
import time
-import pyXLWriter as xl
+#import pyXLWriter as xl
#import pp - Note from Sam: is this used?
import math
import datetime
--
cgit v1.2.3
From 3912f2bacd87f607e9fdfa7a83fcdc05522589e0 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Thu, 24 May 2012 03:28:38 -0400
Subject: Added more to readme
---
README-wqflask.txt | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/README-wqflask.txt b/README-wqflask.txt
index fdade7fa..03e3a1cc 100644
--- a/README-wqflask.txt
+++ b/README-wqflask.txt
@@ -21,11 +21,31 @@ Installation:
We highly recommend you create a virtual enviornment called ve27 in your home directory.
+
+Get into your home directory
> cd ~
+Create a virtual environment
> virtualenv ve27
+Activate the environment
> source ~/ve27/bin/activate
+Install dependencies
> pip install -r ~/gene/wqflask/requirements.txt
(Or replace gene with the name of the directory holding your repository)
+
+**************************
+
+Running the program:
+
+Assuming your enviornment is activated (source ~/ve27/bin/activate) just run:
+
+> python ~/gene/wqflask/runserver.py
+
+The program as configured runs on port 5000 and does not serve static files.
+
+You'll have to run a webserver to serve pages on port 80 and to server the static files (or
+flask could also be configured to serve the static pages).
+
+A sample configuration file for nginx is in the directory: wqflask/other_config/nginx.conf
--
cgit v1.2.3
From 1fee128fafc491dbe84ebac22d8522bcb6ca1e6b Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Thu, 24 May 2012 03:43:09 -0400
Subject: Got rid of a bunch of prints used for debugging
---
wqflask/wqflask/search_results.py | 34 +++++++---------------------------
wqflask/wqflask/views.py | 4 ----
2 files changed, 7 insertions(+), 31 deletions(-)
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
index 9ec676b8..ee67c5de 100644
--- a/wqflask/wqflask/search_results.py
+++ b/wqflask/wqflask/search_results.py
@@ -59,25 +59,12 @@ class SearchResultPage(templatePage):
nkeywords = 0
def __init__(self, fd):
- _log.info("Got here - xerxes2")
- _log.info("sys.path: %s" % (sys.path))
- #_log.info(causeanerror)
- _log.info("xerxesc")
- #self.jtemplate = JinjaEnv.get_template('SearchResultPage.html')
- #templatePage.__init__(self, fd)
-
if not self.openMysql():
return
- _log.info("xerxesd")
-
- #self.dict['title'] = 'Search Results'
- #TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
- print("e2.8")
self.database = [fd['database']]
- print("e2.9")
+
if not self.database or self.database == 'spacer':
- print("e3")
#Error, No database selected
heading = "Search Result"
detail = ['''No database was selected for this search, please
@@ -85,16 +72,14 @@ class SearchResultPage(templatePage):
self.error(heading=heading,detail=detail,error="No Database Selected")
return
elif type(self.database) == type(""):
- print("e3.2")
#convert database into a database list
#was used for multiple databases search, this
#feature has been abandoned,
self.database = string.split(self.database,',')
else:
- print("e3.4")
pass
- print("e4")
+
###########################################
# Names and IDs of RISet / F2 set
###########################################
@@ -155,7 +140,6 @@ class SearchResultPage(templatePage):
#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)
- print("e4.5")
###########################################
# make sure search from same type of databases
###########################################
@@ -175,22 +159,20 @@ class SearchResultPage(templatePage):
elif self.dbType == "Geno":
self.searchField = ['Name','Chr']
- print("e4.6")
###########################################
# Search Options
###########################################
self.matchwhole = fd['matchwhole']
- print("e4.65")
#split result into pages
self.pageNumber = fd.get('pageno', 0)
- print("e4.7")
+
try:
self.pageNumber = int(self.pageNumber)
except Exception as why:
print(why)
self.pageNumber = 0
- print("e5")
+
###########################################
# Generate Mysql Query
###########################################
@@ -252,7 +234,6 @@ class SearchResultPage(templatePage):
dbUrlLink = " were"
else:
dbUrl = self.database[0].genHTML()
- print("glasses:", dbUrl)
dbUrlLink = " was"
#SearchText = HT.Blockquote('GeneNetwork searched the ', dbUrl, ' for all records ')
@@ -309,7 +290,6 @@ class SearchResultPage(templatePage):
# SearchText.append(" and ")
#
#SearchText.append(". ")
- _log.info("fweep")
#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."]
@@ -331,7 +311,7 @@ class SearchResultPage(templatePage):
#TD_LR.append(HT.Paragraph('Search Results', Class="title"), SearchText)
- _log.info("flop")
+
self.genSearchResultTable()
#self.dict['body'] = str(TD_LR)
#self.dict['js1'] = ''
@@ -397,7 +377,7 @@ class SearchResultPage(templatePage):
tblobj = {}
mainfmName = thisFormName
species = webqtlDatabaseFunction.retrieveSpecies(cursor=self.cursor, RISet=RISet)
- _log.info("flap trait is: %s" % (thisTrait.db.type))
+
if thisTrait.db.type=="Geno":
tblobj['header'] = self.getTableHeaderForGeno(worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
@@ -534,7 +514,7 @@ class SearchResultPage(templatePage):
self.results = []
for item in searchCountQuery:
start_time = datetime.datetime.now()
- _log.info("foo - Executing query: %s"%(item))
+ _log.info("Executing query: %s"%(item))
self.cursor.execute(item)
allResults.append(self.cursor.fetchall())
end_time = datetime.datetime.now()
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 2f686432..88a6f6a1 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -15,9 +15,5 @@ def index_page():
@app.route("/search")
def search():
- print("request is:", request.args)
the_search = search_results.SearchResultPage(request.args)
- print("At rendering...")
- print(pf(the_search.__dict__))
- print("yack:", the_search.database[0].genHTML())
return render_template("search_result_page.html", **the_search.__dict__)
--
cgit v1.2.3
From 88022d6c26b320cb614454b706fad26fcd34033e Mon Sep 17 00:00:00 2001
From: root
Date: Thu, 31 May 2012 17:10:28 -0500
Subject: On branch develop Changes to be committed: modified:
web/javascript/jqueryFunction.js modified:
web/webqtl/correlation/CorrelationPage.py modified:
web/webqtl/showTrait/DataEditingPage.py
---
web/javascript/jqueryFunction.js | 2041 ++++++++++++++---------------
web/webqtl/correlation/CorrelationPage.py | 1118 +++++++++-------
web/webqtl/showTrait/DataEditingPage.py | 35 +-
3 files changed, 1648 insertions(+), 1546 deletions(-)
mode change 100644 => 100755 web/javascript/jqueryFunction.js
mode change 100644 => 100755 web/webqtl/showTrait/DataEditingPage.py
diff --git a/web/javascript/jqueryFunction.js b/web/javascript/jqueryFunction.js
old mode 100644
new mode 100755
index 5e6641cd..e612098b
--- a/web/javascript/jqueryFunction.js
+++ b/web/javascript/jqueryFunction.js
@@ -1,80 +1,75 @@
/*
jquery part
*/
-
/*
used by index (base/indexBody.py)
*/
-
-$(document).ready(function(){
+$(document).ready(function () {
options_visible = 0; //Whether advanced options are being shown
-
$('tr .advanced_option').hide();
- $('.toggle_advanced').click(function(){
+ $('.toggle_advanced').click(function () {
$('tr .advanced_option').toggle();
-
- if (options_visible = 0) {
- $('.full_search_td').css('display','none;');
- $('.search_td').css('display','inline');
- options_visible = 1;
- }
- else {
- if ($('#type_menu.type_menu').val() = 'Hippocampus'){
- $('.search_td').css('display','none;');
- $('.full_search_td').css('display','inline');
- }
- options_visible = 0;
- }
+
+ if (options_visible = 0) {
+ $('.full_search_td').css('display', 'none;');
+ $('.search_td').css('display', 'inline');
+ options_visible = 1;
+ } else {
+ if ($('#type_menu.type_menu').val() = 'Hippocampus') {
+ $('.search_td').css('display', 'none;');
+ $('.full_search_td').css('display', 'inline');
+ }
+ options_visible = 0;
+ }
});
- $('#full_search').click(function(){
+ $('#full_search').click(function () {
gene_symbol = $('input[name=keyword]').val();
scriptable_interface_url = 'http://alexandria.uthsc.edu:89/webqtl/main.py?cmd=sch&gene=' + gene_symbol;
- window.open(scriptable_interface_url,'_self');
+ window.open(scriptable_interface_url, '_self');
});
});
-$('select.type_menu').live('change', function() {
+$('select.type_menu').live('change', function () {
var trait_type = $('select.type_menu option:selected').val();
- $('#tissue').val(trait_type);
- $('#tissue').trigger('change');
+ $('#tissue').val(trait_type);
+ $('#tissue').trigger('change');
});
/*
used by CorrelationPage.py, AddToSelectionPage.py, and SearchResultPage.py
*/
-$(document).ready(function(){
- $('img[name=addselect], img[name=networkgraph], img[name=corrmatrix], img[name=partialCorr], img[name=comparecorr], img[name=mintmap], img[name=heatmap]').click(function(){
- if ($('input[name=searchResult]:checked').length < 1){
- for (i=0; i<10; i++){
- $('input[name=searchResult]:eq('+i+')').attr('checked',true);
+$(document).ready(function () {
+ $('img[name=addselect], img[name=networkgraph], img[name=corrmatrix], img[name=partialCorr], img[name=comparecorr], img[name=mintmap], img[name=heatmap]').click(function () {
+ if ($('input[name=searchResult]:checked').length < 1) {
+ for (i = 0; i < 10; i++) {
+ $('input[name=searchResult]:eq(' + i + ')').attr('checked', true);
}
}
});
- $('img[name=addselect]').click(function(){
- addRmvSelection($('input[name=RISet]').val(), document.getElementsByName('showDatabase'+ $('input[name=RISet]').val())[0], 'addToSelection');
+ $('img[name=addselect]').click(function () {
+ addRmvSelection($('input[name=RISet]').val(), document.getElementsByName('showDatabase' + $('input[name=RISet]').val())[0], 'addToSelection');
});
- $('.toggleShowHide').click(function(){
+ $('.toggleShowHide').click(function () {
var className = '.extra_options';
- if ($(className).css('display') == 'none'){
- var less = 'less';
- $('input[name=showHideOptions]').val(less);
+ if ($(className).css('display') == 'none') {
+ var less = 'less';
+ $('input[name=showHideOptions]').val(less);
$(className).show();
$('input[name=options]').val('Fewer Options');
var display = $('input[name=options]').css('display')
- $(display).val('block');
- }
- else {
- var more = 'more';
- $('input[name=showHideOptions]').val(more);
- $(className).hide();
- $('input[name=options]').val('More Options');
- var display = $('input[name=showHideOptions]').css('display')
- $(display).val('block');
+ $(display).val('block');
+ } else {
+ var more = 'more';
+ $('input[name=showHideOptions]').val(more);
+ $(className).hide();
+ $('input[name=options]').val('More Options');
+ var display = $('input[name=showHideOptions]').css('display')
+ $(display).val('block');
}
});
});
@@ -83,82 +78,91 @@ $(document).ready(function(){
used by AddToSelectionPage.py
*/
function validateTraitNumber() {
- var checkBoxes = $('.checkallbox');
- if (checkBoxes.filter(":checked").length < 2) {
- alert("Please select at least two traits.");
- return false;
- }
- else {
- return true;
- }
+ var checkBoxes = $('.checkallbox');
+ if (checkBoxes.filter(":checked").length < 2) {
+ alert("Please select at least two traits.");
+ return false;
+ } else {
+ return true;
+ }
}
/*
used by TextSearchPage.py
*/
-$(document).ready(function(){
-
- $('.add_traits').click(function(){
- $('input[name=searchResult]').each(function(){
- if ($(this).is(':checked')){
- groupName = $(this).parents().next().next().children('[href]').text();
- addORrmv = 'addToSelection';
- thisForm = $('form[name=showDatabase]');
- addRmvSelection_allGroups(groupName, thisForm, addORrmv);
- }
- });
- });
-
- function addRmvSelection_allGroups(groupName, thisForm, addORrmv){
- thisForm.attr('target',groupName);
- thisForm.children('input[name=FormID]:hidden').val(addORrmv);
- thisForm.children('input[name=RISet]:hidden').val(groupName);
- var newWindow = open("",thisForm.attr('target'),"menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=1,directories=1,width=900");
- thisForm.submit();
- }
-
- $('.tab_content').hide(); //Hide all tab content
- $('div.tab_container').each(function(){
- $(this).parent('td').find('div.tab_container:first').find('div.tab_content:first').show();
- });
- $('ul.tabs').each(function(){
- $(this).find('li:first').addClass('active');
- });
- $('ul.tabs:first').find('li:first').show();
- $('.tab_container:first').find('.tab_content:first').show();
-
- //On Click Event
- $('ul.tabs li').click(function() {
- $('ul.tabs').find('li').removeClass('last_viewed');
- if($(this).parent('ul.tabs').next('div.tab_container').attr('id').indexOf('stats') != 1){
- $(this).addClass('last_viewed');
- }
- $(this).parent('ul.tabs').find('li').removeClass('active');
- $(this).addClass('active');
- $(this).parent('ul.tabs').next('div.tab_container').find('.tab_content').hide();
- var activeTab = $(this).find('a').attr('href');
- if ($.browser.msie)
- {$(activeTab).show();}
- else
- {$(activeTab).fadeIn();} //Fade in the active ID content
-
- return false;
- });
+$(document).ready(function () {
+
+ $('.add_traits').click(function () {
+ $('input[name=searchResult]').each(function () {
+ if ($(this).is(':checked')) {
+ groupName = $(this).parents().next().next().children('[href]').text();
+ addORrmv = 'addToSelection';
+ thisForm = $('form[name=showDatabase]');
+ addRmvSelection_allGroups(groupName, thisForm, addORrmv);
+ }
+ });
+ });
+
+ function addRmvSelection_allGroups(groupName, thisForm, addORrmv) {
+ thisForm.attr('target', groupName);
+ thisForm.children('input[name=FormID]:hidden').val(addORrmv);
+ thisForm.children('input[name=RISet]:hidden').val(groupName);
+ var newWindow = open("", thisForm.attr('target'), "menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=1,directories=1,width=900");
+ thisForm.submit();
+ }
+
+ $('.tab_content').hide(); //Hide all tab content
+ $('div.tab_container').each(function () {
+ $(this).parent('td').find('div.tab_container:first').find('div.tab_content:first').show();
+ });
+ $('ul.tabs').each(function () {
+ $(this).find('li:first').addClass('active');
+ });
+ $('ul.tabs:first').find('li:first').show();
+ $('.tab_container:first').find('.tab_content:first').show();
+
+ //On Click Event
+ $('ul.tabs li').click(function () {
+ $('ul.tabs').find('li').removeClass('last_viewed');
+ if ($(this).parent('ul.tabs').next('div.tab_container').attr('id').indexOf('stats') != 1) {
+ $(this).addClass('last_viewed');
+ }
+ $(this).parent('ul.tabs').find('li').removeClass('active');
+ $(this).addClass('active');
+ $(this).parent('ul.tabs').next('div.tab_container').find('.tab_content').hide();
+ var activeTab = $(this).find('a').attr('href');
+ if ($.browser.msie) {
+ $(activeTab).show();
+ } else {
+ $(activeTab).fadeIn();
+ } //Fade in the active ID content
+ return false;
+ });
});
/*
used by DataEditingPage.py
*/
-$(document).ready(function() {
+$(document).ready(function () {
+
+ // ZS: This checks the number of columns in order to determine which column to not sort; in this case the plus-minus symbol shouldn't be sortable
+ $('#sortable1,#sortable2').find('th').each(function () {
+ if ($(this).text() == 'SE') {
+ $.tablesorter.defaults.headers = {
+ 3: {
+ sorter: false
+ }
+ };
+ return false;
+ }
+ });
+
+ if ($('#sortable1,#sortable2').find('.outlier').size() > 0) {
+ $('input[name=sample_method]:eq(1)').attr('checked','checked');
+ $('input[name=tissue_method]:eq(1)').attr('checked','checked');
+ }
- // ZS: This checks the number of columns in order to determine which column to not sort; in this case the plus-minus symbol shouldn't be sortable
- $('#sortable1,#sortable2').find('th').each(function() {
- if ($(this).text() == 'SE'){
- $.tablesorter.defaults.headers = { 3: {sorter: false} };
- return false;
- }
- });
/*
ZS: This segment is called by tablesorter.js; it determines where to get the text used when sorting, based on the type of cell.
@@ -167,949 +171,922 @@ $(document).ready(function() {
This segment is repeated twice. Ideally this wouldn't be the case, but I can't find a way to reuse the inner textExtraction function.
*/
- //ZS: Defining these here, so they don't need to be searched for in the DOM for every single node
- primaryTable = $("#sortable1");
- otherTable = $("#sortable2");
-
- primaryValueHeader = primaryTable.find('th:contains("Value"):eq(0)');
- primarySEHeader = primaryTable.find('th:contains("SE"):eq(0)');
- otherValueHeader = otherTable.find('th:contains("Value"):eq(1)');
- otherSEHeader = otherTable.find('th:contains("SE"):eq(1)');
-
- $("#sortable1").tablesorter({
- textExtraction: function(node) {
- if ((node.children[0] == "[object HTMLInputElement]" && node.children[0].type == "text") || (/\S/.test(node.id))) {
- cellId = node.id;
- thisCell = $('#'+cellId).children(':eq(0)')
- valueClassNames = thisCell.attr('class').split(/\s+/);
- capitalized_column_name = cellId.split('_')[0].charAt(0).toUpperCase() + cellId.split('_')[0].slice(1);
- value = valueClassNames[valueClassNames.length - 1];
- newValue = thisCell.val();
-
- if (newValue == 'x' || value == '9999' || value == '-9999') {
- valueType = cellId.split('_')[0];
- if (valueType == 'value'){
- header = primaryValueHeader;
- } else {
- header = primarySEHeader;
- }
-
- if (header.hasClass('headerSortUp')){
- sort_order = 'desc';
- } else if (header.hasClass('headerSortDown')){
- sort_order = 'asc';
- } else {
- sort_order = 'desc';
- }
-
- if (sort_order == 'desc') {
- value = 9999;
- thisCell.removeClass(value).addClass('9999');
- } else if (sort_order == 'asc'){
- value = -9999;
- thisCell.removeClass(value).addClass('-9999');
- } else {
- value = 9999;
- thisCell.removeClass(value).addClass('9999');
- }
- }
-
- text = value;
- }
-
- else {
- if (node.textContent) {
- text = node.textContent;
- } else {
- if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
- text = node.childNodes[0].innerHTML;
- } else {
- text = node.innerText;
- }
- }
- }
- return text
- }
- });
-
- $("#sortable2").tablesorter({
- textExtraction: function(node) {
- if ((node.children[0] == "[object HTMLInputElement]" && node.children[0].type == "text") || (/\S/.test(node.id))) {
- cellId = node.id;
- thisCell = $('#'+cellId).children(':eq(0)')
- valueClassNames = thisCell.attr('class').split(/\s+/);
- capitalized_column_name = cellId.split('_')[0].charAt(0).toUpperCase() + cellId.split('_')[0].slice(1);
- value = valueClassNames[valueClassNames.length - 1];
- newValue = thisCell.val();
-
- if (newValue == 'x' || value == '9999' || value == '-9999') {
- valueType = cellId.split('_')[0];
- if (valueType == 'value'){
- header = otherValueHeader;
- } else {
- header = otherSEHeader;
- }
-
- if (header.hasClass('headerSortUp')){
- sort_order = 'desc';
- } else if (header.hasClass('headerSortDown')){
- sort_order = 'asc';
- } else {
- sort_order = 'desc';
- }
-
- if (sort_order == 'desc') {
- value = 9999;
- thisCell.removeClass(value).addClass('9999');
- } else if (sort_order == 'asc'){
- value = -9999;
- thisCell.removeClass(value).addClass('-9999');
- } else {
- value = 9999;
- thisCell.removeClass(value).addClass('9999');
- }
- }
-
- text = value;
- }
-
- else {
- if (node.textContent) {
- text = node.textContent;
- } else {
- if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
- text = node.childNodes[0].innerHTML;
- } else {
- text = node.innerText;
- }
- }
- }
- return text
- }
- });
+ //ZS: Defining these here, so they don't need to be searched for in the DOM for every single node
+ primaryTable = $("#sortable1");
+ otherTable = $("#sortable2");
+
+ primaryValueHeader = primaryTable.find('th:contains("Value"):eq(0)');
+ primarySEHeader = primaryTable.find('th:contains("SE"):eq(0)');
+ otherValueHeader = otherTable.find('th:contains("Value"):eq(1)');
+ otherSEHeader = otherTable.find('th:contains("SE"):eq(1)');
+
+ $("#sortable1").tablesorter({
+ textExtraction: function (node) {
+ if ((node.children[0] == "[object HTMLInputElement]" && node.children[0].type == "text") || (/\S/.test(node.id))) {
+ cellId = node.id;
+ thisCell = $('#' + cellId).children(':eq(0)')
+ valueClassNames = thisCell.attr('class').split(/\s+/);
+ capitalized_column_name = cellId.split('_')[0].charAt(0).toUpperCase() + cellId.split('_')[0].slice(1);
+ value = valueClassNames[valueClassNames.length - 1];
+ newValue = thisCell.val();
+
+ if (newValue == 'x' || value == '9999' || value == '-9999') {
+ valueType = cellId.split('_')[0];
+ if (valueType == 'value') {
+ header = primaryValueHeader;
+ } else {
+ header = primarySEHeader;
+ }
+
+ if (header.hasClass('headerSortUp')) {
+ sort_order = 'desc';
+ } else if (header.hasClass('headerSortDown')) {
+ sort_order = 'asc';
+ } else {
+ sort_order = 'desc';
+ }
+
+ if (sort_order == 'desc') {
+ value = 9999;
+ thisCell.removeClass(value).addClass('9999');
+ } else if (sort_order == 'asc') {
+ value = -9999;
+ thisCell.removeClass(value).addClass('-9999');
+ } else {
+ value = 9999;
+ thisCell.removeClass(value).addClass('9999');
+ }
+ }
-/*
+ text = value;
+ } else {
+ if (node.textContent) {
+ text = node.textContent;
+ } else {
+ if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
+ text = node.childNodes[0].innerHTML;
+ } else {
+ text = node.innerText;
+ }
+ }
+ }
+ return text
+ }
+ });
+
+ $("#sortable2").tablesorter({
+ textExtraction: function (node) {
+ if ((node.children[0] == "[object HTMLInputElement]" && node.children[0].type == "text") || (/\S/.test(node.id))) {
+ cellId = node.id;
+ thisCell = $('#' + cellId).children(':eq(0)')
+ valueClassNames = thisCell.attr('class').split(/\s+/);
+ capitalized_column_name = cellId.split('_')[0].charAt(0).toUpperCase() + cellId.split('_')[0].slice(1);
+ value = valueClassNames[valueClassNames.length - 1];
+ newValue = thisCell.val();
+
+ if (newValue == 'x' || value == '9999' || value == '-9999') {
+ valueType = cellId.split('_')[0];
+ if (valueType == 'value') {
+ header = otherValueHeader;
+ } else {
+ header = otherSEHeader;
+ }
+
+ if (header.hasClass('headerSortUp')) {
+ sort_order = 'desc';
+ } else if (header.hasClass('headerSortDown')) {
+ sort_order = 'asc';
+ } else {
+ sort_order = 'desc';
+ }
+
+ if (sort_order == 'desc') {
+ value = 9999;
+ thisCell.removeClass(value).addClass('9999');
+ } else if (sort_order == 'asc') {
+ value = -9999;
+ thisCell.removeClass(value).addClass('-9999');
+ } else {
+ value = 9999;
+ thisCell.removeClass(value).addClass('9999');
+ }
+ }
+
+ text = value;
+ } else {
+ if (node.textContent) {
+ text = node.textContent;
+ } else {
+ if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
+ text = node.childNodes[0].innerHTML;
+ } else {
+ text = node.innerText;
+ }
+ }
+ }
+ return text
+ }
+ });
+
+ /*
ZS: When the user changes the value in the text field, the new value is added as a class. This is because
$('input[type=text]').val() gets the value attribute, which is always the default value, instead of the
value property (which can be changed)
*/
- var thisTable = $('#sortable1,#sortable2');
-
- thisTable.bind("update propertychange keyup input paste", function(e){
-
- var target = e.target;
- $target = $(target);
-
- if (target.nodeName.toLowerCase() == 'input'){
- thisClassNames = $target.attr('class').split(/\s+/);
- valueClass = thisClassNames[thisClassNames.length - 1];
- newValue = $target.val();
- thisParent = $target.parent('td');
- thisParentId = thisParent.attr('id');
-
- $target.removeClass(valueClass);
-
- if (newValue == 'x'){
- thisParent.parent('tr').addClass('blocked');
- } else {
- $('#'+thisParentId).children('input.valueField:eq(0)').addClass(newValue);
- }
- }
- });
-
- ////////////////////////////////////
- // Initially close tabs
- ////////////////////////////////////
-
- thisForm = $('form[name="dataInput"]');
-
- $('#sectionbody2').hide();
- $('#sectionbody3').hide();
- $('#sectionbody4').hide();
-
- $('#title1').click(function() {
- $('#sectionbody1').toggle();
- return false;
- });
- $('#title2').click(function() {
- $('#sectionbody2').toggle();
- return false;
- });
- $('#title3').click(function() {
- $('#sectionbody3').toggle();
- return false;
- });
- $('#title4').click(function() {
- $('#sectionbody4').toggle();
- return false;
- });
- $('#title5').click(function() {
- $('#sectionbody5').toggle();
- return false;
- });
-
-
-
- //////////////////////////////////////////////////////////////
- // Switch out + and - icon when you click each section header
- //////////////////////////////////////////////////////////////
-
- var expand_html = "";
- var contract_html = "";
-
- $('#title2, #title3, #title4').prepend(expand_html).addClass('1');
-
- $('#title1, #title5').prepend(contract_html).addClass('0');
-
- for(i=1;i<=5;i++){
- $('#title'+i).click(function(){
- if ($(this).hasClass('0')) {
- $(this).find('span').replaceWith(expand_html);
- $(this).removeClass('0');
- $(this).addClass('1');
- }
- else {
- $(this).find('span').replaceWith(contract_html);
- $(this).removeClass('1');
- $(this).addClass('0');
- }
- });
- }
-
- // Exclude cases by attributes
-
- $('div.attribute_values:first').css('display', 'inline'); //Display the dropdown menu with the first attribute's distinct values
-
- $('select[name=exclude_menu]').change(function(){
- $('div.attribute_values').css('display', 'none'); //clear all other menus when a new attribute is selected
- attribute = $(this).val();
- //attribute = $('select[name=exclude_menu]').val();
- menu = $('div.attribute_values').find('[name=\''+attribute+'\']');
- menu.parent().css('display', 'inline');
- });
-
- primary_row_count = $('#primary').find('tr').length - 1;
- other_row_count = $('#other').find('tr').length - 1;
-
- if (primary_row_count >= other_row_count) {
- row_count = primary_row_count;
- }
- else {
- row_count = other_row_count;
- }
-
- $('div.attribute_values').children('select').change(function(){
- exclude_value = $(this).val();
- });
-});
-
-$(window).load(function(){
-
- //ZS: These are needed in a few places; looping through rows by index is faster than doing a "find" search
- numPrimaryRows = $('#sortable1').find('tr').length;
- numOtherRows = $('#sortable2').find('tr').length;
-
-
-///////////////////////////////
-//Basic Statistics
-///////////////////////////////
-
- /////////////////////////////////////////////////////////////////
- // Hide unselected Basic Statistics tabs (when just BXD strains
- // are selected, hide the results for all strains/non-BXD)
- /////////////////////////////////////////////////////////////////
-
- $('#stats_tabs1').hide();
- $('#stats_tabs2').hide();
-
- $('#sectionbody2').find('select[name=stats_mdp]').change(function(){
- selected = $('#sectionbody2').find('select[name=stats_mdp] option:selected').val();
- for (i=0;i<=2;i++){
- $('#stats_tabs'+i).hide();
- }
- $('#stats_tabs'+selected).show();
- });
-
- ////////////////////////////////////////////////////////////////////////
- // Select the same tab across each sample group (when a Box Plot is
- // selected for BXD, switching to Non-BXD will also display a Box Plot)
- ////////////.///////////////////////////////////////////////////////////
-
- var $tabs1 = $('#stats_tabs0').tabs();
- var $tabs2 = $('#stats_tabs1').tabs();
- var $tabs3 = $('#stats_tabs2').tabs();
-
- $tabs1.tabs({
- show: function(event, ui) {
- var selected = $tabs1.tabs('option','selected');
- $tabs2.tabs('select',selected);
- $tabs3.tabs('select',selected);
- }
- });
- $tabs2.tabs({
- show: function(event, ui) {
- var selected = $tabs2.tabs('option','selected');
- $tabs1.tabs('select',selected);
- $tabs3.tabs('select',selected);
- }
- });
- $tabs3.tabs({
- show: function(event, ui) {
- var selected = $tabs3.tabs('option','selected');
- $tabs1.tabs('select',selected);
- $tabs2.tabs('select',selected);
- }
- });
-
-
-///////////////////////////////
-//Calculate Correlations
-///////////////////////////////
-
- $('#sectionbody3').find('input[name="sample_corr"]').click(function() {
- dbValue = $('select[name=database1] option:selected').val();
- $('input[name=database]').val(dbValue);
- criteriaValue = $('select[name=criteria1] option:selected').val();
- $('input[name=criteria]').val(criteriaValue);
- MDPValue = $('select[name=MDPChoice1] option:selected').val();
- $('input[name=MDPChoice]').val(MDPValue);
-
- methodValue = $('input[name=sample_method]:checked').val();
-
- //This simple method can be used now that 'method' is defaulted to None instead of ''
- if (methodValue == "1"){
- $('input[name=method]').val('1');
- }
- else{
- $('input[name=method]').val('2');
- }
-
- dataEditingFunc(this.form,'correlation');
- });
-
- $('#sectionbody3').find('input[name="lit_corr"]').click(function() {
- dbValue = $('select[name=database2] option:selected').val();
- $('input[name=database]').val(dbValue);
- criteriaValue = $('select[name=criteria2] option:selected').val();
- $('input[name=criteria]').val(criteriaValue);
- MDPValue = $('select[name=MDPChoice2] option:selected').val();
- $('input[name=MDPChoice]').val(MDPValue);
-
- $('input[name=method]').val('3');
-
- dataEditingFunc(this.form,'correlation');
- });
-
- $('#sectionbody3').find('input[name="tiss_corr"]').click(function() {
- dbValue = $('select[name=database3] option:selected').val();
- $('input[name=database]').val(dbValue);
- criteriaValue = $('select[name=criteria3] option:selected').val();
- $('input[name=criteria]').val(criteriaValue);
- MDPValue = $('select[name=MDPChoice3] option:selected').val();
- $('input[name=MDPChoice]').val(MDPValue);
-
- methodValue = $('input[name=tissue_method]:checked').val();
-
- if (methodValue == "4"){
- $('input[name=method]').val('4');
- }
- else{
- $('input[name=method]').val('5');
- }
- dataEditingFunc(this.form,'correlation');
- });
-
-///////////////////////////////
-//Mapping Tools
-///////////////////////////////
-
- $('#sectionbody4').find('input[name=interval]').click(function() {
- chrValue = $('select[name=chromosomes1] option:selected').val();
- $('input[name=chromosomes]').val(chrValue);
- scaleValue = $('select[name=scale1] option:selected').val();
- $('input[name=scale]').val(scaleValue);
- $('input[name=controlLocus]').val('');
-
- //Changed the way permValue, bootValue, and parentsValue are acquired; before it was $(____).is(':checked');
- permValue = $('input[name=permCheck1]:checked').val();
- $('input[name=permCheck]').val(permValue);
-
- bootValue = $('input[name=bootCheck1]:checked').val();
- $('input[name=bootCheck]').val(bootValue);
-
- if ($('input[name=parentsf14regression1]:checked').length > 0){
- $('input[name=parentsf14regression]').val('on');
- } else {
- $('input[name=parentsf14regression]').val('off');
- }
-
- varValue = $('input[name=applyVarianceSE1]:checked').val();
- $('input[name=applyVarianceSE]').val(varValue);
-
- dataEditingFunc(this.form,'intervalMap');
- });
-
- var tiptext = "e.g., rs12345";
- controlLocus = $('#sectionbody4').find('input[name=controlLocus]');
-
- if(controlLocus.val() == '' || controlLocus == tiptext) {
- controlLocus.addClass('searchtip').val(tiptext);
- }
-
- controlLocus.focus(function(e) {
- if(controlLocus.val() == tiptext) {
- controlLocus.val('');
- }
- controlLocus.removeClass('searchtip');
- });
-
- controlLocus.blur(function(e) {
- if(controlLocus.val() == '') {
- controlLocus.addClass('searchtip').val(tiptext);
- } else if(controlLocus.val() == tiptext) {
- controlLocus.addClass('searchtip');
- } else {
- controlLocus.removeClass('searchtip');
- }
- });
-
- $('#sectionbody4').find('input[name=composite]').click(function() {
- chrValue = $('select[name=chromosomes2] option:selected').val();
- $('input[name=chromosomes]').val(chrValue);
- scaleValue = $('select[name=scale2] option:selected').val();
- $('input[name=scale]').val(scaleValue);
- controlValue = controlLocus.val();
- if (controlValue != tiptext){
- controlLocus.val(controlValue);
- }
- else{
- controlLocus.val('');
- }
-
- //Changed the way permValue, bootValue, and parentsValue are acquired; before it was $(____).is(':checked');
- permValue = $('input[name=permCheck2]:checked').val();
- $('input[name=permCheck]').val(permValue);
-
- bootValue = $('input[name=bootCheck2]:checked').val();
- $('input[name=bootCheck]').val(bootValue);
-
- if ($('input[name=parentsf14regression3]:checked').length > 0){
- $('input[name=parentsf14regression]').val('on');
- } else {
- $('input[name=parentsf14regression]').val('off');
- }
-
- dataEditingFunc(this.form,'intervalMap');
-
- });
-
- $('#sectionbody4').find('input[name=marker]').click(function() {
- //Changed the way parentsValue is acquired; before it was $(____).is(':checked');
- if ($('input[name=parentsf14regression2]:checked').length > 0){
- $('input[name=parentsf14regression]').val('on');
- } else {
- $('input[name=parentsf14regression]').val('off');
- }
-
- varValue = $('input[name=applyVarianceSE2]:checked').val();
- $('input[name=applyVarianceSE]').val(varValue);
-
- dataEditingFunc(this.form,'markerRegression');
- });
-
-///////////////////////////////
-//Review and Edit Data
-///////////////////////////////
-
- $('input[name=excludeGroup]').click(function(){
- for (i = 1;i <= Math.max(primary_row_count,other_row_count)-1; i++){
- valueExists = 0;
- $('#Primary_'+i+',#Other_'+i).children().each(function(){
- if ($(this).text() == exclude_value) {
- $('#Primary_'+i+',#Other_'+i).addClass('blocked').find('input[type=text]').val('x');
- valueExists = 1;
- return false;
- }
- });
- }
- });
-
- $('.update').click(function(){
- windowName = 'formTarget' + (new Date().getTime());
- newWindow = open("",windowName,"menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=0,directories=1,width=900");
- document.dataInput.target = windowName;
- document.dataInput.submitID.value = "basicStatistics";
-
- primaryData = getTraitData()[0];
- otherData = getTraitData()[1];
- allData = getTraitData()[2];
-
- if (otherData[0].length > 0) {
- if ($('select[name="stats_mdp"] option:selected').val() == 0) {
- document.dataInput.strainNames.value = allData[0].toString();
- document.dataInput.strainVals.value = allData[1].toString();
- document.dataInput.strainVars.value = allData[2].toString();
- }
- else if ($('select[name="stats_mdp"] option:selected').val() == 1) {
- document.dataInput.strainNames.value = primaryData[0].toString();
- document.dataInput.strainVals.value = primaryData[1].toString();
- document.dataInput.strainVars.value = primaryData[2].toString();
- }
- else {
- document.dataInput.strainNames.value = otherData[0].toString();
- document.dataInput.strainVals.value = otherData[1].toString();
- document.dataInput.strainVars.value = otherData[2].toString();
- }
- }
- else {
- document.dataInput.strainNames.value = allData[0].toString();
- document.dataInput.strainVals.value = allData[1].toString();
- document.dataInput.strainVars.value = allData[2].toString();
- }
-
- document.dataInput.submit();
- });
-
- $('input[name="export"]').click(function(){
- windowName = 'formTarget' + (new Date().getTime());
- newWindow = open("",windowName,"menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=0,directories=1,width=900");
- document.dataInput.target = windowName;
- document.dataInput.submitID.value = "exportData";
-
- primaryData = getTraitData()[0];
- otherData = getTraitData()[1];
-
- document.dataInput.strainNames.value = primaryData[0].toString();
- document.dataInput.strainVals.value = primaryData[1].toString();
- document.dataInput.strainVars.value = primaryData[2].toString();
-
- document.dataInput.otherStrainNames.value = otherData[0].toString();
- document.dataInput.otherStrainVals.value = otherData[1].toString();
- document.dataInput.otherStrainVars.value = otherData[2].toString();
-
- attribute_names = new Array();
- $('#primary,#other').find('th.attribute_name').each(function(){
- attribute_names.push($(this).val().toString());
- });
-
- primary_attribute_values = ""; //This string will be structured as a dictionary with a set of values for each attribute; it will be parsed in the ExportPage class
- other_attribute_values = "";
-
- attr_counter = 1; // Counter for each different attribute
- row_counter = 1; // Counter for each value for each attribute
- while (attr_counter <= attribute_names.length){
- attribute_name = $('#primary,#other').find('th.attribute_name:eq('+ (attr_counter-1).toString() + ')').text();
- primary_row_count = $('#primary').find('tr').length - 1;
- other_row_count = $('#other').find('tr').length - 1;
-
- primary_attribute_values += attribute_name + " : ";
- other_attribute_values += attribute_name + " : ";
-
- primary_value_string = ""; //This string of values (in the format 'a,b,c', etc) will be appended to the primary_attribute_values string
- for (row_counter = 1;row_counter <= numPrimaryRows; row_counter++){
- value = $('#primary_attribute'+attr_counter.toString()+'_sample'+row_counter.toString()).text();
- if (row_counter == primary_row_count) {
- primary_value_string += (value + " / ");
- }
- else{
- primary_value_string += (value + ",");
- }
- }
-
- primary_attribute_values += primary_value_string;
-
- other_value_string = ""; //This string of values (in the format 'a,b,c', etc) will be appended to the other_attribute_values string
- for (row_counter = 1;row_counter <= numOtherRows; row_counter++){
- value = $('#other_attribute'+attr_counter.toString()+'_sample'+row_counter.toString()).text();
- if (row_counter == other_row_count) {
- other_value_string += (value + " / ");
- }
- else{
- other_value_string += (value + ",");
- }
- }
- other_attribute_values += other_value_string;
- attr_counter += 1
- }
-
- document.dataInput.extra_attributes.value = primary_attribute_values;
- document.dataInput.other_extra_attributes.value = other_attribute_values;
-
- document.dataInput.submit();
- });
-
- var thisTable = $('#sortable1,#sortable2'); //ZS: variable representing each table, because it's used often
-
- thisTable.find('input[name="selectCheck"]').click(function(){
- if($(this).is(':checked')){
- $(this).parent("").parent("").children("td").css("background-color", "yellow");
- }
- else{
- if(!($(this).parent().parent().hasClass('outlier'))){
- $(this).parent().parent().children("td").css("background-color", "white");
- }
- }
- });
-
- $('input[name=resetButton]').click(function(){
-
- //ZS: Reset "hide no value" and "hide outliers"
- $('#showHideOptions').find('input[name=showHideNoValue]').val(' Hide No Value ');
- $('#showHideOptions').find('input[name=showHideOutliers]').val(' Hide Outliers ');
- noValShown = 1;
- outliersShown = 1;
-
- for (i=1;i<=numPrimaryRows-1;i++){
- var thisRow = $('#Primary_'+i);
- if (thisRow.is('.invisible')){
- thisRow.removeClass('invisible');
- }
- if (thisRow.is('.blocked')){
- thisRow.removeClass('blocked');
- }
- if (thisRow.is(':not(.outlier)')){
- thisRow.css("background-color", "white");
- }
-
- var thisValueField = thisRow.find('.valueField');
-
- var originalValue = thisValueField[0].defaultValue;
- var thisClassNames = thisRow.find('input:eq(1)').attr('class').split(/\s+/);
- var valueClass = thisClassNames[thisClassNames.length-1];
- thisRow.find('input:eq(1)').removeClass(valueClass).addClass(originalValue).val(originalValue);
-
- if (thisValueField.length > 1){
- var originalValue = thisValueField[1].defaultValue;
- var thisClassNames = thisRow.find('input:eq(2)').attr('class').split(/\s+/);
- var valueClass = thisClassNames[thisClassNames.length-1];
- thisRow.find('input:eq(2)').removeClass(valueClass).addClass(originalValue).val(originalValue);
- }
- }
- for (i=1;i<=numOtherRows-1;i++){
- var thisRow = $('#Other_'+i);
- if (thisRow.is('.invisible')){
- thisRow.removeClass('invisible')
- }
- if (thisRow.is('.blocked')){
- thisRow.removeClass('blocked');
- }
- if (thisRow.is(':not(.outlier)')){
- thisRow.css("background-color", "white");
- }
-
- var thisValueField = thisRow.find('.valueField');
-
- var originalValue = thisValueField[0].defaultValue;
- var thisClassNames = thisRow.find('input:eq(1)').attr('class').split(/\s+/);
- var valueClass = thisClassNames[thisClassNames.length-1];
- thisRow.find('input:eq(1)').removeClass(valueClass).addClass(originalValue).val(originalValue);
-
- if (thisValueField.length > 1){
- var originalValue = thisValueField[1].defaultValue;
- var thisClassNames = thisRow.find('input:eq(2)').attr('class').split(/\s+/);
- var valueClass = thisClassNames[thisClassNames.length-1];
- thisRow.find('input:eq(2)').removeClass(valueClass).addClass(originalValue).val(originalValue);
- }
- }
- });
-
- var tiptext2 = "e.g., 4, 6-30, 43";
- var blockField = $('#showHideOptions').find('input[name=removeField]'); //ZS: Field where user inputs the index of the samples he/she wants to block; created variable because it's used often
-
- if(blockField.val() == '' || blockField.val() == tiptext2) {
- blockField.addClass('searchtip');
- blockField.val(tiptext2);
- }
-
- blockField.focus(function(e) {
- if(blockField.val() == tiptext2) {
- blockField.val('');
- }
- blockField.removeClass('searchtip');
- });
-
- blockField.blur(function(e) {
- if(blockField.val() == '') {
- blockField.addClass('searchtip');
- blockField.val(tiptext2);
- } else if(blockField.val() == tiptext2) {
- blockField.addClass('searchtip');
- } else {
- blockField.removeClass('searchtip');
- }
- });
-
- var noValShown = new Boolean(1);
- var outliersShown = new Boolean(1);
-
- $('#showHideOptions').bind('click', function(e){
- var target = e.target;
- $target = $(target);
-
- if (target.name === 'blockSamples'){
- if (blockField.val() == tiptext2){
- blockField.val('')
- }
- blockedText = blockField.val();
- blockedTextSplit = new Array();
- blockedItems = new Array();
-
- blockedTextSplit = blockedText.split(/\,/);
-
- for (i=0;i<=blockedTextSplit.length-1;i++) {
- var item = blockedTextSplit[i];
- if(item.indexOf('-') != -1){
- subArray = new Array();
- subArray = item.split('-');
- num1 = parseInt(subArray[0]);
- num2 = parseInt(subArray[1]);
- for (j=num1;j<=num2;j=j+1){
- blockedItems.push(j);
- }
- }
- else if(!(isNaN(item))) {
- blockedItems.push(item);
- }
- }
-
- for (i=0;i<=blockedItems.length-1;i++) {
- item = blockedItems[i];
- if ($('select[name=block_method]').val() == '0') {
- var thisRow = $('#Other_'+item);
- }
- else {
- var thisRow = $('#Primary_'+item);
- }
-
- if (thisRow.is('.novalue')) {
- continue;
- }
- else {
- thisRow.addClass('blocked').find('input.valueField').val('x');
- }
-
- //First look at value cell
- var thisCell = thisRow.find('input:eq(1)');
- var thisClassNames = thisCell.attr('class').split(/\s+/);
- var valueClass = thisClassNames[thisClassNames.length-1];
- var header = thisRow.parents('table.tablesorter').find('th.header:contains("Value"):eq(0)');
- if (header.hasClass('headerSortUp')){
- thisCell.removeClass(valueClass).addClass('-9999');
- } else if (header.hasClass('headerSortDown')){
- thisCell.removeClass(valueClass).addClass('9999');
- } else {
- thisCell.removeClass(valueClass).addClass('-9999');
- }
-
- //Check if there is an SE column
- if (thisRow.find('input.valueField').length > 1) {
- var thisCell = thisRow.find('input:eq(2)');
- var thisClassNames = thisCell.attr('class').split(/\s+/);
- var valueClass = thisClassNames[thisClassNames.length-1];
- var header = thisRow.parents('table.tablesorter').find('th.header:contains("SE"):eq(0)');
- if (header.hasClass('headerSortUp')){
- thisCell.removeClass(valueClass).addClass('-9999');
- } else if (header.hasClass('headerSortDown')){
- thisCell.removeClass(valueClass).addClass('9999');
- } else {
- thisCell.removeClass(valueClass).addClass('-9999');
- }
- }
- }
- }
-
- else if (target.name === 'showHideNoValue'){
- if (noValShown) {
- $('#showHideOptions').find('input[name=showHideNoValue]').val(' Show No Value ');
- for (i=1;i<=Math.max(numPrimaryRows,numOtherRows)-1;i++) {
- if (i<=numPrimaryRows-1) {
- var thisRow = $('#Primary_'+i);
- if (thisRow.is('.novalue:visible') || thisRow.is('.blocked:visible')){
- jQuery(thisRow).addClass('invisible');
- }
- }
- if (i<=numOtherRows-1){
- var thisOtherRow = $('#Other_'+i);
- if (thisOtherRow.is('.novalue:visible') || thisOtherRow.is('.blocked:visible')){
- if (thisOtherRow.is(':visible')){
- jQuery(thisOtherRow).addClass('invisible');
- }
- }
- }
- }
- noValShown = 0;
- }
- else {
- $('#showHideOptions').find('input[name=showHideNoValue]').val(' Hide No Value ');
- for (i=1;i<=Math.max(numPrimaryRows,numOtherRows)-1;i++) {
- if (i<=numPrimaryRows-1) {
- var thisRow = $('#Primary_'+i);
- if (thisRow.is('.novalue') || thisRow.is('.blocked')){
- jQuery(thisRow).removeClass('invisible');
- if (!(outliersShown)) {
- if (thisRow.is('.outlier:visible')){
- jQuery(thisRow).addClass('invisible');
- }
- }
- }
- }
- if (i<=numOtherRows-1){
- var thisOtherRow = $('#Other_'+i);
- if (thisOtherRow.is('.novalue') || thisOtherRow.is('.blocked')){
- jQuery(thisOtherRow).removeClass('invisible');
- if (!(outliersShown)) {
- if (thisOtherRow.is('.outlier:visible')){
- jQuery(thisOtherRow).addClass('invisible');
- }
- }
- }
- }
- }
- noValShown = 1;
- }
- }
-
- else if (target.name === 'showHideOutliers'){
- if (outliersShown){
- $('#showHideOptions').find('input[name=showHideOutliers]').val(' Show Outliers ');
- for (i=1;i<=Math.max(numPrimaryRows,numOtherRows)-1;i++) {
- if (i<=numPrimaryRows-1) {
- thisRow = $('#Primary_'+i);
- if (thisRow.is('.outlier:visible') && (!(thisRow.is('.invisible')))) {
- thisRow.addClass('invisible')
- }
- }
- if (i<=numOtherRows-1) {
- thisOtherRow = $('#Other_'+i);
- if (thisOtherRow.is('.outlier:visible') && (!(thisOtherRow.is('.invisible')))) {
- thisOtherRow.addClass('invisible')
- }
- }
- }
- outliersShown = 0;
- }
- else {
- $('#showHideOptions').find('input[name=showHideOutliers]').val(' Hide Outliers ');
- for (i=1;i<=Math.max(numPrimaryRows,numOtherRows)-1;i++) {
- if (i<=numPrimaryRows-1) {
- thisRow = $('#Primary_'+i);
- if (thisRow.is('.outlier') && (!(thisRow.is(':visible')))) {
- if (!(noValShown)) {
- if (thisRow.is('.blocked')){
- continue;
- }
- }
- jQuery(thisRow).removeClass('invisible')
- }
- }
- if (i<=numOtherRows-1) {
- thisOtherRow = $('#Other_'+i);
- if (thisOtherRow.is('.outlier') && (!(thisOtherRow.is(':visible')))) {
- if (!(noValShown)) {
- if (thisOtherRow.is('.blocked')){
- continue;
- }
- }
- jQuery(thisOtherRow).removeClass('invisible')
- }
- }
- }
- outliersShown = 1;
- }
- }
- return false;
- });
-});
-
-function getTraitData(){
- primary_row_count = $('#sortable1').find('tr').length - 1;
- other_row_count = $('#sortable2').find('tr').length - 1;
-
- primaryStrainNames = new Array();
- primaryVals = new Array();
- primaryVars = new Array();
-
- allStrainNames = new Array();
- allVals = new Array();
- allVars = new Array();
-
- for (i = 1;i <= primary_row_count; i++){
- thisRow = $('#Primary_'+i);
- strainName = thisRow.find('span:first').text();
- primaryStrainNames.push(strainName);
- allStrainNames.push(strainName);
- strainVal = thisRow.find('input:eq(1)').val();
- primaryVals.push(strainVal);
- allVals.push(strainVal);
- strainVar = ''; // Just to initialize it in case there is no var
- strainVar = thisRow.find('input:eq(2)').val();
- primaryVars.push(strainVar);
- allVars.push(strainVar);
- }
-
- otherStrainNames = new Array();
- otherVals = new Array();
- otherVars = new Array();
-
- for (j = 1;j <= other_row_count; j++){
- thisRow = $('#Other_'+j)
- strainName = thisRow.find('span:first').text();
- otherStrainNames.push(strainName);
- strainVal = thisRow.find('input:eq(1)').val();
- otherVals.push(strainVal);
- strainVar = ''; // Just to initialize it in case there is no var
- strainVar = thisRow.find('input:eq(2)').val();
- otherVars.push(strainVar);
-
- if (jQuery.inArray(strainName, allStrainNames) == -1) {
- allStrainNames.push(strainName);
- allVals.push(strainVal);
- allVars.push(strainVar);
- }
- }
-
- primaryData = [primaryStrainNames, primaryVals, primaryVars];
- otherData = [otherStrainNames, otherVals, otherVars];
- allData = [allStrainNames, allVals, allVars];
-
- return [primaryData, otherData, allData];
-}
+ var thisTable = $('#sortable1,#sortable2');
+ thisTable.bind("update propertychange keyup input paste", function (e) {
-/*
-used by networkGraphPageBody.py
-*/
+ var target = e.target;
+ $target = $(target);
-//Default to plain text + symbol for the "Export Graph File" button
-$('input[name=exportGraphFile]').live('click', function() { window.open($('input[name=exportFilename]').val() + "_plain_symbol.txt") });
+ if (target.nodeName.toLowerCase() == 'input') {
+ thisClassNames = $target.attr('class').split(/\s+/);
+ valueClass = thisClassNames[thisClassNames.length - 1];
+ newValue = $target.val();
+ thisParent = $target.parent('td');
+ thisParentId = thisParent.attr('id');
+
+ $target.removeClass(valueClass);
+
+ if (newValue == 'x') {
+ thisParent.parent('tr').addClass('blocked');
+ } else {
+ $('#' + thisParentId).children('input.valueField:eq(0)').addClass(newValue);
+ }
+ }
+ });
+
+ ////////////////////////////////////
+ // Initially close tabs
+ ////////////////////////////////////
+ thisForm = $('form[name="dataInput"]');
+
+ $('#sectionbody2').hide();
+ $('#sectionbody3').hide();
+ $('#sectionbody4').hide();
+
+ $('#title1').click(function () {
+ $('#sectionbody1').toggle();
+ return false;
+ });
+ $('#title2').click(function () {
+ $('#sectionbody2').toggle();
+ return false;
+ });
+ $('#title3').click(function () {
+ $('#sectionbody3').toggle();
+ return false;
+ });
+ $('#title4').click(function () {
+ $('#sectionbody4').toggle();
+ return false;
+ });
+ $('#title5').click(function () {
+ $('#sectionbody5').toggle();
+ return false;
+ });
-function changeFormat(graphName){
- var graphFormat = $('#exportFormat').val();
- var traitType = $('#traitType').val();
- $('input[name=exportGraphFile]').die('click');
- if (graphFormat=="xgmml"){
- if (traitType=="symbol"){
- var graphFile = graphName+ "_xgmml_symbol.txt";
- $('input[name=exportGraphFile]').live('click', function() { window.open(graphFile) });
+ //////////////////////////////////////////////////////////////
+ // Switch out + and - icon when you click each section header
+ //////////////////////////////////////////////////////////////
+ var expand_html = "";
+ var contract_html = "";
+
+ $('#title2, #title3, #title4').prepend(expand_html).addClass('1');
+
+ $('#title1, #title5').prepend(contract_html).addClass('0');
+
+ for (i = 1; i <= 5; i++) {
+ $('#title' + i).click(function () {
+ if ($(this).hasClass('0')) {
+ $(this).find('span').replaceWith(expand_html);
+ $(this).removeClass('0');
+ $(this).addClass('1');
+ } else {
+ $(this).find('span').replaceWith(contract_html);
+ $(this).removeClass('1');
+ $(this).addClass('0');
+ }
+ });
+ }
+
+ // Exclude cases by attributes
+ $('div.attribute_values:first').css('display', 'inline'); //Display the dropdown menu with the first attribute's distinct values
+ $('select[name=exclude_menu]').change(function () {
+ $('div.attribute_values').css('display', 'none'); //clear all other menus when a new attribute is selected
+ attribute = $(this).val();
+ //attribute = $('select[name=exclude_menu]').val();
+ menu = $('div.attribute_values').find('[name=\'' + attribute + '\']');
+ menu.parent().css('display', 'inline');
+ });
+
+ primary_row_count = $('#primary').find('tr').length - 1;
+ other_row_count = $('#other').find('tr').length - 1;
+
+ if (primary_row_count >= other_row_count) {
+ row_count = primary_row_count;
+ } else {
+ row_count = other_row_count;
+ }
+
+ $('div.attribute_values').children('select').change(function () {
+ exclude_value = $(this).val();
+ });
+});
+
+$(window).load(function () {
+
+ //ZS: These are needed in a few places; looping through rows by index is faster than doing a "find" search
+ numPrimaryRows = $('#sortable1').find('tr').length;
+ numOtherRows = $('#sortable2').find('tr').length;
+
+
+ ///////////////////////////////
+ //Basic Statistics
+ ///////////////////////////////
+ /////////////////////////////////////////////////////////////////
+ // Hide unselected Basic Statistics tabs (when just BXD strains
+ // are selected, hide the results for all strains/non-BXD)
+ /////////////////////////////////////////////////////////////////
+ $('#stats_tabs1').hide();
+ $('#stats_tabs2').hide();
+
+ $('#sectionbody2').find('select[name=stats_mdp]').change(function () {
+ selected = $('#sectionbody2').find('select[name=stats_mdp] option:selected').val();
+ for (i = 0; i <= 2; i++) {
+ $('#stats_tabs' + i).hide();
+ }
+ $('#stats_tabs' + selected).show();
+ });
+
+ ////////////////////////////////////////////////////////////////////////
+ // Select the same tab across each sample group (when a Box Plot is
+ // selected for BXD, switching to Non-BXD will also display a Box Plot)
+ ////////////.///////////////////////////////////////////////////////////
+ var $tabs1 = $('#stats_tabs0').tabs();
+ var $tabs2 = $('#stats_tabs1').tabs();
+ var $tabs3 = $('#stats_tabs2').tabs();
+
+ $tabs1.tabs({
+ show: function (event, ui) {
+ var selected = $tabs1.tabs('option', 'selected');
+ $tabs2.tabs('select', selected);
+ $tabs3.tabs('select', selected);
+ }
+ });
+ $tabs2.tabs({
+ show: function (event, ui) {
+ var selected = $tabs2.tabs('option', 'selected');
+ $tabs1.tabs('select', selected);
+ $tabs3.tabs('select', selected);
+ }
+ });
+ $tabs3.tabs({
+ show: function (event, ui) {
+ var selected = $tabs3.tabs('option', 'selected');
+ $tabs1.tabs('select', selected);
+ $tabs2.tabs('select', selected);
+ }
+ });
+
+
+ ///////////////////////////////
+ //Calculate Correlations
+ ///////////////////////////////
+ $('#sectionbody3').find('input[name="sample_corr"]').click(function () {
+ dbValue = $('select[name=database1] option:selected').val();
+ $('input[name=database]').val(dbValue);
+ criteriaValue = $('select[name=criteria1] option:selected').val();
+ $('input[name=criteria]').val(criteriaValue);
+ MDPValue = $('select[name=MDPChoice1] option:selected').val();
+ $('input[name=MDPChoice]').val(MDPValue);
+
+ methodValue = $('input[name=sample_method]:checked').val();
+
+ //This simple method can be used now that 'method' is defaulted to None instead of ''
+ if (methodValue == "1") {
+ $('input[name=method]').val('1');
+ } else {
+ $('input[name=method]').val('2');
+ }
+
+ dataEditingFunc(this.form, 'correlation');
+ });
+
+ $('#sectionbody3').find('input[name="lit_corr"]').click(function () {
+ dbValue = $('select[name=database2] option:selected').val();
+ $('input[name=database]').val(dbValue);
+ criteriaValue = $('select[name=criteria2] option:selected').val();
+ $('input[name=criteria]').val(criteriaValue);
+ MDPValue = $('select[name=MDPChoice2] option:selected').val();
+ $('input[name=MDPChoice]').val(MDPValue);
+
+ $('input[name=method]').val('3');
+
+ dataEditingFunc(this.form, 'correlation');
+ });
+
+ $('#sectionbody3').find('input[name="tiss_corr"]').click(function () {
+ dbValue = $('select[name=database3] option:selected').val();
+ $('input[name=database]').val(dbValue);
+ criteriaValue = $('select[name=criteria3] option:selected').val();
+ $('input[name=criteria]').val(criteriaValue);
+ MDPValue = $('select[name=MDPChoice3] option:selected').val();
+ $('input[name=MDPChoice]').val(MDPValue);
+
+ methodValue = $('input[name=tissue_method]:checked').val();
+
+ if (methodValue == "4") {
+ $('input[name=method]').val('4');
+ } else {
+ $('input[name=method]').val('5');
+ }
+ dataEditingFunc(this.form, 'correlation');
+ });
+
+ ///////////////////////////////
+ //Mapping Tools
+ ///////////////////////////////
+ $('#sectionbody4').find('input[name=interval]').click(function () {
+ chrValue = $('select[name=chromosomes1] option:selected').val();
+ $('input[name=chromosomes]').val(chrValue);
+ scaleValue = $('select[name=scale1] option:selected').val();
+ $('input[name=scale]').val(scaleValue);
+ $('input[name=controlLocus]').val('');
+
+ //Changed the way permValue, bootValue, and parentsValue are acquired; before it was $(____).is(':checked');
+ permValue = $('input[name=permCheck1]:checked').val();
+ $('input[name=permCheck]').val(permValue);
+
+ bootValue = $('input[name=bootCheck1]:checked').val();
+ $('input[name=bootCheck]').val(bootValue);
+
+ if ($('input[name=parentsf14regression1]:checked').length > 0) {
+ $('input[name=parentsf14regression]').val('on');
+ } else {
+ $('input[name=parentsf14regression]').val('off');
+ }
+
+ varValue = $('input[name=applyVarianceSE1]:checked').val();
+ $('input[name=applyVarianceSE]').val(varValue);
+
+ dataEditingFunc(this.form, 'intervalMap');
+ });
+
+ var tiptext = "e.g., rs12345";
+ controlLocus = $('#sectionbody4').find('input[name=controlLocus]');
+
+ if (controlLocus.val() == '' || controlLocus == tiptext) {
+ controlLocus.addClass('searchtip').val(tiptext);
+ }
+
+ controlLocus.focus(function (e) {
+ if (controlLocus.val() == tiptext) {
+ controlLocus.val('');
+ }
+ controlLocus.removeClass('searchtip');
+ });
+
+ controlLocus.blur(function (e) {
+ if (controlLocus.val() == '') {
+ controlLocus.addClass('searchtip').val(tiptext);
+ } else if (controlLocus.val() == tiptext) {
+ controlLocus.addClass('searchtip');
+ } else {
+ controlLocus.removeClass('searchtip');
+ }
+ });
+
+ $('#sectionbody4').find('input[name=composite]').click(function () {
+ chrValue = $('select[name=chromosomes2] option:selected').val();
+ $('input[name=chromosomes]').val(chrValue);
+ scaleValue = $('select[name=scale2] option:selected').val();
+ $('input[name=scale]').val(scaleValue);
+ controlValue = controlLocus.val();
+ if (controlValue != tiptext) {
+ controlLocus.val(controlValue);
+ } else {
+ controlLocus.val('');
+ }
+
+ //Changed the way permValue, bootValue, and parentsValue are acquired; before it was $(____).is(':checked');
+ permValue = $('input[name=permCheck2]:checked').val();
+ $('input[name=permCheck]').val(permValue);
+
+ bootValue = $('input[name=bootCheck2]:checked').val();
+ $('input[name=bootCheck]').val(bootValue);
+
+ if ($('input[name=parentsf14regression3]:checked').length > 0) {
+ $('input[name=parentsf14regression]').val('on');
+ } else {
+ $('input[name=parentsf14regression]').val('off');
+ }
+
+ dataEditingFunc(this.form, 'intervalMap');
+
+ });
+
+ $('#sectionbody4').find('input[name=marker]').click(function () {
+ //Changed the way parentsValue is acquired; before it was $(____).is(':checked');
+ if ($('input[name=parentsf14regression2]:checked').length > 0) {
+ $('input[name=parentsf14regression]').val('on');
+ } else {
+ $('input[name=parentsf14regression]').val('off');
+ }
+
+ varValue = $('input[name=applyVarianceSE2]:checked').val();
+ $('input[name=applyVarianceSE]').val(varValue);
+
+ dataEditingFunc(this.form, 'markerRegression');
+ });
+
+ ///////////////////////////////
+ //Review and Edit Data
+ ///////////////////////////////
+ $('input[name=excludeGroup]').click(function () {
+ for (i = 1; i <= Math.max(primary_row_count, other_row_count) - 1; i++) {
+ valueExists = 0;
+ $('#Primary_' + i + ',#Other_' + i).children().each(function () {
+ if ($(this).text() == exclude_value) {
+ $('#Primary_' + i + ',#Other_' + i).addClass('blocked').find('input[type=text]').val('x');
+ valueExists = 1;
+ return false;
}
- else if (traitType=="name"){
- var graphFile = graphName+ "_xgmml_name.txt";
- $('input[name=exportGraphFile]').live('click', function() { window.open(graphFile) });
+ });
+ }
+ });
+
+ $('.update').click(function () {
+ windowName = 'formTarget' + (new Date().getTime());
+ var windowHeight; // windowHeight and windowWidth are used to place the window in the center of the screen
+ var windowWidth;
+ windowHeight = (window.screen.height/2) - (350 + 10)
+ windowWidth = (window.screen.width/2) - (450 + 50)
+ newWindow = open("",windowName,"menubar=1,toolbar=1,resizable=1,left=" + windowWidth + ",top=" + windowHeight + ",screenX=" + windowWidth + ",screenY=" + windowHeight + ",status=1,scrollbars=0,directories=1");
+
+ document.dataInput.target = windowName;
+ document.dataInput.submitID.value = "basicStatistics";
+
+ primaryData = getTraitData()[0];
+ otherData = getTraitData()[1];
+ allData = getTraitData()[2];
+
+ if (otherData[0].length > 0) {
+ if ($('select[name="stats_mdp"] option:selected').val() == 0) {
+ document.dataInput.strainNames.value = allData[0].toString();
+ document.dataInput.strainVals.value = allData[1].toString();
+ document.dataInput.strainVars.value = allData[2].toString();
+ } else if ($('select[name="stats_mdp"] option:selected').val() == 1) {
+ document.dataInput.strainNames.value = primaryData[0].toString();
+ document.dataInput.strainVals.value = primaryData[1].toString();
+ document.dataInput.strainVars.value = primaryData[2].toString();
+ } else {
+ document.dataInput.strainNames.value = otherData[0].toString();
+ document.dataInput.strainVals.value = otherData[1].toString();
+ document.dataInput.strainVars.value = otherData[2].toString();
+ }
+ } else {
+ document.dataInput.strainNames.value = allData[0].toString();
+ document.dataInput.strainVals.value = allData[1].toString();
+ document.dataInput.strainVars.value = allData[2].toString();
+ }
+
+ document.dataInput.submit();
+ });
+
+ $('input[name="export"]').click(function () {
+ windowName = 'formTarget' + (new Date().getTime());
+ newWindow = open("", windowName, "menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=0,directories=1,width=900");
+ document.dataInput.target = windowName;
+ document.dataInput.submitID.value = "exportData";
+
+ primaryData = getTraitData()[0];
+ otherData = getTraitData()[1];
+
+ document.dataInput.strainNames.value = primaryData[0].toString();
+ document.dataInput.strainVals.value = primaryData[1].toString();
+ document.dataInput.strainVars.value = primaryData[2].toString();
+
+ document.dataInput.otherStrainNames.value = otherData[0].toString();
+ document.dataInput.otherStrainVals.value = otherData[1].toString();
+ document.dataInput.otherStrainVars.value = otherData[2].toString();
+
+ attribute_names = new Array();
+ $('#primary,#other').find('th.attribute_name').each(function () {
+ attribute_names.push($(this).val().toString());
+ });
+
+ primary_attribute_values = ""; //This string will be structured as a dictionary with a set of values for each attribute; it will be parsed in the ExportPage class
+ other_attribute_values = "";
+
+ attr_counter = 1; // Counter for each different attribute
+ row_counter = 1; // Counter for each value for each attribute
+ while (attr_counter <= attribute_names.length) {
+ attribute_name = $('#primary,#other').find('th.attribute_name:eq(' + (attr_counter - 1).toString() + ')').text();
+ primary_row_count = $('#primary').find('tr').length - 1;
+ other_row_count = $('#other').find('tr').length - 1;
+
+ primary_attribute_values += attribute_name + " : ";
+ other_attribute_values += attribute_name + " : ";
+
+ primary_value_string = ""; //This string of values (in the format 'a,b,c', etc) will be appended to the primary_attribute_values string
+ for (row_counter = 1; row_counter <= numPrimaryRows; row_counter++) {
+ value = $('#primary_attribute' + attr_counter.toString() + '_sample' + row_counter.toString()).text();
+ if (row_counter == primary_row_count) {
+ primary_value_string += (value + " / ");
+ } else {
+ primary_value_string += (value + ",");
}
+ }
+
+ primary_attribute_values += primary_value_string;
+
+ other_value_string = ""; //This string of values (in the format 'a,b,c', etc) will be appended to the other_attribute_values string
+ for (row_counter = 1; row_counter <= numOtherRows; row_counter++) {
+ value = $('#other_attribute' + attr_counter.toString() + '_sample' + row_counter.toString()).text();
+ if (row_counter == other_row_count) {
+ other_value_string += (value + " / ");
+ } else {
+ other_value_string += (value + ",");
+ }
+ }
+ other_attribute_values += other_value_string;
+ attr_counter += 1
+ }
+
+ document.dataInput.extra_attributes.value = primary_attribute_values;
+ document.dataInput.other_extra_attributes.value = other_attribute_values;
+
+ document.dataInput.submit();
+ });
+
+ var thisTable = $('#sortable1,#sortable2'); //ZS: variable representing each table, because it's used often
+ thisTable.find('input[name="selectCheck"]').click(function () {
+ if ($(this).is(':checked')) {
+ $(this).parent("").parent("").children("td").css("background-color", "yellow");
+ } else {
+ if (!($(this).parent().parent().hasClass('outlier'))) {
+ $(this).parent().parent().children("td").css("background-color", "white");
+ }
}
+ });
- else if (graphFormat=="plain"){
- if (traitType=="symbol"){
- var graphFile = graphName+ "_plain_symbol.txt";
- $('input[name=exportGraphFile]').live('click', function() { window.open(graphFile) });
+ $('input[name=resetButton]').click(function () {
+
+ //ZS: Reset "hide no value" and "hide outliers"
+ $('#showHideOptions').find('input[name=showHideNoValue]').val(' Hide No Value ');
+ $('#showHideOptions').find('input[name=showHideOutliers]').val(' Hide Outliers ');
+ noValShown = 1;
+ outliersShown = 1;
+
+ for (i = 1; i <= numPrimaryRows - 1; i++) {
+ var thisRow = $('#Primary_' + i);
+ if (thisRow.is('.invisible')) {
+ thisRow.removeClass('invisible');
+ }
+ if (thisRow.is('.blocked')) {
+ thisRow.removeClass('blocked');
+ }
+ if (thisRow.is(':not(.outlier)')) {
+ thisRow.css("background-color", "white");
+ }
+
+ var thisValueField = thisRow.find('.valueField');
+
+ var originalValue = thisValueField[0].defaultValue;
+ var thisClassNames = thisRow.find('input:eq(1)').attr('class').split(/\s+/);
+ var valueClass = thisClassNames[thisClassNames.length - 1];
+ thisRow.find('input:eq(1)').removeClass(valueClass).addClass(originalValue).val(originalValue);
+
+ if (thisValueField.length > 1) {
+ var originalValue = thisValueField[1].defaultValue;
+ var thisClassNames = thisRow.find('input:eq(2)').attr('class').split(/\s+/);
+ var valueClass = thisClassNames[thisClassNames.length - 1];
+ thisRow.find('input:eq(2)').removeClass(valueClass).addClass(originalValue).val(originalValue);
+ }
+ }
+ for (i = 1; i <= numOtherRows - 1; i++) {
+ var thisRow = $('#Other_' + i);
+ if (thisRow.is('.invisible')) {
+ thisRow.removeClass('invisible')
+ }
+ if (thisRow.is('.blocked')) {
+ thisRow.removeClass('blocked');
+ }
+ if (thisRow.is(':not(.outlier)')) {
+ thisRow.css("background-color", "white");
+ }
+
+ var thisValueField = thisRow.find('.valueField');
+
+ var originalValue = thisValueField[0].defaultValue;
+ var thisClassNames = thisRow.find('input:eq(1)').attr('class').split(/\s+/);
+ var valueClass = thisClassNames[thisClassNames.length - 1];
+ thisRow.find('input:eq(1)').removeClass(valueClass).addClass(originalValue).val(originalValue);
+
+ if (thisValueField.length > 1) {
+ var originalValue = thisValueField[1].defaultValue;
+ var thisClassNames = thisRow.find('input:eq(2)').attr('class').split(/\s+/);
+ var valueClass = thisClassNames[thisClassNames.length - 1];
+ thisRow.find('input:eq(2)').removeClass(valueClass).addClass(originalValue).val(originalValue);
+ }
+ }
+ });
+
+ var tiptext2 = "e.g., 4, 6-30, 43";
+ var blockField = $('#showHideOptions').find('input[name=removeField]'); //ZS: Field where user inputs the index of the samples he/she wants to block; created variable because it's used often
+ if (blockField.val() == '' || blockField.val() == tiptext2) {
+ blockField.addClass('searchtip');
+ blockField.val(tiptext2);
+ }
+
+ blockField.focus(function (e) {
+ if (blockField.val() == tiptext2) {
+ blockField.val('');
+ }
+ blockField.removeClass('searchtip');
+ });
+
+ blockField.blur(function (e) {
+ if (blockField.val() == '') {
+ blockField.addClass('searchtip');
+ blockField.val(tiptext2);
+ } else if (blockField.val() == tiptext2) {
+ blockField.addClass('searchtip');
+ } else {
+ blockField.removeClass('searchtip');
+ }
+ });
+
+ var noValShown = new Boolean(1);
+ var outliersShown = new Boolean(1);
+
+ $('#showHideOptions').bind('click', function (e) {
+ var target = e.target;
+ $target = $(target);
+
+ if (target.name === 'blockSamples') {
+ if (blockField.val() == tiptext2) {
+ blockField.val('')
+ }
+ blockedText = blockField.val();
+ blockedTextSplit = new Array();
+ blockedItems = new Array();
+
+ blockedTextSplit = blockedText.split(/\,/);
+
+ for (i = 0; i <= blockedTextSplit.length - 1; i++) {
+ var item = blockedTextSplit[i];
+ if (item.indexOf('-') != -1) {
+ subArray = new Array();
+ subArray = item.split('-');
+ num1 = parseInt(subArray[0]);
+ num2 = parseInt(subArray[1]);
+ for (j = num1; j <= num2; j = j + 1) {
+ blockedItems.push(j);
+ }
+ } else if (!(isNaN(item))) {
+ blockedItems.push(item);
+ }
+ }
+
+ for (i = 0; i <= blockedItems.length - 1; i++) {
+ item = blockedItems[i];
+ if ($('select[name=block_method]').val() == '0') {
+ var thisRow = $('#Other_' + item);
+ } else {
+ var thisRow = $('#Primary_' + item);
+ }
+
+ if (thisRow.is('.novalue')) {
+ continue;
+ } else {
+ thisRow.addClass('blocked').find('input.valueField').val('x');
+ }
+
+ //First look at value cell
+ var thisCell = thisRow.find('input:eq(1)');
+ var thisClassNames = thisCell.attr('class').split(/\s+/);
+ var valueClass = thisClassNames[thisClassNames.length - 1];
+ var header = thisRow.parents('table.tablesorter').find('th.header:contains("Value"):eq(0)');
+ if (header.hasClass('headerSortUp')) {
+ thisCell.removeClass(valueClass).addClass('-9999');
+ } else if (header.hasClass('headerSortDown')) {
+ thisCell.removeClass(valueClass).addClass('9999');
+ } else {
+ thisCell.removeClass(valueClass).addClass('-9999');
+ }
+
+ //Check if there is an SE column
+ if (thisRow.find('input.valueField').length > 1) {
+ var thisCell = thisRow.find('input:eq(2)');
+ var thisClassNames = thisCell.attr('class').split(/\s+/);
+ var valueClass = thisClassNames[thisClassNames.length - 1];
+ var header = thisRow.parents('table.tablesorter').find('th.header:contains("SE"):eq(0)');
+ if (header.hasClass('headerSortUp')) {
+ thisCell.removeClass(valueClass).addClass('-9999');
+ } else if (header.hasClass('headerSortDown')) {
+ thisCell.removeClass(valueClass).addClass('9999');
+ } else {
+ thisCell.removeClass(valueClass).addClass('-9999');
+ }
+ }
+ }
+ } else if (target.name === 'showHideNoValue') {
+ if (noValShown) {
+ $('#showHideOptions').find('input[name=showHideNoValue]').val(' Show No Value ');
+ for (i = 1; i <= Math.max(numPrimaryRows, numOtherRows) - 1; i++) {
+ if (i <= numPrimaryRows - 1) {
+ var thisRow = $('#Primary_' + i);
+ if (thisRow.is('.novalue:visible') || thisRow.is('.blocked:visible')) {
+ jQuery(thisRow).addClass('invisible');
+ }
+ }
+ if (i <= numOtherRows - 1) {
+ var thisOtherRow = $('#Other_' + i);
+ if (thisOtherRow.is('.novalue:visible') || thisOtherRow.is('.blocked:visible')) {
+ if (thisOtherRow.is(':visible')) {
+ jQuery(thisOtherRow).addClass('invisible');
+ }
+ }
+ }
+ }
+ noValShown = 0;
+ } else {
+ $('#showHideOptions').find('input[name=showHideNoValue]').val(' Hide No Value ');
+ for (i = 1; i <= Math.max(numPrimaryRows, numOtherRows) - 1; i++) {
+ if (i <= numPrimaryRows - 1) {
+ var thisRow = $('#Primary_' + i);
+ if (thisRow.is('.novalue') || thisRow.is('.blocked')) {
+ jQuery(thisRow).removeClass('invisible');
+ if (!(outliersShown)) {
+ if (thisRow.is('.outlier:visible')) {
+ jQuery(thisRow).addClass('invisible');
+ }
+ }
+ }
+ }
+ if (i <= numOtherRows - 1) {
+ var thisOtherRow = $('#Other_' + i);
+ if (thisOtherRow.is('.novalue') || thisOtherRow.is('.blocked')) {
+ jQuery(thisOtherRow).removeClass('invisible');
+ if (!(outliersShown)) {
+ if (thisOtherRow.is('.outlier:visible')) {
+ jQuery(thisOtherRow).addClass('invisible');
+ }
+ }
+ }
+ }
}
- else if (traitType=="name"){
- var graphFile = graphName+ "_plain_name.txt";
- $('input[name=exportGraphFile]').live('click', function() { window.open(graphFile) });
+ noValShown = 1;
+ }
+ } else if (target.name === 'showHideOutliers') {
+ if (outliersShown) {
+ $('#showHideOptions').find('input[name=showHideOutliers]').val(' Show Outliers ');
+ for (i = 1; i <= Math.max(numPrimaryRows, numOtherRows) - 1; i++) {
+ if (i <= numPrimaryRows - 1) {
+ thisRow = $('#Primary_' + i);
+ if (thisRow.is('.outlier:visible') && (!(thisRow.is('.invisible')))) {
+ thisRow.addClass('invisible')
+ }
+ }
+ if (i <= numOtherRows - 1) {
+ thisOtherRow = $('#Other_' + i);
+ if (thisOtherRow.is('.outlier:visible') && (!(thisOtherRow.is('.invisible')))) {
+ thisOtherRow.addClass('invisible')
+ }
+ }
+ }
+ outliersShown = 0;
+ } else {
+ $('#showHideOptions').find('input[name=showHideOutliers]').val(' Hide Outliers ');
+ for (i = 1; i <= Math.max(numPrimaryRows, numOtherRows) - 1; i++) {
+ if (i <= numPrimaryRows - 1) {
+ thisRow = $('#Primary_' + i);
+ if (thisRow.is('.outlier') && (!(thisRow.is(':visible')))) {
+ if (!(noValShown)) {
+ if (thisRow.is('.blocked')) {
+ continue;
+ }
+ }
+ jQuery(thisRow).removeClass('invisible')
+ }
+ }
+ if (i <= numOtherRows - 1) {
+ thisOtherRow = $('#Other_' + i);
+ if (thisOtherRow.is('.outlier') && (!(thisOtherRow.is(':visible')))) {
+ if (!(noValShown)) {
+ if (thisOtherRow.is('.blocked')) {
+ continue;
+ }
+ }
+ jQuery(thisOtherRow).removeClass('invisible')
+ }
+ }
}
+ outliersShown = 1;
+ }
+ }
+ return false;
+ });
+});
+
+function getTraitData() {
+ primary_row_count = $('#sortable1').find('tr').length - 1;
+ other_row_count = $('#sortable2').find('tr').length - 1;
+
+ primaryStrainNames = new Array();
+ primaryVals = new Array();
+ primaryVars = new Array();
+
+ allStrainNames = new Array();
+ allVals = new Array();
+ allVars = new Array();
+
+ for (i = 1; i <= primary_row_count; i++) {
+ thisRow = $('#Primary_' + i);
+ strainName = thisRow.find('span:first').text();
+ primaryStrainNames.push(strainName);
+ allStrainNames.push(strainName);
+ strainVal = thisRow.find('input:eq(1)').val();
+ primaryVals.push(strainVal);
+ allVals.push(strainVal);
+ strainVar = ''; // Just to initialize it in case there is no var
+ strainVar = thisRow.find('input:eq(2)').val();
+ primaryVars.push(strainVar);
+ allVars.push(strainVar);
+ }
+
+ otherStrainNames = new Array();
+ otherVals = new Array();
+ otherVars = new Array();
+
+ for (j = 1; j <= other_row_count; j++) {
+ thisRow = $('#Other_' + j)
+ strainName = thisRow.find('span:first').text();
+ otherStrainNames.push(strainName);
+ strainVal = thisRow.find('input:eq(1)').val();
+ otherVals.push(strainVal);
+ strainVar = ''; // Just to initialize it in case there is no var
+ strainVar = thisRow.find('input:eq(2)').val();
+ otherVars.push(strainVar);
+
+ if (jQuery.inArray(strainName, allStrainNames) == -1) {
+ allStrainNames.push(strainName);
+ allVals.push(strainVal);
+ allVars.push(strainVar);
}
+ }
+
+ primaryData = [primaryStrainNames, primaryVals, primaryVars];
+ otherData = [otherStrainNames, otherVals, otherVars];
+ allData = [allStrainNames, allVals, allVars];
+
+ return [primaryData, otherData, allData];
}
+/*
+used by networkGraphPageBody.py
+*/
+
+//Default to plain text + symbol for the "Export Graph File" button
+$('input[name=exportGraphFile]').live('click', function () {
+ window.open($('input[name=exportFilename]').val() + "_plain_symbol.txt")
+});
+
+function changeFormat(graphName) {
+ var graphFormat = $('#exportFormat').val();
+ var traitType = $('#traitType').val();
+
+ $('input[name=exportGraphFile]').die('click');
+
+ if (graphFormat == "xgmml") {
+ if (traitType == "symbol") {
+ var graphFile = graphName + "_xgmml_symbol.txt";
+ $('input[name=exportGraphFile]').live('click', function () {
+ window.open(graphFile)
+ });
+ } else if (traitType == "name") {
+ var graphFile = graphName + "_xgmml_name.txt";
+ $('input[name=exportGraphFile]').live('click', function () {
+ window.open(graphFile)
+ });
+ }
+ } else if (graphFormat == "plain") {
+ if (traitType == "symbol") {
+ var graphFile = graphName + "_plain_symbol.txt";
+ $('input[name=exportGraphFile]').live('click', function () {
+ window.open(graphFile)
+ });
+ } else if (traitType == "name") {
+ var graphFile = graphName + "_plain_name.txt";
+ $('input[name=exportGraphFile]').live('click', function () {
+ window.open(graphFile)
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/webqtl/correlation/CorrelationPage.py b/web/webqtl/correlation/CorrelationPage.py
index 8ce669cb..1fd16021 100755
--- a/web/webqtl/correlation/CorrelationPage.py
+++ b/web/webqtl/correlation/CorrelationPage.py
@@ -23,6 +23,9 @@
# Created by GeneNetwork Core Team 2010/08/10
#
# Last updated by NL 2011/02/11
+# Last updated by Christian Fernandez 2012/04/07
+# Refactored correlation calculation into smaller functions in preparation of
+# separating html from existing code
import string
from math import *
@@ -47,447 +50,324 @@ from dbFunction import webqtlDatabaseFunction
import utility.webqtlUtil #this is for parallel computing only.
from correlation import correlationFunction
+import logging
+logging.basicConfig(filename="/tmp/gn_log", level=logging.INFO)
+_log = logging.getLogger("correlation")
-class CorrelationPage(templatePage):
+METHOD_SAMPLE_PEARSON = "1"
+METHOD_SAMPLE_RANK = "2"
+METHOD_LIT = "3"
+METHOD_TISSUE_PEARSON = "4"
+METHOD_TISSUE_RANK = "5"
- corrMinInformative = 4
+TISSUE_METHODS = [METHOD_TISSUE_PEARSON, METHOD_TISSUE_RANK]
- def __init__(self, fd):
+TISSUE_MOUSE_DB = 1
- #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):
+class AuthException(Exception): pass
- 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 "
+class Trait(object):
+ def __init__(self, name, raw_values = None, lit_corr = None, tissue_corr = None, p_tissue = None):
+ self.name = name
+ self.raw_values = raw_values
+ self.lit_corr = lit_corr
+ self.tissue_corr = tissue_corr
+ self.p_tissue = p_tissue
+ self.correlation = 0
+ self.p_value = 0
- traitdataName = tokens[0]
- database_trait = tokens[1:]
+ @staticmethod
+ def from_csv(line, data_start = 1):
+ name = line[0]
+ numbers = line[data_start:]
+ # _log.info(numbers)
+ numbers = [ float(number) for number in numbers ]
- 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 Trait(name, raw_values = numbers)
- return allcorrelations
+ def calculate_correlation(self, values, method):
+ """Calculate the correlation value and p value according to the method specified"""
+ #ZS: This takes the list of values of the trait our selected trait is being correlated against and removes the values of the samples our trait has no value for
+ #There's probably a better way of dealing with this, but I'll have to ask Christian
+ updated_raw_values = []
+ updated_values = []
+ for i in range(len(values)):
+ if values[i] != "None":
+ updated_raw_values.append(self.raw_values[i])
+ updated_values.append(values[i])
- templatePage.__init__(self, fd)
+ self.raw_values = updated_raw_values
+ values = updated_values
- if not self.openMysql():
- return
-
- if not fd.genotype:
- fd.readGenotype()
+ if method == METHOD_SAMPLE_PEARSON or method == METHOD_LIT or method == METHOD_TISSUE_PEARSON:
+ corr,nOverlap = webqtlUtil.calCorrelation(self.raw_values, values, len(values))
+ else:
+ corr,nOverlap = webqtlUtil.calCorrelationRank(self.raw_values, values, len(values))
- #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"
+ self.correlation = corr
+ self.overlap = nOverlap
+
+ if self.overlap < 3:
+ self.p_value = 1.0
+ else:
+ #ZS - This is probably the wrong way to deal with this. Correlation values of 1.0 definitely exist (the trait correlated against itself), so zero division needs to br prevented.
+ if abs(self.correlation) >= 1.0:
+ self.p_value = 0.0
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()
+ ZValue = 0.5*log((1.0+self.correlation)/(1.0-self.correlation))
+ ZValue = ZValue*sqrt(self.overlap-3)
+ self.p_value = 2.0*(1.0 - reaper.normp(abs(ZValue)))
- #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')
+#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
+
+def get_correlation_method_key(form_data):
+ #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.
+
+ method = form_data.formdata.getvalue("method")
+ if method not in ["1", "2", "3" ,"4", "5"]:
+ return "1"
+
+ return method
+
+
+def get_custom_trait(form_data, cursor):
+ """Pulls the custom trait, if it exists, out of the form data"""
+ trait_name = form_data.formdata.getvalue('fullname')
+
+ if trait_name:
+ trait = webqtlTrait(fullname=trait_name, cursor=cursor)
+ trait.retrieveInfo()
+ return trait
+ else:
+ return None
+
+
+#XZ, 09/18/2008: get the information such as value, variance of the input strain names from the form.
+def get_sample_data(form_data):
+ if form_data.allstrainlist:
+ mdpchoice = form_data.formdata.getvalue('MDPChoice')
+ #XZ, in HTML source code, it is "BXD Only" or "BXH only", and so on
+ if mdpchoice == "1":
+ strainlist = form_data.f1list + form_data.strainlist
+ #XZ, in HTML source code, it is "MDP Only"
+ elif mdpchoice == "2":
+ strainlist = []
+ strainlist2 = form_data.f1list + form_data.strainlist
+ for strain in form_data.allstrainlist:
+ if strain not in strainlist2:
+ strainlist.append(strain)
+ #So called MDP Panel
+ if strainlist:
+ strainlist = form_data.f1list+form_data.parlist+strainlist
+ #XZ, in HTML source code, it is "All Cases"
+ else:
+ strainlist = form_data.allstrainlist
+ #XZ, 09/18/2008: put the trait data into dictionary form_data.allTraitData
+ form_data.readData(form_data.allstrainlist)
+ else:
+ mdpchoice = None
+ strainlist = form_data.strainlist
+ #XZ, 09/18/2008: put the trait data into dictionary form_data.allTraitData
+ form_data.readData()
+
+ return strainlist
+
+
+def get_mdp_choice(form_data):
+ if form_data.allstrainlist:
+ return form_data.formdata.getvalue("MDPChoice")
+ else:
+ return None
+
+
+def get_species(fd, 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=cursor, RISet=RISet)
+ return species
+
+
+def sortTraitCorrelations(traits, method="1"):
+ if method in TISSUE_METHODS:
+ traits.sort(key=lambda trait: trait.tissue_corr != None and abs(trait.tissue_corr), reverse=True)
+ elif method == METHOD_LIT:
+ traits.sort(key=lambda trait: trait.lit_corr != None and abs(trait.lit_corr), reverse=True)
+ else:
+ traits.sort(key=lambda trait: trait.correlation != None and abs(trait.correlation), reverse=True)
+
+ return traits
+
+
+def auth_user_for_db(db, cursor, target_db_name, privilege, username):
+ """Authorize a user for access to a database if that database is
+ confidential. A db (identified by a record in ProbeSetFreeze) contains a
+ list of authorized users who may access it, as well as its confidentiality
+ level.
+
+ If the current user's privilege level is greater than 'user', ie: root or
+ admin, then they are automatically authed, otherwise, check the
+ AuthorizedUsers field for the presence of their name."""
+
+ if db.type == 'ProbeSet':
+ cursor.execute('SELECT Id, Name, FullName, confidentiality, AuthorisedUsers FROM ProbeSetFreeze WHERE Name = "%s"' % target_db_name)
+ indId, indName, indFullName, confidential, AuthorisedUsers = cursor.fetchall()[0]
+
+ if confidential:
+ authorized = 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[privilege] > webqtlConfig.USERDICT['user']:
+ authorized = 1
+ else:
+ if username in AuthorisedUsers.split(","):
+ authorized = 1
+
+ if not authorized:
+ raise AuthException("The %s database you selected is not open to the public at this time, please go back and select other database." % indFullName)
- 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]
+class CorrelationPage(templatePage):
- if confidential == 1:
- access_to_confidential_dataset = 0
+ corrMinInformative = 4
- #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
+ PAGE_HEADING = "Correlation Table"
+ CORRELATION_METHODS = {"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)"}
- 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
+ RANK_ORDERS = {"1": 0, "2": 1, "3": 0, "4": 0, "5": 1}
- #XZ, 09/18/2008: filter out the strains that have no value.
- _strains, _vals, _vars, N = fd.informativeStrains(strainlist)
- N = len(_strains)
+ def error(self, message, error="Error", heading = None):
+ heading = heading or self.PAGE_HEADING
+ return templatePage.error(heading = heading, detail = [message], error=error)
- 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)
+ def __init__(self, fd):
+
+ # Call the superclass constructor
+ templatePage.__init__(self, fd)
+
+ # Connect to the database
+ if not self.openMysql():
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"
+ # Read the genotype from a file
+ if not fd.genotype:
+ fd.readGenotype()
- self.returnNumber = int(fd.formdata.getvalue('criteria'))
+ sample_list = get_sample_data(fd)
+ mdp_choice = get_mdp_choice(fd) # No idea what this is yet
+ self.species = get_species(fd, self.cursor)
- myTrait = fd.formdata.getvalue('fullname')
- if myTrait:
- myTrait = webqtlTrait(fullname=myTrait, cursor=self.cursor)
- myTrait.retrieveInfo()
+ #XZ, 09/18/2008: get all information about the user selected database.
+ target_db_name = fd.formdata.getvalue('database')
+ self.target_db_name = target_db_name
- # 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'))
+ self.db = webqtlDataset(target_db_name, self.cursor)
except:
- input_trait_GeneId = None
+ detail = ["The database you just requested has not been established yet."]
+ self.error(detail)
+ return
- # We will not get Tissue Correlations if there is no gene symbol because there is nothing to look against
+ # Auth if needed
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)
+ auth_user_for_db(self.db, self.cursor, target_db_name, self.privilege, self.userName)
+ except AuthException, e:
+ detail = [e.message]
+ return self.error(detail)
+ #XZ, 09/18/2008: filter out the strains that have no value.
+ self.sample_names, vals, vars, N = fd.informativeStrains(sample_list)
-#############################################################
+ #CF - If less than a minimum number of strains/cases in common, don't calculate anything
+ if len(self.sample_names) < self.corrMinInformative:
+ 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=PAGE_HEADING,detail=detail)
- 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)
+ self.method = get_correlation_method_key(fd)
+ correlation_method = self.CORRELATION_METHODS[self.method]
+ rankOrder = self.RANK_ORDERS[self.method]
- #XZ, 09/20/2008: we only need the top ones.
- self.returnNumber = min(self.returnNumber,len(allcorrelations))
- allcorrelations = allcorrelations[:self.returnNumber]
+ # CF - Number of results returned
+ self.returnNumber = int(fd.formdata.getvalue('criteria'))
- addLiteratureCorr = False
- addTissueCorr = False
+ self.record_count = 0
- traitList = []
- for item in allcorrelations:
- thisTrait = webqtlTrait(db=self.db, name=item[0], cursor=self.cursor)
- thisTrait.retrieveInfo( QTL='Yes' )
+ myTrait = get_custom_trait(fd, self.cursor)
- 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
+ # We will not get Literature Correlations if there is no GeneId because there is nothing to look against
+ self.gene_id = int(fd.formdata.getvalue('GeneId') or 0)
- #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
+ # We will not get Tissue Correlations if there is no gene symbol because there is nothing to look against
+ self.trait_symbol = myTrait.symbol
+
- #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
+ #XZ, 12/12/2008: if the species is rat or human, translate the geneid to mouse geneid
+ self.input_trait_mouse_gene_id = self.translateToMouseGeneID(self.species, self.gene_id)
- traitList.append(thisTrait)
+ #XZ: As of Nov/13/2010, this dataset is 'UTHSC Illumina V6.2 RankInv B6 D2 average CNS GI average (May 08)'
+ self.tissue_probeset_freeze_id = 1
- 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)
+ traitList = self.correlate(vals)
+
+ _log.info("Done doing correlation calculation")
-########################################################
+############################################################################################################################################
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}
+ hddn = {'FormID': 'showDatabase',
+ 'ProbeSetID': '_',
+ 'database': self.target_db_name,
+ 'databaseFull': self.db.fullname,
+ 'CellID': '_',
+ 'RISet': fd.RISet,
+ 'identification': fd.identification}
if myTrait:
hddn['fullname']=fd.formdata.getvalue('fullname')
- if mdpchoice:
- hddn['MDPChoice']=mdpchoice
+ if mdp_choice:
+ hddn['MDPChoice']=mdp_choice
#XZ, 09/18/2008: pass the trait data to next page by hidden parameters.
@@ -510,13 +390,13 @@ class CorrelationPage(templatePage):
#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'))
+ form.append(HT.Input(name="TissueProbeSetFreezeId", value="%s" % self.tissue_probeset_freeze_id, 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 )
+ info = self.getTopInfo(myTrait=myTrait, method=self.method, db=self.db, target_db_name=self.target_db_name, returnNumber=self.returnNumber, methodDict=self.CORRELATION_METHODS, totalTraits=traitList, identification=fd.identification )
##############
# Excel file #
@@ -536,7 +416,7 @@ class CorrelationPage(templatePage):
#####################################################################
-
+ #Select All, Deselect All, Invert Selection, Add to Collection
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)
@@ -555,10 +435,10 @@ class CorrelationPage(templatePage):
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 = HT.Href(url="#redirect", onClick="addRmvSelection('%s', document.getElementsByName('%s')[0], 'addToSelection');" % (fd.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 = 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)
@@ -575,20 +455,90 @@ class CorrelationPage(templatePage):
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")
+ #External analysis tools
+ 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 self.species == 'rat':
+ hddnWebGestalt['org'] = 'Rattus norvegicus'
+ elif self.species == 'human':
+ hddnWebGestalt['org'] = 'Homo sapiens'
+ elif self.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'))
+
- 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(" "*1,"Select"), HT.TD("Deselect"), HT.TD(" "*1,"Invert"), HT.TD(" "*3,"Add")))
+ #Create tables with options, etc
+
+ 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")
+
+
+ if not GO_tree_value:
+ optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="480", height="80", border=0, align="Left")
+ optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), HT.TD(GCATButton), HT.TD(ODE), align="left"))
+ optionsTable.append(HT.TR(HT.TD(" "*1,"Select"), HT.TD("Deselect"), HT.TD(" "*1,"Invert"), HT.TD(" "*3,"Add"), HT.TD("Gene Set"), HT.TD(" "*2,"GCAT")))
+ else:
+ optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="560", height="80", border=0, align="Left")
+ optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), HT.TD(GCATButton), HT.TD(ODE), HT.TD(WebGestalt), align="left"))
+ optionsTable.append(HT.TR(HT.TD(" "*1,"Select"), HT.TD("Deselect"), HT.TD(" "*1,"Invert"), HT.TD(" "*3,"Add"), HT.TD("Gene Set"), HT.TD(" "*2,"GCAT"), HT.TD(" "*3, "ODE")))
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(" "*1,HT.Text("Graph")), HT.TD(" "*1,HT.Text("Matrix")), HT.TD(" "*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()))
+ 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")
@@ -597,12 +547,14 @@ class CorrelationPage(templatePage):
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(" "), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
- containerTable.append(HT.TR(HT.TD(" ")))
+ containerTable.append(HT.TR(HT.TD(" "), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD(" ")))
else:
- containerTable.append(HT.TR(HT.TD(" "), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
- containerTable.append(HT.TR(HT.TD(" ")))
+ containerTable.append(HT.TR(HT.TD(" "), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD(" ")))
+ """
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"))
@@ -615,9 +567,9 @@ class CorrelationPage(templatePage):
if self.db.type=="Geno":
- containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
+ containerTable.append(HT.TR(HT.TD(xlsUrl, height=60)))
- pageTable.append(HT.TR(HT.TD(containerTable)))
+ pageTable.append(HT.TR(HT.TD(containerTable)))
tblobj['header'], worksheet = self.getTableHeaderForGeno( method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
newrow += 1
@@ -636,9 +588,9 @@ class CorrelationPage(templatePage):
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)))
+ pageTable.append(HT.TR(HT.TD(div)))
- form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
+ 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())
@@ -649,9 +601,9 @@ class CorrelationPage(templatePage):
elif self.db.type=="Publish":
- containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
+ containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
- pageTable.append(HT.TR(HT.TD(containerTable)))
+ pageTable.append(HT.TR(HT.TD(containerTable)))
tblobj['header'], worksheet = self.getTableHeaderForPublish(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
newrow += 1
@@ -661,7 +613,7 @@ class CorrelationPage(templatePage):
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)
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForPublish(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript, species=self.species)
workbook.close()
@@ -671,7 +623,7 @@ class CorrelationPage(templatePage):
# 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)))
+ pageTable.append(HT.TR(HT.TD(div)))
form.append(
HT.Input(name='ShowStrains',type='hidden', value =1),
@@ -685,7 +637,6 @@ class CorrelationPage(templatePage):
elif self.db.type=="ProbeSet":
-
tblobj['header'], worksheet = self.getTableHeaderForProbeSet(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
newrow += 1
@@ -694,7 +645,7 @@ class CorrelationPage(templatePage):
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)
+ tblobj['body'], worksheet, corrScript = self.getTableBodyForProbeSet(traitList=traitList, primaryTrait=myTrait, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript, species=self.species)
workbook.close()
objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
@@ -741,95 +692,21 @@ class CorrelationPage(templatePage):
#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)
+ strainIds=self.getStrainIds(species=self.species, strains=self.sample_names)
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')
+ 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)
+ containerTable.append(HT.TR(HT.TD(xlsUrl, HT.BR(), HT.BR())))
- '''
- #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()
+ pageTable.append(HT.TR(HT.TD(containerTable)))
- if result:
- GO_tree_value = result[0]
+ pageTable.append(HT.TR(HT.TD(div)))
- 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(" ", HT.Text("GCAT"), width="50%"), HT.TD(" ",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(" "*2, HT.Text("GCAT")), HT.TD(" "*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':
+ if self.species == 'human':
heatmap = ""
form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
@@ -1009,7 +886,7 @@ Resorting this table
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)
+ tempTable = self.getTempTissueCorrTable(primaryTraitSymbol=GeneSymbol, TissueProbeSetFreezeId=TISSUE_MOUSE_DB, method=method, returnNumber=returnNumber)
for step in range(nnn):
temp = []
@@ -1068,18 +945,30 @@ Resorting this table
oridata.append(results)
datasize = len(oridata[0])
- traitdatabase = []
- # put all of the seperate data together into a huge list of lists
+ traits = []
+ # put all of the separate 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)
+
+ trait = Trait(traitdata[0], traitdata[dataStartPos:])
+
+ if method == METHOD_LIT:
+ trait.lit_corr = traitdata[1]
+
+ if method in TISSUE_METHODS:
+ trait.tissue_corr = traitdata[1]
+ trait.p_tissue = traitdata[2]
+
+ traits.append(trait)
if tempTable:
self.cursor.execute( 'DROP TEMPORARY TABLE %s' % tempTable )
- return traitdatabase, dataStartPos
+ return traits
+
+
# XZ, 09/20/2008: This function creates TEMPORARY TABLE tmpTableName_2 and return its name.
@@ -1159,7 +1048,7 @@ Resorting this table
except:
return 0
- symbolCorrDict, symbolPvalueDict = self.calculateCorrOfAllTissueTrait(primaryTraitSymbol=primaryTraitSymbol, TissueProbeSetFreezeId=TissueProbeSetFreezeId, method=method)
+ symbolCorrDict, symbolPvalueDict = self.calculateCorrOfAllTissueTrait(primaryTraitSymbol=primaryTraitSymbol, TissueProbeSetFreezeId=TISSUE_MOUSE_DB, method=method)
symbolCorrList = symbolCorrDict.items()
@@ -1216,7 +1105,7 @@ Resorting this table
Returns a dictionary of 'TraitID':(tissueCorr, tissuePValue) for the requested correlation"""
- tempTable = self.getTempTissueCorrTable(primaryTraitSymbol=primaryTraitSymbol, TissueProbeSetFreezeId=TissueProbeSetFreezeId, method=method, returnNumber=returnNumber)
+ tempTable = self.getTempTissueCorrTable(primaryTraitSymbol=primaryTraitSymbol, TissueProbeSetFreezeId=TISSUE_MOUSE_DB, method=method, returnNumber=returnNumber)
query = "SELECT ProbeSet.Name, %s.Correlation, %s.PValue" % (tempTable, tempTable)
query += ' FROM (ProbeSet, ProbeSetXRef, ProbeSetFreeze)'
@@ -1276,6 +1165,225 @@ Resorting this table
return traitList
+ def get_trait(self, cached, vals):
+
+ if cached:
+ _log.info("Using the fast method because the file exists")
+ lit_corrs = {}
+ tissue_corrs = {}
+ use_lit = False
+ if self.method == METHOD_LIT:
+ lit_corrs = self.fetchLitCorrelations(species=self.species, GeneId=self.gene_id, db=self.db, returnNumber=self.returnNumber)
+ use_lit = True
+
+ use_tissue_corr = False
+ if self.method in TISSUE_METHODS:
+ tissue_corrs = self.fetchTissueCorrelations(db=self.db, primaryTraitSymbol=self.trait_symbol, TissueProbeSetFreezeId=TISSUE_MOUSE_DB, method=self.method, returnNumber = self.returnNumber)
+ use_tissue_corr = True
+
+ DatabaseFileName = self.getFileName( target_db_name=self.target_db_name )
+ datasetFile = open(webqtlConfig.TEXTDIR+DatabaseFileName,'r')
+
+ #XZ, 01/08/2009: read the first line
+ line = datasetFile.readline()
+ cached_sample_names = 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'.
+ new_vals = []
+ for name in cached_sample_names:
+ if name in self.sample_names:
+ new_vals.append(float(vals[self.sample_names.index(name)]))
+ else:
+ new_vals.append('None')
+
+ nnCorr = len(new_vals)
+
+ #XZ, 01/14/2009: If literature corr or tissue corr is selected,
+ #XZ: there is no need to use parallel computing.
+
+ traits = []
+ data_start = 1
+ for line in datasetFile:
+ raw_trait = webqtlUtil.readLineCSV(line)
+ trait = Trait.from_csv(raw_trait, data_start)
+ trait.lit_corr = lit_corrs.get(trait.name)
+ trait.tissue_corr, trait.p_tissue = tissue_corrs.get(trait.name, (None, None))
+ traits.append(trait)
+
+ return traits, new_vals
+
+ else:
+ _log.info("Using the slow method for correlation")
+
+ _log.info("Fetching from database")
+ traits = self.fetchAllDatabaseData(species=self.species, GeneId=self.gene_id, GeneSymbol=self.trait_symbol, strains=self.sample_names, db=self.db, method=self.method, returnNumber=self.returnNumber, tissueProbeSetFreezeId= self.tissue_probeset_freeze_id)
+ _log.info("Done fetching from database")
+ totalTraits = len(traits) #XZ, 09/18/2008: total trait number
+
+ return traits, vals
+
+
+ def do_parallel_correlation(self):
+ _log.info("Invoking parallel computing")
+ input_line_list = datasetFile.readlines()
+ _log.info("Read lines from the file")
+ all_line_number = len(input_line_list)
+
+ step = 1000
+ job_number = math.ceil( float(all_line_number)/step )
+
+ job_input_lists = []
+
+ _log.info("Configuring jobs")
+
+ 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 )
+
+ _log.info("Creating pp servers")
+
+ ppservers = ()
+ # Creates jobserver with automatically detected number of workers
+ job_server = pp.Server(ppservers=ppservers)
+
+ _log.info("Done creating servers")
+
+ jobs = []
+ results = []
+
+ _log.info("Starting parallel computation, submitting jobs")
+ 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",)) )
+ _log.info("Done submitting jobs")
+
+ for one_job in jobs:
+ one_result = one_job()
+ results.append( one_result )
+
+ _log.info("Acquiring results")
+
+ for one_result in results:
+ for one_traitinfo in one_result:
+ allcorrelations.append( one_traitinfo )
+
+ _log.info("Appending the results")
+
+ datasetFile.close()
+ totalTraits = len(allcorrelations)
+ _log.info("Done correlating using the fast method")
+
+
+ def correlate(self, vals):
+
+ correlations = []
+
+ #XZ: Use the fast method only for probeset dataset, and this dataset must have been created.
+ #XZ: Otherwise, use original method
+ _log.info("Entering correlation")
+
+ db_filename = self.getFileName( target_db_name=self.target_db_name )
+
+ cache_available = db_filename in os.listdir(webqtlConfig.TEXTDIR)
+
+ # If the cache file exists, do a cached correlation for probeset data
+ if self.db.type == "ProbeSet":
+# if self.method in [METHOD_SAMPLE_PEARSON, METHOD_SAMPLE_RANK] and cache_available:
+# traits = do_parallel_correlation()
+#
+# else:
+
+ (traits, vals) = self.get_trait(cache_available, vals)
+
+ for trait in traits:
+ trait.calculate_correlation(vals, self.method)
+
+ self.record_count = len(traits) #ZS: This isn't a good way to get this value, so I need to change it later
+
+ #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.
+ #if self.method in [METHOD_LIT, METHOD_TISSUE_PEARSON, METHOD_TISSUE_RANK] and self.gene_id:
+ # traits.sort(webqtlUtil.cmpLitCorr)
+ #else:
+ #if self.method in TISSUE_METHODS:
+ # sort(traits, key=lambda A: math.fabs(A.tissue_corr))
+ #elif self.method == METHOD_LIT:
+ # traits.sort(traits, key=lambda A: math.fabs(A.lit_corr))
+ #else:
+ traits = sortTraitCorrelations(traits, self.method)
+
+ # Strip to the top N correlations
+ traits = traits[:min(self.returnNumber, len(traits))]
+
+ addLiteratureCorr = False
+ addTissueCorr = False
+
+ trait_list = []
+ for trait in traits:
+ db_trait = webqtlTrait(db=self.db, name=trait.name, cursor=self.cursor)
+ db_trait.retrieveInfo( QTL='Yes' )
+
+ db_trait.Name = trait.name
+ db_trait.corr = trait.correlation
+ db_trait.nOverlap = trait.overlap
+ db_trait.corrPValue = trait.p_value
+
+ # NL, 07/19/2010
+ # js function changed, add a new parameter rankOrder for js function 'showTissueCorrPlot'
+ db_trait.RANK_ORDER = self.RANK_ORDERS[self.method]
+
+ #XZ, 26/09/2008: Method is 4 or 5. Have fetched tissue corr, but no literature correlation yet.
+ if self.method in TISSUE_METHODS:
+ db_trait.tissueCorr = trait.tissue_corr
+ db_trait.tissuePValue = trait.p_tissue
+ addTissueCorr = True
+
+
+ #XZ, 26/09/2008: Method is 3, Have fetched literature corr, but no tissue corr yet.
+ elif self.method == METHOD_LIT:
+ db_trait.LCorr = trait.lit_corr
+ db_trait.mouse_geneid = self.translateToMouseGeneID(self.species, db_trait.geneid)
+ addLiteratureCorr = 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 self.input_trait_mouse_gene_id and self.db.type=="ProbeSet":
+ addLiteratureCorr = True
+ if self.trait_symbol and self.db.type=="ProbeSet":
+ addTissueCorr = True
+
+ trait_list.append(db_trait)
+
+ if addLiteratureCorr:
+ trait_list = self.getLiteratureCorrelationByList(self.input_trait_mouse_gene_id,
+ self.species, trait_list)
+ if addTissueCorr:
+ trait_list = self.getTissueCorrelationByList(
+ primaryTraitSymbol = self.trait_symbol,
+ traitList = trait_list,
+ TissueProbeSetFreezeId = TISSUE_MOUSE_DB,
+ method=self.method)
+
+ return trait_list
def calculateCorrOfAllTissueTrait(self, primaryTraitSymbol=None, TissueProbeSetFreezeId=None, method=None):
@@ -1283,10 +1391,10 @@ Resorting this table
symbolCorrDict = {}
symbolPvalueDict = {}
- primaryTraitSymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[primaryTraitSymbol], TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ primaryTraitSymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[primaryTraitSymbol], TissueProbeSetFreezeId=TISSUE_MOUSE_DB)
primaryTraitValue = primaryTraitSymbolValueDict.values()[0]
- SymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[], TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ SymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[], TissueProbeSetFreezeId=TISSUE_MOUSE_DB)
if method in ["2","5"]:
symbolCorrDict, symbolPvalueDict = correlationFunction.batchCalTissueCorr(primaryTraitValue,SymbolValueDict,method='spearman')
@@ -1301,7 +1409,7 @@ Resorting this table
#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)
+ primaryTraitSymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[primaryTraitSymbol], TissueProbeSetFreezeId=TISSUE_MOUSE_DB)
if primaryTraitSymbol.lower() in primaryTraitSymbolValueDict:
primaryTraitValue = primaryTraitSymbolValueDict[primaryTraitSymbol.lower()]
@@ -1312,7 +1420,7 @@ Resorting this table
if hasattr(thisTrait, 'symbol'):
geneSymbolList.append(thisTrait.symbol)
- SymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=geneSymbolList, TissueProbeSetFreezeId=TissueProbeSetFreezeId)
+ SymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=geneSymbolList, TissueProbeSetFreezeId=TISSUE_MOUSE_DB)
for thisTrait in traitList:
if hasattr(thisTrait, 'symbol') and thisTrait.symbol and thisTrait.symbol.lower() in SymbolValueDict:
@@ -1339,7 +1447,7 @@ Resorting this table
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 were compared to all %d records in the " % self.record_count, 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:
@@ -1359,7 +1467,7 @@ Resorting this table
' 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),
+ info = HT.Paragraph('Values of %s were compared to all %d traits in ' % (identification, self.record_count),
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.')
@@ -1934,7 +2042,7 @@ Resorting this table
TCorr = thisTrait.tissueCorr
TCorrStr = "%2.3f" % thisTrait.tissueCorr
# NL, 07/19/2010: add a new parameter rankOrder for js function 'showTissueCorrPlot'
- rankOrder = thisTrait.rankOrder
+ rankOrder = self.RANK_ORDERS[self.method]
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:
diff --git a/web/webqtl/showTrait/DataEditingPage.py b/web/webqtl/showTrait/DataEditingPage.py
old mode 100644
new mode 100755
index f38b9880..974b2ed5
--- a/web/webqtl/showTrait/DataEditingPage.py
+++ b/web/webqtl/showTrait/DataEditingPage.py
@@ -416,13 +416,15 @@ class DataEditingPage(templatePage):
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 = HT.Href(url="#")
+ verifyButtonImg = HT.Image("/images/verify_icon.jpg", name="verify", alt=" Check probe locations at UCSC ",
+ title=" Check probe locations at UCSC ", onClick="javascript:openNewWin('%s'); return false;" % UCSC_BLAT_URL, 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 = HT.Href(url="#")
+ rnaseqButtonImg = HT.Image("/images/rnaseq_icon.jpg", name="rnaseq", alt=" View probes, SNPs, and RNA-seq at UTHSC ",
+ title=" View probes, SNPs, and RNA-seq at UTHSC ", onClick="javascript:openNewWin('%s'); return false;" % UTHSC_BLAT_URL, style="border:none;")
rnaseqButton.append(rnaseqButtonImg)
rnaseqText = 'RNA-seq'
tSpan.append(HT.BR())
@@ -590,10 +592,24 @@ class DataEditingPage(templatePage):
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), " "*2)
- if thisTrait.geneid:
+ if thisTrait.symbol:
+ #ZS: The "species scientific" converts the plain English species names we're using to their scientific names, which are needed for PANTHER's input
+ #We should probably use the scientific name along with the English name (if not instead of) elsewhere as well, given potential non-English speaking users
+ if _Species == "mouse":
+ species_scientific = "Mus%20musculus"
+ elif _Species == "rat":
+ species_scientific = "Rattus%20norvegicus"
+ elif _Species == "human":
+ species_scientific = "Homo%20sapiens"
+ elif _Species == "drosophila":
+ species_scientific = "Drosophila%20melanogaster"
+ else:
+ species_scientific = "all"
+
+ species_scientific
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", \
+ url="http://www.pantherdb.org/genes/geneList.do?searchType=basic&fieldName=all&organism=%s&listType=1&fieldValue=%s" \
+ % (species_scientific, thisTrait.symbol),Class="fs14 fwn", \
title="Gene and protein data resources from Celera-ABI"), style=linkStyle), " "*2)
else:
pass
@@ -755,11 +771,12 @@ class DataEditingPage(templatePage):
UCSC_BLAT_URL = ""
UTHSC_BLAT_URL = ""
if UCSC_BLAT_URL:
- verifyButton = HT.Href(url="#redirect", onClick="openNewWin('%s')" % UCSC_BLAT_URL)
+ #verifyButton = HT.Href(url="#", onClick="openNewWin('%s')" % UCSC_BLAT_URL)
+ verifyButton = HT.Href(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)
+ rnaseqButton = HT.Href(url="#", 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"
--
cgit v1.2.3
From 63297d5f4eb61541cb98dcbca668410f6550257a Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Fri, 1 Jun 2012 02:03:02 -0400
Subject: Views and templates modified to allow template analysis
---
web/javascript/webqtl.js | 184 +++++++++++-----------
wqflask/runserver.py | 6 +
wqflask/wqflask/search_results.py | 6 +-
wqflask/wqflask/templates/search_result_page.html | 5 +-
wqflask/wqflask/views.py | 4 +
5 files changed, 111 insertions(+), 94 deletions(-)
diff --git a/web/javascript/webqtl.js b/web/javascript/webqtl.js
index 19ecf3b7..536e7d26 100755
--- a/web/javascript/webqtl.js
+++ b/web/javascript/webqtl.js
@@ -38,16 +38,16 @@ function makeTree(thisForm, nnn){
j += 1;
}
}
-
+
var windowName = 'formTarget' + (new Date().getTime());
var newWindow = open("", windowName,"width=900,menubar=0,toolbar=1,resizable=1,status=1,scrollbars=1");
var html = "";
if (j > 0)
- {
+ {
var waithtml1 ="
Your list of "+j+" transcripts is being exported to the Gene Ontology Tree Machine for analysis. This window will soon be replaced with the main GOTM results.
";
}
else
- {
+ {
var waithtml1 ="
Your should select at least one transcript to export to the Gene Ontology Tree Machine for analysis.
";
}
html += waithtml1;
@@ -152,7 +152,11 @@ function showDatabase3(formName, Database,ProbeSetID,CellID){
document[formName].database.value = Database;
document[formName].ProbeSetID.value = ProbeSetID;
document[formName].CellID.value = CellID;
- document[formName].submit();
+ console.log("formName:", formName)
+ console.log("document[formName]:", document[formName])
+ console.log("submit turned off for debugging")
+ console.log("showDatabase3 is deprecated for the flask version of this site")
+ //document[formName].submit();
}
@@ -188,10 +192,10 @@ function showTrait(fmName){
var thisForm = getForm(fmName);
if (thisForm == null || showTrait.arguments.length < 2)
return;
-
+
windowName = genNewWin();
thisForm.target = windowName;
-
+
thisForm.FormID.value = "showDatabase";
thisForm.ProbeSetID.value = showTrait.arguments[1];
if (showTrait.arguments.length > 2)
@@ -205,10 +209,10 @@ function showCateGraph(fmName){
var thisForm = getForm(fmName);
if (thisForm == null || showCateGraph.arguments.length < 2)
return;
-
+
windowName = genNewWin();
thisForm.target = windowName;
-
+
thisForm.FormID.value = "showCategoryGraph";
thisForm.interval1.value = showCateGraph.arguments[1];
thisForm.interval2.value = showCateGraph.arguments[2];
@@ -219,22 +223,22 @@ function showCorrPlot(fmName){
var thisForm = getForm(fmName);
if (thisForm == null || showCorrPlot.arguments.length < 2)
return;
-
+
windowName = genNewWin();
thisForm.target = windowName;
-
+
thisForm.FormID.value = "showCorrelationPlot";
thisForm.ProbeSetID.value = showCorrPlot.arguments[1];
if (showCorrPlot.arguments.length > 2)
thisForm.CellID.value = showCorrPlot.arguments[2];
else
thisForm.CellID.value = "";
-
+
thisForm.X_geneSymbol.value = null;
thisForm.Y_geneSymbol.value = null;
thisForm.submit();
-
+
}
@@ -242,12 +246,12 @@ function showCorrPlotThird(fmName){
var thisForm = getForm(fmName);
if (thisForm == null || showCorrPlotThird.arguments.length < 3)
return;
-
+
windowName = genNewWin();
thisForm.target = windowName;
-
+
var olddb = thisForm.database.value;
-
+
thisForm.FormID.value = "showCorrelationPlot";
thisForm.database.value = showCorrPlotThird.arguments[1];
thisForm.ProbeSetID.value = showCorrPlotThird.arguments[2];
@@ -284,15 +288,15 @@ function ODE(thisForm, script){
var windowName = 'formTarget' + (new Date().getTime());
var newWindow = open("", windowName, "width=900,menubar=0,toolbar=1,resizable=1,status=1,scrollbars=1");
var html = "";
- if (j == 0){
+ if (j == 0){
j = length;
trait_list2 = trait_list_all;
correlation2 = correlation_all;
llid_list2 = llid_list_all;
}
-
+
var waithtml1 ="
Your list of "+j+" transcripts is being exported to the ODE for analysis. This window will soon be replaced with the results.
";
-
+
html += waithtml1;
newWindow.document.write(html);
newWindow.document.close();
@@ -302,14 +306,14 @@ function ODE(thisForm, script){
thisForm.correlation.value = correlation2.join(',');
thisForm.id_value.value = thisForm.correlation.value;
thisForm.llid_list.value = llid_list2.join(',');
-
+
// ODE
-
+
thisForm.idtype.value = thisForm.id_type.value;
thisForm.species.value = thisForm.org.value;
thisForm.list.value = thisForm.id_list.value;
thisForm.client.value = "genenetwork";
-
+
thisForm.target = windowName;
var oldaction = thisForm.action;
thisForm.action = script;
@@ -318,13 +322,13 @@ function ODE(thisForm, script){
}
}
*/
-// 02/12/2009
+// 02/12/2009
// Lei Yan
/*scripts in the Dataediting form*/
function dataEditingFunc(thisForm,submitIdValue){
-
+
windowName = 'formTarget' + (new Date().getTime());
if (thisForm.FormID.value!='secondRegression'){
@@ -336,7 +340,7 @@ function dataEditingFunc(thisForm,submitIdValue){
}
else if (submitIdValue == "addRecord"){
- windowName = thisForm.RISet.value;
+ windowName = thisForm.RISet.value;
var name = thisForm.identification.value;
if (name != ""){
}
@@ -352,7 +356,7 @@ function dataEditingFunc(thisForm,submitIdValue){
newWindow = open("",windowName,"menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=1,directories=1,width=900");
thisForm.target = windowName;
- newWindow.focus();
+ newWindow.focus();
thisForm.submitID.value = submitIdValue;
thisForm.submit();
}
@@ -394,7 +398,7 @@ function addRmvSelection(windowName, thisForm, addORrmv){
thisForm.target = windowName;
thisForm.FormID.value = addORrmv;
thisForm.submit();
- newWindow.focus();
+ newWindow.focus();
}
function batchSelection(thisForm){
@@ -424,7 +428,7 @@ function showTop10(formName, submitIdValue){
if ((submitIdValue == "markerRegression")||(submitIdValue == "compositeRegression")){
thisForm.topten.value = "topten";
}
-
+
thisForm.submitID.value = submitIdValue;
thisForm.submit();
}
@@ -441,12 +445,12 @@ function showIndividualChromosome(formName, submitIdValue, ii){
}
if (match == 0)
return;
-
+
windowName = 'formTarget' + (new Date().getTime());
newWindow = open("",windowName,"menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=1,directories=1,width=900");
newWindow.focus();
thisForm.target = windowName;
-
+
if (submitIdValue == "showIntMap"){
thisForm.chromosomes.value = ii;
}
@@ -529,10 +533,10 @@ function dataWindow(form){
}
-function xchange() {
+function xchange() {
var select = document.crossChoice.RISet;
var value = select.options[select.selectedIndex].value;
-
+
if (value !="BDAI") return;
document.crossChoice.variance.checked = false;
}
@@ -580,97 +584,97 @@ function crossinfo2(){
function checkWidth(){
var width = document.getElementsByName('plotSize')[0].value
-
+
if (width < 600) {
alert("Plot size is too small - setting size to 600")
document.getElementsByName('plotSize')[0].value = 600
- }
+ }
}
function changeLineColor(){
var lineColor = document.getElementsByName('lineColorSel')[0].value
-
+
document.getElementsByName('lineColor')[0].value = lineColor
}
function changeLineSize(){
var lineSize = document.getElementsByName('lineSizeSel')[0].value
-
+
document.getElementsByName('lineSize')[0].value = lineSize
}
function changeIdColor(){
var idColor = document.getElementsByName('idColorSel')[0].value
-
+
document.getElementsByName('idColor')[0].value = idColor
}
function changeIdFont(){
var idFont = document.getElementsByName('idFontSel')[0].value
-
+
document.getElementsByName('idFont')[0].value = idFont
}
function changeIdSize(){
var idSize = document.getElementsByName('idSizeSel')[0].value
-
+
document.getElementsByName('idSize')[0].value = idSize
}
function changeSymbolColor(){
var symbolColor = document.getElementsByName('colorSel')[0].value
-
+
document.getElementsByName('symbolColor')[0].value = symbolColor
}
function changeSymbol(){
var symbol = document.getElementsByName('symbolSel')[0].value
-
+
document.getElementsByName('symbol')[0].value = symbol
}
function changeFilled(){
var filled = document.getElementsByName('fillSel')[0].value
-
+
document.getElementsByName('filled')[0].value = filled
}
function changeSize(){
var symbolSize = document.getElementsByName('sizeSel')[0].value
-
+
document.getElementsByName('symbolSize')[0].value = symbolSize
}
-function checkAll(thisForm){
+function checkAll(thisForm){
var length = thisForm.searchResult.length;
for(var i = 0; i < length; i++)
{
thisForm.searchResult[i].checked = true;
highlight(thisForm.searchResult[i]);
}
-}
+}
-function checkNone(thisForm){
+function checkNone(thisForm){
var length = thisForm.searchResult.length;
for(var i = 0; i < length; i++)
{
thisForm.searchResult[i].checked = false;
highlight(thisForm.searchResult[i]);
}
-}
+}
-function checkInvert(thisForm){
+function checkInvert(thisForm){
var length = thisForm.searchResult.length;
for(var i = 0; i < length; i++)
{
thisForm.searchResult[i].checked = !(thisForm.searchResult[i].checked);
highlight(thisForm.searchResult[i]);
}
-}
+}
/*Not used anymore*/
-function checkTraits2(thisForm){
+function checkTraits2(thisForm){
var length = thisForm.searchResult.length;
var category = thisForm.selectmenu.value;
for(var i = 0; i < length; i++)
@@ -720,18 +724,18 @@ function checkTraits2(thisForm){
else
{}
}
-}
+}
function checkNumeric(field,limit,resetvalue,compares,fdname)
{
- pattern = /^-?[0-9]*\.?[0-9]*$/;
+ pattern = /^-?[0-9]*\.?[0-9]*$/;
if(pattern.test(field.value)==false)
{
alert("Not numeric in " + fdname);
field.value = resetvalue;
}
- else
+ else
{
if (compares == 'gthan') {
if(field.value > limit)
@@ -748,7 +752,7 @@ function checkNumeric(field,limit,resetvalue,compares,fdname)
}
}
-function checkTraits(thisForm){
+function checkTraits(thisForm){
var length = thisForm.searchResult.length;
var andor = thisForm.selectandor.value;
var gthan = parseFloat(thisForm.selectgt.value);
@@ -780,7 +784,7 @@ function checkTraits(thisForm){
}
-function checkPM(thisForm){
+function checkPM(thisForm){
var length = thisForm.searchResult.length;
for(var i = 0; i < length; i++)
{
@@ -792,8 +796,8 @@ function checkPM(thisForm){
{thisForm.searchResult[i].checked = false;}
highlight(thisForm.searchResult[i]);
}
-}
-function checkMM(thisForm){
+}
+function checkMM(thisForm){
var length = thisForm.searchResult.length;
for(var i = 0; i < length; i++)
{
@@ -804,14 +808,14 @@ function checkMM(thisForm){
{thisForm.searchResult[i].checked = false;}
highlight(thisForm.searchResult[i]);
}
-}
+}
-function directPermuAlert(thisForm){
- if (thisForm.directPermuCheckbox.checked){
- alert("Interaction permutation will take long time to compute.\n Check this box only when necessary.");
+function directPermuAlert(thisForm){
+ if (thisForm.directPermuCheckbox.checked){
+ alert("Interaction permutation will take long time to compute.\n Check this box only when necessary.");
}
-}
+}
function cliqueDatabase(pid){
var windowName = 'clique';
@@ -869,7 +873,7 @@ function snpbrowser_function_refresh() {
for (var i=1; i
+
@@ -185,7 +185,7 @@ Quick HELP Examples and
User's Guide
- You can also use advanced commands. Copy these simple examples
+ You can also use advanced commands. Copy these simple examples
into the Get Any or Combined search fields:
@@ -206,85 +206,85 @@ Quick HELP Examples and
RIF=diabetes LRS=(9 999 Chr2 100 105) transLRS=(9 999 10) in Combined finds diabetes-associated transcripts with peak trans eQTLs on Chr 2 between 100 and 105 Mb with LRS scores between 9 and 999.
-
Trait Data and Analysis for Record ID 1441186_at
--
cgit v1.2.3
From eb2e4311de82d8b97450d5114f8b75e112d32ba3 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Sun, 10 Jun 2012 03:45:14 -0400
Subject: Added uncustomized pylintrc
---
wqflask/other_config/pylintrc | 249 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 249 insertions(+)
create mode 100644 wqflask/other_config/pylintrc
diff --git a/wqflask/other_config/pylintrc b/wqflask/other_config/pylintrc
new file mode 100644
index 00000000..c42acc35
--- /dev/null
+++ b/wqflask/other_config/pylintrc
@@ -0,0 +1,249 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+#disable=
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=text
+
+# Include message's id in output
+include-ids=no
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
--
cgit v1.2.3
From 893164a15a18030715167c45f0d114d13e37aadb Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Sun, 10 Jun 2012 05:33:44 -0400
Subject: Modified pylintrc
---
wqflask/other_config/dot.pylintrc | 249 ++++++++++++++++++++++++++++++++++++++
wqflask/other_config/pylintrc | 249 --------------------------------------
2 files changed, 249 insertions(+), 249 deletions(-)
create mode 100644 wqflask/other_config/dot.pylintrc
delete mode 100644 wqflask/other_config/pylintrc
diff --git a/wqflask/other_config/dot.pylintrc b/wqflask/other_config/dot.pylintrc
new file mode 100644
index 00000000..2774300a
--- /dev/null
+++ b/wqflask/other_config/dot.pylintrc
@@ -0,0 +1,249 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+#disable=
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=colorized
+
+# Include message's id in output
+include-ids=no
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/wqflask/other_config/pylintrc b/wqflask/other_config/pylintrc
deleted file mode 100644
index c42acc35..00000000
--- a/wqflask/other_config/pylintrc
+++ /dev/null
@@ -1,249 +0,0 @@
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Profiled execution.
-profile=no
-
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=CVS
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-
-[MESSAGES CONTROL]
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once).
-#disable=
-
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html
-output-format=text
-
-# Include message's id in output
-include-ids=no
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (RP0004).
-comment=no
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set).
-ignored-classes=SQLObject
-
-# When zope mode is activated, add a predefined set of Zope acquired attributes
-# to generated-members.
-zope=no
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=REQUEST,acl_users,aq_parent
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-
-[BASIC]
-
-# Required attributes for module, separated by a comma
-required-attributes=
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,apply,input
-
-# Regular expression which should only match correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression which should only match correct module level names
-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Regular expression which should only match correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression which should only match correct function names
-function-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct method names
-method-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct instance attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct list comprehension /
-# generator expression variable names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Regular expression which should only match functions or classes name which do
-# not require a docstring
-no-docstring-rgx=__.*__
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the beginning of the name of dummy variables
-# (i.e. not used).
-dummy-variables-rgx=_|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=80
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string=' '
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=5
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=15
-
-# Maximum number of return / yield for function / method body
-max-returns=6
-
-# Maximum number of branch for function / method body
-max-branchs=12
-
-# Maximum number of statements in function / method body
-max-statements=50
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-[CLASSES]
-
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
--
cgit v1.2.3
From be2baf17cba5468d901f8e2d8818fe558e2ee5fe Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Sun, 10 Jun 2012 06:02:11 -0400
Subject: Debug messages for trying to understand code
---
wqflask/basicStatistics/BasicStatisticsFunctions.py | 4 ++++
wqflask/wqflask/show_trait/DataEditingPage.py | 1 +
2 files changed, 5 insertions(+)
diff --git a/wqflask/basicStatistics/BasicStatisticsFunctions.py b/wqflask/basicStatistics/BasicStatisticsFunctions.py
index d2584bdd..74784853 100755
--- a/wqflask/basicStatistics/BasicStatisticsFunctions.py
+++ b/wqflask/basicStatistics/BasicStatisticsFunctions.py
@@ -4,6 +4,7 @@ from __future__ import print_function
from math import *
#import piddle as pid
#import os
+import traceback
from pprint import pformat as pf
@@ -18,6 +19,7 @@ from base import webqtlConfig
from dbFunction import webqtlDatabaseFunction
def basicStatsTable(vals, trait_type=None, cellid=None, heritability=None):
+ print("basicStatsTable called - len of vals", len(vals))
st = {} # This is the dictionary where we'll put everything for the template
valsOnly = []
dataXZ = vals[:]
@@ -48,6 +50,8 @@ def basicStatsTable(vals, trait_type=None, cellid=None, heritability=None):
at75 = stats.percentile(75)
at25 = stats.percentile(25)
+ print("should get a stack")
+ traceback.print_stack()
print("Interquartile:", at75 - at25)
#tbl.append(HT.TR(HT.TD("Statistic",align="left", Class="fs14 fwb ffl b1 cw cbrb", width = 180),
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index d82c47d5..a496a919 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -175,6 +175,7 @@ class DataEditingPage(templatePage):
else:
pass
# We'll get this part working later
+ print("Calling dispBasicStatistics")
self.dispBasicStatistics(fd, thisTrait)
#self.dispMappingTools(fd, title4Body, thisTrait)
--
cgit v1.2.3
From b4c536fa8e94643f8cbd37f9fb1db18b2ab52263 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Tue, 12 Jun 2012 04:36:47 -0400
Subject: More progress on data trait and analysis
---
wqflask/other_config/nginx.conf | 6 ++++-
wqflask/wqflask/show_trait/DataEditingPage.py | 25 +++++++++++--------
.../wqflask/templates/trait_data_and_analysis.html | 28 ++++++++++++----------
wqflask/wqflask/views.py | 1 +
4 files changed, 37 insertions(+), 23 deletions(-)
diff --git a/wqflask/other_config/nginx.conf b/wqflask/other_config/nginx.conf
index 93e6af10..65ee768c 100644
--- a/wqflask/other_config/nginx.conf
+++ b/wqflask/other_config/nginx.conf
@@ -49,6 +49,10 @@ http {
root /home/sam/gene/wqflask/wqflask/static/;
}
+# location ^~ /image/ {
+# root /home/sam/gene/wqflask/wqflask/static/;
+# }
+
location ^~ /images/ {
root /home/sam/gene/wqflask/wqflask/static/;
}
@@ -60,7 +64,7 @@ http {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
+ }
}
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index a496a919..d5238828 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -853,6 +853,8 @@ class DataEditingPage(templatePage):
primary_strains = [] #XZ: strain of primary group, e.g., BXD, LXS
#MDP_menu = HT.Select(name='stats_mdp', Class='stats_mdp')
+ MDP_menu = [] # We're going to use the same named data structure as in the old version
+ # but repurpose it for Jinja2 as an array
for strain in thisTrait.data.keys():
strainName = strain.replace("_2nd_", "")
@@ -872,21 +874,24 @@ class DataEditingPage(templatePage):
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'))
+ print("ac1") # This is the one used for first sall3
+ 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'))
+ print("ac2")
+ 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, " "*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:
+ print("ac3")
all_strains = strainlist
other_strains.sort(key=webqtlUtil.natsort_key)
@@ -962,7 +967,7 @@ class DataEditingPage(templatePage):
vals_set = [vals]
#stats_script = HT.Script(language="Javascript") #script needed for tabs
-
+ self.stats_data = []
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
@@ -994,11 +999,11 @@ class DataEditingPage(templatePage):
if thisTrait.db:
if thisTrait.cellid:
- statsTableCell = BasicStatisticsFunctions.basicStatsTable(vals=vals, trait_type=thisTrait.db.type, cellid=thisTrait.cellid)
+ self.stats_data.append(BasicStatisticsFunctions.basicStatsTable(vals=vals, trait_type=thisTrait.db.type, cellid=thisTrait.cellid))
else:
- statsTableCell = BasicStatisticsFunctions.basicStatsTable(vals=vals, trait_type=thisTrait.db.type)
+ self.stats_data.append(BasicStatisticsFunctions.basicStatsTable(vals=vals, trait_type=thisTrait.db.type))
else:
- statsTableCell = BasicStatisticsFunctions.basicStatsTable(vals=vals)
+ self.stats_data.append(BasicStatisticsFunctions.basicStatsTable(vals=vals))
#statsTable.append(HT.TR(HT.TD(statsTableCell)))
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index 122bafd9..f77d22d4 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -267,7 +267,8 @@
+
+
+
+
+
{% endblock %}
--
cgit v1.2.3
From 5ab5ede79ee823f7fbb70016809c887a78732472 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Fri, 22 Jun 2012 23:35:30 -0400
Subject: Working my way through getting the review and edit data dynamically
generated in Jinja2
---
wqflask/utility/Plot.py | 868 +++++++++++++-------------
wqflask/wqflask/show_trait/DataEditingPage.py | 109 ++--
2 files changed, 497 insertions(+), 480 deletions(-)
diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py
index 04fe85bf..086f3d57 100755
--- a/wqflask/utility/Plot.py
+++ b/wqflask/utility/Plot.py
@@ -487,440 +487,440 @@ def plotSecurity(canvas, text="12345"):
# 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 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'
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index 0194a7d9..38ab8c90 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -7,7 +7,7 @@ from collections import OrderedDict
from htmlgen import HTMLgen2 as HT
from base import webqtlConfig
-from utility import webqtlUtil #, Plot
+from utility import webqtlUtil, Plot
from base.webqtlTrait import webqtlTrait
from dbFunction import webqtlDatabaseFunction
from base.templatePage import templatePage
@@ -183,7 +183,7 @@ class DataEditingPage(templatePage):
## Trait Value Table
#############################
#
- #self.dispTraitValues(fd, title5Body, varianceDataPage, nCols, mainForm, thisTrait)
+ self.dispTraitValues(fd, varianceDataPage, nCols, thisTrait)
#
if fd.allstrainlist:
hddn['allstrainlist'] = string.join(fd.allstrainlist, ' ')
@@ -1549,14 +1549,15 @@ class DataEditingPage(templatePage):
##########################################
## 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')
+ def dispTraitValues(self, fd, varianceDataPage, nCols, thisTrait):
+ print("in dispTraitValues")
+ #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
@@ -1615,21 +1616,21 @@ class DataEditingPage(templatePage):
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:
- 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:
+ # pass
#showHideMenuOptions.append(HT.Bold(" Block samples by index: "), blockSamplesField, " ", blockMenuSpan, " ", blockSamplesButton, HT.BR())
- else:
- pass
+ #else:
+ # pass
#showHideMenuOptions.append(HT.Bold(" Block samples by index: "), blockSamplesField, " ", blockSamplesButton, HT.BR())
- exportButton = HT.Input(type='button', name='export', value=' Export ', Class='button')
+ #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(" Block samples by group:"), " "*5, exclude_menu, " "*5)
- for menu in dropdown_menus:
- pass
+ #for menu in dropdown_menus:
+ # pass
#showHideMenuOptions.append(menu)
#showHideMenuOptions.append(" "*5, excludeButton, HT.BR())
#showHideMenuOptions.append(HT.Bold(" Options:"), " "*5, showHideNoValue, " "*5, showHideOutliers, " "*5, resetButton, " "*5, exportButton)
@@ -1652,19 +1653,23 @@ class DataEditingPage(templatePage):
other_strainsExist = False
for strain in thisTrait.data.keys():
+ print("hjl - strain is:", strain)
if strain not in allstrainlist_neworder:
other_strainsExist = True
break
+ mainForm = None # Just trying to get things working
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)):
+ print("hji")
pass
#primary_table.append(primary_body[i])
other_strains = []
for strain in thisTrait.data.keys():
+ print("hjk - strain is:", strain)
if strain not in allstrainlist_neworder:
pass
#allstrainlist_neworder.append(strain)
@@ -1697,6 +1702,7 @@ class DataEditingPage(templatePage):
#other_table.append(other_header)
for i in range(len(other_body)):
+ print("hjn")
pass
#other_table.append(other_body[i])
else:
@@ -1704,6 +1710,7 @@ class DataEditingPage(templatePage):
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])):
+ print("hjs")
fd.allstrainlist = allstrainlist_neworder
## We put isSE into hddn
@@ -1711,7 +1718,7 @@ class DataEditingPage(templatePage):
# #mainForm.append(HT.Input(name='isSE', value="yes", type='hidden'))
# hddn['isSE'] = "yes"
- primary_div = HT.Div(primary_table, Id="primary") #Container for table with primary (for example, BXD) strain values
+ #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:
@@ -1719,13 +1726,13 @@ class DataEditingPage(templatePage):
#container.append(HT.Div(' ', height=30))
#container.append(other_div)
- table.append(HT.TR(HT.TD(container)))
+ #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
-
+ print("in addTrait2Table")
table_body = []
vals = []
@@ -1744,9 +1751,10 @@ class DataEditingPage(templatePage):
upperBound, lowerBound = Plot.findOutliers(vals) # ZS: Values greater than upperBound or less than lowerBound are considered outliers.
for i, strainNameOrig in enumerate(strainlist):
-
+ strain = {}
+ print("zyt - strainNameOrig:", strainNameOrig)
trId = strainNameOrig
- selectCheck = HT.Input(type="checkbox", name="selectCheck", value=trId, Class="checkbox", onClick="highlight(this)")
+ #selectCheck = HT.Input(type="checkbox", name="selectCheck", value=trId, Class="checkbox", onClick="highlight(this)")
strainName = strainNameOrig.replace("_2nd_", "")
strainNameAdd = ''
@@ -1769,6 +1777,7 @@ class DataEditingPage(templatePage):
traitVal = ''
dispVal = 'x'
+ strain['strain_name'] = StrainName
strainNameDisp = HT.Span(strainName, Class='fs14 fwn ffl')
if varianceDataPage:
@@ -1806,38 +1815,46 @@ class DataEditingPage(templatePage):
# 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)
+ #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)
+ pass
+ #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)
+ pass
+ #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)
+ pass
+ #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)
+ pass
+ #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)
+ pass
+ #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)
+ strain[the_id] = "Primary_" + str(i+1)
+ #table_row = HT.TR(Id="Primary_"+str(i+1), Class=rowClassName)
else:
- table_row = HT.TR(Id="Other_"+str(i+1), Class=rowClassName)
+ strain[the_id] = "Other_" + str(i+1)
+ #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("±", width=20, align='center', Class=className))
- table_row.append(HT.TD(seField, width=80, align='right', Id="SE_"+str(i)+"_"+strains, Class=className))
+ #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("±", width=20, align='center', Class=className))
+ #table_row.append(HT.TD(seField, width=80, align='right', Id="SE_"+str(i)+"_"+strains, Class=className))
+ pass
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))
-
+ #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))
+ pass
if thisTrait and thisTrait.db and thisTrait.db.type =='ProbeSet':
if len(attribute_ids) > 0:
@@ -1876,7 +1893,7 @@ class DataEditingPage(templatePage):
table_row.append(HT.TD(attr_container, align='right', Class=attr_className))
attr_counter += 1
- table_body.append(table_row)
+ #table_body.append(table_row)
return table_body
def getTableHeader(self, fd, thisTrait, nCols, attribute_names):
--
cgit v1.2.3
From 5fdbe22fdec6f806984670e9251b29450803fd7d Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Sun, 24 Jun 2012 23:00:11 -0400
Subject: Before changing template for traits
---
wqflask/wqflask/show_trait/DataEditingPage.py | 69 ++++++++++++++++-----------
1 file changed, 40 insertions(+), 29 deletions(-)
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index 38ab8c90..cbda3e41 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import, print_function, division
+
import string
import os
import cPickle
@@ -13,6 +15,7 @@ from dbFunction import webqtlDatabaseFunction
from base.templatePage import templatePage
from basicStatistics import BasicStatisticsFunctions
+from pprint import pformat as pf
#########################################
# DataEditingPage
@@ -1659,32 +1662,32 @@ class DataEditingPage(templatePage):
break
mainForm = None # Just trying to get things working
- 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_strains = 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)):
- print("hji")
- pass
+ #for i in range(len(primary_body)):
+ # print("hji")
+ # pass
#primary_table.append(primary_body[i])
other_strains = []
for strain in thisTrait.data.keys():
print("hjk - strain is:", strain)
if strain not in allstrainlist_neworder:
- pass
- #allstrainlist_neworder.append(strain)
- #other_strains.append(strain)
+ #pass
+ 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_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')
+ #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'))
@@ -1698,12 +1701,12 @@ class DataEditingPage(templatePage):
#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_strains = 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)):
- print("hjn")
- pass
+ #for i in range(len(other_body)):
+ # print("hjn")
+ # pass
#other_table.append(other_body[i])
else:
pass
@@ -1721,11 +1724,13 @@ class DataEditingPage(templatePage):
#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
+ #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(' ', height=30))
#container.append(other_div)
+ self.primary_strains = primary_strains
+ self.other_strains = other_strains
#table.append(HT.TR(HT.TD(container)))
#title5Body.append(table)
@@ -1750,6 +1755,8 @@ class DataEditingPage(templatePage):
upperBound, lowerBound = Plot.findOutliers(vals) # ZS: Values greater than upperBound or less than lowerBound are considered outliers.
+ the_strains = []
+
for i, strainNameOrig in enumerate(strainlist):
strain = {}
print("zyt - strainNameOrig:", strainNameOrig)
@@ -1777,7 +1784,7 @@ class DataEditingPage(templatePage):
traitVal = ''
dispVal = 'x'
- strain['strain_name'] = StrainName
+ strain['strain_name'] = strainName
strainNameDisp = HT.Span(strainName, Class='fs14 fwn ffl')
if varianceDataPage:
@@ -1836,25 +1843,28 @@ class DataEditingPage(templatePage):
#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'):
- strain[the_id] = "Primary_" + str(i+1)
+ if strains == 'primary':
+ strain['the_id'] = "Primary_" + str(i+1)
#table_row = HT.TR(Id="Primary_"+str(i+1), Class=rowClassName)
else:
- strain[the_id] = "Other_" + str(i+1)
+ strain['the_id'] = "Other_" + str(i+1)
#table_row = HT.TR(Id="Other_"+str(i+1), Class=rowClassName)
- if varianceDataPage:
+ strain['value'] = traitVal
+
+ strain['se'] = dispVar
+ #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("±", width=20, align='center', Class=className))
#table_row.append(HT.TD(seField, width=80, align='right', Id="SE_"+str(i)+"_"+strains, Class=className))
- pass
- else:
+ #pass
+ #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))
- pass
+ #pass
if thisTrait and thisTrait.db and thisTrait.db.type =='ProbeSet':
if len(attribute_ids) > 0:
@@ -1892,9 +1902,10 @@ class DataEditingPage(templatePage):
attr_className = str(attributeValue) + " " + className
table_row.append(HT.TD(attr_container, align='right', Class=attr_className))
attr_counter += 1
-
+ the_strains.append(strain)
#table_body.append(table_row)
- return table_body
+ print("*the_strains are [%i]: %s" % (len(the_strains), pf(the_strains)))
+ return the_strains
def getTableHeader(self, fd, thisTrait, nCols, attribute_names):
--
cgit v1.2.3
From 9ab5aa849d344ab49f48b6629eebf95177a6b530 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Mon, 25 Jun 2012 00:29:16 -0400
Subject: Outlier support added
---
wqflask/wqflask/show_trait/DataEditingPage.py | 28 ++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index cbda3e41..39aa19ae 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -1798,22 +1798,24 @@ class DataEditingPage(templatePage):
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 '
+ #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'
+ strain['outlier'] = True
+ #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)
+ strain['outlier'] = False
+ #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):
--
cgit v1.2.3
From 47fdfa932d900ec9d235840ca17e06035f877fd3 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Mon, 25 Jun 2012 02:22:33 -0400
Subject: Creating a new css file for use with flask
---
web/css/general_flask.css | 244 ++++
wqflask/wqflask/show_trait/DataEditingPage.py | 4 +-
wqflask/wqflask/templates/base.html | 2 +-
.../wqflask/templates/trait_data_and_analysis.html | 1489 +-------------------
4 files changed, 274 insertions(+), 1465 deletions(-)
create mode 100755 web/css/general_flask.css
diff --git a/web/css/general_flask.css b/web/css/general_flask.css
new file mode 100755
index 00000000..7a54e7b8
--- /dev/null
+++ b/web/css/general_flask.css
@@ -0,0 +1,244 @@
+@import url(import.css);
+
+body
+{
+ font-family : verdana, geneva, lucida, 'lucida grande', arial, helvetica;
+ font-weight : Normal;
+}
+
+Blockquote {
+ margin : 14px 18px 14px 18px;
+}
+
+/*Font size*/
+.fs10 {font-size : 10px}
+.fs11 {font-size : 11px}
+.fs12 {font-size : 12px}
+.fs13 {font-size : 13px}
+.fs14 {font-size : 14px}
+.fs15 {font-size : 15px}
+.fs16 {font-size : 16px}
+.fs17 {font-size : 17px}
+
+/*Font Weight*/
+.fwb {font-weight : Bold}
+.fwn {font-weight : Normal}
+
+/*Font Style*/
+.fsI {font-style : Italic}
+
+/*Font family*/
+.ffv {font-family : verdana, geneva, lucida, 'lucida grande', arial, helvetica;}
+.ffl {font-family : lucida, verdana, 'lucida grande', helvetica, arial, geneva;}
+.ffmono {font-family : "CourierNew", Courier, mono;}
+
+/*Color*/
+.cr {color : #f00}
+.cg {color : #0f0}
+.cdg {color : darkgreen}
+.cb {color : #00f}
+.c222 {color : #222}
+.c999 {color : #999}
+.c00d {color : #00d}
+.cori {color : #CC9933}
+.crb {color : royalblue}
+.cw {color : #fff}
+.cbl {color : #000000}
+.cydull {color : #cfcf32}
+.cdefault {color : #503A7D}
+
+/*backColor*/
+.cbr {background-color : #f00}
+.cbg {background-color : #0f0}
+.cbdg {background-color : darkgreen}
+.cbb {background-color : #00f}
+.cb222 {background-color : #222}
+.cbg22t {background-color : #FF6}
+.cbg22c {background-color : #5CB3FF}
+.cbg2C {background-color : #1569C7}
+.cbg22a {background-color : #F66}
+.cbg22g {background-color : #CF9}
+.cb00d {background-color : #00d}
+.cb222 {background-color : #222}
+.cbeee {background-color : #eee}
+.cbori {background-color : #CC9933}
+.cbrb {background-color : royalblue}
+.cbdb {background-color : #2D2DB5}
+.cbw {background-color : #fff}
+.cbydull {background-color : #cfcf32}
+.cbrdull {background-color : #c33232}
+.cbgdull {background-color : #32c332}
+.cbbdull {background-color : #1569C7}
+.cbpdull {background-color : #c332c3}
+.cbccc {background-color : #ccc}
+.cbddf {background-color : #ddf}
+
+.nowrap {white-space: nowrap;}
+
+/*Table Cell*/
+.collap {border-collapse : collapse;}
+
+TH.header {
+ background-image: url(/images/bg.gif);
+ background-color: #4169E1;
+ cursor: pointer;
+ background-repeat: no-repeat;
+ background-position: center left;
+ padding-left: 20px;
+ margin-left: -1px;
+}
+TH.headerSortUp {
+ background-image: url(/images/desc.gif);
+ background-color: #4169E1;
+}
+TH.headerSortDown {
+ background-image: url(/images/asc.gif);
+ background-color: #4169E1;
+}
+
+TD, P {color : #222222; font-size : 13px}
+TD.b1 {border : 1px solid #999999; padding : 3px;}
+TH.b1 {border : 1px solid #999999; padding : 3px;}
+TD.bt1 {border-top : 1px solid #999999; padding : 3px;}
+TD.bb1 {border-bottom : 1px solid #999999; padding : 3px;}
+
+.b2 {border : 2px solid royalblue; padding : 3px;}
+
+.bd1 {border : 1px dashed #999999; padding : 6px;}
+
+TD.outlier {background-color : yellow;}
+
+TR.alt td {
+ background: #e6e8fa;
+}
+
+TR.over td {
+ background: #82CFFD;
+}
+
+/*Table Row*/
+.toggleShowHide { color : #0000DD; cursor: pointer;}
+.invisible {display: none;}
+
+/*Link*/
+A.font_black:link {color: #000000; text-decoration : None}
+A.font_black:active {color: #000000; text-decoration : None}
+A.font_black:hover {color: #000000; text-decoration : None}
+A.font_black:visited {color: #000000; text-decoration : None}
+
+A {font-family : lucida, 'lucida grande', verdana, helvetica, arial, geneva;
+ font-weight : Bold; font-size : 13px; text-decoration : None}
+
+A:link, A:visited {color : #0000DD; text-decoration : None}
+
+A:active {color : #FF0000; text-decoration : None}
+
+A:hover {color : #FF0000; text-decoration : None}
+
+A.background_grey {background:#dddddd;padding:2;}
+
+A.non_bold {font-weight : Normal; color : #0000DD;}
+
+/*Border Style*/
+.solidBorder {border : 1px solid #CCCCCC; padding : 2px;}
+.doubleBorder {border : double #AAAAAA; padding : 2px;}
+
+/*Title style*/
+.title {font-weight:Bold; color:#222222; font-size:16px}
+
+.subtitle {font-family : lucida, verdana, 'lucida grande', helvetica, arial, geneva;
+ font-weight:Bold; font-size:14px; color:#000082}
+
+.sectionheader {font-family : arial, verdana, 'lucida grande', helvetica, lucida, geneva;
+ font-weight:Bold; font-size:14px; vertical-align: middle; display:block; color:#000000; background-color:#DDDDDD; line-height:24px; height:24px;}
+
+/*drop shadow*/
+#v3 .wrap1 {background:url(/images/shadow/shadow.gif) right bottom no-repeat;}
+#v3 .wrap2 {background:url(/images/shadow/corner_bl.gif) -12px 100% no-repeat;}
+#v3 .wrap3 {
+ padding:0 9px 9px 0;
+ background:url(/images/shadow/corner_tr.gif) 100% -12px no-repeat;}
+
+
+/*steal from google*/
+
+ .tabsTableBox {
+ width:100%;
+ border-spacing:0;
+ border-collapse:collapse;
+ margin-top:5px;
+ font-size:smaller;
+ text-align:center;
+ }
+ .tabsTableBox td {
+ padding-right:5px;
+ padding-left:5px;
+ padding-bottom:3px;
+ }
+
+/*For making the Custom Strain box in snpBrowser.py a default width, instead of looking weird always*/
+.customBoxWidth {
+ width: 143px;
+}
+ .selectedBox {
+ border-top:1px solid #676767;
+ border-right:1px solid #676767;
+ border-left:1px solid #676767;
+ width:80;
+ font-weight:bolder;
+ color:#3366cc;
+ font-size:12px;
+ }
+ .unselectedBox {
+ background-color:#dddddd;
+ border-top:1px solid #aaaaaa;
+ width:80;
+ border-right:1px solid #aaaaaa;
+ border-left:1px solid #aaaaaa;
+ border-bottom:1px solid #676767;
+ font-size:12px;
+ }
+
+ .spacerTabBox {
+ border-bottom:1px solid #676767;
+ width:5px;
+ }
+
+ .emptyTabBox {
+ border-bottom:1px solid #676767;
+ }
+
+/*For font color of 'Get Any' and 'Combined' in the main page*/
+.searchtip
+{
+color: #999999;
+}
+
+
+/*For font style and color of commands and keywords in the scriptable interface page*/
+.keywords
+{
+font-family : "CourierNew", Courier, mono;
+font-size : 15px;
+color : #0000FF;
+font-weight : Normal
+}
+/*For RIsample.html page*/
+.strains
+{
+border:1px solid #999999;
+border-top:1px solid #940;
+border-bottom:1px solid #940;
+padding:5;
+background-color:#ddf;
+font-family:verdana;
+}
+.values
+{
+border:1px solid #999999;
+border-top:1px solid #940;
+border-bottom:1px solid #940;
+padding:5;
+background-color:#eee;
+font-family:courier;
+}
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index 39aa19ae..fa343535 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -1803,12 +1803,12 @@ class DataEditingPage(templatePage):
#rowClassName = 'novalue '
else:
if (thisval >= upperBound) or (thisval <= lowerBound):
- strain['outlier'] = True
+ strain['outlier'] = "outlier" # We're going to use this as a class, so we want it to be a word
#className = 'fs13 b1 c222 outlier '
#valueClassName = 'fs13 b1 c222 valueField '
#rowClassName = 'outlier'
else:
- strain['outlier'] = False
+ strain['outlier'] = "not_outlier"
#className = 'fs13 b1 c222 '
#valueClassName = 'fs13 b1 c222 valueField '
#rowClassName = ' '
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 117d26fb..6776a71c 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -11,7 +11,7 @@
-
+
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index 39174425..c3bdd787 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -3059,1469 +3059,34 @@
SE
-
-
1
-
-
B6D2F1
-
-
-
-
±
-
-
-
-
-
-
2
-
-
D2B6F1
-
-
-
-
±
-
-
-
-
-
-
3
-
-
C57BL/6J
-
-
-
-
±
-
-
-
-
-
-
4
-
-
DBA/2J
-
-
-
-
±
-
-
-
-
-
-
5
-
-
BXD1
-
-
-
-
±
-
-
-
-
-
-
6
-
-
BXD2
-
-
-
-
±
-
-
-
-
-
-
7
-
-
BXD5
-
-
-
-
±
-
-
-
-
-
-
8
-
-
BXD6
-
-
-
-
±
-
-
-
-
-
-
9
-
-
BXD8
-
-
-
-
±
-
-
-
-
-
-
10
-
-
BXD9
-
-
-
-
±
-
-
-
-
-
-
11
-
-
BXD11
-
-
-
-
±
-
-
-
-
-
-
12
-
-
BXD12
-
-
-
-
±
-
-
-
-
-
-
13
-
-
BXD13
-
-
-
-
±
-
-
-
-
-
-
14
-
-
BXD14
-
-
-
-
±
-
-
-
-
-
-
15
-
-
BXD15
-
-
-
-
±
-
-
-
-
-
-
16
-
-
BXD16
-
-
-
-
±
-
-
-
-
-
-
17
-
-
BXD18
-
-
-
-
±
-
-
-
-
-
-
18
-
-
BXD19
-
-
-
-
±
-
-
-
-
-
-
19
-
-
BXD20
-
-
-
-
±
-
-
-
-
-
-
20
-
-
BXD21
-
-
-
-
±
-
-
-
-
-
-
21
-
-
BXD22
-
-
-
-
±
-
-
-
-
-
-
22
-
-
BXD23
-
-
-
-
±
-
-
-
-
-
-
23
-
-
BXD24a
-
-
-
-
±
-
-
-
-
-
-
24
-
-
BXD24
-
-
-
-
±
-
-
-
-
-
-
25
-
-
BXD25
-
-
-
-
±
-
-
-
-
-
-
26
-
-
BXD27
-
-
-
-
±
-
-
-
-
-
-
27
-
-
BXD28
-
-
-
-
±
-
-
-
-
-
-
28
-
-
BXD29
-
-
-
-
±
-
-
-
-
-
-
29
-
-
BXD30
-
-
-
-
±
-
-
-
-
-
-
30
-
-
BXD31
-
-
-
-
±
-
-
-
-
-
-
31
-
-
BXD32
-
-
-
-
±
-
-
-
-
-
-
32
-
-
BXD33
-
-
-
-
±
-
-
-
-
-
-
33
-
-
BXD34
-
-
-
-
±
-
-
-
-
-
-
34
-
-
BXD35
-
-
-
-
±
-
-
-
-
-
-
35
-
-
BXD36
-
-
-
-
±
-
-
-
-
-
-
36
-
-
BXD37
-
-
-
-
±
-
-
-
-
-
-
37
-
-
BXD38
-
-
-
-
±
-
-
-
-
-
-
38
-
-
BXD39
-
-
-
-
±
-
-
-
-
-
-
39
-
-
BXD40
-
-
-
-
±
-
-
-
-
-
-
40
-
-
BXD41
-
-
-
-
±
-
-
-
-
-
-
41
-
-
BXD42
-
-
-
-
±
-
-
-
-
-
-
42
-
-
BXD43
-
-
-
-
±
-
-
-
-
-
-
43
-
-
BXD44
-
-
-
-
±
-
-
-
-
-
-
44
-
-
BXD45
-
-
-
-
±
-
-
-
-
-
-
45
-
-
BXD48
-
-
-
-
±
-
-
-
-
-
-
46
-
-
BXD49
-
-
-
-
±
-
-
-
-
-
-
47
-
-
BXD50
-
-
-
-
±
-
-
-
-
-
-
48
-
-
BXD51
-
-
-
-
±
-
-
-
-
-
-
49
-
-
BXD52
-
-
-
-
±
-
-
-
-
-
-
50
-
-
BXD53
-
-
-
-
±
-
-
-
-
-
-
51
-
-
BXD54
-
-
-
-
±
-
-
-
-
-
-
52
-
-
BXD55
-
-
-
-
±
-
-
-
-
-
-
53
-
-
BXD56
-
-
-
-
±
-
-
-
-
-
-
54
-
-
BXD59
-
-
-
-
±
-
-
-
-
-
-
55
-
-
BXD60
-
-
-
-
±
-
-
-
-
-
-
56
-
-
BXD61
-
-
-
-
±
-
-
-
-
-
-
57
-
-
BXD62
-
-
-
-
±
-
-
-
-
-
-
58
-
-
BXD63
-
-
-
-
±
-
-
-
-
-
-
59
-
-
BXD64
-
-
-
-
±
-
-
-
-
-
-
60
-
-
BXD65
-
-
-
-
±
-
-
-
-
-
-
61
-
-
BXD66
-
-
-
-
±
-
-
-
-
-
-
62
-
-
BXD67
-
-
-
-
±
-
-
-
-
-
-
63
-
-
BXD68
-
-
-
-
±
-
-
-
-
-
-
64
-
-
BXD69
-
-
-
-
±
-
-
-
-
-
-
65
-
-
BXD70
-
-
-
-
±
-
-
-
-
-
-
66
-
-
BXD71
-
-
+ {% for strain in primary_strains %}
+
+
+ {{ loop.index }}
+
+
+
+
+ {{ strain.strain_name }}
+
+
+
+
+
+
+
+ ±
+
+
+
+
+
+ {% endfor %}
-
±
-
-
-
-
-
-
67
-
-
BXD72
-
-
-
-
±
-
-
-
-
-
-
68
-
-
BXD73
-
-
-
-
±
-
-
-
-
-
-
69
-
-
BXD74
-
-
-
-
±
-
-
-
-
-
-
70
-
-
BXD75
-
-
-
-
±
-
-
-
-
-
-
71
-
-
BXD76
-
-
-
-
±
-
-
-
-
-
-
72
-
-
BXD77
-
-
-
-
±
-
-
-
-
-
-
73
-
-
BXD78
-
-
-
-
±
-
-
-
-
-
-
74
-
-
BXD79
-
-
-
-
±
-
-
-
-
-
-
75
-
-
BXD80
-
-
-
-
±
-
-
-
-
-
-
76
-
-
BXD81
-
-
-
-
±
-
-
-
-
-
-
77
-
-
BXD83
-
-
-
-
±
-
-
-
-
-
-
78
-
-
BXD84
-
-
-
-
±
-
-
-
-
-
-
79
-
-
BXD85
-
-
-
-
±
-
-
-
-
-
-
80
-
-
BXD86
-
-
-
-
±
-
-
-
-
-
-
81
-
-
BXD87
-
-
-
-
±
-
-
-
-
-
-
82
-
-
BXD88
-
-
-
-
±
-
-
-
-
-
-
83
-
-
BXD89
-
-
-
-
±
-
-
-
-
-
-
84
-
-
BXD90
-
-
-
-
±
-
-
-
-
-
-
85
-
-
BXD91
-
-
-
-
±
-
-
-
-
-
-
86
-
-
BXD92
-
-
-
-
±
-
-
-
-
-
-
87
-
-
BXD93
-
-
-
-
±
-
-
-
-
-
-
88
-
-
BXD94
-
-
-
-
±
-
-
-
-
-
-
89
-
-
BXD95
-
-
-
-
±
-
-
-
-
-
-
90
-
-
BXD96
-
-
-
-
±
-
-
-
-
-
-
91
-
-
BXD97
-
-
-
-
±
-
-
-
-
-
-
92
-
-
BXD98
-
-
-
-
±
-
-
-
-
-
-
93
-
-
BXD99
-
-
-
-
±
-
-
-
-
-
-
94
-
-
BXD100
-
-
-
-
±
-
-
-
-
-
-
95
-
-
BXD101
-
-
-
-
±
-
-
-
-
-
-
96
-
-
BXD102
-
-
-
-
±
-
-
-
-
-
-
97
-
-
BXD103
-
-
-
-
±
-
-
-
--
cgit v1.2.3
From f94b7e23d1026fec0b778e1754e01c5050d20444 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Mon, 25 Jun 2012 02:32:32 -0400
Subject: Modified css
---
web/css/general_flask.css | 56 +++++++++++++++++++++++------------------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/web/css/general_flask.css b/web/css/general_flask.css
index 7a54e7b8..d0cffbc4 100755
--- a/web/css/general_flask.css
+++ b/web/css/general_flask.css
@@ -1,6 +1,6 @@
@import url(import.css);
-body
+body
{
font-family : verdana, geneva, lucida, 'lucida grande', arial, helvetica;
font-weight : Normal;
@@ -78,23 +78,23 @@ Blockquote {
/*Table Cell*/
.collap {border-collapse : collapse;}
-TH.header {
+TH.header {
background-image: url(/images/bg.gif);
- background-color: #4169E1;
- cursor: pointer;
- background-repeat: no-repeat;
- background-position: center left;
- padding-left: 20px;
- margin-left: -1px;
-}
-TH.headerSortUp {
- background-image: url(/images/desc.gif);
- background-color: #4169E1;
-}
-TH.headerSortDown {
- background-image: url(/images/asc.gif);
- background-color: #4169E1;
-}
+ background-color: #4169E1;
+ cursor: pointer;
+ background-repeat: no-repeat;
+ background-position: center left;
+ padding-left: 20px;
+ margin-left: -1px;
+}
+TH.headerSortUp {
+ background-image: url(/images/desc.gif);
+ background-color: #4169E1;
+}
+TH.headerSortDown {
+ background-image: url(/images/asc.gif);
+ background-color: #4169E1;
+}
TD, P {color : #222222; font-size : 13px}
TD.b1 {border : 1px solid #999999; padding : 3px;}
@@ -106,7 +106,7 @@ TD.bb1 {border-bottom : 1px solid #999999; padding : 3px;}
.bd1 {border : 1px dashed #999999; padding : 6px;}
-TD.outlier {background-color : yellow;}
+TR.outlier, TD.outlier {background-color : yellow;}
TR.alt td {
background: #e6e8fa;
@@ -126,7 +126,7 @@ A.font_black:active {color: #000000; text-decoration : None}
A.font_black:hover {color: #000000; text-decoration : None}
A.font_black:visited {color: #000000; text-decoration : None}
-A {font-family : lucida, 'lucida grande', verdana, helvetica, arial, geneva;
+A {font-family : lucida, 'lucida grande', verdana, helvetica, arial, geneva;
font-weight : Bold; font-size : 13px; text-decoration : None}
A:link, A:visited {color : #0000DD; text-decoration : None}
@@ -137,7 +137,7 @@ A:hover {color : #FF0000; text-decoration : None}
A.background_grey {background:#dddddd;padding:2;}
-A.non_bold {font-weight : Normal; color : #0000DD;}
+A.non_bold {font-weight : Normal; color : #0000DD;}
/*Border Style*/
.solidBorder {border : 1px solid #CCCCCC; padding : 2px;}
@@ -146,10 +146,10 @@ A.non_bold {font-weight : Normal; color : #0000DD;}
/*Title style*/
.title {font-weight:Bold; color:#222222; font-size:16px}
-.subtitle {font-family : lucida, verdana, 'lucida grande', helvetica, arial, geneva;
+.subtitle {font-family : lucida, verdana, 'lucida grande', helvetica, arial, geneva;
font-weight:Bold; font-size:14px; color:#000082}
-
-.sectionheader {font-family : arial, verdana, 'lucida grande', helvetica, lucida, geneva;
+
+.sectionheader {font-family : arial, verdana, 'lucida grande', helvetica, lucida, geneva;
font-weight:Bold; font-size:14px; vertical-align: middle; display:block; color:#000000; background-color:#DDDDDD; line-height:24px; height:24px;}
/*drop shadow*/
@@ -174,7 +174,7 @@ A.non_bold {font-weight : Normal; color : #0000DD;}
padding-right:5px;
padding-left:5px;
padding-bottom:3px;
- }
+ }
/*For making the Custom Strain box in snpBrowser.py a default width, instead of looking weird always*/
.customBoxWidth {
@@ -186,7 +186,7 @@ A.non_bold {font-weight : Normal; color : #0000DD;}
border-left:1px solid #676767;
width:80;
font-weight:bolder;
- color:#3366cc;
+ color:#3366cc;
font-size:12px;
}
.unselectedBox {
@@ -198,16 +198,16 @@ A.non_bold {font-weight : Normal; color : #0000DD;}
border-bottom:1px solid #676767;
font-size:12px;
}
-
+
.spacerTabBox {
border-bottom:1px solid #676767;
width:5px;
}
-
+
.emptyTabBox {
border-bottom:1px solid #676767;
}
-
+
/*For font color of 'Get Any' and 'Combined' in the main page*/
.searchtip
{
--
cgit v1.2.3
From 3a222b876cf291921194d9f0e2dd3fc8e6a999a2 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Mon, 25 Jun 2012 04:43:00 -0400
Subject: checkpoint
---
wqflask/wqflask/show_trait/DataEditingPage.py | 54 +--
.../wqflask/templates/trait_data_and_analysis.html | 518 +--------------------
2 files changed, 36 insertions(+), 536 deletions(-)
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index fa343535..b1cf5a32 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -1817,33 +1817,33 @@ class DataEditingPage(templatePage):
# 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:
- pass
- #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:
- pass
- #valueField = HT.Input(name=strainNameOrig, size=8, maxlength=8, style="text-align:right; background-color:#FFFFFF;", value=dispVal, Class=valueClassName)
- if varianceDataPage:
- pass
- #seField = HT.Input(name='V'+strainNameOrig, size=8, maxlength=8, style="text-align:right", value=dispVar, Class=varClassName)
- else:
- pass
- #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:
- pass
- #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 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:
+ # pass
+ # #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:
+ # pass
+ # #valueField = HT.Input(name=strainNameOrig, size=8, maxlength=8, style="text-align:right; background-color:#FFFFFF;", value=dispVal, Class=valueClassName)
+ # if varianceDataPage:
+ # pass
+ # #seField = HT.Input(name='V'+strainNameOrig, size=8, maxlength=8, style="text-align:right", value=dispVar, Class=varClassName)
+ #else:
+ # pass
+ # #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:
+ # pass
+ # #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':
strain['the_id'] = "Primary_" + str(i+1)
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index c3bdd787..efd87acc 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -3045,8 +3045,11 @@
and samples with no value (x) can be hidden by clicking Hide No Value .
-
-
+ {% for strain_type in (primary_strains, other_strains) %}
+
{# Slightly tortuous, but best way to get the id we need #}
+
Index
@@ -3059,7 +3062,7 @@
SE
- {% for strain in primary_strains %}
+ {% for strain in strain_type %}
{{ loop.index }}
@@ -3089,518 +3092,15 @@
-
-
-
-
-
-
Index
-
-
Sample
-
-
Value
-
-
-
-
SE
-
-
-
-
1
-
-
B6D2F1
-
-
-
-
±
-
-
-
-
-
-
2
-
-
D2B6F1
-
-
-
-
±
-
-
-
-
-
-
3
-
-
C57BL/6J
-
-
-
-
±
-
-
-
-
-
-
4
-
-
DBA/2J
-
-
-
-
±
-
-
-
-
-
-
5
-
-
129S1/SvImJ
-
-
-
-
±
-
-
-
-
-
-
6
-
-
A/J
-
-
-
-
±
-
-
-
-
-
-
7
-
-
AKR/J
-
-
-
-
±
-
-
-
-
-
-
8
-
-
BALB/cByJ
-
-
-
-
±
-
-
-
-
-
-
9
-
-
BALB/cJ
-
-
-
-
±
-
-
-
-
-
-
10
-
-
C3H/HeJ
-
-
-
-
±
-
-
-
-
-
-
11
-
-
C57BL/6ByJ
-
-
-
-
±
-
-
-
-
-
-
12
-
-
CAST/EiJ
-
-
-
-
±
-
-
-
-
-
-
13
-
-
CXB1
-
-
-
-
±
-
-
-
-
-
-
14
-
-
CXB10
-
-
-
-
±
-
-
-
-
-
-
15
-
-
CXB11
-
-
-
-
±
-
-
-
-
-
-
16
-
-
CXB12
-
-
-
-
±
-
-
-
-
-
-
17
-
-
CXB13
-
-
-
-
±
-
-
-
-
-
-
18
-
-
CXB2
-
-
-
-
±
-
-
-
-
-
-
19
-
-
CXB3
-
-
-
-
±
-
-
-
-
-
-
20
-
-
CXB4
-
-
-
-
±
-
-
-
-
-
-
21
-
-
CXB5
-
-
-
-
±
-
-
-
-
-
-
22
-
-
CXB6
-
-
-
-
±
-
-
-
-
-
-
23
-
-
CXB7
-
-
-
-
±
-
-
-
-
-
-
24
-
-
CXB8
-
-
-
-
±
-
-
-
-
-
-
25
-
-
CXB9
-
-
-
-
±
-
-
-
-
-
-
26
-
-
KK/HlJ
-
-
-
-
±
-
-
-
-
-
-
27
-
-
LG/J
-
-
-
-
±
-
-
-
-
-
-
28
-
-
NOD/ShiLtJ
-
-
-
-
±
-
-
-
-
-
-
29
-
-
NZO/HlLtJ
-
-
-
-
±
-
-
-
-
-
-
30
-
-
PWD/PhJ
-
-
-
-
±
-
-
-
-
-
-
31
-
-
PWK/PhJ
-
-
-
-
±
-
-
-
-
-
-
32
-
-
WSB/EiJ
-
-
-
-
±
-
-
-
-
-
+ {% endfor %}
-
+
+
--
cgit v1.2.3
From 877e0832959c0ab9e7ad417cfdc233b450274a8d Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Fri, 29 Jun 2012 16:49:08 -0400
Subject: Added dataSharing to flask directory
---
wqflask/dataSharing/SharingBody.py | 290 ++++++++++++++++++++++++++
wqflask/dataSharing/SharingInfo.py | 98 +++++++++
wqflask/dataSharing/SharingInfoAddPage.py | 47 +++++
wqflask/dataSharing/SharingInfoDeletePage.py | 55 +++++
wqflask/dataSharing/SharingInfoEditPage.py | 51 +++++
wqflask/dataSharing/SharingInfoPage.py | 52 +++++
wqflask/dataSharing/SharingInfoUpdatePage.py | 109 ++++++++++
wqflask/dataSharing/SharingListDataSetPage.py | 99 +++++++++
wqflask/dataSharing/SharingPage.py | 40 ++++
wqflask/dataSharing/__init__.py | 0
10 files changed, 841 insertions(+)
create mode 100755 wqflask/dataSharing/SharingBody.py
create mode 100755 wqflask/dataSharing/SharingInfo.py
create mode 100755 wqflask/dataSharing/SharingInfoAddPage.py
create mode 100755 wqflask/dataSharing/SharingInfoDeletePage.py
create mode 100755 wqflask/dataSharing/SharingInfoEditPage.py
create mode 100755 wqflask/dataSharing/SharingInfoPage.py
create mode 100755 wqflask/dataSharing/SharingInfoUpdatePage.py
create mode 100755 wqflask/dataSharing/SharingListDataSetPage.py
create mode 100755 wqflask/dataSharing/SharingPage.py
create mode 100755 wqflask/dataSharing/__init__.py
diff --git a/wqflask/dataSharing/SharingBody.py b/wqflask/dataSharing/SharingBody.py
new file mode 100755
index 00000000..4445e0d1
--- /dev/null
+++ b/wqflask/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 = """
+
About the cases used to generate this set of data:
+
%s
+
About the tissue used to generate this set of data:
+
%s
+
About downloading this data set:
+
%s
+
About the array platform:
+
%s
+
About data values and data processing:
+
%s
+
Data source acknowledgment:
+
%s
+
Experiment Type:
+
%s
+
Overall Design:
+
%s
+
Contributor:
+
%s
+
Citation:
+
%s
+
Submission Date:
+
%s
+
Laboratory:
+
%s
+
Samples:
+
%s
+
+
+
+"""
+
+sharinginfoedit_body_string = """
+
%s
+
+
+
+
+
+
Principal Investigator
+
Contact Name:
+
Emails:
+
Phone:
+
URL:
+
Organization Name:
+
Department:
+
Laboratory:
+
Address:
+
City:
+
State:
+
ZIP:
+
Country:
+
+
Summary
+
Summary:
+
+
Biology
+
Experiment Design:
+
About the cases used to generate this set of data:
+
About the tissue used to generate this set of data:
+
+
Technique
+
About downloading this data set:
+
About the array platform:
+
+
Bioinformatics
+
About data values and data processing:
+
Overall Design:
+
+
Misc
+
Contributor:
+
Citation:
+
Data source acknowledgment:
+
+
Administrator ONLY
+
GN Accesion Id:
+
DB Title in GN:
+
GEO Series:
+
Status:
+
Title:
+
Organism_Id (Taxonomy ID):
+
Organism:
+
Submission Date:
+
Platforms:
+
Species:
+
Tissue:
+
Normalization:
+
Inbred Set:
+
Info Page Name:
+
Samples:
+
Authorized Users:
+
Progress:
+
+
+
+
+
+
"""
diff --git a/wqflask/dataSharing/SharingInfo.py b/wqflask/dataSharing/SharingInfo.py
new file mode 100755
index 00000000..10abcefa
--- /dev/null
+++ b/wqflask/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 = '
\n'
+ for i in range(len(filelist)):
+ if i%2==0:
+ filename = filelist[i]
+ filesize = filelist[i+1]
+ htmlfilelist += "
"
+ 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/wqflask/dataSharing/SharingInfoAddPage.py b/wqflask/dataSharing/SharingInfoAddPage.py
new file mode 100755
index 00000000..8174bf68
--- /dev/null
+++ b/wqflask/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/wqflask/dataSharing/SharingInfoDeletePage.py b/wqflask/dataSharing/SharingInfoDeletePage.py
new file mode 100755
index 00000000..edc0be7d
--- /dev/null
+++ b/wqflask/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/wqflask/dataSharing/SharingInfoEditPage.py b/wqflask/dataSharing/SharingInfoEditPage.py
new file mode 100755
index 00000000..266b8602
--- /dev/null
+++ b/wqflask/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/wqflask/dataSharing/SharingInfoPage.py b/wqflask/dataSharing/SharingInfoPage.py
new file mode 100755
index 00000000..230ba2f3
--- /dev/null
+++ b/wqflask/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/wqflask/dataSharing/SharingInfoUpdatePage.py b/wqflask/dataSharing/SharingInfoUpdatePage.py
new file mode 100755
index 00000000..a70238b9
--- /dev/null
+++ b/wqflask/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/wqflask/dataSharing/SharingListDataSetPage.py b/wqflask/dataSharing/SharingListDataSetPage.py
new file mode 100755
index 00000000..ec90f5f3
--- /dev/null
+++ b/wqflask/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(" ")
+ operation.append(operation_delete)
+ datasetRow.append(operation)
+ datasetTable.append(datasetRow)
+
+ TD_LR.append(heading, HT.P(), newrecord, HT.P(), info, HT.P(), datasetTable)
+
+ js1 = """ """
+ self.dict['js1'] = js1
+ self.dict['body'] = str(TD_LR)
\ No newline at end of file
diff --git a/wqflask/dataSharing/SharingPage.py b/wqflask/dataSharing/SharingPage.py
new file mode 100755
index 00000000..cf1d9ac3
--- /dev/null
+++ b/wqflask/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/wqflask/dataSharing/__init__.py b/wqflask/dataSharing/__init__.py
new file mode 100755
index 00000000..e69de29b
--
cgit v1.2.3
From d67019ce6d763b983d17b6bd2fb573f61618ea09 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Fri, 29 Jun 2012 18:23:39 -0400
Subject: working on data_sharing
---
wqflask/wqflask/dataSharing/SharingBody.py | 290 +++++++
wqflask/wqflask/dataSharing/SharingInfo.py | 98 +++
wqflask/wqflask/dataSharing/SharingInfoAddPage.py | 47 ++
.../wqflask/dataSharing/SharingInfoDeletePage.py | 55 ++
wqflask/wqflask/dataSharing/SharingInfoEditPage.py | 51 ++
wqflask/wqflask/dataSharing/SharingInfoPage.py | 58 ++
.../wqflask/dataSharing/SharingInfoUpdatePage.py | 109 +++
.../wqflask/dataSharing/SharingListDataSetPage.py | 99 +++
wqflask/wqflask/dataSharing/SharingPage.py | 40 +
wqflask/wqflask/dataSharing/__init__.py | 0
wqflask/wqflask/templates/data_sharing.html | 831 +++++++++++++++++++++
wqflask/wqflask/templates/index_page.html | 3 +-
wqflask/wqflask/views.py | 19 +-
13 files changed, 1696 insertions(+), 4 deletions(-)
create mode 100755 wqflask/wqflask/dataSharing/SharingBody.py
create mode 100755 wqflask/wqflask/dataSharing/SharingInfo.py
create mode 100755 wqflask/wqflask/dataSharing/SharingInfoAddPage.py
create mode 100755 wqflask/wqflask/dataSharing/SharingInfoDeletePage.py
create mode 100755 wqflask/wqflask/dataSharing/SharingInfoEditPage.py
create mode 100755 wqflask/wqflask/dataSharing/SharingInfoPage.py
create mode 100755 wqflask/wqflask/dataSharing/SharingInfoUpdatePage.py
create mode 100755 wqflask/wqflask/dataSharing/SharingListDataSetPage.py
create mode 100755 wqflask/wqflask/dataSharing/SharingPage.py
create mode 100755 wqflask/wqflask/dataSharing/__init__.py
create mode 100644 wqflask/wqflask/templates/data_sharing.html
diff --git a/wqflask/wqflask/dataSharing/SharingBody.py b/wqflask/wqflask/dataSharing/SharingBody.py
new file mode 100755
index 00000000..880161f5
--- /dev/null
+++ b/wqflask/wqflask/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 = """
+
About the cases used to generate this set of data:
+
%s
+
About the tissue used to generate this set of data:
+
%s
+
About downloading this data set:
+
%s
+
About the array platform:
+
%s
+
About data values and data processing:
+
%s
+
Data source acknowledgment:
+
%s
+
Experiment Type:
+
%s
+
Overall Design:
+
%s
+
Contributor:
+
%s
+
Citation:
+
%s
+
Submission Date:
+
%s
+
Laboratory:
+
%s
+
Samples:
+
%s
+
+
+
+"""
+
+sharinginfoedit_body_string = """
+
%s
+
+
+
+
+
+
Principal Investigator
+
Contact Name:
+
Emails:
+
Phone:
+
URL:
+
Organization Name:
+
Department:
+
Laboratory:
+
Address:
+
City:
+
State:
+
ZIP:
+
Country:
+
+
Summary
+
Summary:
+
+
Biology
+
Experiment Design:
+
About the cases used to generate this set of data:
+
About the tissue used to generate this set of data:
+
+
Technique
+
About downloading this data set:
+
About the array platform:
+
+
Bioinformatics
+
About data values and data processing:
+
Overall Design:
+
+
Misc
+
Contributor:
+
Citation:
+
Data source acknowledgment:
+
+
Administrator ONLY
+
GN Accesion Id:
+
DB Title in GN:
+
GEO Series:
+
Status:
+
Title:
+
Organism_Id (Taxonomy ID):
+
Organism:
+
Submission Date:
+
Platforms:
+
Species:
+
Tissue:
+
Normalization:
+
Inbred Set:
+
Info Page Name:
+
Samples:
+
Authorized Users:
+
Progress:
+
+
+
+
+
+
"""
diff --git a/wqflask/wqflask/dataSharing/SharingInfo.py b/wqflask/wqflask/dataSharing/SharingInfo.py
new file mode 100755
index 00000000..131a4551
--- /dev/null
+++ b/wqflask/wqflask/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 = '
\n'
+ for i in range(len(filelist)):
+ if i%2==0:
+ filename = filelist[i]
+ filesize = filelist[i+1]
+ htmlfilelist += "
"
+ 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/wqflask/wqflask/dataSharing/SharingInfoAddPage.py b/wqflask/wqflask/dataSharing/SharingInfoAddPage.py
new file mode 100755
index 00000000..452fb474
--- /dev/null
+++ b/wqflask/wqflask/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/wqflask/wqflask/dataSharing/SharingInfoDeletePage.py b/wqflask/wqflask/dataSharing/SharingInfoDeletePage.py
new file mode 100755
index 00000000..a9c785c6
--- /dev/null
+++ b/wqflask/wqflask/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
diff --git a/wqflask/wqflask/dataSharing/SharingInfoEditPage.py b/wqflask/wqflask/dataSharing/SharingInfoEditPage.py
new file mode 100755
index 00000000..c5f4ed22
--- /dev/null
+++ b/wqflask/wqflask/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/wqflask/wqflask/dataSharing/SharingInfoPage.py b/wqflask/wqflask/dataSharing/SharingInfoPage.py
new file mode 100755
index 00000000..4e07e01b
--- /dev/null
+++ b/wqflask/wqflask/dataSharing/SharingInfoPage.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
+
+from __future__ import print_function, division
+
+from pprint import pformat as pf
+
+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):
+ templatePage.__init__(self, fd)
+ print("fd is:", pf(fd.__dict__))
+ # Todo: Need a [0] in line below????
+ GN_AccessionId = fd.get('GN_AccessionId') # Used under search datasharing
+ InfoPageName = fd['database'][0]
+ 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/wqflask/wqflask/dataSharing/SharingInfoUpdatePage.py b/wqflask/wqflask/dataSharing/SharingInfoUpdatePage.py
new file mode 100755
index 00000000..181f2eed
--- /dev/null
+++ b/wqflask/wqflask/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)
diff --git a/wqflask/wqflask/dataSharing/SharingListDataSetPage.py b/wqflask/wqflask/dataSharing/SharingListDataSetPage.py
new file mode 100755
index 00000000..8685ac65
--- /dev/null
+++ b/wqflask/wqflask/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(" ")
+ operation.append(operation_delete)
+ datasetRow.append(operation)
+ datasetTable.append(datasetRow)
+
+ TD_LR.append(heading, HT.P(), newrecord, HT.P(), info, HT.P(), datasetTable)
+
+ js1 = """ """
+ self.dict['js1'] = js1
+ self.dict['body'] = str(TD_LR)
diff --git a/wqflask/wqflask/dataSharing/SharingPage.py b/wqflask/wqflask/dataSharing/SharingPage.py
new file mode 100755
index 00000000..b244a6bd
--- /dev/null
+++ b/wqflask/wqflask/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();"'
diff --git a/wqflask/wqflask/dataSharing/__init__.py b/wqflask/wqflask/dataSharing/__init__.py
new file mode 100755
index 00000000..e69de29b
diff --git a/wqflask/wqflask/templates/data_sharing.html b/wqflask/wqflask/templates/data_sharing.html
new file mode 100644
index 00000000..e9d082d6
--- /dev/null
+++ b/wqflask/wqflask/templates/data_sharing.html
@@ -0,0 +1,831 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
MOST HIGHLY RECOMMENDED DATA SET (Overall et al., 2009): The Hippocampus Consortium data set provides estimates of mRNA expression in the adult hippocampus of 99 genetically diverse strains of mice including 67 BXD recombinant inbred strains, 13 CXB recombinant inbred strains, a diverse set of common inbred strains, and two reciprocal F1 hybrids.
+
+
+
The hippocampus is an important and intriguing part of the forebrain that is crucial in memory formation and retrieval, and that is often affected in epilepsy, Alzheimer's disease, and schizophrenia. Unlike most other parts of the brain, the hippocampus contains a remarkable population of stems cells that continue to generate neurons and glial cells even in adult mammals (Kempermann, 2005). This genetic analysis of transcript expression in the hippocampus (dentate gyrus, CA1-CA3) is a joint effort of 14 investigators that is supported by numerous agencies described in the acknowledgments section.
+
+
+
About the cases used to generate this set of data:
+
The BXD genetic reference panel of recombinant inbred strains consists of just over 80 strains. The BXDs in this data set include 27 of the BXD strains made by Benjamin Taylor at the Jackson Laboratory in the 1970s and 1990s (BXD1 through BXD42). All of these strains are fully inbred, many well beyond the 100th filial (F) generation of inbreeding. We have also included 39 inbred (25 strains at F20+) and nearly inbred (14 strains between F14 and F20) BXD lines generated by Lu and Peirce. All of these strains, including those between F14 and F20, have been genotyped at 13,377 SNPs.
+
+
Mouse Diversity Panel (MDP). We have profiled a MDP consisting 16 inbred strains and a pair of reciprocal F1 hybrids; B6D2F1 and D2B6F1. These strains were selected for several reasons:
+
+
genetic and phenotypic diversity, including use by the Phenome Project
+
their use in making genetic reference populations including recombinant inbred strains, cosomic strains, congenic and recombinant congenic strains
+
their use by the Complex Trait Consortium to make the Collaborative Cross (Nairobi/Wellcome, Oak Ridge/DOE, and Perth/UWA)
+
genome sequence data from three sources (NHGRI, Celera, and Perlegen-NIEHS)
+
availability from The Jackson Laboratory
+
+
+
All eight parents of the Collaborative Cross (129, A, C57BL/6J, CAST, NOD, NZO, PWK, and WSB) have been included in the MDP (noted below in the list). Twelve MDP strains have been sequenced, or are currently being resequenced by Perlegen for the NIEHS. This panel will be extremely helpful in systems genetic analysis of a wide variety of traits, and will be a powerful adjunct in fine mapping modulators using what is essentially an association analysis of sequence variants.
+
+
+
129S1/SvImJ
+ Collaborative Cross strain sequenced by NIEHS; background for many knockouts; Phenome Project A list
+
+
A/J
+ Collaborative Cross strain sequenced by Perlegen/NIEHS; parent of the AXB/BXA panel
+
+
AKR/J
+ Sequenced by NIEHS; Phenome Project B list
+
+
BALB/cByJ
+ Sequenced by NIEHS; maternal parent of the CXB panel; Phenome Project A list
+
+
BALB/cJ
+ Widely used strain with forebrain abnormalities (callosal defects); Phenome Project A list
+
+
C3H/HeJ Sequenced by Perlegen/NIEHS; paternal parent of the BXH panel; Phenome Project A list
+
+
C57BL/6J
+ Sequenced by NHGRI; parental strain of AXB/BXA, BXD, and BXH; Phenome Project A list
+
+
C57BL/6ByJ
+ Paternal substrain of B6 used to generate the CXB panel
+
+
CAST/Ei
+ Collaborative Cross strain sequenced by NIEHS; Phenome Project A list
+
+
DBA/2J
+ Sequenced by Perlegen/NIEHS and Celera; paternal parent of the BXD panel; Phenome Project A list
+
+
PWD/PhJ
+ Sequenced by Perlegen/NIEHS; parental strain for a consomic set by Forjet and colleagues
+
+
PWK/PhJ
+ Collaborative Cross strain; Phenome Project D list
+
+
WSB/EiJ Collaborative Cross strain sequenced by NIEHS; Phenome Project C list
+
+
B6D2F1 and D2B6F1
+ F1 hybrids generated by crossing C57BL/6J with DBA/2J
+
+
+
We have not combined data from reciprocal F1s because they have different Y chromosome and mitochondrial haplotypes. Parent-of-origin effects (imprinting, maternal environment) may also lead to interesting differences in hippocampal transcript levels.
+
+
These strains are available from The Jackson Laboratory. BXD43 through BXD100 strains are available from Lu Lu and colleagues at UTHSC.
+
About the tissue used to generate this set of data:
+
BXD animals were obtained from UTHSC, UAB, or directly from The Jackson Laboratory (see Table 1 below). Animals were housed at UTHSC, Beth Israel Deaconess, or the Jackson Laboratory before sacrifice. Virtually all CXB animals were obtained directly at the Jackson Laboratory by Lu Lu. We thank Muriel Davisson for making it possible to collect these cases on site. Standard inbred strain stock was from The Jackson Laboratory, but most animals were housed or reared at UTHSC. Mice were killed by cervical dislocation and brains were removed and placed in RNAlater prior to dissection. Cerebella and olfactory bulbs were removed; brains were hemisected, and both hippocampi were dissected whole by Hong Tao Zhang in the Lu lab. Hippocampal samples are very close to complete (see Lu et al., 2001) but probably include variable amounts of subiculum and fimbria.
+
+
A great majority of animals used in this study were between 45 and 90 days of age (average of 66 days, maximum range from 41 to 196 days; see Table 1 below). All animals were sacrifice between 9 AM and 5 PM during the light phase.
+
+
+
A pool of dissected tissue typically from six hippocampi and three naive adults of the same strain, sex, and age was collected in one session and used to generate cRNA samples. Two-hundred and one RNA samples were extracted at UTHSC by Zhiping Jia, four samples by Shuhua Qi (R2331H1, R2332H1, P2350H1, R2349H1), and one by Siming Shou (R0129H2).
+
+
RNA Extraction: In brief, we used the RNA STAT-60 protocol (TEL-TEST "B" Bulletin No. 1), steps 5.1A (homogenization of tissue), 5.2 (RNA extraction), 5.3 (RNA precipitation), and 5.4 (RNA wash). In Step 5.4 we stopped after adding 75% ethanol (1 ml per 1 ml RNA STAT-60) and stored the mix at -80°C until further use. Before RNA labeling we thawed samples and proceeded with the remainder of Step 5.4; pelleting, drying, and redissolving the pellet in RNase-free water.
+
+
We finally purify RNA by using Na4OAc before running arrays. Here is the detailed method:
+
+
Final RNA purification protocol
+
+
+
Add 1/10th volume of 3M Na4OAc , pH 5.2. If the sample was eluted with 100 µl nuclease-free water as suggested, this will be 10 µl of 3M Na4OAc.
+
Add 2.5 volumes of 100% ethanol (250 µl if the RNA was eluted in100 µl). Mix well and incubate at –20°C for 2 hrs.
+
Centrifuge at speed of 13,000 rpm for 20 min at 4°C. Carefully remove and discard the supernatant.
+
Wash the pellet with 800 µl 75% cold ethanol, centrifuge at speed of 8,600 rpm for 5 min, and remove the 75% ethanol. Wash again.
+
To remove the last traces of ethanol, quickly respin the tube, and aspirate any residual fluid.
+
Air dry the pellet.
+
Resuspend pellet in nuclease-free water.
+
+
+
+
+
Sample Processing: Samples were processed in the INIA Bioanalytical Core at the W. Harry Feinstone Center for Genomic Research, The University of Memphis, led by Thomas R. Sutter. All processing steps were performed by Shirlean Goodwin. In brief, RNA purity was evaluated using the 260/280 nm absorbance ratio, and values had to be greater than 1.8. The majority of samples were 1.9 to 2.1. RNA integrity was assessed using the Agilent Bioanalyzer 2100. We required an RNA integrity number (RIN) of greater than 8. This RIN value is based on the intensity ratio and amplitude of 18S and 28S rRNA signals. The standard Eberwine T7 polymerase method was used to catalyze the synthesis of cDNA template from polyA-tailed RNA using Superscript II reverse transcriptase (Invitrogen Inc.). The Enzo Life Sciences, Inc., BioArray High Yield RNA Transcript Labeling Kit (T7, Part No. 42655) was used to synthesize labeled cRNA. The cRNA was evaluated using both the 260/280 ratio (values of 2.0 or 2.1 are acceptable) and the Bioanalyzer output (a dark cRNA smear on the 2100 output centered roughly between 600 and 2000 nucleotides is required). Those samples that passed both QC steps (10% usually failed and new RNA samples had to be acquired and processed) were then sheared using a fragmentation buffer included in the Affymetrix GeneChip Sample Cleanup Module (Part No. 900371). Fragmented cRNA samples were either stored at -80°C until use or were immediately injected onto the array. The arrays were hybridized and washed following standard Affymetrix protocols.
+
+
Replication and Sample Balance: Our goal was to obtain a male sample pool and female sample pool from each isogenic group. While almost all strains were orginally represented by matched male and female samples, not all data sets passed the final quality control steps. All but 5 of 99 strains (BXD55, BXD86, BXD94, BALB/cByJ, and CAST/EiJ) are represented by pairs or (rarely) trios of arrays. The first and last samples are technical replicates of a B6D2F1 hippocampal pool (aliquots R1291H3 and R1291H4).
+
+
+
Sex Balance: Based on the expression of Xist, probe set 1427262_at, DBA/2J and KK/HlJ are represented only by female samples, BXD55, and BALB/cByJ are only represented by a single male sample, BXD74 is represented by two male samples, and BXD86, BXD94, and CAST/EiJ are possibly mixed sex samples. One of the BXD9 samples, array R1523, may be a mixed sex sample pool because the expression of Xist is intermediate.
+
+
Experimental Design and Batch Structure: This data set consists arrays processed in six groups over a three month period (May 2005 to August 2005). Each group consists of 32 to 34 arrays. Sex, strain, and strain type (BXD, CXB, and MDP) were interleaved among groups to ensure reasonable balance and to minimize group-by-strain statistical confounds in group normalization. The two independent samples from a single strain were always run in different groups. All arrays were processed using a single protocol by a single operator, Shirlean Goodwin.
+
+
All samples in a group were labeled on one day, except for a few cases that failed QC on their first pass. The hybridization station accommodates up to 20 samples, and for this reason each group was split into a large first set of 20 samples and a second set of 12 to 14 samples. Samples were washed in groups of four and then held in at 4°C until all 20 (or 12-14) arrays were ready to scan. The last four samples out of the wash stations were scanned directly. Samples were scanned in sets of four.
+
+
+
COMPARISON with December 2005 Data Set: Both BXD14 arrays in the Dec05 data set were found to actually be from BXD23 cases. This error of strain identification has been corrected in the present data set. Four arrays in the Dec05 data set have been deleted because we judged them to be of poor quality (strain_sex_sample_firstreaction_group):
+
+
BXD21_F_1_1_G1
+
BXD23_M_1_1_G7
+
BXD36_M_1_1_G2
+
BXD36_F_1_1_G3
+
+
+
+In the Dec05 data set there are a total of 1986 transcripts with QTLs that have LRS scores above 50, whereas in the corrected June06 data sets there are a total of 2074 transcripts with QTLs above 50.
+
+
Data Table 1:
+This table lists all arrays by file order (Index), tube/sample ID, age, sex, batch, and numbers of animals in each sample pool (pool size). The next columns (RMA outlier, scale factor, background average, present, absent, marginal, AFFY-b-ActinMur(3'/5'), AFFY-GapdhMur(3'/5')) are all Affymetrix QC data. Finally, source lists the source colony of the animals. (Final version, fully corrected, by Arthur Centeno, October 2008)
+
+
+
+
+
+
index
+
tube ID
+
strain
+
age
+
sex
+
batch ID
+
pool size
+
RMA outlier
+
scale factor
+
back ground average
+
present
+
absent
+
marginal
+
AFFX-b-ActinMur (3'/5')
+
AFFX-GapdhMur (3'/5')
+
source
+
+
+
1
R1289H2
B6D2F1
64
F
6
3
0.02
2.406
53.84
0.492
0.489
0.019
1.61
0.96
UTM RW
+
+
2
R1291H3
B6D2F1
66
M
+
1
3
0.01
3.524
48.54
0.487
0.494
0.019
1.21
1.52
UTM RW
+
+
3
R1291H4
B6D2F1
66
M technical duplicate of above
6
3
0.08
3.891
46.69
0.512
0.469
0.019
1.9
0.89
UTM RW
+
4
R2045H2
D2B6F1
65
F
1
2
0.01
4.403
47.99
0.497
0.485
0.018
1.09
1.53
UTM RW
+
5
R1595H2
D2B6F1
63
F
5
3
0.06
2.579
58.49
0.506
0.475
0.019
2.49
1.21
UTM RW
+
6
R1551H1
D2B6F1
72
F
6
3
0.02
2.62
53.76
0.506
0.476
0.018
1.37
0.76
UTM RW
+
7
R1361H1
C57BL/6J
69
F
6
4
0.01
3.058
51.87
0.477
0.503
0.02
1.67
0.76
UTM RW
+
8
R2041H2
C57BL/6J
65
M
1
4
0.04
3.341
49.26
0.527
0.456
0.018
1.14
1.45
UTM RW
+
9
R1449H2
C57BL/6J
71
M
5
3
0.09
3.592
44.32
0.47
0.51
0.02
1.68
0.77
UTM DG
+
10
R1290H2
DBA/2J
63
F
7
2
0.04
2.576
59.6
0.513
0.468
0.018
1.3
0.78
JAX
+
11
R1468H1
DBA/2J
64
F
5
3
0.03
2.929
53.8
0.515
0.465
0.019
1.28
0.79
UTM RW
+
12
R1507H1
BXD1
58
M
3
3
0.02
4.056
60.17
0.478
0.503
0.019
1.15
0.76
Glenn
+
13
R1542H1
BXD1
59
F
7
3
0.03
1.792
80.56
0.492
0.489
0.018
1.57
0.79
Glenn
+
14
R1520H1
BXD2
56
F
4
4
0.09
1.715
71.62
0.515
0.467
0.018
2.36
1.6
Glenn
+
15
R1516H1
BXD2
61
M
1
4
0.01
2.231
64.86
0.508
0.474
0.019
1.3
1.53
Glenn
+
16
R1593H2
BXD5
60
F
1
4
0
1.913
59.96
0.487
0.493
0.02
0.98
1.44
Glenn
+
17
R1692H1
BXD5
60
M
3
2
0.07
3.764
72.74
0.465
0.516
0.02
1.15
0.74
Glenn
+
18
R1539H2
BXD6
59
F
1
4
0
2.488
54.97
0.518
0.463
0.018
1.08
1.33
Glenn
+
19
R1538H1
BXD6
59
M
4
3
0.01
2.585
50.27
0.505
0.475
0.02
1.46
0.79
Glenn
+
20
R1518H1
BXD8
56
F
1
3
0
2.92
54.84
0.515
0.465
0.02
1.32
1.24
Glenn
+
21
R1548H1
BXD8
59
M
6
3
0.07
2.132
59.37
0.504
0.477
0.019
2.16
1.54
Glenn
+
22
R1350H2
BXD9
86
F
1
3
0.05
2.771
60.62
0.5
0.482
0.018
1.01
1.28
UMemphis
+
23
R1523H3
BXD9
57
MF (mixed)
7
3
0.14
3.9
78.36
0.435
0.547
0.018
1.36
0.77
UTM RW
+
24
R1531H1
BXD11
56
F
6
3
0.06
2.229
56.36
0.505
0.475
0.02
2.23
1.02
Glenn
+
25
R1367H1
BXD11
56
M
1
3
0.01
2.11
78.78
0.503
0.477
0.02
1.07
1.27
Glenn
+
26
R1530H1
BXD12
58
F
1
3
0
3.227
53.77
0.505
0.477
0.018
0.95
1.4
Glenn
+
27
R2674H1
BXD12
59
M
7
3
0.03
1.924
83.44
0.519
0.464
0.018
1.21
0.78
Glenn
+
28
R1529H1
BXD13
58
F
6
3
0.05
2.55
59.05
0.497
0.485
0.018
2
1.54
Glenn
+
29
R1662H2
BXD13
60
M
1
3
0.03
4.603
45.81
0.509
0.472
0.019
1.3
0.82
Glenn
+
30
R1304H2
BXD14
72
F
7
3
0.03
3.946
61.87
0.484
0.498
0.018
1.22
0.77
UTM RW
+
31
R1278H2
BXD14
55
M
7
3
0.06
4.75
67.52
0.449
0.532
0.019
1.1
0.73
UTM RW
+
32
R1524H1
BXD15
60
F
6
4
0.02
2.961
50.93
0.497
0.484
0.019
1.74
0.91
Glenn
+
33
R1515H1
BXD15
61
M
1
3
0.01
3.316
57.05
0.503
0.478
0.019
1.32
1.21
Glenn
+
34
R1661H1
BXD16
61
F
1
3
0.01
2.778
59.81
0.516
0.466
0.019
1.39
1.2
Glenn
+
35
R1594H1
BXD16
61
M
4
3
0.03
2.634
53.66
0.504
0.478
0.018
1.96
1.51
Glenn
+
36
R2666H1
BXD19
60
F
7
3
0.02
2.498
76.2
0.495
0.486
0.019
1.41
0.77
Glenn
+
37
R1471H1
BXD19
157
M
1
3
0.02
3.165
43.34
0.519
0.462
0.018
1.01
1.29
UTM JB
+
38
R1573H1
BXD20
59
F
1
3
0.02
3.749
52.7
0.513
0.469
0.018
1.01
1.27
Glenn
+
39
R2507H1
BXD20
60
M
6
3
0.06
3.568
57
0.472
0.508
0.02
1.29
0.76
Glenn
+
40
R2668H1
BXD21
60
M
7
4
0.07
2.605
44.9
0.535
0.449
0.017
1.54
0.76
Glenn
+
41
R1337H2
BXD21
102
F
2
4
0
2.673
58.05
0.492
0.489
0.019
1.4
0.76
UAB
+
42
R1848H3
BXD22
196
F
6
4
0.02
2.943
51.7
0.494
0.485
0.021
2.2
0.78
UAB
+
43
R1525H1
BXD22
59
M
2
3
0.02
2.248
55.76
0.548
0.433
0.018
1.26
0.74
Glenn
+
44
R1280H2
BXD23
56
F
1
3
0.01
3.187
54.63
0.458
0.523
0.019
0.96
1.2
UTM RW
+
45
R1537H1
BXD23
58
F
5
3
0.1
3.719
67.54
0.468
0.513
0.019
1.51
0.96
Glenn
+
46
R1343H2
BXD24
71
F
2
3
0.01
2.083
65.07
0.506
0.474
0.019
1.46
0.75
UMemphis
+
47
R1517H1
BXD24
57
M
3
3
0.01
3.471
53.66
0.504
0.476
0.019
1.28
0.78
Glenn
+
48
R1366H1
BXD27
60
F
2
4
0
2.26
48.46
0.518
0.463
0.019
1.29
0.77
Glenn
+
49
R1849H1
BXD27
70
M
5
3
0.06
8.801
38.34
0.468
0.512
0.019
2.42
1.08
UAB
+
50
R1353H1
BXD28
79
F
3
4
0.01
3.22
76.22
0.48
0.5
0.02
1.33
0.78
UMemphis
+
51
R2332H1
BXD28
60
M
2
3
0.01
3.217
63.68
0.491
0.49
0.019
1.37
0.79
Glenn
+
52
R1532H1
BXD29
57
F
2
3
0.01
2.122
59.18
0.524
0.456
0.019
1.17
0.76
Glenn
+
53
R1356H1
BXD29
76
M
5
3
0.01
4.033
47.67
0.52
0.463
0.017
1.17
0.78
UMemphis
+
54
R1240H2
BXD31
61
M
2
3
0.02
2.335
65.17
0.507
0.474
0.019
1.31
0.78
UTM RW
+
55
R1526H2
BXD31
57
F
7
4
0.1
7.267
89.54
0.435
0.547
0.017
1.35
0.78
UTM RW
+
56
R2675H1
BXD32
57
F
7
3
0.03
2.268
78.01
0.502
0.478
0.02
1.22
0.78
Glenn
+
57
R1508H2
BXD32
58
M
2
4
0.01
1.917
67.78
0.539
0.442
0.019
1.28
0.73
Glenn
+
58
R1345H3
BXD33
65
F
2
2
0.01
2.098
63.14
0.522
0.459
0.019
1.27
0.73
UMemphis
+
59
R1581H1
BXD33
59
M
3
3
0.01
3.229
53.16
0.496
0.485
0.019
1.19
0.78
Glenn
+
60
R1527H1
BXD34
59
F
2
3
0.01
2.3
58.92
0.51
0.471
0.019
1.24
0.76
Glenn
+
61
R1339H3
BXD34
74
M
5
3
0.12
2.888
53.49
0.506
0.476
0.018
2.39
1.35
UMemphis
+
62
R1855H1
BXD38
55
F
3
4
0.01
3.536
54.54
0.49
0.492
0.018
1.39
0.75
Glenn
+
63
R1510H1
BXD38
59
M
2
3
0.01
2.186
68.06
0.521
0.46
0.019
1.26
0.79
Glenn
+
64
R1528H2
BXD39
59
F
2
3
0.03
4.717
38.3
0.511
0.47
0.02
1.12
0.75
Glenn
+
65
R1514H1
BXD39
59
M
3
3
0.03
3.992
56.06
0.477
0.504
0.019
1.43
0.81
Glenn
+
66
R1522H1
BXD40
59
F
4
4
0
2.631
67.16
0.49
0.491
0.018
1.56
0.77
Glenn
+
67
R1359H1
BXD40
73
M
2
3
0.09
7.458
39.86
0.451
0.527
0.021
1.28
0.74
UMemphis
+
68
R1541H2
BXD42
58
F
7
3
0.07
6.784
52.12
0.483
0.499
0.017
1.13
0.66
Glenn
+
69
R1540H1
BXD42
58
M
7
4
0.03
2.423
75.14
0.492
0.488
0.02
1.48
0.78
Glenn
+
70
R1334H2
BXD43
59
F
1
3
0
2.672
54.36
0.492
0.491
0.017
1.2
2.06
UTM RW
+
71
R1303H1
BXD43
63
M
3
4
0.02
3.497
51.9
0.486
0.495
0.019
1.15
0.8
UTM RW
+
72
R1326H1
BXD44
65
F
3
4
0
3.412
53.96
0.496
0.485
0.018
1.35
0.78
UTM RW
+
73
R1577H2
BXD44
56
M
1
3
0.02
2.159
67.52
0.512
0.469
0.019
1.18
1.71
UTM RW
+
74
R1403H2
BXD45
63
F
7
2
0.03
3.146
44.5
0.524
0.457
0.018
1.41
0.78
Glenn
+
75
R1472H1
BXD45
65
M
7
4
0.04
1.651
73.31
0.543
0.44
0.018
1.63
0.74
UTM RW
+
76
R1316H1
BXD48
58
F
4
3
0
2.445
68.59
0.515
0.467
0.019
1.16
0.73
UTM RW
+
77
R1575H3
BXD48
65
M
3
4
0.05
4.577
55.78
0.466
0.514
0.019
1.59
0.9
UTM RW
+
78
R2521H1
BXD50
63
F
6
4
0.01
3.109
57.28
0.495
0.485
0.02
1.23
0.78
UTM RW
+
79
R1944H2
BXD50
81
M
1
3
0.01
2.546
63.39
0.495
0.485
0.02
0.9
1.57
UTM RW
+
80
R2331H1
BXD51
66
F
3
3
0.03
3.534
44.42
0.501
0.481
0.017
1.2
0.9
UTM RW
+
81
R1582H1
BXD51
71
M
6
4
0.03
2.92
47.87
0.489
0.491
0.02
1.36
0.75
UTM RW
+
82
R2680H1
BXD55
65
M
7
3
0.07
1.707
79.75
0.503
0.48
0.017
1.91
1.05
UTM RW
+
83
R1331H1
BXD60
60
F
4
3
0.01
2.867
50.33
0.492
0.487
0.021
1.34
0.78
UTM RW
+
84
R1281H2
BXD60
59
M
1
3
0
2.39
58.44
0.511
0.469
0.02
0.94
1.2
UTM RW
+
85
R2667H1
BXD61
70
F
7
4
0.03
3.36
59.04
0.495
0.488
0.018
1.16
0.76
UTM RW
+
86
R1856H2
BXD61
94
M
1
2
0
3.502
49.6
0.501
0.48
0.019
0.96
1.3
UTM RW
+
87
R1246H1
BXD62
54
F
1
4
0.02
3.405
51.47
0.511
0.471
0.018
1.14
1.34
UTM RW
+
88
R1585H2
BXD62
64
M
6
4
0.01
3.156
55.77
0.518
0.464
0.018
1.43
0.82
UTM RW
+
89
R1945H1
BXD63
107
F
1
3
0.02
2.811
52.65
0.522
0.459
0.019
1.05
1.36
UTM RW
+
90
R2093H3
BXD63
70
M
6
3
0.02
3.894
42.85
0.503
0.477
0.019
1.29
1.01
UTM RW
+
91
R2062H2
BXD64
65
F
1
3
0.05
3.795
78.48
0.513
0.468
0.019
0.98
1.43
UTM RW
+
92
R2061H1
BXD64
87
M
3
4
0.01
3.536
61.57
0.477
0.504
0.019
1.31
0.78
UTM RW
+
93
R2054H2
BXD65
55
F
1
2
0.03
3.159
80.96
0.48
0.502
0.018
1.09
1.24
UTM RW
+
94
R2056H2
BXD65
89
M
6
2
0
2.836
59.6
0.504
0.477
0.019
1.3
0.75
UTM RW
+
95
R1941H2
BXD66
78
F
1
4
0.01
2.734
50.93
0.499
0.481
0.02
1.18
1.29
UTM RW
+
96
R1949H2
BXD66
96
M
4
2
0.04
2.828
51.27
0.474
0.508
0.019
2.05
1.12
UTM RW
+
97
R2060H1
BXD67
54
F
6
3
0.01
2.561
43.88
0.502
0.479
0.02
1.7
0.84
UTM RW
+
98
R2052H1
BXD67
61
M
1
4
0.01
3.161
43.23
0.521
0.46
0.018
1.09
1.31
UTM RW
+
99
R2074H1
BXD68
60
F
5
3
0.02
6.528
49.62
0.479
0.502
0.019
1.48
0.83
UTM RW
+
100
R1928H1
BXD68
72
M
2
2
0.01
2.404
48.28
0.521
0.459
0.02
1.3
0.74
UTM RW
+
101
R1439H3
BXD69
60
F
2
3
0.02
2.463
59.14
0.522
0.459
0.018
1.31
0.78
UTM RW
+
102
R1559H1
BXD69
64
M
3
3
0.03
2.987
67.74
0.486
0.496
0.017
1.38
0.8
UTM RW
+
103
R2134H1
BXD70
64
F
5
2
0.02
2.148
58.64
0.532
0.45
0.019
1.4
0.85
UTM RW
+
104
R2063H1
BXD70
55
M
2
3
0.02
3.481
55.32
0.513
0.469
0.018
1.28
0.71
UTM RW
+
105
R1277H1
BXD73
60
F
4
2
0.01
2.576
62.45
0.502
0.479
0.019
1.35
0.79
UTM RW
+
106
R1443H2
BXD73
76
M
2
3
0.01
2.312
64.34
0.499
0.481
0.02
1.48
0.77
UTM RW
+
107
R2055H2
BXD74
79
M
2
3
0.01
2.576
56.84
0.509
0.473
0.018
1.46
0.88
UTM RW
+
108
R2316H1
BXD74
193
M
5
2
0.01
3.457
55.35
0.508
0.471
0.02
1.17
0.78
UTM RW
+
109
R1871H1
BXD75
61
F
2
3
0.04
1.723
56.4
0.53
0.451
0.019
1.3
0.76
UTM RW
+
110
R1844H2
BXD75
90
M
3
4
0.01
1.934
56.23
0.52
0.461
0.019
1.62
0.86
UTM RW
+
111
R1948H2
BXD76
81
F
2
3
0.01
1.507
68.85
0.553
0.428
0.02
1.3
0.75
UTM RW
+
112
R2094H1
BXD76
61
M
5
4
0.01
3.299
42.69
0.519
0.462
0.019
1.39
0.88
UTM RW
+
113
R2262H1
BXD77
62
F
3
4
0.02
4.317
47.16
0.493
0.488
0.019
1.32
0.74
UTM RW
+
114
R1423H1
BXD77
62
M
2
3
0.02
3.071
54.15
0.51
0.471
0.019
1.26
0.74
UTM RW
+
115
R1947H1
BXD79
108
F
2
2
0.01
2.599
51.52
0.524
0.457
0.019
1.35
0.74
UTM RW
+
116
R2092H1
BXD79
86
M
5
4
0.06
3.735
42.25
0.514
0.468
0.018
2.94
1.06
UTM RW
+
117
R1880H1
BXD80
68
F
5
3
0.06
4.855
42.22
0.501
0.481
0.018
2.17
1.36
UTM RW
+
118
R1881H2
BXD80
68
M
2
3
0.02
2.073
48.93
0.524
0.458
0.019
1.34
0.83
UTM RW
+
119
R2075H1
BXD83
60
F
2
3
0.01
2.454
55.1
0.502
0.48
0.018
1.27
0.77
UTM RW
+
120
R2076H2
BXD83
60
M
6
3
0.03
2.624
55.65
0.495
0.488
0.018
2.21
0.94
UTM RW
+
121
R2077H2
BXD84
62
F
6
2
0
2.1
71.87
0.522
0.459
0.018
1.68
0.81
UTM RW
+
122
R2135H3
BXD84
75
M
2
2
0.01
2.467
64.46
0.505
0.476
0.019
1.2
0.74
UTM RW
+
123
R1473H1
BXD85
79
F
2
3
0.02
3.384
55.34
0.478
0.502
0.02
1.24
0.77
UTM RW
+
124
R1474H1
BXD85
57
M
1
3
0.01
2.831
55.24
0.522
0.461
0.018
1.04
1.29
UTM RW
+
125
R1597H1
BXD85
86
M
4
4
0.09
2.028
53.95
0.487
0.492
0.021
1.28
0.83
UTM RW
+
126
R1415H1
BXD86
77
F
4
3
0.02
2.525
53.16
0.495
0.485
0.02
1.66
0.91
UTM RW
+
127
R2669H2
BXD87
63
F
7
3
0.07
2.61
57.59
0.513
0.47
0.018
1.6
0.91
UTM RW
+
128
R1710H1
BXD87
84
M
2
4
0.01
2.697
56.4
0.512
0.469
0.019
1.28
0.79
UTM RW
+
129
R1872H2
BXD89
90
F
2
2
0.02
3.013
63.53
0.492
0.488
0.021
1.22
0.72
UTM RW
+
130
R1850H3
BXD89
82
M
4
4
0.03
2.736
44.89
0.498
0.483
0.019
1.5
0.83
UTM RW
+
131
R2058H1
BXD90
61
F
2
3
0.01
3.389
48.05
0.502
0.478
0.02
1.53
0.76
UTM RW
+
132
R1600H2
BXD90
74
M
7
4
0.03
3.261
51.31
0.517
0.465
0.018
1.16
0.75
Glenn
+
133
R1301H2
BXD92
58
F
2
3
0.02
3.543
41.97
0.522
0.46
0.018
1.5
0.79
UTM RW
+
134
R1309H1
BXD92
59
M
4
3
0.05
1.655
66.34
0.498
0.481
0.021
1.52
0.82
UTM RW
+
135
R2057H1
BXD93
92
F
5
3
0.02
4.033
44.41
0.509
0.471
0.02
1.22
0.78
UTM RW
+
136
R2059H1
BXD93
58
M
1
3
0
3.058
60.29
0.493
0.488
0.019
1.18
1.37
UTM RW
+
137
R2313H1
BXD94
59
F
3
3
0
3.091
59.45
0.487
0.495
0.018
1.34
0.73
UTM RW
+
138
R1915H1
BXD96
65
F
5
2
0.04
5.145
46.19
0.502
0.481
0.017
1.37
0.74
UTM RW
+
139
R1846H2
BXD96
63
M
1
3
0
3.159
55.85
0.487
0.493
0.02
0.92
1.26
UTM RW
+
140
R2648H1
BXD97
74
F
7
4
0.02
1.664
82.08
0.518
0.464
0.019
1.4
0.78
UTM RW
+
141
R1927H2
BXD97
67
M
1
3
0.04
2.622
57.81
0.539
0.444
0.017
1.45
1.32
UTM RW
+
142
R1942H1
BXD98
62
F
5
3
0.04
3.104
48.42
0.528
0.454
0.019
2.22
1.08
UTM RW
+
143
R1943H2
BXD98
62
M
3
3
0.02
4.04
56.85
0.484
0.497
0.019
1.18
0.76
UTM RW
+
144
R2197H1
BXD99
70
F
3
3
0.02
4.288
51.75
0.49
0.492
0.018
1.35
0.81
UTM RW
+
145
R2315H1
BXD99
84
M
5
2
0.03
6.036
43.05
0.484
0.497
0.018
1.7
0.96
UTM RW
+
146
R2028H2
129S1/SvImJ
66
F
5
3
0.1
4.362
64.49
0.497
0.484
0.019
2.78
1.13
JAX
+
147
R2029H2
129S1/SvImJ
66
M
6
3
0.04
5.208
41.21
0.49
0.49
0.02
1.62
0.95
JAX
+
148
R2670H1
A/J
65
F
7
3
0.04
3.951
46.8
0.498
0.485
0.017
1.32
0.75
UTM RW
+
149
R2030H1
A/J
57
M
5
2
0.06
3.307
45.16
0.527
0.454
0.018
1.63
0.99
UTM RW
+
150
R2032H3
AKR/J
66
F
5
3
0.04
3.054
61.03
0.51
0.471
0.018
1.46
0.79
JAX
+
151
R2454H1
AKR/J
66
M
6
4
0.11
2.892
58.55
0.474
0.507
0.019
1.99
0.78
JAX
+
152
R1675H1
BALB/cByJ
83
M
7
3
0.03
3.405
48.13
0.509
0.474
0.018
1.13
0.78
JAX
+
153
R2036H3
BALB/cJ
51
F
5
3
0.12
2.611
56.29
0.518
0.466
0.017
3.3
1.23
UTM RW
+
154
R2053H1
BALB/cJ
55
M
5
3
0.1
2.505
63.27
0.499
0.483
0.018
3.1
1.34
UTM RW
+
155
R2037H2
BALB/cJ
51
M
6
4
0.01
2.546
58.13
0.497
0.485
0.018
1.26
0.77
UTM RW
+
156
R2038H3
C3H/HeJ
63
F
6
3
0.02
2.671
66.74
0.476
0.504
0.02
1.41
0.77
UTM RW
+
157
R2039H1
C3H/HeJ
63
M
5
3
0.1
3.384
44.15
0.528
0.454
0.017
2.16
0.88
UTM RW
+
158
R2137H1
C57BL/6ByJ
55
F
5
3
0.02
4.746
47.01
0.488
0.493
0.018
1.23
0.79
JAX
+
159
R2673H1
C57BL/6ByJ
55
M
7
3
0.08
1.842
67.69
0.514
0.469
0.017
1.75
0.78
JAX
+
160
R2619H1
CAST/EiJ
64
F
5
3
0.14
4.077
51.87
0.455
0.528
0.018
2.74
1.2
JAX
+
161
R1683H1
KK/HIJ
72
F
6
3
0.02
3.919
54.23
0.491
0.489
0.02
1.31
0.83
JAX
+
162
R1687H3
KK/HIJ
72
F
5
3
0.04
3.888
40.86
0.499
0.483
0.019
1.86
0.88
JAX
+
163
R2046H1
LG/J
63
F
5
2
0.03
2.822
59.18
0.514
0.468
0.018
1.68
0.8
UTM RW
+
164
R2047H2
LG/J
63
M
6
3
0.07
2.038
60.34
0.509
0.471
0.02
2.16
0.95
UTM RW
+
165
R2048H1
NOD/LtJ
77
F
6
2
0.14
4.045
50.21
0.489
0.49
0.021
2.89
0.95
UTM RW
+
166
R2049H3
NOD/LtJ
76
M
5
3
0.1
2.328
52.78
0.519
0.462
0.019
3.09
1.35
UTM RW
+
167
R2200H1
NZO/HlLtJ
62
F
5
2
0.03
2.648
54.29
0.543
0.438
0.019
1.27
0.8
JAX
+
168
R2350H1
NZO/HlLtJ
96
M
6
2
0.19
2.391
50.52
0.518
0.463
0.02
3.71
2.21
JAX
+
169
R2677H1
PWD/PhJ
65
M
7
2
0.12
2.764
65.49
0.462
0.52
0.018
1.89
1.16
UTM RW
+
170
R2051H3
PWD/PhJ
64
M
5
3
0.07
3.266
51.5
0.475
0.506
0.019
2.8
1.01
UTM RW
+
171
R2322H1
PWK/PhJ
63
F
5
2
0.09
2.94
54.91
0.511
0.47
0.019
2.32
1.02
JAX
+
172
R2349H1
PWK/PhJ
83
M
6
2
0.15
3.306
54.93
0.459
0.522
0.019
4.65
1.45
JAX
+
173
R2198H2
WSB/EiJ
58
F
6
1
0.02
2.922
57.97
0.502
0.479
0.019
1.44
0.76
JAX
+
174
R2199H1
WSB/EiJ
58
M
5
3
0.04
3.171
54.95
0.475
0.505
0.02
1.32
0.81
JAX
+
175
R2116H1
CXB1
55
F
3
3
0.07
5.792
51.59
0.459
0.521
0.02
1.17
0.8
JAX
+
176
R2096H1
CXB1
55
M
4
2
0.01
3.435
53.78
0.495
0.485
0.02
1.22
0.79
JAX
+
177
R2117H2
CXB2
62
F
4
2
0.04
3.39
45.97
0.533
0.45
0.017
2.05
0.89
JAX
+
178
R2098H1
CXB2
68
M
3
3
0.02
2.572
54.22
0.496
0.485
0.019
1.38
0.86
JAX
+
179
R2118H1
CXB3
47
F
3
3
0.03
3.646
63.16
0.478
0.503
0.019
1.22
0.77
JAX
+
180
R2100H1
CXB3
47
M
4
3
0.02
5.76
51.38
0.48
0.503
0.017
1.24
0.81
JAX
+
181
R2119H1
CXB4
58
F
4
3
0.02
3.897
49.21
0.488
0.494
0.018
1.31
0.79
JAX
+
182
R2101H1
CXB4
58
M
3
3
0.13
7.372
53.77
0.433
0.548
0.019
1.2
0.97
JAX
+
183
R2505H1
CXB5
80
F
6
3
0.02
2.83
49.6
0.499
0.48
0.02
1.33
0.76
UTM RW
+
184
R2131H1
CXB5
42
M
4
3
0.1
5.577
51.15
0.434
0.547
0.019
1.7
0.89
JAX
+
185
R0129H2
CXB5
70
M
3
3
0.07
4.829
45.42
0.488
0.493
0.019
1.23
0.83
UTM RW
+
186
R2676H1
CXB6
47
F
7
2
0.05
2.146
62.51
0.507
0.475
0.018
1.52
0.78
JAX
+
187
R2102H1
CXB6
49
M
4
3
0.07
5.148
51.63
0.453
0.529
0.018
1.43
0.87
JAX
+
188
R2121H1
CXB7
63
F
4
2
0.06
4.904
48.71
0.464
0.517
0.019
1.19
0.92
JAX
+
189
R2104H2
CXB7
58
M
3
2
0.06
3.389
48.79
0.502
0.479
0.019
1.74
1.48
JAX
+
190
R2122H1
CXB8
54
F
3
3
0.04
4.128
59.77
0.451
0.529
0.02
1.12
0.76
JAX
+
191
R2105H1
CXB8
41
M
4
3
0.16
3.146
61.04
0.451
0.53
0.019
1.34
0.84
JAX
+
192
R2123H1
CXB9
54
F
3
3
0.08
5.708
55.94
0.438
0.543
0.019
1.32
0.78
JAX
+
193
R2106H1
CXB9
54
M
4
3
0.06
5.868
46.55
0.469
0.512
0.019
1.18
0.82
JAX
+
194
R2124H1
CXB10
53
F
4
2
0.11
4.867
39.88
0.451
0.528
0.02
1.55
0.8
JAX
+
195
R2671H1
CXB10
53
M
7
3
0.09
2.348
71.45
0.488
0.494
0.018
2.2
1.14
JAX
+
196
R2125H1
CXB11
58
F
3
3
0.03
3.256
54.95
0.461
0.519
0.02
1.46
0.77
JAX
+
197
R2128H1
CXB11
58
M
4
2
0.06
4.986
54.13
0.465
0.515
0.02
1.11
0.83
JAX
+
198
R2126H1
CXB12
47
F
4
3
0.11
3.935
54.11
0.469
0.511
0.021
1.5
0.79
JAX
+
199
R2109H1
CXB12
47
M
3
3
0.07
4.518
49.26
0.488
0.492
0.02
1.23
0.77
JAX
+
200
R2672H1
CXB13
49
F
7
3
0.03
1.722
79.52
0.516
0.465
0.019
1.64
0.75
JAX
+
201
R2110H1
CXB13
56
M
4
3
0.21
3.478
48.08
0.461
0.517
0.022
1.21
0.78
JAX
+
+
+
+
About downloading this data set:
+
All data links (right-most column above) will be made active as sooon as the global analysis of these data by the Consortium has been accepted for publication. Please see text on Data Sharing Policies, and Conditions and Limitations, and Contacts. Following publication, download a summary text file or Excel file of the PDNN probe set data. Contact RW Williams regarding data access problems.
+
+
About the array platform:
+
Affymetrix Mouse Genome 430 2.0 array: The 430v2 array consists of 992936 useful 25-nucleotide probes that estimate the expression of approximately 39,000 transcripts and the majority of known genes and expressed sequence tags. The array sequences were selected late in 2002 using Unigene Build 107 by Affymetrix. The UTHSC group has recently reannotated all probe sets on this array, producing more accurate data on probe and probe set targets. All probes were aligned to the most recent assembly of the Mouse Genome (Build 34, mm6) using Jim Kent's BLAT program. Many of the probe sets have been manually curated by Jing Gu and Rob Williams.
+
About data values and data processing:
+
Harshlight was used to examine the image quality of the array (CEL files). Bad areas (bubbles, scratches, blemishes) of arrays were masked.
+
+
First pass data quality control: Affymetrix GCOS provides useful array quality control data including:
+
+
The scale factor used to normalize mean probe intensity. This averaged 3.3 for the 179 arrays that passed and 6.2 for arrays that were excluded. The scale factor is not a particular critical parameter.
+
The average background level. Values averaged 54.8 units for the data sets that passed and 55.8 for data sets that were excluded. This factor is not important for quality control.
+
The percentage of probe sets that are associated with good signal ("present" calls). This averaged 50% for the 179 data sets that passed and 42% for those that failed. Values for passing data sets extended from 43% to 55%. This is a particularly important criterion.
+
The 3':5' signal ratios of actin and Gapdh. Values for passing data sets averaged 1.5 for actin and 1.0 for Gapdh. Values for excluded data sets averaged 12.9 for actin and 9.6 for Gapdh. This is a highly discriminative QC criterion, although one must keep in mind that only two transcripts are being tested. Sequence variation among strains (particularly wild derivative strains such as CAST/Ei) may affect these ratios.
+
+
+
The second step in our post-processing QC involves a count of the number of probe sets in each array that are more than 2 standard deviations (z score units) from the mean across the entire 206 array data sets. This was the most important criterion used to eliminate "bad" data sets. All 206 arrays were processed togther using standard RMA and PDNN methods. The count and percentage of probe sets in each array that were beyond the 2 z theshold was computed. Using the RMA transform the average percentage of probe sets beyond the 2 z threshold for the 179 arrays that finally passed of QC procedure was 1.76% (median of 1.18%). In contrast the 2 z percentage was more than 10-fold higher (mean of 22.4% and median 20.2%) for those arrays that were excluded. This method is not very sensitive to the transformation method that is used. Using the PDNN transform, the average percent of probe sets exceeding was 1.31% for good arrays and was 22.6% for those that were excluded. In our opinion, this 2 z criterion is the most useful criterion for the final decision of whether or not to include arrays, although again, allowances need to be made for wild strains that one expects to be different from the majority of conventional inbred strains. For example, if a data set has excellent characteristics on all of the Affymetrix GCOS metrics listed above, but generates a high 2 z percentage, then one would include the sample if one can verify that there are no problems in sample and data set identification.
+
+
The entire procedure can be reapplied once the initial outlier data sets have been eliminated to detect any remaining outlier data sets.
+
+
+
DataDesk was used to examine the statistical quality of the probe level (CEL) data after step 5 below. DataDesk allows the rapid detection of subsets of probes that are particularly sensitive to still unknown factors in array processing. Arrays can then be categorized at the probe level into "reaction classes." A reaction class is a group of arrays for which the expression of essentially all probes are colinear over the full range of log2 values. A single but large group of arrays (n = 32) processed in essentially the identical manner by a single operator can produce arrays belonging to as many as four different reaction classes. Reaction classes are NOT related to strain, age, sex, treatment, or any known biological parameter (technical replicates can belong to different reaction classes). We do not yet understand the technical origins of reaction classes. The number of probes that contribute to the definition of reaction classes is quite small (<10% of all probes). We have categorized all arrays in this data set into one of 5 reaction classes. These have then been treated as if they were separate batches. Probes in these data type "batches" have been aligned to a common mean as described below.
+
+
Probe (cell) level data from the CEL file: These CEL values produced by GCOS are 75% quantiles from a set of 91 pixel values per cell.
+
+
+
We added an offset of 1.0 unit to each cell signal to ensure that all values could be logged without generating negative values. We then computed the log base 2 of each cell.
+
+
We performed a quantile normalization of the log base 2 values for all arrays using the same initial steps used by the RMA transform.
+
+
We computed the Z scores for each cell value.
+
+
We multiplied all Z scores by 2.
+
+
We added 8 to the value of all Z scores. The consequence of this simple set of transformations is to produce a set of Z scores that have a mean of 8, a variance of 4, and a standard deviation of 2. The advantage of this modified Z score is that a two-fold difference in expression level (probe brightness level) corresponds approximately to a 1 unit difference.
+
+
Finally, we computed the arithmetic mean of the values for the set of microarrays for each strain. Technical replicates were averaged before computing the mean for independent biological samples. Note, that we have not (yet) corrected for variance introduced by differences in sex or any interaction terms. We have not corrected for background beyond the background correction implemented by Affymetrix in generating the CEL file. We eventually hope to add statistical controls and adjustments for some of these variables.
+
+
Probe set data from the CHP file: The expression values were generated using PDNN. The same simple steps described above were also applied to these values. Every microarray data set therefore has a mean expression of 8 with a standard deviation of 2. A 1 unit difference represents roughly a two-fold difference in expression level. Expression levels below 5 are usually close to background noise levels.
+
+
+
Probe level QC: Log2 probe data of all arrays were inspected in DataDesk before and after quantile normalization. Inspection involved examining scatterplots of pairs of arrays for signal homogeneity (i.e., high correlation and linearity of the bivariate plots) and looking at all pairs of correlation coefficients. XY plots of probe expression and signal variance were also examined. Probe level array data sets were organized into reaction groups. Arrays with probe data that were not homogeneous when compared to other arrays were flagged.
+
+
Probe set level QC: The final normalized individual array data were evaluated for outliers. This involved counting the number of times that the probe set value for a particular array was beyond two standard deviations of the mean. This outlier analysis was carried out using the PDNN, RMA and MAS5 transforms and outliers across different levels of expression. Arrays that were associated with an average of more than 8% outlier probe sets across all transforms and at all expression levels were eliminated. In contrast, most other arrays generated fewer than 5% outliers.
+
+
+
Validation of strains and sex of each array data set: A subset of probes and probe sets with a Mendelian pattern of inheritance were used to construct a expression correlation matrix for all arrays and the ideal Mendelian expectation for each strain constructed from the genotypes. There should naturally be a very high correlation in the expression patterns of transcripts with Mendelian phenotypes within each strain, as well as with the genotype strain distribution pattern of markers for the strain.
+
+
Sex of the samples was validated using sex-specific probe sets such as Xist and Dby.
+
Data source acknowledgment:
+
Data were generated with funds provided by a variety of public and private source to members of the Consortium. All of us thank Muriel Davisson, Cathy Lutz, and colleagues at the Jackson Laboratory for making it possible for us to add all of the CXB strains, and one or more samples from KK/HIJ, WSB/Ei, NZO/HILtJ, LG/J, CAST/Ei, PWD/PhJ, and PWK/PhJ to this study. We thank Yan Cui at UTHSC for allowing us to use his Linux cluster to align all M430 2.0 probes and probe sets to the mouse genome. We thank Hui-Chen Hsu and John Mountz for providing us BXD tissue samples, as well as many strains of BXD stock. We thanks Douglas Matthews (UMem in Table 1) and John Boughter (JBo in Table 1) for sharing BXD stock with us. Members of the Hippocampus Consortium thank the following sources for financial support of this effort:
+
+
+
David C. Airey, Ph.D.
+ Grant Support: Vanderbilt Institute for Integratie Genomics
+ Department of Pharmacology
+ david.airey at vanderbilt.edu
+
+
Lu Lu, M.D.
+ Grant Support: NIH U01AA13499, U24AA13513
+
+
Dan Goldowitz, Ph.D.
+ Grant Support: NIAAA INIA AA013503
+ University of Tennessee Health Science Center
+ Dept. Anatomy and Neurobiology
+ email: dgold@nb.utmem.edu
+
+
Gerd Kempermann, M.D.
+ Grant Support: The Volkswagen Foundation Grant on Permissive and Persistent Factors in Neurogenesis in the Adult Central Nervous System
+ Humboldt-Universitat Berlin
+ Universitatsklinikum Charite
+ email: gerd.kempermann at mdc-berlin.de
+
+
Kenneth F. Manly, Ph.D.
+ Grant Support: NIH P20MH062009 and U01CA105417
+
+
Richard S. Nowakowski, Ph.D.
+ Grant Support: R01 NS049445-01
+
+
Glenn D. Rosen, Ph.D.
+ Grant Support: NIH P20
+
+
Leonard C. Schalkwyk, Ph.D.
+ Grant Support: MRC Career Establishment Grant G0000170
+ Social, Genetic and Developmental Psychiatry
+ Institute of Psychiatry,Kings College London
+ PO82, De Crespigny Park London SE5 8AF
+ L.Schalkwyk@iop.kcl.ac.uk
+
+
Guus Smit, Ph.D.
+ Dutch NeuroBsik Mouse Phenomics Consortium
+ Center for Neurogenomics & Cognitive Research
+ Vrije Universiteit Amsterdam, The Netherlands
+ e-mail: guus.smit at falw.vu.nl
+ Grant Support: BSIK 03053
+
+
Thomas Sutter, Ph.D.
+ Grant Support: INIA U01 AA13515 and the W. Harry Feinstone Center for Genome Research
+
+
Stephen Whatley, Ph.D.
+ Grant Support: XXXX
+
+
Robert W. Williams, Ph.D.
+ Grant Support: NIH U01AA013499, P20MH062009, U01AA013499, U01AA013513
+
+
+
Experiment Type:
+
Pooled RNA samples (usually one pool of male hippocampii and one pool of female hippocampii) were prepared using standard protocols. Samples were processed using a total of 206 Affymetrix GeneChip Mouse Expression 430 2.0 short oligomer arrays (MOE430 2.0 or M430v2; see GEO platform ID GPL1261), of which 201 passed quality control and error checking. This particular data set was processed using the PDNN protocol. To simplify comparisons among transforms, PDNN values of each array were adjusted to an average of 8 units and a standard deviation of 2 units.
+
+
Overall Design:
+
Pooled RNA samples (usually one pool of male hippocampii and one pool of female hippocampii) were prepared using standard protocols. Samples were processed using a total of 206 Affymetrix GeneChip Mouse Expression 430 2.0 short oligomer arrays (MOE430 2.0 or M430v2; see GEO platform ID GPL1261), of which 201 passed quality control and error checking. This particular data set was processed using the PDNN protocol. To simplify comparisons among transforms, PDNN values of each array were adjusted to an average of 8 units and a standard deviation of 2 units.
+
+
Contributor:
+
+
David C. Airey, Ph.D.
+ Grant Support: Vanderbilt Institute for Integratie Genomics
+ Department of Pharmacology
+ david.airey at vanderbilt.edu
+
+
Lu Lu, M.D.
+ Grant Support: NIH U01AA13499, U24AA13513
+
+
Dan Goldowitz, Ph.D.
+ Grant Support: NIAAA INIA AA013503
+ University of Tennessee Health Science Center
+ Dept. Anatomy and Neurobiology
+ email: dgold@nb.utmem.edu
+
+
Gerd Kempermann, M.D.
+ Grant Support: The Volkswagen Foundation Grant on Permissive and Persistent Factors in Neurogenesis in the Adult Central Nervous System
+ Humboldt-Universitat Berlin
+ Universitatsklinikum Charite
+ email: gerd.kempermann at mdc-berlin.de
+
+
Kenneth F. Manly, Ph.D.
+ Grant Support: NIH P20MH062009 and U01CA105417
+
+
Richard S. Nowakowski, Ph.D.
+ Grant Support: R01 NS049445-01
+
+
Glenn D. Rosen, Ph.D.
+ Grant Support: NIH P20
+
+
Leonard C. Schalkwyk, Ph.D.
+ Grant Support: MRC Career Establishment Grant G0000170
+ Social, Genetic and Developmental Psychiatry
+ Institute of Psychiatry,Kings College London
+ PO82, De Crespigny Park London SE5 8AF
+ L.Schalkwyk@iop.kcl.ac.uk
+
+
Guus Smit, Ph.D.
+ Dutch NeuroBsik Mouse Phenomics Consortium
+ Center for Neurogenomics & Cognitive Research
+ Vrije Universiteit Amsterdam, The Netherlands
+ e-mail: guus.smit at falw.vu.nl
+ Grant Support: BSIK 03053
+
+
Thomas Sutter, Ph.D.
+ Grant Support: INIA U01 AA13515 and the W. Harry Feinstone Center for Genome Research
+
+
Stephen Whatley, Ph.D.
+ Grant Support: XXXX
+
+
Robert W. Williams, Ph.D.
+ Grant Support: NIH U01AA013499, P20MH062009, U01AA013499, U01AA013513
+
+
Citation:
+
+
Please cite: Overall RW, Kempermann G, Peirce J, Lu L, Goldowitz D, Gage FH, Goodwin S, Smit AB, Airey DC, Rosen GD, Schalkwyk LC, Sutter TR, Nowakowski RS, Whatley S, Williams RW (2009) Genetics of the hippocampal transcriptome in mice: a systematic survey and online neurogenomic resource. Front. Neurogen. 1:3 Full Text HTML doi:10.3389/neuro.15.003.2009
+
+
-
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index c15f4ba1..a2c68f13 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -7,6 +7,8 @@ from flask import render_template, request
from wqflask import search_results
from wqflask.show_trait import show_trait_page
+from wqflask.dataSharing import SharingInfoPage
+
from base import webqtlFormData
from pprint import pformat as pf
@@ -18,8 +20,12 @@ def index_page():
@app.route("/search")
def search():
- the_search = search_results.SearchResultPage(request.args)
- return render_template("search_result_page.html", **the_search.__dict__)
+ if 'info_database' in request.args:
+ print("Going to data_sharing")
+ data_sharing()
+ else:
+ the_search = search_results.SearchResultPage(request.args)
+ return render_template("search_result_page.html", **the_search.__dict__)
@app.route("/showDatabaseBXD")
def showDatabaseBXD():
@@ -28,3 +34,12 @@ def showDatabaseBXD():
template_vars = show_trait_page.ShowTraitPage(fd)
print("showDatabaseBXD template_vars:", pf(template_vars.__dict__))
return render_template("trait_data_and_analysis.html", **template_vars.__dict__)
+
+#@app.route("/data_sharing")
+def data_sharing():
+ print("In data_sharing")
+ fd = webqtlFormData.webqtlFormData(request.args)
+ print("Have fd")
+ template_vars = SharingInfoPage.SharingInfoPage(fd)
+ print("Made it to rendering")
+ return render_template("data_sharing.html", **template_vars.__dict__)
--
cgit v1.2.3
From 243a0ff8a0926f9653d8196613d55fe8abdba871 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Fri, 29 Jun 2012 18:24:50 -0400
Subject: removed some previously deleted files
---
wqflask/dataSharing/SharingBody.py | 290 --------------------------
wqflask/dataSharing/SharingInfo.py | 98 ---------
wqflask/dataSharing/SharingInfoAddPage.py | 47 -----
wqflask/dataSharing/SharingInfoDeletePage.py | 55 -----
wqflask/dataSharing/SharingInfoEditPage.py | 51 -----
wqflask/dataSharing/SharingInfoPage.py | 52 -----
wqflask/dataSharing/SharingInfoUpdatePage.py | 109 ----------
wqflask/dataSharing/SharingListDataSetPage.py | 99 ---------
wqflask/dataSharing/SharingPage.py | 40 ----
wqflask/dataSharing/__init__.py | 0
10 files changed, 841 deletions(-)
delete mode 100755 wqflask/dataSharing/SharingBody.py
delete mode 100755 wqflask/dataSharing/SharingInfo.py
delete mode 100755 wqflask/dataSharing/SharingInfoAddPage.py
delete mode 100755 wqflask/dataSharing/SharingInfoDeletePage.py
delete mode 100755 wqflask/dataSharing/SharingInfoEditPage.py
delete mode 100755 wqflask/dataSharing/SharingInfoPage.py
delete mode 100755 wqflask/dataSharing/SharingInfoUpdatePage.py
delete mode 100755 wqflask/dataSharing/SharingListDataSetPage.py
delete mode 100755 wqflask/dataSharing/SharingPage.py
delete mode 100755 wqflask/dataSharing/__init__.py
diff --git a/wqflask/dataSharing/SharingBody.py b/wqflask/dataSharing/SharingBody.py
deleted file mode 100755
index 4445e0d1..00000000
--- a/wqflask/dataSharing/SharingBody.py
+++ /dev/null
@@ -1,290 +0,0 @@
-# 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 = """
-
About the cases used to generate this set of data:
-
%s
-
About the tissue used to generate this set of data:
-
%s
-
About downloading this data set:
-
%s
-
About the array platform:
-
%s
-
About data values and data processing:
-
%s
-
Data source acknowledgment:
-
%s
-
Experiment Type:
-
%s
-
Overall Design:
-
%s
-
Contributor:
-
%s
-
Citation:
-
%s
-
Submission Date:
-
%s
-
Laboratory:
-
%s
-
Samples:
-
%s
-
-
-
-"""
-
-sharinginfoedit_body_string = """
-
%s
-
-
-
-
-
-
Principal Investigator
-
Contact Name:
-
Emails:
-
Phone:
-
URL:
-
Organization Name:
-
Department:
-
Laboratory:
-
Address:
-
City:
-
State:
-
ZIP:
-
Country:
-
-
Summary
-
Summary:
-
-
Biology
-
Experiment Design:
-
About the cases used to generate this set of data:
-
About the tissue used to generate this set of data:
-
-
Technique
-
About downloading this data set:
-
About the array platform:
-
-
Bioinformatics
-
About data values and data processing:
-
Overall Design:
-
-
Misc
-
Contributor:
-
Citation:
-
Data source acknowledgment:
-
-
Administrator ONLY
-
GN Accesion Id:
-
DB Title in GN:
-
GEO Series:
-
Status:
-
Title:
-
Organism_Id (Taxonomy ID):
-
Organism:
-
Submission Date:
-
Platforms:
-
Species:
-
Tissue:
-
Normalization:
-
Inbred Set:
-
Info Page Name:
-
Samples:
-
Authorized Users:
-
Progress:
-
-
-
-
-
-
"""
diff --git a/wqflask/dataSharing/SharingInfo.py b/wqflask/dataSharing/SharingInfo.py
deleted file mode 100755
index 10abcefa..00000000
--- a/wqflask/dataSharing/SharingInfo.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# 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 = '
\n'
- for i in range(len(filelist)):
- if i%2==0:
- filename = filelist[i]
- filesize = filelist[i+1]
- htmlfilelist += "
"
- 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/wqflask/dataSharing/SharingInfoAddPage.py b/wqflask/dataSharing/SharingInfoAddPage.py
deleted file mode 100755
index 8174bf68..00000000
--- a/wqflask/dataSharing/SharingInfoAddPage.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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/wqflask/dataSharing/SharingInfoDeletePage.py b/wqflask/dataSharing/SharingInfoDeletePage.py
deleted file mode 100755
index edc0be7d..00000000
--- a/wqflask/dataSharing/SharingInfoDeletePage.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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/wqflask/dataSharing/SharingInfoEditPage.py b/wqflask/dataSharing/SharingInfoEditPage.py
deleted file mode 100755
index 266b8602..00000000
--- a/wqflask/dataSharing/SharingInfoEditPage.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# 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/wqflask/dataSharing/SharingInfoPage.py b/wqflask/dataSharing/SharingInfoPage.py
deleted file mode 100755
index 230ba2f3..00000000
--- a/wqflask/dataSharing/SharingInfoPage.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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/wqflask/dataSharing/SharingInfoUpdatePage.py b/wqflask/dataSharing/SharingInfoUpdatePage.py
deleted file mode 100755
index a70238b9..00000000
--- a/wqflask/dataSharing/SharingInfoUpdatePage.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# 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/wqflask/dataSharing/SharingListDataSetPage.py b/wqflask/dataSharing/SharingListDataSetPage.py
deleted file mode 100755
index ec90f5f3..00000000
--- a/wqflask/dataSharing/SharingListDataSetPage.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# 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(" ")
- operation.append(operation_delete)
- datasetRow.append(operation)
- datasetTable.append(datasetRow)
-
- TD_LR.append(heading, HT.P(), newrecord, HT.P(), info, HT.P(), datasetTable)
-
- js1 = """ """
- self.dict['js1'] = js1
- self.dict['body'] = str(TD_LR)
\ No newline at end of file
diff --git a/wqflask/dataSharing/SharingPage.py b/wqflask/dataSharing/SharingPage.py
deleted file mode 100755
index cf1d9ac3..00000000
--- a/wqflask/dataSharing/SharingPage.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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/wqflask/dataSharing/__init__.py b/wqflask/dataSharing/__init__.py
deleted file mode 100755
index e69de29b..00000000
--
cgit v1.2.3
From 275174497daa6d0dae64124addb360cb8c71c658 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Wed, 4 Jul 2012 21:41:34 -0400
Subject: Changes around trait data editing
---
wqflask/wqflask/dataSharing/SharingInfoPage.py | 13 +-
.../new/javascript/trait_data_and_analysis.coffee | 48 +++++-
.../new/javascript/trait_data_and_analysis.js | 54 +++++-
wqflask/wqflask/templates/base.html | 4 +-
wqflask/wqflask/templates/data_sharing.html | 190 +--------------------
.../wqflask/templates/trait_data_and_analysis.html | 20 ++-
wqflask/wqflask/views.py | 33 +++-
7 files changed, 153 insertions(+), 209 deletions(-)
diff --git a/wqflask/wqflask/dataSharing/SharingInfoPage.py b/wqflask/wqflask/dataSharing/SharingInfoPage.py
index 4e07e01b..91538a07 100755
--- a/wqflask/wqflask/dataSharing/SharingInfoPage.py
+++ b/wqflask/wqflask/dataSharing/SharingInfoPage.py
@@ -28,6 +28,8 @@ from __future__ import print_function, division
from pprint import pformat as pf
+import flask
+
from base.templatePage import templatePage
from base import webqtlConfig
from dbFunction import webqtlDatabaseFunction
@@ -42,8 +44,9 @@ class SharingInfoPage(templatePage):
def __init__(self, fd):
templatePage.__init__(self, fd)
+ self.redirect_url = None # Set if you want a redirect
print("fd is:", pf(fd.__dict__))
- # Todo: Need a [0] in line below????
+ # Todo: Need a [0] in line below????d
GN_AccessionId = fd.get('GN_AccessionId') # Used under search datasharing
InfoPageName = fd['database'][0]
cursor = webqtlDatabaseFunction.getCursor()
@@ -51,8 +54,12 @@ class SharingInfoPage(templatePage):
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
+ self.redirect_url = "http://23.21.59.238:5001/data_sharing&GN_AccessionId=%s" % GN_AccessionId
+ #self.redirect_url = flask.url_for('data_sharing', GN_AccessionId=GN_AccessionId[0])
+ print("set self.redirect_url")
+ #print("before redirect")
+ #return flask.redirect(url)
+ #print("after redirect")
else:
sharingInfoObject = SharingInfo.SharingInfo(GN_AccessionId, InfoPageName)
self.dict['body'] = sharingInfoObject.getBody(infoupdate="")
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
index 118be8ec..d3b1051d 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
@@ -1,5 +1,15 @@
console.log("start_b")
+isNumber = (o) ->
+ return ! isNaN (o-0) && o != null
+
+console.log("isNumber 7:", isNumber(7))
+console.log("isNumber 13.1:", isNumber(13.1))
+console.log("isNumber x:", isNumber("x"))
+console.log("isNumber '9':", isNumber('9'))
+console.log("isNumber:", isNumber())
+
+
$ ->
hide_tabs = (start) ->
for x in [start..10]
@@ -12,7 +22,7 @@ $ ->
console.log("hidden?")
-
+ # Changes stats table between all, bxd only and non-bxd, etc.
stats_mdp_change = ->
console.log("In stats_mdp_change")
selected = $(this).val()
@@ -24,3 +34,39 @@ $ ->
console.log("tape")
+
+ mean = (the_values)->
+ total = 0
+ total += value for value in the_values
+ console.log("yeap")
+ console.log(total)
+ the_mean = total / the_values.length
+ return the_mean.toFixed(2)
+
+
+
+ edit_data_change = ->
+ console.log("In edit_data_change")
+ the_values = []
+ #console.log($(this))
+ #$(this).each (counter, element) =>
+ # #console.log("counter is:" + counter)
+ # console.log("element is:")
+ # console.log(element)
+ console.log("foo")
+ values = $('#primary').find(".edit_strain_value")
+ console.log("values are:", values)
+ for value in values
+ console.log(value)
+ real_value = $(value).val()
+ #if real_value
+ console.log(real_value)
+ if isNumber(real_value) and real_value != ""
+ the_values.push(parseFloat(real_value))
+ console.log(the_values)
+ the_mean = mean(the_values)
+ console.log(the_mean)
+ $("#mean_value").html(the_mean)
+
+ $('#primary').change(edit_data_change)
+ console.log("loaded")
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
index e59edbdb..eecc630f 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
@@ -1,10 +1,25 @@
// Generated by CoffeeScript 1.3.3
(function() {
+ var isNumber;
console.log("start_b");
+ isNumber = function(o) {
+ return !isNaN((o - 0) && o !== null);
+ };
+
+ console.log("isNumber 7:", isNumber(7));
+
+ console.log("isNumber 13.1:", isNumber(13.1));
+
+ console.log("isNumber x:", isNumber("x"));
+
+ console.log("isNumber '9':", isNumber('9'));
+
+ console.log("isNumber:", isNumber());
+
$(function() {
- var hide_tabs, stats_mdp_change;
+ var edit_data_change, hide_tabs, mean, stats_mdp_change;
hide_tabs = function(start) {
var x, _i, _results;
_results = [];
@@ -26,7 +41,42 @@
return $("#stats_tabs" + selected).show();
};
$(".stats_mdp").change(stats_mdp_change);
- return console.log("tape");
+ console.log("tape");
+ mean = function(the_values) {
+ var the_mean, total, value, _i, _len;
+ total = 0;
+ for (_i = 0, _len = the_values.length; _i < _len; _i++) {
+ value = the_values[_i];
+ total += value;
+ }
+ console.log("yeap");
+ console.log(total);
+ the_mean = total / the_values.length;
+ return the_mean.toFixed(2);
+ };
+ edit_data_change = function() {
+ var real_value, the_mean, the_values, value, values, _i, _len;
+ console.log("In edit_data_change");
+ the_values = [];
+ console.log("foo");
+ values = $('#primary').find(".edit_strain_value");
+ console.log("values are:", values);
+ for (_i = 0, _len = values.length; _i < _len; _i++) {
+ value = values[_i];
+ console.log(value);
+ real_value = $(value).val();
+ console.log(real_value);
+ if (isNumber(real_value) && real_value !== "") {
+ the_values.push(parseFloat(real_value));
+ }
+ }
+ console.log(the_values);
+ the_mean = mean(the_values);
+ console.log(the_mean);
+ return $("#mean_value").html(the_mean);
+ };
+ $('#primary').change(edit_data_change);
+ return console.log("loaded");
});
}).call(this);
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 6776a71c..d7154a5b 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -18,11 +18,11 @@
-
+
-
+
diff --git a/wqflask/wqflask/templates/data_sharing.html b/wqflask/wqflask/templates/data_sharing.html
index e9d082d6..e6942504 100644
--- a/wqflask/wqflask/templates/data_sharing.html
+++ b/wqflask/wqflask/templates/data_sharing.html
@@ -1,112 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--
cgit v1.2.3
From 9515b97ae134ab923f935fa66b6a378056d616d0 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Thu, 5 Jul 2012 16:53:19 -0400
Subject: Working with Zach
---
wqflask/wqflask/show_trait/DataEditingPage.py | 24 ++++++++++++++++++++++
.../wqflask/templates/trait_data_and_analysis.html | 11 +++++-----
wqflask/wqflask/views.py | 24 ++++++++++++----------
3 files changed, 42 insertions(+), 17 deletions(-)
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index b1cf5a32..81bb3a92 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -6,6 +6,8 @@ import cPickle
from collections import OrderedDict
#import pyXLWriter as xl
+import yaml
+
from htmlgen import HTMLgen2 as HT
from base import webqtlConfig
@@ -210,6 +212,28 @@ class DataEditingPage(templatePage):
self.thisTrait = thisTrait
self.hddn = hddn
+ self.basic_table = {}
+ self.basic_table['rows'] = yaml.load("""
+ - N of Samples
+ - Mean
+ - Median
+ - Standard Error (SE)
+ - Standard Deviation (SD)
+ - Minimum
+ - Maximum
+ - Range (log2)
+ - Range (fold)
+ - Interquartile Range
+ """)
+
+ self.basic_table['columns'] = yaml.load("""
+ - All Cases
+ - BXD Only
+ - Non-BXD Only
+ """)
+
+ print(pf(self.basic_table))
+
##########################################
## Function to display header
##########################################
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index 1916a10c..0304aa03 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -258,6 +258,8 @@
//-->
+
+
@@ -3109,13 +3111,10 @@
-
+
+
-
+
{% endblock %}
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 55d6ffe2..caad811f 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -22,12 +22,22 @@ def index_page():
return render_template("index_page.html")
+@app.route("/data_sharing")
+def data_sharing():
+ print("In data_sharing")
+ fd = webqtlFormData.webqtlFormData(request.args)
+ print("1Have fd")
+ template_vars = SharingInfoPage.SharingInfoPage(fd)
+ print("1 Made it to rendering")
+ return template_vars
+
@app.route("/search")
def search():
if 'info_database' in request.args:
print("Going to sharing_info_page")
template_vars = sharing_info_page()
if template_vars.redirect_url:
+ print("Going to redirect")
return flask.redirect(template_vars.redirect_url)
else:
return render_template("data_sharing.html", **template_vars.__dict__)
@@ -35,14 +45,7 @@ def search():
the_search = search_results.SearchResultPage(request.args)
return render_template("search_result_page.html", **the_search.__dict__)
-@app.route("/data_sharing")
-def data_sharing():
- print("In data_sharing")
- fd = webqtlFormData.webqtlFormData(request.args)
- print("Have fd")
- template_vars = SharingInfoPage.SharingInfoPage(fd)
- print("Made it to rendering")
- return template_vars
+
@app.route("/showDatabaseBXD")
@@ -59,8 +62,7 @@ def showDatabaseBXD():
def sharing_info_page():
print("In sharing_info_page")
fd = webqtlFormData.webqtlFormData(request.args)
- print("Have fd")
- print("SharingInfoPage is:", SharingInfoPage)
+ print("2Have fd")
template_vars = SharingInfoPage.SharingInfoPage(fd)
- print("Made it to rendering")
+ print("2 Made it to rendering")
return template_vars
--
cgit v1.2.3
From d4085c3f85e392427067d2c004a0b15449fbc0d9 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Thu, 5 Jul 2012 16:53:51 -0400
Subject: Added DataTables
---
.../new/packages/DataTables/css/demo_page.css | 107 +
.../new/packages/DataTables/css/demo_table.css | 576 +
.../new/packages/DataTables/css/demo_table_jui.css | 526 +
.../packages/DataTables/css/jquery.dataTables.css | 220 +
.../css/jquery.dataTables_themeroller.css | 245 +
.../packages/DataTables/images/Sorting icons.psd | Bin 0 -> 27490 bytes
.../packages/DataTables/images/back_disabled.png | Bin 0 -> 1361 bytes
.../packages/DataTables/images/back_enabled.png | Bin 0 -> 1379 bytes
.../DataTables/images/back_enabled_hover.png | Bin 0 -> 1375 bytes
.../new/packages/DataTables/images/favicon.ico | Bin 0 -> 894 bytes
.../DataTables/images/forward_disabled.png | Bin 0 -> 1363 bytes
.../packages/DataTables/images/forward_enabled.png | Bin 0 -> 1380 bytes
.../DataTables/images/forward_enabled_hover.png | Bin 0 -> 1379 bytes
.../new/packages/DataTables/images/sort_asc.png | Bin 0 -> 1118 bytes
.../DataTables/images/sort_asc_disabled.png | Bin 0 -> 1050 bytes
.../new/packages/DataTables/images/sort_both.png | Bin 0 -> 1136 bytes
.../new/packages/DataTables/images/sort_desc.png | Bin 0 -> 1127 bytes
.../DataTables/images/sort_desc_disabled.png | Bin 0 -> 1045 bytes
.../packages/DataTables/js/jquery.dataTables.js | 11863 +++++++++++++++++++
.../DataTables/js/jquery.dataTables.min.js | 154 +
.../static/new/packages/DataTables/js/jquery.js | 4 +
.../new/packages/DataTables/src/DataTables.js | 259 +
.../packages/DataTables/src/api/api.internal.js | 128 +
.../new/packages/DataTables/src/api/api.methods.js | 1276 ++
.../new/packages/DataTables/src/api/api.static.js | 98 +
.../new/packages/DataTables/src/core/core.ajax.js | 185 +
.../packages/DataTables/src/core/core.columns.js | 365 +
.../DataTables/src/core/core.constructor.js | 439 +
.../new/packages/DataTables/src/core/core.data.js | 546 +
.../new/packages/DataTables/src/core/core.draw.js | 788 ++
.../packages/DataTables/src/core/core.filter.js | 405 +
.../new/packages/DataTables/src/core/core.info.js | 117 +
.../new/packages/DataTables/src/core/core.init.js | 153 +
.../packages/DataTables/src/core/core.length.js | 122 +
.../new/packages/DataTables/src/core/core.page.js | 119 +
.../DataTables/src/core/core.processing.js | 44 +
.../packages/DataTables/src/core/core.scrolling.js | 495 +
.../packages/DataTables/src/core/core.sizing.js | 405 +
.../new/packages/DataTables/src/core/core.sort.js | 460 +
.../new/packages/DataTables/src/core/core.state.js | 201 +
.../packages/DataTables/src/core/core.support.js | 316 +
.../new/packages/DataTables/src/ext/ext.classes.js | 112 +
.../new/packages/DataTables/src/ext/ext.paging.js | 257 +
.../new/packages/DataTables/src/ext/ext.sorting.js | 86 +
.../new/packages/DataTables/src/ext/ext.types.js | 88 +
.../packages/DataTables/src/model/model.column.js | 248 +
.../DataTables/src/model/model.defaults.columns.js | 737 ++
.../DataTables/src/model/model.defaults.js | 1944 +++
.../new/packages/DataTables/src/model/model.ext.js | 528 +
.../new/packages/DataTables/src/model/model.row.js | 64 +
.../packages/DataTables/src/model/model.search.js | 40 +
.../DataTables/src/model/model.settings.js | 868 ++
.../packages/DataTables/unit_testing/controller.js | 94 +
.../DataTables/unit_testing/controller.php | 100 +
.../packages/DataTables/unit_testing/index.html | 7 +
.../DataTables/unit_testing/performance/draw.html | 482 +
.../DataTables/unit_testing/performance/large.php | 108 +
.../DataTables/unit_testing/performance/page.html | 477 +
.../DataTables/unit_testing/performance/sort.html | 477 +
.../unit_testing/templates/-complex_header.php | 469 +
.../DataTables/unit_testing/templates/2512.php | 464 +
.../DataTables/unit_testing/templates/6776.php | 116 +
.../unit_testing/templates/complex_header_2.php | 485 +
.../unit_testing/templates/deferred_table.php | 132 +
.../DataTables/unit_testing/templates/dom_data.php | 465 +
.../unit_testing/templates/dom_data_th.php | 465 +
.../templates/dom_data_two_headers.php | 472 +
.../unit_testing/templates/dymanic_table.php | 45 +
.../unit_testing/templates/empty_table.php | 55 +
.../unit_testing/templates/html_table.php | 66 +
.../DataTables/unit_testing/templates/js_data.php | 124 +
.../unit_testing/templates/js_data_mixed_types.php | 124 +
.../unit_testing/templates/two_tables.php | 227 +
.../unit_testing/tests/1_dom/_zero_config.js | 437 +
.../tests_onhold/1_dom/-complex_header.js | 52 +
.../unit_testing/tests_onhold/1_dom/-iDraw.js | 41 +
.../unit_testing/tests_onhold/1_dom/2512.js | 17 +
.../unit_testing/tests_onhold/1_dom/2530-2.js | 15 +
.../unit_testing/tests_onhold/1_dom/2530.js | 29 +
.../unit_testing/tests_onhold/1_dom/2569.js | 36 +
.../unit_testing/tests_onhold/1_dom/2600.js | 44 +
.../unit_testing/tests_onhold/1_dom/2608.js | 54 +
.../unit_testing/tests_onhold/1_dom/2635.js | 40 +
.../tests_onhold/1_dom/2746-stable-sort.js | 199 +
.../unit_testing/tests_onhold/1_dom/2799.js | 14 +
.../tests_onhold/1_dom/2840-restore-table-width.js | 19 +
.../tests_onhold/1_dom/2914-state-save-sort.js | 39 +
.../tests_onhold/1_dom/5396-fnUpdate-arrays.js | 103 +
.../1_dom/5508-xscroll-zero-content.js | 23 +
.../1_dom/6776-scrolling-table-grows.js | 64 +
.../tests_onhold/1_dom/_zero_config.js | 437 +
.../unit_testing/tests_onhold/1_dom/aaSorting.js | 183 +
.../tests_onhold/1_dom/aaSortingFixed.js | 60 +
.../tests_onhold/1_dom/aoColumns.bSearchable.js | 67 +
.../tests_onhold/1_dom/aoColumns.bSortable.js | 105 +
.../tests_onhold/1_dom/aoColumns.bUseRendered.js | 145 +
.../tests_onhold/1_dom/aoColumns.bVisible.js | 132 +
.../tests_onhold/1_dom/aoColumns.bVisible2.js | 268 +
.../tests_onhold/1_dom/aoColumns.fnRender.js | 176 +
.../tests_onhold/1_dom/aoColumns.iDataSort.js | 88 +
.../tests_onhold/1_dom/aoColumns.sClass.js | 111 +
.../tests_onhold/1_dom/aoColumns.sName.js | 27 +
.../tests_onhold/1_dom/aoColumns.sTitle.js | 78 +
.../tests_onhold/1_dom/aoColumns.sWidth.js | 84 +
.../tests_onhold/1_dom/aoSearchCols.js | 112 +
.../tests_onhold/1_dom/asStripClasses.js | 106 +
.../unit_testing/tests_onhold/1_dom/bAutoWidth.js | 138 +
.../unit_testing/tests_onhold/1_dom/bFilter.js | 40 +
.../tests_onhold/1_dom/bInfiniteScroll.js | 130 +
.../unit_testing/tests_onhold/1_dom/bInfo.js | 40 +
.../unit_testing/tests_onhold/1_dom/bJQueryUI.js | 40 +
.../tests_onhold/1_dom/bLengthChange.js | 71 +
.../unit_testing/tests_onhold/1_dom/bPaginate.js | 55 +
.../unit_testing/tests_onhold/1_dom/bProcessing.js | 99 +
.../unit_testing/tests_onhold/1_dom/bServerSide.js | 18 +
.../unit_testing/tests_onhold/1_dom/bSort.js | 101 +
.../tests_onhold/1_dom/bSortCellsTop.js | 77 +
.../tests_onhold/1_dom/bSortClasses.js | 128 +
.../tests_onhold/1_dom/fnCookieCallback.js | 97 +
.../tests_onhold/1_dom/fnCreatedCell.js | 151 +
.../tests_onhold/1_dom/fnCreatedRow.js | 115 +
.../unit_testing/tests_onhold/1_dom/fnDeleteRow.js | 30 +
.../tests_onhold/1_dom/fnDrawCallback.js | 80 +
.../unit_testing/tests_onhold/1_dom/fnFilter.js | 16 +
.../tests_onhold/1_dom/fnFooterCallback.js | 227 +
.../tests_onhold/1_dom/fnHeaderCallback.js | 227 +
.../tests_onhold/1_dom/fnInfoCallback.js | 115 +
.../tests_onhold/1_dom/fnInitComplete.js | 94 +
.../tests_onhold/1_dom/fnRowCallback.js | 105 +
.../tests_onhold/1_dom/fnSetColumnVis.js | 120 +
.../tests_onhold/1_dom/fnSetColumnVis2.js | 236 +
.../tests_onhold/1_dom/html-autodetect-sort.js | 57 +
.../tests_onhold/1_dom/iDisplayLength.js | 76 +
.../tests_onhold/1_dom/oLanguage.oPaginate.js | 80 +
.../tests_onhold/1_dom/oLanguage.sInfo.js | 109 +
.../tests_onhold/1_dom/oLanguage.sInfoEmpty.js | 75 +
.../tests_onhold/1_dom/oLanguage.sInfoPostFix.js | 73 +
.../tests_onhold/1_dom/oLanguage.sLengthMenu.js | 106 +
.../tests_onhold/1_dom/oLanguage.sProcessing.js | 47 +
.../tests_onhold/1_dom/oLanguage.sSearch.js | 66 +
.../tests_onhold/1_dom/oLanguage.sUrl.js | 59 +
.../tests_onhold/1_dom/oLanguage.sZeroRecords.js | 45 +
.../unit_testing/tests_onhold/1_dom/oSearch.js | 101 +
.../unit_testing/tests_onhold/1_dom/sAjaxSource.js | 18 +
.../unit_testing/tests_onhold/1_dom/sDom.js | 319 +
.../tests_onhold/1_dom/sPaginationType.js | 122 +
.../unit_testing/tests_onhold/1_dom/sScrollXY.js | 63 +
.../unit_testing/tests_onhold/1_dom/th_in_body.js | 437 +
.../2_js/6872-default-content-missing-props.js | 285 +
.../2_js/8549--string-sorting-nonstrings.js | 47 +
.../unit_testing/tests_onhold/2_js/_zero_config.js | 440 +
.../unit_testing/tests_onhold/2_js/aaSorting.js | 198 +
.../tests_onhold/2_js/aaSortingFixed.js | 64 +
.../tests_onhold/2_js/aoColumns.bSearchable.js | 71 +
.../tests_onhold/2_js/aoColumns.bSortable.js | 109 +
.../tests_onhold/2_js/aoColumns.bUseRendered.js | 148 +
.../tests_onhold/2_js/aoColumns.bVisible.js | 110 +
.../tests_onhold/2_js/aoColumns.fnRender.js | 156 +
.../tests_onhold/2_js/aoColumns.iDataSort.js | 90 +
.../tests_onhold/2_js/aoColumns.sClass.js | 115 +
.../tests_onhold/2_js/aoColumns.sName.js | 28 +
.../tests_onhold/2_js/aoColumns.sTitle.js | 82 +
.../tests_onhold/2_js/aoColumns.sWidth.js | 87 +
.../unit_testing/tests_onhold/2_js/aoSearchCols.js | 119 +
.../tests_onhold/2_js/asStripClasses.js | 100 +
.../unit_testing/tests_onhold/2_js/bAutoWidth.js | 142 +
.../unit_testing/tests_onhold/2_js/bFilter.js | 44 +
.../unit_testing/tests_onhold/2_js/bInfo.js | 44 +
.../tests_onhold/2_js/bLengthChange.js | 75 +
.../unit_testing/tests_onhold/2_js/bPaginate.js | 59 +
.../unit_testing/tests_onhold/2_js/bProcessing.js | 103 +
.../unit_testing/tests_onhold/2_js/bServerSide.js | 20 +
.../unit_testing/tests_onhold/2_js/bSort.js | 99 +
.../unit_testing/tests_onhold/2_js/bSortClasses.js | 132 +
.../tests_onhold/2_js/fnCreatedCell.js | 158 +
.../unit_testing/tests_onhold/2_js/fnCreatedRow.js | 121 +
.../tests_onhold/2_js/fnDrawCallback.js | 85 +
.../tests_onhold/2_js/fnFooterCallback.js | 240 +
.../tests_onhold/2_js/fnHeaderCallback.js | 240 +
.../tests_onhold/2_js/fnInitComplete.js | 83 +
.../tests_onhold/2_js/fnRowCallback.js | 112 +
.../tests_onhold/2_js/iDisplayLength.js | 81 +
.../tests_onhold/2_js/js_data_mixed_types.js | 392 +
.../tests_onhold/2_js/oLanguage.oPaginate.js | 84 +
.../tests_onhold/2_js/oLanguage.sInfo.js | 117 +
.../tests_onhold/2_js/oLanguage.sInfoEmpty.js | 79 +
.../tests_onhold/2_js/oLanguage.sInfoPostFix.js | 78 +
.../tests_onhold/2_js/oLanguage.sLengthMenu.js | 111 +
.../tests_onhold/2_js/oLanguage.sProcessing.js | 49 +
.../tests_onhold/2_js/oLanguage.sSearch.js | 70 +
.../tests_onhold/2_js/oLanguage.sUrl.js | 62 +
.../tests_onhold/2_js/oLanguage.sZeroRecords.js | 48 +
.../unit_testing/tests_onhold/2_js/oSearch.js | 108 +
.../unit_testing/tests_onhold/2_js/sAjaxSource.js | 20 +
.../unit_testing/tests_onhold/2_js/sDom.js | 262 +
.../tests_onhold/2_js/sPaginationType.js | 125 +
.../tests_onhold/3_ajax/_zero_config.js | 440 +
.../unit_testing/tests_onhold/3_ajax/aaSorting.js | 198 +
.../tests_onhold/3_ajax/aaSortingFixed.js | 67 +
.../tests_onhold/3_ajax/aoColumns.bSearchable.js | 76 +
.../tests_onhold/3_ajax/aoColumns.bSortable.js | 109 +
.../tests_onhold/3_ajax/aoColumns.bUseRendered.js | 148 +
.../tests_onhold/3_ajax/aoColumns.bVisible.js | 124 +
.../tests_onhold/3_ajax/aoColumns.fnRender.js | 156 +
.../tests_onhold/3_ajax/aoColumns.iDataSort.js | 90 +
.../tests_onhold/3_ajax/aoColumns.sClass.js | 115 +
.../tests_onhold/3_ajax/aoColumns.sName.js | 28 +
.../tests_onhold/3_ajax/aoColumns.sTitle.js | 82 +
.../tests_onhold/3_ajax/aoColumns.sWidth.js | 87 +
.../tests_onhold/3_ajax/aoSearchCols.js | 119 +
.../tests_onhold/3_ajax/asStripClasses.js | 105 +
.../unit_testing/tests_onhold/3_ajax/bAutoWidth.js | 142 +
.../unit_testing/tests_onhold/3_ajax/bFilter.js | 44 +
.../unit_testing/tests_onhold/3_ajax/bInfo.js | 44 +
.../tests_onhold/3_ajax/bLengthChange.js | 75 +
.../unit_testing/tests_onhold/3_ajax/bPaginate.js | 59 +
.../tests_onhold/3_ajax/bProcessing.js | 103 +
.../tests_onhold/3_ajax/bServerSide.js | 20 +
.../unit_testing/tests_onhold/3_ajax/bSort.js | 99 +
.../tests_onhold/3_ajax/bSortClasses.js | 132 +
.../tests_onhold/3_ajax/fnCreatedCell.js | 183 +
.../tests_onhold/3_ajax/fnCreatedRow.js | 142 +
.../tests_onhold/3_ajax/fnDrawCallback.js | 98 +
.../tests_onhold/3_ajax/fnHeaderCallback.js | 191 +
.../tests_onhold/3_ajax/fnInitComplete.js | 100 +
.../tests_onhold/3_ajax/fnRowCallback.js | 112 +
.../tests_onhold/3_ajax/fnServerData.js | 64 +
.../tests_onhold/3_ajax/iDisplayLength.js | 81 +
.../tests_onhold/3_ajax/oLanguage.oPaginate.js | 84 +
.../tests_onhold/3_ajax/oLanguage.sInfo.js | 117 +
.../tests_onhold/3_ajax/oLanguage.sInfoEmpty.js | 79 +
.../tests_onhold/3_ajax/oLanguage.sInfoPostFix.js | 78 +
.../tests_onhold/3_ajax/oLanguage.sLengthMenu.js | 111 +
.../3_ajax/oLanguage.sLoadingRecords.js | 65 +
.../tests_onhold/3_ajax/oLanguage.sProcessing.js | 49 +
.../tests_onhold/3_ajax/oLanguage.sSearch.js | 70 +
.../tests_onhold/3_ajax/oLanguage.sUrl.js | 62 +
.../tests_onhold/3_ajax/oLanguage.sZeroRecords.js | 48 +
.../unit_testing/tests_onhold/3_ajax/oSearch.js | 108 +
.../tests_onhold/3_ajax/sAjaxDataProp.js | 139 +
.../tests_onhold/3_ajax/sAjaxDataProp2.js | 139 +
.../tests_onhold/3_ajax/sAjaxSource.js | 22 +
.../unit_testing/tests_onhold/3_ajax/sDom.js | 262 +
.../tests_onhold/3_ajax/sPaginationType.js | 134 +
.../tests_onhold/4_server-side/-iDraw.js | 44 +
.../tests_onhold/4_server-side/2440.js | 32 +
.../tests_onhold/4_server-side/2569.js | 47 +
.../tests_onhold/4_server-side/2600.js | 47 +
.../tests_onhold/4_server-side/_zero_config.js | 424 +
.../tests_onhold/4_server-side/aaSorting.js | 212 +
.../tests_onhold/4_server-side/aaSortingFixed.js | 67 +
.../4_server-side/aoColumns.bSearchable.js | 25 +
.../4_server-side/aoColumns.bSortable.js | 112 +
.../4_server-side/aoColumns.bUseRendered.js | 43 +
.../4_server-side/aoColumns.bVisible.js | 123 +
.../4_server-side/aoColumns.fnRender.js | 162 +
.../tests_onhold/4_server-side/aoColumns.sClass.js | 118 +
.../tests_onhold/4_server-side/aoColumns.sName.js | 29 +
.../tests_onhold/4_server-side/aoColumns.sTitle.js | 85 +
.../tests_onhold/4_server-side/aoColumns.sWidth.js | 90 +
.../tests_onhold/4_server-side/aoSearchCols.js | 70 +
.../tests_onhold/4_server-side/asStripClasses.js | 109 +
.../tests_onhold/4_server-side/bAutoWidth.js | 145 +
.../tests_onhold/4_server-side/bFilter.js | 47 +
.../tests_onhold/4_server-side/bInfiniteScroll.js | 168 +
.../tests_onhold/4_server-side/bInfo.js | 47 +
.../tests_onhold/4_server-side/bLengthChange.js | 78 +
.../tests_onhold/4_server-side/bPaginate.js | 62 +
.../tests_onhold/4_server-side/bProcessing.js | 106 +
.../tests_onhold/4_server-side/bServerSide.js | 21 +
.../tests_onhold/4_server-side/bSort.js | 102 +
.../tests_onhold/4_server-side/bSortClasses.js | 135 +
.../tests_onhold/4_server-side/fnCreatedCell.js | 190 +
.../tests_onhold/4_server-side/fnCreatedRow.js | 148 +
.../tests_onhold/4_server-side/fnDrawCallback.js | 89 +
.../tests_onhold/4_server-side/fnHeaderCallback.js | 191 +
.../tests_onhold/4_server-side/fnInitComplete.js | 89 +
.../tests_onhold/4_server-side/fnRowCallback.js | 118 +
.../tests_onhold/4_server-side/iDeferLoading.js | 95 +
.../tests_onhold/4_server-side/iDisplayLength.js | 85 +
.../4_server-side/oLanguage.oPaginate.js | 86 +
.../tests_onhold/4_server-side/oLanguage.sInfo.js | 124 +
.../4_server-side/oLanguage.sInfoEmpty.js | 82 +
.../4_server-side/oLanguage.sInfoPostFix.js | 82 +
.../4_server-side/oLanguage.sLengthMenu.js | 115 +
.../4_server-side/oLanguage.sProcessing.js | 51 +
.../4_server-side/oLanguage.sSearch.js | 73 +
.../tests_onhold/4_server-side/oLanguage.sUrl.js | 64 +
.../4_server-side/oLanguage.sZeroRecords.js | 58 +
.../tests_onhold/4_server-side/oSearch.js | 100 +
.../tests_onhold/4_server-side/sAjaxDataProp.js | 146 +
.../tests_onhold/4_server-side/sAjaxSource.js | 23 +
.../tests_onhold/4_server-side/sDom.js | 269 +
.../tests_onhold/4_server-side/sPaginationType.js | 138 +
.../tests_onhold/5_ajax_objects/_zero_config.js | 847 ++
.../_zero_config_arrays_subobjects.js | 961 ++
.../5_ajax_objects/_zero_config_deep.js | 1075 ++
.../5_ajax_objects/_zero_config_null_source.js | 458 +
.../5_ajax_objects/_zero_config_objects.js | 847 ++
.../_zero_config_objects_subarrays.js | 961 ++
.../tests_onhold/5_ajax_objects/aaSorting.js | 296 +
.../tests_onhold/5_ajax_objects/aaSortingFixed.js | 88 +
.../5_ajax_objects/aoColumns.bSearchable.js | 83 +
.../5_ajax_objects/aoColumns.bSortable.js | 116 +
.../5_ajax_objects/aoColumns.bUseRendered.js | 155 +
.../5_ajax_objects/aoColumns.bVisible.js | 131 +
.../5_ajax_objects/aoColumns.fnRender.js | 177 +
.../5_ajax_objects/aoColumns.iDataSort.js | 90 +
.../5_ajax_objects/aoColumns.sClass.js | 122 +
.../tests_onhold/5_ajax_objects/aoColumns.sName.js | 28 +
.../5_ajax_objects/aoColumns.sTitle.js | 89 +
.../5_ajax_objects/aoColumns.sWidth.js | 87 +
.../tests_onhold/5_ajax_objects/aoSearchCols.js | 161 +
.../tests_onhold/5_ajax_objects/asStripClasses.js | 133 +
.../tests_onhold/5_ajax_objects/bAutoWidth.js | 163 +
.../tests_onhold/5_ajax_objects/bFilter.js | 65 +
.../tests_onhold/5_ajax_objects/bInfo.js | 65 +
.../tests_onhold/5_ajax_objects/bLengthChange.js | 96 +
.../tests_onhold/5_ajax_objects/bPaginate.js | 80 +
.../tests_onhold/5_ajax_objects/bProcessing.js | 124 +
.../tests_onhold/5_ajax_objects/bServerSide.js | 27 +
.../tests_onhold/5_ajax_objects/bSort.js | 120 +
.../tests_onhold/5_ajax_objects/bSortClasses.js | 153 +
.../tests_onhold/5_ajax_objects/fnDrawCallback.js | 126 +
.../5_ajax_objects/fnHeaderCallback.js | 254 +
.../tests_onhold/5_ajax_objects/fnInitComplete.js | 135 +
.../tests_onhold/5_ajax_objects/fnRowCallback.js | 154 +
.../tests_onhold/5_ajax_objects/fnServerData.js | 92 +
.../tests_onhold/5_ajax_objects/iDisplayLength.js | 109 +
.../5_ajax_objects/oLanguage.oPaginate.js | 98 +
.../tests_onhold/5_ajax_objects/oLanguage.sInfo.js | 166 +
.../5_ajax_objects/oLanguage.sInfoEmpty.js | 100 +
.../5_ajax_objects/oLanguage.sInfoPostFix.js | 106 +
.../5_ajax_objects/oLanguage.sLengthMenu.js | 139 +
.../5_ajax_objects/oLanguage.sProcessing.js | 63 +
.../5_ajax_objects/oLanguage.sSearch.js | 91 +
.../tests_onhold/5_ajax_objects/oLanguage.sUrl.js | 76 +
.../5_ajax_objects/oLanguage.sZeroRecords.js | 62 +
.../tests_onhold/5_ajax_objects/oSearch.js | 150 +
.../tests_onhold/5_ajax_objects/sAjaxSource.js | 29 +
.../tests_onhold/5_ajax_objects/sDom.js | 311 +
.../tests_onhold/5_ajax_objects/sPaginationType.js | 148 +
.../6_delayed_rendering/_zero_config.js | 403 +
.../tests_onhold/6_delayed_rendering/aaSorting.js | 212 +
.../6_delayed_rendering/aaSortingFixed.js | 70 +
.../6_delayed_rendering/aoColumns.bSearchable.js | 79 +
.../6_delayed_rendering/aoColumns.bSortable.js | 112 +
.../6_delayed_rendering/aoColumns.bUseRendered.js | 151 +
.../6_delayed_rendering/aoColumns.bVisible.js | 127 +
.../6_delayed_rendering/aoColumns.fnRender.js | 190 +
.../6_delayed_rendering/aoColumns.iDataSort.js | 92 +
.../6_delayed_rendering/aoColumns.sClass.js | 118 +
.../6_delayed_rendering/aoColumns.sName.js | 29 +
.../6_delayed_rendering/aoColumns.sTitle.js | 85 +
.../6_delayed_rendering/aoColumns.sWidth.js | 90 +
.../6_delayed_rendering/aoSearchCols.js | 125 +
.../6_delayed_rendering/asStripClasses.js | 109 +
.../tests_onhold/6_delayed_rendering/bAutoWidth.js | 145 +
.../tests_onhold/6_delayed_rendering/bFilter.js | 47 +
.../tests_onhold/6_delayed_rendering/bInfo.js | 47 +
.../6_delayed_rendering/bLengthChange.js | 78 +
.../tests_onhold/6_delayed_rendering/bPaginate.js | 62 +
.../6_delayed_rendering/bProcessing.js | 106 +
.../6_delayed_rendering/bServerSide.js | 21 +
.../tests_onhold/6_delayed_rendering/bSort.js | 102 +
.../6_delayed_rendering/bSortClasses.js | 135 +
.../6_delayed_rendering/fnDrawCallback.js | 102 +
.../6_delayed_rendering/fnHeaderCallback.js | 200 +
.../6_delayed_rendering/fnInitComplete.js | 105 +
.../6_delayed_rendering/fnRowCallback.js | 118 +
.../6_delayed_rendering/fnServerData.js | 68 +
.../6_delayed_rendering/iDisplayLength.js | 85 +
.../6_delayed_rendering/oLanguage.oPaginate.js | 86 +
.../6_delayed_rendering/oLanguage.sInfo.js | 124 +
.../6_delayed_rendering/oLanguage.sInfoEmpty.js | 82 +
.../6_delayed_rendering/oLanguage.sInfoPostFix.js | 82 +
.../6_delayed_rendering/oLanguage.sLengthMenu.js | 115 +
.../6_delayed_rendering/oLanguage.sProcessing.js | 51 +
.../6_delayed_rendering/oLanguage.sSearch.js | 73 +
.../6_delayed_rendering/oLanguage.sUrl.js | 64 +
.../6_delayed_rendering/oLanguage.sZeroRecords.js | 50 +
.../tests_onhold/6_delayed_rendering/oSearch.js | 114 +
.../6_delayed_rendering/sAjaxDataProp.js | 140 +
.../6_delayed_rendering/sAjaxDataProp2.js | 140 +
.../6_delayed_rendering/sAjaxSource.js | 23 +
.../tests_onhold/6_delayed_rendering/sDom.js | 269 +
.../6_delayed_rendering/sPaginationType.js | 136 +
.../packages/DataTables/unit_testing/unit_test.js | 409 +
388 files changed, 70486 insertions(+)
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/css/demo_page.css
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/css/demo_table.css
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/css/demo_table_jui.css
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables_themeroller.css
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/Sorting icons.psd
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/back_disabled.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/back_enabled.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/back_enabled_hover.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/favicon.ico
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/forward_disabled.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled_hover.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/sort_asc.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/sort_asc_disabled.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/sort_both.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/sort_desc.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/images/sort_desc_disabled.png
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/js/jquery.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/DataTables.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/api/api.internal.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/api/api.methods.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/api/api.static.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.ajax.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.columns.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.constructor.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.data.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.draw.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.filter.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.info.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.init.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.length.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.page.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.processing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.scrolling.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.sizing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.sort.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.state.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/core/core.support.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/ext/ext.classes.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/ext/ext.paging.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/ext/ext.sorting.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/ext/ext.types.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/model/model.column.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/model/model.defaults.columns.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/model/model.defaults.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/model/model.ext.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/model/model.row.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/model/model.search.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/src/model/model.settings.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/controller.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/controller.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/index.html
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/performance/draw.html
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/performance/large.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/performance/page.html
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/performance/sort.html
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/-complex_header.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/2512.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/6776.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/complex_header_2.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/deferred_table.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/dom_data.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/dom_data_th.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/dom_data_two_headers.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/dymanic_table.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/empty_table.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/html_table.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/js_data.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/js_data_mixed_types.php
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/templates/two_tables.php
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests/1_dom/_zero_config.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/-complex_header.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/-iDraw.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2512.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2530-2.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2530.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2569.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2600.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2608.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2635.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2746-stable-sort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2799.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2840-restore-table-width.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/2914-state-save-sort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/5396-fnUpdate-arrays.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/5508-xscroll-zero-content.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/6776-scrolling-table-grows.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/_zero_config.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aaSorting.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aaSortingFixed.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.bSearchable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.bSortable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.bUseRendered.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.bVisible.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.bVisible2.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.fnRender.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.iDataSort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.sClass.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.sName.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.sTitle.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoColumns.sWidth.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/aoSearchCols.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/asStripClasses.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bAutoWidth.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bFilter.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bInfiniteScroll.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bInfo.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bJQueryUI.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bLengthChange.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bPaginate.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bProcessing.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bServerSide.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bSort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bSortCellsTop.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/bSortClasses.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnCookieCallback.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnCreatedCell.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnCreatedRow.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnDeleteRow.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnDrawCallback.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnFilter.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnFooterCallback.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnHeaderCallback.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnInfoCallback.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnInitComplete.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnRowCallback.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnSetColumnVis.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/fnSetColumnVis2.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/html-autodetect-sort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/iDisplayLength.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.oPaginate.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sInfo.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sInfoEmpty.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sInfoPostFix.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sLengthMenu.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sProcessing.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sSearch.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sUrl.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oLanguage.sZeroRecords.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/oSearch.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/sAjaxSource.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/sDom.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/sPaginationType.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/sScrollXY.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/th_in_body.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/6872-default-content-missing-props.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/8549--string-sorting-nonstrings.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/_zero_config.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aaSorting.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aaSortingFixed.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.bSearchable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.bSortable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.bUseRendered.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.bVisible.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.fnRender.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.iDataSort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.sClass.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.sName.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.sTitle.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoColumns.sWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/aoSearchCols.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/asStripClasses.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bAutoWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bFilter.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bLengthChange.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bServerSide.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bSort.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/bSortClasses.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/fnCreatedCell.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/fnCreatedRow.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/fnDrawCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/fnFooterCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/fnHeaderCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/fnInitComplete.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/fnRowCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/iDisplayLength.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/js_data_mixed_types.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.oPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sInfoEmpty.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sInfoPostFix.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sLengthMenu.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sUrl.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oLanguage.sZeroRecords.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/oSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/sAjaxSource.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/sDom.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/2_js/sPaginationType.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/_zero_config.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aaSorting.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aaSortingFixed.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.bSearchable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.bSortable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.bUseRendered.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.bVisible.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.fnRender.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.iDataSort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.sClass.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.sName.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.sTitle.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoColumns.sWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/aoSearchCols.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/asStripClasses.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bAutoWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bFilter.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bLengthChange.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bServerSide.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bSort.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/bSortClasses.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/fnCreatedCell.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/fnCreatedRow.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/fnDrawCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/fnHeaderCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/fnInitComplete.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/fnRowCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/fnServerData.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/iDisplayLength.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.oPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sInfoEmpty.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sInfoPostFix.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sLengthMenu.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sLoadingRecords.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sUrl.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oLanguage.sZeroRecords.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/oSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/sAjaxDataProp.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/sAjaxDataProp2.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/sAjaxSource.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/sDom.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/3_ajax/sPaginationType.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/-iDraw.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/2440.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/2569.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/2600.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/_zero_config.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aaSorting.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aaSortingFixed.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.bSearchable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.bSortable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.bUseRendered.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.bVisible.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.fnRender.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.sClass.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.sName.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.sTitle.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoColumns.sWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/aoSearchCols.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/asStripClasses.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bAutoWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bFilter.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bInfiniteScroll.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bLengthChange.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bServerSide.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bSort.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/bSortClasses.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/fnCreatedCell.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/fnCreatedRow.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/fnDrawCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/fnHeaderCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/fnInitComplete.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/fnRowCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/iDeferLoading.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/iDisplayLength.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.oPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sInfoEmpty.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sInfoPostFix.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sLengthMenu.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sUrl.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oLanguage.sZeroRecords.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/oSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/sAjaxDataProp.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/sAjaxSource.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/sDom.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/4_server-side/sPaginationType.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/_zero_config.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/_zero_config_arrays_subobjects.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/_zero_config_deep.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/_zero_config_null_source.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/_zero_config_objects.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/_zero_config_objects_subarrays.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aaSorting.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aaSortingFixed.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.bSearchable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.bSortable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.bUseRendered.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.bVisible.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.fnRender.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.iDataSort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.sClass.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.sName.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.sTitle.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoColumns.sWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/aoSearchCols.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/asStripClasses.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bAutoWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bFilter.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bLengthChange.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bServerSide.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bSort.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/bSortClasses.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/fnDrawCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/fnHeaderCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/fnInitComplete.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/fnRowCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/fnServerData.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/iDisplayLength.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.oPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sInfoEmpty.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sInfoPostFix.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sLengthMenu.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sUrl.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oLanguage.sZeroRecords.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/oSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/sAjaxSource.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/sDom.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/5_ajax_objects/sPaginationType.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/_zero_config.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aaSorting.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aaSortingFixed.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.bSearchable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.bSortable.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.bUseRendered.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.bVisible.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.fnRender.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.iDataSort.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.sClass.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.sName.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.sTitle.js
create mode 100755 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoColumns.sWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/aoSearchCols.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/asStripClasses.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bAutoWidth.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bFilter.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bLengthChange.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bServerSide.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bSort.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/bSortClasses.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/fnDrawCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/fnHeaderCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/fnInitComplete.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/fnRowCallback.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/fnServerData.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/iDisplayLength.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.oPaginate.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sInfo.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sInfoEmpty.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sInfoPostFix.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sLengthMenu.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sProcessing.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sUrl.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oLanguage.sZeroRecords.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/oSearch.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/sAjaxDataProp.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/sAjaxDataProp2.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/sAjaxSource.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/sDom.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/sPaginationType.js
create mode 100644 wqflask/wqflask/static/new/packages/DataTables/unit_testing/unit_test.js
diff --git a/wqflask/wqflask/static/new/packages/DataTables/css/demo_page.css b/wqflask/wqflask/static/new/packages/DataTables/css/demo_page.css
new file mode 100644
index 00000000..89c62bb7
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/css/demo_page.css
@@ -0,0 +1,107 @@
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * General page setup
+ */
+#dt_example {
+ font: 80%/1.45em "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
+ margin: 0;
+ padding: 0;
+ color: #333;
+ background-color: #fff;
+}
+
+
+#dt_example #container {
+ width: 800px;
+ margin: 30px auto;
+ padding: 0;
+}
+
+
+#dt_example #footer {
+ margin: 50px auto 0 auto;
+ padding: 0;
+}
+
+#dt_example #demo {
+ margin: 30px auto 0 auto;
+}
+
+#dt_example .demo_jui {
+ margin: 30px auto 0 auto;
+}
+
+#dt_example .big {
+ font-size: 1.3em;
+ font-weight: bold;
+ line-height: 1.6em;
+ color: #4E6CA3;
+}
+
+#dt_example .spacer {
+ height: 20px;
+ clear: both;
+}
+
+#dt_example .clear {
+ clear: both;
+}
+
+#dt_example pre {
+ padding: 15px;
+ background-color: #F5F5F5;
+ border: 1px solid #CCCCCC;
+}
+
+#dt_example h1 {
+ margin-top: 2em;
+ font-size: 1.3em;
+ font-weight: normal;
+ line-height: 1.6em;
+ color: #4E6CA3;
+ border-bottom: 1px solid #B0BED9;
+ clear: both;
+}
+
+#dt_example h2 {
+ font-size: 1.2em;
+ font-weight: normal;
+ line-height: 1.6em;
+ color: #4E6CA3;
+ clear: both;
+}
+
+#dt_example a {
+ color: #0063DC;
+ text-decoration: none;
+}
+
+#dt_example a:hover {
+ text-decoration: underline;
+}
+
+#dt_example ul {
+ color: #4E6CA3;
+}
+
+.css_right {
+ float: right;
+}
+
+.css_left {
+ float: left;
+}
+
+.demo_links {
+ float: left;
+ width: 50%;
+ margin-bottom: 1em;
+}
+
+#demo_info {
+ padding: 5px;
+ border: 1px solid #B0BED9;
+ height: 100px;
+ width: 100%;
+ overflow: auto;
+}
\ No newline at end of file
diff --git a/wqflask/wqflask/static/new/packages/DataTables/css/demo_table.css b/wqflask/wqflask/static/new/packages/DataTables/css/demo_table.css
new file mode 100644
index 00000000..f41a0042
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/css/demo_table.css
@@ -0,0 +1,576 @@
+/*
+ * File: demo_table.css
+ * CVS: $Id$
+ * Description: CSS descriptions for DataTables demo pages
+ * Author: Allan Jardine
+ * Created: Tue May 12 06:47:22 BST 2009
+ * Modified: $Date$ by $Author$
+ * Language: CSS
+ * Project: DataTables
+ *
+ * Copyright 2009 Allan Jardine. All Rights Reserved.
+ *
+ * ***************************************************************************
+ * DESCRIPTION
+ *
+ * The styles given here are suitable for the demos that are used with the standard DataTables
+ * distribution (see www.datatables.net). You will most likely wish to modify these styles to
+ * meet the layout requirements of your site.
+ *
+ * Common issues:
+ * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is
+ * no conflict between the two pagination types. If you want to use full_numbers pagination
+ * ensure that you either have "example_alt_pagination" as a body class name, or better yet,
+ * modify that selector.
+ * Note that the path used for Images is relative. All images are by default located in
+ * ../images/ - relative to this CSS file.
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables features
+ */
+
+.dataTables_wrapper {
+ position: relative;
+ clear: both;
+ zoom: 1; /* Feeling sorry for IE */
+}
+
+.dataTables_processing {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 250px;
+ height: 30px;
+ margin-left: -125px;
+ margin-top: -15px;
+ padding: 14px 0 2px 0;
+ border: 1px solid #ddd;
+ text-align: center;
+ color: #999;
+ font-size: 14px;
+ background-color: white;
+}
+
+.dataTables_length {
+ width: 40%;
+ float: left;
+}
+
+.dataTables_filter {
+ width: 50%;
+ float: right;
+ text-align: right;
+}
+
+.dataTables_info {
+ width: 60%;
+ float: left;
+}
+
+.dataTables_paginate {
+ float: right;
+ text-align: right;
+}
+
+/* Pagination nested */
+.paginate_disabled_previous, .paginate_enabled_previous,
+.paginate_disabled_next, .paginate_enabled_next {
+ height: 19px;
+ float: left;
+ cursor: pointer;
+ *cursor: hand;
+ color: #111 !important;
+}
+.paginate_disabled_previous:hover, .paginate_enabled_previous:hover,
+.paginate_disabled_next:hover, .paginate_enabled_next:hover {
+ text-decoration: none !important;
+}
+.paginate_disabled_previous:active, .paginate_enabled_previous:active,
+.paginate_disabled_next:active, .paginate_enabled_next:active {
+ outline: none;
+}
+
+.paginate_disabled_previous,
+.paginate_disabled_next {
+ color: #666 !important;
+}
+.paginate_disabled_previous, .paginate_enabled_previous {
+ padding-left: 23px;
+}
+.paginate_disabled_next, .paginate_enabled_next {
+ padding-right: 23px;
+ margin-left: 10px;
+}
+
+.paginate_disabled_previous {
+ background: url('../images/back_disabled.png') no-repeat top left;
+}
+
+.paginate_enabled_previous {
+ background: url('../images/back_enabled.png') no-repeat top left;
+}
+.paginate_enabled_previous:hover {
+ background: url('../images/back_enabled_hover.png') no-repeat top left;
+}
+
+.paginate_disabled_next {
+ background: url('../images/forward_disabled.png') no-repeat top right;
+}
+
+.paginate_enabled_next {
+ background: url('../images/forward_enabled.png') no-repeat top right;
+}
+.paginate_enabled_next:hover {
+ background: url('../images/forward_enabled_hover.png') no-repeat top right;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables display
+ */
+table.display {
+ margin: 0 auto;
+ clear: both;
+ width: 100%;
+
+ /* Note Firefox 3.5 and before have a bug with border-collapse
+ * ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 )
+ * border-spacing: 0; is one possible option. Conditional-css.com is
+ * useful for this kind of thing
+ *
+ * Further note IE 6/7 has problems when calculating widths with border width.
+ * It subtracts one px relative to the other browsers from the first column, and
+ * adds one to the end...
+ *
+ * If you want that effect I'd suggest setting a border-top/left on th/td's and
+ * then filling in the gaps with other borders.
+ */
+}
+
+table.display thead th {
+ padding: 3px 18px 3px 10px;
+ border-bottom: 1px solid black;
+ font-weight: bold;
+ cursor: pointer;
+ * cursor: hand;
+}
+
+table.display tfoot th {
+ padding: 3px 18px 3px 10px;
+ border-top: 1px solid black;
+ font-weight: bold;
+}
+
+table.display tr.heading2 td {
+ border-bottom: 1px solid #aaa;
+}
+
+table.display td {
+ padding: 3px 10px;
+}
+
+table.display td.center {
+ text-align: center;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables sorting
+ */
+
+.sorting_asc {
+ background: url('../images/sort_asc.png') no-repeat center right;
+}
+
+.sorting_desc {
+ background: url('../images/sort_desc.png') no-repeat center right;
+}
+
+.sorting {
+ background: url('../images/sort_both.png') no-repeat center right;
+}
+
+.sorting_asc_disabled {
+ background: url('../images/sort_asc_disabled.png') no-repeat center right;
+}
+
+.sorting_desc_disabled {
+ background: url('../images/sort_desc_disabled.png') no-repeat center right;
+}
+
+th:active {
+ outline: none;
+}
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables row classes
+ */
+table.display tr.odd.gradeA {
+ background-color: #ddffdd;
+}
+
+table.display tr.even.gradeA {
+ background-color: #eeffee;
+}
+
+table.display tr.odd.gradeC {
+ background-color: #ddddff;
+}
+
+table.display tr.even.gradeC {
+ background-color: #eeeeff;
+}
+
+table.display tr.odd.gradeX {
+ background-color: #ffdddd;
+}
+
+table.display tr.even.gradeX {
+ background-color: #ffeeee;
+}
+
+table.display tr.odd.gradeU {
+ background-color: #ddd;
+}
+
+table.display tr.even.gradeU {
+ background-color: #eee;
+}
+
+
+tr.odd {
+ background-color: #E2E4FF;
+}
+
+tr.even {
+ background-color: white;
+}
+
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Misc
+ */
+.dataTables_scroll {
+ clear: both;
+}
+
+.dataTables_scrollBody {
+ *margin-top: -1px;
+ -webkit-overflow-scrolling: touch;
+}
+
+.top, .bottom {
+ padding: 15px;
+ background-color: #F5F5F5;
+ border: 1px solid #CCCCCC;
+}
+
+.top .dataTables_info {
+ float: none;
+}
+
+.clear {
+ clear: both;
+}
+
+.dataTables_empty {
+ text-align: center;
+}
+
+tfoot input {
+ margin: 0.5em 0;
+ width: 100%;
+ color: #444;
+}
+
+tfoot input.search_init {
+ color: #999;
+}
+
+td.group {
+ background-color: #d1cfd0;
+ border-bottom: 2px solid #A19B9E;
+ border-top: 2px solid #A19B9E;
+}
+
+td.details {
+ background-color: #d1cfd0;
+ border: 2px solid #A19B9E;
+}
+
+
+.example_alt_pagination div.dataTables_info {
+ width: 40%;
+}
+
+.paging_full_numbers {
+ width: 400px;
+ height: 22px;
+ line-height: 22px;
+}
+
+.paging_full_numbers a:active {
+ outline: none
+}
+
+.paging_full_numbers a:hover {
+ text-decoration: none;
+}
+
+.paging_full_numbers a.paginate_button,
+ .paging_full_numbers a.paginate_active {
+ border: 1px solid #aaa;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ padding: 2px 5px;
+ margin: 0 3px;
+ cursor: pointer;
+ *cursor: hand;
+ color: #333 !important;
+}
+
+.paging_full_numbers a.paginate_button {
+ background-color: #ddd;
+}
+
+.paging_full_numbers a.paginate_button:hover {
+ background-color: #ccc;
+ text-decoration: none !important;
+}
+
+.paging_full_numbers a.paginate_active {
+ background-color: #99B3FF;
+}
+
+table.display tr.even.row_selected td {
+ background-color: #B0BED9;
+}
+
+table.display tr.odd.row_selected td {
+ background-color: #9FAFD1;
+}
+
+
+/*
+ * Sorting classes for columns
+ */
+/* For the standard odd/even */
+tr.odd td.sorting_1 {
+ background-color: #D3D6FF;
+}
+
+tr.odd td.sorting_2 {
+ background-color: #DADCFF;
+}
+
+tr.odd td.sorting_3 {
+ background-color: #E0E2FF;
+}
+
+tr.even td.sorting_1 {
+ background-color: #EAEBFF;
+}
+
+tr.even td.sorting_2 {
+ background-color: #F2F3FF;
+}
+
+tr.even td.sorting_3 {
+ background-color: #F9F9FF;
+}
+
+
+/* For the Conditional-CSS grading rows */
+/*
+ Colour calculations (based off the main row colours)
+ Level 1:
+ dd > c4
+ ee > d5
+ Level 2:
+ dd > d1
+ ee > e2
+ */
+tr.odd.gradeA td.sorting_1 {
+ background-color: #c4ffc4;
+}
+
+tr.odd.gradeA td.sorting_2 {
+ background-color: #d1ffd1;
+}
+
+tr.odd.gradeA td.sorting_3 {
+ background-color: #d1ffd1;
+}
+
+tr.even.gradeA td.sorting_1 {
+ background-color: #d5ffd5;
+}
+
+tr.even.gradeA td.sorting_2 {
+ background-color: #e2ffe2;
+}
+
+tr.even.gradeA td.sorting_3 {
+ background-color: #e2ffe2;
+}
+
+tr.odd.gradeC td.sorting_1 {
+ background-color: #c4c4ff;
+}
+
+tr.odd.gradeC td.sorting_2 {
+ background-color: #d1d1ff;
+}
+
+tr.odd.gradeC td.sorting_3 {
+ background-color: #d1d1ff;
+}
+
+tr.even.gradeC td.sorting_1 {
+ background-color: #d5d5ff;
+}
+
+tr.even.gradeC td.sorting_2 {
+ background-color: #e2e2ff;
+}
+
+tr.even.gradeC td.sorting_3 {
+ background-color: #e2e2ff;
+}
+
+tr.odd.gradeX td.sorting_1 {
+ background-color: #ffc4c4;
+}
+
+tr.odd.gradeX td.sorting_2 {
+ background-color: #ffd1d1;
+}
+
+tr.odd.gradeX td.sorting_3 {
+ background-color: #ffd1d1;
+}
+
+tr.even.gradeX td.sorting_1 {
+ background-color: #ffd5d5;
+}
+
+tr.even.gradeX td.sorting_2 {
+ background-color: #ffe2e2;
+}
+
+tr.even.gradeX td.sorting_3 {
+ background-color: #ffe2e2;
+}
+
+tr.odd.gradeU td.sorting_1 {
+ background-color: #c4c4c4;
+}
+
+tr.odd.gradeU td.sorting_2 {
+ background-color: #d1d1d1;
+}
+
+tr.odd.gradeU td.sorting_3 {
+ background-color: #d1d1d1;
+}
+
+tr.even.gradeU td.sorting_1 {
+ background-color: #d5d5d5;
+}
+
+tr.even.gradeU td.sorting_2 {
+ background-color: #e2e2e2;
+}
+
+tr.even.gradeU td.sorting_3 {
+ background-color: #e2e2e2;
+}
+
+
+/*
+ * Row highlighting example
+ */
+.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
+ background-color: #ECFFB3;
+}
+
+.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted {
+ background-color: #E6FF99;
+}
+
+.ex_highlight_row #example tr.even:hover {
+ background-color: #ECFFB3;
+}
+
+.ex_highlight_row #example tr.even:hover td.sorting_1 {
+ background-color: #DDFF75;
+}
+
+.ex_highlight_row #example tr.even:hover td.sorting_2 {
+ background-color: #E7FF9E;
+}
+
+.ex_highlight_row #example tr.even:hover td.sorting_3 {
+ background-color: #E2FF89;
+}
+
+.ex_highlight_row #example tr.odd:hover {
+ background-color: #E6FF99;
+}
+
+.ex_highlight_row #example tr.odd:hover td.sorting_1 {
+ background-color: #D6FF5C;
+}
+
+.ex_highlight_row #example tr.odd:hover td.sorting_2 {
+ background-color: #E0FF84;
+}
+
+.ex_highlight_row #example tr.odd:hover td.sorting_3 {
+ background-color: #DBFF70;
+}
+
+
+/*
+ * KeyTable
+ */
+table.KeyTable td {
+ border: 3px solid transparent;
+}
+
+table.KeyTable td.focus {
+ border: 3px solid #3366FF;
+}
+
+table.display tr.gradeA {
+ background-color: #eeffee;
+}
+
+table.display tr.gradeC {
+ background-color: #ddddff;
+}
+
+table.display tr.gradeX {
+ background-color: #ffdddd;
+}
+
+table.display tr.gradeU {
+ background-color: #ddd;
+}
+
+div.box {
+ height: 100px;
+ padding: 10px;
+ overflow: auto;
+ border: 1px solid #8080FF;
+ background-color: #E5E5FF;
+}
diff --git a/wqflask/wqflask/static/new/packages/DataTables/css/demo_table_jui.css b/wqflask/wqflask/static/new/packages/DataTables/css/demo_table_jui.css
new file mode 100644
index 00000000..de7c8426
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/css/demo_table_jui.css
@@ -0,0 +1,526 @@
+/*
+ * File: demo_table_jui.css
+ * CVS: $Id$
+ * Description: CSS descriptions for DataTables demo pages
+ * Author: Allan Jardine
+ * Created: Tue May 12 06:47:22 BST 2009
+ * Modified: $Date$ by $Author$
+ * Language: CSS
+ * Project: DataTables
+ *
+ * Copyright 2009 Allan Jardine. All Rights Reserved.
+ *
+ * ***************************************************************************
+ * DESCRIPTION
+ *
+ * The styles given here are suitable for the demos that are used with the standard DataTables
+ * distribution (see www.datatables.net). You will most likely wish to modify these styles to
+ * meet the layout requirements of your site.
+ *
+ * Common issues:
+ * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is
+ * no conflict between the two pagination types. If you want to use full_numbers pagination
+ * ensure that you either have "example_alt_pagination" as a body class name, or better yet,
+ * modify that selector.
+ * Note that the path used for Images is relative. All images are by default located in
+ * ../images/ - relative to this CSS file.
+ */
+
+
+/*
+ * jQuery UI specific styling
+ */
+
+.paging_two_button .ui-button {
+ float: left;
+ cursor: pointer;
+ * cursor: hand;
+}
+
+.paging_full_numbers .ui-button {
+ padding: 2px 6px;
+ margin: 0;
+ cursor: pointer;
+ * cursor: hand;
+ color: #333 !important;
+}
+
+.dataTables_paginate .ui-button {
+ margin-right: -0.1em !important;
+}
+
+.paging_full_numbers {
+ width: 350px !important;
+}
+
+.dataTables_wrapper .ui-toolbar {
+ padding: 5px;
+}
+
+.dataTables_paginate {
+ width: auto;
+}
+
+.dataTables_info {
+ padding-top: 3px;
+}
+
+table.display thead th {
+ padding: 3px 0px 3px 10px;
+ cursor: pointer;
+ * cursor: hand;
+}
+
+div.dataTables_wrapper .ui-widget-header {
+ font-weight: normal;
+}
+
+
+/*
+ * Sort arrow icon positioning
+ */
+table.display thead th div.DataTables_sort_wrapper {
+ position: relative;
+ padding-right: 20px;
+ padding-right: 20px;
+}
+
+table.display thead th div.DataTables_sort_wrapper span {
+ position: absolute;
+ top: 50%;
+ margin-top: -8px;
+ right: 0;
+}
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Everything below this line is the same as demo_table.css. This file is
+ * required for 'cleanliness' of the markup
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables features
+ */
+
+.dataTables_wrapper {
+ position: relative;
+ clear: both;
+}
+
+.dataTables_processing {
+ position: absolute;
+ top: 0px;
+ left: 50%;
+ width: 250px;
+ margin-left: -125px;
+ border: 1px solid #ddd;
+ text-align: center;
+ color: #999;
+ font-size: 11px;
+ padding: 2px 0;
+}
+
+.dataTables_length {
+ width: 40%;
+ float: left;
+}
+
+.dataTables_filter {
+ width: 50%;
+ float: right;
+ text-align: right;
+}
+
+.dataTables_info {
+ width: 50%;
+ float: left;
+}
+
+.dataTables_paginate {
+ float: right;
+ text-align: right;
+}
+
+/* Pagination nested */
+.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
+ height: 19px;
+ width: 19px;
+ margin-left: 3px;
+ float: left;
+}
+
+.paginate_disabled_previous {
+ background-image: url('../images/back_disabled.jpg');
+}
+
+.paginate_enabled_previous {
+ background-image: url('../images/back_enabled.jpg');
+}
+
+.paginate_disabled_next {
+ background-image: url('../images/forward_disabled.jpg');
+}
+
+.paginate_enabled_next {
+ background-image: url('../images/forward_enabled.jpg');
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables display
+ */
+table.display {
+ margin: 0 auto;
+ width: 100%;
+ clear: both;
+ border-collapse: collapse;
+}
+
+table.display tfoot th {
+ padding: 3px 0px 3px 10px;
+ font-weight: bold;
+ font-weight: normal;
+}
+
+table.display tr.heading2 td {
+ border-bottom: 1px solid #aaa;
+}
+
+table.display td {
+ padding: 3px 10px;
+}
+
+table.display td.center {
+ text-align: center;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables sorting
+ */
+
+.sorting_asc {
+ background: url('../images/sort_asc.png') no-repeat center right;
+}
+
+.sorting_desc {
+ background: url('../images/sort_desc.png') no-repeat center right;
+}
+
+.sorting {
+ background: url('../images/sort_both.png') no-repeat center right;
+}
+
+.sorting_asc_disabled {
+ background: url('../images/sort_asc_disabled.png') no-repeat center right;
+}
+
+.sorting_desc_disabled {
+ background: url('../images/sort_desc_disabled.png') no-repeat center right;
+}
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables row classes
+ */
+table.display tr.odd.gradeA {
+ background-color: #ddffdd;
+}
+
+table.display tr.even.gradeA {
+ background-color: #eeffee;
+}
+
+
+
+
+table.display tr.odd.gradeA {
+ background-color: #ddffdd;
+}
+
+table.display tr.even.gradeA {
+ background-color: #eeffee;
+}
+
+table.display tr.odd.gradeC {
+ background-color: #ddddff;
+}
+
+table.display tr.even.gradeC {
+ background-color: #eeeeff;
+}
+
+table.display tr.odd.gradeX {
+ background-color: #ffdddd;
+}
+
+table.display tr.even.gradeX {
+ background-color: #ffeeee;
+}
+
+table.display tr.odd.gradeU {
+ background-color: #ddd;
+}
+
+table.display tr.even.gradeU {
+ background-color: #eee;
+}
+
+
+tr.odd {
+ background-color: #E2E4FF;
+}
+
+tr.even {
+ background-color: white;
+}
+
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Misc
+ */
+.dataTables_scroll {
+ clear: both;
+}
+
+.dataTables_scrollBody {
+ -webkit-overflow-scrolling: touch;
+}
+
+.top, .bottom {
+ padding: 15px;
+ background-color: #F5F5F5;
+ border: 1px solid #CCCCCC;
+}
+
+.top .dataTables_info {
+ float: none;
+}
+
+.clear {
+ clear: both;
+}
+
+.dataTables_empty {
+ text-align: center;
+}
+
+tfoot input {
+ margin: 0.5em 0;
+ width: 100%;
+ color: #444;
+}
+
+tfoot input.search_init {
+ color: #999;
+}
+
+td.group {
+ background-color: #d1cfd0;
+ border-bottom: 2px solid #A19B9E;
+ border-top: 2px solid #A19B9E;
+}
+
+td.details {
+ background-color: #d1cfd0;
+ border: 2px solid #A19B9E;
+}
+
+
+.example_alt_pagination div.dataTables_info {
+ width: 40%;
+}
+
+.paging_full_numbers a.paginate_button,
+ .paging_full_numbers a.paginate_active {
+ border: 1px solid #aaa;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ padding: 2px 5px;
+ margin: 0 3px;
+ cursor: pointer;
+ *cursor: hand;
+ color: #333 !important;
+}
+
+.paging_full_numbers a.paginate_button {
+ background-color: #ddd;
+}
+
+.paging_full_numbers a.paginate_button:hover {
+ background-color: #ccc;
+ text-decoration: none !important;
+}
+
+.paging_full_numbers a.paginate_active {
+ background-color: #99B3FF;
+}
+
+table.display tr.even.row_selected td {
+ background-color: #B0BED9;
+}
+
+table.display tr.odd.row_selected td {
+ background-color: #9FAFD1;
+}
+
+
+/*
+ * Sorting classes for columns
+ */
+/* For the standard odd/even */
+tr.odd td.sorting_1 {
+ background-color: #D3D6FF;
+}
+
+tr.odd td.sorting_2 {
+ background-color: #DADCFF;
+}
+
+tr.odd td.sorting_3 {
+ background-color: #E0E2FF;
+}
+
+tr.even td.sorting_1 {
+ background-color: #EAEBFF;
+}
+
+tr.even td.sorting_2 {
+ background-color: #F2F3FF;
+}
+
+tr.even td.sorting_3 {
+ background-color: #F9F9FF;
+}
+
+
+/* For the Conditional-CSS grading rows */
+/*
+ Colour calculations (based off the main row colours)
+ Level 1:
+ dd > c4
+ ee > d5
+ Level 2:
+ dd > d1
+ ee > e2
+ */
+tr.odd.gradeA td.sorting_1 {
+ background-color: #c4ffc4;
+}
+
+tr.odd.gradeA td.sorting_2 {
+ background-color: #d1ffd1;
+}
+
+tr.odd.gradeA td.sorting_3 {
+ background-color: #d1ffd1;
+}
+
+tr.even.gradeA td.sorting_1 {
+ background-color: #d5ffd5;
+}
+
+tr.even.gradeA td.sorting_2 {
+ background-color: #e2ffe2;
+}
+
+tr.even.gradeA td.sorting_3 {
+ background-color: #e2ffe2;
+}
+
+tr.odd.gradeC td.sorting_1 {
+ background-color: #c4c4ff;
+}
+
+tr.odd.gradeC td.sorting_2 {
+ background-color: #d1d1ff;
+}
+
+tr.odd.gradeC td.sorting_3 {
+ background-color: #d1d1ff;
+}
+
+tr.even.gradeC td.sorting_1 {
+ background-color: #d5d5ff;
+}
+
+tr.even.gradeC td.sorting_2 {
+ background-color: #e2e2ff;
+}
+
+tr.even.gradeC td.sorting_3 {
+ background-color: #e2e2ff;
+}
+
+tr.odd.gradeX td.sorting_1 {
+ background-color: #ffc4c4;
+}
+
+tr.odd.gradeX td.sorting_2 {
+ background-color: #ffd1d1;
+}
+
+tr.odd.gradeX td.sorting_3 {
+ background-color: #ffd1d1;
+}
+
+tr.even.gradeX td.sorting_1 {
+ background-color: #ffd5d5;
+}
+
+tr.even.gradeX td.sorting_2 {
+ background-color: #ffe2e2;
+}
+
+tr.even.gradeX td.sorting_3 {
+ background-color: #ffe2e2;
+}
+
+tr.odd.gradeU td.sorting_1 {
+ background-color: #c4c4c4;
+}
+
+tr.odd.gradeU td.sorting_2 {
+ background-color: #d1d1d1;
+}
+
+tr.odd.gradeU td.sorting_3 {
+ background-color: #d1d1d1;
+}
+
+tr.even.gradeU td.sorting_1 {
+ background-color: #d5d5d5;
+}
+
+tr.even.gradeU td.sorting_2 {
+ background-color: #e2e2e2;
+}
+
+tr.even.gradeU td.sorting_3 {
+ background-color: #e2e2e2;
+}
+
+
+/*
+ * Row highlighting example
+ */
+.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
+ background-color: #ECFFB3;
+}
+
+.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted {
+ background-color: #E6FF99;
+}
\ No newline at end of file
diff --git a/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css
new file mode 100644
index 00000000..83df98ea
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css
@@ -0,0 +1,220 @@
+
+/*
+ * Table
+ */
+table.dataTable {
+ margin: 0 auto;
+ clear: both;
+ width: 100%;
+}
+
+table.dataTable thead th {
+ padding: 3px 18px 3px 10px;
+ border-bottom: 1px solid black;
+ font-weight: bold;
+ cursor: pointer;
+ *cursor: hand;
+}
+
+table.dataTable tfoot th {
+ padding: 3px 18px 3px 10px;
+ border-top: 1px solid black;
+ font-weight: bold;
+}
+
+table.dataTable td {
+ padding: 3px 10px;
+}
+
+table.dataTable td.center,
+table.dataTable td.dataTables_empty {
+ text-align: center;
+}
+
+table.dataTable tr.odd { background-color: #E2E4FF; }
+table.dataTable tr.even { background-color: white; }
+
+table.dataTable tr.odd td.sorting_1 { background-color: #D3D6FF; }
+table.dataTable tr.odd td.sorting_2 { background-color: #DADCFF; }
+table.dataTable tr.odd td.sorting_3 { background-color: #E0E2FF; }
+table.dataTable tr.even td.sorting_1 { background-color: #EAEBFF; }
+table.dataTable tr.even td.sorting_2 { background-color: #F2F3FF; }
+table.dataTable tr.even td.sorting_3 { background-color: #F9F9FF; }
+
+
+/*
+ * Table wrapper
+ */
+.dataTables_wrapper {
+ position: relative;
+ clear: both;
+ *zoom: 1;
+}
+
+
+/*
+ * Page length menu
+ */
+.dataTables_length {
+ float: left;
+}
+
+
+/*
+ * Filter
+ */
+.dataTables_filter {
+ float: right;
+ text-align: right;
+}
+
+
+/*
+ * Table information
+ */
+.dataTables_info {
+ clear: both;
+ float: left;
+}
+
+
+/*
+ * Pagination
+ */
+.dataTables_paginate {
+ float: right;
+ text-align: right;
+}
+
+/* Two button pagination - previous / next */
+.paginate_disabled_previous,
+.paginate_enabled_previous,
+.paginate_disabled_next,
+.paginate_enabled_next {
+ height: 19px;
+ float: left;
+ cursor: pointer;
+ *cursor: hand;
+ color: #111 !important;
+}
+.paginate_disabled_previous:hover,
+.paginate_enabled_previous:hover,
+.paginate_disabled_next:hover,
+.paginate_enabled_next:hover {
+ text-decoration: none !important;
+}
+.paginate_disabled_previous:active,
+.paginate_enabled_previous:active,
+.paginate_disabled_next:active,
+.paginate_enabled_next:active {
+ outline: none;
+}
+
+.paginate_disabled_previous,
+.paginate_disabled_next {
+ color: #666 !important;
+}
+.paginate_disabled_previous,
+.paginate_enabled_previous {
+ padding-left: 23px;
+}
+.paginate_disabled_next,
+.paginate_enabled_next {
+ padding-right: 23px;
+ margin-left: 10px;
+}
+
+.paginate_enabled_previous { background: url('../images/back_enabled.png') no-repeat top left; }
+.paginate_enabled_previous:hover { background: url('../images/back_enabled_hover.png') no-repeat top left; }
+.paginate_disabled_previous { background: url('../images/back_disabled.png') no-repeat top left; }
+
+.paginate_enabled_next { background: url('../images/forward_enabled.png') no-repeat top right; }
+.paginate_enabled_next:hover { background: url('../images/forward_enabled_hover.png') no-repeat top right; }
+.paginate_disabled_next { background: url('../images/forward_disabled.png') no-repeat top right; }
+
+/* Full number pagination */
+.paging_full_numbers {
+ height: 22px;
+ line-height: 22px;
+}
+.paging_full_numbers a:active {
+ outline: none
+}
+.paging_full_numbers a:hover {
+ text-decoration: none;
+}
+
+.paging_full_numbers a.paginate_button,
+.paging_full_numbers a.paginate_active {
+ border: 1px solid #aaa;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+ padding: 2px 5px;
+ margin: 0 3px;
+ cursor: pointer;
+ *cursor: hand;
+ color: #333 !important;
+}
+
+.paging_full_numbers a.paginate_button {
+ background-color: #ddd;
+}
+
+.paging_full_numbers a.paginate_button:hover {
+ background-color: #ccc;
+ text-decoration: none !important;
+}
+
+.paging_full_numbers a.paginate_active {
+ background-color: #99B3FF;
+}
+
+
+/*
+ * Processing indicator
+ */
+.dataTables_processing {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 250px;
+ height: 30px;
+ margin-left: -125px;
+ margin-top: -15px;
+ padding: 14px 0 2px 0;
+ border: 1px solid #ddd;
+ text-align: center;
+ color: #999;
+ font-size: 14px;
+ background-color: white;
+}
+
+
+/*
+ * Sorting
+ */
+.sorting { background: url('../images/sort_both.png') no-repeat center right; }
+.sorting_asc { background: url('../images/sort_asc.png') no-repeat center right; }
+.sorting_desc { background: url('../images/sort_desc.png') no-repeat center right; }
+
+.sorting_asc_disabled { background: url('../images/sort_asc_disabled.png') no-repeat center right; }
+.sorting_desc_disabled { background: url('../images/sort_desc_disabled.png') no-repeat center right; }
+
+table.dataTable th:active {
+ outline: none;
+}
+
+
+/*
+ * Scrolling
+ */
+.dataTables_scroll {
+ clear: both;
+}
+
+.dataTables_scrollBody {
+ *margin-top: -1px;
+ -webkit-overflow-scrolling: touch;
+}
+
diff --git a/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables_themeroller.css b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables_themeroller.css
new file mode 100644
index 00000000..55661c6d
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables_themeroller.css
@@ -0,0 +1,245 @@
+
+
+/*
+ * Table
+ */
+table.dataTable {
+ margin: 0 auto;
+ clear: both;
+ width: 100%;
+ border-collapse: collapse;
+}
+
+table.dataTable thead th {
+ padding: 3px 0px 3px 10px;
+ cursor: pointer;
+ *cursor: hand;
+}
+
+table.dataTable tfoot th {
+ padding: 3px 10px;
+}
+
+table.dataTable td {
+ padding: 3px 10px;
+}
+
+table.dataTable td.center,
+table.dataTable td.dataTables_empty {
+ text-align: center;
+}
+
+table.dataTable tr.odd { background-color: #E2E4FF; }
+table.dataTable tr.even { background-color: white; }
+
+table.dataTable tr.odd td.sorting_1 { background-color: #D3D6FF; }
+table.dataTable tr.odd td.sorting_2 { background-color: #DADCFF; }
+table.dataTable tr.odd td.sorting_3 { background-color: #E0E2FF; }
+table.dataTable tr.even td.sorting_1 { background-color: #EAEBFF; }
+table.dataTable tr.even td.sorting_2 { background-color: #F2F3FF; }
+table.dataTable tr.even td.sorting_3 { background-color: #F9F9FF; }
+
+
+/*
+ * Table wrapper
+ */
+.dataTables_wrapper {
+ position: relative;
+ clear: both;
+ *zoom: 1;
+}
+.dataTables_wrapper .ui-widget-header {
+ font-weight: normal;
+}
+.dataTables_wrapper .ui-toolbar {
+ padding: 5px;
+}
+
+
+/*
+ * Page length menu
+ */
+.dataTables_length {
+ float: left;
+}
+
+
+/*
+ * Filter
+ */
+.dataTables_filter {
+ float: right;
+ text-align: right;
+}
+
+
+/*
+ * Table information
+ */
+.dataTables_info {
+ padding-top: 3px;
+ clear: both;
+ float: left;
+}
+
+
+/*
+ * Pagination
+ */
+.dataTables_paginate {
+ float: right;
+ text-align: right;
+}
+
+.dataTables_paginate .ui-button {
+ margin-right: -0.1em !important;
+}
+
+.paging_two_button .ui-button {
+ float: left;
+ cursor: pointer;
+ * cursor: hand;
+}
+
+.paging_full_numbers .ui-button {
+ padding: 2px 6px;
+ margin: 0;
+ cursor: pointer;
+ * cursor: hand;
+ color: #333 !important;
+}
+
+/* Two button pagination - previous / next */
+.paginate_disabled_previous,
+.paginate_enabled_previous,
+.paginate_disabled_next,
+.paginate_enabled_next {
+ height: 19px;
+ float: left;
+ cursor: pointer;
+ *cursor: hand;
+ color: #111 !important;
+}
+.paginate_disabled_previous:hover,
+.paginate_enabled_previous:hover,
+.paginate_disabled_next:hover,
+.paginate_enabled_next:hover {
+ text-decoration: none !important;
+}
+.paginate_disabled_previous:active,
+.paginate_enabled_previous:active,
+.paginate_disabled_next:active,
+.paginate_enabled_next:active {
+ outline: none;
+}
+
+.paginate_disabled_previous,
+.paginate_disabled_next {
+ color: #666 !important;
+}
+.paginate_disabled_previous,
+.paginate_enabled_previous {
+ padding-left: 23px;
+}
+.paginate_disabled_next,
+.paginate_enabled_next {
+ padding-right: 23px;
+ margin-left: 10px;
+}
+
+.paginate_enabled_previous { background: url('../images/back_enabled.png') no-repeat top left; }
+.paginate_enabled_previous:hover { background: url('../images/back_enabled_hover.png') no-repeat top left; }
+.paginate_disabled_previous { background: url('../images/back_disabled.png') no-repeat top left; }
+
+.paginate_enabled_next { background: url('../images/forward_enabled.png') no-repeat top right; }
+.paginate_enabled_next:hover { background: url('../images/forward_enabled_hover.png') no-repeat top right; }
+.paginate_disabled_next { background: url('../images/forward_disabled.png') no-repeat top right; }
+
+/* Full number pagination */
+.paging_full_numbers a:active {
+ outline: none
+}
+.paging_full_numbers a:hover {
+ text-decoration: none;
+}
+
+.paging_full_numbers a.paginate_button,
+.paging_full_numbers a.paginate_active {
+ border: 1px solid #aaa;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+ padding: 2px 5px;
+ margin: 0 3px;
+ cursor: pointer;
+ *cursor: hand;
+ color: #333 !important;
+}
+
+.paging_full_numbers a.paginate_button {
+ background-color: #ddd;
+}
+
+.paging_full_numbers a.paginate_button:hover {
+ background-color: #ccc;
+ text-decoration: none !important;
+}
+
+.paging_full_numbers a.paginate_active {
+ background-color: #99B3FF;
+}
+
+
+/*
+ * Processing indicator
+ */
+.dataTables_processing {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 250px;
+ height: 30px;
+ margin-left: -125px;
+ margin-top: -15px;
+ padding: 14px 0 2px 0;
+ border: 1px solid #ddd;
+ text-align: center;
+ color: #999;
+ font-size: 14px;
+ background-color: white;
+}
+
+
+/*
+ * Sorting
+ */
+table.dataTable thead th div.DataTables_sort_wrapper {
+ position: relative;
+ padding-right: 20px;
+ padding-right: 20px;
+}
+
+table.dataTable thead th div.DataTables_sort_wrapper span {
+ position: absolute;
+ top: 50%;
+ margin-top: -8px;
+ right: 0;
+}
+
+table.dataTable th:active {
+ outline: none;
+}
+
+
+/*
+ * Scrolling
+ */
+.dataTables_scroll {
+ clear: both;
+}
+
+.dataTables_scrollBody {
+ *margin-top: -1px;
+ -webkit-overflow-scrolling: touch;
+}
+
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/Sorting icons.psd b/wqflask/wqflask/static/new/packages/DataTables/images/Sorting icons.psd
new file mode 100644
index 00000000..53b2e068
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/Sorting icons.psd differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/back_disabled.png b/wqflask/wqflask/static/new/packages/DataTables/images/back_disabled.png
new file mode 100644
index 00000000..881de797
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/back_disabled.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/back_enabled.png b/wqflask/wqflask/static/new/packages/DataTables/images/back_enabled.png
new file mode 100644
index 00000000..c608682b
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/back_enabled.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/back_enabled_hover.png b/wqflask/wqflask/static/new/packages/DataTables/images/back_enabled_hover.png
new file mode 100644
index 00000000..d300f106
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/back_enabled_hover.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/favicon.ico b/wqflask/wqflask/static/new/packages/DataTables/images/favicon.ico
new file mode 100644
index 00000000..6eeaa2a0
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/favicon.ico differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/forward_disabled.png b/wqflask/wqflask/static/new/packages/DataTables/images/forward_disabled.png
new file mode 100644
index 00000000..6a6ded7d
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/forward_disabled.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled.png b/wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled.png
new file mode 100644
index 00000000..a4e6b538
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled_hover.png b/wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled_hover.png
new file mode 100644
index 00000000..fc46c5eb
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/forward_enabled_hover.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/sort_asc.png b/wqflask/wqflask/static/new/packages/DataTables/images/sort_asc.png
new file mode 100644
index 00000000..a88d7975
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/sort_asc.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/sort_asc_disabled.png b/wqflask/wqflask/static/new/packages/DataTables/images/sort_asc_disabled.png
new file mode 100644
index 00000000..4e144cf0
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/sort_asc_disabled.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/sort_both.png b/wqflask/wqflask/static/new/packages/DataTables/images/sort_both.png
new file mode 100644
index 00000000..18670406
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/sort_both.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/sort_desc.png b/wqflask/wqflask/static/new/packages/DataTables/images/sort_desc.png
new file mode 100644
index 00000000..def071ed
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/sort_desc.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/images/sort_desc_disabled.png b/wqflask/wqflask/static/new/packages/DataTables/images/sort_desc_disabled.png
new file mode 100644
index 00000000..7824973c
Binary files /dev/null and b/wqflask/wqflask/static/new/packages/DataTables/images/sort_desc_disabled.png differ
diff --git a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js
new file mode 100644
index 00000000..ae5d1750
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js
@@ -0,0 +1,11863 @@
+/**
+ * @summary DataTables
+ * @description Paginate, search and sort HTML tables
+ * @version 1.9.2
+ * @file jquery.dataTables.js
+ * @author Allan Jardine (www.sprymedia.co.uk)
+ * @contact www.sprymedia.co.uk/contact
+ *
+ * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved.
+ *
+ * This source file is free software, under either the GPL v2 license or a
+ * BSD style license, available at:
+ * http://datatables.net/license_gpl2
+ * http://datatables.net/license_bsd
+ *
+ * This source file 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 license files for details.
+ *
+ * For details please refer to: http://www.datatables.net
+ */
+
+/*jslint evil: true, undef: true, browser: true */
+/*globals $, jQuery,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros*/
+
+(/** @lends */function($, window, document, undefined) {
+ /**
+ * DataTables is a plug-in for the jQuery Javascript library. It is a
+ * highly flexible tool, based upon the foundations of progressive
+ * enhancement, which will add advanced interaction controls to any
+ * HTML table. For a full list of features please refer to
+ * DataTables.net.
+ *
+ * Note that the DataTable object is not a global variable but is
+ * aliased to jQuery.fn.DataTable and jQuery.fn.dataTable through which
+ * it may be accessed.
+ *
+ * @class
+ * @param {object} [oInit={}] Configuration object for DataTables. Options
+ * are defined by {@link DataTable.defaults}
+ * @requires jQuery 1.3+
+ *
+ * @example
+ * // Basic initialisation
+ * $(document).ready( function {
+ * $('#example').dataTable();
+ * } );
+ *
+ * @example
+ * // Initialisation with configuration options - in this case, disable
+ * // pagination and sorting.
+ * $(document).ready( function {
+ * $('#example').dataTable( {
+ * "bPaginate": false,
+ * "bSort": false
+ * } );
+ * } );
+ */
+ var DataTable = function( oInit )
+ {
+
+
+ /**
+ * Add a column to the list used for the table with default values
+ * @param {object} oSettings dataTables settings object
+ * @param {node} nTh The th element for this column
+ * @memberof DataTable#oApi
+ */
+ function _fnAddColumn( oSettings, nTh )
+ {
+ var oDefaults = DataTable.defaults.columns;
+ var iCol = oSettings.aoColumns.length;
+ var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
+ "sSortingClass": oSettings.oClasses.sSortable,
+ "sSortingClassJUI": oSettings.oClasses.sSortJUI,
+ "nTh": nTh ? nTh : document.createElement('th'),
+ "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
+ "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
+ "mDataProp": oDefaults.mDataProp ? oDefaults.oDefaults : iCol
+ } );
+ oSettings.aoColumns.push( oCol );
+
+ /* Add a column specific filter */
+ if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )
+ {
+ oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch );
+ }
+ else
+ {
+ var oPre = oSettings.aoPreSearchCols[ iCol ];
+
+ /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
+ if ( oPre.bRegex === undefined )
+ {
+ oPre.bRegex = true;
+ }
+
+ if ( oPre.bSmart === undefined )
+ {
+ oPre.bSmart = true;
+ }
+
+ if ( oPre.bCaseInsensitive === undefined )
+ {
+ oPre.bCaseInsensitive = true;
+ }
+ }
+
+ /* Use the column options function to initialise classes etc */
+ _fnColumnOptions( oSettings, iCol, null );
+ }
+
+
+ /**
+ * Apply options for a column
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iCol column index to consider
+ * @param {object} oOptions object with sType, bVisible and bSearchable
+ * @memberof DataTable#oApi
+ */
+ function _fnColumnOptions( oSettings, iCol, oOptions )
+ {
+ var oCol = oSettings.aoColumns[ iCol ];
+
+ /* User specified column options */
+ if ( oOptions !== undefined && oOptions !== null )
+ {
+ if ( oOptions.sType !== undefined )
+ {
+ oCol.sType = oOptions.sType;
+ oCol._bAutoType = false;
+ }
+
+ $.extend( oCol, oOptions );
+ _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
+
+ /* iDataSort to be applied (backwards compatibility), but aDataSort will take
+ * priority if defined
+ */
+ if ( oOptions.iDataSort !== undefined )
+ {
+ oCol.aDataSort = [ oOptions.iDataSort ];
+ }
+ _fnMap( oCol, oOptions, "aDataSort" );
+ }
+
+ /* Cache the data get and set functions for speed */
+ oCol.fnGetData = _fnGetObjectDataFn( oCol.mDataProp );
+ oCol.fnSetData = _fnSetObjectDataFn( oCol.mDataProp );
+
+ /* Feature sorting overrides column specific when off */
+ if ( !oSettings.oFeatures.bSort )
+ {
+ oCol.bSortable = false;
+ }
+
+ /* Check that the class assignment is correct for sorting */
+ if ( !oCol.bSortable ||
+ ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
+ {
+ oCol.sSortingClass = oSettings.oClasses.sSortableNone;
+ oCol.sSortingClassJUI = "";
+ }
+ else if ( oCol.bSortable ||
+ ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
+ {
+ oCol.sSortingClass = oSettings.oClasses.sSortable;
+ oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
+ }
+ else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
+ {
+ oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
+ oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
+ }
+ else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
+ {
+ oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
+ oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
+ }
+ }
+
+
+ /**
+ * Adjust the table column widths for new data. Note: you would probably want to
+ * do a redraw after calling this function!
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnAdjustColumnSizing ( oSettings )
+ {
+ /* Not interested in doing column width calculation if autowidth is disabled */
+ if ( oSettings.oFeatures.bAutoWidth === false )
+ {
+ return false;
+ }
+
+ _fnCalculateColumnWidths( oSettings );
+ for ( var i=0 , iLen=oSettings.aoColumns.length ; i=0 ; i-- )
+ {
+ /* Each definition can target multiple columns, as it is an array */
+ var aTargets = aoColDefs[i].aTargets;
+ if ( !$.isArray( aTargets ) )
+ {
+ _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
+ }
+
+ for ( j=0, jLen=aTargets.length ; j= 0 )
+ {
+ /* Add columns that we don't yet know about */
+ while( oSettings.aoColumns.length <= aTargets[j] )
+ {
+ _fnAddColumn( oSettings );
+ }
+
+ /* Integer, basic index */
+ fn( aTargets[j], aoColDefs[i] );
+ }
+ else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
+ {
+ /* Negative integer, right to left column counting */
+ fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] );
+ }
+ else if ( typeof aTargets[j] === 'string' )
+ {
+ /* Class name matching on TH element */
+ for ( k=0, kLen=oSettings.aoColumns.length ; k=0 if successful (index of new aoData entry), -1 if failed
+ * @memberof DataTable#oApi
+ */
+ function _fnAddData ( oSettings, aDataSupplied )
+ {
+ var oCol;
+
+ /* Take an independent copy of the data source so we can bash it about as we wish */
+ var aDataIn = ($.isArray(aDataSupplied)) ?
+ aDataSupplied.slice() :
+ $.extend( true, {}, aDataSupplied );
+
+ /* Create the object for storing information about this new row */
+ var iRow = oSettings.aoData.length;
+ var oData = $.extend( true, {}, DataTable.models.oRow );
+ oData._aData = aDataIn;
+ oSettings.aoData.push( oData );
+
+ /* Create the cells */
+ var nTd, sThisType;
+ for ( var i=0, iLen=oSettings.aoColumns.length ; i iTarget )
+ {
+ a[i]--;
+ }
+ }
+
+ if ( iTargetIndex != -1 )
+ {
+ a.splice( iTargetIndex, 1 );
+ }
+ }
+
+
+ /**
+ * Call the developer defined fnRender function for a given cell (row/column) with
+ * the required parameters and return the result.
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iRow aoData index for the row
+ * @param {int} iCol aoColumns index for the column
+ * @returns {*} Return of the developer's fnRender function
+ * @memberof DataTable#oApi
+ */
+ function _fnRender( oSettings, iRow, iCol )
+ {
+ var oCol = oSettings.aoColumns[iCol];
+
+ return oCol.fnRender( {
+ "iDataRow": iRow,
+ "iDataColumn": iCol,
+ "oSettings": oSettings,
+ "aData": oSettings.aoData[iRow]._aData,
+ "mDataProp": oCol.mDataProp
+ }, _fnGetCellData(oSettings, iRow, iCol, 'display') );
+ }
+
+ /**
+ * Create a new TR element (and it's TD children) for a row
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iRow Row to consider
+ * @memberof DataTable#oApi
+ */
+ function _fnCreateTr ( oSettings, iRow )
+ {
+ var oData = oSettings.aoData[iRow];
+ var nTd;
+
+ if ( oData.nTr === null )
+ {
+ oData.nTr = document.createElement('tr');
+
+ /* Use a private property on the node to allow reserve mapping from the node
+ * to the aoData array for fast look up
+ */
+ oData.nTr._DT_RowIndex = iRow;
+
+ /* Special parameters can be given by the data source to be used on the row */
+ if ( oData._aData.DT_RowId )
+ {
+ oData.nTr.id = oData._aData.DT_RowId;
+ }
+
+ if ( oData._aData.DT_RowClass )
+ {
+ $(oData.nTr).addClass( oData._aData.DT_RowClass );
+ }
+
+ /* Process each column */
+ for ( var i=0, iLen=oSettings.aoColumns.length ; i=0 ; j-- )
+ {
+ if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
+ {
+ aoLocal[i].splice( j, 1 );
+ }
+ }
+
+ /* Prep the applied array - it needs an element for each row */
+ aApplied.push( [] );
+ }
+
+ for ( i=0, iLen=aoLocal.length ; i= oSettings.fnRecordsDisplay()) ?
+ 0 : oSettings.iInitDisplayStart;
+ }
+ oSettings.iInitDisplayStart = -1;
+ _fnCalculateEnd( oSettings );
+ }
+
+ /* Server-side processing draw intercept */
+ if ( oSettings.bDeferLoading )
+ {
+ oSettings.bDeferLoading = false;
+ oSettings.iDraw++;
+ }
+ else if ( !oSettings.oFeatures.bServerSide )
+ {
+ oSettings.iDraw++;
+ }
+ else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
+ {
+ return;
+ }
+
+ if ( oSettings.aiDisplay.length !== 0 )
+ {
+ var iStart = oSettings._iDisplayStart;
+ var iEnd = oSettings._iDisplayEnd;
+
+ if ( oSettings.oFeatures.bServerSide )
+ {
+ iStart = 0;
+ iEnd = oSettings.aoData.length;
+ }
+
+ for ( var j=iStart ; j')[0];
+ oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
+
+ /*
+ * All DataTables are wrapped in a div
+ */
+ oSettings.nTableWrapper = $('')[0];
+ oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
+
+ /* Track where we want to insert the option */
+ var nInsertNode = oSettings.nTableWrapper;
+
+ /* Loop over the user set positioning and place the elements as needed */
+ var aDom = oSettings.sDom.split('');
+ var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;
+ for ( var i=0 ; i')[0];
+
+ /* Check to see if we should append an id and/or a class name to the container */
+ cNext = aDom[i+1];
+ if ( cNext == "'" || cNext == '"' )
+ {
+ sAttr = "";
+ j = 2;
+ while ( aDom[i+j] != cNext )
+ {
+ sAttr += aDom[i+j];
+ j++;
+ }
+
+ /* Replace jQuery UI constants */
+ if ( sAttr == "H" )
+ {
+ sAttr = oSettings.oClasses.sJUIHeader;
+ }
+ else if ( sAttr == "F" )
+ {
+ sAttr = oSettings.oClasses.sJUIFooter;
+ }
+
+ /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
+ * breaks the string into parts and applies them as needed
+ */
+ if ( sAttr.indexOf('.') != -1 )
+ {
+ var aSplit = sAttr.split('.');
+ nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
+ nNewNode.className = aSplit[1];
+ }
+ else if ( sAttr.charAt(0) == "#" )
+ {
+ nNewNode.id = sAttr.substr(1, sAttr.length-1);
+ }
+ else
+ {
+ nNewNode.className = sAttr;
+ }
+
+ i += j; /* Move along the position array */
+ }
+
+ nInsertNode.appendChild( nNewNode );
+ nInsertNode = nNewNode;
+ }
+ else if ( cOption == '>' )
+ {
+ /* End container div */
+ nInsertNode = nInsertNode.parentNode;
+ }
+ else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
+ {
+ /* Length */
+ nTmp = _fnFeatureHtmlLength( oSettings );
+ iPushFeature = 1;
+ }
+ else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
+ {
+ /* Filter */
+ nTmp = _fnFeatureHtmlFilter( oSettings );
+ iPushFeature = 1;
+ }
+ else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
+ {
+ /* pRocessing */
+ nTmp = _fnFeatureHtmlProcessing( oSettings );
+ iPushFeature = 1;
+ }
+ else if ( cOption == 't' )
+ {
+ /* Table */
+ nTmp = _fnFeatureHtmlTable( oSettings );
+ iPushFeature = 1;
+ }
+ else if ( cOption == 'i' && oSettings.oFeatures.bInfo )
+ {
+ /* Info */
+ nTmp = _fnFeatureHtmlInfo( oSettings );
+ iPushFeature = 1;
+ }
+ else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
+ {
+ /* Pagination */
+ nTmp = _fnFeatureHtmlPaginate( oSettings );
+ iPushFeature = 1;
+ }
+ else if ( DataTable.ext.aoFeatures.length !== 0 )
+ {
+ /* Plug-in features */
+ var aoFeatures = DataTable.ext.aoFeatures;
+ for ( var k=0, kLen=aoFeatures.length ; k') :
+ sSearchStr==="" ? '' : sSearchStr+' ';
+
+ var nFilter = document.createElement( 'div' );
+ nFilter.className = oSettings.oClasses.sFilter;
+ nFilter.innerHTML = '';
+ if ( !oSettings.aanFeatures.f )
+ {
+ nFilter.id = oSettings.sTableId+'_filter';
+ }
+
+ var jqFilter = $('input[type="text"]', nFilter);
+
+ // Store a reference to the input element, so other input elements could be
+ // added to the filter wrapper if needed (submit button for example)
+ nFilter._DT_Input = jqFilter[0];
+
+ jqFilter.val( oPreviousSearch.sSearch.replace('"','"') );
+ jqFilter.bind( 'keyup.DT', function(e) {
+ /* Update all other filter input elements for the new display */
+ var n = oSettings.aanFeatures.f;
+ var val = this.value==="" ? "" : this.value; // mental IE8 fix :-(
+
+ for ( var i=0, iLen=n.length ; i=0 ; i-- )
+ {
+ var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ),
+ oSettings.aoColumns[iColumn].sType );
+ if ( ! rpSearch.test( sData ) )
+ {
+ oSettings.aiDisplay.splice( i, 1 );
+ iIndexCorrector++;
+ }
+ }
+ }
+
+
+ /**
+ * Filter the data table based on user input and draw the table
+ * @param {object} oSettings dataTables settings object
+ * @param {string} sInput string to filter on
+ * @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)
+ * @param {bool} bRegex treat as a regular expression or not
+ * @param {bool} bSmart perform smart filtering or not
+ * @param {bool} bCaseInsensitive Do case insenstive matching or not
+ * @memberof DataTable#oApi
+ */
+ function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive )
+ {
+ var i;
+ var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
+ var oPrevSearch = oSettings.oPreviousSearch;
+
+ /* Check if we are forcing or not - optional parameter */
+ if ( !iForce )
+ {
+ iForce = 0;
+ }
+
+ /* Need to take account of custom filtering functions - always filter */
+ if ( DataTable.ext.afnFiltering.length !== 0 )
+ {
+ iForce = 1;
+ }
+
+ /*
+ * If the input is blank - we want the full data set
+ */
+ if ( sInput.length <= 0 )
+ {
+ oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
+ oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
+ }
+ else
+ {
+ /*
+ * We are starting a new search or the new search string is smaller
+ * then the old one (i.e. delete). Search from the master array
+ */
+ if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
+ oPrevSearch.sSearch.length > sInput.length || iForce == 1 ||
+ sInput.indexOf(oPrevSearch.sSearch) !== 0 )
+ {
+ /* Nuke the old display array - we are going to rebuild it */
+ oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
+
+ /* Force a rebuild of the search array */
+ _fnBuildSearchArray( oSettings, 1 );
+
+ /* Search through all records to populate the search array
+ * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
+ * mapping
+ */
+ for ( i=0 ; i tag - remove it */
+ sSearch = sSearch.replace(/\n/g," ").replace(/\r/g,"");
+ }
+
+ return sSearch;
+ }
+
+ /**
+ * Build a regular expression object suitable for searching a table
+ * @param {string} sSearch string to search for
+ * @param {bool} bRegex treat as a regular expression or not
+ * @param {bool} bSmart perform smart filtering or not
+ * @param {bool} bCaseInsensitive Do case insenstive matching or not
+ * @returns {RegExp} constructed object
+ * @memberof DataTable#oApi
+ */
+ function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive )
+ {
+ var asSearch, sRegExpString;
+
+ if ( bSmart )
+ {
+ /* Generate the regular expression to use. Something along the lines of:
+ * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
+ */
+ asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' );
+ sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';
+ return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" );
+ }
+ else
+ {
+ sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch );
+ return new RegExp( sSearch, bCaseInsensitive ? "i" : "" );
+ }
+ }
+
+
+ /**
+ * Convert raw data into something that the user can search on
+ * @param {string} sData data to be modified
+ * @param {string} sType data type
+ * @returns {string} search string
+ * @memberof DataTable#oApi
+ */
+ function _fnDataToSearch ( sData, sType )
+ {
+ if ( typeof DataTable.ext.ofnSearch[sType] === "function" )
+ {
+ return DataTable.ext.ofnSearch[sType]( sData );
+ }
+ else if ( sData === null )
+ {
+ return '';
+ }
+ else if ( sType == "html" )
+ {
+ return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" );
+ }
+ else if ( typeof sData === "string" )
+ {
+ return sData.replace(/[\r\n]/g," ");
+ }
+ return sData;
+ }
+
+
+ /**
+ * scape a string stuch that it can be used in a regular expression
+ * @param {string} sVal string to escape
+ * @returns {string} escaped string
+ * @memberof DataTable#oApi
+ */
+ function _fnEscapeRegex ( sVal )
+ {
+ var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ];
+ var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' );
+ return sVal.replace(reReplace, '\\$1');
+ }
+
+
+
+ /**
+ * Generate the node required for the info display
+ * @param {object} oSettings dataTables settings object
+ * @returns {node} Information element
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlInfo ( oSettings )
+ {
+ var nInfo = document.createElement( 'div' );
+ nInfo.className = oSettings.oClasses.sInfo;
+
+ /* Actions that are to be taken once only for this feature */
+ if ( !oSettings.aanFeatures.i )
+ {
+ /* Add draw callback */
+ oSettings.aoDrawCallback.push( {
+ "fn": _fnUpdateInfo,
+ "sName": "information"
+ } );
+
+ /* Add id */
+ nInfo.id = oSettings.sTableId+'_info';
+ }
+ oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' );
+
+ return nInfo;
+ }
+
+
+ /**
+ * Update the information elements in the display
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnUpdateInfo ( oSettings )
+ {
+ /* Show information about the table */
+ if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 )
+ {
+ return;
+ }
+
+ var
+ oLang = oSettings.oLanguage,
+ iStart = oSettings._iDisplayStart+1,
+ iEnd = oSettings.fnDisplayEnd(),
+ iMax = oSettings.fnRecordsTotal(),
+ iTotal = oSettings.fnRecordsDisplay(),
+ sOut;
+
+ if ( iTotal === 0 && iTotal == iMax )
+ {
+ /* Empty record set */
+ sOut = oLang.sInfoEmpty;
+ }
+ else if ( iTotal === 0 )
+ {
+ /* Empty record set after filtering */
+ sOut = oLang.sInfoEmpty +' '+ oLang.sInfoFiltered;
+ }
+ else if ( iTotal == iMax )
+ {
+ /* Normal record set */
+ sOut = oLang.sInfo;
+ }
+ else
+ {
+ /* Record set after filtering */
+ sOut = oLang.sInfo +' '+ oLang.sInfoFiltered;
+ }
+
+ // Convert the macros
+ sOut += oLang.sInfoPostFix;
+ sOut = _fnInfoMacros( oSettings, sOut );
+
+ if ( oLang.fnInfoCallback !== null )
+ {
+ sOut = oLang.fnInfoCallback.call( oSettings.oInstance,
+ oSettings, iStart, iEnd, iMax, iTotal, sOut );
+ }
+
+ var n = oSettings.aanFeatures.i;
+ for ( var i=0, iLen=n.length ; i';
+ var i, iLen;
+ var aLengthMenu = oSettings.aLengthMenu;
+
+ if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' &&
+ typeof aLengthMenu[1] === 'object' )
+ {
+ for ( i=0, iLen=aLengthMenu[0].length ; i'+aLengthMenu[1][i]+'';
+ }
+ }
+ else
+ {
+ for ( i=0, iLen=aLengthMenu.length ; i'+aLengthMenu[i]+'';
+ }
+ }
+ sStdMenu += '';
+
+ var nLength = document.createElement( 'div' );
+ if ( !oSettings.aanFeatures.l )
+ {
+ nLength.id = oSettings.sTableId+'_length';
+ }
+ nLength.className = oSettings.oClasses.sLength;
+ nLength.innerHTML = '';
+
+ /*
+ * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
+ * and Stefan Skopnik for fixing the fix!
+ */
+ $('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true);
+
+ $('select', nLength).bind( 'change.DT', function(e) {
+ var iVal = $(this).val();
+
+ /* Update all other length options for the new display */
+ var n = oSettings.aanFeatures.l;
+ for ( i=0, iLen=n.length ; i oSettings.aiDisplay.length ||
+ oSettings._iDisplayLength == -1 )
+ {
+ oSettings._iDisplayEnd = oSettings.aiDisplay.length;
+ }
+ else
+ {
+ oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
+ }
+ }
+ }
+
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Note that most of the paging logic is done in
+ * DataTable.ext.oPagination
+ */
+
+ /**
+ * Generate the node required for default pagination
+ * @param {object} oSettings dataTables settings object
+ * @returns {node} Pagination feature node
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlPaginate ( oSettings )
+ {
+ if ( oSettings.oScroll.bInfinite )
+ {
+ return null;
+ }
+
+ var nPaginate = document.createElement( 'div' );
+ nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
+
+ DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate,
+ function( oSettings ) {
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+ );
+
+ /* Add a draw callback for the pagination on first instance, to update the paging display */
+ if ( !oSettings.aanFeatures.p )
+ {
+ oSettings.aoDrawCallback.push( {
+ "fn": function( oSettings ) {
+ DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ } );
+ },
+ "sName": "pagination"
+ } );
+ }
+ return nPaginate;
+ }
+
+
+ /**
+ * Alter the display settings to change the page
+ * @param {object} oSettings dataTables settings object
+ * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
+ * or page number to jump to (integer)
+ * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
+ * @memberof DataTable#oApi
+ */
+ function _fnPageChange ( oSettings, mAction )
+ {
+ var iOldStart = oSettings._iDisplayStart;
+
+ if ( typeof mAction === "number" )
+ {
+ oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
+ if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else if ( mAction == "first" )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ else if ( mAction == "previous" )
+ {
+ oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?
+ oSettings._iDisplayStart - oSettings._iDisplayLength :
+ 0;
+
+ /* Correct for underrun */
+ if ( oSettings._iDisplayStart < 0 )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else if ( mAction == "next" )
+ {
+ if ( oSettings._iDisplayLength >= 0 )
+ {
+ /* Make sure we are not over running the display array */
+ if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
+ {
+ oSettings._iDisplayStart += oSettings._iDisplayLength;
+ }
+ }
+ else
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else if ( mAction == "last" )
+ {
+ if ( oSettings._iDisplayLength >= 0 )
+ {
+ var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
+ oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
+ }
+ else
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else
+ {
+ _fnLog( oSettings, 0, "Unknown paging action: "+mAction );
+ }
+ $(oSettings.oInstance).trigger('page', oSettings);
+
+ return iOldStart != oSettings._iDisplayStart;
+ }
+
+
+
+ /**
+ * Generate the node required for the processing node
+ * @param {object} oSettings dataTables settings object
+ * @returns {node} Processing element
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlProcessing ( oSettings )
+ {
+ var nProcessing = document.createElement( 'div' );
+
+ if ( !oSettings.aanFeatures.r )
+ {
+ nProcessing.id = oSettings.sTableId+'_processing';
+ }
+ nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
+ nProcessing.className = oSettings.oClasses.sProcessing;
+ oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
+
+ return nProcessing;
+ }
+
+
+ /**
+ * Display or hide the processing indicator
+ * @param {object} oSettings dataTables settings object
+ * @param {bool} bShow Show the processing indicator (true) or not (false)
+ * @memberof DataTable#oApi
+ */
+ function _fnProcessingDisplay ( oSettings, bShow )
+ {
+ if ( oSettings.oFeatures.bProcessing )
+ {
+ var an = oSettings.aanFeatures.r;
+ for ( var i=0, iLen=an.length ; i 0 )
+ {
+ nCaption = nCaption[0];
+ if ( nCaption._captionSide === "top" )
+ {
+ nScrollHeadTable.appendChild( nCaption );
+ }
+ else if ( nCaption._captionSide === "bottom" && nTfoot )
+ {
+ nScrollFootTable.appendChild( nCaption );
+ }
+ }
+
+ /*
+ * Sizing
+ */
+ /* When xscrolling add the width and a scroller to move the header with the body */
+ if ( oSettings.oScroll.sX !== "" )
+ {
+ nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );
+ nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );
+
+ if ( nTfoot !== null )
+ {
+ nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );
+ }
+
+ /* When the body is scrolled, then we also want to scroll the headers */
+ $(nScrollBody).scroll( function (e) {
+ nScrollHead.scrollLeft = this.scrollLeft;
+
+ if ( nTfoot !== null )
+ {
+ nScrollFoot.scrollLeft = this.scrollLeft;
+ }
+ } );
+ }
+
+ /* When yscrolling, add the height */
+ if ( oSettings.oScroll.sY !== "" )
+ {
+ nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );
+ }
+
+ /* Redraw - align columns across the tables */
+ oSettings.aoDrawCallback.push( {
+ "fn": _fnScrollDraw,
+ "sName": "scrolling"
+ } );
+
+ /* Infinite scrolling event handlers */
+ if ( oSettings.oScroll.bInfinite )
+ {
+ $(nScrollBody).scroll( function() {
+ /* Use a blocker to stop scrolling from loading more data while other data is still loading */
+ if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 )
+ {
+ /* Check if we should load the next data set */
+ if ( $(this).scrollTop() + $(this).height() >
+ $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )
+ {
+ /* Only do the redraw if we have to - we might be at the end of the data */
+ if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )
+ {
+ _fnPageChange( oSettings, 'next' );
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+ }
+ }
+ } );
+ }
+
+ oSettings.nScrollHead = nScrollHead;
+ oSettings.nScrollFoot = nScrollFoot;
+
+ return nScroller;
+ }
+
+
+ /**
+ * Update the various tables for resizing. It's a bit of a pig this function, but
+ * basically the idea to:
+ * 1. Re-create the table inside the scrolling div
+ * 2. Take live measurements from the DOM
+ * 3. Apply the measurements
+ * 4. Clean up
+ * @param {object} o dataTables settings object
+ * @returns {node} Node to add to the DOM
+ * @memberof DataTable#oApi
+ */
+ function _fnScrollDraw ( o )
+ {
+ var
+ nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
+ nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
+ nScrollBody = o.nTable.parentNode,
+ i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
+ nTheadSize, nTfootSize,
+ iWidth, aApplied=[], iSanityWidth,
+ nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
+ nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
+ ie67 = $.browser.msie && $.browser.version <= 7;
+
+ /*
+ * 1. Re-create the table inside the scrolling div
+ */
+
+ /* Remove the old minimised thead and tfoot elements in the inner table */
+ $(o.nTable).children('thead, tfoot').remove();
+
+ /* Clone the current header and footer elements and then place it into the inner table */
+ nTheadSize = $(o.nTHead).clone()[0];
+ o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
+
+ if ( o.nTFoot !== null )
+ {
+ nTfootSize = $(o.nTFoot).clone()[0];
+ o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
+ }
+
+ /*
+ * 2. Take live measurements from the DOM - do not alter the DOM itself!
+ */
+
+ /* Remove old sizing and apply the calculated column widths
+ * Get the unique column headers in the newly created (cloned) header. We want to apply the
+ * calclated sizes to this header
+ */
+ if ( o.oScroll.sX === "" )
+ {
+ nScrollBody.style.width = '100%';
+ nScrollHeadInner.parentNode.style.width = '100%';
+ }
+
+ var nThs = _fnGetUniqueThs( o, nTheadSize );
+ for ( i=0, iLen=nThs.length ; i nScrollBody.offsetHeight ||
+ $(nScrollBody).css('overflow-y') == "scroll") )
+ {
+ o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
+ }
+ }
+ else
+ {
+ if ( o.oScroll.sXInner !== "" )
+ {
+ /* x scroll inner has been given - use it */
+ o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
+ }
+ else if ( iSanityWidth == $(nScrollBody).width() &&
+ $(nScrollBody).height() < $(o.nTable).height() )
+ {
+ /* There is y-scrolling - try to take account of the y scroll bar */
+ o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );
+ if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )
+ {
+ /* Not possible to take account of it */
+ o.nTable.style.width = _fnStringToCss( iSanityWidth );
+ }
+ }
+ else
+ {
+ /* All else fails */
+ o.nTable.style.width = _fnStringToCss( iSanityWidth );
+ }
+ }
+
+ /* Recalculate the sanity width - now that we've applied the required width, before it was
+ * a temporary variable. This is required because the column width calculation is done
+ * before this table DOM is created.
+ */
+ iSanityWidth = $(o.nTable).outerWidth();
+
+ /* We want the hidden header to have zero height, so remove padding and borders. Then
+ * set the width based on the real headers
+ */
+ anHeadToSize = o.nTHead.getElementsByTagName('tr');
+ anHeadSizers = nTheadSize.getElementsByTagName('tr');
+
+ _fnApplyToChildren( function(nSizer, nToSize) {
+ oStyle = nSizer.style;
+ oStyle.paddingTop = "0";
+ oStyle.paddingBottom = "0";
+ oStyle.borderTopWidth = "0";
+ oStyle.borderBottomWidth = "0";
+ oStyle.height = 0;
+
+ iWidth = $(nSizer).width();
+ nToSize.style.width = _fnStringToCss( iWidth );
+ aApplied.push( iWidth );
+ }, anHeadSizers, anHeadToSize );
+ $(anHeadSizers).height(0);
+
+ if ( o.nTFoot !== null )
+ {
+ /* Clone the current footer and then place it into the body table as a "hidden header" */
+ anFootSizers = nTfootSize.getElementsByTagName('tr');
+ anFootToSize = o.nTFoot.getElementsByTagName('tr');
+
+ _fnApplyToChildren( function(nSizer, nToSize) {
+ oStyle = nSizer.style;
+ oStyle.paddingTop = "0";
+ oStyle.paddingBottom = "0";
+ oStyle.borderTopWidth = "0";
+ oStyle.borderBottomWidth = "0";
+ oStyle.height = 0;
+
+ iWidth = $(nSizer).width();
+ nToSize.style.width = _fnStringToCss( iWidth );
+ aApplied.push( iWidth );
+ }, anFootSizers, anFootToSize );
+ $(anFootSizers).height(0);
+ }
+
+ /*
+ * 3. Apply the measurements
+ */
+
+ /* "Hide" the header and footer that we used for the sizing. We want to also fix their width
+ * to what they currently are
+ */
+ _fnApplyToChildren( function(nSizer) {
+ nSizer.innerHTML = "";
+ nSizer.style.width = _fnStringToCss( aApplied.shift() );
+ }, anHeadSizers );
+
+ if ( o.nTFoot !== null )
+ {
+ _fnApplyToChildren( function(nSizer) {
+ nSizer.innerHTML = "";
+ nSizer.style.width = _fnStringToCss( aApplied.shift() );
+ }, anFootSizers );
+ }
+
+ /* Sanity check that the table is of a sensible width. If not then we are going to get
+ * misalignment - try to prevent this by not allowing the table to shrink below its min width
+ */
+ if ( $(o.nTable).outerWidth() < iSanityWidth )
+ {
+ /* The min width depends upon if we have a vertical scrollbar visible or not */
+ var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight ||
+ $(nScrollBody).css('overflow-y') == "scroll")) ?
+ iSanityWidth+o.oScroll.iBarWidth : iSanityWidth;
+
+ /* IE6/7 are a law unto themselves... */
+ if ( ie67 && (nScrollBody.scrollHeight >
+ nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") )
+ {
+ o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth );
+ }
+
+ /* Apply the calculated minimum width to the table wrappers */
+ nScrollBody.style.width = _fnStringToCss( iCorrection );
+ nScrollHeadInner.parentNode.style.width = _fnStringToCss( iCorrection );
+
+ if ( o.nTFoot !== null )
+ {
+ nScrollFootInner.parentNode.style.width = _fnStringToCss( iCorrection );
+ }
+
+ /* And give the user a warning that we've stopped the table getting too small */
+ if ( o.oScroll.sX === "" )
+ {
+ _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
+ " misalignment. The table has been drawn at its minimum possible width." );
+ }
+ else if ( o.oScroll.sXInner !== "" )
+ {
+ _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
+ " misalignment. Increase the sScrollXInner value or remove it to allow automatic"+
+ " calculation" );
+ }
+ }
+ else
+ {
+ nScrollBody.style.width = _fnStringToCss( '100%' );
+ nScrollHeadInner.parentNode.style.width = _fnStringToCss( '100%' );
+
+ if ( o.nTFoot !== null )
+ {
+ nScrollFootInner.parentNode.style.width = _fnStringToCss( '100%' );
+ }
+ }
+
+
+ /*
+ * 4. Clean up
+ */
+ if ( o.oScroll.sY === "" )
+ {
+ /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
+ * the scrollbar height from the visible display, rather than adding it on. We need to
+ * set the height in order to sort this. Don't want to do it in any other browsers.
+ */
+ if ( ie67 )
+ {
+ nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );
+ }
+ }
+
+ if ( o.oScroll.sY !== "" && o.oScroll.bCollapse )
+ {
+ nScrollBody.style.height = _fnStringToCss( o.oScroll.sY );
+
+ var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
+ o.oScroll.iBarWidth : 0;
+ if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
+ {
+ nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );
+ }
+ }
+
+ /* Finally set the width's of the header and footer tables */
+ var iOuterWidth = $(o.nTable).outerWidth();
+ nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
+ nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );
+
+ // Figure out if there are scrollbar present - if so then we need a the header and footer to
+ // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
+ var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
+ nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
+
+ if ( o.nTFoot !== null )
+ {
+ nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
+ nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
+ nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
+ }
+
+ /* Adjust the position of the header incase we loose the y-scrollbar */
+ $(nScrollBody).scroll();
+
+ /* If sorting or filtering has occurred, jump the scrolling back to the top */
+ if ( o.bSorted || o.bFiltered )
+ {
+ nScrollBody.scrollTop = 0;
+ }
+ }
+
+
+ /**
+ * Apply a given function to the display child nodes of an element array (typically
+ * TD children of TR rows
+ * @param {function} fn Method to apply to the objects
+ * @param array {nodes} an1 List of elements to look through for display children
+ * @param array {nodes} an2 Another list (identical structure to the first) - optional
+ * @memberof DataTable#oApi
+ */
+ function _fnApplyToChildren( fn, an1, an2 )
+ {
+ for ( var i=0, iLen=an1.length ; itd', nCalcTmp);
+ }
+
+ /* Apply custom sizing to the cloned header */
+ var nThs = _fnGetUniqueThs( oSettings, nTheadClone );
+ iCorrector = 0;
+ for ( i=0 ; i 0 )
+ {
+ oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );
+ }
+ iCorrector++;
+ }
+ }
+
+ var cssWidth = $(nCalcTmp).css('width');
+ oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
+ cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() );
+ nCalcTmp.parentNode.removeChild( nCalcTmp );
+ }
+
+ if ( widthAttr )
+ {
+ oSettings.nTable.style.width = _fnStringToCss( widthAttr );
+ }
+ }
+
+
+ /**
+ * Adjust a table's width to take account of scrolling
+ * @param {object} oSettings dataTables settings object
+ * @param {node} n table node
+ * @memberof DataTable#oApi
+ */
+ function _fnScrollingWidthAdjust ( oSettings, n )
+ {
+ if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" )
+ {
+ /* When y-scrolling only, we want to remove the width of the scroll bar so the table
+ * + scroll bar will fit into the area avaialble.
+ */
+ var iOrigWidth = $(n).width();
+ n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );
+ }
+ else if ( oSettings.oScroll.sX !== "" )
+ {
+ /* When x-scrolling both ways, fix the table at it's current size, without adjusting */
+ n.style.width = _fnStringToCss( $(n).outerWidth() );
+ }
+ }
+
+
+ /**
+ * Get the widest node
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iCol column of interest
+ * @returns {string} max strlens for each column
+ * @memberof DataTable#oApi
+ */
+ function _fnGetWidestNode( oSettings, iCol )
+ {
+ var iMaxIndex = _fnGetMaxLenString( oSettings, iCol );
+ if ( iMaxIndex < 0 )
+ {
+ return null;
+ }
+
+ if ( oSettings.aoData[iMaxIndex].nTr === null )
+ {
+ var n = document.createElement('td');
+ n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' );
+ return n;
+ }
+ return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
+ }
+
+
+ /**
+ * Get the maximum strlen for each data column
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iCol column of interest
+ * @returns {string} max strlens for each column
+ * @memberof DataTable#oApi
+ */
+ function _fnGetMaxLenString( oSettings, iCol )
+ {
+ var iMax = -1;
+ var iMaxIndex = -1;
+
+ for ( var i=0 ; i/g, "" );
+ if ( s.length > iMax )
+ {
+ iMax = s.length;
+ iMaxIndex = i;
+ }
+ }
+
+ return iMaxIndex;
+ }
+
+
+ /**
+ * Append a CSS unit (only if required) to a string
+ * @param {array} aArray1 first array
+ * @param {array} aArray2 second array
+ * @returns {int} 0 if match, 1 if length is different, 2 if no match
+ * @memberof DataTable#oApi
+ */
+ function _fnStringToCss( s )
+ {
+ if ( s === null )
+ {
+ return "0px";
+ }
+
+ if ( typeof s == 'number' )
+ {
+ if ( s < 0 )
+ {
+ return "0px";
+ }
+ return s+"px";
+ }
+
+ /* Check if the last character is not 0-9 */
+ var c = s.charCodeAt( s.length-1 );
+ if (c < 0x30 || c > 0x39)
+ {
+ return s;
+ }
+ return s+"px";
+ }
+
+
+ /**
+ * Get the width of a scroll bar in this browser being used
+ * @returns {int} width in pixels
+ * @memberof DataTable#oApi
+ */
+ function _fnScrollBarWidth ()
+ {
+ var inner = document.createElement('p');
+ var style = inner.style;
+ style.width = "100%";
+ style.height = "200px";
+ style.padding = "0px";
+
+ var outer = document.createElement('div');
+ style = outer.style;
+ style.position = "absolute";
+ style.top = "0px";
+ style.left = "0px";
+ style.visibility = "hidden";
+ style.width = "200px";
+ style.height = "150px";
+ style.padding = "0px";
+ style.overflow = "hidden";
+ outer.appendChild(inner);
+
+ document.body.appendChild(outer);
+ var w1 = inner.offsetWidth;
+ outer.style.overflow = 'scroll';
+ var w2 = inner.offsetWidth;
+ if ( w1 == w2 )
+ {
+ w2 = outer.clientWidth;
+ }
+
+ document.body.removeChild(outer);
+ return (w1 - w2);
+ }
+
+
+
+ /**
+ * Change the order of the table
+ * @param {object} oSettings dataTables settings object
+ * @param {bool} bApplyClasses optional - should we apply classes or not
+ * @memberof DataTable#oApi
+ */
+ function _fnSort ( oSettings, bApplyClasses )
+ {
+ var
+ i, iLen, j, jLen, k, kLen,
+ sDataType, nTh,
+ aaSort = [],
+ aiOrig = [],
+ oSort = DataTable.ext.oSort,
+ aoData = oSettings.aoData,
+ aoColumns = oSettings.aoColumns,
+ oAria = oSettings.oLanguage.oAria;
+
+ /* No sorting required if server-side or no sorting array */
+ if ( !oSettings.oFeatures.bServerSide &&
+ (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )
+ {
+ aaSort = ( oSettings.aaSortingFixed !== null ) ?
+ oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
+ oSettings.aaSorting.slice();
+
+ /* If there is a sorting data type, and a fuction belonging to it, then we need to
+ * get the data from the developer's function and apply it for this column
+ */
+ for ( i=0 ; i/g, "" );
+ nTh = aoColumns[i].nTh;
+ nTh.removeAttribute('aria-sort');
+ nTh.removeAttribute('aria-label');
+
+ /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
+ if ( aoColumns[i].bSortable )
+ {
+ if ( aaSort.length > 0 && aaSort[0][0] == i )
+ {
+ nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" );
+
+ var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ?
+ aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];
+ nTh.setAttribute('aria-label', sTitle+
+ (nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
+ }
+ else
+ {
+ nTh.setAttribute('aria-label', sTitle+
+ (aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
+ }
+ }
+ else
+ {
+ nTh.setAttribute('aria-label', sTitle);
+ }
+ }
+
+ /* Tell the draw function that we have sorted the data */
+ oSettings.bSorted = true;
+ $(oSettings.oInstance).trigger('sort', oSettings);
+
+ /* Copy the master data into the draw array and re-draw */
+ if ( oSettings.oFeatures.bFilter )
+ {
+ /* _fnFilter() will redraw the table for us */
+ _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
+ }
+ else
+ {
+ oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
+ oSettings._iDisplayStart = 0; /* reset display back to page 0 */
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+ }
+
+
+ /**
+ * Attach a sort handler (click) to a node
+ * @param {object} oSettings dataTables settings object
+ * @param {node} nNode node to attach the handler to
+ * @param {int} iDataIndex column sorting index
+ * @param {function} [fnCallback] callback function
+ * @memberof DataTable#oApi
+ */
+ function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )
+ {
+ _fnBindAction( nNode, {}, function (e) {
+ /* If the column is not sortable - don't to anything */
+ if ( oSettings.aoColumns[iDataIndex].bSortable === false )
+ {
+ return;
+ }
+
+ /*
+ * This is a little bit odd I admit... I declare a temporary function inside the scope of
+ * _fnBuildHead and the click handler in order that the code presented here can be used
+ * twice - once for when bProcessing is enabled, and another time for when it is
+ * disabled, as we need to perform slightly different actions.
+ * Basically the issue here is that the Javascript engine in modern browsers don't
+ * appear to allow the rendering engine to update the display while it is still excuting
+ * it's thread (well - it does but only after long intervals). This means that the
+ * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
+ * I force an execution break by using setTimeout - but this breaks the expected
+ * thread continuation for the end-developer's point of view (their code would execute
+ * too early), so we on;y do it when we absolutely have to.
+ */
+ var fnInnerSorting = function () {
+ var iColumn, iNextSort;
+
+ /* If the shift key is pressed then we are multipe column sorting */
+ if ( e.shiftKey )
+ {
+ /* Are we already doing some kind of sort on this column? */
+ var bFound = false;
+ for ( var i=0 ; i= iColumns )
+ {
+ for ( i=0 ; i 4096 ) /* Magic 10 for padding */
+ {
+ var aCookies =document.cookie.split(';');
+ for ( var i=0, iLen=aCookies.length ; i=0 ; i-- )
+ {
+ aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) );
+ }
+
+ if ( sTrigger !== null )
+ {
+ $(oSettings.oInstance).trigger(sTrigger, aArgs);
+ }
+
+ return aRet;
+ }
+
+
+ /**
+ * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
+ * library, then we use that as it is fast, safe and accurate. If the function isn't
+ * available then we need to built it ourselves - the insperation for this function comes
+ * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
+ * not perfect and absolutely should not be used as a replacement to json2.js - but it does
+ * do what we need, without requiring a dependency for DataTables.
+ * @param {object} o JSON object to be converted
+ * @returns {string} JSON string
+ * @memberof DataTable#oApi
+ */
+ var _fnJsonString = (window.JSON) ? JSON.stringify : function( o )
+ {
+ /* Not an object or array */
+ var sType = typeof o;
+ if (sType !== "object" || o === null)
+ {
+ // simple data type
+ if (sType === "string")
+ {
+ o = '"'+o+'"';
+ }
+ return o+"";
+ }
+
+ /* If object or array, need to recurse over it */
+ var
+ sProp, mValue,
+ json = [],
+ bArr = $.isArray(o);
+
+ for (sProp in o)
+ {
+ mValue = o[sProp];
+ sType = typeof mValue;
+
+ if (sType === "string")
+ {
+ mValue = '"'+mValue+'"';
+ }
+ else if (sType === "object" && mValue !== null)
+ {
+ mValue = _fnJsonString(mValue);
+ }
+
+ json.push((bArr ? "" : '"'+sProp+'":') + mValue);
+ }
+
+ return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
+ };
+
+
+
+
+ /**
+ * Perform a jQuery selector action on the table's TR elements (from the tbody) and
+ * return the resulting jQuery object.
+ * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
+ * @param {object} [oOpts] Optional parameters for modifying the rows to be included
+ * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
+ * criterion ("applied") or all TR elements (i.e. no filter).
+ * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
+ * Can be either 'current', whereby the current sorting of the table is used, or
+ * 'original' whereby the original order the data was read into the table is used.
+ * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
+ * ("current") or not ("all"). If 'current' is given, then order is assumed to be
+ * 'current' and filter is 'applied', regardless of what they might be given as.
+ * @returns {object} jQuery object, filtered by the given selector.
+ * @dtopt API
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Highlight every second row
+ * oTable.$('tr:odd').css('backgroundColor', 'blue');
+ * } );
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Filter to rows with 'Webkit' in them, add a background colour and then
+ * // remove the filter, thus highlighting the 'Webkit' rows only.
+ * oTable.fnFilter('Webkit');
+ * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
+ * oTable.fnFilter('');
+ * } );
+ */
+ this.$ = function ( sSelector, oOpts )
+ {
+ var i, iLen, a = [], tr;
+ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
+ var aoData = oSettings.aoData;
+ var aiDisplay = oSettings.aiDisplay;
+ var aiDisplayMaster = oSettings.aiDisplayMaster;
+
+ if ( !oOpts )
+ {
+ oOpts = {};
+ }
+
+ oOpts = $.extend( {}, {
+ "filter": "none", // applied
+ "order": "current", // "original"
+ "page": "all" // current
+ }, oOpts );
+
+ // Current page implies that order=current and fitler=applied, since it is fairly
+ // senseless otherwise
+ if ( oOpts.page == 'current' )
+ {
+ for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i
+ *
1D array of data - add a single row with the data provided
+ *
2D array of arrays - add multiple rows in a single call
+ *
object - data object when using mDataProp
+ *
array of objects - multiple data objects when using mDataProp
+ *
+ * @param {bool} [bRedraw=true] redraw the table or not
+ * @returns {array} An array of integers, representing the list of indexes in
+ * aoData ({@link DataTable.models.oSettings}) that have been added to
+ * the table.
+ * @dtopt API
+ *
+ * @example
+ * // Global var for counter
+ * var giCount = 2;
+ *
+ * $(document).ready(function() {
+ * $('#example').dataTable();
+ * } );
+ *
+ * function fnClickAddRow() {
+ * $('#example').dataTable().fnAddData( [
+ * giCount+".1",
+ * giCount+".2",
+ * giCount+".3",
+ * giCount+".4" ]
+ * );
+ *
+ * giCount++;
+ * }
+ */
+ this.fnAddData = function( mData, bRedraw )
+ {
+ if ( mData.length === 0 )
+ {
+ return [];
+ }
+
+ var aiReturn = [];
+ var iTest;
+
+ /* Find settings from table node */
+ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
+
+ /* Check if we want to add multiple rows or not */
+ if ( typeof mData[0] === "object" && mData[0] !== null )
+ {
+ for ( var i=0 ; i= oSettings.fnRecordsDisplay() )
+ {
+ oSettings._iDisplayStart -= oSettings._iDisplayLength;
+ if ( oSettings._iDisplayStart < 0 )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+
+ if ( bRedraw === undefined || bRedraw )
+ {
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+
+ return oData;
+ };
+
+
+ /**
+ * Restore the table to it's original state in the DOM by removing all of DataTables
+ * enhancements, alterations to the DOM structure of the table and event listeners.
+ * @param {boolean} [bRemove=false] Completely remove the table from the DOM
+ * @dtopt API
+ *
+ * @example
+ * $(document).ready(function() {
+ * // This example is fairly pointless in reality, but shows how fnDestroy can be used
+ * var oTable = $('#example').dataTable();
+ * oTable.fnDestroy();
+ * } );
+ */
+ this.fnDestroy = function ( bRemove )
+ {
+ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
+ var nOrig = oSettings.nTableWrapper.parentNode;
+ var nBody = oSettings.nTBody;
+ var i, iLen;
+
+ bRemove = (bRemove===undefined) ? false : true;
+
+ /* Flag to note that the table is currently being destroyed - no action should be taken */
+ oSettings.bDestroying = true;
+
+ /* Fire off the destroy callbacks for plug-ins etc */
+ _fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] );
+
+ /* Restore hidden columns */
+ for ( i=0, iLen=oSettings.aoColumns.length ; itr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
+
+ /* When scrolling we had to break the table up - restore it */
+ if ( oSettings.nTable != oSettings.nTHead.parentNode )
+ {
+ $(oSettings.nTable).children('thead').remove();
+ oSettings.nTable.appendChild( oSettings.nTHead );
+ }
+
+ if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )
+ {
+ $(oSettings.nTable).children('tfoot').remove();
+ oSettings.nTable.appendChild( oSettings.nTFoot );
+ }
+
+ /* Remove the DataTables generated nodes, events and classes */
+ oSettings.nTable.parentNode.removeChild( oSettings.nTable );
+ $(oSettings.nTableWrapper).remove();
+
+ oSettings.aaSorting = [];
+ oSettings.aaSortingFixed = [];
+ _fnSortingClasses( oSettings );
+
+ $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') );
+
+ $('th, td', oSettings.nTHead).removeClass( [
+ oSettings.oClasses.sSortable,
+ oSettings.oClasses.sSortableAsc,
+ oSettings.oClasses.sSortableDesc,
+ oSettings.oClasses.sSortableNone ].join(' ')
+ );
+ if ( oSettings.bJUI )
+ {
+ $('th span.'+oSettings.oClasses.sSortIcon
+ + ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
+
+ $('th, td', oSettings.nTHead).each( function () {
+ var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this);
+ var kids = jqWrapper.contents();
+ $(this).append( kids );
+ jqWrapper.remove();
+ } );
+ }
+
+ /* Add the TR elements back into the table in their original order */
+ if ( !bRemove && oSettings.nTableReinsertBefore )
+ {
+ nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore );
+ }
+ else if ( !bRemove )
+ {
+ nOrig.appendChild( oSettings.nTable );
+ }
+
+ for ( i=0, iLen=oSettings.aoData.length ; i= _fnVisbleColumns( oSettings ));
+
+ /* Which coloumn should we be inserting before? */
+ if ( !bAppend )
+ {
+ for ( i=iCol ; i= oSettings.aoColumns.length )
+ {
+ oSettings.aaSorting[i][0] = 0;
+ }
+ var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
+
+ /* Add a default sorting index */
+ if ( oSettings.aaSorting[i][2] === undefined )
+ {
+ oSettings.aaSorting[i][2] = 0;
+ }
+
+ /* If aaSorting is not defined, then we use the first indicator in asSorting */
+ if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined )
+ {
+ oSettings.aaSorting[i][1] = oColumn.asSorting[0];
+ }
+
+ /* Set the current sorting index based on aoColumns.asSorting */
+ for ( j=0, jLen=oColumn.asSorting.length ; j 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
+ {
+ // If we are a scrolling table, and no footer has been given, then we need to create
+ // a tfoot element for the caption element to be appended to
+ tfoot = [ document.createElement( 'tfoot' ) ];
+ this.appendChild( tfoot[0] );
+ }
+
+ if ( tfoot.length > 0 )
+ {
+ oSettings.nTFoot = tfoot[0];
+ _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
+ }
+
+ /* Check if there is data passing into the constructor */
+ if ( bUsePassedData )
+ {
+ for ( i=0 ; i= parseInt(sThat, 10);
+ };
+
+
+ /**
+ * Check if a TABLE node is a DataTable table already or not.
+ * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
+ * node types can be passed in, but will always return false).
+ * @returns {boolean} true the table given is a DataTable, or false otherwise
+ * @static
+ * @dtopt API-Static
+ *
+ * @example
+ * var ex = document.getElementById('example');
+ * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
+ * $(ex).dataTable();
+ * }
+ */
+ DataTable.fnIsDataTable = function ( nTable )
+ {
+ var o = DataTable.settings;
+
+ for ( var i=0 ; i 0 ) {
+ * $(table).dataTable().fnAdjustColumnSizing();
+ * }
+ */
+ DataTable.fnTables = function ( bVisible )
+ {
+ var out = [];
+
+ jQuery.each( DataTable.settings, function (i, o) {
+ if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )
+ {
+ out.push( o.nTable );
+ }
+ } );
+
+ return out;
+ };
+
+
+ /**
+ * Version string for plug-ins to check compatibility. Allowed format is
+ * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
+ * e are optional
+ * @member
+ * @type string
+ * @default Version number
+ */
+ DataTable.version = "1.9.2";
+
+ /**
+ * Private data store, containing all of the settings objects that are created for the
+ * tables on a given page.
+ *
+ * Note that the DataTable.settings object is aliased to jQuery.fn.dataTableExt
+ * through which it may be accessed and manipulated, or jQuery.fn.dataTable.settings.
+ * @member
+ * @type array
+ * @default []
+ * @private
+ */
+ DataTable.settings = [];
+
+ /**
+ * Object models container, for the various models that DataTables has available
+ * to it. These models define the objects that are used to hold the active state
+ * and configuration of the table.
+ * @namespace
+ */
+ DataTable.models = {};
+
+
+ /**
+ * DataTables extension options and plug-ins. This namespace acts as a collection "area"
+ * for plug-ins that can be used to extend the default DataTables behaviour - indeed many
+ * of the build in methods use this method to provide their own capabilities (sorting methods
+ * for example).
+ *
+ * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
+ * and modified by plug-ins.
+ * @namespace
+ */
+ DataTable.models.ext = {
+ /**
+ * Plug-in filtering functions - this method of filtering is complimentary to the default
+ * type based filtering, and a lot more comprehensive as it allows you complete control
+ * over the filtering logic. Each element in this array is a function (parameters
+ * described below) that is called for every row in the table, and your logic decides if
+ * it should be included in the filtered data set or not.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{array|object} Data for the row to be processed (same as the original format
+ * that was passed in as the data source, or an array from a DOM data source
+ *
{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
+ * be useful to retrieve the TR element if you need DOM interaction.
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{boolean} Include the row in the filtered result set (true) or not (false)
+ *
+ *
+ *
+ * @type array
+ * @default []
+ *
+ * @example
+ * // The following example shows custom filtering being applied to the fourth column (i.e.
+ * // the aData[3] index) based on two input values from the end-user, matching the data in
+ * // a certain range.
+ * $.fn.dataTableExt.afnFiltering.push(
+ * function( oSettings, aData, iDataIndex ) {
+ * var iMin = document.getElementById('min').value * 1;
+ * var iMax = document.getElementById('max').value * 1;
+ * var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
+ * if ( iMin == "" && iMax == "" ) {
+ * return true;
+ * }
+ * else if ( iMin == "" && iVersion < iMax ) {
+ * return true;
+ * }
+ * else if ( iMin < iVersion && "" == iMax ) {
+ * return true;
+ * }
+ * else if ( iMin < iVersion && iVersion < iMax ) {
+ * return true;
+ * }
+ * return false;
+ * }
+ * );
+ */
+ "afnFiltering": [],
+
+
+ /**
+ * Plug-in sorting functions - this method of sorting is complimentary to the default type
+ * based sorting that DataTables does automatically, allowing much greater control over the
+ * the data that is being used to sort a column. This is useful if you want to do sorting
+ * based on live data (for example the contents of an 'input' element) rather than just the
+ * static string that DataTables knows of. The way these plug-ins work is that you create
+ * an array of the values you wish to be sorted for the column in question and then return
+ * that array. Which pre-sorting function is run here depends on the sSortDataType parameter
+ * that is used for the column (if any). This is the corollary of ofnSearch for sort
+ * data.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{int} Target column index
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{array} Data for the column to be sorted upon
+ *
+ *
+ *
+ *
+ * Note that as of v1.9, it is typically preferable to use mDataProp to prepare data for
+ * the different uses that DataTables can put the data to. Specifically mDataProp when
+ * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
+ * prepare the data as required for the different types. As such, this method is deprecated.
+ * @type array
+ * @default []
+ * @deprecated
+ *
+ * @example
+ * // Updating the cached sorting information with user entered values in HTML input elements
+ * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
+ * {
+ * var aData = [];
+ * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
+ * aData.push( this.value );
+ * } );
+ * return aData;
+ * }
+ */
+ "afnSortData": [],
+
+
+ /**
+ * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
+ * available to DataTables. These feature plug-ins are accessible through the sDom initialisation
+ * option. As such, each feature plug-in must describe a function that is used to initialise
+ * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
+ * of the feature (sFeature). Thus the objects attached to this method must provide:
+ *
+ *
{function} fnInit Initialisation of the plug-in
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{node|null} The element which contains your feature. Note that the return
+ * may also be void if your plug-in does not require to inject any DOM elements
+ * into DataTables control (sDom) - for example this might be useful when
+ * developing a plug-in which allows table control via keyboard entry.
+ *
+ *
+ *
+ *
+ *
{character} cFeature Character that will be matched in sDom - case sensitive
+ *
{string} sFeature Feature name
+ *
+ * @type array
+ * @default []
+ *
+ * @example
+ * // How TableTools initialises itself.
+ * $.fn.dataTableExt.aoFeatures.push( {
+ * "fnInit": function( oSettings ) {
+ * return new TableTools( { "oDTSettings": oSettings } );
+ * },
+ * "cFeature": "T",
+ * "sFeature": "TableTools"
+ * } );
+ */
+ "aoFeatures": [],
+
+
+ /**
+ * Type detection plug-in functions - DataTables utilises types to define how sorting and
+ * filtering behave, and types can be either be defined by the developer (sType for the
+ * column) or they can be automatically detected by the methods in this array. The functions
+ * defined in the array are quite simple, taking a single parameter (the data to analyse)
+ * and returning the type if it is a known type, or null otherwise.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{*} Data from the column cell to be analysed
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{string|null} Data type detected, or null if unknown (and thus pass it
+ * on to the other type detection functions.
+ *
+ *
+ *
+ * @type array
+ * @default []
+ *
+ * @example
+ * // Currency type detection plug-in:
+ * jQuery.fn.dataTableExt.aTypes.push(
+ * function ( sData ) {
+ * var sValidChars = "0123456789.-";
+ * var Char;
+ *
+ * // Check the numeric part
+ * for ( i=1 ; iafnSortData for filtering data.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{*} Data from the column cell to be prepared for filtering
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{string|null} Formatted string that will be used for the filtering.
+ *
+ *
+ *
+ *
+ * Note that as of v1.9, it is typically preferable to use mDataProp to prepare data for
+ * the different uses that DataTables can put the data to. Specifically mDataProp when
+ * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
+ * prepare the data as required for the different types. As such, this method is deprecated.
+ * @type object
+ * @default {}
+ * @deprecated
+ *
+ * @example
+ * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
+ * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
+ * }
+ */
+ "ofnSearch": {},
+
+
+ /**
+ * Container for all private functions in DataTables so they can be exposed externally
+ * @type object
+ * @default {}
+ */
+ "oApi": {},
+
+
+ /**
+ * Storage for the various classes that DataTables uses
+ * @type object
+ * @default {}
+ */
+ "oStdClasses": {},
+
+
+ /**
+ * Storage for the various classes that DataTables uses - jQuery UI suitable
+ * @type object
+ * @default {}
+ */
+ "oJUIClasses": {},
+
+
+ /**
+ * Pagination plug-in methods - The style and controls of the pagination can significantly
+ * impact on how the end user interacts with the data in your table, and DataTables allows
+ * the addition of pagination controls by extending this object, which can then be enabled
+ * through the sPaginationType initialisation parameter. Each pagination type that
+ * is added is an object (the property name of which is what sPaginationType refers
+ * to) that has two properties, both methods that are used by DataTables to update the
+ * control's state.
+ *
+ *
+ * fnInit - Initialisation of the paging controls. Called only during initialisation
+ * of the table. It is expected that this function will add the required DOM elements
+ * to the page for the paging controls to work. The element pointer
+ * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging
+ * controls (note that this is a 2D array to allow for multiple instances of each
+ * DataTables DOM element). It is suggested that you add the controls to this element
+ * as children
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{node} Container into which the pagination controls must be inserted
+ *
{function} Draw callback function - whenever the controls cause a page
+ * change, this method must be called to redraw the table.
+ *
+ *
+ *
+ * Function return:
+ *
+ *
No return required
+ *
+ *
+ *
+ *
+ *
+ * fnInit - This function is called whenever the paging status of the table changes and is
+ * typically used to update classes and/or text of the paging controls to reflex the new
+ * status.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{function} Draw callback function - in case you need to redraw the table again
+ * or attach new event listeners
{int} Sorting match: <0 if first parameter should be sorted lower than
+ * the second parameter, ===0 if the two parameters are equal and >0 if
+ * the first parameter should be sorted height than the second parameter.
+ *
+ *
+ *
+ * @type object
+ * @default {}
+ *
+ * @example
+ * // Case-sensitive string sorting, with no pre-formatting method
+ * $.extend( $.fn.dataTableExt.oSort, {
+ * "string-case-asc": function(x,y) {
+ * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ * },
+ * "string-case-desc": function(x,y) {
+ * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ * }
+ * } );
+ *
+ * @example
+ * // Case-insensitive string sorting, with pre-formatting
+ * $.extend( $.fn.dataTableExt.oSort, {
+ * "string-pre": function(x) {
+ * return x.toLowerCase();
+ * },
+ * "string-asc": function(x,y) {
+ * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ * },
+ * "string-desc": function(x,y) {
+ * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ * }
+ * } );
+ */
+ "oSort": {},
+
+
+ /**
+ * Version string for plug-ins to check compatibility. Allowed format is
+ * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
+ * e are optional
+ * @type string
+ * @default Version number
+ */
+ "sVersion": DataTable.version,
+
+
+ /**
+ * How should DataTables report an error. Can take the value 'alert' or 'throw'
+ * @type string
+ * @default alert
+ */
+ "sErrMode": "alert",
+
+
+ /**
+ * Store information for DataTables to access globally about other instances
+ * @namespace
+ * @private
+ */
+ "_oExternConfig": {
+ /* int:iNextUnique - next unique number for an instance */
+ "iNextUnique": 0
+ }
+ };
+
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * search information for the global filter and individual column filters.
+ * @namespace
+ */
+ DataTable.models.oSearch = {
+ /**
+ * Flag to indicate if the filtering should be case insensitive or not
+ * @type boolean
+ * @default true
+ */
+ "bCaseInsensitive": true,
+
+ /**
+ * Applied search term
+ * @type string
+ * @default Empty string
+ */
+ "sSearch": "",
+
+ /**
+ * Flag to indicate if the search term should be interpreted as a
+ * regular expression (true) or not (false) and therefore and special
+ * regex characters escaped.
+ * @type boolean
+ * @default false
+ */
+ "bRegex": false,
+
+ /**
+ * Flag to indicate if DataTables is to use its smart filtering or not.
+ * @type boolean
+ * @default true
+ */
+ "bSmart": true
+ };
+
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * each individual row. This is the object format used for the settings
+ * aoData array.
+ * @namespace
+ */
+ DataTable.models.oRow = {
+ /**
+ * TR element for the row
+ * @type node
+ * @default null
+ */
+ "nTr": null,
+
+ /**
+ * Data object from the original data source for the row. This is either
+ * an array if using the traditional form of DataTables, or an object if
+ * using mDataProp options. The exact type will depend on the passed in
+ * data from the data source, or will be an array if using DOM a data
+ * source.
+ * @type array|object
+ * @default []
+ */
+ "_aData": [],
+
+ /**
+ * Sorting data cache - this array is ostensibly the same length as the
+ * number of columns (although each index is generated only as it is
+ * needed), and holds the data that is used for sorting each column in the
+ * row. We do this cache generation at the start of the sort in order that
+ * the formatting of the sort data need be done only once for each cell
+ * per sort. This array should not be read from or written to by anything
+ * other than the master sorting methods.
+ * @type array
+ * @default []
+ * @private
+ */
+ "_aSortData": [],
+
+ /**
+ * Array of TD elements that are cached for hidden rows, so they can be
+ * reinserted into the table if a column is made visible again (or to act
+ * as a store if a column is made hidden). Only hidden columns have a
+ * reference in the array. For non-hidden columns the value is either
+ * undefined or null.
+ * @type array nodes
+ * @default []
+ * @private
+ */
+ "_anHidden": [],
+
+ /**
+ * Cache of the class name that DataTables has applied to the row, so we
+ * can quickly look at this variable rather than needing to do a DOM check
+ * on className for the nTr property.
+ * @type string
+ * @default Empty string
+ * @private
+ */
+ "_sRowStripe": ""
+ };
+
+
+
+ /**
+ * Template object for the column information object in DataTables. This object
+ * is held in the settings aoColumns array and contains all the information that
+ * DataTables needs about each individual column.
+ *
+ * Note that this object is related to {@link DataTable.defaults.columns}
+ * but this one is the internal data store for DataTables's cache of columns.
+ * It should NOT be manipulated outside of DataTables. Any configuration should
+ * be done through the initialisation options.
+ * @namespace
+ */
+ DataTable.models.oColumn = {
+ /**
+ * A list of the columns that sorting should occur on when this column
+ * is sorted. That this property is an array allows multi-column sorting
+ * to be defined for a column (for example first name / last name columns
+ * would benefit from this). The values are integers pointing to the
+ * columns to be sorted on (typically it will be a single integer pointing
+ * at itself, but that doesn't need to be the case).
+ * @type array
+ */
+ "aDataSort": null,
+
+ /**
+ * Define the sorting directions that are applied to the column, in sequence
+ * as the column is repeatedly sorted upon - i.e. the first value is used
+ * as the sorting direction when the column if first sorted (clicked on).
+ * Sort it again (click again) and it will move on to the next index.
+ * Repeat until loop.
+ * @type array
+ */
+ "asSorting": null,
+
+ /**
+ * Flag to indicate if the column is searchable, and thus should be included
+ * in the filtering or not.
+ * @type boolean
+ */
+ "bSearchable": null,
+
+ /**
+ * Flag to indicate if the column is sortable or not.
+ * @type boolean
+ */
+ "bSortable": null,
+
+ /**
+ * When using fnRender, you have two options for what to do with the data,
+ * and this property serves as the switch. Firstly, you can have the sorting
+ * and filtering use the rendered value (true - default), or you can have
+ * the sorting and filtering us the original value (false).
+ *
+ * *NOTE* It is it is advisable now to use mDataProp as a function and make
+ * use of the 'type' that it gives, allowing (potentially) different data to
+ * be used for sorting, filtering, display and type detection.
+ * @type boolean
+ * @deprecated
+ */
+ "bUseRendered": null,
+
+ /**
+ * Flag to indicate if the column is currently visible in the table or not
+ * @type boolean
+ */
+ "bVisible": null,
+
+ /**
+ * Flag to indicate to the type detection method if the automatic type
+ * detection should be used, or if a column type (sType) has been specified
+ * @type boolean
+ * @default true
+ * @private
+ */
+ "_bAutoType": true,
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to fnRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available (since it is not when fnRender is called).
+ * @type function
+ * @param {element} nTd The TD node that has been created
+ * @param {*} sData The Data for the cell
+ * @param {array|object} oData The data for the whole row
+ * @param {int} iRow The row index for the aoData data store
+ * @default null
+ */
+ "fnCreatedCell": null,
+
+ /**
+ * Function to get data from a cell in a column. You should never
+ * access data directly through _aData internally in DataTables - always use
+ * the method attached to this property. It allows mDataProp to function as
+ * required. This function is automatically assigned by the column
+ * initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {string} sSpecific The specific data type you want to get -
+ * 'display', 'type' 'filter' 'sort'
+ * @returns {*} The data for the cell from the given row's data
+ * @default null
+ */
+ "fnGetData": null,
+
+ /**
+ * Custom display function that will be called for the display of each cell
+ * in this column.
+ * @type function
+ * @param {object} o Object with the following parameters:
+ * @param {int} o.iDataRow The row in aoData
+ * @param {int} o.iDataColumn The column in question
+ * @param {array} o.aData The data for the row in question
+ * @param {object} o.oSettings The settings object for this DataTables instance
+ * @returns {string} The string you which to use in the display
+ * @default null
+ */
+ "fnRender": null,
+
+ /**
+ * Function to set data for a cell in the column. You should never
+ * set the data directly to _aData internally in DataTables - always use
+ * this method. It allows mDataProp to function as required. This function
+ * is automatically assigned by the column initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {*} sValue Value to set
+ * @default null
+ */
+ "fnSetData": null,
+
+ /**
+ * Property to read the value for the cells in the column from the data
+ * source array / object. If null, then the default content is used, if a
+ * function is given then the return from the function is used.
+ * @type function|int|string|null
+ * @default null
+ */
+ "mDataProp": null,
+
+ /**
+ * Unique header TH/TD element for this column - this is what the sorting
+ * listener is attached to (if sorting is enabled.)
+ * @type node
+ * @default null
+ */
+ "nTh": null,
+
+ /**
+ * Unique footer TH/TD element for this column (if there is one). Not used
+ * in DataTables as such, but can be used for plug-ins to reference the
+ * footer for each column.
+ * @type node
+ * @default null
+ */
+ "nTf": null,
+
+ /**
+ * The class to apply to all TD elements in the table's TBODY for the column
+ * @type string
+ * @default null
+ */
+ "sClass": null,
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * @type string
+ */
+ "sContentPadding": null,
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because mDataProp
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ */
+ "sDefaultContent": null,
+
+ /**
+ * Name for the column, allowing reference to the column by name as well as
+ * by index (needs a lookup to work by name).
+ * @type string
+ */
+ "sName": null,
+
+ /**
+ * Custom sorting data type - defines which of the available plug-ins in
+ * afnSortData the custom sorting will use - if any is defined.
+ * @type string
+ * @default std
+ */
+ "sSortDataType": 'std',
+
+ /**
+ * Class to be applied to the header element when sorting on this column
+ * @type string
+ * @default null
+ */
+ "sSortingClass": null,
+
+ /**
+ * Class to be applied to the header element when sorting on this column -
+ * when jQuery UI theming is used.
+ * @type string
+ * @default null
+ */
+ "sSortingClassJUI": null,
+
+ /**
+ * Title of the column - what is seen in the TH element (nTh).
+ * @type string
+ */
+ "sTitle": null,
+
+ /**
+ * Column sorting and filtering type
+ * @type string
+ * @default null
+ */
+ "sType": null,
+
+ /**
+ * Width of the column
+ * @type string
+ * @default null
+ */
+ "sWidth": null,
+
+ /**
+ * Width of the column when it was first "encountered"
+ * @type string
+ * @default null
+ */
+ "sWidthOrig": null
+ };
+
+
+
+ /**
+ * Initialisation options that can be given to DataTables at initialisation
+ * time.
+ * @namespace
+ */
+ DataTable.defaults = {
+ /**
+ * An array of data to use for the table, passed in at initialisation which
+ * will be used in preference to any data which is already in the DOM. This is
+ * particularly useful for constructing tables purely in Javascript, for
+ * example with a custom Ajax call.
+ * @type array
+ * @default null
+ * @dtopt Option
+ *
+ * @example
+ * // Using a 2D array data source
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "aaData": [
+ * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
+ * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
+ * ],
+ * "aoColumns": [
+ * { "sTitle": "Engine" },
+ * { "sTitle": "Browser" },
+ * { "sTitle": "Platform" },
+ * { "sTitle": "Version" },
+ * { "sTitle": "Grade" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using an array of objects as a data source (mDataProp)
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "aaData": [
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 4.0",
+ * "platform": "Win 95+",
+ * "version": 4,
+ * "grade": "X"
+ * },
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 5.0",
+ * "platform": "Win 95+",
+ * "version": 5,
+ * "grade": "C"
+ * }
+ * ],
+ * "aoColumns": [
+ * { "sTitle": "Engine", "mDataProp": "engine" },
+ * { "sTitle": "Browser", "mDataProp": "browser" },
+ * { "sTitle": "Platform", "mDataProp": "platform" },
+ * { "sTitle": "Version", "mDataProp": "version" },
+ * { "sTitle": "Grade", "mDataProp": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "aaData": null,
+
+
+ /**
+ * If sorting is enabled, then DataTables will perform a first pass sort on
+ * initialisation. You can define which column(s) the sort is performed upon,
+ * and the sorting direction, with this variable. The aaSorting array should
+ * contain an array for each column to be sorted initially containing the
+ * column's index and a direction string ('asc' or 'desc').
+ * @type array
+ * @default [[0,'asc']]
+ * @dtopt Option
+ *
+ * @example
+ * // Sort by 3rd column first, and then 4th column
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aaSorting": [[2,'asc'], [3,'desc']]
+ * } );
+ * } );
+ *
+ * // No initial sorting
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aaSorting": []
+ * } );
+ * } );
+ */
+ "aaSorting": [[0,'asc']],
+
+
+ /**
+ * This parameter is basically identical to the aaSorting parameter, but
+ * cannot be overridden by user interaction with the table. What this means
+ * is that you could have a column (visible or hidden) which the sorting will
+ * always be forced on first - any sorting after that (from the user) will
+ * then be performed as required. This can be useful for grouping rows
+ * together.
+ * @type array
+ * @default null
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aaSortingFixed": [[0,'asc']]
+ * } );
+ * } )
+ */
+ "aaSortingFixed": null,
+
+
+ /**
+ * This parameter allows you to readily specify the entries in the length drop
+ * down menu that DataTables shows when pagination is enabled. It can be
+ * either a 1D array of options which will be used for both the displayed
+ * option and the value, or a 2D array which will use the array in the first
+ * position as the value, and the array in the second position as the
+ * displayed options (useful for language strings such as 'All').
+ * @type array
+ * @default [ 10, 25, 50, 100 ]
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
+ * } );
+ * } );
+ *
+ * @example
+ * // Setting the default display length as well as length menu
+ * // This is likely to be wanted if you remove the '10' option which
+ * // is the iDisplayLength default.
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "iDisplayLength": 25,
+ * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
+ * } );
+ * } );
+ */
+ "aLengthMenu": [ 10, 25, 50, 100 ],
+
+
+ /**
+ * The aoColumns option in the initialisation parameter allows you to define
+ * details about the way individual columns behave. For a full list of
+ * column options that can be set, please see
+ * {@link DataTable.defaults.columns}. Note that if you use aoColumns to
+ * define your columns, you must have an entry in the array for every single
+ * column that you have in your table (these can be null if you don't which
+ * to specify any options).
+ * @member
+ */
+ "aoColumns": null,
+
+ /**
+ * Very similar to aoColumns, aoColumnDefs allows you to target a specific
+ * column, multiple columns, or all columns, using the aTargets property of
+ * each object in the array. This allows great flexibility when creating
+ * tables, as the aoColumnDefs arrays can be of any length, targeting the
+ * columns you specifically want. aoColumnDefs may use any of the column
+ * options available: {@link DataTable.defaults.columns}, but it _must_
+ * have aTargets defined in each object in the array. Values in the aTargets
+ * array may be:
+ *
+ *
a string - class name will be matched on the TH for the column
+ *
0 or a positive integer - column index counting from the left
+ *
a negative integer - column index counting from the right
+ *
the string "_all" - all columns (i.e. assign a default)
+ *
+ * @member
+ */
+ "aoColumnDefs": null,
+
+
+ /**
+ * Basically the same as oSearch, this parameter defines the individual column
+ * filtering state at initialisation time. The array must be of the same size
+ * as the number of columns, and each element be an object with the parameters
+ * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
+ * accepted and the default will be used.
+ * @type array
+ * @default []
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoSearchCols": [
+ * null,
+ * { "sSearch": "My filter" },
+ * null,
+ * { "sSearch": "^[0-9]", "bEscapeRegex": false }
+ * ]
+ * } );
+ * } )
+ */
+ "aoSearchCols": [],
+
+
+ /**
+ * An array of CSS classes that should be applied to displayed rows. This
+ * array may be of any length, and DataTables will apply each class
+ * sequentially, looping when required.
+ * @type array
+ * @default null Will take the values determinted by the oClasses.sStripe*
+ * options
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ]
+ * } );
+ * } )
+ */
+ "asStripeClasses": null,
+
+
+ /**
+ * Enable or disable automatic column width calculation. This can be disabled
+ * as an optimisation (it takes some time to calculate the widths) if the
+ * tables widths are passed in using aoColumns.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bAutoWidth": false
+ * } );
+ * } );
+ */
+ "bAutoWidth": true,
+
+
+ /**
+ * Deferred rendering can provide DataTables with a huge speed boost when you
+ * are using an Ajax or JS data source for the table. This option, when set to
+ * true, will cause DataTables to defer the creation of the table elements for
+ * each row until they are needed for a draw - saving a significant amount of
+ * time.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/arrays.txt",
+ * "bDeferRender": true
+ * } );
+ * } );
+ */
+ "bDeferRender": false,
+
+
+ /**
+ * Replace a DataTable which matches the given selector and replace it with
+ * one which has the properties of the new initialisation object passed. If no
+ * table matches the selector, then the new DataTable will be constructed as
+ * per normal.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false
+ * } );
+ *
+ * // Some time later....
+ * $('#example').dataTable( {
+ * "bFilter": false,
+ * "bDestroy": true
+ * } );
+ * } );
+ */
+ "bDestroy": false,
+
+
+ /**
+ * Enable or disable filtering of data. Filtering in DataTables is "smart" in
+ * that it allows the end user to input multiple words (space separated) and
+ * will match a row containing those words, even if not in the order that was
+ * specified (this allow matching across multiple columns). Note that if you
+ * wish to use filtering in DataTables this must remain 'true' - to remove the
+ * default filtering input box and retain filtering abilities, please use
+ * {@link DataTable.defaults.sDom}.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bFilter": false
+ * } );
+ * } );
+ */
+ "bFilter": true,
+
+
+ /**
+ * Enable or disable the table information display. This shows information
+ * about the data that is currently visible on the page, including information
+ * about filtered data if that action is being performed.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bInfo": false
+ * } );
+ * } );
+ */
+ "bInfo": true,
+
+
+ /**
+ * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
+ * slightly different and additional mark-up from what DataTables has
+ * traditionally used).
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bJQueryUI": true
+ * } );
+ * } );
+ */
+ "bJQueryUI": false,
+
+
+ /**
+ * Allows the end user to select the size of a formatted page from a select
+ * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bLengthChange": false
+ * } );
+ * } );
+ */
+ "bLengthChange": true,
+
+
+ /**
+ * Enable or disable pagination.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bPaginate": false
+ * } );
+ * } );
+ */
+ "bPaginate": true,
+
+
+ /**
+ * Enable or disable the display of a 'processing' indicator when the table is
+ * being processed (e.g. a sort). This is particularly useful for tables with
+ * large amounts of data where it can take a noticeable amount of time to sort
+ * the entries.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bProcessing": true
+ * } );
+ * } );
+ */
+ "bProcessing": false,
+
+
+ /**
+ * Retrieve the DataTables object for the given selector. Note that if the
+ * table has already been initialised, this parameter will cause DataTables
+ * to simply return the object that has already been set up - it will not take
+ * account of any changes you might have made to the initialisation object
+ * passed to DataTables (setting this parameter to true is an acknowledgement
+ * that you understand this). bDestroy can be used to reinitialise a table if
+ * you need.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * initTable();
+ * tableActions();
+ * } );
+ *
+ * function initTable ()
+ * {
+ * return $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false,
+ * "bRetrieve": true
+ * } );
+ * }
+ *
+ * function tableActions ()
+ * {
+ * var oTable = initTable();
+ * // perform API operations with oTable
+ * }
+ */
+ "bRetrieve": false,
+
+
+ /**
+ * Indicate if DataTables should be allowed to set the padding / margin
+ * etc for the scrolling header elements or not. Typically you will want
+ * this.
+ * @type boolean
+ * @default true
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bScrollAutoCss": false,
+ * "sScrollY": "200px"
+ * } );
+ * } );
+ */
+ "bScrollAutoCss": true,
+
+
+ /**
+ * When vertical (y) scrolling is enabled, DataTables will force the height of
+ * the table's viewport to the given height at all times (useful for layout).
+ * However, this can look odd when filtering data down to a small data set,
+ * and the footer is left "floating" further down. This parameter (when
+ * enabled) will cause DataTables to collapse the table's viewport down when
+ * the result set will fit within the given Y height.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "sScrollY": "200",
+ * "bScrollCollapse": true
+ * } );
+ * } );
+ */
+ "bScrollCollapse": false,
+
+
+ /**
+ * Enable infinite scrolling for DataTables (to be used in combination with
+ * sScrollY). Infinite scrolling means that DataTables will continually load
+ * data as a user scrolls through a table, which is very useful for large
+ * dataset. This cannot be used with pagination, which is automatically
+ * disabled. Note - the Scroller extra for DataTables is recommended in
+ * in preference to this option.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bScrollInfinite": true,
+ * "bScrollCollapse": true,
+ * "sScrollY": "200px"
+ * } );
+ * } );
+ */
+ "bScrollInfinite": false,
+
+
+ /**
+ * Configure DataTables to use server-side processing. Note that the
+ * sAjaxSource parameter must also be given in order to give DataTables a
+ * source to obtain the required data for each draw.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "xhr.php"
+ * } );
+ * } );
+ */
+ "bServerSide": false,
+
+
+ /**
+ * Enable or disable sorting of columns. Sorting of individual columns can be
+ * disabled by the "bSortable" option for each column.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bSort": false
+ * } );
+ * } );
+ */
+ "bSort": true,
+
+
+ /**
+ * Allows control over whether DataTables should use the top (true) unique
+ * cell that is found for a single column, or the bottom (false - default).
+ * This is useful when using complex headers.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bSortCellsTop": true
+ * } );
+ * } );
+ */
+ "bSortCellsTop": false,
+
+
+ /**
+ * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and
+ * 'sorting_3' to the columns which are currently being sorted on. This is
+ * presented as a feature switch as it can increase processing time (while
+ * classes are removed and added) so for large data sets you might want to
+ * turn this off.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bSortClasses": false
+ * } );
+ * } );
+ */
+ "bSortClasses": true,
+
+
+ /**
+ * Enable or disable state saving. When enabled a cookie will be used to save
+ * table display information such as pagination information, display length,
+ * filtering and sorting. As such when the end user reloads the page the
+ * display display will match what thy had previously set up.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bStateSave": true
+ * } );
+ * } );
+ */
+ "bStateSave": false,
+
+
+ /**
+ * Customise the cookie and / or the parameters being stored when using
+ * DataTables with state saving enabled. This function is called whenever
+ * the cookie is modified, and it expects a fully formed cookie string to be
+ * returned. Note that the data object passed in is a Javascript object which
+ * must be converted to a string (JSON.stringify for example).
+ * @type function
+ * @param {string} sName Name of the cookie defined by DataTables
+ * @param {object} oData Data to be stored in the cookie
+ * @param {string} sExpires Cookie expires string
+ * @param {string} sPath Path of the cookie to set
+ * @returns {string} Cookie formatted string (which should be encoded by
+ * using encodeURIComponent())
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "fnCookieCallback": function (sName, oData, sExpires, sPath) {
+ * // Customise oData or sName or whatever else here
+ * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
+ * }
+ * } );
+ * } );
+ */
+ "fnCookieCallback": null,
+
+
+ /**
+ * This function is called when a TR element is created (and all TD child
+ * elements have been inserted), or registered if using a DOM source, allowing
+ * manipulation of the TR element (adding classes etc).
+ * @type function
+ * @param {node} nRow "TR" element for the current row
+ * @param {array} aData Raw data array for this row
+ * @param {int} iDataIndex The index of this row in aoData
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "fnCreatedRow": function( nRow, aData, iDataIndex ) {
+ * // Bold the grade for all 'A' grade browsers
+ * if ( aData[4] == "A" )
+ * {
+ * $('td:eq(4)', nRow).html( 'A' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnCreatedRow": null,
+
+
+ /**
+ * This function is called on every 'draw' event, and allows you to
+ * dynamically modify any aspect you want about the created DOM.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fnDrawCallback": function( oSettings ) {
+ * alert( 'DataTables has redrawn the table' );
+ * }
+ * } );
+ * } );
+ */
+ "fnDrawCallback": null,
+
+
+ /**
+ * Identical to fnHeaderCallback() but for the table footer this function
+ * allows you to modify the table footer on every 'draw' even.
+ * @type function
+ * @param {node} nFoot "TR" element for the footer
+ * @param {array} aData Full table data (as derived from the original HTML)
+ * @param {int} iStart Index for the current display starting point in the
+ * display array
+ * @param {int} iEnd Index for the current display ending point in the
+ * display array
+ * @param {array int} aiDisplay Index array to translate the visual position
+ * to the full data array
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
+ * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
+ * }
+ * } );
+ * } )
+ */
+ "fnFooterCallback": null,
+
+
+ /**
+ * When rendering large numbers in the information element for the table
+ * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
+ * to have a comma separator for the 'thousands' units (e.g. 1 million is
+ * rendered as "1,000,000") to help readability for the end user. This
+ * function will override the default method DataTables uses.
+ * @type function
+ * @member
+ * @param {int} iIn number to be formatted
+ * @returns {string} formatted string for DataTables to show the number
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "fnFormatNumber": function ( iIn ) {
+ * if ( iIn < 1000 ) {
+ * return iIn;
+ * } else {
+ * var
+ * s=(iIn+""),
+ * a=s.split(""), out="",
+ * iLen=s.length;
+ *
+ * for ( var i=0 ; i<iLen ; i++ ) {
+ * if ( i%3 === 0 && i !== 0 ) {
+ * out = "'"+out;
+ * }
+ * out = a[iLen-i-1]+out;
+ * }
+ * }
+ * return out;
+ * };
+ * } );
+ * } );
+ */
+ "fnFormatNumber": function ( iIn ) {
+ if ( iIn < 1000 )
+ {
+ // A small optimisation for what is likely to be the majority of use cases
+ return iIn;
+ }
+
+ var s=(iIn+""), a=s.split(""), out="", iLen=s.length;
+
+ for ( var i=0 ; iA' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnRowCallback": null,
+
+
+ /**
+ * This parameter allows you to override the default function which obtains
+ * the data from the server ($.getJSON) so something more suitable for your
+ * application. For example you could use POST data, or pull information from
+ * a Gears or AIR database.
+ * @type function
+ * @member
+ * @param {string} sSource HTTP source to obtain the data from (sAjaxSource)
+ * @param {array} aoData A key/value pair object containing the data to send
+ * to the server
+ * @param {function} fnCallback to be called on completion of the data get
+ * process that will draw the data on the page.
+ * @param {object} oSettings DataTables settings object
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ *
+ * @example
+ * // POST data to server
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bProcessing": true,
+ * "bServerSide": true,
+ * "sAjaxSource": "xhr.php",
+ * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
+ * oSettings.jqXHR = $.ajax( {
+ * "dataType": 'json',
+ * "type": "POST",
+ * "url": sSource,
+ * "data": aoData,
+ * "success": fnCallback
+ * } );
+ * }
+ * } );
+ * } );
+ */
+ "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) {
+ oSettings.jqXHR = $.ajax( {
+ "url": sUrl,
+ "data": aoData,
+ "success": function (json) {
+ $(oSettings.oInstance).trigger('xhr', oSettings);
+ fnCallback( json );
+ },
+ "dataType": "json",
+ "cache": false,
+ "type": oSettings.sServerMethod,
+ "error": function (xhr, error, thrown) {
+ if ( error == "parsererror" ) {
+ oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+
+ "server could not be parsed. This is caused by a JSON formatting error." );
+ }
+ }
+ } );
+ },
+
+
+ /**
+ * It is often useful to send extra data to the server when making an Ajax
+ * request - for example custom filtering information, and this callback
+ * function makes it trivial to send extra information to the server. The
+ * passed in parameter is the data set that has been constructed by
+ * DataTables, and you can add to this or modify it as you require.
+ * @type function
+ * @param {array} aoData Data array (array of objects which are name/value
+ * pairs) that has been constructed by DataTables and will be sent to the
+ * server. In the case of Ajax sourced data with server-side processing
+ * this will be an empty array, for server-side processing there will be a
+ * significant number of parameters!
+ * @returns {undefined} Ensure that you modify the aoData array passed in,
+ * as this is passed by reference.
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bProcessing": true,
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/server_processing.php",
+ * "fnServerParams": function ( aoData ) {
+ * aoData.push( { "name": "more_data", "value": "my_value" } );
+ * }
+ * } );
+ * } );
+ */
+ "fnServerParams": null,
+
+
+ /**
+ * Load the table state. With this function you can define from where, and how, the
+ * state of a table is loaded. By default DataTables will load from its state saving
+ * cookie, but you might wish to use local storage (HTML5) or a server-side database.
+ * @type function
+ * @member
+ * @param {object} oSettings DataTables settings object
+ * @return {object} The DataTables state object to be loaded
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoad": function (oSettings) {
+ * var o;
+ *
+ * // Send an Ajax request to the server to get the data. Note that
+ * // this is a synchronous request.
+ * $.ajax( {
+ * "url": "/state_load",
+ * "async": false,
+ * "dataType": "json",
+ * "success": function (json) {
+ * o = json;
+ * }
+ * } );
+ *
+ * return o;
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoad": function ( oSettings ) {
+ var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );
+ var oData;
+
+ try {
+ oData = (typeof $.parseJSON === 'function') ?
+ $.parseJSON(sData) : eval( '('+sData+')' );
+ } catch (e) {
+ oData = null;
+ }
+
+ return oData;
+ },
+
+
+ /**
+ * Callback which allows modification of the saved state prior to loading that state.
+ * This callback is called when the table is loading state from the stored data, but
+ * prior to the settings object being modified by the saved state. Note that for
+ * plug-in authors, you should use the 'stateLoadParams' event to load parameters for
+ * a plug-in.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object that is to be loaded
+ * @dtopt Callbacks
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never loaded
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoadParams": function (oSettings, oData) {
+ * oData.oSearch.sSearch = "";
+ * } );
+ * } );
+ *
+ * @example
+ * // Disallow state loading by returning false
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoadParams": function (oSettings, oData) {
+ * return false;
+ * } );
+ * } );
+ */
+ "fnStateLoadParams": null,
+
+
+ /**
+ * Callback that is called when the state has been loaded from the state saving method
+ * and the DataTables settings object has been modified as a result of the loaded state.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object that was loaded
+ * @dtopt Callbacks
+ *
+ * @example
+ * // Show an alert with the filtering value that was saved
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoaded": function (oSettings, oData) {
+ * alert( 'Saved filter was: '+oData.oSearch.sSearch );
+ * } );
+ * } );
+ */
+ "fnStateLoaded": null,
+
+
+ /**
+ * Save the table state. This function allows you to define where and how the state
+ * information for the table is stored - by default it will use a cookie, but you
+ * might want to use local storage (HTML5) or a server-side database.
+ * @type function
+ * @member
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object to be saved
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateSave": function (oSettings, oData) {
+ * // Send an Ajax request to the server with the state object
+ * $.ajax( {
+ * "url": "/state_save",
+ * "data": oData,
+ * "dataType": "json",
+ * "method": "POST"
+ * "success": function () {}
+ * } );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateSave": function ( oSettings, oData ) {
+ this.oApi._fnCreateCookie(
+ oSettings.sCookiePrefix+oSettings.sInstance,
+ this.oApi._fnJsonString(oData),
+ oSettings.iCookieDuration,
+ oSettings.sCookiePrefix,
+ oSettings.fnCookieCallback
+ );
+ },
+
+
+ /**
+ * Callback which allows modification of the state to be saved. Called when the table
+ * has changed state a new state save is required. This method allows modification of
+ * the state saving object prior to actually doing the save, including addition or
+ * other state properties or modification. Note that for plug-in authors, you should
+ * use the 'stateSaveParams' event to save parameters for a plug-in.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object to be saved
+ * @dtopt Callbacks
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never saved
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateSaveParams": function (oSettings, oData) {
+ * oData.oSearch.sSearch = "";
+ * } );
+ * } );
+ */
+ "fnStateSaveParams": null,
+
+
+ /**
+ * Duration of the cookie which is used for storing session information. This
+ * value is given in seconds.
+ * @type int
+ * @default 7200 (2 hours)
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iCookieDuration": 60*60*24 // 1 day
+ * } );
+ * } )
+ */
+ "iCookieDuration": 7200,
+
+
+ /**
+ * When enabled DataTables will not make a request to the server for the first
+ * page draw - rather it will use the data already on the page (no sorting etc
+ * will be applied to it), thus saving on an XHR at load time. iDeferLoading
+ * is used to indicate that deferred loading is required, but it is also used
+ * to tell DataTables how many records there are in the full table (allowing
+ * the information element and pagination to be displayed correctly). In the case
+ * where a filtering is applied to the table on initial load, this can be
+ * indicated by giving the parameter as an array, where the first element is
+ * the number of records available after filtering and the second element is the
+ * number of records without filtering (allowing the table information element
+ * to be shown correctly).
+ * @type int | array
+ * @default null
+ * @dtopt Options
+ *
+ * @example
+ * // 57 records available in the table, no filtering applied
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/server_processing.php",
+ * "iDeferLoading": 57
+ * } );
+ * } );
+ *
+ * @example
+ * // 57 records after filtering, 100 without filtering (an initial filter applied)
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/server_processing.php",
+ * "iDeferLoading": [ 57, 100 ],
+ * "oSearch": {
+ * "sSearch": "my_filter"
+ * }
+ * } );
+ * } );
+ */
+ "iDeferLoading": null,
+
+
+ /**
+ * Number of rows to display on a single page when using pagination. If
+ * feature enabled (bLengthChange) then the end user will be able to override
+ * this to a custom setting using a pop-up menu.
+ * @type int
+ * @default 10
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iDisplayLength": 50
+ * } );
+ * } )
+ */
+ "iDisplayLength": 10,
+
+
+ /**
+ * Define the starting point for data display when using DataTables with
+ * pagination. Note that this parameter is the number of records, rather than
+ * the page number, so if you have 10 records per page and want to start on
+ * the third page, it should be "20".
+ * @type int
+ * @default 0
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iDisplayStart": 20
+ * } );
+ * } )
+ */
+ "iDisplayStart": 0,
+
+
+ /**
+ * The scroll gap is the amount of scrolling that is left to go before
+ * DataTables will load the next 'page' of data automatically. You typically
+ * want a gap which is big enough that the scrolling will be smooth for the
+ * user, while not so large that it will load more data than need.
+ * @type int
+ * @default 100
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bScrollInfinite": true,
+ * "bScrollCollapse": true,
+ * "sScrollY": "200px",
+ * "iScrollLoadGap": 50
+ * } );
+ * } );
+ */
+ "iScrollLoadGap": 100,
+
+
+ /**
+ * By default DataTables allows keyboard navigation of the table (sorting, paging,
+ * and filtering) by adding a tabindex attribute to the required elements. This
+ * allows you to tab through the controls and press the enter key to activate them.
+ * The tabindex is default 0, meaning that the tab follows the flow of the document.
+ * You can overrule this using this parameter if you wish. Use a value of -1 to
+ * disable built-in keyboard navigation.
+ * @type int
+ * @default 0
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "iTabIndex": 1
+ * } );
+ * } );
+ */
+ "iTabIndex": 0,
+
+
+ /**
+ * All strings that DataTables uses in the user interface that it creates
+ * are defined in this object, allowing you to modified them individually or
+ * completely replace them all as required.
+ * @namespace
+ */
+ "oLanguage": {
+ /**
+ * Strings that are used for WAI-ARIA labels and controls only (these are not
+ * actually visible on the page, but will be read by screenreaders, and thus
+ * must be internationalised as well).
+ * @namespace
+ */
+ "oAria": {
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted ascending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oAria": {
+ * "sSortAscending": " - click/return to sort ascending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortAscending": ": activate to sort column ascending",
+
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted descending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oAria": {
+ * "sSortDescending": " - click/return to sort descending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortDescending": ": activate to sort column descending"
+ },
+
+ /**
+ * Pagination string used by DataTables for the two built-in pagination
+ * control types ("two_button" and "full_numbers")
+ * @namespace
+ */
+ "oPaginate": {
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the first page.
+ * @type string
+ * @default First
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sFirst": "First page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sFirst": "First",
+
+
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the last page.
+ * @type string
+ * @default Last
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sLast": "Last page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sLast": "Last",
+
+
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the next page.
+ * @type string
+ * @default Next
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sNext": "Next page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sNext": "Next",
+
+
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the previous page.
+ * @type string
+ * @default Previous
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sPrevious": "Previous page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sPrevious": "Previous"
+ },
+
+ /**
+ * This string is shown in preference to sZeroRecords when the table is
+ * empty of data (regardless of filtering). Note that this is an optional
+ * parameter - if it is not given, the value of sZeroRecords will be used
+ * instead (either the default or given value).
+ * @type string
+ * @default No data available in table
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sEmptyTable": "No data available in table"
+ * }
+ * } );
+ * } );
+ */
+ "sEmptyTable": "No data available in table",
+
+
+ /**
+ * This string gives information to the end user about the information that
+ * is current on display on the page. The _START_, _END_ and _TOTAL_
+ * variables are all dynamically replaced as the table display updates, and
+ * can be freely moved or removed as the language requirements change.
+ * @type string
+ * @default Showing _START_ to _END_ of _TOTAL_ entries
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
+ * }
+ * } );
+ * } );
+ */
+ "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
+
+
+ /**
+ * Display information string for when the table is empty. Typically the
+ * format of this string should match sInfo.
+ * @type string
+ * @default Showing 0 to 0 of 0 entries
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoEmpty": "No entries to show"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoEmpty": "Showing 0 to 0 of 0 entries",
+
+
+ /**
+ * When a user filters the information in a table, this string is appended
+ * to the information (sInfo) to give an idea of how strong the filtering
+ * is. The variable _MAX_ is dynamically updated.
+ * @type string
+ * @default (filtered from _MAX_ total entries)
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoFiltered": " - filtering from _MAX_ records"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoFiltered": "(filtered from _MAX_ total entries)",
+
+
+ /**
+ * If can be useful to append extra information to the info string at times,
+ * and this variable does exactly that. This information will be appended to
+ * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
+ * being used) at all times.
+ * @type string
+ * @default Empty string
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoPostFix": "All records shown are derived from real information."
+ * }
+ * } );
+ * } );
+ */
+ "sInfoPostFix": "",
+
+
+ /**
+ * DataTables has a build in number formatter (fnFormatNumber) which is used
+ * to format large numbers that are used in the table information. By
+ * default a comma is used, but this can be trivially changed to any
+ * character you wish with this parameter.
+ * @type string
+ * @default ,
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoThousands": "'"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoThousands": ",",
+
+
+ /**
+ * Detail the action that will be taken when the drop down menu for the
+ * pagination length option is changed. The '_MENU_' variable is replaced
+ * with a default select list of 10, 25, 50 and 100, and can be replaced
+ * with a custom select box if required.
+ * @type string
+ * @default Show _MENU_ entries
+ * @dtopt Language
+ *
+ * @example
+ * // Language change only
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sLengthMenu": "Display _MENU_ records"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Language and options change
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sLengthMenu": 'Display '+
+ * ''+
+ * ''+
+ * ''+
+ * ''+
+ * ''+
+ * ''+
+ * ' records'
+ * }
+ * } );
+ * } );
+ */
+ "sLengthMenu": "Show _MENU_ entries",
+
+
+ /**
+ * When using Ajax sourced data and during the first draw when DataTables is
+ * gathering the data, this message is shown in an empty row in the table to
+ * indicate to the end user the the data is being loaded. Note that this
+ * parameter is not used when loading data by server-side processing, just
+ * Ajax sourced data with client-side processing.
+ * @type string
+ * @default Loading...
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sLoadingRecords": "Please wait - loading..."
+ * }
+ * } );
+ * } );
+ */
+ "sLoadingRecords": "Loading...",
+
+
+ /**
+ * Text which is displayed when the table is processing a user action
+ * (usually a sort command or similar).
+ * @type string
+ * @default Processing...
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sProcessing": "DataTables is currently busy"
+ * }
+ * } );
+ * } );
+ */
+ "sProcessing": "Processing...",
+
+
+ /**
+ * Details the actions that will be taken when the user types into the
+ * filtering input text box. The variable "_INPUT_", if used in the string,
+ * is replaced with the HTML text box for the filtering input allowing
+ * control over where it appears in the string. If "_INPUT_" is not given
+ * then the input box is appended to the string automatically.
+ * @type string
+ * @default Search:
+ * @dtopt Language
+ *
+ * @example
+ * // Input text box will be appended at the end automatically
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sSearch": "Filter records:"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Specify where the filter should appear
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sSearch": "Apply filter _INPUT_ to table"
+ * }
+ * } );
+ * } );
+ */
+ "sSearch": "Search:",
+
+
+ /**
+ * All of the language information can be stored in a file on the
+ * server-side, which DataTables will look up if this parameter is passed.
+ * It must store the URL of the language file, which is in a JSON format,
+ * and the object has the same properties as the oLanguage object in the
+ * initialiser object (i.e. the above parameters). Please refer to one of
+ * the example language files to see how this works in action.
+ * @type string
+ * @default Empty string - i.e. disabled
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt"
+ * }
+ * } );
+ * } );
+ */
+ "sUrl": "",
+
+
+ /**
+ * Text shown inside the table records when the is no information to be
+ * displayed after filtering. sEmptyTable is shown when there is simply no
+ * information in the table at all (regardless of filtering).
+ * @type string
+ * @default No matching records found
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sZeroRecords": "No records to display"
+ * }
+ * } );
+ * } );
+ */
+ "sZeroRecords": "No matching records found"
+ },
+
+
+ /**
+ * This parameter allows you to have define the global filtering state at
+ * initialisation time. As an object the "sSearch" parameter must be
+ * defined, but all other parameters are optional. When "bRegex" is true,
+ * the search string will be treated as a regular expression, when false
+ * (default) it will be treated as a straight string. When "bSmart"
+ * DataTables will use it's smart filtering methods (to word match at
+ * any point in the data), when false this will not be done.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oSearch": {"sSearch": "Initial search"}
+ * } );
+ * } )
+ */
+ "oSearch": $.extend( {}, DataTable.models.oSearch ),
+
+
+ /**
+ * By default DataTables will look for the property 'aaData' when obtaining
+ * data from an Ajax source or for server-side processing - this parameter
+ * allows that property to be changed. You can use Javascript dotted object
+ * notation to get a data source for multiple levels of nesting.
+ * @type string
+ * @default aaData
+ * @dtopt Options
+ * @dtopt Server-side
+ *
+ * @example
+ * // Get data from { "data": [...] }
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/data.txt",
+ * "sAjaxDataProp": "data"
+ * } );
+ * } );
+ *
+ * @example
+ * // Get data from { "data": { "inner": [...] } }
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/data.txt",
+ * "sAjaxDataProp": "data.inner"
+ * } );
+ * } );
+ */
+ "sAjaxDataProp": "aaData",
+
+
+ /**
+ * You can instruct DataTables to load data from an external source using this
+ * parameter (use aData if you want to pass data in you already have). Simply
+ * provide a url a JSON object can be obtained from. This object must include
+ * the parameter 'aaData' which is the data source for the table.
+ * @type string
+ * @default null
+ * @dtopt Options
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
+ * } );
+ * } )
+ */
+ "sAjaxSource": null,
+
+
+ /**
+ * This parameter can be used to override the default prefix that DataTables
+ * assigns to a cookie when state saving is enabled.
+ * @type string
+ * @default SpryMedia_DataTables_
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "sCookiePrefix": "my_datatable_",
+ * } );
+ * } );
+ */
+ "sCookiePrefix": "SpryMedia_DataTables_",
+
+
+ /**
+ * This initialisation variable allows you to specify exactly where in the
+ * DOM you want DataTables to inject the various controls it adds to the page
+ * (for example you might want the pagination controls at the top of the
+ * table). DIV elements (with or without a custom class) can also be added to
+ * aid styling. The follow syntax is used:
+ *
+ *
+ * @type string
+ * @default lfrtip (when bJQueryUI is false)or
+ * <"H"lfr>t<"F"ip> (when bJQueryUI is true)
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "sDom": '<"top"i>rt<"bottom"flp><"clear">'
+ * } );
+ * } );
+ */
+ "sDom": "lfrtip",
+
+
+ /**
+ * DataTables features two different built-in pagination interaction methods
+ * ('two_button' or 'full_numbers') which present different page controls to
+ * the end user. Further methods can be added using the API (see below).
+ * @type string
+ * @default two_button
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sPaginationType": "full_numbers"
+ * } );
+ * } )
+ */
+ "sPaginationType": "two_button",
+
+
+ /**
+ * Enable horizontal scrolling. When a table is too wide to fit into a certain
+ * layout, or you have a large number of columns in the table, you can enable
+ * x-scrolling to show the table in a viewport, which can be scrolled. This
+ * property can be any CSS unit, or a number (in which case it will be treated
+ * as a pixel measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "sScrollX": "100%",
+ * "bScrollCollapse": true
+ * } );
+ * } );
+ */
+ "sScrollX": "",
+
+
+ /**
+ * This property can be used to force a DataTable to use more width than it
+ * might otherwise do when x-scrolling is enabled. For example if you have a
+ * table which requires to be well spaced, this parameter is useful for
+ * "over-sizing" the table, and thus forcing scrolling. This property can by
+ * any CSS unit, or a number (in which case it will be treated as a pixel
+ * measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "sScrollX": "100%",
+ * "sScrollXInner": "110%"
+ * } );
+ * } );
+ */
+ "sScrollXInner": "",
+
+
+ /**
+ * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
+ * to the given height, and enable scrolling for any data which overflows the
+ * current viewport. This can be used as an alternative to paging to display
+ * a lot of data in a small area (although paging and scrolling can both be
+ * enabled at the same time). This property can be any CSS unit, or a number
+ * (in which case it will be treated as a pixel measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false
+ * } );
+ * } );
+ */
+ "sScrollY": "",
+
+
+ /**
+ * Set the HTTP method that is used to make the Ajax call for server-side
+ * processing or Ajax sourced data.
+ * @type string
+ * @default GET
+ * @dtopt Options
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/post.php",
+ * "sServerMethod": "POST"
+ * } );
+ * } );
+ */
+ "sServerMethod": "GET"
+ };
+
+
+
+ /**
+ * Column options that can be given to DataTables at initialisation time.
+ * @namespace
+ */
+ DataTable.defaults.columns = {
+ /**
+ * Allows a column's sorting to take multiple columns into account when
+ * doing a sort. For example first name / last name columns make sense to
+ * do a multi-column sort over the two columns.
+ * @type array
+ * @default null Takes the value of the column index automatically
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
+ * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
+ * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "aDataSort": [ 0, 1 ] },
+ * { "aDataSort": [ 1, 0 ] },
+ * { "aDataSort": [ 2, 3, 4 ] },
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "aDataSort": null,
+
+
+ /**
+ * You can control the default sorting direction, and even alter the behaviour
+ * of the sort handler (i.e. only allow ascending sorting etc) using this
+ * parameter.
+ * @type array
+ * @default [ 'asc', 'desc' ]
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
+ * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
+ * { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * { "asSorting": [ "asc" ] },
+ * { "asSorting": [ "desc", "asc", "asc" ] },
+ * { "asSorting": [ "desc" ] },
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "asSorting": [ 'asc', 'desc' ],
+
+
+ /**
+ * Enable or disable filtering on the data in this column.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "bSearchable": false, "aTargets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "bSearchable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSearchable": true,
+
+
+ /**
+ * Enable or disable sorting on this column.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "bSortable": false, "aTargets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "bSortable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSortable": true,
+
+
+ /**
+ * When using fnRender() for a column, you may wish to use the original data
+ * (before rendering) for sorting and filtering (the default is to used the
+ * rendered data that the user can see). This may be useful for dates etc.
+ *
+ * *NOTE* It is it is advisable now to use mDataProp as a function and make
+ * use of the 'type' that it gives, allowing (potentially) different data to
+ * be used for sorting, filtering, display and type detection.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * {
+ * "fnRender": function ( oObj ) {
+ * return oObj.aData[0] +' '+ oObj.aData[3];
+ * },
+ * "bUseRendered": false,
+ * "aTargets": [ 0 ]
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * {
+ * "fnRender": function ( oObj ) {
+ * return oObj.aData[0] +' '+ oObj.aData[3];
+ * },
+ * "bUseRendered": false
+ * },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "bUseRendered": true,
+
+
+ /**
+ * Enable or disable the display of this column.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "bVisible": false, "aTargets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "bVisible": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bVisible": true,
+
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to fnRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available (since it is not when fnRender is called).
+ * @type function
+ * @param {element} nTd The TD node that has been created
+ * @param {*} sData The Data for the cell
+ * @param {array|object} oData The data for the whole row
+ * @param {int} iRow The row index for the aoData data store
+ * @param {int} iCol The column index for aoColumns
+ * @dtopt Columns
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [ {
+ * "aTargets": [3],
+ * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
+ * if ( sData == "1.7" ) {
+ * $(nTd).css('color', 'blue')
+ * }
+ * }
+ * } ]
+ * });
+ * } );
+ */
+ "fnCreatedCell": null,
+
+
+ /**
+ * Custom display function that will be called for the display of each cell in
+ * this column.
+ * @type function
+ * @param {object} o Object with the following parameters:
+ * @param {int} o.iDataRow The row in aoData
+ * @param {int} o.iDataColumn The column in question
+ * @param {array} o.aData The data for the row in question
+ * @param {object} o.oSettings The settings object for this DataTables instance
+ * @param {object} o.mDataProp The data property used for this column
+ * @param {*} val The current cell value
+ * @returns {string} The string you which to use in the display
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * {
+ * "fnRender": function ( o, val ) {
+ * return o.aData[0] +' '+ o.aData[3];
+ * },
+ * "aTargets": [ 0 ]
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "fnRender": function ( o, val ) {
+ * return o.aData[0] +' '+ o.aData[3];
+ * } },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "fnRender": null,
+
+
+ /**
+ * The column index (starting from 0!) that you wish a sort to be performed
+ * upon when this column is selected for sorting. This can be used for sorting
+ * on hidden columns for example.
+ * @type int
+ * @default -1 Use automatically calculated column index
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "iDataSort": 1, "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "iDataSort": 1 },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "iDataSort": -1,
+
+
+ /**
+ * This property can be used to read data from any JSON data source property,
+ * including deeply nested objects / properties. mDataProp can be given in a
+ * number of different ways which effect its behaviour:
+ *
+ *
integer - treated as an array index for the data source. This is the
+ * default that DataTables uses (incrementally increased for each column).
+ *
string - read an object property from the data source. Note that you can
+ * use Javascript dotted notation to read deep properties/arrays from the
+ * data source.
+ *
null - the sDefaultContent option will be used for the cell (null
+ * by default, so you will need to specify the default content you want -
+ * typically an empty string). This can be useful on generated columns such
+ * as edit / delete action columns.
+ *
function - the function given will be executed whenever DataTables
+ * needs to set or get the data for a cell in the column. The function
+ * takes three parameters:
+ *
+ *
{array|object} The data source for the row
+ *
{string} The type call data requested - this will be 'set' when
+ * setting data or 'filter', 'display', 'type', 'sort' or undefined when
+ * gathering data. Note that when undefined is given for the type
+ * DataTables expects to get the raw data for the object back
+ *
{*} Data to set when the second parameter is 'set'.
+ *
+ * The return value from the function is not required when 'set' is the type
+ * of call, but otherwise the return is what will be used for the data
+ * requested.
+ *
+ * @type string|int|function|null
+ * @default null Use automatically calculated column index
+ * @dtopt Columns
+ *
+ * @example
+ * // Read table data from objects
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/deep.txt",
+ * "aoColumns": [
+ * { "mDataProp": "engine" },
+ * { "mDataProp": "browser" },
+ * { "mDataProp": "platform.inner" },
+ * { "mDataProp": "platform.details.0" },
+ * { "mDataProp": "platform.details.1" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using mDataProp as a function to provide different information for
+ * // sorting, filtering and display. In this case, currency (price)
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * {
+ * "aTargets": [ 0 ],
+ * "mDataProp": function ( source, type, val ) {
+ * if (type === 'set') {
+ * source.price = val;
+ * // Store the computed dislay and filter values for efficiency
+ * source.price_display = val=="" ? "" : "$"+numberFormat(val);
+ * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
+ * return;
+ * }
+ * else if (type === 'display') {
+ * return source.price_display;
+ * }
+ * else if (type === 'filter') {
+ * return source.price_filter;
+ * }
+ * // 'sort', 'type' and undefined all just use the integer
+ * return source.price;
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "mDataProp": null,
+
+
+ /**
+ * Change the cell type created for the column - either TD cells or TH cells. This
+ * can be useful as TH cells have semantic meaning in the table body, allowing them
+ * to act as a header for a row (you may wish to add scope='row' to the TH elements).
+ * @type string
+ * @default td
+ * @dtopt Columns
+ *
+ * @example
+ * // Make the first column use TH cells
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * {
+ * "aTargets": [ 0 ],
+ * "sCellType": "th"
+ * ]
+ * } );
+ * } );
+ */
+ "sCellType": "td",
+
+
+ /**
+ * Class to give to each cell in this column.
+ * @type string
+ * @default Empty string
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sClass": "my_class", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sClass": "my_class" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sClass": "",
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * Generally you shouldn't need this, and it is not documented on the
+ * general DataTables.net documentation
+ * @type string
+ * @default Empty string
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "sContentPadding": "mmm"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sContentPadding": "",
+
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because mDataProp
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * {
+ * "mDataProp": null,
+ * "sDefaultContent": "Edit",
+ * "aTargets": [ -1 ]
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "mDataProp": null,
+ * "sDefaultContent": "Edit"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sDefaultContent": null,
+
+
+ /**
+ * This parameter is only used in DataTables' server-side processing. It can
+ * be exceptionally useful to know what columns are being displayed on the
+ * client side, and to map these to database fields. When defined, the names
+ * also allow DataTables to reorder information from the server if it comes
+ * back in an unexpected order (i.e. if you switch your columns around on the
+ * client-side, your server-side code does not also need updating).
+ * @type string
+ * @default Empty string
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sName": "engine", "aTargets": [ 0 ] },
+ * { "sName": "browser", "aTargets": [ 1 ] },
+ * { "sName": "platform", "aTargets": [ 2 ] },
+ * { "sName": "version", "aTargets": [ 3 ] },
+ * { "sName": "grade", "aTargets": [ 4 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sName": "engine" },
+ * { "sName": "browser" },
+ * { "sName": "platform" },
+ * { "sName": "version" },
+ * { "sName": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "sName": "",
+
+
+ /**
+ * Defines a data source type for the sorting which can be used to read
+ * realtime information from the table (updating the internally cached
+ * version) prior to sorting. This allows sorting to occur on user editable
+ * elements such as form inputs.
+ * @type string
+ * @default std
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
+ * { "sType": "numeric", "aTargets": [ 3 ] },
+ * { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
+ * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * null,
+ * { "sSortDataType": "dom-text" },
+ * { "sSortDataType": "dom-text", "sType": "numeric" },
+ * { "sSortDataType": "dom-select" },
+ * { "sSortDataType": "dom-checkbox" }
+ * ]
+ * } );
+ * } );
+ */
+ "sSortDataType": "std",
+
+
+ /**
+ * The title of this column.
+ * @type string
+ * @default null Derived from the 'TH' value for this column in the
+ * original HTML table.
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sTitle": "My column title", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sTitle": "My column title" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sTitle": null,
+
+
+ /**
+ * The type allows you to specify how the data for this column will be sorted.
+ * Four types (string, numeric, date and html (which will strip HTML tags
+ * before sorting)) are currently available. Note that only date formats
+ * understood by Javascript's Date() object will be accepted as type date. For
+ * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric',
+ * 'date' or 'html' (by default). Further types can be adding through
+ * plug-ins.
+ * @type string
+ * @default null Auto-detected from raw data
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sType": "html", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sType": "html" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sType": null,
+
+
+ /**
+ * Defining the width of the column, this parameter may take any CSS value
+ * (3em, 20px etc). DataTables applys 'smart' widths to columns which have not
+ * been given a specific width through this interface ensuring that the table
+ * remains readable.
+ * @type string
+ * @default null Automatic
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sWidth": "20%", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready(function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sWidth": "20%" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sWidth": null
+ };
+
+
+
+ /**
+ * DataTables settings object - this holds all the information needed for a
+ * given table, including configuration, data and current application of the
+ * table options. DataTables does not have a single instance for each DataTable
+ * with the settings attached to that instance, but rather instances of the
+ * DataTable "class" are created on-the-fly as needed (typically by a
+ * $().dataTable() call) and the settings object is then applied to that
+ * instance.
+ *
+ * Note that this object is related to {@link DataTable.defaults} but this
+ * one is the internal data store for DataTables's cache of columns. It should
+ * NOT be manipulated outside of DataTables. Any configuration should be done
+ * through the initialisation options.
+ * @namespace
+ * @todo Really should attach the settings object to individual instances so we
+ * don't need to create new instances on each $().dataTable() call (if the
+ * table already exists). It would also save passing oSettings around and
+ * into every single function. However, this is a very significant
+ * architecture change for DataTables and will almost certainly break
+ * backwards compatibility with older installations. This is something that
+ * will be done in 2.0.
+ */
+ DataTable.models.oSettings = {
+ /**
+ * Primary features of DataTables and their enablement state.
+ * @namespace
+ */
+ "oFeatures": {
+
+ /**
+ * Flag to say if DataTables should automatically try to calculate the
+ * optimum table and columns widths (true) or not (false).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bAutoWidth": null,
+
+ /**
+ * Delay the creation of TR and TD elements until they are actually
+ * needed by a driven page draw. This can give a significant speed
+ * increase for Ajax source and Javascript source data, but makes no
+ * difference at all fro DOM and server-side processing tables.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bDeferRender": null,
+
+ /**
+ * Enable filtering on the table or not. Note that if this is disabled
+ * then there is no filtering at all on the table, including fnFilter.
+ * To just remove the filtering input use sDom and remove the 'f' option.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bFilter": null,
+
+ /**
+ * Table information element (the 'Showing x of y records' div) enable
+ * flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bInfo": null,
+
+ /**
+ * Present a user control allowing the end user to change the page size
+ * when pagination is enabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bLengthChange": null,
+
+ /**
+ * Pagination enabled or not. Note that if this is disabled then length
+ * changing must also be disabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bPaginate": null,
+
+ /**
+ * Processing indicator enable flag whenever DataTables is enacting a
+ * user request - typically an Ajax request for server-side processing.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bProcessing": null,
+
+ /**
+ * Server-side processing enabled flag - when enabled DataTables will
+ * get all data from the server for every draw - there is no filtering,
+ * sorting or paging done on the client-side.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bServerSide": null,
+
+ /**
+ * Sorting enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSort": null,
+
+ /**
+ * Apply a class to the columns which are being sorted to provide a
+ * visual highlight or not. This can slow things down when enabled since
+ * there is a lot of DOM interaction.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortClasses": null,
+
+ /**
+ * State saving enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bStateSave": null
+ },
+
+
+ /**
+ * Scrolling settings for a table.
+ * @namespace
+ */
+ "oScroll": {
+ /**
+ * Indicate if DataTables should be allowed to set the padding / margin
+ * etc for the scrolling header elements or not. Typically you will want
+ * this.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bAutoCss": null,
+
+ /**
+ * When the table is shorter in height than sScrollY, collapse the
+ * table container down to the height of the table (when true).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bCollapse": null,
+
+ /**
+ * Infinite scrolling enablement flag. Now deprecated in favour of
+ * using the Scroller plug-in.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bInfinite": null,
+
+ /**
+ * Width of the scrollbar for the web-browser's platform. Calculated
+ * during table initialisation.
+ * @type int
+ * @default 0
+ */
+ "iBarWidth": 0,
+
+ /**
+ * Space (in pixels) between the bottom of the scrolling container and
+ * the bottom of the scrolling viewport before the next page is loaded
+ * when using infinite scrolling.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type int
+ */
+ "iLoadGap": null,
+
+ /**
+ * Viewport width for horizontal scrolling. Horizontal scrolling is
+ * disabled if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sX": null,
+
+ /**
+ * Width to expand the table to when using x-scrolling. Typically you
+ * should not need to use this.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @deprecated
+ */
+ "sXInner": null,
+
+ /**
+ * Viewport height for vertical scrolling. Vertical scrolling is disabled
+ * if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sY": null
+ },
+
+ /**
+ * Language information for the table.
+ * @namespace
+ * @extends DataTable.defaults.oLanguage
+ */
+ "oLanguage": {
+ /**
+ * Information callback function. See
+ * {@link DataTable.defaults.fnInfoCallback}
+ * @type function
+ * @default
+ */
+ "fnInfoCallback": null
+ },
+
+ /**
+ * Array referencing the nodes which are used for the features. The
+ * parameters of this object match what is allowed by sDom - i.e.
+ *
+ *
'l' - Length changing
+ *
'f' - Filtering input
+ *
't' - The table!
+ *
'i' - Information
+ *
'p' - Pagination
+ *
'r' - pRocessing
+ *
+ * @type array
+ * @default []
+ */
+ "aanFeatures": [],
+
+ /**
+ * Store data information - see {@link DataTable.models.oRow} for detailed
+ * information.
+ * @type array
+ * @default []
+ */
+ "aoData": [],
+
+ /**
+ * Array of indexes which are in the current display (after filtering etc)
+ * @type array
+ * @default []
+ */
+ "aiDisplay": [],
+
+ /**
+ * Array of indexes for display - no filtering
+ * @type array
+ * @default []
+ */
+ "aiDisplayMaster": [],
+
+ /**
+ * Store information about each column that is in use
+ * @type array
+ * @default []
+ */
+ "aoColumns": [],
+
+ /**
+ * Store information about the table's header
+ * @type array
+ * @default []
+ */
+ "aoHeader": [],
+
+ /**
+ * Store information about the table's footer
+ * @type array
+ * @default []
+ */
+ "aoFooter": [],
+
+ /**
+ * Search data array for regular expression searching
+ * @type array
+ * @default []
+ */
+ "asDataSearch": [],
+
+ /**
+ * Store the applied global search information in case we want to force a
+ * research or compare the old search to a new one.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ */
+ "oPreviousSearch": {},
+
+ /**
+ * Store the applied search for each column - see
+ * {@link DataTable.models.oSearch} for the format that is used for the
+ * filtering information for each column.
+ * @type array
+ * @default []
+ */
+ "aoPreSearchCols": [],
+
+ /**
+ * Sorting that is applied to the table. Note that the inner arrays are
+ * used in the following manner:
+ *
+ *
Index 0 - column number
+ *
Index 1 - current sorting direction
+ *
Index 2 - index of asSorting for this column
+ *
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @todo These inner arrays should really be objects
+ */
+ "aaSorting": null,
+
+ /**
+ * Sorting that is always applied to the table (i.e. prefixed in front of
+ * aaSorting).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array|null
+ * @default null
+ */
+ "aaSortingFixed": null,
+
+ /**
+ * Classes to use for the striping of a table.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "asStripeClasses": null,
+
+ /**
+ * If restoring a table - we should restore its striping classes as well
+ * @type array
+ * @default []
+ */
+ "asDestroyStripes": [],
+
+ /**
+ * If restoring a table - we should restore its width
+ * @type int
+ * @default 0
+ */
+ "sDestroyWidth": 0,
+
+ /**
+ * Callback functions array for every time a row is inserted (i.e. on a draw).
+ * @type array
+ * @default []
+ */
+ "aoRowCallback": [],
+
+ /**
+ * Callback functions for the header on each draw.
+ * @type array
+ * @default []
+ */
+ "aoHeaderCallback": [],
+
+ /**
+ * Callback function for the footer on each draw.
+ * @type array
+ * @default []
+ */
+ "aoFooterCallback": [],
+
+ /**
+ * Array of callback functions for draw callback functions
+ * @type array
+ * @default []
+ */
+ "aoDrawCallback": [],
+
+ /**
+ * Array of callback functions for row created function
+ * @type array
+ * @default []
+ */
+ "aoRowCreatedCallback": [],
+
+ /**
+ * Callback functions for just before the table is redrawn. A return of
+ * false will be used to cancel the draw.
+ * @type array
+ * @default []
+ */
+ "aoPreDrawCallback": [],
+
+ /**
+ * Callback functions for when the table has been initialised.
+ * @type array
+ * @default []
+ */
+ "aoInitComplete": [],
+
+
+ /**
+ * Callbacks for modifying the settings to be stored for state saving, prior to
+ * saving state.
+ * @type array
+ * @default []
+ */
+ "aoStateSaveParams": [],
+
+ /**
+ * Callbacks for modifying the settings that have been stored for state saving
+ * prior to using the stored values to restore the state.
+ * @type array
+ * @default []
+ */
+ "aoStateLoadParams": [],
+
+ /**
+ * Callbacks for operating on the settings object once the saved state has been
+ * loaded
+ * @type array
+ * @default []
+ */
+ "aoStateLoaded": [],
+
+ /**
+ * Cache the table ID for quick access
+ * @type string
+ * @default Empty string
+ */
+ "sTableId": "",
+
+ /**
+ * The TABLE node for the main table
+ * @type node
+ * @default null
+ */
+ "nTable": null,
+
+ /**
+ * Permanent ref to the thead element
+ * @type node
+ * @default null
+ */
+ "nTHead": null,
+
+ /**
+ * Permanent ref to the tfoot element - if it exists
+ * @type node
+ * @default null
+ */
+ "nTFoot": null,
+
+ /**
+ * Permanent ref to the tbody element
+ * @type node
+ * @default null
+ */
+ "nTBody": null,
+
+ /**
+ * Cache the wrapper node (contains all DataTables controlled elements)
+ * @type node
+ * @default null
+ */
+ "nTableWrapper": null,
+
+ /**
+ * Indicate if when using server-side processing the loading of data
+ * should be deferred until the second draw.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ * @default false
+ */
+ "bDeferLoading": false,
+
+ /**
+ * Indicate if all required information has been read in
+ * @type boolean
+ * @default false
+ */
+ "bInitialised": false,
+
+ /**
+ * Information about open rows. Each object in the array has the parameters
+ * 'nTr' and 'nParent'
+ * @type array
+ * @default []
+ */
+ "aoOpenRows": [],
+
+ /**
+ * Dictate the positioning of DataTables' control elements - see
+ * {@link DataTable.model.oInit.sDom}.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default null
+ */
+ "sDom": null,
+
+ /**
+ * Which type of pagination should be used.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default two_button
+ */
+ "sPaginationType": "two_button",
+
+ /**
+ * The cookie duration (for bStateSave) in seconds.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type int
+ * @default 0
+ */
+ "iCookieDuration": 0,
+
+ /**
+ * The cookie name prefix.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default Empty string
+ */
+ "sCookiePrefix": "",
+
+ /**
+ * Callback function for cookie creation.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ * @default null
+ */
+ "fnCookieCallback": null,
+
+ /**
+ * Array of callback functions for state saving. Each array element is an
+ * object with the following parameters:
+ *
+ *
function:fn - function to call. Takes two parameters, oSettings
+ * and the JSON string to save that has been thus far created. Returns
+ * a JSON string to be inserted into a json object
+ * (i.e. '"param": [ 0, 1, 2]')
+ *
string:sName - name of callback
+ *
+ * @type array
+ * @default []
+ */
+ "aoStateSave": [],
+
+ /**
+ * Array of callback functions for state loading. Each array element is an
+ * object with the following parameters:
+ *
+ *
function:fn - function to call. Takes two parameters, oSettings
+ * and the object stored. May return false to cancel state loading
+ *
string:sName - name of callback
+ *
+ * @type array
+ * @default []
+ */
+ "aoStateLoad": [],
+
+ /**
+ * State that was loaded from the cookie. Useful for back reference
+ * @type object
+ * @default null
+ */
+ "oLoadedState": null,
+
+ /**
+ * Source url for AJAX data for the table.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default null
+ */
+ "sAjaxSource": null,
+
+ /**
+ * Property from a given object from which to read the table data from. This
+ * can be an empty string (when not server-side processing), in which case
+ * it is assumed an an array is given directly.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sAjaxDataProp": null,
+
+ /**
+ * Note if draw should be blocked while getting data
+ * @type boolean
+ * @default true
+ */
+ "bAjaxDataGet": true,
+
+ /**
+ * The last jQuery XHR object that was used for server-side data gathering.
+ * This can be used for working with the XHR information in one of the
+ * callbacks
+ * @type object
+ * @default null
+ */
+ "jqXHR": null,
+
+ /**
+ * Function to get the server-side data.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ */
+ "fnServerData": null,
+
+ /**
+ * Functions which are called prior to sending an Ajax request so extra
+ * parameters can easily be sent to the server
+ * @type array
+ * @default []
+ */
+ "aoServerParams": [],
+
+ /**
+ * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
+ * required).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sServerMethod": null,
+
+ /**
+ * Format numbers for display.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ */
+ "fnFormatNumber": null,
+
+ /**
+ * List of options that can be used for the user selectable length menu.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "aLengthMenu": null,
+
+ /**
+ * Counter for the draws that the table does. Also used as a tracker for
+ * server-side processing
+ * @type int
+ * @default 0
+ */
+ "iDraw": 0,
+
+ /**
+ * Indicate if a redraw is being done - useful for Ajax
+ * @type boolean
+ * @default false
+ */
+ "bDrawing": false,
+
+ /**
+ * Draw index (iDraw) of the last error when parsing the returned data
+ * @type int
+ * @default -1
+ */
+ "iDrawError": -1,
+
+ /**
+ * Paging display length
+ * @type int
+ * @default 10
+ */
+ "_iDisplayLength": 10,
+
+ /**
+ * Paging start point - aiDisplay index
+ * @type int
+ * @default 0
+ */
+ "_iDisplayStart": 0,
+
+ /**
+ * Paging end point - aiDisplay index. Use fnDisplayEnd rather than
+ * this property to get the end point
+ * @type int
+ * @default 10
+ * @private
+ */
+ "_iDisplayEnd": 10,
+
+ /**
+ * Server-side processing - number of records in the result set
+ * (i.e. before filtering), Use fnRecordsTotal rather than
+ * this property to get the value of the number of records, regardless of
+ * the server-side processing setting.
+ * @type int
+ * @default 0
+ * @private
+ */
+ "_iRecordsTotal": 0,
+
+ /**
+ * Server-side processing - number of records in the current display set
+ * (i.e. after filtering). Use fnRecordsDisplay rather than
+ * this property to get the value of the number of records, regardless of
+ * the server-side processing setting.
+ * @type boolean
+ * @default 0
+ * @private
+ */
+ "_iRecordsDisplay": 0,
+
+ /**
+ * Flag to indicate if jQuery UI marking and classes should be used.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bJUI": null,
+
+ /**
+ * The classes to use for the table
+ * @type object
+ * @default {}
+ */
+ "oClasses": {},
+
+ /**
+ * Flag attached to the settings object so you can check in the draw
+ * callback if filtering has been done in the draw. Deprecated in favour of
+ * events.
+ * @type boolean
+ * @default false
+ * @deprecated
+ */
+ "bFiltered": false,
+
+ /**
+ * Flag attached to the settings object so you can check in the draw
+ * callback if sorting has been done in the draw. Deprecated in favour of
+ * events.
+ * @type boolean
+ * @default false
+ * @deprecated
+ */
+ "bSorted": false,
+
+ /**
+ * Indicate that if multiple rows are in the header and there is more than
+ * one unique cell per column, if the top one (true) or bottom one (false)
+ * should be used for sorting / title by DataTables.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortCellsTop": null,
+
+ /**
+ * Initialisation object that is used for the table
+ * @type object
+ * @default null
+ */
+ "oInit": null,
+
+ /**
+ * Destroy callback functions - for plug-ins to attach themselves to the
+ * destroy so they can clean up markup and events.
+ * @type array
+ * @default []
+ */
+ "aoDestroyCallback": [],
+
+
+ /**
+ * Get the number of records in the current record set, before filtering
+ * @type function
+ */
+ "fnRecordsTotal": function ()
+ {
+ if ( this.oFeatures.bServerSide ) {
+ return parseInt(this._iRecordsTotal, 10);
+ } else {
+ return this.aiDisplayMaster.length;
+ }
+ },
+
+ /**
+ * Get the number of records in the current record set, after filtering
+ * @type function
+ */
+ "fnRecordsDisplay": function ()
+ {
+ if ( this.oFeatures.bServerSide ) {
+ return parseInt(this._iRecordsDisplay, 10);
+ } else {
+ return this.aiDisplay.length;
+ }
+ },
+
+ /**
+ * Set the display end point - aiDisplay index
+ * @type function
+ * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
+ */
+ "fnDisplayEnd": function ()
+ {
+ if ( this.oFeatures.bServerSide ) {
+ if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {
+ return this._iDisplayStart+this.aiDisplay.length;
+ } else {
+ return Math.min( this._iDisplayStart+this._iDisplayLength,
+ this._iRecordsDisplay );
+ }
+ } else {
+ return this._iDisplayEnd;
+ }
+ },
+
+ /**
+ * The DataTables object for this table
+ * @type object
+ * @default null
+ */
+ "oInstance": null,
+
+ /**
+ * Unique identifier for each instance of the DataTables object. If there
+ * is an ID on the table node, then it takes that value, otherwise an
+ * incrementing internal counter is used.
+ * @type string
+ * @default null
+ */
+ "sInstance": null,
+
+ /**
+ * tabindex attribute value that is added to DataTables control elements, allowing
+ * keyboard navigation of the table and its controls.
+ */
+ "iTabIndex": 0,
+
+ /**
+ * DIV container for the footer scrolling table if scrolling
+ */
+ "nScrollHead": null,
+
+ /**
+ * DIV container for the footer scrolling table if scrolling
+ */
+ "nScrollFoot": null
+ };
+
+ /**
+ * Extension object for DataTables that is used to provide all extension options.
+ *
+ * Note that the DataTable.ext object is available through
+ * jQuery.fn.dataTable.ext where it may be accessed and manipulated. It is
+ * also aliased to jQuery.fn.dataTableExt for historic reasons.
+ * @namespace
+ * @extends DataTable.models.ext
+ */
+ DataTable.ext = $.extend( true, {}, DataTable.models.ext );
+
+ $.extend( DataTable.ext.oStdClasses, {
+ "sTable": "dataTable",
+
+ /* Two buttons buttons */
+ "sPagePrevEnabled": "paginate_enabled_previous",
+ "sPagePrevDisabled": "paginate_disabled_previous",
+ "sPageNextEnabled": "paginate_enabled_next",
+ "sPageNextDisabled": "paginate_disabled_next",
+ "sPageJUINext": "",
+ "sPageJUIPrev": "",
+
+ /* Full numbers paging buttons */
+ "sPageButton": "paginate_button",
+ "sPageButtonActive": "paginate_active",
+ "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled",
+ "sPageFirst": "first",
+ "sPagePrevious": "previous",
+ "sPageNext": "next",
+ "sPageLast": "last",
+
+ /* Striping classes */
+ "sStripeOdd": "odd",
+ "sStripeEven": "even",
+
+ /* Empty row */
+ "sRowEmpty": "dataTables_empty",
+
+ /* Features */
+ "sWrapper": "dataTables_wrapper",
+ "sFilter": "dataTables_filter",
+ "sInfo": "dataTables_info",
+ "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
+ "sLength": "dataTables_length",
+ "sProcessing": "dataTables_processing",
+
+ /* Sorting */
+ "sSortAsc": "sorting_asc",
+ "sSortDesc": "sorting_desc",
+ "sSortable": "sorting", /* Sortable in both directions */
+ "sSortableAsc": "sorting_asc_disabled",
+ "sSortableDesc": "sorting_desc_disabled",
+ "sSortableNone": "sorting_disabled",
+ "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
+ "sSortJUIAsc": "",
+ "sSortJUIDesc": "",
+ "sSortJUI": "",
+ "sSortJUIAscAllowed": "",
+ "sSortJUIDescAllowed": "",
+ "sSortJUIWrapper": "",
+ "sSortIcon": "",
+
+ /* Scrolling */
+ "sScrollWrapper": "dataTables_scroll",
+ "sScrollHead": "dataTables_scrollHead",
+ "sScrollHeadInner": "dataTables_scrollHeadInner",
+ "sScrollBody": "dataTables_scrollBody",
+ "sScrollFoot": "dataTables_scrollFoot",
+ "sScrollFootInner": "dataTables_scrollFootInner",
+
+ /* Misc */
+ "sFooterTH": "",
+ "sJUIHeader": "",
+ "sJUIFooter": ""
+ } );
+
+
+ $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
+ /* Two buttons buttons */
+ "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
+ "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
+ "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
+ "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
+ "sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
+ "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
+
+ /* Full numbers paging buttons */
+ "sPageButton": "fg-button ui-button ui-state-default",
+ "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
+ "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
+ "sPageFirst": "first ui-corner-tl ui-corner-bl",
+ "sPageLast": "last ui-corner-tr ui-corner-br",
+
+ /* Features */
+ "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
+ "ui-buttonset-multi paging_", /* Note that the type is postfixed */
+
+ /* Sorting */
+ "sSortAsc": "ui-state-default",
+ "sSortDesc": "ui-state-default",
+ "sSortable": "ui-state-default",
+ "sSortableAsc": "ui-state-default",
+ "sSortableDesc": "ui-state-default",
+ "sSortableNone": "ui-state-default",
+ "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
+ "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
+ "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
+ "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
+ "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
+ "sSortJUIWrapper": "DataTables_sort_wrapper",
+ "sSortIcon": "DataTables_sort_icon",
+
+ /* Scrolling */
+ "sScrollHead": "dataTables_scrollHead ui-state-default",
+ "sScrollFoot": "dataTables_scrollFoot ui-state-default",
+
+ /* Misc */
+ "sFooterTH": "ui-state-default",
+ "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
+ "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
+ } );
+
+
+ /*
+ * Variable: oPagination
+ * Purpose:
+ * Scope: jQuery.fn.dataTableExt
+ */
+ $.extend( DataTable.ext.oPagination, {
+ /*
+ * Variable: two_button
+ * Purpose: Standard two button (forward/back) pagination
+ * Scope: jQuery.fn.dataTableExt.oPagination
+ */
+ "two_button": {
+ /*
+ * Function: oPagination.two_button.fnInit
+ * Purpose: Initialise dom elements required for pagination with forward/back buttons only
+ * Returns: -
+ * Inputs: object:oSettings - dataTables settings object
+ * node:nPaging - the DIV which contains this pagination control
+ * function:fnCallbackDraw - draw function which must be called on update
+ */
+ "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
+ {
+ var oLang = oSettings.oLanguage.oPaginate;
+ var oClasses = oSettings.oClasses;
+ var fnClickHandler = function ( e ) {
+ if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
+ {
+ fnCallbackDraw( oSettings );
+ }
+ };
+
+ var sAppend = (!oSettings.bJUI) ?
+ ''+oLang.sPrevious+''+
+ ''+oLang.sNext+''
+ :
+ ''+
+ '';
+ $(nPaging).append( sAppend );
+
+ var els = $('a', nPaging);
+ var nPrevious = els[0],
+ nNext = els[1];
+
+ oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
+
+ /* ID the first elements only */
+ if ( !oSettings.aanFeatures.p )
+ {
+ nPaging.id = oSettings.sTableId+'_paginate';
+ nPrevious.id = oSettings.sTableId+'_previous';
+ nNext.id = oSettings.sTableId+'_next';
+
+ nPrevious.setAttribute('aria-controls', oSettings.sTableId);
+ nNext.setAttribute('aria-controls', oSettings.sTableId);
+ }
+ },
+
+ /*
+ * Function: oPagination.two_button.fnUpdate
+ * Purpose: Update the two button pagination at the end of the draw
+ * Returns: -
+ * Inputs: object:oSettings - dataTables settings object
+ * function:fnCallbackDraw - draw function to call on page change
+ */
+ "fnUpdate": function ( oSettings, fnCallbackDraw )
+ {
+ if ( !oSettings.aanFeatures.p )
+ {
+ return;
+ }
+
+ var oClasses = oSettings.oClasses;
+ var an = oSettings.aanFeatures.p;
+
+ /* Loop over each instance of the pager */
+ for ( var i=0, iLen=an.length ; i'+oLang.sFirst+''+
+ ''+oLang.sPrevious+''+
+ ''+
+ ''+oLang.sNext+''+
+ ''+oLang.sLast+''
+ );
+ var els = $('a', nPaging);
+ var nFirst = els[0],
+ nPrev = els[1],
+ nNext = els[2],
+ nLast = els[3];
+
+ oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler );
+
+ /* ID the first elements only */
+ if ( !oSettings.aanFeatures.p )
+ {
+ nPaging.id = oSettings.sTableId+'_paginate';
+ nFirst.id =oSettings.sTableId+'_first';
+ nPrev.id =oSettings.sTableId+'_previous';
+ nNext.id =oSettings.sTableId+'_next';
+ nLast.id =oSettings.sTableId+'_last';
+ }
+ },
+
+ /*
+ * Function: oPagination.full_numbers.fnUpdate
+ * Purpose: Update the list of page buttons shows
+ * Returns: -
+ * Inputs: object:oSettings - dataTables settings object
+ * function:fnCallbackDraw - draw function to call on page change
+ */
+ "fnUpdate": function ( oSettings, fnCallbackDraw )
+ {
+ if ( !oSettings.aanFeatures.p )
+ {
+ return;
+ }
+
+ var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
+ var iPageCountHalf = Math.floor(iPageCount / 2);
+ var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
+ var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
+ var sList = "";
+ var iStartButton, iEndButton, i, iLen;
+ var oClasses = oSettings.oClasses;
+ var anButtons, anStatic, nPaginateList;
+ var an = oSettings.aanFeatures.p;
+ var fnBind = function (j) {
+ oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) {
+ /* Use the information in the element to jump to the required page */
+ oSettings.oApi._fnPageChange( oSettings, e.data.page );
+ fnCallbackDraw( oSettings );
+ e.preventDefault();
+ } );
+ };
+
+ /* Pages calculation */
+ if ( oSettings._iDisplayLength === -1 )
+ {
+ iStartButton = 1;
+ iEndButton = 1;
+ iCurrentPage = 1;
+ }
+ else if (iPages < iPageCount)
+ {
+ iStartButton = 1;
+ iEndButton = iPages;
+ }
+ else if (iCurrentPage <= iPageCountHalf)
+ {
+ iStartButton = 1;
+ iEndButton = iPageCount;
+ }
+ else if (iCurrentPage >= (iPages - iPageCountHalf))
+ {
+ iStartButton = iPages - iPageCount + 1;
+ iEndButton = iPages;
+ }
+ else
+ {
+ iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
+ iEndButton = iStartButton + iPageCount - 1;
+ }
+
+
+ /* Build the dynamic list */
+ for ( i=iStartButton ; i<=iEndButton ; i++ )
+ {
+ sList += (iCurrentPage !== i) ?
+ ''+oSettings.fnFormatNumber(i)+'' :
+ ''+oSettings.fnFormatNumber(i)+'';
+ }
+
+ /* Loop over each instance of the pager */
+ for ( i=0, iLen=an.length ; i y) ? 1 : 0));
+ },
+
+ "string-desc": function ( x, y )
+ {
+ return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ },
+
+
+ /*
+ * html sorting (ignore html tags)
+ */
+ "html-pre": function ( a )
+ {
+ return a.replace( /<.*?>/g, "" ).toLowerCase();
+ },
+
+ "html-asc": function ( x, y )
+ {
+ return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ },
+
+ "html-desc": function ( x, y )
+ {
+ return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ },
+
+
+ /*
+ * date sorting
+ */
+ "date-pre": function ( a )
+ {
+ var x = Date.parse( a );
+
+ if ( isNaN(x) || x==="" )
+ {
+ x = Date.parse( "01/01/1970 00:00:00" );
+ }
+ return x;
+ },
+
+ "date-asc": function ( x, y )
+ {
+ return x - y;
+ },
+
+ "date-desc": function ( x, y )
+ {
+ return y - x;
+ },
+
+
+ /*
+ * numerical sorting
+ */
+ "numeric-pre": function ( a )
+ {
+ return (a=="-" || a==="") ? 0 : a*1;
+ },
+
+ "numeric-asc": function ( x, y )
+ {
+ return x - y;
+ },
+
+ "numeric-desc": function ( x, y )
+ {
+ return y - x;
+ }
+ } );
+
+
+ $.extend( DataTable.ext.aTypes, [
+ /*
+ * Function: -
+ * Purpose: Check to see if a string is numeric
+ * Returns: string:'numeric' or null
+ * Inputs: mixed:sText - string to check
+ */
+ function ( sData )
+ {
+ /* Allow zero length strings as a number */
+ if ( typeof sData === 'number' )
+ {
+ return 'numeric';
+ }
+ else if ( typeof sData !== 'string' )
+ {
+ return null;
+ }
+
+ var sValidFirstChars = "0123456789-";
+ var sValidChars = "0123456789.";
+ var Char;
+ var bDecimal = false;
+
+ /* Check for a valid first char (no period and allow negatives) */
+ Char = sData.charAt(0);
+ if (sValidFirstChars.indexOf(Char) == -1)
+ {
+ return null;
+ }
+
+ /* Check all the other characters are valid */
+ for ( var i=1 ; i') != -1 )
+ {
+ return 'html';
+ }
+ return null;
+ }
+ ] );
+
+
+ // jQuery aliases
+ $.fn.DataTable = DataTable;
+ $.fn.dataTable = DataTable;
+ $.fn.dataTableSettings = DataTable.settings;
+ $.fn.dataTableExt = DataTable.ext;
+
+
+ // Information about events fired by DataTables - for documentation.
+ /**
+ * Draw event, fired whenever the table is redrawn on the page, at the same point as
+ * fnDrawCallback. This may be useful for binding events or performing calculations when
+ * the table is altered at all.
+ * @name DataTable#draw
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Filter event, fired when the filtering applied to the table (using the build in global
+ * global filter, or column filters) is altered.
+ * @name DataTable#filter
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Page change event, fired when the paging of the table is altered.
+ * @name DataTable#page
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Sort event, fired when the sorting applied to the table is altered.
+ * @name DataTable#sort
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * DataTables initialisation complete event, fired when the table is fully drawn,
+ * including Ajax data loaded, if Ajax data is required.
+ * @name DataTable#init
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The JSON object request from the server - only
+ * present if client-side Ajax sourced data is used
+ */
+
+ /**
+ * State save event, fired when the table has changed state a new state save is required.
+ * This method allows modification of the state saving object prior to actually doing the
+ * save, including addition or other state properties (for plug-ins) or modification
+ * of a DataTables core property.
+ * @name DataTable#stateSaveParams
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The state information to be saved
+ */
+
+ /**
+ * State load event, fired when the table is loading state from the stored data, but
+ * prior to the settings object being modified by the saved state - allowing modification
+ * of the saved state is required or loading of state for a plug-in.
+ * @name DataTable#stateLoadParams
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The saved state information
+ */
+
+ /**
+ * State loaded event, fired when state has been loaded from stored data and the settings
+ * object has been modified by the loaded data.
+ * @name DataTable#stateLoaded
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The saved state information
+ */
+
+ /**
+ * Processing event, fired when DataTables is doing some kind of processing (be it,
+ * sort, filter or anything else). Can be used to indicate to the end user that
+ * there is something happening, or that something has finished.
+ * @name DataTable#processing
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {boolean} bShow Flag for if DataTables is doing processing or not
+ */
+
+ /**
+ * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to
+ * made to the server for new data (note that this trigger is called in fnServerData,
+ * if you override fnServerData and which to use this event, you need to trigger it in
+ * you success function).
+ * @name DataTable#xhr
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
+ * the bDestroy:true parameter in the initialisation object. This can be used to remove
+ * bound events, added DOM nodes, etc.
+ * @name DataTable#destroy
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+}(jQuery, window, document, undefined));
diff --git a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js
new file mode 100644
index 00000000..ce18c935
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js
@@ -0,0 +1,154 @@
+/*
+ * File: jquery.dataTables.min.js
+ * Version: 1.9.2
+ * Author: Allan Jardine (www.sprymedia.co.uk)
+ * Info: www.datatables.net
+ *
+ * Copyright 2008-2012 Allan Jardine, all rights reserved.
+ *
+ * This source file is free software, under either the GPL v2 license or a
+ * BSD style license, available at:
+ * http://datatables.net/license_gpl2
+ * http://datatables.net/license_bsd
+ *
+ * This source file 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 license files for details.
+ */
+(function(i,V,l,n){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=i.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mDataProp:c.mDataProp?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=i.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d],
+c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;r(a,d,null)}function r(a,b,c){b=a.aoColumns[b];c!==n&&null!==c&&(c.sType!==n&&(b.sType=c.sType,b._bAutoType=!1),i.extend(b,c),p(b,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(b.aDataSort=[c.iDataSort]),p(b,c,"aDataSort"));b.fnGetData=W(b.mDataProp);b.fnSetData=ta(b.mDataProp);a.oFeatures.bSort||(b.bSortable=!1);!b.bSortable||-1==i.inArray("asc",b.asSorting)&&-1==i.inArray("desc",b.asSorting)?(b.sSortingClass=
+a.oClasses.sSortableNone,b.sSortingClassJUI=""):b.bSortable||-1==i.inArray("asc",b.asSorting)&&-1==i.inArray("desc",b.asSorting)?(b.sSortingClass=a.oClasses.sSortable,b.sSortingClassJUI=a.oClasses.sSortJUI):-1!=i.inArray("asc",b.asSorting)&&-1==i.inArray("desc",b.asSorting)?(b.sSortingClass=a.oClasses.sSortableAsc,b.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1==i.inArray("asc",b.asSorting)&&-1!=i.inArray("desc",b.asSorting)&&(b.sSortingClass=a.oClasses.sSortableDesc,b.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}
+function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;ba(a);for(var b=0,c=a.aoColumns.length;bm[f])d(a.aoColumns.length+m[f],b[g]);else if("string"===typeof m[f]){e=0;for(s=a.aoColumns.length;eb&&a[d]--; -1!=c&&a.splice(c,1)}function R(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mDataProp},w(a,b,c,"display"))}function ca(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&&i(c.nTr).addClass(c._aData.DT_RowClass);for(var g=0,f=a.aoColumns.length;g=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,A(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var h=a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(h=0,d=a.aoData.length);for(;h")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=i('')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),g,f,h,e,s,m,o,k=0;k")[0];s=d[k+1];if("'"==s||'"'==s){m="";for(o=2;d[k+o]!=s;)m+=d[k+o],o++;"H"==m?m=a.oClasses.sJUIHeader:"F"==m&&(m=a.oClasses.sJUIFooter);
+-1!=m.indexOf(".")?(s=m.split("."),e.id=s[0].substr(1,s[0].length-1),e.className=s[1]):"#"==m.charAt(0)?e.id=m.substr(1,m.length-1):e.className=m;k+=o}c.appendChild(e);c=e}else if(">"==h)c=c.parentNode;else if("l"==h&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)g=ya(a),f=1;else if("f"==h&&a.oFeatures.bFilter)g=za(a),f=1;else if("r"==h&&a.oFeatures.bProcessing)g=Aa(a),f=1;else if("t"==h)g=Ba(a),f=1;else if("i"==h&&a.oFeatures.bInfo)g=Ca(a),f=1;else if("p"==h&&a.oFeatures.bPaginate)g=Da(a),f=1;
+else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;o=0;for(s=e.length;o'):
+""===c?'':c+' ',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=i('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"""));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value,h=0,e=c.length;h=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||g.sSearch.length>b.length||1==c||0!==b.indexOf(g.sSearch)){a.aiDisplay.splice(0,a.aiDisplay.length);ja(a,1);for(b=0;b/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function na(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)",
+"g"),"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ja,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ja(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),g=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),h;h=0===f&&f==g?b.sInfoEmpty:0===f?b.sInfoEmpty+" "+b.sInfoFiltered:f==g?b.sInfo:b.sInfo+
+" "+b.sInfoFiltered;h+=b.sInfoPostFix;h=ha(a,h);null!==b.fnInfoCallback&&(h=b.fnInfoCallback.call(a.oInstance,a,c,d,g,f,h));a=a.aanFeatures.i;b=0;for(c=a.length;b",c,d,g=a.aLengthMenu;if(2==g.length&&"object"===typeof g[0]&&"object"===typeof g[1]){c=0;for(d=g[0].length;c'+g[1][c]+""}else{c=0;for(d=g.length;c'+g[c]+""}b+=
+"";g=l.createElement("div");a.aanFeatures.l||(g.id=a.sTableId+"_length");g.className=a.oClasses.sLength;g.innerHTML="";i('select option[value="'+a._iDisplayLength+'"]',g).attr("selected",!0);i("select",g).bind("change.DT",function(){var b=i(this).val(),g=a.aanFeatures.l;c=0;for(d=g.length;ca.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;
+j.ext.oPagination[a.sPaginationType].fnInit(a,b,function(a){A(a);y(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){A(a);y(a)})},sName:"pagination"});return b}function pa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-
+a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart=0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLengthi(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()=i.browser.version;i(a.nTable).children("thead, tfoot").remove();h=i(a.nTHead).clone()[0];a.nTable.insertBefore(h,a.nTable.childNodes[0]);null!==a.nTFoot&&(j=i(a.nTFoot).clone()[0],a.nTable.insertBefore(j,a.nTable.childNodes[1]));""===a.oScroll.sX&&(d.style.width="100%",b.parentNode.style.width="100%");var t=O(a,h);g=0;for(f=t.length;gd.offsetHeight||"scroll"==i(d).css("overflow-y")))a.nTable.style.width=q(i(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width=q(a.oScroll.sXInner):g==i(d).width()&&i(d).height()g-a.oScroll.iBarWidth&&
+(a.nTable.style.width=q(g))):a.nTable.style.width=q(g);g=i(a.nTable).outerWidth();f=a.nTHead.getElementsByTagName("tr");h=h.getElementsByTagName("tr");N(function(a,b){m=a.style;m.paddingTop="0";m.paddingBottom="0";m.borderTopWidth="0";m.borderBottomWidth="0";m.height=0;k=i(a).width();b.style.width=q(k);n.push(k)},h,f);i(h).height(0);null!==a.nTFoot&&(e=j.getElementsByTagName("tr"),j=a.nTFoot.getElementsByTagName("tr"),N(function(a,b){m=a.style;m.paddingTop="0";m.paddingBottom="0";m.borderTopWidth=
+"0";m.borderBottomWidth="0";m.height=0;k=i(a).width();b.style.width=q(k);n.push(k)},e,j),i(e).height(0));N(function(a){a.innerHTML="";a.style.width=q(n.shift())},h);null!==a.nTFoot&&N(function(a){a.innerHTML="";a.style.width=q(n.shift())},e);if(i(a.nTable).outerWidth()d.offsetHeight||"scroll"==i(d).css("overflow-y")?g+a.oScroll.iBarWidth:g;if(l&&(d.scrollHeight>d.offsetHeight||"scroll"==i(d).css("overflow-y")))a.nTable.style.width=q(e-a.oScroll.iBarWidth);d.style.width=q(e);b.parentNode.style.width=
+q(e);null!==a.nTFoot&&(r.parentNode.style.width=q(e));""===a.oScroll.sX?E(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."):""!==a.oScroll.sXInner&&E(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),b.parentNode.style.width=q("100%"),null!==a.nTFoot&&(r.parentNode.style.width=
+q("100%"));""===a.oScroll.sY&&l&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),l=""!==a.oScroll.sX&&a.nTable.offsetWidth>d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeightd.clientHeight||"scroll"==i(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+
+"px":"0px";null!==a.nTFoot&&(p.style.width=q(l),r.style.width=q(l),r.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");i(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function N(a,b,c){for(var d=0,g=b.length;dtd",b));h=O(a,f);for(f=d=0;fc)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=w(a,c,b,"");return d}return L(a,c)[b]}function Oa(a,b){for(var c=
+-1,d=-1,g=0;g/g,"");f.length>c&&(c=f.length,d=g)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1);return 48>b||57/g,""),g=l[c].nTh,g.removeAttribute("aria-sort"),g.removeAttribute("aria-label"),l[c].bSortable?0=h)for(b=0;be&&e++}}}function qa(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b,c;b=a.oScroll.bInfinite;var d={iCreate:(new Date).getTime(),iStart:b?0:a._iDisplayStart,
+iEnd:b?a._iDisplayLength:a._iDisplayEnd,iLength:a._iDisplayLength,aaSorting:i.extend(!0,[],a.aaSorting),oSearch:i.extend(!0,{},a.oPreviousSearch),aoSearchCols:i.extend(!0,[],a.aoPreSearchCols),abVisCols:[]};b=0;for(c=a.aoColumns.length;b=d.fnRecordsDisplay()&&(d._iDisplayStart-=d._iDisplayLength,0>d._iDisplayStart&&(d._iDisplayStart=0));if(c===n||c)A(d),y(d);return h};this.fnDestroy=function(a){var b=u(this[j.ext.iApiIndex]),c=b.nTableWrapper.parentNode,d=b.nTBody,g,e,a=a===n?!1:!0;b.bDestroying=!0;C(b,"aoDestroyCallback","destroy",[b]);g=0;for(e=b.aoColumns.length;gtr>td."+b.oClasses.sRowEmpty,b.nTable).parent().remove();b.nTable!=b.nTHead.parentNode&&(i(b.nTable).children("thead").remove(),b.nTable.appendChild(b.nTHead));b.nTFoot&&b.nTable!=b.nTFoot.parentNode&&(i(b.nTable).children("tfoot").remove(),b.nTable.appendChild(b.nTFoot));b.nTable.parentNode.removeChild(b.nTable);i(b.nTableWrapper).remove();b.aaSorting=[];b.aaSortingFixed=[];Q(b);i(S(b)).removeClass(b.asStripeClasses.join(" "));
+i("th, td",b.nTHead).removeClass([b.oClasses.sSortable,b.oClasses.sSortableAsc,b.oClasses.sSortableDesc,b.oClasses.sSortableNone].join(" "));b.bJUI&&(i("th span."+b.oClasses.sSortIcon+", td span."+b.oClasses.sSortIcon,b.nTHead).remove(),i("th, td",b.nTHead).each(function(){var a=i("div."+b.oClasses.sSortJUIWrapper,this),c=a.contents();i(this).append(c);a.remove()}));!a&&b.nTableReinsertBefore?c.insertBefore(b.nTable,b.nTableReinsertBefore):a||c.appendChild(b.nTable);g=0;for(e=b.aoData.length;g=v(d);if(!m)for(e=a;et<"F"ip>')):i.extend(h.oClasses,j.ext.oStdClasses);i(this).addClass(h.oClasses.sTable);
+if(""!==h.oScroll.sX||""!==h.oScroll.sY)h.oScroll.iBarWidth=Pa();h.iInitDisplayStart===n&&(h.iInitDisplayStart=e.iDisplayStart,h._iDisplayStart=e.iDisplayStart);e.bStateSave&&(h.oFeatures.bStateSave=!0,Ra(h,e),B(h,"aoDrawCallback",qa,"state_save"));null!==e.iDeferLoading&&(h.bDeferLoading=!0,a=i.isArray(e.iDeferLoading),h._iRecordsDisplay=a?e.iDeferLoading[0]:e.iDeferLoading,h._iRecordsTotal=a?e.iDeferLoading[1]:e.iDeferLoading);null!==e.aaData&&(f=!0);""!==e.oLanguage.sUrl?(h.oLanguage.sUrl=e.oLanguage.sUrl,
+i.getJSON(h.oLanguage.sUrl,null,function(a){oa(a);i.extend(true,h.oLanguage,e.oLanguage,a);aa(h)}),g=!0):i.extend(!0,h.oLanguage,e.oLanguage);null===e.asStripeClasses&&(h.asStripeClasses=[h.oClasses.sStripeOdd,h.oClasses.sStripeEven]);c=!1;d=i(this).children("tbody").children("tr");a=0;for(b=h.asStripeClasses.length;a=h.aoColumns.length&&(h.aaSorting[a][0]=0);var k=h.aoColumns[h.aaSorting[a][0]];h.aaSorting[a][2]===n&&(h.aaSorting[a][2]=0);e.aaSorting===n&&h.saved_aaSorting===n&&(h.aaSorting[a][1]=k.asSorting[0]);c=0;for(d=k.asSorting.length;c=parseInt(n,10)};j.fnIsDataTable=function(e){for(var i=j.settings,r=0;re)return e;for(var i=e+"",e=i.split(""),j="",i=i.length,k=0;k'+k.sPrevious+''+k.sNext+"":'';i(j).append(k);var t=i("a",j),k=t[0],t=t[1];e.oApi._fnBindAction(k,{action:"previous"},l);e.oApi._fnBindAction(t,{action:"next"},l);
+e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_previous",t.id=e.sTableId+"_next",k.setAttribute("aria-controls",e.sTableId),t.setAttribute("aria-controls",e.sTableId))},fnUpdate:function(e){if(e.aanFeatures.p)for(var i=e.oClasses,j=e.aanFeatures.p,k=0,n=j.length;k'+k.sFirst+''+k.sPrevious+''+k.sNext+''+k.sLast+"");var v=i("a",j),k=v[0],l=v[1],z=v[2],v=v[3];e.oApi._fnBindAction(k,{action:"first"},t);e.oApi._fnBindAction(l,{action:"previous"},t);e.oApi._fnBindAction(z,{action:"next"},t);e.oApi._fnBindAction(v,{action:"last"},t);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_first",l.id=e.sTableId+"_previous",z.id=e.sTableId+"_next",v.id=e.sTableId+"_last")},fnUpdate:function(e,o){if(e.aanFeatures.p){var l=j.ext.oPagination.iFullNumbersShowPages,k=Math.floor(l/
+2),n=Math.ceil(e.fnRecordsDisplay()/e._iDisplayLength),t=Math.ceil(e._iDisplayStart/e._iDisplayLength)+1,v="",z,D=e.oClasses,x,J=e.aanFeatures.p,H=function(i){e.oApi._fnBindAction(this,{page:i+z-1},function(i){e.oApi._fnPageChange(e,i.data.page);o(e);i.preventDefault()})};-1===e._iDisplayLength?t=k=z=1:n=n-k?(z=n-l+1,k=n):(z=t-Math.ceil(l/2)+1,k=z+l-1);for(l=z;l<=k;l++)v+=t!==l?''+e.fnFormatNumber(l)+"":''+e.fnFormatNumber(l)+"";l=0;for(k=J.length;li?1:0},"string-desc":function(e,i){return ei?-1:0},"html-pre":function(e){return e.replace(/<.*?>/g,"").toLowerCase()},"html-asc":function(e,i){return ei?1:0},"html-desc":function(e,i){return ei?-1:0},"date-pre":function(e){e=Date.parse(e);if(isNaN(e)||""===e)e=Date.parse("01/01/1970 00:00:00");
+return e},"date-asc":function(e,i){return e-i},"date-desc":function(e,i){return i-e},"numeric-pre":function(e){return"-"==e||""===e?0:1*e},"numeric-asc":function(e,i){return e-i},"numeric-desc":function(e,i){return i-e}});i.extend(j.ext.aTypes,[function(e){if("number"===typeof e)return"numeric";if("string"!==typeof e)return null;var i,j=!1;i=e.charAt(0);if(-1=="0123456789-".indexOf(i))return null;for(var k=1;k")?"html":null}]);i.fn.DataTable=j;i.fn.dataTable=j;i.fn.dataTableSettings=j.settings;i.fn.dataTableExt=j.ext})(jQuery,window,document,void 0);
diff --git a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.js b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.js
new file mode 100644
index 00000000..ee023370
--- /dev/null
+++ b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.1 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
MOST HIGHLY RECOMMENDED DATA SET (Overall et al., 2009): The Hippocampus Consortium data set provides estimates of mRNA expression in the adult hippocampus of 99 genetically diverse strains of mice including 67 BXD recombinant inbred strains, 13 CXB recombinant inbred strains, a diverse set of common inbred strains, and two reciprocal F1 hybrids.
-
-
-
The hippocampus is an important and intriguing part of the forebrain that is crucial in memory formation and retrieval, and that is often affected in epilepsy, Alzheimer's disease, and schizophrenia. Unlike most other parts of the brain, the hippocampus contains a remarkable population of stems cells that continue to generate neurons and glial cells even in adult mammals (Kempermann, 2005). This genetic analysis of transcript expression in the hippocampus (dentate gyrus, CA1-CA3) is a joint effort of 14 investigators that is supported by numerous agencies described in the acknowledgments section.
-
-
+
{{ info.Summary }}
About the cases used to generate this set of data:
-
The BXD genetic reference panel of recombinant inbred strains consists of just over 80 strains. The BXDs in this data set include 27 of the BXD strains made by Benjamin Taylor at the Jackson Laboratory in the 1970s and 1990s (BXD1 through BXD42). All of these strains are fully inbred, many well beyond the 100th filial (F) generation of inbreeding. We have also included 39 inbred (25 strains at F20+) and nearly inbred (14 strains between F14 and F20) BXD lines generated by Lu and Peirce. All of these strains, including those between F14 and F20, have been genotyped at 13,377 SNPs.
-
-
Mouse Diversity Panel (MDP). We have profiled a MDP consisting 16 inbred strains and a pair of reciprocal F1 hybrids; B6D2F1 and D2B6F1. These strains were selected for several reasons:
-
-
genetic and phenotypic diversity, including use by the Phenome Project
-
their use in making genetic reference populations including recombinant inbred strains, cosomic strains, congenic and recombinant congenic strains
-
their use by the Complex Trait Consortium to make the Collaborative Cross (Nairobi/Wellcome, Oak Ridge/DOE, and Perth/UWA)
-
genome sequence data from three sources (NHGRI, Celera, and Perlegen-NIEHS)
-
availability from The Jackson Laboratory
-
-
-
All eight parents of the Collaborative Cross (129, A, C57BL/6J, CAST, NOD, NZO, PWK, and WSB) have been included in the MDP (noted below in the list). Twelve MDP strains have been sequenced, or are currently being resequenced by Perlegen for the NIEHS. This panel will be extremely helpful in systems genetic analysis of a wide variety of traits, and will be a powerful adjunct in fine mapping modulators using what is essentially an association analysis of sequence variants.
-
-
-
129S1/SvImJ
- Collaborative Cross strain sequenced by NIEHS; background for many knockouts; Phenome Project A list
-
-
A/J
- Collaborative Cross strain sequenced by Perlegen/NIEHS; parent of the AXB/BXA panel
-
-
AKR/J
- Sequenced by NIEHS; Phenome Project B list
-
-
BALB/cByJ
- Sequenced by NIEHS; maternal parent of the CXB panel; Phenome Project A list
-
-
BALB/cJ
- Widely used strain with forebrain abnormalities (callosal defects); Phenome Project A list
-
-
C3H/HeJ Sequenced by Perlegen/NIEHS; paternal parent of the BXH panel; Phenome Project A list
-
-
C57BL/6J
- Sequenced by NHGRI; parental strain of AXB/BXA, BXD, and BXH; Phenome Project A list
-
-
C57BL/6ByJ
- Paternal substrain of B6 used to generate the CXB panel
-
-
CAST/Ei
- Collaborative Cross strain sequenced by NIEHS; Phenome Project A list
-
-
DBA/2J
- Sequenced by Perlegen/NIEHS and Celera; paternal parent of the BXD panel; Phenome Project A list
-
-
PWD/PhJ
- Sequenced by Perlegen/NIEHS; parental strain for a consomic set by Forjet and colleagues
-
-
PWK/PhJ
- Collaborative Cross strain; Phenome Project D list
-
-
WSB/EiJ Collaborative Cross strain sequenced by NIEHS; Phenome Project C list
-
-
B6D2F1 and D2B6F1
- F1 hybrids generated by crossing C57BL/6J with DBA/2J
-
-
-
We have not combined data from reciprocal F1s because they have different Y chromosome and mitochondrial haplotypes. Parent-of-origin effects (imprinting, maternal environment) may also lead to interesting differences in hippocampal transcript levels.
-
-
These strains are available from The Jackson Laboratory. BXD43 through BXD100 strains are available from Lu Lu and colleagues at UTHSC.
+
{{ info.About_Cases | safe}}
About the tissue used to generate this set of data:
-
BXD animals were obtained from UTHSC, UAB, or directly from The Jackson Laboratory (see Table 1 below). Animals were housed at UTHSC, Beth Israel Deaconess, or the Jackson Laboratory before sacrifice. Virtually all CXB animals were obtained directly at the Jackson Laboratory by Lu Lu. We thank Muriel Davisson for making it possible to collect these cases on site. Standard inbred strain stock was from The Jackson Laboratory, but most animals were housed or reared at UTHSC. Mice were killed by cervical dislocation and brains were removed and placed in RNAlater prior to dissection. Cerebella and olfactory bulbs were removed; brains were hemisected, and both hippocampi were dissected whole by Hong Tao Zhang in the Lu lab. Hippocampal samples are very close to complete (see Lu et al., 2001) but probably include variable amounts of subiculum and fimbria.
-
-
A great majority of animals used in this study were between 45 and 90 days of age (average of 66 days, maximum range from 41 to 196 days; see Table 1 below). All animals were sacrifice between 9 AM and 5 PM during the light phase.
-
-
-
A pool of dissected tissue typically from six hippocampi and three naive adults of the same strain, sex, and age was collected in one session and used to generate cRNA samples. Two-hundred and one RNA samples were extracted at UTHSC by Zhiping Jia, four samples by Shuhua Qi (R2331H1, R2332H1, P2350H1, R2349H1), and one by Siming Shou (R0129H2).
-
-
RNA Extraction: In brief, we used the RNA STAT-60 protocol (TEL-TEST "B" Bulletin No. 1), steps 5.1A (homogenization of tissue), 5.2 (RNA extraction), 5.3 (RNA precipitation), and 5.4 (RNA wash). In Step 5.4 we stopped after adding 75% ethanol (1 ml per 1 ml RNA STAT-60) and stored the mix at -80°C until further use. Before RNA labeling we thawed samples and proceeded with the remainder of Step 5.4; pelleting, drying, and redissolving the pellet in RNase-free water.
-
-
We finally purify RNA by using Na4OAc before running arrays. Here is the detailed method:
-
-
Final RNA purification protocol
-
-
-
Add 1/10th volume of 3M Na4OAc , pH 5.2. If the sample was eluted with 100 µl nuclease-free water as suggested, this will be 10 µl of 3M Na4OAc.
-
Add 2.5 volumes of 100% ethanol (250 µl if the RNA was eluted in100 µl). Mix well and incubate at –20°C for 2 hrs.
-
Centrifuge at speed of 13,000 rpm for 20 min at 4°C. Carefully remove and discard the supernatant.
-
Wash the pellet with 800 µl 75% cold ethanol, centrifuge at speed of 8,600 rpm for 5 min, and remove the 75% ethanol. Wash again.
-
To remove the last traces of ethanol, quickly respin the tube, and aspirate any residual fluid.
-
Air dry the pellet.
-
Resuspend pellet in nuclease-free water.
-
-
-
-
-
Sample Processing: Samples were processed in the INIA Bioanalytical Core at the W. Harry Feinstone Center for Genomic Research, The University of Memphis, led by Thomas R. Sutter. All processing steps were performed by Shirlean Goodwin. In brief, RNA purity was evaluated using the 260/280 nm absorbance ratio, and values had to be greater than 1.8. The majority of samples were 1.9 to 2.1. RNA integrity was assessed using the Agilent Bioanalyzer 2100. We required an RNA integrity number (RIN) of greater than 8. This RIN value is based on the intensity ratio and amplitude of 18S and 28S rRNA signals. The standard Eberwine T7 polymerase method was used to catalyze the synthesis of cDNA template from polyA-tailed RNA using Superscript II reverse transcriptase (Invitrogen Inc.). The Enzo Life Sciences, Inc., BioArray High Yield RNA Transcript Labeling Kit (T7, Part No. 42655) was used to synthesize labeled cRNA. The cRNA was evaluated using both the 260/280 ratio (values of 2.0 or 2.1 are acceptable) and the Bioanalyzer output (a dark cRNA smear on the 2100 output centered roughly between 600 and 2000 nucleotides is required). Those samples that passed both QC steps (10% usually failed and new RNA samples had to be acquired and processed) were then sheared using a fragmentation buffer included in the Affymetrix GeneChip Sample Cleanup Module (Part No. 900371). Fragmented cRNA samples were either stored at -80°C until use or were immediately injected onto the array. The arrays were hybridized and washed following standard Affymetrix protocols.
-
-
Replication and Sample Balance: Our goal was to obtain a male sample pool and female sample pool from each isogenic group. While almost all strains were orginally represented by matched male and female samples, not all data sets passed the final quality control steps. All but 5 of 99 strains (BXD55, BXD86, BXD94, BALB/cByJ, and CAST/EiJ) are represented by pairs or (rarely) trios of arrays. The first and last samples are technical replicates of a B6D2F1 hippocampal pool (aliquots R1291H3 and R1291H4).
-
-
-
Sex Balance: Based on the expression of Xist, probe set 1427262_at, DBA/2J and KK/HlJ are represented only by female samples, BXD55, and BALB/cByJ are only represented by a single male sample, BXD74 is represented by two male samples, and BXD86, BXD94, and CAST/EiJ are possibly mixed sex samples. One of the BXD9 samples, array R1523, may be a mixed sex sample pool because the expression of Xist is intermediate.
-
-
Experimental Design and Batch Structure: This data set consists arrays processed in six groups over a three month period (May 2005 to August 2005). Each group consists of 32 to 34 arrays. Sex, strain, and strain type (BXD, CXB, and MDP) were interleaved among groups to ensure reasonable balance and to minimize group-by-strain statistical confounds in group normalization. The two independent samples from a single strain were always run in different groups. All arrays were processed using a single protocol by a single operator, Shirlean Goodwin.
-
-
All samples in a group were labeled on one day, except for a few cases that failed QC on their first pass. The hybridization station accommodates up to 20 samples, and for this reason each group was split into a large first set of 20 samples and a second set of 12 to 14 samples. Samples were washed in groups of four and then held in at 4°C until all 20 (or 12-14) arrays were ready to scan. The last four samples out of the wash stations were scanned directly. Samples were scanned in sets of four.
-
-
-
COMPARISON with December 2005 Data Set: Both BXD14 arrays in the Dec05 data set were found to actually be from BXD23 cases. This error of strain identification has been corrected in the present data set. Four arrays in the Dec05 data set have been deleted because we judged them to be of poor quality (strain_sex_sample_firstreaction_group):
-
-
BXD21_F_1_1_G1
-
BXD23_M_1_1_G7
-
BXD36_M_1_1_G2
-
BXD36_F_1_1_G3
-
-
-
-In the Dec05 data set there are a total of 1986 transcripts with QTLs that have LRS scores above 50, whereas in the corrected June06 data sets there are a total of 2074 transcripts with QTLs above 50.
-
-
Data Table 1:
-This table lists all arrays by file order (Index), tube/sample ID, age, sex, batch, and numbers of animals in each sample pool (pool size). The next columns (RMA outlier, scale factor, background average, present, absent, marginal, AFFY-b-ActinMur(3'/5'), AFFY-GapdhMur(3'/5')) are all Affymetrix QC data. Finally, source lists the source colony of the animals. (Final version, fully corrected, by Arthur Centeno, October 2008)
-
-
-
-
-
-
index
-
tube ID
-
strain
-
age
-
sex
-
batch ID
-
pool size
-
RMA outlier
-
scale factor
-
back ground average
-
present
-
absent
-
marginal
-
AFFX-b-ActinMur (3'/5')
-
AFFX-GapdhMur (3'/5')
-
source
-
-
-
1
R1289H2
B6D2F1
64
F
6
3
0.02
2.406
53.84
0.492
0.489
0.019
1.61
0.96
UTM RW
-
-
2
R1291H3
B6D2F1
66
M
-
1
3
0.01
3.524
48.54
0.487
0.494
0.019
1.21
1.52
UTM RW
-
-
3
R1291H4
B6D2F1
66
M technical duplicate of above
6
3
0.08
3.891
46.69
0.512
0.469
0.019
1.9
0.89
UTM RW
-
4
R2045H2
D2B6F1
65
F
1
2
0.01
4.403
47.99
0.497
0.485
0.018
1.09
1.53
UTM RW
-
5
R1595H2
D2B6F1
63
F
5
3
0.06
2.579
58.49
0.506
0.475
0.019
2.49
1.21
UTM RW
-
6
R1551H1
D2B6F1
72
F
6
3
0.02
2.62
53.76
0.506
0.476
0.018
1.37
0.76
UTM RW
-
7
R1361H1
C57BL/6J
69
F
6
4
0.01
3.058
51.87
0.477
0.503
0.02
1.67
0.76
UTM RW
-
8
R2041H2
C57BL/6J
65
M
1
4
0.04
3.341
49.26
0.527
0.456
0.018
1.14
1.45
UTM RW
-
9
R1449H2
C57BL/6J
71
M
5
3
0.09
3.592
44.32
0.47
0.51
0.02
1.68
0.77
UTM DG
-
10
R1290H2
DBA/2J
63
F
7
2
0.04
2.576
59.6
0.513
0.468
0.018
1.3
0.78
JAX
-
11
R1468H1
DBA/2J
64
F
5
3
0.03
2.929
53.8
0.515
0.465
0.019
1.28
0.79
UTM RW
-
12
R1507H1
BXD1
58
M
3
3
0.02
4.056
60.17
0.478
0.503
0.019
1.15
0.76
Glenn
-
13
R1542H1
BXD1
59
F
7
3
0.03
1.792
80.56
0.492
0.489
0.018
1.57
0.79
Glenn
-
14
R1520H1
BXD2
56
F
4
4
0.09
1.715
71.62
0.515
0.467
0.018
2.36
1.6
Glenn
-
15
R1516H1
BXD2
61
M
1
4
0.01
2.231
64.86
0.508
0.474
0.019
1.3
1.53
Glenn
-
16
R1593H2
BXD5
60
F
1
4
0
1.913
59.96
0.487
0.493
0.02
0.98
1.44
Glenn
-
17
R1692H1
BXD5
60
M
3
2
0.07
3.764
72.74
0.465
0.516
0.02
1.15
0.74
Glenn
-
18
R1539H2
BXD6
59
F
1
4
0
2.488
54.97
0.518
0.463
0.018
1.08
1.33
Glenn
-
19
R1538H1
BXD6
59
M
4
3
0.01
2.585
50.27
0.505
0.475
0.02
1.46
0.79
Glenn
-
20
R1518H1
BXD8
56
F
1
3
0
2.92
54.84
0.515
0.465
0.02
1.32
1.24
Glenn
-
21
R1548H1
BXD8
59
M
6
3
0.07
2.132
59.37
0.504
0.477
0.019
2.16
1.54
Glenn
-
22
R1350H2
BXD9
86
F
1
3
0.05
2.771
60.62
0.5
0.482
0.018
1.01
1.28
UMemphis
-
23
R1523H3
BXD9
57
MF (mixed)
7
3
0.14
3.9
78.36
0.435
0.547
0.018
1.36
0.77
UTM RW
-
24
R1531H1
BXD11
56
F
6
3
0.06
2.229
56.36
0.505
0.475
0.02
2.23
1.02
Glenn
-
25
R1367H1
BXD11
56
M
1
3
0.01
2.11
78.78
0.503
0.477
0.02
1.07
1.27
Glenn
-
26
R1530H1
BXD12
58
F
1
3
0
3.227
53.77
0.505
0.477
0.018
0.95
1.4
Glenn
-
27
R2674H1
BXD12
59
M
7
3
0.03
1.924
83.44
0.519
0.464
0.018
1.21
0.78
Glenn
-
28
R1529H1
BXD13
58
F
6
3
0.05
2.55
59.05
0.497
0.485
0.018
2
1.54
Glenn
-
29
R1662H2
BXD13
60
M
1
3
0.03
4.603
45.81
0.509
0.472
0.019
1.3
0.82
Glenn
-
30
R1304H2
BXD14
72
F
7
3
0.03
3.946
61.87
0.484
0.498
0.018
1.22
0.77
UTM RW
-
31
R1278H2
BXD14
55
M
7
3
0.06
4.75
67.52
0.449
0.532
0.019
1.1
0.73
UTM RW
-
32
R1524H1
BXD15
60
F
6
4
0.02
2.961
50.93
0.497
0.484
0.019
1.74
0.91
Glenn
-
33
R1515H1
BXD15
61
M
1
3
0.01
3.316
57.05
0.503
0.478
0.019
1.32
1.21
Glenn
-
34
R1661H1
BXD16
61
F
1
3
0.01
2.778
59.81
0.516
0.466
0.019
1.39
1.2
Glenn
-
35
R1594H1
BXD16
61
M
4
3
0.03
2.634
53.66
0.504
0.478
0.018
1.96
1.51
Glenn
-
36
R2666H1
BXD19
60
F
7
3
0.02
2.498
76.2
0.495
0.486
0.019
1.41
0.77
Glenn
-
37
R1471H1
BXD19
157
M
1
3
0.02
3.165
43.34
0.519
0.462
0.018
1.01
1.29
UTM JB
-
38
R1573H1
BXD20
59
F
1
3
0.02
3.749
52.7
0.513
0.469
0.018
1.01
1.27
Glenn
-
39
R2507H1
BXD20
60
M
6
3
0.06
3.568
57
0.472
0.508
0.02
1.29
0.76
Glenn
-
40
R2668H1
BXD21
60
M
7
4
0.07
2.605
44.9
0.535
0.449
0.017
1.54
0.76
Glenn
-
41
R1337H2
BXD21
102
F
2
4
0
2.673
58.05
0.492
0.489
0.019
1.4
0.76
UAB
-
42
R1848H3
BXD22
196
F
6
4
0.02
2.943
51.7
0.494
0.485
0.021
2.2
0.78
UAB
-
43
R1525H1
BXD22
59
M
2
3
0.02
2.248
55.76
0.548
0.433
0.018
1.26
0.74
Glenn
-
44
R1280H2
BXD23
56
F
1
3
0.01
3.187
54.63
0.458
0.523
0.019
0.96
1.2
UTM RW
-
45
R1537H1
BXD23
58
F
5
3
0.1
3.719
67.54
0.468
0.513
0.019
1.51
0.96
Glenn
-
46
R1343H2
BXD24
71
F
2
3
0.01
2.083
65.07
0.506
0.474
0.019
1.46
0.75
UMemphis
-
47
R1517H1
BXD24
57
M
3
3
0.01
3.471
53.66
0.504
0.476
0.019
1.28
0.78
Glenn
-
48
R1366H1
BXD27
60
F
2
4
0
2.26
48.46
0.518
0.463
0.019
1.29
0.77
Glenn
-
49
R1849H1
BXD27
70
M
5
3
0.06
8.801
38.34
0.468
0.512
0.019
2.42
1.08
UAB
-
50
R1353H1
BXD28
79
F
3
4
0.01
3.22
76.22
0.48
0.5
0.02
1.33
0.78
UMemphis
-
51
R2332H1
BXD28
60
M
2
3
0.01
3.217
63.68
0.491
0.49
0.019
1.37
0.79
Glenn
-
52
R1532H1
BXD29
57
F
2
3
0.01
2.122
59.18
0.524
0.456
0.019
1.17
0.76
Glenn
-
53
R1356H1
BXD29
76
M
5
3
0.01
4.033
47.67
0.52
0.463
0.017
1.17
0.78
UMemphis
-
54
R1240H2
BXD31
61
M
2
3
0.02
2.335
65.17
0.507
0.474
0.019
1.31
0.78
UTM RW
-
55
R1526H2
BXD31
57
F
7
4
0.1
7.267
89.54
0.435
0.547
0.017
1.35
0.78
UTM RW
-
56
R2675H1
BXD32
57
F
7
3
0.03
2.268
78.01
0.502
0.478
0.02
1.22
0.78
Glenn
-
57
R1508H2
BXD32
58
M
2
4
0.01
1.917
67.78
0.539
0.442
0.019
1.28
0.73
Glenn
-
58
R1345H3
BXD33
65
F
2
2
0.01
2.098
63.14
0.522
0.459
0.019
1.27
0.73
UMemphis
-
59
R1581H1
BXD33
59
M
3
3
0.01
3.229
53.16
0.496
0.485
0.019
1.19
0.78
Glenn
-
60
R1527H1
BXD34
59
F
2
3
0.01
2.3
58.92
0.51
0.471
0.019
1.24
0.76
Glenn
-
61
R1339H3
BXD34
74
M
5
3
0.12
2.888
53.49
0.506
0.476
0.018
2.39
1.35
UMemphis
-
62
R1855H1
BXD38
55
F
3
4
0.01
3.536
54.54
0.49
0.492
0.018
1.39
0.75
Glenn
-
63
R1510H1
BXD38
59
M
2
3
0.01
2.186
68.06
0.521
0.46
0.019
1.26
0.79
Glenn
-
64
R1528H2
BXD39
59
F
2
3
0.03
4.717
38.3
0.511
0.47
0.02
1.12
0.75
Glenn
-
65
R1514H1
BXD39
59
M
3
3
0.03
3.992
56.06
0.477
0.504
0.019
1.43
0.81
Glenn
-
66
R1522H1
BXD40
59
F
4
4
0
2.631
67.16
0.49
0.491
0.018
1.56
0.77
Glenn
-
67
R1359H1
BXD40
73
M
2
3
0.09
7.458
39.86
0.451
0.527
0.021
1.28
0.74
UMemphis
-
68
R1541H2
BXD42
58
F
7
3
0.07
6.784
52.12
0.483
0.499
0.017
1.13
0.66
Glenn
-
69
R1540H1
BXD42
58
M
7
4
0.03
2.423
75.14
0.492
0.488
0.02
1.48
0.78
Glenn
-
70
R1334H2
BXD43
59
F
1
3
0
2.672
54.36
0.492
0.491
0.017
1.2
2.06
UTM RW
-
71
R1303H1
BXD43
63
M
3
4
0.02
3.497
51.9
0.486
0.495
0.019
1.15
0.8
UTM RW
-
72
R1326H1
BXD44
65
F
3
4
0
3.412
53.96
0.496
0.485
0.018
1.35
0.78
UTM RW
-
73
R1577H2
BXD44
56
M
1
3
0.02
2.159
67.52
0.512
0.469
0.019
1.18
1.71
UTM RW
-
74
R1403H2
BXD45
63
F
7
2
0.03
3.146
44.5
0.524
0.457
0.018
1.41
0.78
Glenn
-
75
R1472H1
BXD45
65
M
7
4
0.04
1.651
73.31
0.543
0.44
0.018
1.63
0.74
UTM RW
-
76
R1316H1
BXD48
58
F
4
3
0
2.445
68.59
0.515
0.467
0.019
1.16
0.73
UTM RW
-
77
R1575H3
BXD48
65
M
3
4
0.05
4.577
55.78
0.466
0.514
0.019
1.59
0.9
UTM RW
-
78
R2521H1
BXD50
63
F
6
4
0.01
3.109
57.28
0.495
0.485
0.02
1.23
0.78
UTM RW
-
79
R1944H2
BXD50
81
M
1
3
0.01
2.546
63.39
0.495
0.485
0.02
0.9
1.57
UTM RW
-
80
R2331H1
BXD51
66
F
3
3
0.03
3.534
44.42
0.501
0.481
0.017
1.2
0.9
UTM RW
-
81
R1582H1
BXD51
71
M
6
4
0.03
2.92
47.87
0.489
0.491
0.02
1.36
0.75
UTM RW
-
82
R2680H1
BXD55
65
M
7
3
0.07
1.707
79.75
0.503
0.48
0.017
1.91
1.05
UTM RW
-
83
R1331H1
BXD60
60
F
4
3
0.01
2.867
50.33
0.492
0.487
0.021
1.34
0.78
UTM RW
-
84
R1281H2
BXD60
59
M
1
3
0
2.39
58.44
0.511
0.469
0.02
0.94
1.2
UTM RW
-
85
R2667H1
BXD61
70
F
7
4
0.03
3.36
59.04
0.495
0.488
0.018
1.16
0.76
UTM RW
-
86
R1856H2
BXD61
94
M
1
2
0
3.502
49.6
0.501
0.48
0.019
0.96
1.3
UTM RW
-
87
R1246H1
BXD62
54
F
1
4
0.02
3.405
51.47
0.511
0.471
0.018
1.14
1.34
UTM RW
-
88
R1585H2
BXD62
64
M
6
4
0.01
3.156
55.77
0.518
0.464
0.018
1.43
0.82
UTM RW
-
89
R1945H1
BXD63
107
F
1
3
0.02
2.811
52.65
0.522
0.459
0.019
1.05
1.36
UTM RW
-
90
R2093H3
BXD63
70
M
6
3
0.02
3.894
42.85
0.503
0.477
0.019
1.29
1.01
UTM RW
-
91
R2062H2
BXD64
65
F
1
3
0.05
3.795
78.48
0.513
0.468
0.019
0.98
1.43
UTM RW
-
92
R2061H1
BXD64
87
M
3
4
0.01
3.536
61.57
0.477
0.504
0.019
1.31
0.78
UTM RW
-
93
R2054H2
BXD65
55
F
1
2
0.03
3.159
80.96
0.48
0.502
0.018
1.09
1.24
UTM RW
-
94
R2056H2
BXD65
89
M
6
2
0
2.836
59.6
0.504
0.477
0.019
1.3
0.75
UTM RW
-
95
R1941H2
BXD66
78
F
1
4
0.01
2.734
50.93
0.499
0.481
0.02
1.18
1.29
UTM RW
-
96
R1949H2
BXD66
96
M
4
2
0.04
2.828
51.27
0.474
0.508
0.019
2.05
1.12
UTM RW
-
97
R2060H1
BXD67
54
F
6
3
0.01
2.561
43.88
0.502
0.479
0.02
1.7
0.84
UTM RW
-
98
R2052H1
BXD67
61
M
1
4
0.01
3.161
43.23
0.521
0.46
0.018
1.09
1.31
UTM RW
-
99
R2074H1
BXD68
60
F
5
3
0.02
6.528
49.62
0.479
0.502
0.019
1.48
0.83
UTM RW
-
100
R1928H1
BXD68
72
M
2
2
0.01
2.404
48.28
0.521
0.459
0.02
1.3
0.74
UTM RW
-
101
R1439H3
BXD69
60
F
2
3
0.02
2.463
59.14
0.522
0.459
0.018
1.31
0.78
UTM RW
-
102
R1559H1
BXD69
64
M
3
3
0.03
2.987
67.74
0.486
0.496
0.017
1.38
0.8
UTM RW
-
103
R2134H1
BXD70
64
F
5
2
0.02
2.148
58.64
0.532
0.45
0.019
1.4
0.85
UTM RW
-
104
R2063H1
BXD70
55
M
2
3
0.02
3.481
55.32
0.513
0.469
0.018
1.28
0.71
UTM RW
-
105
R1277H1
BXD73
60
F
4
2
0.01
2.576
62.45
0.502
0.479
0.019
1.35
0.79
UTM RW
-
106
R1443H2
BXD73
76
M
2
3
0.01
2.312
64.34
0.499
0.481
0.02
1.48
0.77
UTM RW
-
107
R2055H2
BXD74
79
M
2
3
0.01
2.576
56.84
0.509
0.473
0.018
1.46
0.88
UTM RW
-
108
R2316H1
BXD74
193
M
5
2
0.01
3.457
55.35
0.508
0.471
0.02
1.17
0.78
UTM RW
-
109
R1871H1
BXD75
61
F
2
3
0.04
1.723
56.4
0.53
0.451
0.019
1.3
0.76
UTM RW
-
110
R1844H2
BXD75
90
M
3
4
0.01
1.934
56.23
0.52
0.461
0.019
1.62
0.86
UTM RW
-
111
R1948H2
BXD76
81
F
2
3
0.01
1.507
68.85
0.553
0.428
0.02
1.3
0.75
UTM RW
-
112
R2094H1
BXD76
61
M
5
4
0.01
3.299
42.69
0.519
0.462
0.019
1.39
0.88
UTM RW
-
113
R2262H1
BXD77
62
F
3
4
0.02
4.317
47.16
0.493
0.488
0.019
1.32
0.74
UTM RW
-
114
R1423H1
BXD77
62
M
2
3
0.02
3.071
54.15
0.51
0.471
0.019
1.26
0.74
UTM RW
-
115
R1947H1
BXD79
108
F
2
2
0.01
2.599
51.52
0.524
0.457
0.019
1.35
0.74
UTM RW
-
116
R2092H1
BXD79
86
M
5
4
0.06
3.735
42.25
0.514
0.468
0.018
2.94
1.06
UTM RW
-
117
R1880H1
BXD80
68
F
5
3
0.06
4.855
42.22
0.501
0.481
0.018
2.17
1.36
UTM RW
-
118
R1881H2
BXD80
68
M
2
3
0.02
2.073
48.93
0.524
0.458
0.019
1.34
0.83
UTM RW
-
119
R2075H1
BXD83
60
F
2
3
0.01
2.454
55.1
0.502
0.48
0.018
1.27
0.77
UTM RW
-
120
R2076H2
BXD83
60
M
6
3
0.03
2.624
55.65
0.495
0.488
0.018
2.21
0.94
UTM RW
-
121
R2077H2
BXD84
62
F
6
2
0
2.1
71.87
0.522
0.459
0.018
1.68
0.81
UTM RW
-
122
R2135H3
BXD84
75
M
2
2
0.01
2.467
64.46
0.505
0.476
0.019
1.2
0.74
UTM RW
-
123
R1473H1
BXD85
79
F
2
3
0.02
3.384
55.34
0.478
0.502
0.02
1.24
0.77
UTM RW
-
124
R1474H1
BXD85
57
M
1
3
0.01
2.831
55.24
0.522
0.461
0.018
1.04
1.29
UTM RW
-
125
R1597H1
BXD85
86
M
4
4
0.09
2.028
53.95
0.487
0.492
0.021
1.28
0.83
UTM RW
-
126
R1415H1
BXD86
77
F
4
3
0.02
2.525
53.16
0.495
0.485
0.02
1.66
0.91
UTM RW
-
127
R2669H2
BXD87
63
F
7
3
0.07
2.61
57.59
0.513
0.47
0.018
1.6
0.91
UTM RW
-
128
R1710H1
BXD87
84
M
2
4
0.01
2.697
56.4
0.512
0.469
0.019
1.28
0.79
UTM RW
-
129
R1872H2
BXD89
90
F
2
2
0.02
3.013
63.53
0.492
0.488
0.021
1.22
0.72
UTM RW
-
130
R1850H3
BXD89
82
M
4
4
0.03
2.736
44.89
0.498
0.483
0.019
1.5
0.83
UTM RW
-
131
R2058H1
BXD90
61
F
2
3
0.01
3.389
48.05
0.502
0.478
0.02
1.53
0.76
UTM RW
-
132
R1600H2
BXD90
74
M
7
4
0.03
3.261
51.31
0.517
0.465
0.018
1.16
0.75
Glenn
-
133
R1301H2
BXD92
58
F
2
3
0.02
3.543
41.97
0.522
0.46
0.018
1.5
0.79
UTM RW
-
134
R1309H1
BXD92
59
M
4
3
0.05
1.655
66.34
0.498
0.481
0.021
1.52
0.82
UTM RW
-
135
R2057H1
BXD93
92
F
5
3
0.02
4.033
44.41
0.509
0.471
0.02
1.22
0.78
UTM RW
-
136
R2059H1
BXD93
58
M
1
3
0
3.058
60.29
0.493
0.488
0.019
1.18
1.37
UTM RW
-
137
R2313H1
BXD94
59
F
3
3
0
3.091
59.45
0.487
0.495
0.018
1.34
0.73
UTM RW
-
138
R1915H1
BXD96
65
F
5
2
0.04
5.145
46.19
0.502
0.481
0.017
1.37
0.74
UTM RW
-
139
R1846H2
BXD96
63
M
1
3
0
3.159
55.85
0.487
0.493
0.02
0.92
1.26
UTM RW
-
140
R2648H1
BXD97
74
F
7
4
0.02
1.664
82.08
0.518
0.464
0.019
1.4
0.78
UTM RW
-
141
R1927H2
BXD97
67
M
1
3
0.04
2.622
57.81
0.539
0.444
0.017
1.45
1.32
UTM RW
-
142
R1942H1
BXD98
62
F
5
3
0.04
3.104
48.42
0.528
0.454
0.019
2.22
1.08
UTM RW
-
143
R1943H2
BXD98
62
M
3
3
0.02
4.04
56.85
0.484
0.497
0.019
1.18
0.76
UTM RW
-
144
R2197H1
BXD99
70
F
3
3
0.02
4.288
51.75
0.49
0.492
0.018
1.35
0.81
UTM RW
-
145
R2315H1
BXD99
84
M
5
2
0.03
6.036
43.05
0.484
0.497
0.018
1.7
0.96
UTM RW
-
146
R2028H2
129S1/SvImJ
66
F
5
3
0.1
4.362
64.49
0.497
0.484
0.019
2.78
1.13
JAX
-
147
R2029H2
129S1/SvImJ
66
M
6
3
0.04
5.208
41.21
0.49
0.49
0.02
1.62
0.95
JAX
-
148
R2670H1
A/J
65
F
7
3
0.04
3.951
46.8
0.498
0.485
0.017
1.32
0.75
UTM RW
-
149
R2030H1
A/J
57
M
5
2
0.06
3.307
45.16
0.527
0.454
0.018
1.63
0.99
UTM RW
-
150
R2032H3
AKR/J
66
F
5
3
0.04
3.054
61.03
0.51
0.471
0.018
1.46
0.79
JAX
-
151
R2454H1
AKR/J
66
M
6
4
0.11
2.892
58.55
0.474
0.507
0.019
1.99
0.78
JAX
-
152
R1675H1
BALB/cByJ
83
M
7
3
0.03
3.405
48.13
0.509
0.474
0.018
1.13
0.78
JAX
-
153
R2036H3
BALB/cJ
51
F
5
3
0.12
2.611
56.29
0.518
0.466
0.017
3.3
1.23
UTM RW
-
154
R2053H1
BALB/cJ
55
M
5
3
0.1
2.505
63.27
0.499
0.483
0.018
3.1
1.34
UTM RW
-
155
R2037H2
BALB/cJ
51
M
6
4
0.01
2.546
58.13
0.497
0.485
0.018
1.26
0.77
UTM RW
-
156
R2038H3
C3H/HeJ
63
F
6
3
0.02
2.671
66.74
0.476
0.504
0.02
1.41
0.77
UTM RW
-
157
R2039H1
C3H/HeJ
63
M
5
3
0.1
3.384
44.15
0.528
0.454
0.017
2.16
0.88
UTM RW
-
158
R2137H1
C57BL/6ByJ
55
F
5
3
0.02
4.746
47.01
0.488
0.493
0.018
1.23
0.79
JAX
-
159
R2673H1
C57BL/6ByJ
55
M
7
3
0.08
1.842
67.69
0.514
0.469
0.017
1.75
0.78
JAX
-
160
R2619H1
CAST/EiJ
64
F
5
3
0.14
4.077
51.87
0.455
0.528
0.018
2.74
1.2
JAX
-
161
R1683H1
KK/HIJ
72
F
6
3
0.02
3.919
54.23
0.491
0.489
0.02
1.31
0.83
JAX
-
162
R1687H3
KK/HIJ
72
F
5
3
0.04
3.888
40.86
0.499
0.483
0.019
1.86
0.88
JAX
-
163
R2046H1
LG/J
63
F
5
2
0.03
2.822
59.18
0.514
0.468
0.018
1.68
0.8
UTM RW
-
164
R2047H2
LG/J
63
M
6
3
0.07
2.038
60.34
0.509
0.471
0.02
2.16
0.95
UTM RW
-
165
R2048H1
NOD/LtJ
77
F
6
2
0.14
4.045
50.21
0.489
0.49
0.021
2.89
0.95
UTM RW
-
166
R2049H3
NOD/LtJ
76
M
5
3
0.1
2.328
52.78
0.519
0.462
0.019
3.09
1.35
UTM RW
-
167
R2200H1
NZO/HlLtJ
62
F
5
2
0.03
2.648
54.29
0.543
0.438
0.019
1.27
0.8
JAX
-
168
R2350H1
NZO/HlLtJ
96
M
6
2
0.19
2.391
50.52
0.518
0.463
0.02
3.71
2.21
JAX
-
169
R2677H1
PWD/PhJ
65
M
7
2
0.12
2.764
65.49
0.462
0.52
0.018
1.89
1.16
UTM RW
-
170
R2051H3
PWD/PhJ
64
M
5
3
0.07
3.266
51.5
0.475
0.506
0.019
2.8
1.01
UTM RW
-
171
R2322H1
PWK/PhJ
63
F
5
2
0.09
2.94
54.91
0.511
0.47
0.019
2.32
1.02
JAX
-
172
R2349H1
PWK/PhJ
83
M
6
2
0.15
3.306
54.93
0.459
0.522
0.019
4.65
1.45
JAX
-
173
R2198H2
WSB/EiJ
58
F
6
1
0.02
2.922
57.97
0.502
0.479
0.019
1.44
0.76
JAX
-
174
R2199H1
WSB/EiJ
58
M
5
3
0.04
3.171
54.95
0.475
0.505
0.02
1.32
0.81
JAX
-
175
R2116H1
CXB1
55
F
3
3
0.07
5.792
51.59
0.459
0.521
0.02
1.17
0.8
JAX
-
176
R2096H1
CXB1
55
M
4
2
0.01
3.435
53.78
0.495
0.485
0.02
1.22
0.79
JAX
-
177
R2117H2
CXB2
62
F
4
2
0.04
3.39
45.97
0.533
0.45
0.017
2.05
0.89
JAX
-
178
R2098H1
CXB2
68
M
3
3
0.02
2.572
54.22
0.496
0.485
0.019
1.38
0.86
JAX
-
179
R2118H1
CXB3
47
F
3
3
0.03
3.646
63.16
0.478
0.503
0.019
1.22
0.77
JAX
-
180
R2100H1
CXB3
47
M
4
3
0.02
5.76
51.38
0.48
0.503
0.017
1.24
0.81
JAX
-
181
R2119H1
CXB4
58
F
4
3
0.02
3.897
49.21
0.488
0.494
0.018
1.31
0.79
JAX
-
182
R2101H1
CXB4
58
M
3
3
0.13
7.372
53.77
0.433
0.548
0.019
1.2
0.97
JAX
-
183
R2505H1
CXB5
80
F
6
3
0.02
2.83
49.6
0.499
0.48
0.02
1.33
0.76
UTM RW
-
184
R2131H1
CXB5
42
M
4
3
0.1
5.577
51.15
0.434
0.547
0.019
1.7
0.89
JAX
-
185
R0129H2
CXB5
70
M
3
3
0.07
4.829
45.42
0.488
0.493
0.019
1.23
0.83
UTM RW
-
186
R2676H1
CXB6
47
F
7
2
0.05
2.146
62.51
0.507
0.475
0.018
1.52
0.78
JAX
-
187
R2102H1
CXB6
49
M
4
3
0.07
5.148
51.63
0.453
0.529
0.018
1.43
0.87
JAX
-
188
R2121H1
CXB7
63
F
4
2
0.06
4.904
48.71
0.464
0.517
0.019
1.19
0.92
JAX
-
189
R2104H2
CXB7
58
M
3
2
0.06
3.389
48.79
0.502
0.479
0.019
1.74
1.48
JAX
-
190
R2122H1
CXB8
54
F
3
3
0.04
4.128
59.77
0.451
0.529
0.02
1.12
0.76
JAX
-
191
R2105H1
CXB8
41
M
4
3
0.16
3.146
61.04
0.451
0.53
0.019
1.34
0.84
JAX
-
192
R2123H1
CXB9
54
F
3
3
0.08
5.708
55.94
0.438
0.543
0.019
1.32
0.78
JAX
-
193
R2106H1
CXB9
54
M
4
3
0.06
5.868
46.55
0.469
0.512
0.019
1.18
0.82
JAX
-
194
R2124H1
CXB10
53
F
4
2
0.11
4.867
39.88
0.451
0.528
0.02
1.55
0.8
JAX
-
195
R2671H1
CXB10
53
M
7
3
0.09
2.348
71.45
0.488
0.494
0.018
2.2
1.14
JAX
-
196
R2125H1
CXB11
58
F
3
3
0.03
3.256
54.95
0.461
0.519
0.02
1.46
0.77
JAX
-
197
R2128H1
CXB11
58
M
4
2
0.06
4.986
54.13
0.465
0.515
0.02
1.11
0.83
JAX
-
198
R2126H1
CXB12
47
F
4
3
0.11
3.935
54.11
0.469
0.511
0.021
1.5
0.79
JAX
-
199
R2109H1
CXB12
47
M
3
3
0.07
4.518
49.26
0.488
0.492
0.02
1.23
0.77
JAX
-
200
R2672H1
CXB13
49
F
7
3
0.03
1.722
79.52
0.516
0.465
0.019
1.64
0.75
JAX
-
201
R2110H1
CXB13
56
M
4
3
0.21
3.478
48.08
0.461
0.517
0.022
1.21
0.78
JAX
-
-
-
+
{{ info.About_Tissue }}
About downloading this data set:
All data links (right-most column above) will be made active as sooon as the global analysis of these data by the Consortium has been accepted for publication. Please see text on Data Sharing Policies, and Conditions and Limitations, and Contacts. Following publication, download a summary text file or Excel file of the PDNN probe set data. Contact RW Williams regarding data access problems.
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 89f0b3d7..06d8227c 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -29,6 +29,8 @@ def data_sharing():
print("1Have fd")
sharingInfoObject = SharingInfo.SharingInfo(request.args['GN_AccessionId'], None)
info, htmlfilelist = sharingInfoObject.getBody(infoupdate="")
+ print("type(htmlfilelist):", type(htmlfilelist))
+ htmlfilelist = htmlfilelist.encode("utf-8")
#template_vars = SharingInfo.SharingInfo(request.args['GN_AccessionId'], None)
print("1 Made it to rendering")
return render_template("data_sharing.html",
--
cgit v1.2.3
From f93de74671feafbabeed50c80226d57388210d01 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Thu, 12 Jul 2012 21:48:55 -0400
Subject: Dictionary code now works
---
wqflask/wqflask/dataSharing/SharingInfo.py | 31 ++++++++++++++++++++++-------
wqflask/wqflask/templates/data_sharing.html | 6 +++---
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/wqflask/wqflask/dataSharing/SharingInfo.py b/wqflask/wqflask/dataSharing/SharingInfo.py
index 1d22d57c..4845b5c8 100755
--- a/wqflask/wqflask/dataSharing/SharingInfo.py
+++ b/wqflask/wqflask/dataSharing/SharingInfo.py
@@ -60,7 +60,7 @@ class SharingInfo(object):
About_Array_Platform, About_Data_Values_Processing,
Data_Source_Acknowledge, Progreso """
- InfoRecord = namedtuple('InfoRecord', field_names)
+ #InfoRecord = namedtuple('InfoRecord', field_names)
# We can use string interpolation here cause we own the string
sql = """select %s from InfoFiles where """ % (field_names)
@@ -75,14 +75,18 @@ class SharingInfo(object):
info = cursor.fetchone()
print("432 info:", info)
print("type(info):", type(info))
- info = InfoRecord._make(info)
-
- print("q888 info.Title:", info.Title)
+ #info = InfoRecord._make(info)
+ info = todict(field_names, info)
+ # We need to edit info so we convert it to a dict...
+ #info = info._asdict()
+ print("q888 info.Title:", info['Title'])
print("info type is:", type(info))
- new_about_cases = unicode(info.About_Cases, "utf-8")
- print("new_about_cases is:", new_about_cases)
- info.About_Cases = new_about_cases
+ #new_about_cases = unicode(info.About_Cases, "utf-8")
+ #print("new_about_cases is:", new_about_cases)
+
+
+ #info['About_Cases'] = unicode(info['About_Cases'], "utf-8")
# fetch datasets file list
try:
@@ -130,3 +134,16 @@ class SharingInfo(object):
print("333 keys:", pf(info))
return info, htmlfilelist
#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])
+
+
+def todict(fields, values):
+ """Converts sql results into a user friendly dictionary"""
+ new_dict = {}
+ fields = fields.split(",")
+ for counter, field in enumerate(fields):
+ field = field.strip()
+ value = values[counter]
+ if isinstance(value, str):
+ value = unicode(value, "utf-8")
+ new_dict[field] = value
+ return new_dict
diff --git a/wqflask/wqflask/templates/data_sharing.html b/wqflask/wqflask/templates/data_sharing.html
index a6e044b4..4e92106a 100644
--- a/wqflask/wqflask/templates/data_sharing.html
+++ b/wqflask/wqflask/templates/data_sharing.html
@@ -56,11 +56,11 @@
Summary:
-
{{ info.Summary }}
+
{{ info.Summary | safe}}
About the cases used to generate this set of data:
-
{{ info.About_Cases | safe}}
+
{{ info.About_Cases | safe}}
About the tissue used to generate this set of data:
-
{{ info.About_Tissue }}
+
{{ info.About_Tissue | safe }}
About downloading this data set:
All data links (right-most column above) will be made active as sooon as the global analysis of these data by the Consortium has been accepted for publication. Please see text on Data Sharing Policies, and Conditions and Limitations, and Contacts. Following publication, download a summary text file or Excel file of the PDNN probe set data. Contact RW Williams regarding data access problems.
--
cgit v1.2.3
From 9d22fe88365c96a092febeab9cef7775dcb5a773 Mon Sep 17 00:00:00 2001
From: Sam Ockman
Date: Sun, 15 Jul 2012 21:17:49 -0400
Subject: Continuing trait data table in js
---
wqflask/wqflask/dataSharing/SharingInfo.py | 19 +------
wqflask/wqflask/show_trait/DataEditingPage.py | 24 ++++-----
.../new/javascript/trait_data_and_analysis.coffee | 60 ++++++++++++++++++++++
.../new/javascript/trait_data_and_analysis.js | 52 ++++++++++++++++++-
.../wqflask/templates/trait_data_and_analysis.html | 6 ++-
5 files changed, 129 insertions(+), 32 deletions(-)
diff --git a/wqflask/wqflask/dataSharing/SharingInfo.py b/wqflask/wqflask/dataSharing/SharingInfo.py
index 4845b5c8..289754d0 100755
--- a/wqflask/wqflask/dataSharing/SharingInfo.py
+++ b/wqflask/wqflask/dataSharing/SharingInfo.py
@@ -60,8 +60,6 @@ class SharingInfo(object):
About_Array_Platform, About_Data_Values_Processing,
Data_Source_Acknowledge, Progreso """
- #InfoRecord = namedtuple('InfoRecord', field_names)
-
# We can use string interpolation here cause we own the string
sql = """select %s from InfoFiles where """ % (field_names)
if(self.GN_AccessionId):
@@ -73,20 +71,8 @@ class SharingInfo(object):
else:
raise 'No correct parameter found'
info = cursor.fetchone()
- print("432 info:", info)
- print("type(info):", type(info))
- #info = InfoRecord._make(info)
- info = todict(field_names, info)
- # We need to edit info so we convert it to a dict...
- #info = info._asdict()
- print("q888 info.Title:", info['Title'])
-
- print("info type is:", type(info))
- #new_about_cases = unicode(info.About_Cases, "utf-8")
- #print("new_about_cases is:", new_about_cases)
-
- #info['About_Cases'] = unicode(info['About_Cases'], "utf-8")
+ info = todict(field_names, info)
# fetch datasets file list
try:
@@ -130,8 +116,7 @@ class SharingInfo(object):
htmlfilelist += ""
else:
htmlfilelist = "Data sets are not available or are not public yet."
- print("333 info is:", pf(info))
- print("333 keys:", pf(info))
+
return info, htmlfilelist
#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/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index 81bb3a92..610124ae 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -213,18 +213,18 @@ class DataEditingPage(templatePage):
self.hddn = hddn
self.basic_table = {}
- self.basic_table['rows'] = yaml.load("""
- - N of Samples
- - Mean
- - Median
- - Standard Error (SE)
- - Standard Deviation (SD)
- - Minimum
- - Maximum
- - Range (log2)
- - Range (fold)
- - Interquartile Range
- """)
+ #self.basic_table['rows'] = yaml.load("""
+ # - N of Samples
+ # - Mean
+ # - Median
+ # - Standard Error (SE)
+ # - Standard Deviation (SD)
+ # - Minimum
+ # - Maximum
+ # - Range (log2)
+ # - Range (fold)
+ # - Interquartile Range
+ # """)
self.basic_table['columns'] = yaml.load("""
- All Cases
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
index 380d0a5a..d3817f99 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
@@ -55,6 +55,66 @@ $ ->
the_values.push(parseFloat(real_value))
mean(the_values)
+ make_table = ->
+ header = "
"
+ for column in basic_table['columns']
+ the_id = process_id("column_" + column)
+ header += """
+
+ {% for tissue in corr_tools.dataset_menu %}
+ {% if tissue.tissue %}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+
+
+
+
Return:
+
+
+ {% for return_result in corr_tools.return_results_menu %}
+
+ {% endfor %}
+
+
-
-
-
-
-
-
-
-
Return:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Samples:
-
-
-
-
-
-
-
-
-
-
- Pearson Spearman Rank
-
-
-
- The Sample Correlation is computed
- between trait data and any
- other traits in the sample database selected above. Use Spearman
- Rank
- when the sample size is small (<20) or when there are influential outliers.
-
-
-
-
- The Literature Correlation (Lit r) between this
- gene and all other genes is computed
- using the Semantic Gene Organizer and human, rat, and
- mouse data from PubMed.
- Values are ranked by Lit r, but Sample r and Tissue r are also displayed.
-
- More on using Lit r
-
+
+ {% for group, pretty_group in sample_groups.items() %}
+
+ {% endfor %}
+
+
+
- Pearson Spearman Rank
+ Pearson Spearman Rank
-
+
+
+ The Sample Correlation
+ is computed
+ between trait data and any
+ other traits in the sample database selected above. Use
+ Spearman
+ Rank
+ when the sample size is small (<20) or when there are influential outliers.
+
+
+ The Literature Correlation
+ (Lit r) between
+ this gene and all other genes is computed
+ using the
+ Semantic Gene Organizer
+ and human, rat, and mouse data from PubMed.
+ Values are ranked by Lit r, but Sample r and Tissue r are also displayed.
+ More on using Lit r
+
+
+ The Tissue Correlation
+ (Tissue r)
+ estimates the similarity of expression of two genes
+ or transcripts across different cells, tissues, or organs
+ (glossary).
+ Tissue correlations
+ are generated by analyzing expression in multiple samples usually taken from single cases.
+ Pearson and Spearman Rank correlations have been
+ computed for all pairs of genes using data from mouse samples.
+
- The Tissue Correlation (Tissue r)
- estimates the similarity of expression of two genes
- or transcripts across different cells, tissues, or organs (glossary). Tissue correlations
- are generated by analyzing expression in multiple samples usually taken from single cases.
- Pearson and Spearman Rank correlations have been computed for all pairs of genes
- using data from mouse samples.
--
cgit v1.2.3
From e7e3117695ef86a28df96cf32bfb66f6da2bc404 Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Fri, 7 Sep 2012 17:08:36 -0500
Subject: Worked with passing form data to correlation page
---
wqflask/base/webqtlFormData.py | 73 +-
wqflask/wqflask/correlation/CorrelationPage.py | 2069 ++++++++++++++++++++
wqflask/wqflask/correlation/__init__.py | 0
wqflask/wqflask/correlation/correlationFunction.py | 923 +++++++++
wqflask/wqflask/show_trait/DataEditingPage.py | 4 +-
wqflask/wqflask/show_trait/show_trait_page.py | 6 +-
.../new/javascript/trait_data_and_analysis.coffee | 21 +-
.../new/javascript/trait_data_and_analysis.js | 17 +-
.../wqflask/templates/trait_data_and_analysis.html | 17 +-
wqflask/wqflask/views.py | 10 +-
10 files changed, 3094 insertions(+), 46 deletions(-)
create mode 100644 wqflask/wqflask/correlation/CorrelationPage.py
create mode 100644 wqflask/wqflask/correlation/__init__.py
create mode 100644 wqflask/wqflask/correlation/correlationFunction.py
diff --git a/wqflask/base/webqtlFormData.py b/wqflask/base/webqtlFormData.py
index 06faacc0..a9e3b7d4 100755
--- a/wqflask/base/webqtlFormData.py
+++ b/wqflask/base/webqtlFormData.py
@@ -25,6 +25,10 @@
# Last updated by GeneNetwork Core Team 2010/10/20
#from mod_python import Cookie
+
+from __future__ import print_function
+from pprint import pformat as pf
+
import string
import os
@@ -47,12 +51,25 @@ class webqtlFormData:
#XZ: Attention! All attribute values must be picklable!
- def __init__(self, start_vars = None, req = None, mod_python_session=None, FieldStorage_formdata=None):
-
- self.__dict__.update(start_vars)
-
- for item in self.attrs:
- setattr(self,item, None)
+ def __init__(self,
+ start_vars = None,
+ req = None,
+ mod_python_session=None,
+ FieldStorage_formdata=None):
+ # Todo: rework this whole thing
+ print("in webqtlFormData start_vars are:", pf(start_vars))
+ for item in webqtlFormData.attrs:
+ self.__dict__[item] = None
+ #self.__dict__.update(start_vars)
+ for item in start_vars:
+ self.__dict__[item] = start_vars[item]
+ print(" Now self.dict is:", pf(self.__dict__))
+ #for item in self.attrs:
+ # if getattr(self, item, None):
+ # print("Setting item %s to None" % (item,))
+ # self.attrs[item] = None
+ # else:
+ # self.attrs[item] = self.attrs[item].strip()
try:
self.remote_ip = req.connection.remote_ip
@@ -84,31 +101,37 @@ class webqtlFormData:
# if value != None:
# setattr(self,item,string.strip(value))
- self.ppolar = ""
- self.mpolar = ""
+ self.ppolar = None
+ self.mpolar = None
+
+ print("[yellow] self.RISet is:", self.RISet)
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
-
+ #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
+
+
+ def set_number(stringy):
+ return int(stringy) if stringy else 2000 # Rob asked to change the default value to 2000
+
+ self.nperm = set_number(self.nperm)
+ self.nboot = set_number(self.nboot)
+
+
+ #if self.allstrainlist:
+ # self.allstrainlist = map(string.strip, string.split(self.allstrainlist))
+ print("self.allstrainlist is:", self.allstrainlist)
if self.allstrainlist:
- self.allstrainlist = map(string.strip, string.split(self.allstrainlist))
+ self.allstrainlist = self.allstrainlist.split()
+ print("now self.allstrainlist is:", self.allstrainlist)
#self.readGenotype()
#self.readData()
if self.RISet == 'BXD300':
self.RISet = 'BXD'
- else:
- pass
+
def __getitem__(self, key):
return self.__dict__[key]
@@ -133,7 +156,7 @@ class webqtlFormData:
self.RISet = 'BXD'
else:
pass
- assert self.RISet
+ 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()
diff --git a/wqflask/wqflask/correlation/CorrelationPage.py b/wqflask/wqflask/correlation/CorrelationPage.py
new file mode 100644
index 00000000..9caf6595
--- /dev/null
+++ b/wqflask/wqflask/correlation/CorrelationPage.py
@@ -0,0 +1,2069 @@
+## 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
+# Last updated by Christian Fernandez 2012/04/07
+# Refactored correlation calculation into smaller functions in preparation of
+# separating html from existing code
+
+from __future__ import print_function
+
+import string
+from math import *
+import cPickle
+import os
+import time
+#import pyXLWriter as xl
+import pp
+import math
+
+from pprint import pformat as pf
+
+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.
+import correlationFunction
+
+import logging
+logging.basicConfig(filename="/tmp/gn_log", level=logging.INFO)
+_log = logging.getLogger("correlation")
+
+METHOD_SAMPLE_PEARSON = "1"
+METHOD_SAMPLE_RANK = "2"
+METHOD_LIT = "3"
+METHOD_TISSUE_PEARSON = "4"
+METHOD_TISSUE_RANK = "5"
+
+TISSUE_METHODS = [METHOD_TISSUE_PEARSON, METHOD_TISSUE_RANK]
+
+TISSUE_MOUSE_DB = 1
+
+class AuthException(Exception): pass
+
+
+class Trait(object):
+ def __init__(self, name, raw_values = None, lit_corr = None, tissue_corr = None, p_tissue = None):
+ self.name = name
+ self.raw_values = raw_values
+ self.lit_corr = lit_corr
+ self.tissue_corr = tissue_corr
+ self.p_tissue = p_tissue
+ self.correlation = 0
+ self.p_value = 0
+
+ @staticmethod
+ def from_csv(line, data_start = 1):
+ name = line[0]
+ numbers = line[data_start:]
+ # _log.info(numbers)
+ numbers = [ float(number) for number in numbers ]
+
+ return Trait(name, raw_values = numbers)
+
+ def calculate_correlation(self, values, method):
+ """Calculate the correlation value and p value according to the method specified"""
+
+ #ZS: This takes the list of values of the trait our selected trait is being correlated against and removes the values of the samples our trait has no value for
+ #There's probably a better way of dealing with this, but I'll have to ask Christian
+ updated_raw_values = []
+ updated_values = []
+ for i in range(len(values)):
+ if values[i] != "None":
+ updated_raw_values.append(self.raw_values[i])
+ updated_values.append(values[i])
+
+ self.raw_values = updated_raw_values
+ values = updated_values
+
+ if method == METHOD_SAMPLE_PEARSON or method == METHOD_LIT or method == METHOD_TISSUE_PEARSON:
+ corr,nOverlap = webqtlUtil.calCorrelation(self.raw_values, values, len(values))
+ else:
+ corr,nOverlap = webqtlUtil.calCorrelationRank(self.raw_values, values, len(values))
+
+ self.correlation = corr
+ self.overlap = nOverlap
+
+ if self.overlap < 3:
+ self.p_value = 1.0
+ else:
+ #ZS - This is probably the wrong way to deal with this. Correlation values of 1.0 definitely exist (the trait correlated against itself), so zero division needs to br prevented.
+ if abs(self.correlation) >= 1.0:
+ self.p_value = 0.0
+ else:
+ ZValue = 0.5*log((1.0+self.correlation)/(1.0-self.correlation))
+ ZValue = ZValue*sqrt(self.overlap-3)
+ self.p_value = 2.0*(1.0 - reaper.normp(abs(ZValue)))
+
+
+
+#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
+
+def get_correlation_method_key(form_data):
+ #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.
+
+ method = form_data.formdata.getvalue("method")
+ if method not in ["1", "2", "3" ,"4", "5"]:
+ return "1"
+
+ return method
+
+
+def get_custom_trait(form_data, cursor):
+ """Pulls the custom trait, if it exists, out of the form data"""
+ trait_name = form_data.formdata.getvalue('fullname')
+
+ if trait_name:
+ trait = webqtlTrait(fullname=trait_name, cursor=cursor)
+ trait.retrieveInfo()
+ return trait
+ else:
+ return None
+
+
+#XZ, 09/18/2008: get the information such as value, variance of the input strain names from the form.
+def get_sample_data(form_data):
+ if form_data.allstrainlist:
+ mdpchoice = form_data.formdata.getvalue('MDPChoice')
+ #XZ, in HTML source code, it is "BXD Only" or "BXH only", and so on
+ if mdpchoice == "1":
+ strainlist = form_data.f1list + form_data.strainlist
+ #XZ, in HTML source code, it is "MDP Only"
+ elif mdpchoice == "2":
+ strainlist = []
+ strainlist2 = form_data.f1list + form_data.strainlist
+ for strain in form_data.allstrainlist:
+ if strain not in strainlist2:
+ strainlist.append(strain)
+ #So called MDP Panel
+ if strainlist:
+ strainlist = form_data.f1list+form_data.parlist+strainlist
+ #XZ, in HTML source code, it is "All Cases"
+ else:
+ strainlist = form_data.allstrainlist
+ #XZ, 09/18/2008: put the trait data into dictionary form_data.allTraitData
+ form_data.readData(form_data.allstrainlist)
+ else:
+ mdpchoice = None
+ strainlist = form_data.strainlist
+ #XZ, 09/18/2008: put the trait data into dictionary form_data.allTraitData
+ form_data.readData()
+
+ return strainlist
+
+
+def get_mdp_choice(form_data):
+ if form_data.allstrainlist:
+ return form_data.formdata.getvalue("MDPChoice")
+ else:
+ return None
+
+
+def get_species(fd, 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=cursor, RISet=RISet)
+ return species
+
+
+def sortTraitCorrelations(traits, method="1"):
+ if method in TISSUE_METHODS:
+ traits.sort(key=lambda trait: trait.tissue_corr != None and abs(trait.tissue_corr), reverse=True)
+ elif method == METHOD_LIT:
+ traits.sort(key=lambda trait: trait.lit_corr != None and abs(trait.lit_corr), reverse=True)
+ else:
+ traits.sort(key=lambda trait: trait.correlation != None and abs(trait.correlation), reverse=True)
+
+ return traits
+
+
+def auth_user_for_db(db, cursor, target_db_name, privilege, username):
+ """Authorize a user for access to a database if that database is
+ confidential. A db (identified by a record in ProbeSetFreeze) contains a
+ list of authorized users who may access it, as well as its confidentiality
+ level.
+
+ If the current user's privilege level is greater than 'user', ie: root or
+ admin, then they are automatically authed, otherwise, check the
+ AuthorizedUsers field for the presence of their name."""
+
+ if db.type == 'ProbeSet':
+ cursor.execute('SELECT Id, Name, FullName, confidentiality, AuthorisedUsers FROM ProbeSetFreeze WHERE Name = "%s"' % target_db_name)
+ indId, indName, indFullName, confidential, AuthorisedUsers = cursor.fetchall()[0]
+
+ if confidential:
+ authorized = 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[privilege] > webqtlConfig.USERDICT['user']:
+ authorized = 1
+ else:
+ if username in AuthorisedUsers.split(","):
+ authorized = 1
+
+ if not authorized:
+ raise AuthException("The %s database you selected is not open to the public at this time, please go back and select other database." % indFullName)
+
+
+class CorrelationPage(templatePage):
+
+ corrMinInformative = 4
+
+ PAGE_HEADING = "Correlation Table"
+ CORRELATION_METHODS = {"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)"}
+
+ RANK_ORDERS = {"1": 0, "2": 1, "3": 0, "4": 0, "5": 1}
+
+
+ def error(self, message, error="Error", heading = None):
+ heading = heading or self.PAGE_HEADING
+ return templatePage.error(heading = heading, detail = [message], error=error)
+
+ def __init__(self, fd):
+ print("in CorrelationPage __init__ fd is:", pf(fd.__dict__))
+ # Call the superclass constructor
+ templatePage.__init__(self, fd)
+ print("in CorrelationPage __init__ now fd is:", pf(fd.__dict__))
+ # Connect to the database
+ if not self.openMysql():
+ return
+
+ # Read the genotype from a file
+ if not fd.genotype:
+ fd.readGenotype()
+
+ sample_list = get_sample_data(fd)
+ mdp_choice = get_mdp_choice(fd) # No idea what this is yet
+ self.species = get_species(fd, self.cursor)
+
+ #XZ, 09/18/2008: get all information about the user selected database.
+ target_db_name = fd.formdata.getvalue('database')
+ self.target_db_name = target_db_name
+
+ try:
+ self.db = webqtlDataset(target_db_name, self.cursor)
+ except:
+ detail = ["The database you just requested has not been established yet."]
+ self.error(detail)
+ return
+
+ # Auth if needed
+ try:
+ auth_user_for_db(self.db, self.cursor, target_db_name, self.privilege, self.userName)
+ except AuthException, e:
+ detail = [e.message]
+ return self.error(detail)
+
+ #XZ, 09/18/2008: filter out the strains that have no value.
+ self.sample_names, vals, vars, N = fd.informativeStrains(sample_list)
+
+ #CF - If less than a minimum number of strains/cases in common, don't calculate anything
+ if len(self.sample_names) < self.corrMinInformative:
+ 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=PAGE_HEADING,detail=detail)
+
+
+ self.method = get_correlation_method_key(fd)
+ correlation_method = self.CORRELATION_METHODS[self.method]
+ rankOrder = self.RANK_ORDERS[self.method]
+
+ # CF - Number of results returned
+ self.returnNumber = int(fd.formdata.getvalue('criteria'))
+
+ self.record_count = 0
+
+ myTrait = get_custom_trait(fd, self.cursor)
+
+
+ # We will not get Literature Correlations if there is no GeneId because there is nothing to look against
+ self.gene_id = int(fd.formdata.getvalue('GeneId') or 0)
+
+ # We will not get Tissue Correlations if there is no gene symbol because there is nothing to look against
+ self.trait_symbol = myTrait.symbol
+
+
+ #XZ, 12/12/2008: if the species is rat or human, translate the geneid to mouse geneid
+ self.input_trait_mouse_gene_id = self.translateToMouseGeneID(self.species, self.gene_id)
+
+ #XZ: As of Nov/13/2010, this dataset is 'UTHSC Illumina V6.2 RankInv B6 D2 average CNS GI average (May 08)'
+ self.tissue_probeset_freeze_id = 1
+
+ traitList = self.correlate(vals)
+
+ _log.info("Done doing correlation calculation")
+
+############################################################################################################################################
+
+ 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': fd.RISet,
+ 'identification': fd.identification}
+
+ if myTrait:
+ hddn['fullname']=fd.formdata.getvalue('fullname')
+ if mdp_choice:
+ hddn['MDPChoice']=mdp_choice
+
+
+ #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" % self.tissue_probeset_freeze_id, 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=self.CORRELATION_METHODS, totalTraits=traitList, 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
+
+
+#####################################################################
+
+
+ #Select All, Deselect All, Invert Selection, Add to Collection
+ 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');" % (fd.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')
+
+
+ #External analysis tools
+ 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 self.species == 'rat':
+ hddnWebGestalt['org'] = 'Rattus norvegicus'
+ elif self.species == 'human':
+ hddnWebGestalt['org'] = 'Homo sapiens'
+ elif self.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'))
+
+
+ #Create tables with options, etc
+
+ 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")
+
+
+ if not GO_tree_value:
+ optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="480", height="80", border=0, align="Left")
+ optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), HT.TD(GCATButton), HT.TD(ODE), align="left"))
+ optionsTable.append(HT.TR(HT.TD(" "*1,"Select"), HT.TD("Deselect"), HT.TD(" "*1,"Invert"), HT.TD(" "*3,"Add"), HT.TD("Gene Set"), HT.TD(" "*2,"GCAT")))
+ else:
+ optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="560", height="80", border=0, align="Left")
+ optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), HT.TD(GCATButton), HT.TD(ODE), HT.TD(WebGestalt), align="left"))
+ optionsTable.append(HT.TR(HT.TD(" "*1,"Select"), HT.TD("Deselect"), HT.TD(" "*1,"Invert"), HT.TD(" "*3,"Add"), HT.TD("Gene Set"), HT.TD(" "*2,"GCAT"), HT.TD(" "*3, "ODE")))
+ 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(" "*1,HT.Text("Graph")), HT.TD(" "*1,HT.Text("Matrix")), HT.TD(" "*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(" "), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD(" ")))
+ else:
+ containerTable.append(HT.TR(HT.TD(" "), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
+ containerTable.append(HT.TR(HT.TD(" ")))
+ """
+
+ 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=60)))
+
+ 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=self.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=self.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=self.species, strains=self.sample_names)
+ 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"))
+
+ 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 self.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 = """
+
+
+
+
+
+
+
+
+ Sort Table
+
+
+
+
+
+Resorting this table
+
+
+
+
+
+
+
+
+
+
+ """
+
+ 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=TISSUE_MOUSE_DB, 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])
+ traits = []
+ # put all of the separate 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:])
+
+ trait = Trait(traitdata[0], traitdata[dataStartPos:])
+
+ if method == METHOD_LIT:
+ trait.lit_corr = traitdata[1]
+
+ if method in TISSUE_METHODS:
+ trait.tissue_corr = traitdata[1]
+ trait.p_tissue = traitdata[2]
+
+ traits.append(trait)
+
+ if tempTable:
+ self.cursor.execute( 'DROP TEMPORARY TABLE %s' % tempTable )
+
+ return traits
+
+
+
+
+ # 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=TISSUE_MOUSE_DB, 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=TISSUE_MOUSE_DB, 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 get_trait(self, cached, vals):
+
+ if cached:
+ _log.info("Using the fast method because the file exists")
+ lit_corrs = {}
+ tissue_corrs = {}
+ use_lit = False
+ if self.method == METHOD_LIT:
+ lit_corrs = self.fetchLitCorrelations(species=self.species, GeneId=self.gene_id, db=self.db, returnNumber=self.returnNumber)
+ use_lit = True
+
+ use_tissue_corr = False
+ if self.method in TISSUE_METHODS:
+ tissue_corrs = self.fetchTissueCorrelations(db=self.db, primaryTraitSymbol=self.trait_symbol, TissueProbeSetFreezeId=TISSUE_MOUSE_DB, method=self.method, returnNumber = self.returnNumber)
+ use_tissue_corr = True
+
+ DatabaseFileName = self.getFileName( target_db_name=self.target_db_name )
+ datasetFile = open(webqtlConfig.TEXTDIR+DatabaseFileName,'r')
+
+ #XZ, 01/08/2009: read the first line
+ line = datasetFile.readline()
+ cached_sample_names = 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'.
+ new_vals = []
+ for name in cached_sample_names:
+ if name in self.sample_names:
+ new_vals.append(float(vals[self.sample_names.index(name)]))
+ else:
+ new_vals.append('None')
+
+ nnCorr = len(new_vals)
+
+ #XZ, 01/14/2009: If literature corr or tissue corr is selected,
+ #XZ: there is no need to use parallel computing.
+
+ traits = []
+ data_start = 1
+ for line in datasetFile:
+ raw_trait = webqtlUtil.readLineCSV(line)
+ trait = Trait.from_csv(raw_trait, data_start)
+ trait.lit_corr = lit_corrs.get(trait.name)
+ trait.tissue_corr, trait.p_tissue = tissue_corrs.get(trait.name, (None, None))
+ traits.append(trait)
+
+ return traits, new_vals
+
+ else:
+ _log.info("Using the slow method for correlation")
+
+ _log.info("Fetching from database")
+ traits = self.fetchAllDatabaseData(species=self.species, GeneId=self.gene_id, GeneSymbol=self.trait_symbol, strains=self.sample_names, db=self.db, method=self.method, returnNumber=self.returnNumber, tissueProbeSetFreezeId= self.tissue_probeset_freeze_id)
+ _log.info("Done fetching from database")
+ totalTraits = len(traits) #XZ, 09/18/2008: total trait number
+
+ return traits, vals
+
+
+ def do_parallel_correlation(self):
+ _log.info("Invoking parallel computing")
+ input_line_list = datasetFile.readlines()
+ _log.info("Read lines from the file")
+ all_line_number = len(input_line_list)
+
+ step = 1000
+ job_number = math.ceil( float(all_line_number)/step )
+
+ job_input_lists = []
+
+ _log.info("Configuring jobs")
+
+ 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 )
+
+ _log.info("Creating pp servers")
+
+ ppservers = ()
+ # Creates jobserver with automatically detected number of workers
+ job_server = pp.Server(ppservers=ppservers)
+
+ _log.info("Done creating servers")
+
+ jobs = []
+ results = []
+
+ _log.info("Starting parallel computation, submitting jobs")
+ 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",)) )
+ _log.info("Done submitting jobs")
+
+ for one_job in jobs:
+ one_result = one_job()
+ results.append( one_result )
+
+ _log.info("Acquiring results")
+
+ for one_result in results:
+ for one_traitinfo in one_result:
+ allcorrelations.append( one_traitinfo )
+
+ _log.info("Appending the results")
+
+ datasetFile.close()
+ totalTraits = len(allcorrelations)
+ _log.info("Done correlating using the fast method")
+
+
+ def correlate(self, vals):
+
+ correlations = []
+
+ #XZ: Use the fast method only for probeset dataset, and this dataset must have been created.
+ #XZ: Otherwise, use original method
+ _log.info("Entering correlation")
+
+ db_filename = self.getFileName( target_db_name=self.target_db_name )
+
+ cache_available = db_filename in os.listdir(webqtlConfig.TEXTDIR)
+
+ # If the cache file exists, do a cached correlation for probeset data
+ if self.db.type == "ProbeSet":
+# if self.method in [METHOD_SAMPLE_PEARSON, METHOD_SAMPLE_RANK] and cache_available:
+# traits = do_parallel_correlation()
+#
+# else:
+
+ (traits, vals) = self.get_trait(cache_available, vals)
+
+ for trait in traits:
+ trait.calculate_correlation(vals, self.method)
+
+ self.record_count = len(traits) #ZS: This isn't a good way to get this value, so I need to change it later
+
+ #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.
+ #if self.method in [METHOD_LIT, METHOD_TISSUE_PEARSON, METHOD_TISSUE_RANK] and self.gene_id:
+ # traits.sort(webqtlUtil.cmpLitCorr)
+ #else:
+ #if self.method in TISSUE_METHODS:
+ # sort(traits, key=lambda A: math.fabs(A.tissue_corr))
+ #elif self.method == METHOD_LIT:
+ # traits.sort(traits, key=lambda A: math.fabs(A.lit_corr))
+ #else:
+ traits = sortTraitCorrelations(traits, self.method)
+
+ # Strip to the top N correlations
+ traits = traits[:min(self.returnNumber, len(traits))]
+
+ addLiteratureCorr = False
+ addTissueCorr = False
+
+ trait_list = []
+ for trait in traits:
+ db_trait = webqtlTrait(db=self.db, name=trait.name, cursor=self.cursor)
+ db_trait.retrieveInfo( QTL='Yes' )
+
+ db_trait.Name = trait.name
+ db_trait.corr = trait.correlation
+ db_trait.nOverlap = trait.overlap
+ db_trait.corrPValue = trait.p_value
+
+ # NL, 07/19/2010
+ # js function changed, add a new parameter rankOrder for js function 'showTissueCorrPlot'
+ db_trait.RANK_ORDER = self.RANK_ORDERS[self.method]
+
+ #XZ, 26/09/2008: Method is 4 or 5. Have fetched tissue corr, but no literature correlation yet.
+ if self.method in TISSUE_METHODS:
+ db_trait.tissueCorr = trait.tissue_corr
+ db_trait.tissuePValue = trait.p_tissue
+ addTissueCorr = True
+
+
+ #XZ, 26/09/2008: Method is 3, Have fetched literature corr, but no tissue corr yet.
+ elif self.method == METHOD_LIT:
+ db_trait.LCorr = trait.lit_corr
+ db_trait.mouse_geneid = self.translateToMouseGeneID(self.species, db_trait.geneid)
+ addLiteratureCorr = 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 self.input_trait_mouse_gene_id and self.db.type=="ProbeSet":
+ addLiteratureCorr = True
+ if self.trait_symbol and self.db.type=="ProbeSet":
+ addTissueCorr = True
+
+ trait_list.append(db_trait)
+
+ if addLiteratureCorr:
+ trait_list = self.getLiteratureCorrelationByList(self.input_trait_mouse_gene_id,
+ self.species, trait_list)
+ if addTissueCorr:
+ trait_list = self.getTissueCorrelationByList(
+ primaryTraitSymbol = self.trait_symbol,
+ traitList = trait_list,
+ TissueProbeSetFreezeId = TISSUE_MOUSE_DB,
+ method=self.method)
+
+ return trait_list
+
+
+ def calculateCorrOfAllTissueTrait(self, primaryTraitSymbol=None, TissueProbeSetFreezeId=None, method=None):
+
+ symbolCorrDict = {}
+ symbolPvalueDict = {}
+
+ primaryTraitSymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[primaryTraitSymbol], TissueProbeSetFreezeId=TISSUE_MOUSE_DB)
+ primaryTraitValue = primaryTraitSymbolValueDict.values()[0]
+
+ SymbolValueDict = correlationFunction.getGeneSymbolTissueValueDictForTrait(cursor=self.cursor, GeneNameLst=[], TissueProbeSetFreezeId=TISSUE_MOUSE_DB)
+
+ 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=TISSUE_MOUSE_DB)
+
+ 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=TISSUE_MOUSE_DB)
+
+ 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 " % self.record_count, 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, self.record_count),
+ 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 = self.RANK_ORDERS[self.method]
+ 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/wqflask/wqflask/correlation/__init__.py b/wqflask/wqflask/correlation/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/wqflask/wqflask/correlation/correlationFunction.py b/wqflask/wqflask/correlation/correlationFunction.py
new file mode 100644
index 00000000..4d62a468
--- /dev/null
+++ b/wqflask/wqflask/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
console.log("Found Show Outliers")
$('#show_hide_outliers').val("Hide Outliers")
console.log("Should be now Hide Outliers")
-
+
+
###
Calculate Correlations Code
###
@@ -165,6 +166,17 @@ $ ->
$('select[name=corr_method]').change(on_corr_method_change)
+ on_corr_submit = ->
+ console.log("in beginning of on_corr_submit")
+ values = $('#trait_data_form').serialize()
+ console.log("in on_corr_submit, values are:", values)
+ $.ajax "/corr_compute",
+ type: 'GET'
+ dataType: 'html'
+ data: values
+
+ $('#corr_compute').click(on_corr_submit)
+
###
End Calculate Correlations Code
###
@@ -177,8 +189,9 @@ $ ->
_.mixin(_.str.exports()); # Add string fuctions directly to underscore
$('#value_table').change(edit_data_change)
console.log("loaded")
- console.log("basic_table is:", basic_table)
- make_table()
- edit_data_change() # Set the values at the beginning
+ #console.log("basic_table is:", basic_table)
+ # Add back following two lines later
+ #make_table()
+ #edit_data_change() # Set the values at the beginning
#$("#all-mean").html('foobar8')
console.log("end")
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
index 96b245ea..0de0297b 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
@@ -10,7 +10,7 @@
};
$(function() {
- var edit_data_change, hide_tabs, make_table, on_corr_method_change, process_id, show_hide_outliers, stats_mdp_change, update_stat_values;
+ var edit_data_change, hide_tabs, make_table, on_corr_method_change, on_corr_submit, process_id, show_hide_outliers, stats_mdp_change, update_stat_values;
hide_tabs = function(start) {
var x, _i, _results;
_results = [];
@@ -199,6 +199,18 @@
return $('#' + corr_method + "_r_desc").show().effect("highlight");
};
$('select[name=corr_method]').change(on_corr_method_change);
+ on_corr_submit = function() {
+ var values;
+ console.log("in beginning of on_corr_submit");
+ values = $('#trait_data_form').serialize();
+ console.log("in on_corr_submit, values are:", values);
+ return $.ajax("/corr_compute", {
+ type: 'GET',
+ dataType: 'html',
+ data: values
+ });
+ };
+ $('#corr_compute').click(on_corr_submit);
/*
End Calculate Correlations Code
*/
@@ -209,9 +221,6 @@
_.mixin(_.str.exports());
$('#value_table').change(edit_data_change);
console.log("loaded");
- console.log("basic_table is:", basic_table);
- make_table();
- edit_data_change();
return console.log("end");
});
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index f6917a90..a5d0e05c 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -8,7 +8,7 @@
-
+
{#
@@ -51,9 +51,9 @@
#}
- {% for key in hddn %}
-
- {% endfor %}
+ {% for key in hddn %}
+
+ {% endfor %}
Trait Data and Analysis for Record ID 1441186_at
@@ -770,7 +770,9 @@
Pearson Spearman Rank
-
+
+
+
The Sample Correlation
is computed
@@ -801,6 +803,7 @@
Pearson and Spearman Rank correlations have been
computed for all pairs of genes using data from mouse samples.
+
@@ -1308,9 +1311,9 @@
-
+ -->
-->
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 1ed3c1fd..114ec458 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -8,6 +8,7 @@ from flask import render_template, request
from wqflask import search_results
from wqflask.show_trait import show_trait_page
+from wqflask.correlation import CorrelationPage
from wqflask.dataSharing import SharingInfo, SharingInfoPage
@@ -74,7 +75,14 @@ def showDatabaseBXD():
print("showDatabaseBXD template_vars:", pf(template_vars.__dict__))
return render_template("trait_data_and_analysis.html", **template_vars.__dict__)
-
+@app.route("/corr_compute")
+def corr_compute():
+ print("In corr_compute")
+ fd = webqtlFormData.webqtlFormData(request.args)
+ print("Have fd")
+ template_vars = CorrelationPage.CorrelationPage(fd)
+ print("Made it to rendering")
+ return render_template("corr_compute.html", **template_vars.__dict__)
# Todo: Can we simplify this? -Sam
def sharing_info_page():
--
cgit v1.2.3
From f1d7725c5f7529c5f587bab4ea89d3467b903ddb Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Wed, 12 Sep 2012 18:22:45 -0500
Subject: Worked towards correctly passing form data to correlation page and
addressed various bugs that arose while doing so
---
misc/byobu_commands.txt | 6 -
misc/find.txt | 1 -
misc/notes.txt | 41 +++++++
misc/python_stuff.txt | 1 -
misc/runserver.txt | 1 -
misc/virtual_env.txt | 1 -
wqflask/base/webqtlFormData.py | 121 +++++++++++----------
wqflask/wqflask/correlation/CorrelationPage.py | 82 +++++++-------
.../new/javascript/trait_data_and_analysis.coffee | 12 +-
.../new/javascript/trait_data_and_analysis.js | 9 +-
10 files changed, 160 insertions(+), 115 deletions(-)
delete mode 100644 misc/byobu_commands.txt
delete mode 100644 misc/find.txt
create mode 100644 misc/notes.txt
delete mode 100644 misc/python_stuff.txt
delete mode 100644 misc/runserver.txt
delete mode 100644 misc/virtual_env.txt
diff --git a/misc/byobu_commands.txt b/misc/byobu_commands.txt
deleted file mode 100644
index 48e85396..00000000
--- a/misc/byobu_commands.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-byobu -RD
-control-a then :multiuser on
-control-a then :acladd sam
-
-type: screen -list for sessions
-screen -r zas1024/25679.byobu
diff --git a/misc/find.txt b/misc/find.txt
deleted file mode 100644
index 5c792d80..00000000
--- a/misc/find.txt
+++ /dev/null
@@ -1 +0,0 @@
-find | grep _____
diff --git a/misc/notes.txt b/misc/notes.txt
new file mode 100644
index 00000000..be023c1d
--- /dev/null
+++ b/misc/notes.txt
@@ -0,0 +1,41 @@
+To get server running:
+
+Start up virtual environment:
+source ~/ve27/bin/activate
+
+To set WQFLASK_SETTINGS environment variable:
+export WQFLASK_SETTINGS=~/gene/wqflask/cfg/zach_settings.py (or wherever file is located)
+
+To search for commands in history if necessary:
+history | grep "(whatever is being searched for)"
+
+Run server:
+python runserver.py
+
+===========================================
+
+Start screen session
+byobu -RD (to start)
+control-a then :multiuser on
+control-a then :acladd sam
+
+type: screen -list for sessions
+screen -r zas1024/25679.byobu
+
+or if only one:
+
+screen -r zas1024/
+
+===========================================
+
+Coffeescript Stuff:
+
+coffee -c (filename)
+coffee -c -w (to watch for changes and recompile)
+coffee --help (for information about setting options)
+
+===========================================
+
+Python stuff:
+
+Classes should always inherit "object"
\ No newline at end of file
diff --git a/misc/python_stuff.txt b/misc/python_stuff.txt
deleted file mode 100644
index f36fe338..00000000
--- a/misc/python_stuff.txt
+++ /dev/null
@@ -1 +0,0 @@
-Classes should always inherit "object"
\ No newline at end of file
diff --git a/misc/runserver.txt b/misc/runserver.txt
deleted file mode 100644
index 71e3dfd7..00000000
--- a/misc/runserver.txt
+++ /dev/null
@@ -1 +0,0 @@
-python runserver.py
diff --git a/misc/virtual_env.txt b/misc/virtual_env.txt
deleted file mode 100644
index 7a8f20be..00000000
--- a/misc/virtual_env.txt
+++ /dev/null
@@ -1 +0,0 @@
-source ~/ve27/bin/activate
diff --git a/wqflask/base/webqtlFormData.py b/wqflask/base/webqtlFormData.py
index a9e3b7d4..177c72a2 100755
--- a/wqflask/base/webqtlFormData.py
+++ b/wqflask/base/webqtlFormData.py
@@ -60,17 +60,12 @@ class webqtlFormData:
print("in webqtlFormData start_vars are:", pf(start_vars))
for item in webqtlFormData.attrs:
self.__dict__[item] = None
- #self.__dict__.update(start_vars)
+
for item in start_vars:
self.__dict__[item] = start_vars[item]
- print(" Now self.dict is:", pf(self.__dict__))
- #for item in self.attrs:
- # if getattr(self, item, None):
- # print("Setting item %s to None" % (item,))
- # self.attrs[item] = None
- # else:
- # self.attrs[item] = self.attrs[item].strip()
+ #print(" Now self.dict is:", pf(self.__dict__))
+ #Todo: This can't be good below...rework
try:
self.remote_ip = req.connection.remote_ip
except:
@@ -151,23 +146,32 @@ class webqtlFormData:
def readGenotype(self):
- 'read genotype from .geno file'
+ '''read genotype from .geno file'''
if self.RISet == 'BXD300':
self.RISet = 'BXD'
- else:
- pass
- assert self.RISet
+
+ assert self.RISet, "self.RISet needs to be set"
+
#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'))
+
+ full_filename = os.path.join(webqtlConfig.GENODIR, self.RISet + '.geno')
+
+ # reaper barfs on unicode filenames, so here we ensure it's a string
+ full_filename = str(full_filename)
+ self.genotype_1.read(full_filename)
+
+ print("Got to after read")
+
try:
# NL, 07/27/2010. ParInfo has been moved from webqtlForm.py to webqtlUtil.py;
_f1, _f12, _mat, _pat = webqtlUtil.ParInfo[self.RISet]
- except:
+ except KeyError:
_f1 = _f12 = _mat = _pat = None
- self.genotype_2 =self.genotype_1
+ 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)
@@ -177,78 +181,83 @@ class webqtlFormData:
else:
self.incparentsf1 = 0
self.genotype = self.genotype_1
+
self.strainlist = list(self.genotype.prgy)
- self.f1list = self.parlist = []
+ 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'
+ def readData(self, strainlist, incf1=None):
+ '''read user input data or from trait data and analysis form'''
+
+ if incf1 == None:
+ incf1 = []
if not self.genotype:
self.readGenotype()
- if not strainlst:
+ if not strainlist:
if incf1:
- strainlst = self.f1list + self.strainlist
+ strainlist = self.f1list + self.strainlist
else:
- strainlst = self.strainlist
+ strainlist = self.strainlist
+ #print("before traitfiledata self.traitfile is:", pf(self.traitfile))
- 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')
+ traitfiledata = getattr(self, "traitfile", None)
+ traitpastedata = getattr(self, "traitpaste", None)
+ variancefiledata = getattr(self, "variancefile", None)
+ variancepastedata = getattr(self, "variancepaste", None)
+ Nfiledata = getattr(self, "Nfile", None)
+ #### Todo: Rewrite below when we get to someone submitting their own trait #####
if traitfiledata:
- tt = string.split(traitfiledata)
- vals = map(webqtlUtil.StringAsFloat, tt)
+ tt = traitfiledata.split()
+ values = map(webqtlUtil.StringAsFloat, tt)
elif traitpastedata:
- tt = string.split(traitpastedata)
- vals = map(webqtlUtil.StringAsFloat, tt)
+ tt = traitpastedata.split()
+ values = 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
+ values = map(self.FormDataAsFloat, strainlist)
+ if len(values) < len(strainlist):
+ values += [None] * (len(strainlist) - len(values))
+ elif len(values) > len(strainlist):
+ values = values[:len(strainlist)]
+
if variancefiledata:
- tt = string.split(variancefiledata)
- vars = map(webqtlUtil.StringAsFloat, tt)
+ tt = variancefiledata.split()
+ variances = map(webqtlUtil.StringAsFloat, tt)
elif variancepastedata:
- tt = string.split(variancepastedata)
- vars = map(webqtlUtil.StringAsFloat, tt)
+ tt = variancepastedata.split()
+ variances = map(webqtlUtil.StringAsFloat, tt)
else:
- vars = map(self.FormVarianceAsFloat, strainlst)
+ variances = map(self.FormVarianceAsFloat, strainlist)
- if len(vars) < len(strainlst):
- vars += [None]*(len(strainlst) - len(vars))
- elif len(vars) > len(strainlst):
- vars = vars[:len(strainlst)]
- else:
- pass
+ if len(variances) < len(strainlist):
+ variances += [None]*(len(strainlist) - len(variances))
+ elif len(variances) > len(strainlist):
+ variances = variances[:len(strainlist)]
if Nfiledata:
tt = string.split(Nfiledata)
nstrains = map(webqtlUtil.IntAsFloat, tt)
- if len(nstrains) < len(strainlst):
- nstrains += [None]*(len(strainlst) - len(nstrains))
+ if len(nstrains) < len(strainlist):
+ nstrains += [None]*(len(strainlist) - len(nstrains))
else:
- nstrains = map(self.FormNAsFloat, strainlst)
+ nstrains = map(self.FormNAsFloat, strainlist)
- ##vals, vars, nstrains is obsolete
+ ##values, variances, 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])
+ for i, _strain in enumerate(strainlist):
+ if values[i] != None:
+ self.allTraitData[_strain] = webqtlCaseData(values[i], variances[i], nstrains[i])
diff --git a/wqflask/wqflask/correlation/CorrelationPage.py b/wqflask/wqflask/correlation/CorrelationPage.py
index 9caf6595..62e4c4ab 100644
--- a/wqflask/wqflask/correlation/CorrelationPage.py
+++ b/wqflask/wqflask/correlation/CorrelationPage.py
@@ -177,42 +177,37 @@ def get_custom_trait(form_data, cursor):
#XZ, 09/18/2008: get the information such as value, variance of the input strain names from the form.
-def get_sample_data(form_data):
- if form_data.allstrainlist:
- mdpchoice = form_data.formdata.getvalue('MDPChoice')
- #XZ, in HTML source code, it is "BXD Only" or "BXH only", and so on
+def get_sample_data(fd):
+ print("fd is:", pf(fd.__dict__))
+ if fd.allstrainlist:
+ mdpchoice = fd.MDPChoice
+ #XZ, in HTML source code, it is "BXD Only", "BXH Only", and so on
if mdpchoice == "1":
- strainlist = form_data.f1list + form_data.strainlist
- #XZ, in HTML source code, it is "MDP Only"
+ strainlist = fd.f1list + fd.strainlist
+ #XZ, in HTML source code, it is "Non-BXD Only", "Non-BXD Only", etc
elif mdpchoice == "2":
strainlist = []
- strainlist2 = form_data.f1list + form_data.strainlist
- for strain in form_data.allstrainlist:
+ 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 = form_data.f1list+form_data.parlist+strainlist
+ strainlist = fd.f1list + fd.parlist+strainlist
#XZ, in HTML source code, it is "All Cases"
else:
- strainlist = form_data.allstrainlist
- #XZ, 09/18/2008: put the trait data into dictionary form_data.allTraitData
- form_data.readData(form_data.allstrainlist)
+ strainlist = fd.allstrainlist
+ #XZ, 09/18/2008: put the trait data into dictionary fd.allTraitData
+ fd.readData(fd.allstrainlist)
else:
mdpchoice = None
- strainlist = form_data.strainlist
- #XZ, 09/18/2008: put the trait data into dictionary form_data.allTraitData
- form_data.readData()
+ strainlist = fd.strainlist
+ #XZ, 09/18/2008: put the trait data into dictionary fd.allTraitData
+ fd.readData()
return strainlist
-def get_mdp_choice(form_data):
- if form_data.allstrainlist:
- return form_data.formdata.getvalue("MDPChoice")
- else:
- return None
-
def get_species(fd, cursor):
#XZ, 3/16/2010: variable RISet must be pass by the form
@@ -277,7 +272,7 @@ class CorrelationPage(templatePage):
RANK_ORDERS = {"1": 0, "2": 1, "3": 0, "4": 0, "5": 1}
- def error(self, message, error="Error", heading = None):
+ def error(self, message, *args, **kw):
heading = heading or self.PAGE_HEADING
return templatePage.error(heading = heading, detail = [message], error=error)
@@ -295,23 +290,30 @@ class CorrelationPage(templatePage):
fd.readGenotype()
sample_list = get_sample_data(fd)
- mdp_choice = get_mdp_choice(fd) # No idea what this is yet
+
+ # Whether the user chose BXD Only, Non-BXD Only, or All Strains
+ # (replace BXD with whatever the group/inbredset name is)
+ # "mdp" stands for "mouse diversity panel" This is outdated; it now represents any
+ # cases/strains from the non-primary group
+ mdp_choice = fd.MDPChoice if fd.allstrainlist else None
+
self.species = get_species(fd, self.cursor)
#XZ, 09/18/2008: get all information about the user selected database.
- target_db_name = fd.formdata.getvalue('database')
- self.target_db_name = target_db_name
+ #target_db_name = fd.corr_dataset
+ self.target_db_name = fd.corr_dataset
- try:
- self.db = webqtlDataset(target_db_name, self.cursor)
- except:
- detail = ["The database you just requested has not been established yet."]
- self.error(detail)
- return
+ #try:
+ #print("target_db_name is:", target_db_name)
+ self.db = webqtlDataset(self.target_db_name, self.cursor)
+ #except:
+ # detail = ["The database you just requested has not been established yet."]
+ # self.error(detail)
+ # return
# Auth if needed
try:
- auth_user_for_db(self.db, self.cursor, target_db_name, self.privilege, self.userName)
+ auth_user_for_db(self.db, self.cursor, self.target_db_name, self.privilege, self.userName)
except AuthException, e:
detail = [e.message]
return self.error(detail)
@@ -322,7 +324,7 @@ class CorrelationPage(templatePage):
#CF - If less than a minimum number of strains/cases in common, don't calculate anything
if len(self.sample_names) < self.corrMinInformative:
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=PAGE_HEADING,detail=detail)
+ self.error(heading=None, detail=detail)
self.method = get_correlation_method_key(fd)
@@ -330,15 +332,16 @@ class CorrelationPage(templatePage):
rankOrder = self.RANK_ORDERS[self.method]
# CF - Number of results returned
- self.returnNumber = int(fd.formdata.getvalue('criteria'))
+ self.returnNumber = int(fd.criteria)
self.record_count = 0
myTrait = get_custom_trait(fd, self.cursor)
- # We will not get Literature Correlations if there is no GeneId because there is nothing to look against
- self.gene_id = int(fd.formdata.getvalue('GeneId') or 0)
+ # We will not get Literature Correlations if there is no GeneId because there is nothing
+ # to look against
+ self.gene_id = int(fd.GeneId)
# We will not get Tissue Correlations if there is no gene symbol because there is nothing to look against
self.trait_symbol = myTrait.symbol
@@ -359,7 +362,8 @@ class CorrelationPage(templatePage):
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'))
+ 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,
@@ -369,9 +373,9 @@ class CorrelationPage(templatePage):
'identification': fd.identification}
if myTrait:
- hddn['fullname']=fd.formdata.getvalue('fullname')
+ hddn['fullname'] = fd.fullname
if mdp_choice:
- hddn['MDPChoice']=mdp_choice
+ hddn['MDPChoice']= mdp_choice
#XZ, 09/18/2008: pass the trait data to next page by hidden parameters.
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
index 3ea90b9c..7bfa6d01 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
@@ -170,10 +170,14 @@ $ ->
console.log("in beginning of on_corr_submit")
values = $('#trait_data_form').serialize()
console.log("in on_corr_submit, values are:", values)
- $.ajax "/corr_compute",
- type: 'GET'
- dataType: 'html'
- data: values
+
+ params = $.param(values)
+ window.location.href = "/corr_compute?" + params
+
+ #$.ajax "/corr_compute",
+ # type: 'GET'
+ # dataType: 'html'
+ # data: values
$('#corr_compute').click(on_corr_submit)
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
index 0de0297b..e1f870d9 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
@@ -200,15 +200,12 @@
};
$('select[name=corr_method]').change(on_corr_method_change);
on_corr_submit = function() {
- var values;
+ var params, values;
console.log("in beginning of on_corr_submit");
values = $('#trait_data_form').serialize();
console.log("in on_corr_submit, values are:", values);
- return $.ajax("/corr_compute", {
- type: 'GET',
- dataType: 'html',
- data: values
- });
+ params = $.param(values);
+ return window.location.href = "/corr_compute?" + params;
};
$('#corr_compute').click(on_corr_submit);
/*
--
cgit v1.2.3
From a979480aae5eaa056c84dc3cb05a5e2443c4fbd0 Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Thu, 13 Sep 2012 16:10:27 -0500
Subject: Worked on improving readData and informativeStrains functions in
webqtlFormData while trying to get correlation page running
---
misc/notes.txt | 6 ++
wqflask/base/webqtlFormData.py | 72 ++++++++++++++--------
wqflask/wqflask/correlation/CorrelationPage.py | 18 +++---
.../new/javascript/trait_data_and_analysis.coffee | 28 ++++-----
.../new/javascript/trait_data_and_analysis.js | 11 +---
.../wqflask/templates/trait_data_and_analysis.html | 12 +---
wqflask/wqflask/views.py | 6 +-
7 files changed, 83 insertions(+), 70 deletions(-)
diff --git a/misc/notes.txt b/misc/notes.txt
index be023c1d..9d31fb5d 100644
--- a/misc/notes.txt
+++ b/misc/notes.txt
@@ -36,6 +36,12 @@ coffee --help (for information about setting options)
===========================================
+Unset ASKPASS when trying to git push
+
+unset SSH_ASKPASS
+
+===========================================
+
Python stuff:
Classes should always inherit "object"
\ No newline at end of file
diff --git a/wqflask/base/webqtlFormData.py b/wqflask/base/webqtlFormData.py
index 177c72a2..9f58d437 100755
--- a/wqflask/base/webqtlFormData.py
+++ b/wqflask/base/webqtlFormData.py
@@ -63,7 +63,7 @@ class webqtlFormData:
for item in start_vars:
self.__dict__[item] = start_vars[item]
- #print(" Now self.dict is:", pf(self.__dict__))
+ print(" Now self.dict is:", pf(self.__dict__))
#Todo: This can't be good below...rework
try:
@@ -216,6 +216,13 @@ class webqtlFormData:
#### Todo: Rewrite below when we get to someone submitting their own trait #####
+ def to_float(item):
+ try:
+ return float(item)
+ except ValueError:
+ return None
+
+ print("bottle strainlist is:", strainlist)
if traitfiledata:
tt = traitfiledata.split()
values = map(webqtlUtil.StringAsFloat, tt)
@@ -223,12 +230,17 @@ class webqtlFormData:
tt = traitpastedata.split()
values = map(webqtlUtil.StringAsFloat, tt)
else:
- values = map(self.FormDataAsFloat, strainlist)
+ print("mapping formdataasfloat")
+ #values = map(self.FormDataAsFloat, strainlist)
+ values = [to_float(getattr(self, key)) for key in strainlist]
+ print("rocket values is:", values)
+
if len(values) < len(strainlist):
values += [None] * (len(strainlist) - len(values))
elif len(values) > len(strainlist):
values = values[:len(strainlist)]
+ print("now values is:", values)
if variancefiledata:
@@ -257,40 +269,48 @@ class webqtlFormData:
self.allTraitData = {}
for i, _strain in enumerate(strainlist):
if values[i] != None:
- self.allTraitData[_strain] = webqtlCaseData(values[i], variances[i], nstrains[i])
+ self.allTraitData[_strain] = webqtlCaseData(
+ _strain, values[i], variances[i], nstrains[i])
+ print("allTraitData is:", pf(self.allTraitData))
- 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
+ def informativeStrains(self, strainlist=None, include_variances = None):
+ '''if readData was called, use this to output informative strains (strain with values)'''
+
+ if not strainlist:
+ strainlist = 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
+ values = []
+ variances = []
+
+ #print("self.allTraitData is:", pf(self.allTraitData))
+
+ for strain in strainlist:
+ if strain in self.allTraitData:
+ _val, _var = self.allTraitData[strain].value, self.allTraitData[strain].variance
if _val != None:
- if incVars:
+ if include_variances:
if _var != None:
- strains.append(_strain)
- vals.append(_val)
- vars.append(_var)
+ strains.append(strain)
+ values.append(_val)
+ variances.append(_var)
else:
- strains.append(_strain)
- vals.append(_val)
- vars.append(None)
- return strains, vals, vars, len(strains)
+ strains.append(strain)
+ values.append(_val)
+ variances.append(None)
+
+ return strains, values, variances, len(strains)
- def FormDataAsFloat(self, key):
- try:
- return float(self.formdata.getfirst(key))
- except:
- return None
+ #def FormDataAsFloat(self, key):
+ #
+ # #try:
+ # # return float(self.key)
+ # #except:
+ # # return None
def FormVarianceAsFloat(self, key):
diff --git a/wqflask/wqflask/correlation/CorrelationPage.py b/wqflask/wqflask/correlation/CorrelationPage.py
index 62e4c4ab..0af5297a 100644
--- a/wqflask/wqflask/correlation/CorrelationPage.py
+++ b/wqflask/wqflask/correlation/CorrelationPage.py
@@ -157,7 +157,7 @@ def get_correlation_method_key(form_data):
#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.
- method = form_data.formdata.getvalue("method")
+ method = form_data.method
if method not in ["1", "2", "3" ,"4", "5"]:
return "1"
@@ -166,7 +166,7 @@ def get_correlation_method_key(form_data):
def get_custom_trait(form_data, cursor):
"""Pulls the custom trait, if it exists, out of the form data"""
- trait_name = form_data.formdata.getvalue('fullname')
+ trait_name = form_data.fullname
if trait_name:
trait = webqtlTrait(fullname=trait_name, cursor=cursor)
@@ -178,7 +178,7 @@ def get_custom_trait(form_data, cursor):
#XZ, 09/18/2008: get the information such as value, variance of the input strain names from the form.
def get_sample_data(fd):
- print("fd is:", pf(fd.__dict__))
+ #print("fd is:", pf(fd.__dict__))
if fd.allstrainlist:
mdpchoice = fd.MDPChoice
#XZ, in HTML source code, it is "BXD Only", "BXH Only", and so on
@@ -277,10 +277,10 @@ class CorrelationPage(templatePage):
return templatePage.error(heading = heading, detail = [message], error=error)
def __init__(self, fd):
- print("in CorrelationPage __init__ fd is:", pf(fd.__dict__))
+ #print("in CorrelationPage __init__ fd is:", pf(fd.__dict__))
# Call the superclass constructor
templatePage.__init__(self, fd)
- print("in CorrelationPage __init__ now fd is:", pf(fd.__dict__))
+ #print("in CorrelationPage __init__ now fd is:", pf(fd.__dict__))
# Connect to the database
if not self.openMysql():
return
@@ -290,6 +290,7 @@ class CorrelationPage(templatePage):
fd.readGenotype()
sample_list = get_sample_data(fd)
+ print("sample_list is", pf(sample_list))
# Whether the user chose BXD Only, Non-BXD Only, or All Strains
# (replace BXD with whatever the group/inbredset name is)
@@ -321,17 +322,18 @@ class CorrelationPage(templatePage):
#XZ, 09/18/2008: filter out the strains that have no value.
self.sample_names, vals, vars, N = fd.informativeStrains(sample_list)
- #CF - If less than a minimum number of strains/cases in common, don't calculate anything
+ print("samplenames is:", pf(self.sample_names))
+ #CF - If less than a minimum number of strains/cases in common, don't calculate anything
if len(self.sample_names) < self.corrMinInformative:
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=None, detail=detail)
- self.method = get_correlation_method_key(fd)
+ self.method = fd.method
correlation_method = self.CORRELATION_METHODS[self.method]
rankOrder = self.RANK_ORDERS[self.method]
- # CF - Number of results returned
+ # CF - Number of results returned
self.returnNumber = int(fd.criteria)
self.record_count = 0
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
index 7bfa6d01..5c153ccb 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.coffee
@@ -166,20 +166,20 @@ $ ->
$('select[name=corr_method]').change(on_corr_method_change)
- on_corr_submit = ->
- console.log("in beginning of on_corr_submit")
- values = $('#trait_data_form').serialize()
- console.log("in on_corr_submit, values are:", values)
-
- params = $.param(values)
- window.location.href = "/corr_compute?" + params
-
- #$.ajax "/corr_compute",
- # type: 'GET'
- # dataType: 'html'
- # data: values
-
- $('#corr_compute').click(on_corr_submit)
+ #on_corr_submit = ->
+ # console.log("in beginning of on_corr_submit")
+ # values = $('#trait_data_form').serialize()
+ # console.log("in on_corr_submit, values are:", values)
+ #
+ # params = $.param(values)
+ # window.location.href = "/corr_compute?" + params
+ #
+ # #$.ajax "/corr_compute",
+ # # type: 'GET'
+ # # dataType: 'html'
+ # # data: values
+ #
+ #$('#corr_compute').click(on_corr_submit)
###
End Calculate Correlations Code
diff --git a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
index e1f870d9..55acbada 100644
--- a/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
+++ b/wqflask/wqflask/static/new/javascript/trait_data_and_analysis.js
@@ -10,7 +10,7 @@
};
$(function() {
- var edit_data_change, hide_tabs, make_table, on_corr_method_change, on_corr_submit, process_id, show_hide_outliers, stats_mdp_change, update_stat_values;
+ var edit_data_change, hide_tabs, make_table, on_corr_method_change, process_id, show_hide_outliers, stats_mdp_change, update_stat_values;
hide_tabs = function(start) {
var x, _i, _results;
_results = [];
@@ -199,15 +199,6 @@
return $('#' + corr_method + "_r_desc").show().effect("highlight");
};
$('select[name=corr_method]').change(on_corr_method_change);
- on_corr_submit = function() {
- var params, values;
- console.log("in beginning of on_corr_submit");
- values = $('#trait_data_form').serialize();
- console.log("in on_corr_submit, values are:", values);
- params = $.param(values);
- return window.location.href = "/corr_compute?" + params;
- };
- $('#corr_compute').click(on_corr_submit);
/*
End Calculate Correlations Code
*/
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index a5d0e05c..c25db7c4 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -8,7 +8,7 @@
Values of Record 1436869_at in the Hippocampus Consortium M430v2 (Jun06) PDNN database were compared to all 45101 records in the Hippocampus Consortium M430v2 (Jun06) PDNN database. The top 500 correlations ranked by the Genetic Correlation (Pearson's r) are displayed. You can resort this list using the small arrowheads in the top row. 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.
SWI/SNF related, matrix associated, actin dependent regulator of chromatin, subfamily a, member 3; last two exons of short form message (exons 20 and 21)
sema domain, immunoglobulin domain (Ig), short basic domain, secreted, (semaphorin) 3D; distal end of last exon and proximal 3' UTR (transQTL on chr 4 in BXD Eye Data)
cytochrome P450, family 2, subfamily c, polypeptide 54 (xenobiotic metabolism, phenytoin, tolbutamide, ibuprofen, warfarin, similar to human CYP2C9 and CYP2C19, also see Cyp2c37 and Cyp2c50); putative 3' UTR
Mus musculus transcribed sequence with strong similarity to protein pir:T08738 (H.sapiens) T08738 hypothetical protein DKFZp586E0518.1 - human (fragment)
-->
+ js_data = {{ js_data | safe }}
+
-->
+
+
-
+
--
cgit v1.2.3
From cfa479050353787e8bd2501c7a63b46a1f3b8e64 Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Thu, 20 Sep 2012 16:34:53 -0500
Subject: Put the tables in the trait data/analysis page side by side
---
wqflask/wqflask/templates/trait_data_and_analysis.html | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index 1f33dee5..4d7ec58e 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -1243,9 +1243,10 @@
the Hide Outliers button,
and samples with no value (x) can be hidden by clicking Hide No Value .
-
+
+
{% for strain_type in (primary_strains, other_strains) %}
-
{# Slightly tortuous, but best way to get the id we need #}
+
{# Slightly tortuous, but best way to get the id we need #}
@@ -1292,11 +1293,9 @@
{% endfor %}
-
-
-
{% endfor %}
+
--
cgit v1.2.3
From 4ea9caf926de05046a66ab33e40eda38314db216 Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Thu, 20 Sep 2012 16:56:39 -0500
Subject: Added headers to the trait data/analysis tables
---
wqflask/wqflask/show_trait/DataEditingPage.py | 15 ++++++---------
wqflask/wqflask/templates/trait_data_and_analysis.html | 11 ++++++++---
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/wqflask/wqflask/show_trait/DataEditingPage.py b/wqflask/wqflask/show_trait/DataEditingPage.py
index 32ecc732..13de0b40 100755
--- a/wqflask/wqflask/show_trait/DataEditingPage.py
+++ b/wqflask/wqflask/show_trait/DataEditingPage.py
@@ -932,14 +932,13 @@ class DataEditingPage(templatePage):
self.MDP_menu.append(('All Cases','0'))
self.MDP_menu.append(('%s Only' % fd.RISet, '1'))
self.MDP_menu.append(('Non-%s Only' % fd.RISet, '2'))
- #stats_row.append("Include: ", self.MDP_menu, HT.BR(), HT.BR())
+
else:
if (len(other_strains) > 0) and (len(primary_strains) + len(other_strains) > 3):
print("ac2")
self.MDP_menu.append(('All Cases','0'))
self.MDP_menu.append(('%s Only' % fd.RISet,'1'))
self.MDP_menu.append(('Non-%s Only' % fd.RISet,'2'))
- #stats_row.append("Include: ", self.MDP_menu, " "*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
@@ -950,10 +949,6 @@ class DataEditingPage(templatePage):
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
@@ -1764,9 +1759,11 @@ class DataEditingPage(templatePage):
fd.allstrainlist = allstrainlist_neworder
- self.primary_strains = primary_strains
- self.other_strains = other_strains
-
+ self.primary_strains = dict(header = "%s Only" % (fd.RISet),
+ strains = primary_strains,)
+
+ self.other_strains = dict(header = "Non-%s" % (fd.RISet),
+ strains = other_strains,)
def create_strain_objects(self, fd, varianceDataPage, strainlist, mainForm, thisTrait,
other_strainsExist=None, attribute_ids=None,
diff --git a/wqflask/wqflask/templates/trait_data_and_analysis.html b/wqflask/wqflask/templates/trait_data_and_analysis.html
index 4d7ec58e..110559bc 100644
--- a/wqflask/wqflask/templates/trait_data_and_analysis.html
+++ b/wqflask/wqflask/templates/trait_data_and_analysis.html
@@ -1245,8 +1245,12 @@
- {% for strain_type in (primary_strains, other_strains) %}
-
{# Slightly tortuous, but best way to get the id we need #}
+ {% for strain_type in (primary_strains, other_strains) %}
+
+
+
{{ strain_type.header }}
+
+
{# Slightly tortuous, but best way to get the id we need #}
@@ -1262,7 +1266,7 @@
SE
- {% for strain in strain_type %}
+ {% for strain in strain_type.strains %}
- {% endfor %}
- {# Not used now - Todo: Delete after we're sure this is right.
+ {% endfor %}
+ {# Not used now - Todo: Delete after we're sure this is right.