about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPjotr Prins2016-10-11 12:11:32 +0000
committerPjotr Prins2016-10-11 12:11:32 +0000
commitf942b4b6c0818010be9b9d245d9e02d2f466f29e (patch)
tree86650fa8fa7836e7d4c39907174dba98a39c59e9
parent420fd69ceda63871e9f6755112769c5615ed45f6 (diff)
parentccfe1f2e1afac31de9d1b2f34ad66ed77a517202 (diff)
downloadgenenetwork2-f942b4b6c0818010be9b9d245d9e02d2f466f29e.tar.gz
Merge branch 'testing' into chfi
-rwxr-xr-xbin/genenetwork214
-rwxr-xr-xbin/test-website12
-rw-r--r--etc/default_settings.py1
-rw-r--r--test/lib/mapping.rb1
-rw-r--r--wqflask/base/webqtlConfig.py22
-rw-r--r--wqflask/utility/tools.py13
-rw-r--r--wqflask/wqflask/marker_regression/marker_regression.py107
-rw-r--r--wqflask/wqflask/marker_regression/qtlreaper_mapping.py93
-rw-r--r--wqflask/wqflask/templates/base.html28
-rw-r--r--wqflask/wqflask/templates/ctl_results.html2
-rw-r--r--wqflask/wqflask/templates/ctl_setup.html2
-rw-r--r--wqflask/wqflask/templates/error.html4
-rwxr-xr-xwqflask/wqflask/templates/index_page_orig.html29
-rw-r--r--wqflask/wqflask/views.py8
14 files changed, 188 insertions, 148 deletions
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index d7d1c325..52d3155c 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -26,6 +26,10 @@ GN2_BASE_DIR=$(dirname $(dirname "$SCRIPT"))
 
 echo GN2_BASE_DIR=$GN2_BASE_DIR
 
+GIT_HASH=$(git rev-parse HEAD)
+GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
+export GN_VERSION=$(cat $GN2_BASE_DIR/VERSION)-$GIT_BRANCH-${GIT_HASH:0:9}
+echo GN_VERSION=$GN_VERSION
 
 # Handle settings parameter (can be .py or .json)
 settings=$1
@@ -79,13 +83,13 @@ fi
 # We may change this one:
 export PYTHONPATH=$GN2_BASE_DIR/wqflask:$PYTHONPATH
 
-# TEMPDIR defaults to /tmp if nothing else
-if [ -z $TEMPDIR ]; then
-    TEMPDIR="/tmp"
+# Our UNIX TMPDIR defaults to /tmp - change this on a shared server
+if [ -z $TMPDIR ]; then
+    TMPDIR="/tmp"
 fi
 
 set|grep $GN2_PROFILE
-set|grep TEMPDIR
+set|grep TMPDIR
 
 # Now handle command parameter -c
 if [ "$1" = '-c' ] ; then
@@ -98,7 +102,7 @@ if [ "$1" = '-c' ] ; then
 fi
 
 echo "Starting the redis server:"
-echo -n "dir $TEMPDIR
+echo -n "dir $TMPDIR
 dbfilename gn2.rdb
 " | redis-server - &
 
diff --git a/bin/test-website b/bin/test-website
index c9a72a5e..be223d94 100755
--- a/bin/test-website
+++ b/bin/test-website
@@ -52,12 +52,12 @@ opts = OptionParser.new do |o|
     options[:link_checker] = true
   end
 
-  o.on('--navigation-test', 'Check for navigation') do
-    options[:navigation_test] = true
+  o.on('--navigation', 'Check for navigation') do
+    options[:navigation] = true
   end
 
-  o.on('--mapping-test', 'Check for mapping') do
-    options[:mapping_test] = true
+  o.on('--mapping', 'Check for mapping') do
+    options[:mapping] = true
   end
 
   o.on('--skip-broken', 'Skip tests that are known to be broken') do
@@ -98,7 +98,7 @@ $: << File.join(libpath,'test/lib')
 
 require 'main_web_functionality'
 
-if options[:all] or options[:mapping_test]
+if options[:all] or options[:mapping]
   require 'mapping'
 end
 
@@ -106,6 +106,6 @@ if options[:all] or options[:link_checker]
   require 'link_checker'
 end
 
