aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPjotr Prins2016-10-06 14:27:17 +0000
committerPjotr Prins2016-10-06 14:27:17 +0000
commit94f7e2494f5e48b12ae10c0bf46ebc2367b0eecc (patch)
treea3e3989d0817e63cd6df0ef7d93b50e659c8288f
parentbd35fd6430e5b8b88fd3a7b8afa933d2b0f20b4e (diff)
parent416363b3f8940d145d8aec076865b167e78705d9 (diff)
downloadgenenetwork2-94f7e2494f5e48b12ae10c0bf46ebc2367b0eecc.tar.gz
Merge branch 'master' of github.com:genenetwork/genenetwork2 into mechanize
-rw-r--r--VERSION2
-rwxr-xr-xbin/genenetwork282
-rwxr-xr-xbin/test-website4
-rw-r--r--test/data/input/mapping/1435395_s_at_HC_M2_0606_P.json383
-rw-r--r--test/lib/mapping.rb6
-rw-r--r--wqflask/base/data_set.py2
-rw-r--r--wqflask/base/trait.py2
-rw-r--r--wqflask/base/webqtlCaseData.py2
-rw-r--r--wqflask/maintenance/__init__.py0
-rw-r--r--wqflask/runserver.py19
-rw-r--r--wqflask/utility/helper_functions.py12
-rw-r--r--wqflask/utility/logger.py6
-rw-r--r--wqflask/utility/tools.py40
-rw-r--r--wqflask/wqflask/__init__.py6
-rw-r--r--wqflask/wqflask/collect.py17
-rw-r--r--wqflask/wqflask/marker_regression/marker_regression.py261
-rw-r--r--wqflask/wqflask/marker_regression/rqtl_mapping.py193
-rw-r--r--wqflask/wqflask/static/gif/error/Wild-Type-Mouse.gifbin0 -> 37328 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-aliens-29.gifbin0 -> 14088 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-angels-04.gifbin0 -> 12155 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-cats-016.gifbin0 -> 10388 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-cats-031.gifbin0 -> 6937 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-03.gifbin0 -> 14902 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-16.gifbin0 -> 7307 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-13.gifbin0 -> 7616 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-28.gifbin0 -> 7566 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-32.gifbin0 -> 2970 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-42.gifbin0 -> 9391 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-60.gifbin0 -> 35873 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-64.gifbin0 -> 20728 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-65.gifbin0 -> 26358 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-72.gifbin0 -> 16361 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-74.gifbin0 -> 21087 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-computers-75.gifbin0 -> 98317 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-construction-sites-038.gifbin0 -> 949 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-dogs-04.gifbin0 -> 9450 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-dogs-14.gifbin0 -> 2532 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-dogs-18.gifbin0 -> 3596 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-dogs-47.gifbin0 -> 13920 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-dogs-50.gifbin0 -> 7297 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-lava-lamps-01.gifbin0 -> 27122 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-mice-02.gifbin0 -> 73345 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-mice-09.gifbin0 -> 27822 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-mice-24.gifbin0 -> 10566 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-smileys-063.gifbin0 -> 2230 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-smileys-068.gifbin0 -> 11751 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-smileys-134.gifbin0 -> 21431 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-smileys-211.gifbin0 -> 11209 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-smileys-234.gifbin0 -> 8677 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-001.gifbin0 -> 6897 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-002.gifbin0 -> 14098 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-005.gifbin0 -> 13264 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-012.gifbin0 -> 12141 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-056.gifbin0 -> 5946 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-059.gifbin0 -> 16427 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-060.gifbin0 -> 14434 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/animated-gifs-stickmen-069.gifbin0 -> 7668 bytes
-rw-r--r--wqflask/wqflask/templates/collections/add.html2
-rw-r--r--wqflask/wqflask/templates/ctl_setup.html111
-rw-r--r--wqflask/wqflask/templates/error.html61
-rw-r--r--wqflask/wqflask/templates/show_trait_mapping_tools.html28
-rw-r--r--wqflask/wqflask/templates/wgcna_setup.html85
-rw-r--r--wqflask/wqflask/views.py34
63 files changed, 811 insertions, 547 deletions
diff --git a/VERSION b/VERSION
index cd5ac039..144b089a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0
+2.10-pre1
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index d926d6a1..889401fd 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -1,53 +1,93 @@
#! /bin/bash
#
-# This will run the GN2 server (with default settings if none supplied). Pass in
-# your own settings file, e.g.
+# This will run the GN2 server (with default settings if none
+# supplied). Pass in your own settings file, e.g.
#
# ./bin/genenetwork2 ~/my_settings.py
#
+# But better is to retain the defaults and override them with
+# JSON file (see the deploy docs).
+#
+# ./bin/genenetwork2 ~/my_overrides.json
+#
# To run a maintenance script with settings (instead of the webserver) add that with
# a -c switch, e.g.
#
-# ./bin/genenetwork2 ~/my_settings.py -c ./wqflask/maintenance/gen_select_dataset.py
+# ./bin/genenetwork2 ~/my_overrides.json -c ./wqflask/maintenance/gen_select_dataset.py
#
# Environment settings can be used to preconfigure as well as a
# settings.py file.
+#
+# GN2_BASE_PATH is base directory of wqflask source code
+#
SCRIPT=$(readlink -f "$0")
-GN2_BASE_PATH=$(dirname $(dirname "$SCRIPT"))
+GN2_BASE_DIR=$(dirname $(dirname "$SCRIPT"))
-GN2_GUIX_PATH=$GN2_BASE_PATH/lib/python2.7/site-packages/genenetwork2-2.0-py2.7.egg
-if [ -d $GN2_GUIX_PATH ]; then
- echo GN2 is running from GUIX
- GN2_BASE_PATH=$GN2_GUIX_PATH
-fi
-echo $GN2_BASE_PATH
+echo GN2_BASE_DIR=$GN2_BASE_DIR
-# Handle settings parameter
+
+# Handle settings parameter (can be .py or .json)
settings=$1
-if [ -z $settings ]; then
- # get default
- settings=$GN2_BASE_PATH/etc/default_settings.py
+ext="${settings##*.}"
+if [ -z "$settings" -o "$ext" = "json" -o "$ext" = "JSON" ]; then
+ overrides=$settings
+ settings=$GN2_BASE_DIR/etc/default_settings.py
else
shift
fi
if [ ! -e $settings ]; then
- echo "ERROR: can not locate settings file - pass it in the command line"
- exit 1
+ GUIX_ETC=$GN2_BASE_DIR/lib/python2.7/site-packages/genenetwork2-2.0-py2.7.egg
+ if [ -d $GUIX_ETC ]; then
+ echo INFO: GN2 is actually running from GNU Guix
+ else
+ echo "ERROR: can not locate settings file - pass it in the command line"
+ exit 1
+ fi
+fi
+export WQFLASK_SETTINGS=$settings # Python
+export WQFLASK_OVERRIDES=$overrides # JSON
+
+echo WQFLASK_SETTINGS=$settings
+echo WQFLASK_OVERRIDES=$overrides
+
+# ---- Checks and balances
+if [ -z $GUIX_ETC ]; then
+ if [ -z $GN2_PROFILE ] ; then
+ echo "WARNING: GN2_PROFILE has not been set - I hope you know what you are doing"
+ else
+ export PYTHONPATH=$GN2_PROFILE/lib/python2.7/site-packages
+ export R_LIBS_SITE=$GN2_PROFILE/site-library
+ export GUIX_GTK3_PATH="$GN2_PROFILE/lib/gtk-3.0"
+ export GI_TYPELIB_PATH="$GN2_PROFILE/lib/girepository-1.0"
+ export XDG_DATA_DIRS="$GN2_PROFILE/share"
+ export GIO_EXTRA_MODULES="$GN2_PROFILE/lib/gio/modules"
+ fi
+ if [ -z $PYTHONPATH ] ; then
+ echo "WARNING PYTHONPATH has not been set"
+ fi
+ if [ ! -d $R_LIBS_SITE ] ; then
+ echo "ERROR: R_LIBS_SITE has not been set correctly (we only allow one path)"
+ echo "Paste in the output of, for example,"
+ echo "guix package -p /usr/local/guix-profiles/gn2-staging --search-paths"
+ exit 1
+ fi
fi
-export WQFLASK_SETTINGS=$settings
# We may change this one:
-export PYTHONPATH=$GN2_BASE_PATH/wqflask:$PYTHONPATH
+export PYTHONPATH=$GN2_BASE_DIR/wqflask:$PYTHONPATH
# TEMPDIR defaults to /tmp if nothing else
if [ -z $TEMPDIR ]; then
TEMPDIR="/tmp"
fi
+set|grep $GN2_PROFILE
+set|grep TEMPDIR
+
# Now handle command parameter -c
-if [ $1 = '-c' ] ; then
- cd $GN2_BASE_PATH/wqflask
+if [ "$1" = '-c' ] ; then
+ cd $GN2_BASE_DIR/wqflask
cmd=${2#wqflask/}
echo PYTHONPATH=$PYTHONPATH
echo RUNNING COMMAND $cmd
@@ -61,6 +101,6 @@ dbfilename gn2.rdb
" | redis-server - &
# Start the flask server running GN2
-cd $GN2_BASE_PATH/wqflask
+cd $GN2_BASE_DIR/wqflask
echo "Starting with $settings"
/usr/bin/env python runserver.py
diff --git a/bin/test-website b/bin/test-website
index b693bd60..c9a72a5e 100755
--- a/bin/test-website
+++ b/bin/test-website
@@ -15,6 +15,10 @@ If you are using the small deployment database you can use
./bin/test-website --skip -n
+To run all tests
+
+ ./bin/test-website --all
+
To run individual tests on localhost you can do
ruby -Itest -Itest/lib test/lib/mapping.rb --name="/Mapping/"
diff --git a/test/data/input/mapping/1435395_s_at_HC_M2_0606_P.json b/test/data/input/mapping/1435395_s_at_HC_M2_0606_P.json
index 15428553..195c16e4 100644
--- a/test/data/input/mapping/1435395_s_at_HC_M2_0606_P.json
+++ b/test/data/input/mapping/1435395_s_at_HC_M2_0606_P.json
@@ -1,142 +1,245 @@
{
"temp_uuid" : "unknown",
-"maf" : "0.01",
-"control_marker" : "mCV24506226",
-"dataset" : "HC_M2_0606_P",
- "do_control" : "false",
- "maf" : "0.01",
- "manhattan_plot" : "False",
- "mapmethod_rqtl_geno" : "em",
- "mapmodel_rqtl_geno" : "normal",
- "method" : "rqtl_geno",
- "num_bootstrap" : "2000",
- "num_perm" : "",
- "pair_scan" : "false",
- "suggestive" : "0",
- "trait_id" : "1433387_at",
- "value:129S1/SvImJ" : "6.920",
- "value:A/J" : "7.437",
- "value:AKR/J" : "7.550",
- "value:B6D2F1" : "7.742",
- "value:BALB/cByJ" : "6.613",
- "value:BALB/cJ" : "6.664",
- "value:BXD1" : "6.749",
- "value:BXD100" : "x",
- "value:BXD101" : "x",
- "value:BXD102" : "x",
- "value:BXD103" : "x",
- "value:BXD11" : "7.398",
- "value:BXD12" : "7.073",
- "value:BXD13" : "8.191",
- "value:BXD14" : "x",
- "value:BXD15" : "7.406",
- "value:BXD16" : "6.890",
- "value:BXD18" : "x",
- "value:BXD19" : "6.980",
- "value:BXD2" : "7.248",
- "value:BXD20" : "7.554",
- "value:BXD21" : "7.316",
- "value:BXD22" : "7.327",
- "value:BXD23" : "7.605",
- "value:BXD24" : "7.306",
- "value:BXD24a" : "x",
- "value:BXD25" : "x",
- "value:BXD27" : "7.800",
- "value:BXD28" : "7.023",
- "value:BXD29" : "7.518",
- "value:BXD30" : "x",
- "value:BXD31" : "7.301",
- "value:BXD32" : "7.161",
- "value:BXD33" : "7.140",
- "value:BXD34" : "8.180",
- "value:BXD35" : "x",
- "value:BXD36" : "x",
- "value:BXD37" : "x",
- "value:BXD38" : "7.350",
- "value:BXD39" : "6.976",
- "value:BXD40" : "7.411",
- "value:BXD41" : "x",
- "value:BXD42" : "7.050",
- "value:BXD43" : "6.866",
- "value:BXD44" : "7.246",
- "value:BXD45" : "7.576",
- "value:BXD48" : "7.108",
- "value:BXD48a" : "7.192",
- "value:BXD49" : "x",
- "value:BXD5" : "6.771",
- "value:BXD50" : "7.528",
- "value:BXD51" : "7.408",
- "value:BXD52" : "x",
- "value:BXD53" : "x",
- "value:BXD54" : "x",
- "value:BXD55" : "6.720",
- "value:BXD56" : "x",
- "value:BXD59" : "x",
- "value:BXD6" : "7.372",
- "value:BXD60" : "7.178",
- "value:BXD61" : "7.198",
- "value:BXD62" : "7.618",
- "value:BXD63" : "7.076",
- "value:BXD64" : "6.576",
- "value:BXD65" : "7.046",
- "value:BXD65a" : "7.046",
- "value:BXD65b" : "7.385",
- "value:BXD66" : "7.108",
- "value:BXD67" : "7.342",
- "value:BXD68" : "7.668",
- "value:BXD69" : "7.310",
- "value:BXD70" : "7.278",
- "value:BXD71" : "x",
- "value:BXD72" : "x",
- "value:BXD73" : "7.342",
- "value:BXD73a" : "7.841",
- "value:BXD74" : "7.298",
- "value:BXD75" : "7.133",
- "value:BXD76" : "7.448",
- "value:BXD77" : "7.014",
- "value:BXD78" : "x",
- "value:BXD79" : "7.916",
- "value:BXD8" : "7.148",
- "value:BXD81" : "x",
- "value:BXD83" : "7.322",
- "value:BXD84" : "7.298",
- "value:BXD85" : "7.243",
- "value:BXD86" : "7.719",
- "value:BXD87" : "7.145",
- "value:BXD88" : "x",
- "value:BXD89" : "7.162",
- "value:BXD9" : "6.708",
- "value:BXD90" : "7.497",
- "value:BXD91" : "x",
- "value:BXD93" : "7.558",
- "value:BXD94" : "6.817",
- "value:BXD95" : "x",
- "value:BXD98" : "7.753",
- "value:BXD99" : "8.076",
- "value:C3H/HeJ" : "7.536",
- "value:C57BL/6ByJ" : "6.940",
- "value:C57BL/6J" : "7.309",
- "value:CAST/EiJ" : "8.796",
- "value:CXB1" : "6.430",
- "value:CXB10" : "6.958",
- "value:CXB11" : "6.182",
- "value:CXB12" : "6.432",
- "value:CXB13" : "6.388",
- "value:CXB2" : "7.687",
- "value:CXB3" : "6.312",
- "value:CXB4" : "6.453",
- "value:CXB5" : "6.959",
- "value:CXB6" : "7.022",
- "value:CXB7" : "6.334",
- "value:CXB8" : "6.790",
- "value:CXB9" : "6.545",
- "value:D2B6F1" : "7.615",
- "value:DBA/2J" : "7.816",
- "value:KK/HlJ" : "8.035",
- "value:LG/J" : "7.594",
- "value:NOD/ShiLtJ" : "8.220",
- "value:NZO/HlLtJ" : "7.629",
- "value:PWD/PhJ" : "6.320",
- "value:PWK/PhJ" : "7.235",
- "value:WSB/EiJ" : "7.650"
-}
+ "control_marker": "NES13033186",
+ "dataset": "HC_M2_0606_P",
+ "do_control": "false",
+ "maf": "0.01",
+ "manhattan_plot": "False",
+ "mapmethod_rqtl_geno": "em",
+ "mapmodel_rqtl_geno": "normal",
+ "method": "rqtl_geno",
+ "num_bootstrap": "2000",
+ "num_perm": "",
+ "pair_scan": "false",
+ "suggestive": "0",
+ "trait_id": "1435395_s_at",
+ "value:129S1/SvImJ": "15.468",
+ "value:A/J": "15.230",
+ "value:AKR/J": "15.798",
+ "value:B6D2F1": "15.575",
+ "value:BALB/cByJ": "15.138",
+ "value:BALB/cJ": "15.222",
+ "value:BXD1": "15.034",
+ "value:BXD100": "x",
+ "value:BXD101": "x",
+ "value:BXD102": "x",
+ "value:BXD104": "x",
+ "value:BXD105": "x",
+ "value:BXD106": "x",
+ "value:BXD107": "x",
+ "value:BXD108": "x",
+ "value:BXD109": "x",
+ "value:BXD11": "15.364",
+ "value:BXD110": "x",
+ "value:BXD111": "x",
+ "value:BXD112": "x",
+ "value:BXD113": "x",
+ "value:BXD114": "x",
+ "value:BXD115": "x",
+ "value:BXD116": "x",
+ "value:BXD117": "x",
+ "value:BXD119": "x",
+ "value:BXD12": "14.992",
+ "value:BXD120": "x",
+ "value:BXD121": "x",
+ "value:BXD122": "x",
+ "value:BXD123": "x",
+ "value:BXD124": "x",
+ "value:BXD125": "x",
+ "value:BXD126": "x",
+ "value:BXD127": "x",
+ "value:BXD128": "x",
+ "value:BXD128a": "x",
+ "value:BXD13": "15.290",
+ "value:BXD130": "x",
+ "value:BXD131": "x",
+ "value:BXD132": "x",
+ "value:BXD133": "x",
+ "value:BXD134": "x",
+ "value:BXD135": "x",
+ "value:BXD136": "x",
+ "value:BXD137": "x",
+ "value:BXD138": "x",
+ "value:BXD139": "x",
+ "value:BXD14": "x",
+ "value:BXD141": "x",
+ "value:BXD142": "x",
+ "value:BXD144": "x",
+ "value:BXD145": "x",
+ "value:BXD146": "x",
+ "value:BXD147": "x",
+ "value:BXD148": "x",
+ "value:BXD149": "x",
+ "value:BXD15": "15.188",
+ "value:BXD150": "x",
+ "value:BXD151": "x",
+ "value:BXD152": "x",
+ "value:BXD153": "x",
+ "value:BXD154": "x",
+ "value:BXD155": "x",
+ "value:BXD156": "x",
+ "value:BXD157": "x",
+ "value:BXD16": "15.340",
+ "value:BXD160": "x",
+ "value:BXD161": "x",
+ "value:BXD162": "x",
+ "value:BXD165": "x",
+ "value:BXD168": "x",
+ "value:BXD169": "x",
+ "value:BXD170": "x",
+ "value:BXD171": "x",
+ "value:BXD172": "x",
+ "value:BXD173": "x",
+ "value:BXD174": "x",
+ "value:BXD175": "x",
+ "value:BXD176": "x",
+ "value:BXD177": "x",
+ "value:BXD178": "x",
+ "value:BXD18": "x",
+ "value:BXD180": "x",
+ "value:BXD181": "x",
+ "value:BXD183": "x",
+ "value:BXD184": "x",
+ "value:BXD186": "x",
+ "value:BXD187": "x",
+ "value:BXD188": "x",
+ "value:BXD189": "x",
+ "value:BXD19": "15.144",
+ "value:BXD190": "x",
+ "value:BXD191": "x",
+ "value:BXD192": "x",
+ "value:BXD193": "x",
+ "value:BXD194": "x",
+ "value:BXD195": "x",
+ "value:BXD196": "x",
+ "value:BXD197": "x",
+ "value:BXD198": "x",
+ "value:BXD199": "x",
+ "value:BXD2": "15.538",
+ "value:BXD20": "15.194",
+ "value:BXD200": "x",
+ "value:BXD201": "x",
+ "value:BXD202": "x",
+ "value:BXD203": "x",
+ "value:BXD204": "x",
+ "value:BXD205": "x",
+ "value:BXD206": "x",
+ "value:BXD207": "x",
+ "value:BXD208": "x",
+ "value:BXD209": "x",
+ "value:BXD21": "15.088",
+ "value:BXD210": "x",
+ "value:BXD211": "x",
+ "value:BXD212": "x",
+ "value:BXD213": "x",
+ "value:BXD214": "x",
+ "value:BXD215": "x",
+ "value:BXD216": "x",
+ "value:BXD217": "x",
+ "value:BXD218": "x",
+ "value:BXD219": "x",
+ "value:BXD22": "15.499",
+ "value:BXD220": "x",
+ "value:BXD23": "14.988",
+ "value:BXD24": "15.562",
+ "value:BXD24a": "x",
+ "value:BXD25": "x",
+ "value:BXD27": "15.598",
+ "value:BXD28": "15.510",
+ "value:BXD29": "15.041",
+ "value:BXD30": "x",
+ "value:BXD31": "14.834",
+ "value:BXD32": "15.245",
+ "value:BXD33": "15.466",
+ "value:BXD34": "15.302",
+ "value:BXD35": "x",
+ "value:BXD36": "x",
+ "value:BXD37": "x",
+ "value:BXD38": "15.131",
+ "value:BXD39": "15.430",
+ "value:BXD40": "15.488",
+ "value:BXD41": "x",
+ "value:BXD42": "14.878",
+ "value:BXD43": "15.542",
+ "value:BXD44": "15.417",
+ "value:BXD45": "14.910",
+ "value:BXD48": "15.487",
+ "value:BXD48a": "15.328",
+ "value:BXD49": "x",
+ "value:BXD5": "15.622",
+ "value:BXD50": "15.435",
+ "value:BXD51": "15.183",
+ "value:BXD52": "x",
+ "value:BXD53": "x",
+ "value:BXD54": "x",
+ "value:BXD55": "14.928",
+ "value:BXD56": "x",
+ "value:BXD59": "x",
+ "value:BXD6": "15.366",
+ "value:BXD60": "15.502",
+ "value:BXD61": "15.622",
+ "value:BXD62": "15.198",
+ "value:BXD63": "15.238",
+ "value:BXD64": "15.572",
+ "value:BXD65": "15.485",
+ "value:BXD65a": "15.284",
+ "value:BXD65b": "15.318",
+ "value:BXD66": "15.406",
+ "value:BXD67": "15.509",
+ "value:BXD68": "15.552",
+ "value:BXD69": "15.667",
+ "value:BXD70": "15.104",
+ "value:BXD71": "x",
+ "value:BXD72": "x",
+ "value:BXD73": "15.210",
+ "value:BXD73a": "15.223",
+ "value:BXD73b": "x",
+ "value:BXD74": "15.666",
+ "value:BXD75": "15.554",
+ "value:BXD76": "15.234",
+ "value:BXD77": "15.613",
+ "value:BXD78": "x",
+ "value:BXD79": "15.124",
+ "value:BXD8": "15.548",
+ "value:BXD81": "x",
+ "value:BXD83": "15.512",
+ "value:BXD84": "15.426",
+ "value:BXD85": "15.252",
+ "value:BXD86": "15.457",
+ "value:BXD87": "15.320",
+ "value:BXD88": "x",
+ "value:BXD89": "15.316",
+ "value:BXD9": "15.669",
+ "value:BXD90": "15.348",
+ "value:BXD91": "x",
+ "value:BXD93": "15.602",
+ "value:BXD94": "15.360",
+ "value:BXD95": "x",
+ "value:BXD98": "15.421",
+ "value:BXD99": "15.534",
+ "value:C3H/HeJ": "15.398",
+ "value:C57BL/6ByJ": "15.702",
+ "value:C57BL/6J": "15.281",
+ "value:CAST/EiJ": "15.890",
+ "value:CXB1": "15.774",
+ "value:CXB10": "15.518",
+ "value:CXB11": "15.922",
+ "value:CXB12": "15.753",
+ "value:CXB13": "15.608",
+ "value:CXB2": "15.320",
+ "value:CXB3": "15.492",
+ "value:CXB4": "15.541",
+ "value:CXB5": "15.353",
+ "value:CXB6": "15.454",
+ "value:CXB7": "15.547",
+ "value:CXB8": "15.496",
+ "value:CXB9": "15.880",
+ "value:D2B6F1": "15.265",
+ "value:DBA/2J": "15.287",
+ "value:KK/HlJ": "15.303",
+ "value:LG/J": "15.285",
+ "value:NOD/ShiLtJ": "15.348",
+ "value:NZO/HlLtJ": "15.028",
+ "value:PWD/PhJ": "15.535",
+ "value:PWK/PhJ": "15.382",
+ "value:WSB/EiJ": "15.424"}
diff --git a/test/lib/mapping.rb b/test/lib/mapping.rb
index 4c8ff632..d6a3cd7b 100644
--- a/test/lib/mapping.rb
+++ b/test/lib/mapping.rb
@@ -19,7 +19,7 @@ describe MappingTest do
json["method"] = "pylmm"
# p json
page = @agent.post(URI.encode(url), json)
- # Unpacking the page is slow - but the run is enough as a test
+ # Unpacking the page is slow - somehow - but the run is enough as a test
# form = page.forms_with("marker_regression")[0]
# 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 '6.749'
@@ -37,7 +37,7 @@ describe MappingTest do
({'Content-Type' => 'application/x-www-form-urlencoded'}))
form = page.forms_with("marker_regression")[0]
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 '6.749'
+ form.fields.select { |fld| fld.name == 'value:BXD1' }.first.value.must_equal "15.034"
end
end
@@ -50,7 +50,7 @@ describe MappingTest do
page = @agent.post(URI.encode(url), json)
form = page.forms_with("marker_regression")[0]
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 '6.749'
+ form.fields.select { |fld| fld.name == 'value:BXD1' }.first.value.must_equal "15.034"
end
end
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index 1b4e1195..8bd5bfb9 100644
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -107,7 +107,7 @@ Publish or ProbeSet. E.g.
else:
new_type = "ProbeSet"
self.datasets[short_dataset_name] = new_type
- logger.info("datasets",self.datasets)
+ logger.debug("datasets",self.datasets)
def __call__(self, name):
return self.datasets[name]
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index 900e050c..32032ba7 100644
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -363,7 +363,7 @@ class GeneralTrait(object):
FROM
Homologene, Species, InbredSet
WHERE
- Homologene.GeneId =%s AND
+ Homologene.GeneId ='%s' AND
InbredSet.Name = '%s' AND
InbredSet.SpeciesId = Species.Id AND
Species.TaxonomyId = Homologene.TaxonomyId
diff --git a/wqflask/base/webqtlCaseData.py b/wqflask/base/webqtlCaseData.py
index 8df9939e..2f88f778 100644
--- a/wqflask/base/webqtlCaseData.py
+++ b/wqflask/base/webqtlCaseData.py
@@ -16,8 +16,6 @@
# 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
diff --git a/wqflask/maintenance/__init__.py b/wqflask/maintenance/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/maintenance/__init__.py
diff --git a/wqflask/runserver.py b/wqflask/runserver.py
index 12ec904e..0342b7ad 100644
--- a/wqflask/runserver.py
+++ b/wqflask/runserver.py
@@ -16,34 +16,37 @@ GREEN = '\033[92m'
BOLD = '\033[1m'
ENDC = '\033[0m'
-logger.info("GN2 is running. Visit %shttp://localhost:5003/%s" % (BLUE,ENDC))
-
import os
app.config['SECRET_KEY'] = os.urandom(24)
-from utility.tools import WEBSERVER_MODE
+from utility.tools import WEBSERVER_MODE,get_setting_int
+
+port = get_setting_int("SERVER_PORT")
+
+logger.info("GN2 is running. Visit %shttp://localhost:%s/%s" % (BLUE,port,ENDC))
werkzeug_logger = logging.getLogger('werkzeug')
if WEBSERVER_MODE == 'DEBUG':
app.run(host='0.0.0.0',
- port=app.config['SERVER_PORT'],
+ port=port,
debug=True,
- use_debugger=True,
+ use_debugger=False,
threaded=False,
+ processes=0,
use_reloader=True)
elif WEBSERVER_MODE == 'DEV':
werkzeug_logger.setLevel(logging.WARNING)
app.run(host='0.0.0.0',
- port=app.config['SERVER_PORT'],
+ port=port,
debug=False,
use_debugger=False,
threaded=False,
processes=0,
use_reloader=True)
-else: #production mode
+else: # staging/production modes
app.run(host='0.0.0.0',
- port=app.config['SERVER_PORT'],
+ port=port,
debug=False,
use_debugger=False,
threaded=True,
diff --git a/wqflask/utility/helper_functions.py b/wqflask/utility/helper_functions.py
index 149ee553..377f6b26 100644
--- a/wqflask/utility/helper_functions.py
+++ b/wqflask/utility/helper_functions.py
@@ -5,19 +5,21 @@ from base import data_set
from base.species import TheSpecies
from wqflask import user_manager
+import logging
+logger = logging.getLogger(__name__ )
def get_species_dataset_trait(self, start_vars):
#assert type(read_genotype) == type(bool()), "Expecting boolean value for read_genotype"
self.dataset = data_set.create_dataset(start_vars['dataset'])
- print("After creating dataset")
+ logger.debug("After creating dataset")
self.species = TheSpecies(dataset=self.dataset)
- print("After creating species")
+ logger.debug("After creating species")
self.this_trait = GeneralTrait(dataset=self.dataset,
name=start_vars['trait_id'],
cellid=None,
get_qtl_info=True)
- print("After creating trait")
+ logger.debug("After creating trait")
#if read_genotype:
#self.dataset.group.read_genotype_file()
@@ -27,7 +29,7 @@ def get_species_dataset_trait(self, start_vars):
def get_trait_db_obs(self, trait_db_list):
if isinstance(trait_db_list, basestring):
trait_db_list = trait_db_list.split(",")
-
+
self.trait_list = []
for trait in trait_db_list:
data, _separator, hmac = trait.rpartition(':')
@@ -38,4 +40,4 @@ def get_trait_db_obs(self, trait_db_list):
trait_ob = GeneralTrait(dataset=dataset_ob,
name=trait_name,
cellid=None)
- self.trait_list.append((trait_ob, dataset_ob)) \ No newline at end of file
+ self.trait_list.append((trait_ob, dataset_ob))
diff --git a/wqflask/utility/logger.py b/wqflask/utility/logger.py
index ddc0ea82..b873e16f 100644
--- a/wqflask/utility/logger.py
+++ b/wqflask/utility/logger.py
@@ -31,6 +31,7 @@ import string
from inspect import isfunction
from pprint import pformat as pf
from inspect import stack
+import datetime
from utility.tools import LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_SQL, LOG_FORMAT
@@ -66,7 +67,10 @@ LOG_LEVEL_DEBUG (NYI).
def error(self,*args):
"""Call logging.error for multiple args"""
- self.collect(self.logger.error,*args)
+ now = datetime.datetime.utcnow()
+ time_str = now.strftime('%H:%M:%S UTC %Y%m%d')
+ l = [time_str]+list(args)
+ self.collect(self.logger.error,*l)
def infof(self,*args):
"""Call logging.info for multiple args lazily"""
diff --git a/wqflask/utility/tools.py b/wqflask/utility/tools.py
index 22779739..23d6fb62 100644
--- a/wqflask/utility/tools.py
+++ b/wqflask/utility/tools.py
@@ -3,6 +3,7 @@
import os
import sys
+import json
from wqflask import app
@@ -10,6 +11,8 @@ from wqflask import app
import logging
logger = logging.getLogger(__name__ )
+OVERRIDES = {}
+
def get_setting(command_id,guess=None):
"""Resolve a setting from the environment or the global settings in
app.config, with valid_path is a function checking whether the
@@ -45,13 +48,15 @@ def get_setting(command_id,guess=None):
logger.debug("Looking for "+command_id+"\n")
command = value(os.environ.get(command_id))
if command is None or command == "":
- # ---- Check whether setting exists in app
- command = value(app.config.get(command_id))
+ command = OVERRIDES.get(command_id)
if command is None:
- command = value(guess)
- if command is None or command == "":
- print command
- raise Exception(command_id+' setting unknown or faulty (update default_settings.py?).')
+ # ---- Check whether setting exists in app
+ command = value(app.config.get(command_id))
+ if command is None:
+ command = value(guess)
+ if command is None or command == "":
+ # print command
+ raise Exception(command_id+' setting unknown or faulty (update default_settings.py?).')
logger.debug("Set "+command_id+"="+str(command))
return command
@@ -169,18 +174,20 @@ def show_settings():
log_level = getattr(logging, LOG_LEVEL.upper())
logging.basicConfig(level=log_level)
+ logger.info(OVERRIDES)
logger.info(BLUE+"Mr. Mojo Risin 2"+ENDC)
- print "runserver.py: ****** The webserver has the following configuration ******"
+ print "runserver.py: ****** Webserver configuration ******"
keylist = app.config.keys()
keylist.sort()
for k in keylist:
try:
- print("%s %s%s%s%s" % (k,BLUE,BOLD,get_setting(k),ENDC))
+ print("%s: %s%s%s%s" % (k,BLUE,BOLD,get_setting(k),ENDC))
except:
- print("%s %s%s%s%s" % (k,GREEN,BOLD,app.config[k],ENDC))
+ print("%s: %s%s%s%s" % (k,GREEN,BOLD,app.config[k],ENDC))
# Cached values
+HOME = get_setting('HOME')
WEBSERVER_MODE = get_setting('WEBSERVER_MODE')
GN_SERVER_URL = get_setting('GN_SERVER_URL')
SQL_URI = get_setting('SQL_URI')
@@ -199,3 +206,18 @@ PYLMM_COMMAND = pylmm_command()
GEMMA_COMMAND = gemma_command()
PLINK_COMMAND = plink_command()
TEMPDIR = tempdir()
+
+from six import string_types
+
+if os.environ.get('WQFLASK_OVERRIDES'):
+ jsonfn = get_setting('WQFLASK_OVERRIDES')
+ logger.error("WQFLASK_OVERRIDES: %s" % jsonfn)
+ with open(jsonfn) as data_file:
+ overrides = json.load(data_file)
+ for k in overrides:
+ cmd = overrides[k]
+ if isinstance(cmd, string_types):
+ OVERRIDES[k] = eval(cmd)
+ else:
+ OVERRIDES[k] = cmd
+ logger.debug(OVERRIDES)
diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py
index af271d02..2188ce17 100644
--- a/wqflask/wqflask/__init__.py
+++ b/wqflask/wqflask/__init__.py
@@ -14,11 +14,7 @@ app = Flask(__name__)
app.config.from_object('cfg.default_settings') # Get the defaults from cfg.default_settings
app.config.from_envvar('WQFLASK_SETTINGS') # See http://flask.pocoo.org/docs/config/#configuring-from-files
-
-logger.debug("System path is")
-logger.debug(sys.path)
-logger.debug("App.config is")
-logger.debug(app.config)
+# Note we also use WQFLASK_OVERRIDES
app.jinja_env.globals.update(
undefined = jinja2.StrictUndefined,
diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py
index 7e7aba89..81d03d6c 100644
--- a/wqflask/wqflask/collect.py
+++ b/wqflask/wqflask/collect.py
@@ -164,7 +164,7 @@ class UserCollection(object):
if not uc:
return create_new("Default")
else:
- uc = model.UserCollection.query.get(params['existing_collection'])
+ uc = model.UserCollection.query.get(params['existing_collection'].split(":")[0])
members = list(uc.members_as_set()) #set(json.loads(uc.members))
len_before = len(members)
@@ -218,7 +218,6 @@ def collections_add():
anon_collections = user_manager.AnonUser().get_collections()
collection_names = []
for collection in anon_collections:
- print("COLLECTION:", collection)
collection_names.append({'id':collection['id'], 'name':collection['name']})
return render_template("collections/add.html",
traits = traits,
@@ -229,21 +228,17 @@ def collections_add():
@app.route("/collections/new")
def collections_new():
params = request.args
- #print("request.args in collections_new are:", params)
-
- collection_name = params['new_collection']
- if "anonymous_add" in params:
- AnonCollection(name=collection_name).add_traits(params, "Default")
- return redirect(url_for('view_collection'))
if "sign_in" in params:
return redirect(url_for('login'))
if "create_new" in params:
print("in create_new")
+ collection_name = params['new_collection']
return create_new(collection_name)
elif "add_to_existing" in params:
print("in add to existing")
+ collection_name = params['existing_collection'].split(":")[1]
if g.user_session.logged_in:
return UserCollection().add_traits(params, collection_name)
else:
@@ -251,7 +246,6 @@ def collections_new():
ac.add_traits(params)
return redirect(url_for('view_collection', collection_id=ac.id))
else:
- print("ELSE")
CauseAnError
@@ -288,7 +282,6 @@ def create_new(collection_name):
ac = AnonCollection(collection_name)
ac.changed_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
ac.add_traits(params)
- print("Collection ID:", ac.id)
return redirect(url_for('view_collection', collection_id=ac.id))
@app.route("/collections/list")
@@ -367,7 +360,6 @@ def view_collection():
uc_id = params['uc_id']
uc = model.UserCollection.query.get(uc_id)
traits = json.loads(uc.members)
- print("traits are:", traits)
else:
user_collections = json.loads(Redis.get(user_manager.AnonUser().key))
this_collection = {}
@@ -384,7 +376,6 @@ def view_collection():
json_version = []
for atrait in traits:
- print("atrait is:", atrait)
name, dataset_name = atrait.split(':')
trait_ob = trait.GeneralTrait(name=name, dataset_name=dataset_name)
@@ -393,8 +384,6 @@ def view_collection():
json_version.append(trait_ob.jsonable())
- print("trait_obs:", trait_obs)
-
if "uc_id" in params:
collection_info = dict(trait_obs=trait_obs,
uc = uc)
diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py
index d7c78db0..37ee42a7 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
+from wqflask.marker_regression import gemma_mapping, rqtl_mapping
from utility.tools import locate, locate_ignore_error, PYLMM_COMMAND, GEMMA_COMMAND, PLINK_COMMAND, TEMPDIR
from utility.external import shell
@@ -169,7 +169,10 @@ class MarkerRegression(object):
self.model = start_vars['mapmodel_rqtl_geno']
if start_vars['pair_scan'] == "true":
self.pair_scan = True
- results = self.run_rqtl_geno()
+ 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)
+ 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":
if "startMb" in start_vars: #ZS: Check if first time page loaded, so it can default to ON
if "additiveCheck" in start_vars:
@@ -202,12 +205,12 @@ class MarkerRegression(object):
elif self.mapping_method == "plink":
results = self.run_plink()
elif self.mapping_method == "pylmm":
- print("RUNNING PYLMM")
+ logger.debug("RUNNING PYLMM")
if self.num_perm > 0:
self.run_permutations(str(temp_uuid))
results = self.gen_data(str(temp_uuid))
else:
- print("RUNNING NOTHING")
+ logger.debug("RUNNING NOTHING")
if self.pair_scan == True:
self.qtl_results = []
@@ -261,9 +264,9 @@ class MarkerRegression(object):
#Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary
for index, qtl in enumerate(self.qtl_results):
#if index<40:
- # print("lod score is:", qtl['lod_score'])
+ # logger.debug("lod score is:", qtl['lod_score'])
if qtl['chr'] == highest_chr and highest_chr != "X" and highest_chr != "X/Y":
- #print("changing to X")
+ #logger.debug("changing to X")
self.json_data['chr'].append("X")
else:
self.json_data['chr'].append(str(qtl['chr']))
@@ -281,7 +284,7 @@ class MarkerRegression(object):
self.json_data['chrnames'].append([self.species.chromosomes.chromosomes[key].name, self.species.chromosomes.chromosomes[key].mb_length])
chromosome_mb_lengths[key] = self.species.chromosomes.chromosomes[key].mb_length
- # print("json_data:", self.json_data)
+ # logger.debug("json_data:", self.json_data)
self.js_data = dict(
result_score_type = self.score_type,
@@ -309,7 +312,7 @@ class MarkerRegression(object):
self.dataset.group.name,
self.dataset.group.name,
self.dataset.group.name)
- #print("gemma_command:" + gemma_command)
+ #logger.debug("gemma_command:" + gemma_command)
os.system(gemma_command)
@@ -331,7 +334,7 @@ class MarkerRegression(object):
included_markers.append(line.split("\t")[1])
p_values.append(float(line.split("\t")[10]))
#p_values[line.split("\t")[1]] = float(line.split("\t")[10])
- #print("p_values: ", p_values)
+ #logger.debug("p_values: ", p_values)
return included_markers, p_values
def gen_pheno_txt_file(self):
@@ -353,200 +356,13 @@ class MarkerRegression(object):
count, p_values = self.parse_rqtl_output(plink_output_filename)
- def geno_to_rqtl_function(self): # TODO: Need to figure out why some genofiles have the wrong format and don't convert properly
-
- ro.r("""
- trim <- function( x ) { gsub("(^[[:space:]]+|[[:space:]]+$)", "", x) }
-
- getGenoCode <- function(header, name = 'unk'){
- mat = which(unlist(lapply(header,function(x){ length(grep(paste('@',name,sep=''), x)) })) == 1)
- return(trim(strsplit(header[mat],':')[[1]][2]))
- }
-
- GENOtoCSVR <- function(genotypes = '%s', out = 'cross.csvr', phenotype = NULL, sex = NULL, verbose = FALSE){
- header = readLines(genotypes, 40) # Assume a geno header is not longer than 40 lines
- toskip = which(unlist(lapply(header, function(x){ length(grep("Chr\t", x)) })) == 1)-1 # Major hack to skip the geno headers
-
- genocodes <- c(getGenoCode(header, 'mat'), getGenoCode(header, 'het'), getGenoCode(header, 'pat')) # Get the genotype codes
- type <- getGenoCode(header, 'type')
- genodata <- read.csv(genotypes, sep='\t', skip=toskip, header=TRUE, na.strings=getGenoCode(header,'unk'), colClasses='character', comment.char = '#')
- cat('Genodata:', toskip, " ", dim(genodata), genocodes, '\n')
- if(is.null(phenotype)) phenotype <- runif((ncol(genodata)-4)) # If there isn't a phenotype, generate a random one
- if(is.null(sex)) sex <- rep('m', (ncol(genodata)-4)) # If there isn't a sex phenotype, treat all as males
- outCSVR <- rbind(c('Pheno', '', '', phenotype), # Phenotype
- c('sex', '', '', sex), # Sex phenotype for the mice
- cbind(genodata[,c('Locus','Chr', 'cM')], genodata[, 5:ncol(genodata)])) # Genotypes
- write.table(outCSVR, file = out, row.names=FALSE, col.names=FALSE,quote=FALSE, sep=',') # Save it to a file
- require(qtl)
- cross = read.cross(file=out, 'csvr', genotypes=genocodes) # Load the created cross file using R/qtl read.cross
- if(type == 'riset') cross <- convert2riself(cross) # If its a RIL, convert to a RIL in R/qtl
- return(cross)
- }
- """ % (self.dataset.group.name + ".geno"))
-
- def run_rqtl_geno(self):
- self.geno_to_rqtl_function()
-
- ## Get pointers to some common R functions
- r_library = ro.r["library"] # Map the library function
- r_c = ro.r["c"] # Map the c function
- r_sum = ro.r["sum"] # Map the sum function
- plot = ro.r["plot"] # Map the plot function
- postscript = ro.r["postscript"] # Map the postscript function
- png = ro.r["png"] # Map the png function
- dev_off = ro.r["dev.off"] # Map the device off function
-
- print(r_library("qtl")) # Load R/qtl
-
- ## Get pointers to some R/qtl functions
- scanone = ro.r["scanone"] # Map the scanone function
- scantwo = ro.r["scantwo"] # Map the scantwo function
- calc_genoprob = ro.r["calc.genoprob"] # Map the calc.genoprob function
- read_cross = ro.r["read.cross"] # Map the read.cross function
- write_cross = ro.r["write.cross"] # Map the write.cross function
- GENOtoCSVR = ro.r["GENOtoCSVR"] # Map the local GENOtoCSVR function
-
- crossname = self.dataset.group.name
- genofilelocation = locate(crossname + ".geno", "genotype")
- crossfilelocation = TMPDIR + crossname + ".cross"
-
- #print("Conversion of geno to cross at location:", genofilelocation, " to ", crossfilelocation)
-
- cross_object = GENOtoCSVR(genofilelocation, crossfilelocation) # TODO: Add the SEX if that is available
-
- if self.manhattan_plot:
- cross_object = calc_genoprob(cross_object)
- else:
- cross_object = calc_genoprob(cross_object, step=1, stepwidth="max")
-
- cross_object = self.add_phenotype(cross_object, self.sanitize_rqtl_phenotype()) # Add the phenotype
-
- # for debug: write_cross(cross_object, "csvr", "test.csvr")
-
- # Scan for QTLs
- covar = self.create_covariates(cross_object) # Create the additive covariate matrix
-
- if self.pair_scan:
- if self.do_control == "true": # If sum(covar) > 0 we have a covariate matrix
- print("Using covariate"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", addcovar = covar, model=self.model, method=self.method, n_cluster = 16)
- else:
- print("No covariates"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", model=self.model, method=self.method, n_cluster = 16)
-
- #print("Pair scan results:", result_data_frame)
-
- self.pair_scan_filename = webqtlUtil.genRandStr("scantwo_") + ".png"
- png(file=TEMPDIR+self.pair_scan_filename)
- plot(result_data_frame)
- dev_off()
-
- return self.process_pair_scan_results(result_data_frame)
-
- else:
- if self.do_control == "true":
- print("Using covariate"); result_data_frame = scanone(cross_object, pheno = "the_pheno", addcovar = covar, model=self.model, method=self.method)
- else:
- print("No covariates"); result_data_frame = scanone(cross_object, pheno = "the_pheno", model=self.model, method=self.method)
-
- if self.num_perm > 0 and self.permCheck == "ON": # Do permutation (if requested by user)
- if self.do_control == "true":
- perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", addcovar = covar, n_perm = self.num_perm, model=self.model, method=self.method)
- else:
- perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", n_perm = self.num_perm, model=self.model, method=self.method)
-
- self.process_rqtl_perm_results(perm_data_frame) # Functions that sets the thresholds for the webinterface
-
- return self.process_rqtl_results(result_data_frame)
-
- def add_phenotype(self, cross, pheno_as_string):
- ro.globalenv["the_cross"] = cross
- ro.r('the_cross$pheno <- cbind(pull.pheno(the_cross), the_pheno = '+ pheno_as_string +')')
- return ro.r["the_cross"]
-
- def create_covariates(self, cross):
- ro.globalenv["the_cross"] = cross
- ro.r('genotypes <- pull.geno(the_cross)') # Get the genotype matrix
- userinputS = self.control_marker.replace(" ", "").split(",") # TODO: sanitize user input, Never Ever trust a user
- covariate_names = ', '.join('"{0}"'.format(w) for w in userinputS)
- #print("Marker names of selected covariates:", covariate_names)
- ro.r('covnames <- c(' + covariate_names + ')')
- ro.r('covInGeno <- which(covnames %in% colnames(genotypes))')
- ro.r('covnames <- covnames[covInGeno]')
- ro.r("cat('covnames (purged): ', covnames,'\n')")
- ro.r('covariates <- genotypes[,covnames]') # Get the covariate matrix by using the marker name as index to the genotype file
- #print("R/qtl matrix of covariates:", ro.r["covariates"])
- return ro.r["covariates"]
-
- def sanitize_rqtl_phenotype(self):
- pheno_as_string = "c("
- for i, val in enumerate(self.vals):
- if val == "x":
- if i < (len(self.vals) - 1):
- pheno_as_string += "NA,"
- else:
- pheno_as_string += "NA"
- else:
- if i < (len(self.vals) - 1):
- pheno_as_string += str(val) + ","
- else:
- pheno_as_string += str(val)
- pheno_as_string += ")"
- return pheno_as_string
-
- def process_pair_scan_results(self, result):
- pair_scan_results = []
-
- result = result[1]
- output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)]
- #print("R/qtl scantwo output:", output)
-
- for i, line in enumerate(result.iter_row()):
- marker = {}
- marker['name'] = result.rownames[i]
- marker['chr1'] = output[i][0]
- marker['Mb'] = output[i][1]
- marker['chr2'] = int(output[i][2])
- pair_scan_results.append(marker)
-
- #print("pair_scan_results:", pair_scan_results)
-
- return pair_scan_results
-
- def process_rqtl_results(self, result): # TODO: how to make this a one liner and not copy the stuff in a loop
- qtl_results = []
-
- output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)]
- #print("R/qtl scanone output:", output)
-
- for i, line in enumerate(result.iter_row()):
- marker = {}
- marker['name'] = result.rownames[i]
- marker['chr'] = output[i][0]
- marker['Mb'] = output[i][1]
- marker['lod_score'] = output[i][2]
- qtl_results.append(marker)
-
- return qtl_results
-
- def process_rqtl_perm_results(self, results):
- perm_vals = []
- for line in str(results).split("\n")[1:(self.num_perm+1)]:
- #print("R/qtl permutation line:", line.split())
- perm_vals.append(float(line.split()[1]))
-
- self.perm_output = perm_vals
- self.suggestive = np.percentile(np.array(perm_vals), 67)
- self.significant = np.percentile(np.array(perm_vals), 95)
-
- return self.suggestive, self.significant
-
-
def run_plink(self):
plink_output_filename = webqtlUtil.genRandStr("%s_%s_"%(self.dataset.group.name, self.this_trait.name))
self.gen_pheno_txt_file_plink(pheno_filename = plink_output_filename)
plink_command = PLINK_COMMAND + ' --noweb --ped %s/%s.ped --no-fid --no-parents --no-sex --no-pheno --map %s/%s.map --pheno %s%s.txt --pheno-name %s --maf %s --missing-phenotype -9999 --out %s%s --assoc ' % (PLINK_PATH, self.dataset.group.name, PLINK_PATH, self.dataset.group.name, TMPDIR, plink_output_filename, self.this_trait.name, self.maf, TMPDIR, plink_output_filename)
- print("plink_command:", plink_command)
+ logger.debug("plink_command:", plink_command)
os.system(plink_command)
@@ -554,11 +370,11 @@ class MarkerRegression(object):
#for marker in self.dataset.group.markers.markers:
# if marker['name'] not in included_markers:
- # print("marker:", marker)
+ # logger.debug("marker:", marker)
# self.dataset.group.markers.markers.remove(marker)
# #del self.dataset.group.markers.markers[marker]
- print("p_values:", pf(p_values))
+ logger.debug("p_values:", pf(p_values))
self.dataset.group.markers.add_pvalues(p_values)
@@ -825,7 +641,7 @@ class MarkerRegression(object):
top_lod_scores = []
- #print("self.num_perm:", self.num_perm)
+ #logger.debug("self.num_perm:", self.num_perm)
for permutation in range(self.num_perm):
@@ -870,10 +686,10 @@ class MarkerRegression(object):
if p_value < lowest_p_value:
lowest_p_value = p_value
- #print("lowest_p_value:", lowest_p_value)
+ #logger.debug("lowest_p_value:", lowest_p_value)
top_lod_scores.append(-math.log10(lowest_p_value))
- #print("top_lod_scores:", top_lod_scores)
+ #logger.debug("top_lod_scores:", top_lod_scores)
self.suggestive = np.percentile(top_lod_scores, 67)
self.significant = np.percentile(top_lod_scores, 95)
@@ -881,14 +697,13 @@ class MarkerRegression(object):
def gen_data(self, temp_uuid):
"""Generates p-values for each marker"""
-
- print("self.vals is:", self.vals)
+ logger.debug("self.vals is:", self.vals)
pheno_vector = np.array([(val == "x" or val == "") and np.nan or float(val) for val in self.vals])
#lmm_uuid = str(uuid.uuid4())
key = "pylmm:input:" + temp_uuid
- print("key is:", pf(key))
+ logger.debug("key is:", pf(key))
#with Bench("Loading cache"):
# result = Redis.get(key)
@@ -897,7 +712,7 @@ class MarkerRegression(object):
#p_values = self.trim_results(p_values)
else:
- print("NOW CWD IS:", os.getcwd())
+ logger.debug("NOW CWD IS:", os.getcwd())
genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers]
no_val_samples = self.identify_empty_samples()
@@ -905,9 +720,9 @@ class MarkerRegression(object):
genotype_matrix = np.array(genotype_data).T
- #print("pheno_vector: ", pf(pheno_vector))
- #print("genotype_matrix: ", pf(genotype_matrix))
- #print("genotype_matrix.shape: ", pf(genotype_matrix.shape))
+ #logger.debug("pheno_vector: ", pf(pheno_vector))
+ #logger.debug("genotype_matrix: ", pf(genotype_matrix))
+ #logger.debug("genotype_matrix.shape: ", pf(genotype_matrix.shape))
#params = {"pheno_vector": pheno_vector,
# "genotype_matrix": genotype_matrix,
@@ -915,8 +730,8 @@ class MarkerRegression(object):
# "refit": False,
# "temp_data": tempdata}
- # print("genotype_matrix:", str(genotype_matrix.tolist()))
- # print("pheno_vector:", str(pheno_vector.tolist()))
+ # logger.debug("genotype_matrix:", str(genotype_matrix.tolist()))
+ # logger.debug("pheno_vector:", str(pheno_vector.tolist()))
params = dict(pheno_vector = pheno_vector.tolist(),
genotype_matrix = genotype_matrix.tolist(),
@@ -929,14 +744,14 @@ class MarkerRegression(object):
)
json_params = json.dumps(params)
- #print("json_params:", json_params)
+ #logger.debug("json_params:", json_params)
Redis.set(key, json_params)
Redis.expire(key, 60*60)
- print("before printing command")
+ logger.debug("before printing command")
command = PYLMM_COMMAND + ' --key {} --species {}'.format(key, "other")
- print("command is:", command)
- print("after printing command")
+ logger.debug("command is:", command)
+ logger.debug("after printing command")
shell(command)
@@ -946,7 +761,7 @@ class MarkerRegression(object):
json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60)
results = json.loads(json_results[1])
p_values = [float(result) for result in results['p_values']]
- #print("p_values:", p_values[:10])
+ #logger.debug("p_values:", p_values[:10])
#p_values = self.trim_results(p_values)
t_stats = results['t_stats']
@@ -957,7 +772,7 @@ class MarkerRegression(object):
# refit=False,
# temp_data=tempdata
#)
- #print("p_values:", p_values)
+ #logger.debug("p_values:", p_values)
self.dataset.group.markers.add_pvalues(p_values)
@@ -966,7 +781,7 @@ class MarkerRegression(object):
return self.dataset.group.markers.markers
def trim_results(self, p_values):
- print("len_p_values:", len(p_values))
+ logger.debug("len_p_values:", len(p_values))
if len(p_values) > 500:
p_values.sort(reverse=True)
trimmed_values = p_values[:500]
@@ -985,7 +800,7 @@ class MarkerRegression(object):
kinship_matrix = np.fromfile(open(file_base + '.kin','r'),sep=" ")
kinship_matrix.resize((len(plink_input.indivs),len(plink_input.indivs)))
- print("Before creating params")
+ logger.debug("Before creating params")
params = dict(pheno_vector = pheno_vector.tolist(),
covariate_matrix = covariate_matrix.tolist(),
@@ -998,18 +813,18 @@ class MarkerRegression(object):
timestamp = datetime.datetime.now().isoformat(),
)
- print("After creating params")
+ logger.debug("After creating params")
json_params = json.dumps(params)
Redis.set(key, json_params)
Redis.expire(key, 60*60)
- print("Before creating the command")
+ logger.debug("Before creating the command")
command = PYLMM_COMMAND+' --key {} --species {}'.format(key,
"human")
- print("command is:", command)
+ logger.debug("command is:", command)
os.system(command)
@@ -1032,7 +847,7 @@ class MarkerRegression(object):
return p_values, t_stats
def get_lod_score_cutoff(self):
- print("INSIDE GET LOD CUTOFF")
+ logger.debug("INSIDE GET LOD CUTOFF")
high_qtl_count = 0
for marker in self.dataset.group.markers.markers:
if marker['lod_score'] > 1:
diff --git a/wqflask/wqflask/marker_regression/rqtl_mapping.py b/wqflask/wqflask/marker_regression/rqtl_mapping.py
new file mode 100644
index 00000000..93bf717c
--- /dev/null
+++ b/wqflask/wqflask/marker_regression/rqtl_mapping.py
@@ -0,0 +1,193 @@
+import rpy2.robjects as ro
+import numpy as np
+
+from base.webqtlConfig import TMPDIR
+from utility import webqtlUtil
+from utility.tools import locate, TEMPDIR
+
+def run_rqtl_geno(vals, dataset, method, model, permCheck, num_perm, do_control, control_marker, manhattan_plot, pair_scan):
+ geno_to_rqtl_function(dataset)
+
+ ## Get pointers to some common R functions
+ r_library = ro.r["library"] # Map the library function
+ r_c = ro.r["c"] # Map the c function
+ r_sum = ro.r["sum"] # Map the sum function
+ plot = ro.r["plot"] # Map the plot function
+ postscript = ro.r["postscript"] # Map the postscript function
+ png = ro.r["png"] # Map the png function
+ dev_off = ro.r["dev.off"] # Map the device off function
+
+ print(r_library("qtl")) # Load R/qtl
+
+ ## Get pointers to some R/qtl functions
+ scanone = ro.r["scanone"] # Map the scanone function
+ scantwo = ro.r["scantwo"] # Map the scantwo function
+ calc_genoprob = ro.r["calc.genoprob"] # Map the calc.genoprob function
+ read_cross = ro.r["read.cross"] # Map the read.cross function
+ write_cross = ro.r["write.cross"] # Map the write.cross function
+ GENOtoCSVR = ro.r["GENOtoCSVR"] # Map the local GENOtoCSVR function
+
+ crossname = dataset.group.name
+ genofilelocation = locate(crossname + ".geno", "genotype")
+ crossfilelocation = TMPDIR + crossname + ".cross"
+
+ #print("Conversion of geno to cross at location:", genofilelocation, " to ", crossfilelocation)
+
+ cross_object = GENOtoCSVR(genofilelocation, crossfilelocation) # TODO: Add the SEX if that is available
+
+ if manhattan_plot:
+ cross_object = calc_genoprob(cross_object)
+ else:
+ cross_object = calc_genoprob(cross_object, step=1, stepwidth="max")
+
+ cross_object = add_phenotype(cross_object, sanitize_rqtl_phenotype(vals)) # Add the phenotype
+
+ # for debug: write_cross(cross_object, "csvr", "test.csvr")
+
+ # Scan for QTLs
+ covar = create_covariates(control_marker, cross_object) # Create the additive covariate matrix
+
+ if pair_scan:
+ if do_control == "true": # If sum(covar) > 0 we have a covariate matrix
+ print("Using covariate"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", addcovar = covar, model=model, method=method, n_cluster = 16)
+ else:
+ print("No covariates"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", model=model, method=method, n_cluster = 16)
+
+ #print("Pair scan results:", result_data_frame)
+
+ pair_scan_filename = webqtlUtil.genRandStr("scantwo_") + ".png"
+ png(file=TEMPDIR+pair_scan_filename)
+ plot(result_data_frame)
+ dev_off()
+
+ return process_pair_scan_results(result_data_frame)
+ else:
+ if do_control == "true":
+ print("Using covariate"); result_data_frame = scanone(cross_object, pheno = "the_pheno", addcovar = covar, model=model, method=method)
+ else:
+ print("No covariates"); result_data_frame = scanone(cross_object, pheno = "the_pheno", model=model, method=method)
+
+ if num_perm > 0 and permCheck == "ON": # Do permutation (if requested by user)
+ if do_control == "true":
+ perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", addcovar = covar, n_perm = num_perm, model=model, method=method)
+ else:
+ perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", n_perm = num_perm, model=model, method=method)
+
+ perm_output, suggestive, significant = process_rqtl_perm_results(num_perm, perm_data_frame) # Functions that sets the thresholds for the webinterface
+ return perm_output, suggestive, significant, process_rqtl_results(result_data_frame)
+ else:
+ return process_rqtl_results(result_data_frame)
+
+def geno_to_rqtl_function(dataset): # TODO: Need to figure out why some genofiles have the wrong format and don't convert properly
+
+ ro.r("""
+ trim <- function( x ) { gsub("(^[[:space:]]+|[[:space:]]+$)", "", x) }
+
+ getGenoCode <- function(header, name = 'unk'){
+ mat = which(unlist(lapply(header,function(x){ length(grep(paste('@',name,sep=''), x)) })) == 1)
+ return(trim(strsplit(header[mat],':')[[1]][2]))
+ }
+
+ GENOtoCSVR <- function(genotypes = '%s', out = 'cross.csvr', phenotype = NULL, sex = NULL, verbose = FALSE){
+ header = readLines(genotypes, 40) # Assume a geno header is not longer than 40 lines
+ toskip = which(unlist(lapply(header, function(x){ length(grep("Chr\t", x)) })) == 1)-1 # Major hack to skip the geno headers
+
+ genocodes <- c(getGenoCode(header, 'mat'), getGenoCode(header, 'het'), getGenoCode(header, 'pat')) # Get the genotype codes
+ type <- getGenoCode(header, 'type')
+ genodata <- read.csv(genotypes, sep='\t', skip=toskip, header=TRUE, na.strings=getGenoCode(header,'unk'), colClasses='character', comment.char = '#')
+ cat('Genodata:', toskip, " ", dim(genodata), genocodes, '\n')
+ if(is.null(phenotype)) phenotype <- runif((ncol(genodata)-4)) # If there isn't a phenotype, generate a random one
+ if(is.null(sex)) sex <- rep('m', (ncol(genodata)-4)) # If there isn't a sex phenotype, treat all as males
+ outCSVR <- rbind(c('Pheno', '', '', phenotype), # Phenotype
+ c('sex', '', '', sex), # Sex phenotype for the mice
+ cbind(genodata[,c('Locus','Chr', 'cM')], genodata[, 5:ncol(genodata)])) # Genotypes
+ write.table(outCSVR, file = out, row.names=FALSE, col.names=FALSE,quote=FALSE, sep=',') # Save it to a file
+ require(qtl)
+ cross = read.cross(file=out, 'csvr', genotypes=genocodes) # Load the created cross file using R/qtl read.cross
+ if(type == 'riset') cross <- convert2riself(cross) # If its a RIL, convert to a RIL in R/qtl
+ return(cross)
+ }
+ """ % (dataset.group.name + ".geno"))
+
+def add_phenotype(cross, pheno_as_string):
+ ro.globalenv["the_cross"] = cross
+ ro.r('the_cross$pheno <- cbind(pull.pheno(the_cross), the_pheno = '+ pheno_as_string +')')
+ return ro.r["the_cross"]
+
+def create_covariates(control_marker, cross):
+ ro.globalenv["the_cross"] = cross
+ ro.r('genotypes <- pull.geno(the_cross)') # Get the genotype matrix
+ userinputS = control_marker.replace(" ", "").split(",") # TODO: sanitize user input, Never Ever trust a user
+ covariate_names = ', '.join('"{0}"'.format(w) for w in userinputS)
+ #print("Marker names of selected covariates:", covariate_names)
+ ro.r('covnames <- c(' + covariate_names + ')')
+ ro.r('covInGeno <- which(covnames %in% colnames(genotypes))')
+ ro.r('covnames <- covnames[covInGeno]')
+ ro.r("cat('covnames (purged): ', covnames,'\n')")
+ ro.r('covariates <- genotypes[,covnames]') # Get the covariate matrix by using the marker name as index to the genotype file
+ #print("R/qtl matrix of covariates:", ro.r["covariates"])
+ return ro.r["covariates"]
+
+def sanitize_rqtl_phenotype(vals):
+ pheno_as_string = "c("
+ for i, val in enumerate(vals):
+ if val == "x":
+ if i < (len(vals) - 1):
+ pheno_as_string += "NA,"
+ else:
+ pheno_as_string += "NA"
+ else:
+ if i < (len(vals) - 1):
+ pheno_as_string += str(val) + ","
+ else:
+ pheno_as_string += str(val)
+ pheno_as_string += ")"
+ return pheno_as_string
+
+def process_pair_scan_results(result):
+ pair_scan_results = []
+
+ result = result[1]
+ output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)]
+ #print("R/qtl scantwo output:", output)
+
+ for i, line in enumerate(result.iter_row()):
+ marker = {}
+ marker['name'] = result.rownames[i]
+ marker['chr1'] = output[i][0]
+ marker['Mb'] = output[i][1]
+ marker['chr2'] = int(output[i][2])
+ pair_scan_results.append(marker)
+
+ #print("pair_scan_results:", pair_scan_results)
+
+ return pair_scan_results
+
+def process_rqtl_perm_results(num_perm, results):
+ perm_vals = []
+ for line in str(results).split("\n")[1:(num_perm+1)]:
+ #print("R/qtl permutation line:", line.split())
+ perm_vals.append(float(line.split()[1]))
+
+ perm_output = perm_vals
+ suggestive = np.percentile(np.array(perm_vals), 67)
+ significant = np.percentile(np.array(perm_vals), 95)
+ print("SIGNIFICANT:", significant)
+
+ return perm_output, suggestive, significant
+
+def process_rqtl_results(result): # TODO: how to make this a one liner and not copy the stuff in a loop
+ qtl_results = []
+
+ output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)]
+ #print("R/qtl scanone output:", output)
+
+ for i, line in enumerate(result.iter_row()):
+ marker = {}
+ marker['name'] = result.rownames[i]
+ marker['chr'] = output[i][0]
+ marker['Mb'] = output[i][1]
+ marker['lod_score'] = output[i][2]
+ qtl_results.append(marker)
+
+ return qtl_results \ No newline at end of file
diff --git a/wqflask/wqflask/static/gif/error/Wild-Type-Mouse.gif b/wqflask/wqflask/static/gif/error/Wild-Type-Mouse.gif
new file mode 100644
index 00000000..2c68b5ee
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/Wild-Type-Mouse.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-aliens-29.gif b/wqflask/wqflask/static/gif/error/animated-gifs-aliens-29.gif
new file mode 100644
index 00000000..e9d38277
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-aliens-29.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-angels-04.gif b/wqflask/wqflask/static/gif/error/animated-gifs-angels-04.gif
new file mode 100644
index 00000000..94e11847
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-angels-04.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cats-016.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cats-016.gif
new file mode 100644
index 00000000..7e6ec9a3
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-cats-016.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cats-031.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cats-031.gif
new file mode 100644
index 00000000..af7ef655
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-cats-031.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-03.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-03.gif
new file mode 100644
index 00000000..89c79ddf
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-03.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-16.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-16.gif
new file mode 100644
index 00000000..7530d180
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-16.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-13.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-13.gif
new file mode 100644
index 00000000..afb05c62
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-13.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-28.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-28.gif
new file mode 100644
index 00000000..f5b4a563
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-28.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-32.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-32.gif
new file mode 100644
index 00000000..7258e594
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-32.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-42.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-42.gif
new file mode 100644
index 00000000..ed1f8722
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-42.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-60.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-60.gif
new file mode 100644
index 00000000..f58d69f1
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-60.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-64.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-64.gif
new file mode 100644
index 00000000..5d5b4fdf
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-64.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-65.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-65.gif
new file mode 100644
index 00000000..b4b10845
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-65.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-72.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-72.gif
new file mode 100644
index 00000000..e60cb4fe
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-72.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-74.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-74.gif
new file mode 100644
index 00000000..bd7b72f3
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-74.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-75.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-75.gif
new file mode 100644
index 00000000..916d6b33
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-75.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-construction-sites-038.gif b/wqflask/wqflask/static/gif/error/animated-gifs-construction-sites-038.gif
new file mode 100644
index 00000000..0ec782c4
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-construction-sites-038.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-04.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-04.gif
new file mode 100644
index 00000000..9515c18a
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-04.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-14.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-14.gif
new file mode 100644
index 00000000..f1e2e1f5
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-14.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-18.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-18.gif
new file mode 100644
index 00000000..572849d5
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-18.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-47.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-47.gif
new file mode 100644
index 00000000..d808c9ee
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-47.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-50.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-50.gif
new file mode 100644
index 00000000..9865ee45
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-50.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-lava-lamps-01.gif b/wqflask/wqflask/static/gif/error/animated-gifs-lava-lamps-01.gif
new file mode 100644
index 00000000..ee9c113d
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-lava-lamps-01.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-mice-02.gif b/wqflask/wqflask/static/gif/error/animated-gifs-mice-02.gif
new file mode 100644
index 00000000..5ca2ee5c
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-mice-02.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-mice-09.gif b/wqflask/wqflask/static/gif/error/animated-gifs-mice-09.gif
new file mode 100644
index 00000000..7cb361e4
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-mice-09.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-mice-24.gif b/wqflask/wqflask/static/gif/error/animated-gifs-mice-24.gif
new file mode 100644
index 00000000..96a26450
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-mice-24.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-063.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-063.gif
new file mode 100644
index 00000000..62de166c
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-063.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-068.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-068.gif
new file mode 100644
index 00000000..3550e978
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-068.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-134.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-134.gif
new file mode 100644
index 00000000..954ab614
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-134.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-211.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-211.gif
new file mode 100644
index 00000000..596174d7
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-211.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-234.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-234.gif
new file mode 100644
index 00000000..5aba636b
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-234.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-001.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-001.gif
new file mode 100644
index 00000000..7896ff1f
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-001.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-002.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-002.gif
new file mode 100644
index 00000000..89da6441
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-002.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-005.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-005.gif
new file mode 100644
index 00000000..b7887630
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-005.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-012.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-012.gif
new file mode 100644
index 00000000..f6697d02
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-012.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-056.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-056.gif
new file mode 100644
index 00000000..2b2496a4
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-056.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-059.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-059.gif
new file mode 100644
index 00000000..f2188656
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-059.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-060.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-060.gif
new file mode 100644
index 00000000..aa8f7bd3
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-060.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-069.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-069.gif
new file mode 100644
index 00000000..473212e4
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-069.gif
Binary files differ
diff --git a/wqflask/wqflask/templates/collections/add.html b/wqflask/wqflask/templates/collections/add.html
index 47b87d73..d45aa015 100644
--- a/wqflask/wqflask/templates/collections/add.html
+++ b/wqflask/wqflask/templates/collections/add.html
@@ -25,7 +25,7 @@
<select name="existing_collection" class="form-control">
{% for col in collections %}
- <option value="{{ col.id }}">{{ col.name }}</option>
+ <option value="{{ col.id }}:{{ col.name }}">{{ col.name }}</option>
{% endfor %}
</select>
<br />
diff --git a/wqflask/wqflask/templates/ctl_setup.html b/wqflask/wqflask/templates/ctl_setup.html
index 9c0d7bea..51553322 100644
--- a/wqflask/wqflask/templates/ctl_setup.html
+++ b/wqflask/wqflask/templates/ctl_setup.html
@@ -1,65 +1,70 @@
{% extends "base.html" %}
-{% block title %}WCGNA analysis{% endblock %}
+{% block title %}CTL analysis{% endblock %}
{% block content %} <!-- Start of body -->
<div class="container">
+ {% if request.form['trait_list'].split(",")|length < 2 %}
+ <div class="alert alert-danger" role="alert">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <span class="sr-only">Error:</span>
+ <h2>Too few traits as input</h2>
+ Please make sure you select enough traits to perform CTL. Your collection needs to contain at least 2 different traits. You provided {{request.form['trait_list'].split(',')|length}} traits as input.
+ </div>
+ {% else %}
<h1>CTL analysis parameters</h1>
- {{(request.form['trait_list'].split(',')|length -1)}} phenotypes as input
+ {{(request.form['trait_list'].split(',')|length -1)}} 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']}}">
+ <form action="/ctl_results" method="post" class="form-horizontal">
+ <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}">
+ <div class="dropdown">
+ <label for="Strategy">Strategy</label>
+ <div class="col-sm-10">
+ <select name="strategy" id="strategy">
+ <option value="Exact">Exact</option>
+ <option value="Full">Full</option>
+ <option value="Pairwise">Pairwise</option>
+ </select>
+ </div>
+ </div>
- <div class="dropdown">
- <label for="Strategy">Strategy</label>
- <div class="col-sm-10">
- <select name="strategy" id="strategy">
- <option value="Exact">Exact</option>
- <option value="Full">Full</option>
- <option value="Pairwise">Pairwise</option>
- </select>
- </div>
- </div>
+ <div class="dropdown">
+ <label for="Permutations">Number of permutation (Used when strategy is Full or Pairwise)</label>
+ <div class="col-sm-10">
+ <select name="nperm" id="nperm">
+ <option value="100">100</option>
+ <option value="1000" selected="selected">1000</option>
+ <option value="10000">10000</option>
+ </select>
+ </div>
+ </div>
- <div class="dropdown">
- <label for="Permutations">Number of permutation (Used when strategy is Full or Pairwise)</label>
- <div class="col-sm-10">
- <select name="nperm" id="nperm">
- <option value="100">100</option>
- <option value="1000" selected="selected">1000</option>
- <option value="10000">10000</option>
- </select>
- </div>
- </div>
-
- <div class="dropdown">
- <label for="Coefficient">Type of correlation coefficient</label>
- <div class="col-sm-10">
- <select name="parametric" id="parametric">
- <option value="False">Spearman</option>
- <option value="True">Pearson</option>
- </select>
- </div>
- </div>
-
-
- <div class="dropdown">
- <label for="Significance">Significance level</label>
- <div class="col-sm-10">
- <select name="significance" id="significance">
- <option value="0.1">0.1</option>
- <option value="0.05" selected="selected">0.05</option>
- <option value="0.001">0.001</option>
- </select>
- </div>
- </div>
- <br>
- <div class="form-group">
- <div class="col-sm-10">
- <input type="submit" class="btn btn-primary" value="Run CTL using these settings" />
- </div>
- </div>
+ <div class="dropdown">
+ <label for="Coefficient">Type of correlation coefficient</label>
+ <div class="col-sm-10">
+ <select name="parametric" id="parametric">
+ <option value="False">Spearman</option>
+ <option value="True">Pearson</option>
+ </select>
+ </div>
+ </div>
+ <div class="dropdown">
+ <label for="Significance">Significance level</label>
+ <div class="col-sm-10">
+ <select name="significance" id="significance">
+ <option value="0.1">0.1</option>
+ <option value="0.05" selected="selected">0.05</option>
+ <option value="0.001">0.001</option>
+ </select>
+ </div>
+ </div>
+ <br>
+ <div class="form-group">
+ <div class="col-sm-10">
+ <input type="submit" class="btn btn-primary" value="Run CTL using these settings" />
+ </div>
+ </div>
</form>
-
+{% endif %}
</div>
{% endblock %}
diff --git a/wqflask/wqflask/templates/error.html b/wqflask/wqflask/templates/error.html
new file mode 100644
index 00000000..7ab2bf2f
--- /dev/null
+++ b/wqflask/wqflask/templates/error.html
@@ -0,0 +1,61 @@
+{% extends "base.html" %}
+{% block title %}Error: {{message}}{% endblock %}
+{% block content %}
+<!-- Start of body -->
+
+<div class="col-md-8">
+<div class="form-group has-error">
+ <div class="control-label" for="inputError1">
+
+ <img src="/static/gif/error/{{ error_image }}">
+
+ <h1>ERROR</h1>
+
+ <p>
+ This error is not what we wanted to see. Unfortunately errors
+ are part of all software systems and we need to resolve this
+ together.
+ </p>
+ <p>
+ <b>It is important to report this ERROR so we can fix it for everyone</b>.
+ </p>
+
+ <p>
+ Report to the GeneNetwork team by recording the steps you take
+ to reproduce this ERROR. Next to those steps, copy-paste below
+ stack trace, either as
+ a <a href="https://github.com/genenetwork/genenetwork2/issues/new">new
+ issue</a> or E-mail this full page to one of the developers
+ directly.
+ </p>
+ </div>
+
+ <p>
+ (GeneNetwork error: {{message[:128]}})
+ </p>
+
+ <pre>
+ {{ stack[0] }}
+ {{ message }} (error)
+ {{ stack[-3] }}
+ {{ stack[-2] }}
+ </pre>
+
+ <p>
+ To check if this already a known issue, search the
+ <a href="https://github.com/genenetwork/genenetwork2/issues">issue
+ tracker</a>.
+ </p>
+
+ <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 }}
+ {% endfor %}
+ </pre>
+ </div>
+</div>
+</div>
+
+
+{% endblock %}
diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html
index 3d9c2521..0f293942 100644
--- a/wqflask/wqflask/templates/show_trait_mapping_tools.html
+++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html
@@ -2,7 +2,7 @@
{% if (use_pylmm_rqtl and dataset.group.species != "human") or use_plink_gemma %}
<div class="col-xs-4">
<div class="tabbable"> <!-- Only required for left/right tabs -->
-
+
<ul class="nav nav-pills">
{% if use_pylmm_rqtl and not use_plink_gemma and dataset.group.species != "human" %}
<li class="active">
@@ -61,7 +61,7 @@
No
</label>
</div>
- </div>
+ </div>
<!--
<div class="mapping_method_fields form-group">
@@ -75,7 +75,7 @@
<div class="mapping_method_fields form-group">
<label style="text-align:left;" class="col-xs-12 control-label">Display Additive Effect</label>
- <div class="col-xs-12 controls" id="display_additive_effect">
+ <div class="col-xs-12 controls" id="display_additive_effect">
<label class="radio-inline">
<input type="radio" name="display_additive" id="display_additive" value="yes" checked="">
Yes
@@ -90,8 +90,8 @@
<div class="mapping_method_fields form-group">
- <label style="text-align:left;" class="col-xs-12 control-label">Marker Regr.</label>
- <div class="col-xs-12 controls">
+ <label style="text-align:left;" class="col-xs-3 control-label">Marker<br>Regression</label>
+ <div style="margin-left: 20px;" class="col-xs-4 controls">
<label class="radio-inline">
<input type="radio" name="manhattan_plot_reaper" value="True">
Yes
@@ -146,7 +146,7 @@
<div class="mapping_method_fields form-group">
<label style="text-align:left;" class="col-xs-12 control-label">Manhattan Plot</label>
- <div class="col-xs-12 controls">
+ <div class="col-xs-12 controls">
<label class="radio-inline">
<input type="radio" name="manhattan_plot_pylmm" value="True">
Yes
@@ -167,7 +167,7 @@
</div>
</div>
<div class="tab-pane" id="rqtl_geno">
-
+
<div style="margin-top: 20px" class="form-horizontal">
<div class="mapping_method_fields form-group">
<label for="mapping_permutations" class="col-xs-3 control-label">Permutations</label>
@@ -226,7 +226,7 @@
<div class="mapping_method_fields form-group">
<label style="text-align:left;" class="col-xs-12 control-label">Pair Scan</label>
- <div class="col-xs-12 controls">
+ <div class="col-xs-12 controls">
<label class="radio-inline">
<input type="radio" name="pair_scan" value="true">
Yes
@@ -240,7 +240,7 @@
<div class="mapping_method_fields form-group">
<label style="text-align:left;" class="col-xs-12 control-label">Manhattan Plot</label>
- <div class="col-xs-12 controls">
+ <div class="col-xs-12 controls">
<label class="radio-inline">
<input type="radio" name="manhattan_plot_rqtl" value="True">
Yes
@@ -272,7 +272,7 @@
</div>
</div>
</div>
-
+
<div class="form-group">
<label for="plink_compute" class="col-xs-1 control-label"></label>
<div style="margin-left:20px;" class="col-xs-4 controls">
@@ -282,7 +282,7 @@
</div>
</div>
</div>
-
+
<div class="tab-pane" id="gemma">
<div style="padding: 20px" class="form-horizontal">
<div class="mapping_method_fields form-group">
@@ -292,7 +292,7 @@
</div>
</div>
</div>
-
+
<div class="form-group">
<label for="gemma_compute" class="col-xs-1 control-label"></label>
<div style="margin-left:20px;" class="col-xs-4 controls">
@@ -301,12 +301,12 @@
</button>
</div>
</div>
- </div>
+ </div>
{% endif %}
</div>
</div>
</div>
- <div class="col-xs-6">
+ <div class="col-xs-6">
<dl>
<dt>Interval Mapping</dt>
<dd>Interval mapping is a process in which the statistical significance of a hypothetical QTL is evaluated at regular points across a chromosome, even in the absence of explicit genotype data at those points.</dd>
diff --git a/wqflask/wqflask/templates/wgcna_setup.html b/wqflask/wqflask/templates/wgcna_setup.html
index b4a5730d..c5461497 100644
--- a/wqflask/wqflask/templates/wgcna_setup.html
+++ b/wqflask/wqflask/templates/wgcna_setup.html
@@ -4,49 +4,46 @@
{% block content %} <!-- Start of body -->
<h1> WGCNA analysis parameters</h1>
<div class="container">
- {% if request.form['trait_list'].split(",")|length <= 4 %}
-
- <div class="alert alert-danger" role="alert">
- <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
- <span class="sr-only">Error:</span>
- <h2>
- Too few phenotypes as input
- </h2>
- Please make sure you select enough phenotypes / genes to perform WGCNA, your collection needs to contain at least 4 different phenotypes. You provided {{request.form['trait_list'].split(',')|length}} phenotypes as input
- </div>
- {% else %}
- <form action="/wgcna_results" method="post" class="form-horizontal">
- <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}">
- <div class="form-group">
- <label for="SoftThresholds"> Soft threshold: </label>
- <div class="col-sm-10">
- <input type="text" class="form-inline" name="SoftThresholds" id="SoftThresholds" value="1,2,3,4,5,6,7,8,9">
- </div>
- </div>
- <div class="form-group">
- <label for="MinModuleSize"> Minimum module size: </label>
- <div class="col-sm-10">
- <input type="text" class="form-inline" name="MinModuleSize" id="MinModuleSize" value="30">
- </div>
- </div>
- <div class="form-group">
- <label for="TOMtype"> TOMtype: </label>
- <div class="col-sm-10">
- <input type="text" class="form-inline" name="TOMtype" id="TOMtype" value="unsigned">
- </div>
- </div>
- <div class="form-group">
- <label for="mergeCutHeight"> mergeCutHeight: </label>
- <div class="col-sm-10">
- <input type="text" class="form-inline" name="mergeCutHeight" id="mergeCutHeight" value="0.25">
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-10">
- <input type="submit" class="btn btn-primary" value="Run WGCNA using these settings" />
- </div>
- </div>
- </form>
- {% endif %}
+ {% if request.form['trait_list'].split(",")|length < 4 %}
+ <div class="alert alert-danger" role="alert">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <span class="sr-only">Error:</span>
+ <h2>Too few phenotypes as input</h2>
+ Please make sure you select enough phenotypes / genes to perform WGCNA. Your collection needs to contain at least 4 different phenotypes. You provided {{request.form['trait_list'].split(',')|length}} phenotypes as input.
+ </div>
+ {% else %}
+ <form action="/wgcna_results" method="post" class="form-horizontal">
+ <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}">
+ <div class="form-group">
+ <label for="SoftThresholds"> Soft threshold: </label>
+ <div class="col-sm-10">
+ <input type="text" class="form-inline" name="SoftThresholds" id="SoftThresholds" value="1,2,3,4,5,6,7,8,9">
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="MinModuleSize"> Minimum module size: </label>
+ <div class="col-sm-10">
+ <input type="text" class="form-inline" name="MinModuleSize" id="MinModuleSize" value="30">
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="TOMtype"> TOMtype: </label>
+ <div class="col-sm-10">
+ <input type="text" class="form-inline" name="TOMtype" id="TOMtype" value="unsigned">
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="mergeCutHeight"> mergeCutHeight: </label>
+ <div class="col-sm-10">
+ <input type="text" class="form-inline" name="mergeCutHeight" id="mergeCutHeight" value="0.25">
+ </div>
+ </div>
+ <div class="form-group">
+ <div class="col-sm-10">
+ <input type="submit" class="btn btn-primary" value="Run WGCNA using these settings" />
+ </div>
+ </div>
+ </form>
+ {% endif %}
</div>
{% endblock %}
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 7061e0f1..33fab84d 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -4,6 +4,11 @@
from __future__ import absolute_import, division, print_function
+import traceback # for error page
+import os # for error gifs
+import random # for random error gif
+import datetime # for errors
+import time # for errors
import sys
import csv
import xlsxwriter
@@ -26,7 +31,7 @@ import base64
import array
import sqlalchemy
from wqflask import app
-from flask import g, Response, request, render_template, send_from_directory, jsonify, redirect
+from flask import g, Response, request, make_response, render_template, send_from_directory, jsonify, redirect
from wqflask import search_results
from wqflask import gsearch
from wqflask import update_search_results
@@ -58,6 +63,8 @@ from wqflask import user_manager
from wqflask import collect
from wqflask.database import db_session
+import werkzeug
+
import utility.logger
logger = utility.logger.getLogger(__name__ )
@@ -82,6 +89,31 @@ def shutdown_session(exception=None):
# from wqflask import tracer
# tracer.turn_on()
+@app.errorhandler(Exception)
+def handle_bad_request(e):
+ err_msg = str(e)
+ logger.error(err_msg)
+ logger.error(request.url)
+ # get the stack trace and send it to the logger
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ logger.error(traceback.format_exc())
+ now = datetime.datetime.utcnow()
+ time_str = now.strftime('%l:%M%p UTC %b %d, %Y')
+ formatted_lines = [request.url + " ("+time_str+")"]+traceback.format_exc().splitlines()
+
+ # Handle random animations
+ # Use a cookie to have one animation on refresh
+ animation = request.cookies.get(err_msg[:32])
+ if not animation:
+ 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))
+
+ # logger.error("Set cookie %s with %s" % (err_msg, animation))
+ resp.set_cookie(err_msg[:32],animation)
+ return resp
+
@app.route("/")
def index_page():
logger.info("Sending index_page")