about summary refs log tree commit diff
path: root/web/webqtl/base
diff options
context:
space:
mode:
authorroot2012-05-08 18:39:56 -0500
committerroot2012-05-08 18:39:56 -0500
commitea46f42ee640928b92947bfb204c41a482d80937 (patch)
tree9b27a4eb852d12539b543c3efee9d2a47ef470f3 /web/webqtl/base
parent056b5253fc3857b0444382aa39944f6344dc1ceb (diff)
downloadgenenetwork2-ea46f42ee640928b92947bfb204c41a482d80937.tar.gz
Add all the source codes into the github.
Diffstat (limited to 'web/webqtl/base')
-rwxr-xr-xweb/webqtl/base/GeneralObject.py71
-rwxr-xr-xweb/webqtl/base/__init__.py0
-rwxr-xr-xweb/webqtl/base/admin.py88
-rwxr-xr-xweb/webqtl/base/cgiData.py70
-rwxr-xr-xweb/webqtl/base/cookieData.py52
-rwxr-xr-xweb/webqtl/base/footer.py6
-rwxr-xr-xweb/webqtl/base/header.py6
-rwxr-xr-xweb/webqtl/base/indexBody.py290
-rwxr-xr-xweb/webqtl/base/myCookie.py55
-rwxr-xr-xweb/webqtl/base/sessionData.py53
-rw-r--r--web/webqtl/base/template.py123
-rw-r--r--web/webqtl/base/templatePage.py222
-rwxr-xr-xweb/webqtl/base/webqtlCaseData.py54
-rwxr-xr-xweb/webqtl/base/webqtlConfig.py73
-rwxr-xr-xweb/webqtl/base/webqtlConfigLocal.py19
-rwxr-xr-xweb/webqtl/base/webqtlDataset.py160
-rwxr-xr-xweb/webqtl/base/webqtlFormData.py289
-rw-r--r--web/webqtl/base/webqtlTrait.py581
18 files changed, 2212 insertions, 0 deletions
diff --git a/web/webqtl/base/GeneralObject.py b/web/webqtl/base/GeneralObject.py
new file mode 100755
index 00000000..311c9e22
--- /dev/null
+++ b/web/webqtl/base/GeneralObject.py
@@ -0,0 +1,71 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+class GeneralObject:
+	"""
+	Base class to define an Object.
+	a = [Spam(1, 4), Spam(9, 3), Spam(4,6)]
+	a.sort(lambda x, y: cmp(x.eggs, y.eggs))
+	"""
+
+	def __init__(self, *args, **kw):
+		self.contents = list(args)
+		for name, value in kw.items():
+			setattr(self, name, value)
+			
+	def __setitem__(self, key, value):
+		setattr(self, key, value)
+		
+	def __getitem__(self, key):
+		return getattr(self, key)
+		
+	def __getattr__(self, key):
+		if key in self.__dict__.keys():
+			return self.__dict__[key]
+		else:
+			return eval("self.__dict__.%s" % key)
+			
+	def __len__(self):
+		return len(self.__dict__) - 1
+				
+	def __str__(self):
+		s = ''
+		for key in self.__dict__.keys():
+			if key != 'contents':
+				s += '%s = %s\n' % (key,self.__dict__[key])
+		return s
+	
+	def __repr__(self):
+		s = ''
+		for key in self.__dict__.keys():
+			s += '%s = %s\n' % (key,self.__dict__[key])
+		return s
+	
+	def __cmp__(self,other):
+		return len(self.__dict__.keys()).__cmp__(len(other.__dict__.keys()))
+
+
+
diff --git a/web/webqtl/base/__init__.py b/web/webqtl/base/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/web/webqtl/base/__init__.py
diff --git a/web/webqtl/base/admin.py b/web/webqtl/base/admin.py
new file mode 100755
index 00000000..a04df2da
--- /dev/null
+++ b/web/webqtl/base/admin.py
@@ -0,0 +1,88 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+
+
+
+
+#XZ, 04/02/2009: we should put this into database.
+
+
+###LIST of databases used into gene name query
+
+
+ADMIN_search_dbs = {
+                    'rat': {'PERITONEAL FAT': ['FT_2A_0605_Rz'], 
+                            'KIDNEY': ['KI_2A_0405_Rz'],
+                            'ADRENAL GLAND': ['HXB_Adrenal_1208'],
+                            'HEART': ['HXB_Heart_1208']
+                           },
+                    'mouse': {'CEREBELLUM': ['CB_M_0305_R'], 
+                              'STRIATUM': ['SA_M2_0905_R', 'SA_M2_0405_RC', 'UTHSC_1107_RankInv', 'Striatum_Exon_0209'],
+                              'HIPPOCAMPUS': ['HC_M2_0606_R', 'UMUTAffyExon_0209_RMA'], 
+                              'WHOLE BRAIN': ['BR_M2_1106_R', 'IBR_M_0106_R', 'BRF2_M_0805_R', 'UCLA_BHF2_BRAIN_0605'], 
+                              'LIVER': ['LV_G_0106_B', 'UCLA_BHF2_LIVER_0605'], 
+                              'EYE': ['Eye_M2_0908_R'], 
+                              'HEMATOPOIETIC STEM CELLS': ['HC_U_0304_R'], 
+                              'KIDNEY': ['MA_M2_0806_R'],
+                              'MAMMARY TUMORS': ['MA_M_0704_R', 'NCI_Agil_Mam_Tum_RMA_0409'],
+                              'PREFRONTAL CORTEX': ['VCUSal_1206_R'],
+                              'SPLEEN': ['IoP_SPL_RMA_0509'],
+                              'NUCLEUS ACCUMBENS': ['VCUSalo_1007_R'],
+                              'NEOCORTEX': ['HQFNeoc_0208_RankInv'],
+                              'ADIPOSE': ['UCLA_BHF2_ADIPOSE_0605'],
+                              'RETINA': ['Illum_Retina_BXD_RankInv0410']
+                             },
+                    'human': {
+                              'LYMPHOBLAST B CELL': ['Human_1008', 'UT_CEPH_RankInv0909'],
+                              'WHOLE BRAIN': ['GSE5281_F_RMA0709', 'GSE15222_F_RI_0409']
+                             }
+                   }
+
+
+###LIST of tissue alias
+
+ADMIN_tissue_alias = {'CEREBELLUM': ['Cb'], 
+                      'STRIATUM': ['Str'], 
+                      'HIPPOCAMPUS': ['Hip'], 
+                      'WHOLE BRAIN': ['Brn'], 
+                      'LIVER': ['Liv'], 
+                      'EYE': ['Eye'], 
+                      'PERITONEAL FAT': ['Fat'], 
+                      'HEMATOPOIETIC STEM CELLS': ['Hsc'], 
+                      'KIDNEY': ['Kid'],
+                      'ADRENAL GLAND': ['Adr'],
+                      'HEART': ['Hea'],
+                      'MAMMARY TUMORS': ['Mam'],
+                      'PREFRONTAL CORTEX': ['Pfc'],
+                      'SPLEEN': ['Spl'],
+                      'NUCLEUS ACCUMBENS': ['Nac'],
+                      'NEOCORTEX': ['Ctx'],
+                      'ADIPOSE': ['Wfat'],
+                      'RETINA': ['Ret']
+                     }
+
+
diff --git a/web/webqtl/base/cgiData.py b/web/webqtl/base/cgiData.py
new file mode 100755
index 00000000..57416060
--- /dev/null
+++ b/web/webqtl/base/cgiData.py
@@ -0,0 +1,70 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+#########################################
+#convert Field storage object to Dict object
+#in order to be able to saved into a session file
+#########################################
+
+class cgiData(dict):
+	'''convert Field storage object to Dict object
+	   Filed storage object cannot be properly dumped	
+	'''
+
+	def __init__(self, field_storage=None):
+
+		if not field_storage:
+			field_storage={}
+			
+		for key in field_storage.keys():
+			temp = field_storage.getlist(key)
+			if len(temp) > 1:
+				temp = map(self.toValue, temp)
+			elif len(temp) == 1:
+				temp = self.toValue(temp[0])
+			else:
+				temp = None
+			self[key]= temp
+	
+	def toValue(self, obj):
+		'''fieldstorge returns different type of objects, \
+			need to convert to string or None'''	
+		try:
+			return obj.value
+		except:
+			return ""
+	
+	def getvalue(self, k, default= None):
+		try:
+			return self[k]
+		except:
+			return default
+
+	getfirst = getvalue
+
+
+
+
diff --git a/web/webqtl/base/cookieData.py b/web/webqtl/base/cookieData.py
new file mode 100755
index 00000000..4b7c9046
--- /dev/null
+++ b/web/webqtl/base/cookieData.py
@@ -0,0 +1,52 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+#########################################
+#convert mod_python object to Dict object
+#in order to be able to be pickled
+#########################################
+
+class cookieData(dict):
+	'convert mod python Cookie object to Dict object'
+
+	def __init__(self, cookies=None):
+
+		if not cookies:
+			cookies={}
+			
+		for key in cookies.keys():
+			self[key.lower()]= cookies[key].value
+	
+	def getvalue(self, k, default= None):
+		try:
+			return self[k.lower()]
+		except:
+			return default
+
+	getfirst = getvalue
+
+
+
diff --git a/web/webqtl/base/footer.py b/web/webqtl/base/footer.py
new file mode 100755
index 00000000..6f92fdf8
--- /dev/null
+++ b/web/webqtl/base/footer.py
@@ -0,0 +1,6 @@
+import webqtlConfig
+
+footer_html = open(webqtlConfig.HTMLPATH + 'footer.html', 'r').read()
+footer = footer_html.replace('%"','%%"')
+
+footer_string = footer.replace('<!-- %s -->', '%s')
diff --git a/web/webqtl/base/header.py b/web/webqtl/base/header.py
new file mode 100755
index 00000000..b6136b51
--- /dev/null
+++ b/web/webqtl/base/header.py
@@ -0,0 +1,6 @@
+import webqtlConfig
+
+header_string = open(webqtlConfig.HTMLPATH + 'header.html', 'r').read()
+header_string = header_string.replace("\\'", "'")
+header_string = header_string.replace('%"','%%"')
+header_string = header_string.replace('<!-- %s -->', '%s')
\ No newline at end of file
diff --git a/web/webqtl/base/indexBody.py b/web/webqtl/base/indexBody.py
new file mode 100755
index 00000000..aa67dffa
--- /dev/null
+++ b/web/webqtl/base/indexBody.py
@@ -0,0 +1,290 @@
+index_body_string = """
+<TD vAlign=top width="40%" align="left" height=10 bgColor=#eeeeee>
+							<p style="font-size:18px;font-family:verdana;color:black"><B> Select and Search</B>
+							<Form METHOD="POST" ACTION="/webqtl/main.py" ENCTYPE="multipart/form-data" NAME="SEARCHFORM">
+
+								<TABLE width="100%">
+					
+					<!--  SPECIES  SELECTION -->				
+									<TR>
+										<TD align=right height="35" style="font-size:14px;font-family:verdana;color:black" width="16%">
+											<B>Species:</B>
+										</TD>
+
+										<TD width="3%">
+										</TD>
+
+										<TD NOWRAP width="85%" align="left">
+											<DIV Id="menu0">
+												<Select NAME="species" size=1 id="species" onchange="fillOptions('species');">
+												</Select>
+											</DIV>
+										</TD>
+									</TR>
+				
+					<!--  GROUP  SELECTION -->	
+			
+									<TR>
+
+										<TD align="right" height="35" style="font-size:14px;font-family:verdana;color:black">
+											<B>Group:</B>
+										</TD>
+
+										<TD width="3%">
+										</TD>
+
+										<TD NOWRAP width="85%" align="left">
+											<DIV Id="menu1">
+
+												<Select NAME="cross" size=1 id="cross" onchange="fillOptions('cross');">
+												</Select>
+											<input type="button" class="button" value=" Info " onCLick="javascript:crossinfo();">
+											</DIV>
+										</TD>
+									</TR>
+
+
+					<!--  TYPE  SELECTION -->		
+		
+									<TR>
+
+										<TD align=right height=35 style="font-size:14px;font-family:verdana;color:black">
+											<B>Type:</B>
+										</TD>
+
+										<TD width="3%">
+										</TD>
+										<TD NOWRAP width="85%" align="left">
+											<DIV Id="menu2">
+												<Select NAME="tissue" size=1 id="tissue" onchange="fillOptions('tissue');">
+
+												</Select>
+											</DIV>
+										</TD>
+									</TR>
+		
+
+					<!--  DATABASE  SELECTION -->		
+									<TR>
+										<TD align=right height=35 style="font-size:14px;font-family:verdana;color:black">
+											<B>Database:</B>
+										</TD>
+
+										<TD width="3%">
+										</TD>
+
+										<TD NOWRAP width="85%" align="left">
+											<DIV Id="menu3">
+												<Select NAME="database" size=1 id="database"> 
+												</Select>
+												<input type="button" class="button" value=" Info " onCLick="javascript:databaseinfo();">
+											</DIV>
+
+										</TD>
+									</TR>
+
+					<!--  USER HELP   -->				
+									<TR>
+										<TD align=right height=20 width="10%">
+										</TD>
+										<TD width="3%">
+										</TD>
+
+										<TD align="left" width="85%">
+											<P class="fs12">&nbsp;&nbsp;&nbsp;&nbsp;Databases marked with <B>**</B> suffix are not public yet. 
+											<BR>&nbsp;&nbsp;&nbsp;&nbsp;Access requires <A HREF="/account.html" target="_blank" class="fs14"><small>user login</small></A>.</P>
+										</TD>
+									</TR>
+
+
+<!--  GET ANY  SEARCH -->			
+									<TR>
+										<TD align=right height=35 NOWRAP="on" style="font-size:14px;font-family:verdana;color:black" width="10%">
+											<B>Get Any:</B>
+										</TD>
+
+										<TD width="3%">
+										</TD>
+
+										<TD NOWRAP width="85%" align="left">
+
+											<input id="tfor" name="ORkeyword" style="width:420px; background-color:white; font-family:verdana; font-size:14px" type="text" maxlength="500">
+										</TD>
+									</TR>
+
+
+
+<!--  GET ANY HELP   -->
+									<TR>
+										<TD align=right height=20 width="10%">
+										</TD>
+										<TD width="3%">
+
+										</TD>
+										<TD width="85%" align="left">
+											<P class="fs12">&nbsp;&nbsp;&nbsp;&nbsp;Enter terms, genes, ID numbers in the <B>Get Any</B> field.  
+											<BR>&nbsp;&nbsp;&nbsp;&nbsp;Use <B>*</B> or <B>?</B> wildcards (Cyp*a?, synap*).
+											<BR>&nbsp;&nbsp;&nbsp;&nbsp;Use <B>Combined</B> for terms such as <I>tyrosine kinase</I>.</P>
+
+										</TD>
+									</TR>
+
+
+
+<!--  COMBINED SEARCH  -->
+
+									<TR>
+										<TD align=right height=35 NOWRAP="on" STYLE="font-size:14px;font-family:verdana;color:black" width="10%">
+											<B>Combined:</B>
+										</TD>
+
+										<TD width="3%">
+										</TD>
+
+										<TD NOWRAP width="85%" align="left">
+											<input id="tfand" NAME="ANDkeyword"  STYLE="width:420px; background-color:white; font-family:verdana; font-size:14px" type="text" maxlength="500">
+											<input name="matchwhole" type="hidden" value="ON"> 
+										</TD>
+									</TR>
+
+
+
+<!--  SEARCH, MAKE DEFAULT, ADVANCED SEARCH -->
+
+									<TR ALIGN="center">
+										<TD width="3%">
+										</TD>
+										<TD width="3%">
+										</TD>										
+										<TD ALIGN="left" HEIGHT="40" COLSPAN=3>
+											<INPUT id="btsearch" TYPE="Submit" CLASS="button" STYLE="font-size:12px" VALUE="  Search  ">&nbsp;&nbsp;&nbsp;&nbsp;
+										       <INPUT TYPE="button" CLASS="button" STYLE="font-size:12px" VALUE="  Make Default  " onClick = "setDefault(this.form);">&nbsp;&nbsp;&nbsp;&nbsp;	
+											<INPUT TYPE="button" CLASS="button" STYLE="font-size:12px" VALUE="  Advanced Search  " onClick="javascript:window.open('/index3.html', '_self');">
+
+										</TD>
+									</TR>
+								</TABLE>
+								<INPUT TYPE="hidden" NAME="FormID" VALUE="searchResult">
+								<INPUT TYPE="hidden" NAME="RISet" VALUE="BXD">
+								<SCRIPT SRC="/javascript/selectDatasetMenu.js"></SCRIPT>
+							</FORM>
+							</CENTER>
+
+
+
+
+
+<!--  QUICK HELP  -->
+
+<P><LEFT>&nbsp;______________________________________________________
+
+<P STYLE="font-size:13px;font-family:verdana;color:black"><B>&nbsp;
+
+Quick HELP Examples and </B>
+<A HREF="http://www.genenetwork.org/index4.html" target="_blank"  class="fs14"><B>
+ User's Guide</B></A></P>
+
+</CENTER style="font-size:12px;font-family:verdana;color:black">
+&nbsp;&nbsp;You can also use advanced commands. Copy these simple examples 
+<BR>&nbsp;&nbsp;into the <B>Get Any</B> or <B>Combined</B> search fields:
+<UL style="font-size:12px;font-family:verdana;color:black">
+
+<LI><B><I>POSITION=(chr1 25 30)</I></B> finds genes, markers, or transcripts on chromosome 1 between 25 and 30 Mb.
+
+<LI><B><I>MEAN=(15 16) LRS=(23 46)</I></B> in the <B>Combined</B> field finds highly expressed genes (15 to 16 log2 units) AND with peak <A HREF="http://www.genenetwork.org/glossary.html#L" target="_blank"  class="fs14"><small>LRS</small></A> linkage between 23 and 46.
+
+
+<LI><B><I>RIF=mitochondrial</I></B> searches RNA databases for <A HREF="http://www.ncbi.nlm.nih.gov/projects/GeneRIF/GeneRIFhelp.html" target="_blank"  class="fs14"><small>GeneRIF</small></A> links.
+
+<LI><B><I>WIKI=nicotine</I></B> searches <A HREF="http://www.genenetwork.org/webqtl/main.py?FormID=geneWiki" target="_blank"  class="fs14"><small>GeneWiki</small></A> for genes that you or other users have annotated with the word <I>nicotine</I>.
+
+<LI><B><I>GO:0045202</I></B> searches for synapse-associated genes listed in the <A HREF="http://www.godatabase.org/cgi-bin/amigo/go.cgi" target="_blank"  class="fs14"><small>Gene Ontology</small></A>.
+
+
+<LI><B><I>GO:0045202 LRS=(9 99 Chr4 122 155) cisLRS=(9 999 10)</I> </B><BR> in <B>Combined</B> finds synapse-associated genes with <A HREF="http://www.genenetwork.org/glossary.html#E" target="_blank"  class="fs14"><small>cis eQTL</small></A> on Chr 4 from 122 and 155 Mb with LRS scores between 9 and 999.
+
+<LI><B><I>RIF=diabetes LRS=(9 999 Chr2 100 105) transLRS=(9 999 10)</I> </B><BR> in <B>Combined</B> finds diabetes-associated transcripts with peak <A HREF="http://www.genenetwork.org/glossary.html#E" target="_blank"  class="fs14"><small>trans eQTLs</small></A> on Chr 2 between 100 and 105 Mb with LRS scores between 9 and 999.
+
+
+</UL> 
+</DIR>
+					</TD>				
+<!-- END OF FIND SELECTOR PULL-DOWN PANEL (LEFT SIDE)  -->
+
+<!-- START OF TOP RIGHT PANEL  -->
+
+<TD vAlign=top width="40%" bgColor=#FFFFFF>
+							<p style="font-size:15px;font-family:verdana;color:black"><B>Websites Affiliated with GeneNetwork</B></p>
+		<p style="font-size:12px;font-family:verdana;color:black">
+			<ul>
+				<li><a href="http://ucscbrowser.genenetwork.org/" target="_blank">Genome Browser</a> at UTHSC</li>
+				<li><a href="http://galaxy.genenetwork.org/" target="_blank">Galaxy</a> at UTHSC</li>
+				<li>GeneNetwork at <a href="http://ec2.genenetwork.org/" target="_blank">Amazon Cloud (EC2)</a></li>
+				<li>GeneNetwork Source Codes at <a href="http://sourceforge.net/projects/genenetwork/" target="_blank">SourceForge</a></li>
+			</ul>
+		</p>
+							<P>____________________________
+
+							<p style="font-size:15px;font-family:verdana;color:black"><B>Getting Started</B> &nbsp;&nbsp; </p>
+							<OL style="font-size:12px;font-family:verdana;color:black">
+								<LI>Select <B>Species</B> (or select All) 
+								<LI>Select <B>Group</B> (a specific sample)
+								<LI>Select <B>Type</B> of data:  
+								<UL>
+									<LI>Phenotype (traits)
+									<LI>Genotype (markers)
+									<LI>Expression (mRNAs)
+								</UL>
+								<LI>Select a <B>Database</B> 
+								<LI>Enter search terms in the <B>Get Any</B> or <B>Combined</B> field: words, genes, ID numbers, probes, advanced search commands 
+								<LI>Click on the <B>Search</B> button
+								<LI>Optional: Use the <B>Make Default</B> button to save your preferences
+							</OL>
+
+							<P>____________________________
+
+<p style="font-size:14px;font-family:verdana;color:black"><B>How to Use GeneNetwork</B>
+
+							<BLOCKQUOTE>
+								<p style="font-size:12px;font-family:verdana;color:black">Take a 20-40 minute GeneNetwork <A HREF="http://www.genenetwork.org/tutorial/WebQTLTour/" target="_blank" class="fs14"><small>Tour</small></A> that includes screen shots and typical steps in the analysis.</P>
+							</BLOCKQUOTE>							
+							<BLOCKQUOTE>
+								<p style="font-size:12px;font-family:verdana;color:black">For information about resources and methods, select the <img src="http://www.genenetwork.org/images/upload/Info.png" alt="INFO" border= 0 valign="middle"> buttons.</P>
+
+													
+														
+<p style="font-size:12px;font-family:verdana;color:black">Try the <A HREF="http://alexandria.uthsc.edu/" target="_blank" class="fs14"><small>Workstation</small></A> site to explore data and features that are being implemented.</P>
+
+
+<p style="font-size:12px;font-family:verdana;color:black">Review the <A HREF="/conditionsofUse.html" target="_blank" class="fs14"><small>Conditions</small></A> and <A HREF="/statusandContact.html" target="_blank" class="fs14"><small>Contacts</small></A> pages for information on the status of data sets and advice on their use and citation.</P> 
+
+
+							</BLOCKQUOTE>
+
+							
+
+							<p style="font-size:14px;font-family:verdana;color:black"><B>Mirror and Development Sites</B></P>
+
+							<UL>
+								<LI><A HREF="http://www.genenetwork.org/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Main GN site at UTHSC</A> (main site)
+								<LI><A HREF="http://www.genenetwork.waimr.uwa.edu.au/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Australia at the UWA</A>
+								<LI><A HREF="http://gn.genetics.ucla.edu/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">California at UCLA</A>
+								<LI><A HREF="http://genenetwork.helmholtz-hzi.de/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Germany at the HZI</A>
+								<LI><A HREF="https://genenetwork.hubrecht.eu/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Netherlands at the Hubrecht</A> (Development)
+								<LI><A HREF="http://xzhou3.memphis.edu/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Memphis at the U of M</A>
+								<LI><A HREF="http://webqtl.bic.nus.edu.sg/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Singapore at the NUS</A>
+ 								<LI><A HREF="http://genenetwork.epfl.ch/" target="_blank" style="font-size:12px;font-family:verdana;color:blue">Switzerland at the EPFL</A>
+							</UL>
+
+
+							<p style="font-size:14px;font-family:verdana;color:black"><B>History and Archive</B>
+
+							<BLOCKQUOTE>
+								<p style="font-size:12px;font-family:verdana;color:black">GeneNetwork's <A HREF="http://artemis.uthsc.edu" target="_blank" class="fs14"><small>Time Machine</small></A> links to earlier versions that correspond to specific publication dates.</P>
+
+							</BLOCKQUOTE> 
+
+
+</P>
+						</TD>
+"""
diff --git a/web/webqtl/base/myCookie.py b/web/webqtl/base/myCookie.py
new file mode 100755
index 00000000..db5320df
--- /dev/null
+++ b/web/webqtl/base/myCookie.py
@@ -0,0 +1,55 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+#########################################
+## python cookie and mod python cookie are 
+## not compatible
+#########################################
+
+class myCookie(dict):
+	'define my own cookie'
+
+	def __init__(self, name="", value="", expire = None, path="/"):
+		self['name']= name
+		self['value']= value
+		self['expire']= expire
+		self['path']= path
+	
+	def __getattr__(self, key):
+		if key in self.keys():
+			return self[key]
+		else:
+			return None
+	
+	def __nonzero__ (self):
+		if self['name']:
+			return 1
+		else:
+			return 0	
+
+
+
+
diff --git a/web/webqtl/base/sessionData.py b/web/webqtl/base/sessionData.py
new file mode 100755
index 00000000..01555f87
--- /dev/null
+++ b/web/webqtl/base/sessionData.py
@@ -0,0 +1,53 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+#########################################
+#convert mod_python object to Dict object
+#in order to be able to be pickled
+#########################################
+
+class sessionData(dict):
+	'convert mod python Session object to Dict object'
+
+	def __init__(self, mod_python_session=None):
+	
+		if not mod_python_session:
+			mod_python_session = {}
+
+		for key in mod_python_session.keys():
+			self[key]= mod_python_session[key]
+		
+	
+	def getvalue(self, k, default= None):
+		try:
+			return self[k]
+		except:
+			return default
+
+	getfirst = getvalue
+
+
+
diff --git a/web/webqtl/base/template.py b/web/webqtl/base/template.py
new file mode 100644
index 00000000..85bd86df
--- /dev/null
+++ b/web/webqtl/base/template.py
@@ -0,0 +1,123 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+template = """
+<?XML VERSION="1.0" ENCODING="UTF-8">
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<TITLE>%s</TITLE>
+
+<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<META NAME="keywords" CONTENT="genetics, bioinformatics, genome, phenome, gene expression, complex trait analysis, gene mapping, SNP, quantitative trait locus QTL, expression eQTL, WebQTL, Traitnet, Traitnetwork, personalized medicine">
+<META NAME="description" CONTENT ="GeneNetwork is a free scientific web resource used to study relationships between differences in genes, environmental factors, phenotypes, and disease risk." >
+<META NAME="author" CONTENT ="GeneNetwork developers" >
+<META NAME="geo.placename" CONTENT ="Memphis, TN" >
+<META NAME="geo.region" CONTENT="US-TN">
+%s
+<LINK REL="stylesheet" TYPE="text/css" HREF='/css/general.css'>
+<LINK REL="stylesheet" TYPE="text/css" HREF='/css/menu.css'>
+<link rel="stylesheet" media="all" type="text/css" href="/css/tabbed_pages.css" />
+<LINK REL="apple-touch-icon" href="/images/ipad_icon3.png" />
+<link type="text/css" href='/css/custom-theme/jquery-ui-1.8.12.custom.css' rel='Stylesheet' />
+<link type="text/css" href='/css/tab_style.css' rel='Stylesheet' />
+
+<script type="text/javascript" src="/javascript/jquery-1.5.2.min.js"></script>
+<SCRIPT SRC="/javascript/webqtl.js"></SCRIPT>
+<SCRIPT SRC="/javascript/dhtml.js"></SCRIPT>
+<SCRIPT SRC="/javascript/tablesorter.js"></SCRIPT>
+<SCRIPT SRC="/javascript/jqueryFunction.js"></SCRIPT>
+<script src="/javascript/tabbed_pages.js" type="text/javascript"></script>
+<script src="/javascript/jquery-ui-1.8.12.custom.min.js" type="text/javascript"></script>
+%s
+
+<script type="text/javascript">
+  var _gaq = _gaq || [];
+  _gaq.push(['_setAccount', 'UA-3782271-1']);
+  _gaq.push(['_trackPageview']);
+  (function() {
+    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+  })();
+</script>
+</HEAD>
+<BODY  bottommargin="2" leftmargin="2" rightmargin="2" topmargin="2" text=#000000 bgColor=#ffffff %s>
+%s
+<TABLE cellSpacing=5 cellPadding=4 width="100%%" border=0>
+	<TBODY>
+	<!-- Start of header -->
+	<TR>
+		%s
+	</TR>
+	<!-- End of header -->
+
+	<!-- Start of body -->
+	<TR>
+		<TD  bgColor=#eeeeee class="solidBorder">
+		<Table width= "100%%" cellSpacing=0 cellPadding=5>
+		<TR>
+		%s
+		</TR>
+		</TABLE>
+		</TD>
+	</TR>
+	<!-- End of body -->
+
+        <!-- Start of footer -->
+	<TR>
+		<TD align=center bgColor=#ddddff class="solidBorder">
+			<TABLE width="90%%">%s</table>
+		</td>
+	</TR>
+	<!-- End of footer -->
+</TABLE>
+
+<!-- menu script itself. you should not modify this file -->
+<script language="JavaScript" src="/javascript/menu_new.js"></script>
+<!-- items structure. menu hierarchy and links are stored there -->
+<script language="JavaScript" src="/javascript/menu_items.js"></script>
+<!-- files with geometry and styles structures -->
+<script language="JavaScript" src="/javascript/menu_tpl.js"></script>
+<script language="JavaScript">
+	<!--//
+	// Note where menu initialization block is located in HTML document.
+	// Don't try to position menu locating menu initialization block in
+	// some table cell or other HTML element. Always put it before </body>
+	// each menu gets two parameters (see demo files)
+	// 1. items structure
+	// 2. geometry structure
+	new menu (MENU_ITEMS, MENU_POS);
+	// make sure files containing definitions for these variables are linked to the document
+	// if you got some javascript error like "MENU_POS is not defined", then you've made syntax
+	// error in menu_tpl.js file or that file isn't linked properly.
+	
+	// also take a look at stylesheets loaded in header in order to set styles
+	//-->
+</script>
+</BODY>
+</HTML>
+"""
diff --git a/web/webqtl/base/templatePage.py b/web/webqtl/base/templatePage.py
new file mode 100644
index 00000000..4dece24a
--- /dev/null
+++ b/web/webqtl/base/templatePage.py
@@ -0,0 +1,222 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+#templatePage.py
+#
+#--Genenetwork generates a lot of pages; this file is the generic version of them, defining routines they all use.
+#
+#Classes:
+#templatePage
+#
+#Functions (of templatePage):
+#__init__(...) -- class constructor, allows a more specific template to be used in addition to templatePage
+#__str__(self) -- returns the object's elements as a tuple
+#__del__(self) -- closes the current connection to MySQL, if there is one
+#write -- explained below
+#writefile -- explained below
+#openMysql(self) -- opens a MySQL connection and stores the resulting cursor in the object's cursor variable
+#updMysql(self) -- same as openMysql
+#error -- explained below
+#session -- explained below
+
+
+import socket
+import time
+import shutil
+import MySQLdb
+import os
+
+from htmlgen import HTMLgen2 as HT
+
+import template
+import webqtlConfig
+import header
+import footer
+from utility import webqtlUtil
+
+
+
+class templatePage:
+
+	contents = ['title','basehref','js1','js2', 'layer', 'header', 'body', 'footer']
+
+	# you can pass in another template here if you want
+	def __init__(self, fd=None, template=template.template):
+
+		# initiate dictionary
+		self.starttime = time.time()
+		self.dict = {}
+		self.template = template
+		
+		for item in self.contents:
+			self.dict[item] = ""
+		
+		self.dict['basehref'] = "" #webqtlConfig.BASEHREF
+		self.cursor = None
+		
+		self.cookie = [] #XZ: list to hold cookies (myCookie object) being changed
+		self.content_type = 'text/html'
+		self.content_disposition = ''
+		self.redirection = ''
+		self.debug = ''
+		self.attachment = ''
+
+		#XZ: Holding data (new data or existing data being changed) that should be saved to session. The data must be picklable!!!
+		self.session_data_changed = {}
+
+		self.userName = 'Guest'
+		self.privilege = 'guest'
+		if fd.input_session_data.has_key('user'):
+			self.userName = fd.input_session_data['user']
+		if fd.input_session_data.has_key('privilege'):
+			self.privilege = fd.input_session_data['privilege']
+	
+	def __str__(self):
+
+		#XZ: default setting
+		thisUserName = self.userName
+		thisPrivilege = self.privilege
+		#XZ: user may just go through login or logoff page
+		if self.session_data_changed.has_key('user'):
+			thisUserName = self.session_data_changed['user']
+		if self.session_data_changed.has_key('privilege'):
+			thisPrivilege = self.session_data_changed['privilege']
+
+		if thisUserName == 'Guest':
+			userInfo = 'Welcome! <a href=/account.html><U>Login</U></a>'
+		else:
+			userInfo = 'Hi, %s! <a href=/webqtl/main.py?FormID=userLogoff><U>Logout</U></a>' % thisUserName
+
+		reload(header)
+		self.dict['header'] = header.header_string % userInfo
+
+		serverInfo = "It took %2.3f second(s) for %s to generate this page" % (time.time()-self.starttime, socket.getfqdn())
+		reload(footer)
+		self.dict['footer'] = footer.footer_string % serverInfo
+
+		slist = []
+		for item in self.contents:
+			slist.append(self.dict[item])
+		return self.template % tuple(slist)
+
+
+	def __del__(self):
+		if self.cursor:
+			self.cursor.close()
+			
+	def write(self):
+		'return string representation of this object'
+
+		if self.cursor:
+			self.cursor.close()
+
+		return str(self)	
+		
+	def writeFile(self, filename):
+		'save string representation of this object into a file'
+		if self.cursor:
+			self.cursor.close()
+			
+		try:
+			'it could take a long time to generate the file, save to .tmp first'
+			fp = open(os.path.join(webqtlConfig.TMPDIR, filename+'.tmp'), 'wb')
+			fp.write(str(self))
+			fp.close()
+                        path_tmp = os.path.join(webqtlConfig.TMPDIR, filename+'.tmp')
+                        path_html = os.path.join(webqtlConfig.TMPDIR, filename)
+                        shutil.move(path_tmp,path_html)           
+		except:
+			pass	
+
+	def openMysql(self):
+		try:
+			self.con = MySQLdb.Connect(db=webqtlConfig.DB_NAME,host=webqtlConfig.MYSQL_SERVER, \
+						user=webqtlConfig.DB_USER,passwd=webqtlConfig.DB_PASSWD)
+			self.cursor = self.con.cursor()
+			return 1
+		except:
+			heading = "Connect MySQL Server"
+			detail = ["Can't connect to MySQL server on '"+ webqtlConfig.MYSQL_SERVER+"':100061. \
+					The server may be down at this time"]
+			self.error(heading=heading,detail=detail,error="Error 2003")
+			return 0
+
+	def updMysql(self):
+		try:
+			self.con = MySQLdb.Connect(db=webqtlConfig.DB_UPDNAME,host=webqtlConfig.MYSQL_UPDSERVER, \
+						user=webqtlConfig.DB_UPDUSER,passwd=webqtlConfig.DB_UPDPASSWD)
+			self.cursor = self.con.cursor()
+			return 1
+		except:
+			heading = "Connect MySQL Server"
+			detail = ["update: Can't connect to MySQL server on '"+ webqtlConfig.MYSQL_UPDSERVER+"':100061. \
+					The server may be down at this time "]
+			self.error(heading=heading,detail=detail,error="Error 2003")
+			return 0
+	
+	def error(self,heading="",intro=[],detail=[],title="Error",error="Error"):
+		'generating a WebQTL style error page'
+		Heading = HT.Paragraph(heading)
+		Heading.__setattr__("class","title")
+		
+		Intro = HT.Blockquote()
+		if intro:
+			for item in intro:
+				Intro.append(item)
+		else:
+			Intro.append(HT.Strong('Sorry!'),' Error occurred while processing\
+				your request.', HT.P(),'The nature of the error generated is as\
+				follows:')
+		
+		Detail = HT.Blockquote()
+		Detail.append(HT.Span("%s : " % error,Class="fwb cr"))
+		if detail:
+			Detail2 = HT.Blockquote()
+			for item in detail:
+				Detail2.append(item)
+			Detail.append(HT.Italic(Detail2))
+			
+		#Detail.__setattr__("class","subtitle")
+		TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee',valign="top")
+		TD_LR.append(Heading,Intro,Detail)
+		self.dict['body'] = str(TD_LR)
+		self.dict['title'] = title
+
+	def session(self,mytitle="",myHeading=""):
+		'generate a auto-refreshing temporary html file(waiting page)'
+		self.filename = webqtlUtil.generate_session()
+		self.dict['title'] = mytitle
+		self.dict['basehref'] = webqtlConfig.REFRESHSTR % (webqtlConfig.CGIDIR, self.filename) + "" #webqtlConfig.BASEHREF
+		
+		TD_LR = HT.TD(align="center", valign="middle", height=200,width="100%", bgColor='#eeeeee')
+		Heading = HT.Paragraph(myHeading, Class="fwb fs16 cr")
+		# NL, 07/27/2010. variable 'PROGRESSBAR' has been moved from templatePage.py to webqtlUtil.py;		
+		TD_LR.append(Heading, HT.BR(), webqtlUtil.PROGRESSBAR)
+		self.dict['body'] = TD_LR
+		self.writeFile(self.filename + '.html')
+		return self.filename
+		
+		
diff --git a/web/webqtl/base/webqtlCaseData.py b/web/webqtl/base/webqtlCaseData.py
new file mode 100755
index 00000000..4df32ca4
--- /dev/null
+++ b/web/webqtl/base/webqtlCaseData.py
@@ -0,0 +1,54 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+class webqtlCaseData:
+	"""
+	one case data in one trait
+	"""
+
+	val = None		#Trait Value
+	var = None		#Trait Variance
+	N   = None		#Number of individuals
+
+	def __init__(self, val=val, var=var, N=N):
+		self.val = val
+		self.var = var
+		self.N = N
+	
+	def __str__(self):
+		str = ""
+		if self.val != None:
+			str += "value=%2.3f" % self.val
+		if self.var != None:
+			str += " variance=%2.3f" % self.var
+		if self.N != None:
+			str += " ndata=%d" % self.N
+		return str
+	
+	__repr__ = __str__
+
+
+
diff --git a/web/webqtl/base/webqtlConfig.py b/web/webqtl/base/webqtlConfig.py
new file mode 100755
index 00000000..87e2f3d0
--- /dev/null
+++ b/web/webqtl/base/webqtlConfig.py
@@ -0,0 +1,73 @@
+from webqtlConfigLocal import *
+#########################################'
+#      Environment Variables - public
+#########################################
+
+#Debug Level
+#1 for debug, mod python will reload import each time
+DEBUG = 1
+
+#USER privilege
+USERDICT = {'guest':1,'user':2, 'admin':3, 'root':4} 
+
+#minimum number of informative strains
+KMININFORMATIVE = 5
+
+#maximum number of traits for interval mapping
+MULTIPLEMAPPINGLIMIT = 11
+
+#maximum number of traits for correlation
+MAXCORR = 100
+
+#Daily download limit from one IP
+DAILYMAXIMUM = 1000
+
+#maximum LRS value
+MAXLRS = 460.0
+
+#temporary data life span
+MAXLIFE = 86400 
+
+#MINIMUM Database public value
+PUBLICTHRESH = 0
+
+#NBCI address
+NCBI_LOCUSID = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s"
+UCSC_REFSEQ = "http://genome.cse.ucsc.edu/cgi-bin/hgGene?db=%s&hgg_gene=%s&hgg_chrom=chr%s&hgg_start=%s&hgg_end=%s"
+GENBANK_ID = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=Nucleotide&cmd=search&doptcmdl=DocSum&term=%s"
+OMIM_ID = "http://www.ncbi.nlm.nih.gov/omim/%s"
+UNIGEN_ID = "http://www.ncbi.nlm.nih.gov/UniGene/clust.cgi?ORG=%s&CID=%s"
+HOMOLOGENE_ID = "http://www.ncbi.nlm.nih.gov/sites/entrez?Db=homologene&Cmd=DetailsSearch&Term=%s"
+PUBMEDLINK_URL = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=PubMed&list_uids=%s&dopt=Abstract"
+UCSC_POS = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=mammal&org=%s&db=%s&position=chr%s:%s-%s&pix=800&Submit=submit"
+UCSC_BLAT = 'http://genome.ucsc.edu/cgi-bin/hgBlat?org=%s&db=%s&type=0&sort=0&output=0&userSeq=%s'
+UTHSC_BLAT = 'http://ucscbrowser.genenetwork.org/cgi-bin/hgBlat?org=%s&db=%s&type=0&sort=0&output=0&userSeq=%s'
+UCSC_GENOME = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d&hgt.customText=http://web2qtl.utmem.edu:88/snp/chr%s"
+ENSEMBLE_BLAT = 'http://www.ensembl.org/Mus_musculus/featureview?type=AffyProbe&id=%s'
+DBSNP = 'http://www.ncbi.nlm.nih.gov/SNP/snp_ref.cgi?type=rs&rs=%s'
+UCSC_RUDI_TRACK_URL = " http://genome.cse.ucsc.edu/cgi-bin/hgTracks?org=%s&db=%s&hgt.customText=http://gbic.biol.rug.nl/~ralberts/tracks/%s/%s"
+GENOMEBROWSER_URL="http://ucscbrowser.genenetwork.org/cgi-bin/hgTracks?clade=mammal&org=Mouse&db=mm9&position=%s&hgt.suggest=&pix=800&Submit=submit"
+ENSEMBLETRANSCRIPT_URL="http://useast.ensembl.org/Mus_musculus/Lucene/Details?species=Mus_musculus;idx=Transcript;end=1;q=%s"
+
+SECUREDIR = GNROOT + 'secure/'
+COMMON_LIB = GNROOT + 'support/admin'
+HTMLPATH = GNROOT + 'web/'
+IMGDIR = HTMLPATH +'image/'
+IMAGESPATH = HTMLPATH + 'images/'
+UPLOADPATH = IMAGESPATH + 'upload/' 
+TMPDIR = HTMLPATH +'tmp/'
+GENODIR = HTMLPATH + 'genotypes/'
+GENO_ARCHIVE_DIR = GENODIR + 'archive/'
+TEXTDIR = HTMLPATH + 'ProbeSetFreeze_DataMatrix/'
+CMDLINEDIR = HTMLPATH + 'webqtl/cmdLine/'
+ChangableHtmlPath = GNROOT + 'web/'
+
+SITENAME = 'GN'
+PORTADDR = "http://132.192.47.32"
+BASEHREF = '<base href="http://132.192.47.32/">'
+INFOPAGEHREF = '/dbdoc/%s.html'
+GLOSSARYFILE = "/glossary.html"
+CGIDIR = '/webqtl/' #XZ: The variable name 'CGIDIR' should be changed to 'PYTHONDIR'
+SCRIPTFILE = 'main.py'
+REFRESHSTR = '<meta http-equiv="refresh" content="5;url=%s' + SCRIPTFILE +'?sid=%s">'
+REFRESHDIR = '%s' + SCRIPTFILE +'?sid=%s'
diff --git a/web/webqtl/base/webqtlConfigLocal.py b/web/webqtl/base/webqtlConfigLocal.py
new file mode 100755
index 00000000..0c95fe7b
--- /dev/null
+++ b/web/webqtl/base/webqtlConfigLocal.py
@@ -0,0 +1,19 @@
+#########################################'
+#      Environment Variables - private
+#########################################
+
+MYSQL_SERVER = 'localhost'
+DB_NAME = 'db_webqtl'
+DB_USER = 'webqtlupd'
+DB_PASSWD = 'webqtl'
+
+MYSQL_UPDSERVER = 'localhost'
+DB_UPDNAME = 'db_webqtl'
+DB_UPDUSER = 'webqtlupd'
+DB_UPDPASSWD = 'webqtl'
+
+GNROOT = '/gnshare/gn/'
+PythonPath = '/usr/bin/python'
+PIDDLE_FONT_PATH = '/usr/lib/python2.4/site-packages/piddle/truetypefonts/'
+
+TEXTUI=0   # This is to protect GN production server. If set to 0, no text UI is allowed.
diff --git a/web/webqtl/base/webqtlDataset.py b/web/webqtl/base/webqtlDataset.py
new file mode 100755
index 00000000..da1b8601
--- /dev/null
+++ b/web/webqtl/base/webqtlDataset.py
@@ -0,0 +1,160 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+from htmlgen import HTMLgen2 as HT
+
+import webqtlConfig
+
+
+
+class webqtlDataset:
+	"""
+	Database class defines a database in webqtl, can be either Microarray, 	
+	Published phenotype, genotype, or user input database(temp)
+	"""
+
+	def __init__(self, dbName, cursor=None):
+
+		assert dbName
+		self.id = 0
+		self.name = ''
+		self.type = ''
+		self.riset = ''
+		self.cursor = cursor
+
+                #temporary storage
+		if dbName.find('Temp') >= 0:
+			self.searchfield = ['name','description']
+			self.disfield = ['name','description']
+			self.type = 'Temp'
+			self.id = 1
+			self.fullname = 'Temporary Storage'
+			self.shortname = 'Temp'
+		elif dbName.find('Publish') >= 0:
+			self.searchfield = ['name','post_publication_description','abstract','title','authors']
+			self.disfield = ['name','pubmed_id', 
+					'pre_publication_description', 'post_publication_description', 'original_description', 
+					'pre_publication_abbreviation', 'post_publication_abbreviation',
+					'lab_code', 'submitter', 'owner', 'authorized_users',
+					'authors','title','abstract', 'journal','volume','pages','month',
+					'year','sequence', 'units', 'comments']
+			self.type = 'Publish'
+		elif dbName.find('Geno') >= 0:
+			self.searchfield = ['name','chr']
+			self.disfield = ['name','chr','mb', 'source2', 'sequence']
+			self.type = 'Geno'
+		else: #ProbeSet
+			self.searchfield = ['name','description','probe_target_description',
+				'symbol','alias','genbankid','unigeneid','omim',
+				'refseq_transcriptid','probe_set_specificity', 'probe_set_blat_score']
+			self.disfield = ['name','symbol','description','probe_target_description',
+				'chr','mb','alias','geneid','genbankid', 'unigeneid', 'omim',
+				'refseq_transcriptid','blatseq','targetseq','chipid', 'comments',
+				'strand_probe','strand_gene','probe_set_target_region', 
+				'probe_set_specificity', 'probe_set_blat_score','probe_set_blat_mb_start',
+				'probe_set_blat_mb_end', 'probe_set_strand', 
+				'probe_set_note_by_rw', 'flag']
+			self.type = 'ProbeSet'
+		self.name = dbName
+		if self.cursor and self.id == 0:
+			self.retrieveName()
+	
+	def __str__(self):
+		return self.name
+	
+	__repr__ = __str__
+
+
+	def getRISet(self):
+		assert self.cursor
+		if self.type == 'Publish':
+			query = '''
+					SELECT 
+						InbredSet.Name, InbredSet.Id
+					FROM 
+						InbredSet, PublishFreeze 
+					WHERE 
+						PublishFreeze.InbredSetId = InbredSet.Id AND 
+						PublishFreeze.Name = "%s"
+				''' % self.name
+		elif self.type == 'Geno':
+			query = '''
+					SELECT 
+						InbredSet.Name, InbredSet.Id
+					FROM 
+						InbredSet, GenoFreeze 
+					WHERE 
+						GenoFreeze.InbredSetId = InbredSet.Id AND 
+						GenoFreeze.Name = "%s"
+				''' % self.name
+		elif self.type == 'ProbeSet':
+			query = '''
+					SELECT 
+						InbredSet.Name, InbredSet.Id
+					FROM 
+						InbredSet, ProbeSetFreeze, ProbeFreeze 
+					WHERE 
+						ProbeFreeze.InbredSetId = InbredSet.Id AND 
+						ProbeFreeze.Id = ProbeSetFreeze.ProbeFreezeId AND 
+						ProbeSetFreeze.Name = "%s"
+				''' % self.name
+		else:
+			return ""
+		self.cursor.execute(query)
+		RISet, RIID = self.cursor.fetchone()
+		if RISet == 'BXD300':
+			RISet = "BXD"
+		self.riset = RISet
+		self.risetid = RIID
+		return RISet
+
+		
+	def retrieveName(self):
+		assert self.id == 0 and self.cursor
+		query = '''
+			SELECT 
+				Id, Name, FullName, ShortName 
+			FROM 
+				%sFreeze 
+			WHERE 
+				public > %d AND 
+				(Name = "%s" OR FullName = "%s" OR ShortName = "%s")
+		  '''% (self.type, webqtlConfig.PUBLICTHRESH, self.name, self.name, self.name)
+		try:
+			self.cursor.execute(query)
+			self.id,self.name,self.fullname,self.shortname=self.cursor.fetchone()
+		except:
+			raise KeyError, `self.name`+' doesn\'t exist.'
+
+	
+	def genHTML(self, Class='c0dd'):
+		return  HT.Href(text = HT.Span('%s Database' % self.fullname, Class= "fwb " + Class), 
+			url= webqtlConfig.INFOPAGEHREF % self.name,target="_blank")
+
+
+
+
+	
diff --git a/web/webqtl/base/webqtlFormData.py b/web/webqtl/base/webqtlFormData.py
new file mode 100755
index 00000000..84e41cae
--- /dev/null
+++ b/web/webqtl/base/webqtlFormData.py
@@ -0,0 +1,289 @@
+# Copyright (C) University of Tennessee Health Science Center, Memphis, TN.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Affero General Public License for more details.
+#
+# This program is available from Source Forge: at GeneNetwork Project
+# (sourceforge.net/projects/genenetwork/).
+#
+# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010)
+# at rwilliams@uthsc.edu and xzhou15@uthsc.edu
+#
+#
+#
+# This module is used by GeneNetwork project (www.genenetwork.org)
+#
+# Created by GeneNetwork Core Team 2010/08/10
+#
+# Last updated by GeneNetwork Core Team 2010/10/20
+
+from mod_python import Cookie
+import string
+import os
+
+import reaper
+
+import webqtlConfig
+import cookieData
+import sessionData
+from cgiData import cgiData
+from webqtlCaseData import webqtlCaseData
+from utility import webqtlUtil
+
+
+
+class webqtlFormData:
+	'Represents data from a WebQTL form page, needed to generate the next page'
+	attrs = ('formID','RISet','genotype','strainlist','allstrainlist',
+	'suggestive','significance','submitID','identification', 'enablevariance',
+	'nperm','nboot','email','incparentsf1','genotype_1','genotype_2','traitInfo')
+
+	#XZ: Attention! All attribute values must be picklable!
+
+	def __init__(self, req = None, mod_python_session=None, FieldStorage_formdata=None):
+
+		for item in self.attrs:
+			setattr(self,item, None)
+
+		try:
+			self.remote_ip = req.connection.remote_ip
+		except:
+			self.remote_ip = '1.2.3.4'
+
+		if req and req.headers_in.has_key('referer'):
+			self.refURL = req.headers_in['referer']
+		else:
+			self.refURL = None
+
+
+		self.cookies = cookieData.cookieData(Cookie.get_cookies(req)) #XZ: dictionary type. To hold values transfered from mod_python Cookie.
+
+		#XZ: dictionary type. To hold values transfered from mod_python Session object. We assume that it is always picklable.
+		self.input_session_data = sessionData.sessionData( mod_python_session )
+
+		#XZ: FieldStorage_formdata may contain item that can't be pickled. Must convert to picklable data.
+		self.formdata = cgiData( FieldStorage_formdata )
+
+		#get Form ID
+		self.formID = self.formdata.getfirst('FormID')
+
+		#get rest of the attributes
+		if self.formID:
+			for item in self.attrs:
+				value = self.formdata.getfirst(item)
+				if value != None:
+					setattr(self,item,string.strip(value))
+		
+		self.ppolar = ""
+		self.mpolar	= ""
+		if self.RISet:
+			try:
+				# NL, 07/27/2010. ParInfo has been moved from webqtlForm.py to webqtlUtil.py; 
+				f1, f12, self.mpolar, self.ppolar = webqtlUtil.ParInfo[self.RISet]
+			except:
+				f1 = f12 = self.mpolar = self.ppolar = None
+		
+		try:
+			self.nperm = int(self.nperm)
+			self.nboot = int(self.nboot)
+		except:
+			self.nperm = 2000 #XZ: Rob asked to change the default value to 2000
+			self.nboot = 2000 #XZ: Rob asked to change the default value to 2000
+
+		if self.allstrainlist:
+			self.allstrainlist = map(string.strip, string.split(self.allstrainlist))
+		#self.readGenotype()
+		#self.readData()
+		
+		if self.RISet == 'BXD300':
+			self.RISet = 'BXD'
+		else:
+			pass
+	
+	def __str__(self):
+		rstr = ''
+		for item in self.attrs:
+			if item != 'genotype':
+				rstr += '%s:%s\n' % (item,str(getattr(self,item)))
+		return rstr
+
+		
+	def readGenotype(self):
+		'read genotype from .geno file'
+		if self.RISet == 'BXD300':
+			self.RISet = 'BXD'
+		else:
+			pass
+		assert  self.RISet
+		#genotype_1 is Dataset Object without parents and f1
+		#genotype_2 is Dataset Object with parents and f1 (not for intercross)
+		self.genotype_1 = reaper.Dataset()
+		self.genotype_1.read(os.path.join(webqtlConfig.GENODIR, self.RISet + '.geno'))
+		try:
+			# NL, 07/27/2010. ParInfo has been moved from webqtlForm.py to webqtlUtil.py; 
+			_f1, _f12, _mat, _pat = webqtlUtil.ParInfo[self.RISet]
+		except:
+			_f1 = _f12 = _mat = _pat = None
+		
+		self.genotype_2 =self.genotype_1
+		if self.genotype_1.type == "riset" and _mat and _pat:
+			self.genotype_2 = self.genotype_1.add(Mat=_mat, Pat=_pat)	#, F1=_f1)
+			
+		#determine default genotype object
+		if self.incparentsf1 and self.genotype_1.type != "intercross":
+			self.genotype = self.genotype_2
+		else:
+			self.incparentsf1 = 0
+			self.genotype = self.genotype_1
+		self.strainlist = list(self.genotype.prgy)
+		self.f1list = self.parlist = []
+		if _f1 and _f12:
+			self.f1list = [_f1, _f12]
+		if _mat and _pat:
+			self.parlist = [_mat, _pat]
+		
+	def readData(self, strainlst=[], incf1=[]):
+		'read user input data or from trait data and analysis form'
+
+		if not self.genotype:
+			self.readGenotype()
+		if not strainlst:
+			if incf1:
+				strainlst = self.f1list + self.strainlist
+			else:
+				strainlst = self.strainlist	
+	
+	
+		traitfiledata = self.formdata.getfirst('traitfile')
+		traitpastedata = self.formdata.getfirst('traitpaste')
+		variancefiledata = self.formdata.getfirst('variancefile')
+		variancepastedata = self.formdata.getfirst('variancepaste')
+		Nfiledata = self.formdata.getfirst('Nfile')
+
+	
+		if traitfiledata:
+			tt = string.split(traitfiledata)
+			vals = map(webqtlUtil.StringAsFloat, tt)
+		elif traitpastedata:
+			tt = string.split(traitpastedata)
+			vals = map(webqtlUtil.StringAsFloat, tt)
+		else:
+			vals = map(self.FormDataAsFloat, strainlst)
+
+		if len(vals) < len(strainlst):
+				vals += [None]*(len(strainlst) - len(vals))
+		elif len(vals) > len(strainlst):
+				vals = vals[:len(strainlst)]
+		else:
+			pass
+		
+	
+		if variancefiledata:
+			tt = string.split(variancefiledata)
+			vars = map(webqtlUtil.StringAsFloat, tt)
+		elif variancepastedata:
+			tt = string.split(variancepastedata)
+			vars = map(webqtlUtil.StringAsFloat, tt)
+		else:
+			vars = map(self.FormVarianceAsFloat, strainlst)
+
+		if len(vars) < len(strainlst):
+				vars += [None]*(len(strainlst) - len(vars))
+		elif len(vars) > len(strainlst):
+				vars = vars[:len(strainlst)]
+		else:
+			pass
+		
+		if Nfiledata:
+			tt = string.split(Nfiledata)
+			nstrains = map(webqtlUtil.IntAsFloat, tt)
+			if len(nstrains) < len(strainlst):
+				nstrains += [None]*(len(strainlst) - len(nstrains))
+		else:
+			nstrains = map(self.FormNAsFloat, strainlst)
+		
+		##vals, vars, nstrains is obsolete
+		self.allTraitData = {}
+		for i, _strain in enumerate(strainlst):
+			if vals[i] != None:
+				self.allTraitData[_strain] = webqtlCaseData(vals[i], vars[i], nstrains[i])
+
+	
+
+	def informativeStrains(self, strainlst=[], incVars = 0):
+		'''if readData was called, use this to output the informative strains
+		   (strain with values)'''
+		if not strainlst:
+			strainlst = self.strainlist
+		strains = []
+		vals = []
+		vars = []
+		for _strain in strainlst:
+			if self.allTraitData.has_key(_strain):
+				_val, _var = self.allTraitData[_strain].val, self.allTraitData[_strain].var
+				if _val != None:
+					if incVars:
+						if _var != None:
+							strains.append(_strain)
+							vals.append(_val)
+							vars.append(_var)
+					else:
+						strains.append(_strain)
+						vals.append(_val)
+						vars.append(None)
+		return strains, vals, vars, len(strains)
+
+
+				
+	def FormDataAsFloat(self, key):
+		try:
+			return float(self.formdata.getfirst(key))
+		except:
+			return None
+
+	
+	def FormVarianceAsFloat(self, key):
+		try:
+			return float(self.formdata.getfirst('V' + key))
+		except:
+			return None
+	
+	def FormNAsFloat(self, key):
+		try:
+			return int(self.formdata.getfirst('N' + key))
+		except:
+			return None
+		
+	def Sample(self):
+		'Create some dummy data for testing'
+		self.RISet = 'BXD'
+		self.incparentsf1 = 'on'
+		#self.display = 9.2
+		#self.significance = 16.1
+		self.readGenotype()
+		self.identification = 'BXD : Coat color example by Lu Lu, et al'
+		#self.readGenotype()
+		#self.genotype.ReadMM('AXBXAforQTL')
+		#self.strainlist = map((lambda x, y='': '%s%s' % (y,x)), self.genotype.prgy)
+		#self.strainlist.sort()
+		self.allTraitData = {'BXD29': webqtlCaseData(3), 'BXD28': webqtlCaseData(2), 
+		'BXD25': webqtlCaseData(2), 'BXD24': webqtlCaseData(2), 'BXD27': webqtlCaseData(2), 
+		'BXD21': webqtlCaseData(1), 'BXD20': webqtlCaseData(4), 'BXD23': webqtlCaseData(4), 
+		'BXD22': webqtlCaseData(3), 'BXD14': webqtlCaseData(4), 'BXD15': webqtlCaseData(2), 
+		'BXD16': webqtlCaseData(3), 'BXD11': webqtlCaseData(4), 'BXD12': webqtlCaseData(3), 
+		'BXD13': webqtlCaseData(2), 'BXD18': webqtlCaseData(3), 'BXD19': webqtlCaseData(3), 
+		'BXD38': webqtlCaseData(3), 'BXD39': webqtlCaseData(3), 'BXD36': webqtlCaseData(2), 
+		'BXD34': webqtlCaseData(4), 'BXD35': webqtlCaseData(4), 'BXD32': webqtlCaseData(4), 
+		'BXD33': webqtlCaseData(3), 'BXD30': webqtlCaseData(1), 'BXD31': webqtlCaseData(4), 
+		'DBA/2J': webqtlCaseData(1), 'BXD8': webqtlCaseData(3), 'BXD9': webqtlCaseData(1), 
+		'BXD6': webqtlCaseData(3), 'BXD5': webqtlCaseData(3), 'BXD2': webqtlCaseData(4), 
+		'BXD1': webqtlCaseData(1), 'C57BL/6J': webqtlCaseData(4), 'B6D2F1': webqtlCaseData(4), 
+		'BXD42': webqtlCaseData(4), 'BXD40': webqtlCaseData(3)}
+
diff --git a/web/webqtl/base/webqtlTrait.py b/web/webqtl/base/webqtlTrait.py
new file mode 100644
index 00000000..f5051e45
--- /dev/null
+++ b/web/webqtl/base/webqtlTrait.py
@@ -0,0 +1,581 @@
+import string
+
+from htmlgen import HTMLgen2 as HT
+
+import webqtlConfig
+from webqtlCaseData import webqtlCaseData
+from webqtlDataset import webqtlDataset
+from dbFunction import webqtlDatabaseFunction
+from utility import webqtlUtil
+
+
+class webqtlTrait:
+	"""
+	Trait class defines a trait in webqtl, can be either Microarray, 	
+	Published phenotype, genotype, or user input trait
+	"""
+
+	def __init__(self, cursor = None, **kw):
+		self.cursor = cursor
+		self.db = None			# database object
+		self.name = ''			# Trait ID, ProbeSet ID, Published ID, etc.
+		self.cellid = ''
+		self.identification = 'un-named trait'
+		self.riset = ''
+		self.haveinfo = 0
+		self.sequence = ''		# Blat sequence, available for ProbeSet
+		self.data = {}
+		for name, value in kw.items():
+			if self.__dict__.has_key(name):
+				setattr(self, name, value)
+			elif name == 'fullname':
+				name2 = value.split("::")
+				if len(name2) == 2:
+					self.db, self.name = name2
+				elif len(name2) == 3:
+					self.db, self.name, self.cellid = name2
+				else:
+					raise KeyError, `value` + ' parameter format error.'
+			else:
+				raise KeyError, `name`+' not a valid parameter for this class.'
+		
+		if self.db and type(self.db) == type("1"):
+			assert self.cursor
+			self.db = webqtlDataset(self.db, self.cursor)
+
+		#if self.db == None, not from a database
+		if self.db:
+			if self.db.type == "Temp":
+				self.cursor.execute('''
+					SELECT 
+						InbredSet.Name 
+					FROM 
+						InbredSet, Temp 
+					WHERE 
+						Temp.InbredSetId = InbredSet.Id AND 
+						Temp.Name = "%s"
+				''' % self.name)
+				self.riset = self.cursor.fetchone()[0]
+			else:	
+				self.riset = self.db.getRISet()
+
+		#
+		# In ProbeSet, there are maybe several annotations match one sequence
+		# so we need use sequence(BlatSeq) as the identification, when we update
+		# one annotation, we update the others who match the sequence also.
+		#
+		# Hongqiang Li, 3/3/2008
+		#
+
+                #XZ, 05/08/2009: This block is not neccessary. We can add 'BlatSeq' into disfield.
+                # The variable self.sequence should be changed to self.BlatSeq
+                # It also should be changed in other places where it are used.
+
+		if self.db:
+			if self.db.type == 'ProbeSet':
+				query = '''
+					SELECT 
+						ProbeSet.BlatSeq
+					FROM
+						ProbeSet, ProbeSetFreeze, ProbeSetXRef
+					WHERE
+						ProbeSet.Id=ProbeSetXRef.ProbeSetId and
+						ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId and
+						ProbeSet.Name = "%s" and
+						ProbeSetFreeze.Name = "%s"
+				''' % (self.name, self.db.name)
+				self.cursor.execute(query)
+				self.sequence = self.cursor.fetchone()[0]
+
+	
+	def getName(self):
+		str = ""
+		if self.db and self.name:
+			str = "%s::%s" % (self.db, self.name)
+			if self.cellid:
+				str += "::" + self.cellid
+		else:
+			str = self.description
+		return str
+
+	# 
+	# when user enter a trait or GN generate a trait, user want show the name
+	# not the name that generated by GN randomly, the two follow function are
+	# used to give the real name and the database. displayName() will show the 
+	# database also, getGivenName() just show the name. 
+	# For other trait, displayName() as same as getName(), getGivenName() as 
+	# same as self.name
+	#
+	# Hongqiang 11/29/07
+	#
+	def getGivenName(self):
+		str = self.name
+		if self.db and self.name:
+			if self.db.type=='Temp':
+				self.cursor.execute('SELECT description FROM Temp WHERE Name=%s',self.name)
+				desc = self.cursor.fetchone()[0]
+				if desc.__contains__('PCA'):
+					desc = desc[desc.rindex(':')+1:].strip()
+				else:
+					desc = desc[:desc.index('entered')].strip()
+				str = desc
+		return str
+
+	def displayName(self):
+		str = ""
+		if self.db and self.name:
+			if self.db.type=='Temp':
+				desc = self.description
+				if desc.__contains__('PCA'):
+					desc = desc[desc.rindex(':')+1:].strip()
+				else:
+					desc = desc[:desc.index('entered')].strip()
+				str = "%s::%s" % (self.db, desc)
+			else:
+				str = "%s::%s" % (self.db, self.name)
+				if self.cellid:
+					str += "::" + self.cellid
+		else:
+			str = self.description
+	
+		return str
+
+	
+	#def __str__(self):
+	#	#return "%s %s" % (self.getName(), self.riset)
+	#	return self.getName()
+	__str__ = getName
+	__repr__ = __str__
+
+	def exportData(self, strainlist, type="val"):
+		"""
+			export data according to strainlist
+			mostly used in calculating correlation
+		"""
+		result = []
+		for strain in strainlist:
+			if self.data.has_key(strain):
+				if type=='val':
+					result.append(self.data[strain].val)
+				elif type=='var':
+					result.append(self.data[strain].var)
+				elif type=='N':
+					result.append(self.data[strain].N)
+				else:
+					raise KeyError, `type`+' type is incorrect.'
+			else:
+				result.append(None)
+		return result
+		
+	def exportInformative(self, incVar=0):
+		"""
+			export informative strain
+			mostly used in qtl regression
+		"""
+		strains = []
+		vals = []
+		vars = []
+		for strain, value in self.data.items():
+			if value.val != None:
+				if not incVar or value.var != None:
+					strains.append(strain)
+					vals.append(value.val)
+					vars.append(value.var)
+		return 	strains, vals, vars
+
+
+	#
+	# In ProbeSet, there are maybe several annotations match one sequence
+	# so we need use sequence(BlatSeq) as the identification, when we update
+	# one annotation, we update the others who match the sequence also.
+	#
+	# Hongqiang Li, 3/3/2008
+	#
+	def getSequence(self):
+		assert self.cursor
+		if self.db.type == 'ProbeSet':
+			query = '''
+					SELECT 
+						ProbeSet.BlatSeq
+					FROM
+						ProbeSet, ProbeSetFreeze, ProbeSetXRef
+					WHERE
+						ProbeSet.Id=ProbeSetXRef.ProbeSetId and
+						ProbeSetFreeze.Id = ProbeSetXRef.ProbSetFreezeId and
+						ProbeSet.Name = %s
+						ProbeSetFreeze.Name = %s
+				''' , (self.name, self.db.name)
+			self.cursor.execute(query)
+			results = self.fetchone()
+
+			return results[0]
+			
+			
+		
+	def retrieveData(self, strainlist=[]):
+		assert self.db and self.cursor
+
+		if self.db.type == 'Temp':
+			query = '''
+				SELECT 
+					Strain.Name, TempData.value, TempData.SE, TempData.NStrain, TempData.Id 
+				FROM 
+					TempData, Temp, Strain 
+				WHERE 
+					TempData.StrainId = Strain.Id AND 
+					TempData.Id = Temp.DataId AND 
+					Temp.name = '%s'
+				Order BY
+					Strain.Name
+				''' % self.name
+		#XZ, 03/02/2009: Xiaodong changed Data to PublishData, SE to PublishSE
+		elif self.db.type == 'Publish': 
+			query = '''
+				SELECT 
+					Strain.Name, PublishData.value, PublishSE.error, NStrain.count, PublishData.Id 
+				FROM 
+					(PublishData, Strain, PublishXRef, PublishFreeze)
+				left join PublishSE on 
+					(PublishSE.DataId = PublishData.Id AND PublishSE.StrainId = PublishData.StrainId)
+				left join NStrain on 
+					(NStrain.DataId = PublishData.Id AND 
+					NStrain.StrainId = PublishData.StrainId) 
+				WHERE 
+					PublishXRef.InbredSetId = PublishFreeze.InbredSetId AND 
+					PublishData.Id = PublishXRef.DataId AND PublishXRef.Id = %s AND 
+					PublishFreeze.Id = %d AND PublishData.StrainId = Strain.Id
+				Order BY
+					Strain.Name
+				''' % (self.name, self.db.id)
+
+                #XZ, 03/02/2009: Xiaodong changed Data to ProbeData, SE to ProbeSE
+		elif self.cellid:
+			#Probe Data
+			query = '''
+				SELECT 
+					Strain.Name, ProbeData.value, ProbeSE.error, ProbeData.Id 
+				FROM 
+					(ProbeData, ProbeFreeze, ProbeSetFreeze, ProbeXRef, 
+					Strain, Probe, ProbeSet)
+				left join ProbeSE on 
+					(ProbeSE.DataId = ProbeData.Id AND ProbeSE.StrainId = ProbeData.StrainId)
+				WHERE 
+					Probe.Name = '%s' AND ProbeSet.Name = '%s' AND 
+					Probe.ProbeSetId = ProbeSet.Id AND 
+					ProbeXRef.ProbeId = Probe.Id AND 
+					ProbeXRef.ProbeFreezeId = ProbeFreeze.Id AND 
+					ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id AND 
+					ProbeSetFreeze.Name = '%s' AND 
+					ProbeXRef.DataId = ProbeData.Id AND 
+					ProbeData.StrainId = Strain.Id
+				Order BY
+					Strain.Name
+				''' % (self.cellid, self.name, self.db.name)
+                #XZ, 03/02/2009: Xiaodong added this block for ProbeSetData and ProbeSetSE
+		elif self.db.type == 'ProbeSet':
+			#ProbeSet Data
+                        query = '''
+                                SELECT
+                                        Strain.Name, ProbeSetData.value, ProbeSetSE.error, ProbeSetData.Id
+                                FROM
+                                        (ProbeSetData, ProbeSetFreeze, Strain, ProbeSet, ProbeSetXRef)
+                                left join ProbeSetSE on
+                                        (ProbeSetSE.DataId = ProbeSetData.Id AND ProbeSetSE.StrainId = ProbeSetData.StrainId)
+                                WHERE
+                                        ProbeSet.Name = '%s' AND ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+                                        ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id AND
+                                        ProbeSetFreeze.Name = '%s' AND
+                                        ProbeSetXRef.DataId = ProbeSetData.Id AND
+                                        ProbeSetData.StrainId = Strain.Id
+                                Order BY
+                                        Strain.Name
+                                ''' % (self.name, self.db.name)
+                #XZ, 03/02/2009: Xiaodong changeded Data to GenoData, SE to GenoSE
+		else:
+			#Geno Data
+			#XZ: The SpeciesId is not necessary, but it's nice to keep it to speed up database search.
+			query = '''
+				SELECT 
+					Strain.Name, GenoData.value, GenoSE.error, GenoData.Id 
+				FROM 
+					(GenoData, GenoFreeze, Strain, Geno, GenoXRef)
+				left join GenoSE on
+					(GenoSE.DataId = GenoData.Id AND GenoSE.StrainId = GenoData.StrainId)
+				WHERE 
+					Geno.SpeciesId = %s AND Geno.Name = '%s' AND GenoXRef.GenoId = Geno.Id AND
+					GenoXRef.GenoFreezeId = GenoFreeze.Id AND 
+					GenoFreeze.Name = '%s' AND 
+					GenoXRef.DataId = GenoData.Id AND 
+					GenoData.StrainId = Strain.Id
+				Order BY
+					Strain.Name
+				''' % (webqtlDatabaseFunction.retrieveSpeciesId(self.cursor, self.db.riset), self.name, self.db.name)
+
+		
+		self.cursor.execute(query)
+		results = self.cursor.fetchall()
+		self.data.clear()
+		if results:
+			self.mysqlid = results[0][-1]
+			if strainlist:
+				for item in results:
+					if item[0] in strainlist:
+						val = item[1]
+						if val != None:
+							var = item[2]
+							ndata = None
+							if self.db.type in ('Publish', 'Temp'):
+								ndata = item[3]
+							self.data[item[0]] = webqtlCaseData(val, var, ndata)
+				#end for
+			else:	
+				for item in results:
+					val = item[1]
+					if val != None:
+						var = item[2]
+						ndata = None
+						if self.db.type in ('Publish', 'Temp'):
+							ndata = item[3]
+						self.data[item[0]] = webqtlCaseData(val, var, ndata)
+				#end for
+			#end if
+		else:
+			pass
+			
+	def keys(self):
+		return self.__dict__.keys()
+	
+	def has_key(self, key):
+		return self.__dict__.has_key(key)
+	
+	def items(self):
+		return self.__dict__.items()
+	
+	def retrieveInfo(self, QTL = None):
+		assert self.db and self.cursor
+		if self.db.type == 'Publish':
+			#self.db.DisField = ['Name','PubMed_ID','Phenotype','Abbreviation','Authors','Title',\
+			#	'Abstract', 'Journal','Volume','Pages','Month','Year','Sequence',\
+			#	'Units', 'comments']
+			query = '''
+				SELECT 
+					PublishXRef.Id, Publication.PubMed_ID, 
+					Phenotype.Pre_publication_description, Phenotype.Post_publication_description, Phenotype.Original_description, 
+					Phenotype.Pre_publication_abbreviation, Phenotype.Post_publication_abbreviation, 
+					Phenotype.Lab_code, Phenotype.Submitter, Phenotype.Owner, Phenotype.Authorized_Users,
+					Publication.Authors, Publication.Title, Publication.Abstract, 
+					Publication.Journal, Publication.Volume, Publication.Pages, 
+					Publication.Month, Publication.Year, PublishXRef.Sequence, 
+					Phenotype.Units, PublishXRef.comments 
+				FROM 
+					PublishXRef, Publication, Phenotype, PublishFreeze 
+				WHERE 
+					PublishXRef.Id = %s AND 
+					Phenotype.Id = PublishXRef.PhenotypeId AND 
+					Publication.Id = PublishXRef.PublicationId AND 
+					PublishXRef.InbredSetId = PublishFreeze.InbredSetId AND 
+					PublishFreeze.Id =%s
+				''' % (self.name, self.db.id)
+		#XZ, 05/08/2009: Xiaodong add this block to use ProbeSet.Id to find the probeset instead of just using ProbeSet.Name
+		#XZ, 05/08/2009: to avoid the problem of same probeset name from different platforms.
+		elif self.db.type == 'ProbeSet':
+			disfieldString = string.join(self.db.disfield,',ProbeSet.')
+			disfieldString = 'ProbeSet.' + disfieldString
+			query = """
+				SELECT %s 
+				FROM ProbeSet, ProbeSetFreeze, ProbeSetXRef
+				WHERE
+					ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id AND
+					ProbeSetXRef.ProbeSetId = ProbeSet.Id AND
+					ProbeSetFreeze.Name = '%s' AND
+					ProbeSet.Name = '%s'
+				""" % (disfieldString, self.db.name, self.name)
+		#XZ, 05/08/2009: We also should use Geno.Id to find marker instead of just using Geno.Name
+		# to avoid the problem of same marker name from different species.
+		elif self.db.type == 'Geno':
+			disfieldString = string.join(self.db.disfield,',Geno.')
+			disfieldString = 'Geno.' + disfieldString
+			query = """
+				SELECT %s 
+				FROM Geno, GenoFreeze, GenoXRef
+				WHERE
+					GenoXRef.GenoFreezeId = GenoFreeze.Id AND
+					GenoXRef.GenoId = Geno.Id AND
+					GenoFreeze.Name = '%s' AND
+					Geno.Name = '%s'
+				""" % (disfieldString, self.db.name, self.name)
+		else: #Temp type
+			query = 'SELECT %s FROM %s WHERE Name = "%s"' % \
+				(string.join(self.db.disfield,','), self.db.type, self.name)
+
+		
+		self.cursor.execute(query)
+		traitInfo = self.cursor.fetchone()
+		if traitInfo:
+			self.haveinfo = 1
+
+			#XZ: assign SQL query result to trait attributes.
+			for i, field in enumerate(self.db.disfield):
+				setattr(self, field, traitInfo[i])
+
+			if self.db.type == 'Publish':
+				self.confidential = 0
+				if self.pre_publication_description and not self.pubmed_id:
+					self.confidential = 1
+
+			self.homologeneid = None
+			if self.db.type == 'ProbeSet' and self.riset and self.geneid:
+				#XZ, 05/26/2010: From time to time, this query get error message because some geneid values in database are not number.
+				#XZ: So I have to test if geneid is number before execute the query.
+				#XZ: The geneid values in database should be cleaned up.
+				try:
+					junk = float(self.geneid)
+					geneidIsNumber = 1
+				except:
+					geneidIsNumber = 0
+
+				if geneidIsNumber:
+					query = """
+						SELECT
+							HomologeneId
+						FROM
+							Homologene, Species, InbredSet
+						WHERE
+							Homologene.GeneId =%s AND
+							InbredSet.Name = '%s' AND
+							InbredSet.SpeciesId = Species.Id AND
+							Species.TaxonomyId = Homologene.TaxonomyId
+						""" % (self.geneid, self.riset)
+					self.cursor.execute(query)
+					result = self.cursor.fetchone()
+				else:
+					result = None
+
+				if result:
+					self.homologeneid = result[0]
+
+			if QTL:
+				if self.db.type == 'ProbeSet' and not self.cellid:
+					query = '''
+						SELECT 
+							ProbeSetXRef.Locus, ProbeSetXRef.LRS, ProbeSetXRef.pValue, ProbeSetXRef.mean 
+						FROM 
+							ProbeSetXRef, ProbeSet
+						WHERE 
+							ProbeSetXRef.ProbeSetId = ProbeSet.Id AND 
+							ProbeSet.Name = "%s" AND
+							ProbeSetXRef.ProbeSetFreezeId =%s
+						''' % (self.name, self.db.id)
+					self.cursor.execute(query)
+					traitQTL = self.cursor.fetchone()
+					if traitQTL:
+						self.locus, self.lrs, self.pvalue, self.mean = traitQTL
+					else:
+						self.locus = self.lrs = self.pvalue = self.mean = ""
+				if self.db.type == 'Publish':
+					query = '''
+						SELECT
+							PublishXRef.Locus, PublishXRef.LRS
+						FROM
+							PublishXRef, PublishFreeze
+						WHERE
+							PublishXRef.Id = %s AND
+							PublishXRef.InbredSetId = PublishFreeze.InbredSetId AND
+							PublishFreeze.Id =%s
+						''' % (self.name, self.db.id)
+					self.cursor.execute(query)
+					traitQTL = self.cursor.fetchone()
+					if traitQTL:
+						self.locus, self.lrs = traitQTL
+					else:
+						self.locus = self.lrs = ""
+		else:
+			raise KeyError, `self.name`+' information is not found in the database.'
+	
+	def genHTML(self, formName = "", dispFromDatabase=0, privilege="guest", userName="Guest", authorized_users=""):
+		if not self.haveinfo:
+			self.retrieveInfo()
+		
+		if self.db.type == 'Publish':
+			PubMedLink = ""
+	 		if self.pubmed_id:
+	 			PubMedLink = HT.Href(text="PubMed %d : " % self.pubmed_id,
+	 			target = "_blank", url = webqtlConfig.PUBMEDLINK_URL % self.pubmed_id)
+			else:
+				PubMedLink = HT.Span("Unpublished : ", Class="fs15")
+			
+			if formName:
+				setDescription2 = HT.Href(url="javascript:showDatabase3('%s','%s','%s','')" % 
+				(formName, self.db.name, self.name), Class = "fs14")
+			else:
+				setDescription2 = HT.Href(url="javascript:showDatabase2('%s','%s','')" % 
+				(self.db.name,self.name), Class = "fs14")
+	
+			if self.confidential and not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=privilege, userName=userName, authorized_users=authorized_users):
+					setDescription2.append('RecordID/%s - %s' % (self.name, self.pre_publication_description))
+			else:
+				setDescription2.append('RecordID/%s - %s' % (self.name, self.post_publication_description))
+
+			#XZ 03/26/2011: Xiaodong comment out the following two lins as Rob asked. Need to check with Rob why in PublishXRef table, there are few row whose Sequence > 1.
+			#if self.sequence > 1:
+			#	setDescription2.append(' btach %d' % self.sequence)
+			if self.authors:
+				a1 = string.split(self.authors,',')[0]
+				while a1[0] == '"' or a1[0] == "'" :
+					a1 = a1[1:]
+				setDescription2.append(' by ')
+				setDescription2.append(HT.Italic('%s, and colleagues' % a1))
+			setDescription = HT.Span(PubMedLink, setDescription2)
+			
+		elif self.db.type == 'Temp':
+			setDescription = HT.Href(text="%s" % (self.description),url="javascript:showDatabase2\
+			('%s','%s','')" % (self.db.name,self.name), Class = "fs14")
+			setDescription = HT.Span(setDescription)
+			
+		elif self.db.type == 'Geno': # Genome DB only available for single search
+			if formName:
+				setDescription = HT.Href(text="Locus %s [Chr %s @ %s Mb]" % (self.name,self.chr,\
+			'%2.3f' % self.mb),url="javascript:showDatabase3('%s','%s','%s','')" % \
+			(formName, self.db.name, self.name), Class = "fs14")
+			else:
+				setDescription = HT.Href(text="Locus %s [Chr %s @ %s Mb]" % (self.name,self.chr,\
+			'%2.3f' % self.mb),url="javascript:showDatabase2('%s','%s','')" % \
+			(self.db.name,self.name), Class = "fs14")
+				
+			setDescription = HT.Span(setDescription)
+			
+		else:
+			if self.cellid:
+				if formName:	
+					setDescription = HT.Href(text="ProbeSet/%s/%s" % (self.name, self.cellid),url=\
+				"javascript:showDatabase3('%s','%s','%s','%s')" % (formName, self.db.name,self.name,self.cellid), \
+				Class = "fs14")
+				else:	
+					setDescription = HT.Href(text="ProbeSet/%s/%s" % (self.name,self.cellid),url=\
+				"javascript:showDatabase2('%s','%s','%s')" % (self.db.name,self.name,self.cellid), \
+				Class = "fs14")
+			else:
+				if formName:
+					setDescription = HT.Href(text="ProbeSet/%s" % self.name, url=\
+				"javascript:showDatabase3('%s','%s','%s','')" % (formName, self.db.name,self.name), \
+				Class = "fs14")
+				else:
+					setDescription = HT.Href(text="ProbeSet/%s" % self.name, url=\
+				"javascript:showDatabase2('%s','%s','')" % (self.db.name,self.name), \
+				Class = "fs14")
+			if self.symbol and self.chr and self.mb:
+				setDescription.append(' [')
+				setDescription.append(HT.Italic('%s' % self.symbol,Class="cdg fwb"))
+				setDescription.append(' on Chr %s @ %s Mb]' % (self.chr,self.mb))
+			if self.description:
+				setDescription.append(': %s' % self.description)
+			if self.probe_target_description:
+				setDescription.append('; %s' % self.probe_target_description)
+			setDescription = HT.Span(setDescription)
+			
+		if self.db.type != 'Temp' and dispFromDatabase:
+			setDescription.append( ' --- FROM : ')
+			setDescription.append(self.db.genHTML(Class='cori'))
+		return setDescription
+	
+