-if options[:all] or options[:navigation_test]
+if options[:all] or options[:navigation]
   require 'navigation'
 end
diff --git a/etc/default_settings.py b/etc/default_settings.py
index e03e2781..29b96861 100644
--- a/etc/default_settings.py
+++ b/etc/default_settings.py
@@ -22,6 +22,7 @@
 import os
 import sys
 
+GN_VERSION = open("../VERSION","r").read()
 SQL_URI = "mysql://gn2:mysql_password@localhost/db_webqtl_s"
 SQLALCHEMY_DATABASE_URI = 'mysql://gn2:mysql_password@localhost/db_webqtl_s'
 SQLALCHEMY_POOL_RECYCLE = 3600
diff --git a/test/lib/mapping.rb b/test/lib/mapping.rb
index d6a3cd7b..20e5bd40 100644
--- a/test/lib/mapping.rb
+++ b/test/lib/mapping.rb
@@ -36,6 +36,7 @@ describe MappingTest do
                          json,
                          ({'Content-Type' => 'application/x-www-form-urlencoded'}))
       form = page.forms_with("marker_regression")[0]
+      p form
       form.fields.select { |fld| fld.name == 'dataset' }.first.value.must_equal 'HC_M2_0606_P'
       form.fields.select { |fld| fld.name == 'value:BXD1' }.first.value.must_equal "15.034"
     end
diff --git a/wqflask/base/webqtlConfig.py b/wqflask/base/webqtlConfig.py
index 6bbabdec..e5f10edf 100644
--- a/wqflask/base/webqtlConfig.py
+++ b/wqflask/base/webqtlConfig.py
@@ -8,7 +8,7 @@
 #
 #########################################
 
-from utility.tools import valid_path, mk_dir, assert_dir, flat_files, TEMPDIR
+from utility.tools import valid_path, mk_dir, assert_dir, assert_writable_dir, flat_files, TEMPDIR
 
 #Debug Level
 #1 for debug, mod python will reload import each time
@@ -60,24 +60,36 @@ ENSEMBLETRANSCRIPT_URL="http://useast.ensembl.org/Mus_musculus/Lucene/Details?sp
 #   HTMLPATH is replaced by GENODIR
 #   IMGDIR is replaced by GENERATED_IMAGE_DIR
 
-# Temporary storage (note that this TMPDIR is not the same directory
-# as the UNIX TMPDIR)
+# Temporary storage (note that this TMPDIR can be set as an
+# environment variable - use utility.tools.TEMPDIR when you
+# want to reach this base dir
+assert_writable_dir(TEMPDIR)
+
 TMPDIR               = mk_dir(TEMPDIR+'/gn2/')
+assert_writable_dir(TMPDIR)
+
 CACHEDIR             = mk_dir(TMPDIR+'/cache/')
 # We can no longer write into the git tree:
 GENERATED_IMAGE_DIR  = mk_dir(TMPDIR+'/generated/')
 GENERATED_TEXT_DIR   = mk_dir(TMPDIR+'/generated_text/')
 
+# Make sure we have permissions to access these
+assert_writable_dir(CACHEDIR)
+assert_writable_dir(GENERATED_IMAGE_DIR)
+assert_writable_dir(GENERATED_TEXT_DIR)
+
 # Flat file directories
 GENODIR              = flat_files('genotype')+'/'
+assert_dir(GENODIR)
+
+# JSON genotypes are OBSOLETE
 JSON_GENODIR         = flat_files('genotype/json')+'/'
 if not valid_path(JSON_GENODIR):
     # fall back on old location (move the dir, FIXME)
     JSON_GENODIR = flat_files('json')
-assert_dir(GENODIR)
 
+# Are we using the following...?
 PORTADDR = "http://50.16.251.170"
-
 INFOPAGEHREF = '/dbdoc/%s.html'
 CGIDIR = '/webqtl/' #XZ: The variable name 'CGIDIR' should be changed to 'PYTHONDIR'
 SCRIPTFILE = 'main.py'
diff --git a/wqflask/utility/tools.py b/wqflask/utility/tools.py
index 23d6fb62..90144962 100644
--- a/wqflask/utility/tools.py
+++ b/wqflask/utility/tools.py
@@ -113,6 +113,16 @@ def assert_dir(dir):
         raise Exception("ERROR: can not find directory "+dir)
     return dir
 
+def assert_writable_dir(dir):
+    try:
+        fn = dir + "/test.txt"
+        fh = open( fn, 'w' )
+        fh.write("I am writing this text to the file\n")
+        fh.close()
+        os.remove(fn)
+    except IOError:
+        raise Exception('Unable to write test.txt to directory ' + dir )
+    return dir
 
 def mk_dir(dir):
     if not valid_path(dir):
@@ -187,6 +197,7 @@ def show_settings():
 
 
 # Cached values
+GN_VERSION         = get_setting('GN_VERSION')
 HOME               = get_setting('HOME')
 WEBSERVER_MODE     = get_setting('WEBSERVER_MODE')
 GN_SERVER_URL      = get_setting('GN_SERVER_URL')
@@ -205,7 +216,7 @@ GENENETWORK_FILES  = get_setting('GENENETWORK_FILES')
 PYLMM_COMMAND      = pylmm_command()
 GEMMA_COMMAND      = gemma_command()
 PLINK_COMMAND      = plink_command()
-TEMPDIR            = tempdir()
+TEMPDIR            = tempdir() # defaults to UNIX TMPDIR
 
 from six import string_types
 
diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py
index 37ee42a7..200f2207 100644
--- a/wqflask/wqflask/marker_regression/marker_regression.py
+++ b/wqflask/wqflask/marker_regression/marker_regression.py
@@ -35,7 +35,7 @@ from utility import helper_functions
 from utility import Plot, Bunch
 from utility import temp_data
 from utility.benchmark import Bench
-from wqflask.marker_regression import gemma_mapping, rqtl_mapping
+from wqflask.marker_regression import gemma_mapping, rqtl_mapping, qtlreaper_mapping
 
 from utility.tools import locate, locate_ignore_error, PYLMM_COMMAND, GEMMA_COMMAND, PLINK_COMMAND, TEMPDIR
 from utility.external import shell
@@ -170,7 +170,7 @@ class MarkerRegression(object):
             if start_vars['pair_scan'] == "true":
                 self.pair_scan = True
             if self.permCheck and self.num_perm > 0:
-                perm_output, self.suggestive, self.significant, results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan)
+                self.perm_output, self.suggestive, self.significant, results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan)
             else:
                 results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan)
         elif self.mapping_method == "reaper":
@@ -201,7 +201,16 @@ class MarkerRegression(object):
             self.control_marker = start_vars['control_marker']
             self.do_control = start_vars['do_control']
             logger.info("Running qtlreaper")
-            results = self.gen_reaper_results()
+            results, self.json_data, self.perm_output, self.suggestive, self.significant, self.bootstrap_results = qtlreaper_mapping.gen_reaper_results(self.this_trait,
+                                                                                                                                                        self.dataset,
+                                                                                                                                                        self.samples,
+                                                                                                                                                        self.json_data,
+                                                                                                                                                        self.num_perm,
+                                                                                                                                                        self.bootCheck,
+                                                                                                                                                        self.num_bootstrap,
+                                                                                                                                                        self.do_control,
+                                                                                                                                                        self.control_marker,
+                                                                                                                                                        self.manhattan_plot)
         elif self.mapping_method == "plink":
             results = self.run_plink()
         elif self.mapping_method == "pylmm":
@@ -468,98 +477,6 @@ class MarkerRegression(object):
 
         return sample_list
 
-    def gen_reaper_results(self):
-        genotype = self.dataset.group.read_genotype_file()
-
-        if self.manhattan_plot != True:
-            genotype = genotype.addinterval()
-
-        samples, values, variances, sample_aliases = self.this_trait.export_informative()
-
-        trimmed_samples = []
-        trimmed_values = []
-        for i in range(0, len(samples)):
-            #if self.this_trait.data[samples[i]].name2 in self.dataset.group.samplelist:
-            if self.this_trait.data[samples[i]].name in self.samples:
-                trimmed_samples.append(samples[i])
-                trimmed_values.append(values[i])
-
-        if self.num_perm < 100:
-            self.suggestive = 0
-            self.significant = 0
-        else:
-            self.perm_output = genotype.permutation(strains = trimmed_samples, trait = trimmed_values, nperm=self.num_perm)
-            self.suggestive = self.perm_output[int(self.num_perm*0.37-1)]
-            self.significant = self.perm_output[int(self.num_perm*0.95-1)]
-            self.highly_significant = self.perm_output[int(self.num_perm*0.99-1)]
-
-        self.json_data['suggestive'] = self.suggestive
-        self.json_data['significant'] = self.significant
-
-        if self.control_marker != "" and self.do_control == "true":
-            reaper_results = genotype.regression(strains = trimmed_samples,
-                                                 trait = trimmed_values,
-                                                 control = str(self.control_marker))
-            if self.bootCheck:
-                control_geno = []
-                control_geno2 = []
-                _FIND = 0
-                for _chr in genotype:
-                    for _locus in _chr:
-                        if _locus.name == self.control_marker:
-                            control_geno2 = _locus.genotype
-                            _FIND = 1
-                            break
-                    if _FIND:
-                        break
-                if control_geno2:
-                    _prgy = list(genotype.prgy)
-                    for _strain in trimmed_samples:
-                        _idx = _prgy.index(_strain)
-                        control_geno.append(control_geno2[_idx])
-
-                self.bootstrap_results = genotype.bootstrap(strains = trimmed_samples,
-                                                            trait = trimmed_values,
-                                                            control = control_geno,
-                                                            nboot = self.num_bootstrap)
-        else:
-            reaper_results = genotype.regression(strains = trimmed_samples,
-                                                 trait = trimmed_values)
-
-            if self.bootCheck:
-                self.bootstrap_results = genotype.bootstrap(strains = trimmed_samples,
-                                                            trait = trimmed_values,
-                                                            nboot = self.num_bootstrap)
-
-        self.json_data['chr'] = []
-        self.json_data['pos'] = []
-        self.json_data['lod.hk'] = []
-        self.json_data['markernames'] = []
-        #if self.additive:
-        #    self.json_data['additive'] = []
-
-        #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary
-        qtl_results = []
-        for qtl in reaper_results:
-            reaper_locus = qtl.locus
-            #ZS: Convert chr to int
-            converted_chr = reaper_locus.chr
-            if reaper_locus.chr != "X" and reaper_locus.chr != "X/Y":
-                converted_chr = int(reaper_locus.chr)
-            self.json_data['chr'].append(converted_chr)
-            self.json_data['pos'].append(reaper_locus.Mb)
-            self.json_data['lod.hk'].append(qtl.lrs)
-            self.json_data['markernames'].append(reaper_locus.name)
-            #if self.additive:
-            #    self.json_data['additive'].append(qtl.additive)
-            locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb}
-            qtl = {"lrs_value": qtl.lrs, "chr":converted_chr, "Mb":reaper_locus.Mb,
-                   "cM":reaper_locus.cM, "name":reaper_locus.name, "additive":qtl.additive, "dominance":qtl.dominance}
-            qtl_results.append(qtl)
-
-        return qtl_results
-
-
     def parse_plink_output(self, output_filename):
         plink_results={}
 
diff --git a/wqflask/wqflask/marker_regression/qtlreaper_mapping.py b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
new file mode 100644
index 00000000..b072584c
--- /dev/null
+++ b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
@@ -0,0 +1,93 @@
+def gen_reaper_results(this_trait, dataset, samples_before, json_data, num_perm, bootCheck, num_bootstrap, do_control, control_marker, manhattan_plot):
+    genotype = dataset.group.read_genotype_file()
+
+    if manhattan_plot != True:
+        genotype = genotype.addinterval()
+
+    samples, values, variances, sample_aliases = this_trait.export_informative()
+
+    trimmed_samples = []
+    trimmed_values = []
+    for i in range(0, len(samples)):
+        if this_trait.data[samples[i]].name in samples_before:
+            trimmed_samples.append(samples[i])
+            trimmed_values.append(values[i])
+
+    perm_output = []
+    bootstrap_results = []
+
+    if num_perm < 100:
+        suggestive = 0
+        significant = 0
+    else:
+        perm_output = genotype.permutation(strains = trimmed_samples, trait = trimmed_values, nperm=num_perm)
+        suggestive = perm_output[int(num_perm*0.37-1)]
+        significant = perm_output[int(num_perm*0.95-1)]
+        highly_significant = perm_output[int(num_perm*0.99-1)]
+
+    json_data['suggestive'] = suggestive
+    json_data['significant'] = significant
+
+    if control_marker != "" and do_control == "true":
+        reaper_results = genotype.regression(strains = trimmed_samples,
+                                             trait = trimmed_values,
+                                             control = str(control_marker))
+        if bootCheck:
+            control_geno = []
+            control_geno2 = []
+            _FIND = 0
+            for _chr in genotype:
+                for _locus in _chr:
+                    if _locus.name == control_marker:
+                        control_geno2 = _locus.genotype
+                        _FIND = 1
+                        break
+                if _FIND:
+                    break
+            if control_geno2:
+                _prgy = list(genotype.prgy)
+                for _strain in trimmed_samples:
+                    _idx = _prgy.index(_strain)
+                    control_geno.append(control_geno2[_idx])
+
+            bootstrap_results = genotype.bootstrap(strains = trimmed_samples,
+                                                        trait = trimmed_values,
+                                                        control = control_geno,
+                                                        nboot = num_bootstrap)
+    else:
+        reaper_results = genotype.regression(strains = trimmed_samples,
+                                             trait = trimmed_values)
+
+        if bootCheck:
+            bootstrap_results = genotype.bootstrap(strains = trimmed_samples,
+                                                        trait = trimmed_values,
+                                                        nboot = num_bootstrap)
+
+    json_data['chr'] = []
+    json_data['pos'] = []
+    json_data['lod.hk'] = []
+    json_data['markernames'] = []
+    #if self.additive:
+    #    self.json_data['additive'] = []
+
+    #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary
+    qtl_results = []
+    for qtl in reaper_results:
+        reaper_locus = qtl.locus
+        #ZS: Convert chr to int
+        converted_chr = reaper_locus.chr
+        if reaper_locus.chr != "X" and reaper_locus.chr != "X/Y":
+            converted_chr = int(reaper_locus.chr)
+        json_data['chr'].append(converted_chr)
+        json_data['pos'].append(reaper_locus.Mb)
+        json_data['lod.hk'].append(qtl.lrs)
+        json_data['markernames'].append(reaper_locus.name)
+        #if self.additive:
+        #    self.json_data['additive'].append(qtl.additive)
+        locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb}
+        qtl = {"lrs_value": qtl.lrs, "chr":converted_chr, "Mb":reaper_locus.Mb,
+               "cM":reaper_locus.cM, "name":reaper_locus.name, "additive":qtl.additive, "dominance":qtl.dominance}
+        qtl_results.append(qtl)
+
+
+    return qtl_results, json_data, perm_output, suggestive, significant, bootstrap_results
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index c3826a90..210c5708 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -95,29 +95,27 @@
         </form>
     </div>
 
-    {% block content %}{% endblock %}
+    {% block content %}
+    {% endblock %}
 
-            <!-- Footer
-    ================================================== -->
     <footer class="footer">
       <div class="container">
-
-        <p>
-
-GeneNetwork is a framework for web based genetics
- launched in 1994 as
+        <p>GeneNetwork is a framework for web based genetics
+          launched in 1994 as
         <a href="http://www.ncbi.nlm.nih.gov/pubmed?term=8043953">
             The Portable Dictionary of the Mouse Genome</a> (previously <a href="https://www.ncbi.nlm.nih.gov/pubmed/15043217">WebQTL</a>).
         </p>
-        <p>Operated by
+        <p>
+          Operated by
             <a href="mailto:rwilliams@uthsc.edu">Rob Williams</a>,
             <a href="mailto:lyan6@uthsc.edu">Lei Yan</a>,
-            <a href="mailto:zachary.a.sloan@gmail.com">Zachary Sloan</a>, and
-            <a href="mailto:acenteno@uthsc.edu">Arthur Centeno</a>.
+            <a href="mailto:zachary.a.sloan@gmail.com">Zachary Sloan</a>,
+            <a href="mailto:acenteno@uthsc.edu">Arthur Centeno</a> and
+            <a href="http://thebird.nl/">Pjotr Prins</a>.
         </p>
         <p>Published in
           <a href="http://joss.theoj.org/papers/10.21105/joss.00025"><img src="https://camo.githubusercontent.com/846b750f582ae8f1d0b4f7e8fee78bed705c88ba/687474703a2f2f6a6f73732e7468656f6a2e6f72672f7061706572732f31302e32313130352f6a6f73732e30303032352f7374617475732e737667" alt="JOSS" data-canonical-src="http://joss.theoj.org/papers/10.21105/joss.00025/status.svg" style="max-width:100%;"></a>
-          </p>
+        </p>
           <br />
         <p>GeneNetwork is supported by:</p>
         <UL>
@@ -143,8 +141,12 @@ GeneNetwork is a framework for web based genetics
             </li>
         </UL>
         <!--</p>-->
+        <p>
+          Development and source code on <a href="https://github.com/genenetwork/">github</a> with <a href="https://github.com/genenetwork/genenetwork2/issues">issue tracker</a> and <a href="https://github.com/genenetwork/genenetwork2/blob/master/README.md">documentation</a>. Join the <a href="http://listserv.uthsc.edu/mailman/listinfo/genenetwork-dev">mailing list</a> and find us on <a href="https://webchat.freenode.net/">IRC</a> (#genenetwork channel).
+        {% if version: %}
+        <p><small>GeneNetwork v{{ version }}</small></p>
+        {% endif %}
 
-        Join the <a href="http://listserv.uthsc.edu/mailman/listinfo/genenetwork-dev">mailing list</a>
       </div>
     </footer>
 
diff --git a/wqflask/wqflask/templates/ctl_results.html b/wqflask/wqflask/templates/ctl_results.html
index a5cb1c08..00ccecb6 100644
--- a/wqflask/wqflask/templates/ctl_results.html
+++ b/wqflask/wqflask/templates/ctl_results.html
@@ -4,7 +4,7 @@
 {% block content %} <!-- Start of body -->
 <div class="container">
   <h1>CTL Results</h1>
-  {{(request.form['trait_list'].split(',')|length -1)}} phenotypes as input<br>
+  {{(request.form['trait_list'].split(',')|length)}} phenotypes as input<br>
   <h3>Network Figure</h3>
   <a href="/tmp/{{ results['imgurl1'] }}">
       <img alt="Embedded Image" src="data:image/png;base64,
diff --git a/wqflask/wqflask/templates/ctl_setup.html b/wqflask/wqflask/templates/ctl_setup.html
index 51553322..a05379a8 100644
--- a/wqflask/wqflask/templates/ctl_setup.html
+++ b/wqflask/wqflask/templates/ctl_setup.html
@@ -12,7 +12,7 @@
   </div>
   {% else %}
   <h1>CTL analysis parameters</h1>
-  {{(request.form['trait_list'].split(',')|length -1)}} traits as input
+  {{(request.form['trait_list'].split(',')|length)}} traits as input
 
   <form action="/ctl_results" method="post" class="form-horizontal">
     <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}">
diff --git a/wqflask/wqflask/templates/error.html b/wqflask/wqflask/templates/error.html
index 7ab2bf2f..c707a4fc 100644
--- a/wqflask/wqflask/templates/error.html
+++ b/wqflask/wqflask/templates/error.html
@@ -35,7 +35,7 @@
   </p>
 
   <pre>
-    {{ stack[0] }}
+    GeneNetwork v{{ version }} {{ stack[0] }}
     {{ message }} (error)
     {{ stack[-3] }}
     {{ stack[-2] }}
@@ -50,7 +50,7 @@
   <a href="#Stack" class="btn btn-default" data-toggle="collapse">Toggle full stack trace</a>
   <div id="Stack" class="collapse">
     <pre>
-      {% for line in stack %} {{ line }}
+      GeneNetwork v{{ version }} {% for line in stack %} {{ line }}
       {% endfor %}
     </pre>
   </div>
diff --git a/wqflask/wqflask/templates/index_page_orig.html b/wqflask/wqflask/templates/index_page_orig.html
index 73d3e718..9ac267f1 100755
--- a/wqflask/wqflask/templates/index_page_orig.html
+++ b/wqflask/wqflask/templates/index_page_orig.html
@@ -197,29 +197,28 @@
 
                 <section id="websites">
                     <div class="page-header">
-                        <h1>Affiliates and mirrors</h1>
+                        <h2>Links</h2>
                     </div>
-                    <h3>Websites affiliated with GeneNetwork</h3>
+                    <h3>GeneNetwork v2:</h3>
+                      <ul>
+                        <li><a href="http://gn2.genenetwork.org/">Main website</a> at UTHSC</li>
+                        <li><a href="http://test-gn2.genenetwork.org/">Testing website</a> at UTHSC</li>
+                      </ul>
+                    <h3>GeneNetwork v1:</h3>
                     <ul>
+                        <li><a href="http://www.genenetwork.org/">Main website</a> at UTHSC</li>
+                        <li><a href="http://genenetwork.helmholtz-hzi.de/">Website</a> at the HZI (Germany)</li>
+                        <li><a href="http://ec2.genenetwork.org/">Amazon
+                            Cloud (EC2)</a></li>
+                        </ul>
+                      <h3>Affiliates</h3>
+                      <ul>
                         <li><a href="http://ucscbrowser.genenetwork.org/">Genome
                         browser</a> at UTHSC</li>
 
                         <li><a href="http://galaxy.genenetwork.org/">Galaxy</a> at
                         UTHSC</li>
 
-                        <li>GeneNetwork 1 at <a href="http://ec2.genenetwork.org/">Amazon
-                        Cloud (EC2)</a></li>
-
-                        <li>GeneNetwork 1 Source Code at <a href="http://sourceforge.net/projects/genenetwork/">SourceForge</a></li>
-
-                        <li>GeneNetwork 2 Source Code at <a href="https://github.com/genenetwork/genenetwork2">GitHub</a></li>
-                    </ul>
-                    <h3>GN1 Mirror and development sites</h3>
-
-                    <ul>
-                        <li><a href="http://www.genenetwork.org/">Main GN1 site at UTHSC</a> (main site)</li>
-                        <li><a href="http://genenetwork.helmholtz-hzi.de/">Germany at the HZI</a></li>
-                        <li><a href="http://gn2.genenetwork.org/">Memphis at the U of M</a></li>
                     </ul>
                 </section>
 
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 8ea3f48f..23c3757c 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -53,7 +53,7 @@ from wqflask.ctl import ctl_analysis
 
 from utility import webqtlUtil
 from utility import temp_data
-from utility.tools import SQL_URI,TEMPDIR,USE_REDIS,USE_GN_SERVER,GN_SERVER_URL
+from utility.tools import SQL_URI,TEMPDIR,USE_REDIS,USE_GN_SERVER,GN_SERVER_URL,GN_VERSION
 
 from base import webqtlFormData
 from base.webqtlConfig import GENERATED_IMAGE_DIR, GENERATED_TEXT_DIR
@@ -110,7 +110,7 @@ def handle_bad_request(e):
         list = [fn for fn in os.listdir("./wqflask/static/gif/error") if fn.endswith(".gif") ]
         animation = random.choice(list)
 
-    resp = make_response(render_template("error.html",message=err_msg,stack=formatted_lines,error_image=animation))
+    resp = make_response(render_template("error.html",message=err_msg,stack=formatted_lines,error_image=animation,version=GN_VERSION))
 
     # logger.error("Set cookie %s with %s" % (err_msg, animation))
     resp.set_cookie(err_msg[:32],animation)
@@ -126,10 +126,10 @@ def index_page():
             g.cookie_session.import_traits_to_user()
     if USE_GN_SERVER:
         # The menu is generated using GN_SERVER
-        return render_template("index_page.html", gn_server_url = GN_SERVER_URL)
+        return render_template("index_page.html", gn_server_url = GN_SERVER_URL, version=GN_VERSION)
     else:
         # Old style static menu (OBSOLETE)
-        return render_template("index_page_orig.html")
+        return render_template("index_page_orig.html", version=GN_VERSION)
 
 
 @app.route("/tmp/<img_path>")