diff --git a/.hgignore b/.hgignore
index 59c2b3ce68b..72ceb2ad345 100644
--- a/.hgignore
+++ b/.hgignore
@@ -36,6 +36,7 @@ shed_tool_conf.xml
tool_data_table_conf.xml
tool_sheds_conf.xml
integrated_tool_panel.xml
+openid_conf.xml
static/welcome.html.*
static/welcome.html
@@ -63,8 +64,12 @@ run_functional_tests.html
# Jars
tool-data/shared/jars/
+# CSS build artifacts.
+*/variables.less
+static/june_2007_style/blue/base_sprites.less
+
# Misc
*.orig
.DS_Store
*.rej
-*~
+*~
\ No newline at end of file
diff --git a/community_wsgi.ini.sample b/community_wsgi.ini.sample
index 7dff5b2da3d..4e2dbd712e0 100644
--- a/community_wsgi.ini.sample
+++ b/community_wsgi.ini.sample
@@ -4,7 +4,12 @@
use = egg:Paste#http
port = 9009
+
+# The address on which to listen. By default, only listen to localhost (the tool shed will not
+# be accessible over the network). Use '0.0.0.0' to listen on all available network interfaces.
+#host = 0.0.0.0
host = 127.0.0.1
+
use_threadpool = true
threadpool_workers = 10
diff --git a/contrib/universe_merger.py b/contrib/universe_merger.py
new file mode 100644
index 00000000000..7790f970fbe
--- /dev/null
+++ b/contrib/universe_merger.py
@@ -0,0 +1,87 @@
+#! /usr/bin/env python
+'''
+universe_merger.py
+
+Created by Anne Pajon on 31 Jan 2012
+
+Copyright (c) 2012 Cancer Research UK - Cambridge Research Institute.
+
+This source file is licensed under the Academic Free License version
+3.0 available at http://www.opensource.org/licenses/AFL-3.0.
+
+Permission is hereby granted to reproduce, translate, adapt, alter,
+transform, modify, or arrange this source file (the "Original Work");
+to distribute or communicate copies of it under any license of your
+choice that does not contradict the terms and conditions; to perform
+or display the Original Work publicly.
+
+THE ORIGINAL WORK IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS
+AND WITHOUT WARRANTY, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT
+LIMITATION, THE WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF
+THE ORIGINAL WORK IS WITH YOU.
+
+Script for merging specific local Galaxy config universe_wsgi.ini.cri with default Galaxy universe_wsgi.ini.sample
+'''
+import ConfigParser
+import sys
+import optparse
+import logging
+
+def main():
+ # logging configuration
+ logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
+
+ # get the options
+ parser = optparse.OptionParser()
+ parser.add_option("-s", "--sample", dest="sample", action="store", help="path to Galaxy universe_wsgi.ini.sample file")
+ parser.add_option("-c", "--config", dest="config", action="store", help="path to your own universe_wsgi.ini file")
+ parser.add_option("-o", "--output", dest="output", action="store", help="path to the new merged universe_wsgi.ini.new file")
+ (options, args) = parser.parse_args()
+
+ for option in ['sample', 'config']:
+ if getattr(options, option) == None:
+ print "Please supply a --%s parameter.\n" % (option)
+ parser.print_help()
+ sys.exit()
+
+ config_sample = ConfigParser.RawConfigParser()
+ config_sample.read(options.sample)
+ config_sample_content = open(options.sample, 'r').read()
+
+ config = ConfigParser.RawConfigParser()
+ config.read(options.config)
+
+ logging.info("Merging your own config file %s into the sample one %s." % (options.config, options.sample))
+ logging.info("---------- DIFFERENCE ANALYSIS BEGIN ----------")
+ for section in config.sections():
+ if not config_sample.has_section(section):
+ logging.warning("-MISSING- section [%s] not found in sample file. It will be ignored." % section)
+ else:
+ for (name, value) in config.items(section):
+ if not config_sample.has_option(section, name):
+ if not "#%s" % name in config_sample_content:
+ logging.warning("-MISSING- section [%s] option '%s' not found in sample file. It will be ignored." % (section, name))
+ else:
+ logging.info("-notset- section [%s] option '%s' not set in sample file. It will be added." % (section, name))
+ config_sample.set(section, name, value)
+ else:
+ if not config_sample.get(section, name) == value:
+ logging.info("- diff - section [%s] option '%s' has different value ('%s':'%s'). It will be modified." % (section, name, config_sample.get(section, name), value))
+ config_sample.set(section, name, value)
+ logging.info("---------- DIFFERENCE ANALYSIS END ----------")
+
+ if options.output:
+ outputfile = open(options.output, 'w')
+ config_sample.write(outputfile)
+ outputfile.close()
+ else:
+ #print "----------"
+ #config_sample.write(sys.stdout)
+ #print "----------"
+ logging.info("use -o OUTPUT to write the merged configuration into a file.")
+
+ logging.info("read Galaxy universe_wsgi.ini.sample for detailed information.")
+
+if __name__ == '__main__':
+ main()
diff --git a/datatypes_conf.xml.sample b/datatypes_conf.xml.sample
index b261594ef0c..74d3b3ba1c5 100644
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -10,6 +10,7 @@
+
@@ -19,6 +20,7 @@
+
@@ -31,9 +33,11 @@
+
+
@@ -81,7 +85,11 @@
-
+
+
+
+
+
@@ -170,13 +178,13 @@
-
-
+
+
@@ -268,7 +276,6 @@
-
diff --git a/display_applications/igb/bam.xml b/display_applications/igb/bam.xml
new file mode 100644
index 00000000000..2401a8d1de3
--- /dev/null
+++ b/display_applications/igb/bam.xml
@@ -0,0 +1,58 @@
+
+
+ http://localhost:7085/UnibrowControl?version=${bam_file.dbkey}&feature_url_0=${bam_file.url}&sym_name_0=${thenicename}&sym_method_0=${bam_file.url}&query_url=${bam_file.url}&server_url=galaxy
+
+
+ #import re
+ #set nm=$bam_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+
+
+
+ $jnlp.url
+
+
+ #import re
+ #set nm=$bam_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="6.0+" version="" codebase="http://www.bioviz.org/igb/releases/current/" >
+ <information>
+ <title>IGB</title>
+ <vendor>Genoviz Project</vendor>
+ <homepage href="http://genoviz.sourceforge.net/" />
+ <description>Integrated Genome Browser</description>
+ <icon href="igb.gif"/>
+ <offline-allowed/>
+ <shortcut online="true">
+ <desktop/>
+ <menu submenu="IGB" />
+ </shortcut>
+ </information>
+ <security>
+ <all-permissions/>
+ </security>
+ <resources>
+ <java version="1.6+" initial-heap-size="32m" max-heap-size="1024m"/>
+ <jar href="igb_exe.jar" main="true" />
+ <jar href="igb-i18n.jar" />
+ <property name="apple.laf.useScreenMenuBar" value="true" />
+ <property name="http.agent" value="IGB (Webstart)" />
+ </resources>
+ <application-desc main-class="com.affymetrix.main.Main">
+ <argument>-prefs</argument>
+ <argument>http://www.bioviz.org/igb/releases/current/igb_prefs.xml</argument>
+ <argument>-href</argument>
+ <argument>http://localhost:7085/UnibrowControl?version=${bam_file.dbkey}&feature_url_0=${bam_file.url}&sym_name_0=${thenicename}&sym_method_0=${bam_file.url}&query_url=${bam_file.url}&server_url=galaxy </argument>
+ </application-desc>
+</jnlp>
+
+
+
diff --git a/display_applications/igb/bb.xml b/display_applications/igb/bb.xml
new file mode 100644
index 00000000000..8a58054bc88
--- /dev/null
+++ b/display_applications/igb/bb.xml
@@ -0,0 +1,58 @@
+
+
+
+ http://localhost:7085/UnibrowControl?version=${bigbed_file.dbkey}&loadresidues=false&feature_url_0=${bigbed_file.url}&sym_name_0=${thenicename}&sym_method_0=${bigbed_file.url}&query_url=${bigbed_file.url}&server_url=galaxy
+
+
+ #import re
+ #set nm=$bigbed_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+
+
+ $jnlp.url
+
+
+ #import re
+ #set nm=$bigbed_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="6.0+" version="" codebase="http://www.bioviz.org/igb/releases/current/" >
+ <information>
+ <title>IGB</title>
+ <vendor>Genoviz Project</vendor>
+ <homepage href="http://genoviz.sourceforge.net/" />
+ <description>Integrated Genome Browser</description>
+ <icon href="igb.gif"/>
+ <offline-allowed/>
+ <shortcut online="true">
+ <desktop/>
+ <menu submenu="IGB" />
+ </shortcut>
+ </information>
+ <security>
+ <all-permissions/>
+ </security>
+ <resources>
+ <java version="1.6+" initial-heap-size="32m" max-heap-size="1024m"/>
+ <jar href="igb_exe.jar" main="true" />
+ <jar href="igb-i18n.jar" />
+ <property name="apple.laf.useScreenMenuBar" value="true" />
+ <property name="http.agent" value="IGB (Webstart)" />
+ </resources>
+ <application-desc main-class="com.affymetrix.main.Main">
+ <argument>-prefs</argument>
+ <argument>http://www.bioviz.org/igb/releases/current/igb_prefs.xml</argument>
+ <argument>-href</argument>
+ <argument>http://localhost:7085/UnibrowControl?version=${bigbed_file.dbkey}&loadresidues=false&feature_url_0=${bigbed_file.url}&sym_name_0=${thenicename}&sym_method_0=${bigbed_file.url}&query_url=${bigbed_file.url}&server_url=galaxy </argument>
+ </application-desc>
+</jnlp>
+
+
+
+
diff --git a/display_applications/igb/bed.xml b/display_applications/igb/bed.xml
new file mode 100644
index 00000000000..ebb20a6b6f4
--- /dev/null
+++ b/display_applications/igb/bed.xml
@@ -0,0 +1,73 @@
+
+
+
+ http://localhost:7085/UnibrowControl?version=${bed_file.dbkey}&${position}&loadresidues=false&feature_url_0=${bed_file.url}&sym_name_0=${thenicename}&sym_method_0=${bed_file.url}&query_url=${bed_file.url}&server_url=galaxy
+
+
+ #import re
+ #set nm=$bed_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+ #set chrom, start, end = $bed_file.datatype.get_estimated_display_viewport( $bed_file )
+ #if $chrom is not None:
+ seqid=${chrom}&start=${start}&end=${int(end) + 1}
+ #else:
+ seqid=&start=&end=
+ #end if
+
+
+
+
+ $jnlp.url
+
+
+ #import re
+ #set nm=$bed_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+ #set chrom, start, end = $bed_file.datatype.get_estimated_display_viewport( $bed_file )
+ #if $chrom is not None:
+ seqid=${chrom}&start=${start}&end=${int(end) + 1}
+ #else:
+ seqid=&start=&end=
+ #end if
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="6.0+" version="" codebase="http://www.bioviz.org/igb/releases/current/" >
+ <information>
+ <title>IGB</title>
+ <vendor>Genoviz Project</vendor>
+ <homepage href="http://genoviz.sourceforge.net/" />
+ <description>Integrated Genome Browser</description>
+ <icon href="igb.gif"/>
+ <offline-allowed/>
+ <shortcut online="true">
+ <desktop/>
+ <menu submenu="IGB" />
+ </shortcut>
+ </information>
+ <security>
+ <all-permissions/>
+ </security>
+ <resources>
+ <java version="1.6+" initial-heap-size="32m" max-heap-size="1024m"/>
+ <jar href="igb_exe.jar" main="true" />
+ <jar href="igb-i18n.jar" />
+ <property name="apple.laf.useScreenMenuBar" value="true" />
+ <property name="http.agent" value="IGB (Webstart)" />
+ </resources>
+ <application-desc main-class="com.affymetrix.main.Main">
+ <argument>-prefs</argument>
+ <argument>http://www.bioviz.org/igb/releases/current/igb_prefs.xml</argument>
+ <argument>-href</argument>
+ <argument>http://localhost:7085/UnibrowControl?version=${bed_file.dbkey}&${position}&loadresidues=false&feature_url_0=${bed_file.url}&sym_name_0=${thenicename}&sym_method_0=${bed_file.url}&query_url=${bed_file.url}&server_url=galaxy </argument>
+ </application-desc>
+</jnlp>
+
+
+
diff --git a/display_applications/igb/bigwig.xml b/display_applications/igb/bigwig.xml
new file mode 100644
index 00000000000..ebd451fac86
--- /dev/null
+++ b/display_applications/igb/bigwig.xml
@@ -0,0 +1,65 @@
+
+
+
+ http://localhost:7085/UnibrowControl?version=${bigwig_file.dbkey}&loadresidues=false&feature_url_0=${bigwig_file.url}&sym_name_0=${thenicename}&sym_method_0=${bigwig_file.url}&query_url=${bigwig_file.url}&server_url=galaxy
+
+
+ #import re
+ #set nm=$bigwig_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+
+
+
+ $jnlp.url
+
+
+ #import re
+ #set nm=$bigwig_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="6.0+" version="" codebase="http://www.bioviz.org/igb/releases/current/" >
+ <information>
+ <title>IGB</title>
+ <vendor>Genoviz Project</vendor>
+ <homepage href="http://genoviz.sourceforge.net/" />
+ <description>Integrated Genome Browser</description>
+ <icon href="igb.gif"/>
+ <offline-allowed/>
+ <shortcut online="true">
+ <desktop/>
+ <menu submenu="IGB" />
+ </shortcut>
+ </information>
+ <security>
+ <all-permissions/>
+ </security>
+ <resources>
+ <java version="1.6+" initial-heap-size="32m" max-heap-size="1024m"/>
+ <jar href="igb_exe.jar" main="true" />
+ <jar href="igb-i18n.jar" />
+ <property name="apple.laf.useScreenMenuBar" value="true" />
+ <property name="http.agent" value="IGB (Webstart)" />
+ </resources>
+ <application-desc main-class="com.affymetrix.main.Main">
+ <argument>-prefs</argument>
+ <argument>http://www.bioviz.org/igb/releases/current/igb_prefs.xml</argument>
+ <argument>-href</argument>
+ <argument>http://localhost:7085/UnibrowControl?version=${bigwig_file.dbkey}&loadresidues=false&feature_url_0=${bigwig_file.url}&sym_name_0=${thenicename}&sym_method_0=${bigwig_file.url}&query_url=${bigwig_file.url}&server_url=galaxy </argument>
+ </application-desc>
+</jnlp>
+
+
+
diff --git a/display_applications/igb/wig.xml b/display_applications/igb/wig.xml
new file mode 100644
index 00000000000..ef6f569b4bd
--- /dev/null
+++ b/display_applications/igb/wig.xml
@@ -0,0 +1,74 @@
+
+
+
+ http://localhost:7085/UnibrowControl?version=${wig_file.dbkey}&${position}&loadresidues=false&feature_url_0=${wig_file.url}&sym_name_0=${thenicename}&sym_method_0=${wig_file.url}&query_url=${wig_file.url}&server_url=galaxy
+
+
+ #import re
+ #set nm=$wig_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+ #set chrom, start, end = $wig_file.datatype.get_estimated_display_viewport( $wig_file )
+ #if $chrom is not None:
+ seqid=${chrom}&start=${start}&end=${int(end) + 1}
+ #else:
+ seqid=&start=&end=
+ #end if
+
+
+
+
+ $jnlp.url
+
+
+ #import re
+ #set nm=$wig_file_for_name.name
+ ${re.sub('\W',"_",nm)}
+
+
+
+ #set chrom, start, end = $wig_file.datatype.get_estimated_display_viewport( $wig_file )
+ #if $chrom is not None:
+ seqid=${chrom}&start=${start}&end=${int(end) + 1}
+ #else:
+ seqid=&start=&end=
+ #end if
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="6.0+" version="" codebase="http://www.bioviz.org/igb/releases/current/" >
+ <information>
+ <title>IGB</title>
+ <vendor>Genoviz Project</vendor>
+ <homepage href="http://genoviz.sourceforge.net/" />
+ <description>Integrated Genome Browser</description>
+ <icon href="igb.gif"/>
+ <offline-allowed/>
+ <shortcut online="true">
+ <desktop/>
+ <menu submenu="IGB" />
+ </shortcut>
+ </information>
+ <security>
+ <all-permissions/>
+ </security>
+ <resources>
+ <java version="1.6+" initial-heap-size="32m" max-heap-size="1024m"/>
+ <jar href="igb_exe.jar" main="true" />
+ <jar href="igb-i18n.jar" />
+ <property name="apple.laf.useScreenMenuBar" value="true" />
+ <property name="http.agent" value="IGB (Webstart)" />
+ </resources>
+ <application-desc main-class="com.affymetrix.main.Main">
+ <argument>-prefs</argument>
+ <argument>http://www.bioviz.org/igb/releases/current/igb_prefs.xml</argument>
+ <argument>-href</argument>
+ <argument>http://localhost:7085/UnibrowControl?version=${wig_file.dbkey}&${position}&loadresidues=false&feature_url_0=${wig_file.url}&sym_name_0=${thenicename}&sym_method_0=${wig_file.url}&query_url=${wig_file.url}&server_url=galaxy </argument>
+ </application-desc>
+</jnlp>
+
+
+
+
diff --git a/dist-eggs.ini b/dist-eggs.ini
index 969050fa676..08b43ff6bef 100644
--- a/dist-eggs.ini
+++ b/dist-eggs.ini
@@ -7,105 +7,82 @@
;
[hosts]
-py2.4-linux-i686-ucs2 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs2/bin/python2.4
-py2.4-linux-i686-ucs4 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs4/bin/python2.4
py2.5-linux-i686-ucs2 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs2/bin/python2.5
py2.5-linux-i686-ucs4 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs4/bin/python2.5
py2.6-linux-i686-ucs2 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs2/bin/python2.6
py2.6-linux-i686-ucs4 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs4/bin/python2.6
py2.7-linux-i686-ucs2 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs2/bin/python2.7
py2.7-linux-i686-ucs4 = stegmaier.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-i686-ucs4/bin/python2.7
-py2.4-linux-x86_64-ucs2 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs2/bin/python2.4
-py2.4-linux-x86_64-ucs4 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.4
py2.5-linux-x86_64-ucs2 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs2/bin/python2.5
py2.5-linux-x86_64-ucs4 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.5
py2.6-linux-x86_64-ucs2 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs2/bin/python2.6
py2.6-linux-x86_64-ucs4 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.6
py2.7-linux-x86_64-ucs2 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs2/bin/python2.7
py2.7-linux-x86_64-ucs4 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.7
-py2.4-macosx-10.3-fat-ucs2 = weyerbacher.bx.psu.edu /usr/local/bin/python2.4
-py2.5-macosx-10.3-fat-ucs2 = weyerbacher.bx.psu.edu /usr/local/bin/python2.5
-py2.6-macosx-10.3-fat-ucs2 = weyerbacher.bx.psu.edu /usr/local/bin/python2.6
-py2.7-macosx-10.3-fat-ucs2 = weyerbacher.bx.psu.edu /usr/local/bin/python2.7
+py2.5-macosx-10.3-fat-ucs2 = weyerbacher.bx.psu.edu /Library/Frameworks/Python.framework/Versions/2.5/bin/python2.5
+py2.6-macosx-10.3-fat-ucs2 = weyerbacher.bx.psu.edu /Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6
+py2.7-macosx-10.3-fat-ucs2 = weyerbacher.bx.psu.edu /Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
py2.6-macosx-10.6-universal-ucs2 = lion.bx.psu.edu /usr/bin/python2.6
py2.7-macosx-10.6-intel-ucs2 = lion.bx.psu.edu /usr/local/bin/python2.7
-py2.4-solaris-2.10-i86pc_32-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_32-ucs2/bin/python2.4
py2.5-solaris-2.10-i86pc_32-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_32-ucs2/bin/python2.5
py2.6-solaris-2.10-i86pc_32-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_32-ucs2/bin/python2.6
py2.7-solaris-2.10-i86pc_32-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_32-ucs2/bin/python2.7
-py2.4-solaris-2.10-i86pc_64-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_64-ucs2/bin/python2.4
py2.5-solaris-2.10-i86pc_64-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_64-ucs2/bin/python2.5
py2.6-solaris-2.10-i86pc_64-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_64-ucs2/bin/python2.6
py2.7-solaris-2.10-i86pc_64-ucs2 = thumper.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-i86pc_64-ucs2/bin/python2.7
-py2.4-solaris-2.10-sun4u_32-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_32-ucs2/bin/python2.4
py2.5-solaris-2.10-sun4u_32-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_32-ucs2/bin/python2.5
py2.6-solaris-2.10-sun4u_32-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_32-ucs2/bin/python2.6
py2.7-solaris-2.10-sun4u_32-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_32-ucs2/bin/python2.7
-py2.4-solaris-2.10-sun4u_64-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_64-ucs2/bin/python2.4
-py2.5-solaris-2.10-sun4u_64-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_64-ucs2/bin/python2.5
-py2.6-solaris-2.10-sun4u_64-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_64-ucs2/bin/python2.6
-py2.7-solaris-2.10-sun4u_64-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.8-sun4u_64-ucs2/bin/python2.7
+py2.5-solaris-2.10-sun4u_64-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-sun4u_64-ucs2/bin/python2.5
+py2.6-solaris-2.10-sun4u_64-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-sun4u_64-ucs2/bin/python2.6
+py2.7-solaris-2.10-sun4u_64-ucs2 = early.bx.psu.edu /afs/bx.psu.edu/project/pythons/solaris-2.10-sun4u_64-ucs2/bin/python2.7
; these hosts are used to build eggs with no C extensions
-py2.4 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.4
py2.5 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.5
py2.6 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.6
py2.7 = straub.bx.psu.edu /afs/bx.psu.edu/project/pythons/linux-x86_64-ucs4/bin/python2.7
[groups]
-py2.4-linux-i686 = py2.4-linux-i686-ucs2 py2.4-linux-i686-ucs4
-py2.4-linux-x86_64 = py2.4-linux-x86_64-ucs2 py2.4-linux-x86_64-ucs4
py2.5-linux-i686 = py2.5-linux-i686-ucs2 py2.5-linux-i686-ucs4
py2.5-linux-x86_64 = py2.5-linux-x86_64-ucs2 py2.5-linux-x86_64-ucs4
py2.6-linux-i686 = py2.6-linux-i686-ucs2 py2.6-linux-i686-ucs4
py2.6-linux-x86_64 = py2.6-linux-x86_64-ucs2 py2.6-linux-x86_64-ucs4
py2.7-linux-i686 = py2.7-linux-i686-ucs2 py2.7-linux-i686-ucs4
py2.7-linux-x86_64 = py2.7-linux-x86_64-ucs2 py2.7-linux-x86_64-ucs4
-py2.4-linux = py2.4-linux-i686 py2.4-linux-x86_64
py2.5-linux = py2.5-linux-i686 py2.5-linux-x86_64
py2.6-linux = py2.6-linux-i686 py2.6-linux-x86_64
py2.7-linux = py2.7-linux-i686 py2.7-linux-x86_64
-linux-i686 = py2.4-linux-i686 py2.5-linux-i686 py2.6-linux-i686 py2.7-linux-i686
-linux-x86_64 = py2.4-linux-x86_64 py2.5-linux-x86_64 py2.6-linux-x86_64 py2.7-linux-x86_64
+linux-i686 = py2.5-linux-i686 py2.6-linux-i686 py2.7-linux-i686
+linux-x86_64 = py2.5-linux-x86_64 py2.6-linux-x86_64 py2.7-linux-x86_64
linux = linux-i686 linux-x86_64
-py2.4-macosx = py2.4-macosx-10.3-fat-ucs2
py2.5-macosx = py2.5-macosx-10.3-fat-ucs2
py2.6-macosx = py2.6-macosx-10.3-fat-ucs2 py2.6-macosx-10.6-universal-ucs2
py2.7-macosx = py2.7-macosx-10.3-fat-ucs2 py2.7-macosx-10.6-intel-ucs2
-macosx = py2.4-macosx py2.5-macosx py2.6-macosx py2.7-macosx
-py2.4-solaris-i86pc = py2.4-solaris-2.10-i86pc_32-ucs2 py2.4-solaris-2.10-i86pc_64-ucs2
+macosx = py2.5-macosx py2.6-macosx py2.7-macosx
py2.5-solaris-i86pc = py2.5-solaris-2.10-i86pc_32-ucs2 py2.5-solaris-2.10-i86pc_64-ucs2
py2.6-solaris-i86pc = py2.6-solaris-2.10-i86pc_32-ucs2 py2.6-solaris-2.10-i86pc_64-ucs2
py2.7-solaris-i86pc = py2.7-solaris-2.10-i86pc_32-ucs2 py2.7-solaris-2.10-i86pc_64-ucs2
-py2.4-solaris-sun4u = py2.4-solaris-2.10-sun4u_32-ucs2 py2.4-solaris-2.10-sun4u_64-ucs2
py2.5-solaris-sun4u = py2.5-solaris-2.10-sun4u_32-ucs2 py2.5-solaris-2.10-sun4u_64-ucs2
py2.6-solaris-sun4u = py2.6-solaris-2.10-sun4u_32-ucs2 py2.6-solaris-2.10-sun4u_64-ucs2
py2.7-solaris-sun4u = py2.7-solaris-2.10-sun4u_32-ucs2 py2.7-solaris-2.10-sun4u_64-ucs2
-py2.4-solaris = py2.4-solaris-i86pc py2.4-solaris-sun4u
py2.5-solaris = py2.5-solaris-i86pc py2.5-solaris-sun4u
py2.6-solaris = py2.6-solaris-i86pc py2.6-solaris-sun4u
py2.7-solaris = py2.7-solaris-i86pc py2.7-solaris-sun4u
-solaris-i86pc = py2.4-solaris-i86pc py2.5-solaris-i86pc py2.6-solaris-i86pc py2.7-solaris-i86pc
-solaris-sun4u = py2.4-solaris-sun4u py2.5-solaris-sun4u py2.6-solaris-sun4u py2.7-solaris-sun4u
+solaris-i86pc = py2.5-solaris-i86pc py2.6-solaris-i86pc py2.7-solaris-i86pc
+solaris-sun4u = py2.5-solaris-sun4u py2.6-solaris-sun4u py2.7-solaris-sun4u
solaris = solaris-i86pc solaris-sun4u
-py2.4-all = py2.4-linux py2.4-macosx py2.4-solaris
py2.5-all = py2.5-linux py2.5-macosx py2.5-solaris
py2.6-all = py2.6-linux py2.6-macosx py2.6-solaris
py2.7-all = py2.7-linux py2.7-macosx py2.7-solaris
-; group for building pysam on solaris 10 sparc
-;solaris-2.10-sun4u = py2.4-solaris-2.10-sun4u_32-ucs2 py2.5-solaris-2.10-sun4u_32-ucs2 py2.6-solaris-2.10-sun4u_32-ucs2 py2.4-solaris-2.10-sun4u_64-ucs2 py2.5-solaris-2.10-sun4u_64-ucs2 py2.6-solaris-2.10-sun4u_64-ucs2
-
; the 'all' key is used internally by the build system to specify which hosts
; to build on when no hosts are specified on the dist-eggs.py command line.
all = linux macosx solaris
; the 'noplatform' key, likewise, is for which build hosts should be used when
; building pure python (noplatform) eggs.
-noplatform = py2.4 py2.5 py2.6 py2.7
+noplatform = py2.5 py2.6 py2.7
; don't build these eggs on these platforms:
[ignore]
-GeneTrack = py2.4
-python-daemon = py2.4
ctypes = py2.5-linux-i686-ucs2 py2.5-linux-i686-ucs4 py2.6-linux-i686-ucs2 py2.6-linux-i686-ucs4 py2.7-linux-i686-ucs2 py2.7-linux-i686-ucs4 py2.5-linux-x86_64-ucs2 py2.5-linux-x86_64-ucs4 py2.6-linux-x86_64-ucs2 py2.6-linux-x86_64-ucs4 py2.7-linux-x86_64-ucs2 py2.7-linux-x86_64-ucs4 py2.5-macosx-10.3-fat-ucs2 py2.6-macosx-10.3-fat-ucs2 py2.6-macosx-10.6-universal-ucs2 py2.7-macosx-10.3-fat-ucs2 py2.5-solaris-2.10-i86pc_32-ucs2 py2.6-solaris-2.10-i86pc_32-ucs2 py2.7-solaris-2.10-i86pc_32-ucs2 py2.5-solaris-2.10-i86pc_64-ucs2 py2.6-solaris-2.10-i86pc_64-ucs2 py2.7-solaris-2.10-i86pc_64-ucs2 py2.5-solaris-2.10-sun4u_32-ucs2 py2.6-solaris-2.10-sun4u_32-ucs2 py2.7-solaris-2.10-sun4u_32-ucs2 py2.5-solaris-2.10-sun4u_64-ucs2 py2.6-solaris-2.10-sun4u_64-ucs2 py2.7-solaris-2.10-sun4u_64-ucs2
diff --git a/eggs.ini b/eggs.ini
index d5547b28a71..30c2ed5c742 100644
--- a/eggs.ini
+++ b/eggs.ini
@@ -17,6 +17,7 @@ Cheetah = 2.2.2
ctypes = 1.0.2
DRMAA_python = 0.2
MarkupSafe = 0.12
+mercurial = 2.1.2
MySQL_python = 1.2.3c1
numpy = 1.6.0
pbs_python = 4.1.0
diff --git a/lib/galaxy/app.py b/lib/galaxy/app.py
index be195d90693..2c1c49a4a3b 100644
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -12,6 +12,7 @@ from galaxy.objectstore import build_object_store_from_config
import galaxy.quota
from galaxy.tags.tag_handler import GalaxyTagHandler
from galaxy.tools.imp_exp import load_history_imp_exp_tools
+from galaxy.tools.genome_index import load_genome_index_tools
from galaxy.sample_tracking import external_service_types
from galaxy.openid.providers import OpenIDProviders
@@ -90,6 +91,8 @@ class UniverseApplication( object ):
self.datatypes_registry.load_external_metadata_tool( self.toolbox )
# Load history import/export tools.
load_history_imp_exp_tools( self.toolbox )
+ # Load genome indexer tool.
+ load_genome_index_tools( self.toolbox )
# Load security policy.
self.security_agent = self.model.security_agent
self.host_security_agent = galaxy.security.HostAgent( model=self.security_agent.model, permitted_actions=self.security_agent.permitted_actions )
@@ -124,8 +127,9 @@ class UniverseApplication( object ):
if self.config.get_bool( 'enable_beta_job_managers', False ):
from jobs import transfer_manager
self.transfer_manager = transfer_manager.TransferManager( self )
- # Start the job queue
- self.job_manager = jobs.JobManager( self )
+ # Start the job manager
+ from jobs import manager
+ self.job_manager = manager.JobManager( self )
# FIXME: These are exposed directly for backward compatibility
self.job_queue = self.job_manager.job_queue
self.job_stop_queue = self.job_manager.job_stop_queue
diff --git a/lib/galaxy/config.py b/lib/galaxy/config.py
index 6fc42236775..a122a1063ed 100644
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -42,8 +42,7 @@ class Configuration( object ):
tempfile.tempdir = self.new_file_path
self.openid_consumer_cache_path = resolve_path( kwargs.get( "openid_consumer_cache_path", "database/openid_consumer_cache" ), self.root )
self.cookie_path = kwargs.get( "cookie_path", "/" )
- # web API
- self.enable_api = string_as_bool( kwargs.get( 'enable_api', False ) )
+ self.genome_data_path = kwargs.get( "genome_data_path", "tool-data/genome" )
# Galaxy OpenID settings
self.enable_openid = string_as_bool( kwargs.get( 'enable_openid', False ) )
self.openid_config = kwargs.get( 'openid_config_file', 'openid_conf.xml' )
@@ -86,6 +85,7 @@ class Configuration( object ):
self.allow_user_dataset_purge = string_as_bool( kwargs.get( "allow_user_dataset_purge", "False" ) )
self.allow_user_impersonation = string_as_bool( kwargs.get( "allow_user_impersonation", "False" ) )
self.new_user_dataset_access_role_default_private = string_as_bool( kwargs.get( "new_user_dataset_access_role_default_private", "False" ) )
+ self.collect_outputs_from = [ x.strip() for x in kwargs.get( 'collect_outputs_from', 'new_file_path,job_working_directory' ).lower().split(',') ]
self.template_path = resolve_path( kwargs.get( "template_path", "templates" ), self.root )
self.template_cache = resolve_path( kwargs.get( "template_cache_path", "database/compiled_templates" ), self.root )
self.local_job_queue_workers = int( kwargs.get( "local_job_queue_workers", "5" ) )
@@ -105,6 +105,7 @@ class Configuration( object ):
self.smtp_username = kwargs.get( 'smtp_username', None )
self.smtp_password = kwargs.get( 'smtp_password', None )
self.start_job_runners = kwargs.get( 'start_job_runners', None )
+ self.expose_dataset_path = string_as_bool( kwargs.get( 'expose_dataset_path', 'False' ) )
# External Service types used in sample tracking
self.external_service_type_config_file = resolve_path( kwargs.get( 'external_service_type_config_file', 'external_service_types_conf.xml' ), self.root )
self.external_service_type_path = resolve_path( kwargs.get( 'external_service_type_path', 'external_service_types' ), self.root )
@@ -184,14 +185,43 @@ class Configuration( object ):
# Heartbeat log file name override
if global_conf is not None:
self.heartbeat_log = global_conf.get( 'heartbeat_log', 'heartbeat.log' )
- #Store per-tool runner configs.
+ # Determine which 'server:' this is
+ self.server_name = 'main'
+ for arg in sys.argv:
+ # Crummy, but PasteScript does not give you a way to determine this
+ if arg.lower().startswith('--server-name='):
+ self.server_name = arg.split('=', 1)[-1]
+ # Store advanced job management config
+ self.job_manager = kwargs.get('job_manager', self.server_name).strip()
+ self.job_handlers = [ x.strip() for x in kwargs.get('job_handlers', self.server_name).split(',') ]
+ self.default_job_handlers = [ x.strip() for x in kwargs.get('default_job_handlers', ','.join( self.job_handlers ) ).split(',') ]
+ # Use database for IPC unless this is a standalone server (or multiple servers doing self dispatching in memory)
+ self.track_jobs_in_database = True
+ if ( len( self.job_handlers ) == 1 ) and ( self.job_handlers[0] == self.server_name ) and ( self.job_manager == self.server_name ):
+ self.track_jobs_in_database = False
+ # Store per-tool runner configs
+ self.tool_handlers = self.__read_tool_job_config( global_conf_parser, 'galaxy:tool_handlers', 'name' )
+ self.tool_runners = self.__read_tool_job_config( global_conf_parser, 'galaxy:tool_runners', 'url' )
+ self.datatypes_config = kwargs.get( 'datatypes_config_file', 'datatypes_conf.xml' )
+ # Cloud configuration options
+ self.enable_cloud_launch = string_as_bool( kwargs.get( 'enable_cloud_launch', False ) )
+ # Galaxy messaging (AMQP) configuration options
+ self.amqp = {}
try:
- tool_runners_config = global_conf_parser.items("galaxy:tool_runners")
+ amqp_config = global_conf_parser.items("galaxy_amqp")
+ except ConfigParser.NoSectionError:
+ amqp_config = {}
+ for k, v in amqp_config:
+ self.amqp[k] = v
+ self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
+ def __read_tool_job_config( self, global_conf_parser, section, key ):
+ try:
+ tool_runners_config = global_conf_parser.items( section )
# Process config to group multiple configs for the same tool.
- tool_runners = {}
+ rval = {}
for entry in tool_runners_config:
- tool_config, url = entry
+ tool_config, val = entry
tool = None
runner_dict = {}
if tool_config.find("[") != -1:
@@ -206,29 +236,18 @@ class Configuration( object ):
tool = tool_config
# Add runner URL.
- runner_dict[ 'url' ] = url
+ runner_dict[ key ] = val
# Create tool entry if necessary.
- if tool not in tool_runners:
- tool_runners[ tool ] = []
+ if tool not in rval:
+ rval[ tool ] = []
# Add entry to runners.
- tool_runners[ tool ].append( runner_dict )
+ rval[ tool ].append( runner_dict )
- self.tool_runners = tool_runners
+ return rval
except ConfigParser.NoSectionError:
- self.tool_runners = []
- self.datatypes_config = kwargs.get( 'datatypes_config_file', 'datatypes_conf.xml' )
- # Cloud configuration options
- self.enable_cloud_launch = string_as_bool( kwargs.get( 'enable_cloud_launch', False ) )
- # Galaxy messaging (AMQP) configuration options
- self.amqp = {}
- try:
- amqp_config = global_conf_parser.items("galaxy_amqp")
- except ConfigParser.NoSectionError:
- amqp_config = {}
- for k, v in amqp_config:
- self.amqp[k] = v
+ return []
def get( self, key, default ):
return self.config_dict.get( key, default )
def get_bool( self, key, default ):
@@ -238,16 +257,6 @@ class Configuration( object ):
return default
def check( self ):
paths_to_check = [ self.root, self.tool_path, self.tool_data_path, self.template_path ]
- # Look for any tool shed configs and retrieve the tool_path attribute from the tag.
- tool_configs = self.tool_configs
- if self.migrated_tools_config not in tool_configs:
- tool_configs.append( self.migrated_tools_config )
- for config_filename in tool_configs:
- tree = parse_xml( config_filename )
- root = tree.getroot()
- tool_path = root.get( 'tool_path' )
- if tool_path not in [ None, False ]:
- paths_to_check.append( resolve_path( tool_path, self.root ) )
# Check that required directories exist
for path in paths_to_check:
if path not in [ None, False ] and not os.path.isdir( path ):
diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py
index 938d1e37f22..2bc451454f0 100644
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -34,6 +34,17 @@ class Binary( data.Data ):
"""Returns the mime type of the datatype"""
return 'application/octet-stream'
+ def display_data(self, trans, dataset, preview=False, filename=None, to_ext=None, size=None, offset=None, **kwd):
+ trans.response.set_content_type(dataset.get_mime())
+ trans.log_event( "Display dataset id: %s" % str( dataset.id ) )
+ trans.response.headers['Content-Length'] = int( os.stat( dataset.file_name ).st_size )
+ to_ext = dataset.extension
+ valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ fname = ''.join(c in valid_chars and c or '_' for c in dataset.name)[0:150]
+ trans.response.set_content_type( "application/octet-stream" ) #force octet-stream so Safari doesn't append mime extensions to filename
+ trans.response.headers["Content-Disposition"] = 'attachment; filename="Galaxy%s-[%s].%s"' % (dataset.hid, fname, to_ext)
+ return open( dataset.file_name )
+
class Ab1( Binary ):
"""Class describing an ab1 binary sequence file"""
file_ext = "ab1"
diff --git a/lib/galaxy/datatypes/converters/sam_to_bam.py b/lib/galaxy/datatypes/converters/sam_to_bam.py
new file mode 100644
index 00000000000..d26e28f70df
--- /dev/null
+++ b/lib/galaxy/datatypes/converters/sam_to_bam.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#Dan Blankenberg
+
+"""
+A wrapper script for converting SAM to BAM, with sorting.
+%prog input_filename.sam output_filename.bam
+"""
+
+import sys, optparse, os, tempfile, subprocess, shutil
+
+CHUNK_SIZE = 2**20 #1mb
+
+
+def cleanup_before_exit( tmp_dir ):
+ if tmp_dir and os.path.exists( tmp_dir ):
+ shutil.rmtree( tmp_dir )
+
+def __main__():
+ #Parse Command Line
+ parser = optparse.OptionParser()
+ (options, args) = parser.parse_args()
+
+ assert len( args ) == 2, 'You must specify the input and output filenames'
+ input_filename, output_filename = args
+
+ tmp_dir = tempfile.mkdtemp( prefix='tmp-sam_to_bam_converter-' )
+
+ #convert to SAM
+ unsorted_bam_filename = os.path.join( tmp_dir, 'unsorted.bam' )
+ unsorted_stderr_filename = os.path.join( tmp_dir, 'unsorted.stderr' )
+ cmd = 'samtools view -bS "%s" > "%s"' % ( input_filename, unsorted_bam_filename )
+ proc = subprocess.Popen( args=cmd, stderr=open( unsorted_stderr_filename, 'wb' ), shell=True, cwd=tmp_dir )
+ return_code = proc.wait()
+ if return_code:
+ stderr_target = sys.stderr
+ else:
+ stderr_target = sys.stdout
+ stderr = open( unsorted_stderr_filename )
+ while True:
+ chunk = stderr.read( CHUNK_SIZE )
+ if chunk:
+ stderr_target.write( chunk )
+ else:
+ break
+ stderr.close()
+
+ #sort sam, so indexing will not fail
+ sorted_stderr_filename = os.path.join( tmp_dir, 'sorted.stderr' )
+ sorting_prefix = os.path.join( tmp_dir, 'sorted_bam' )
+ cmd = 'samtools sort -o "%s" "%s" > "%s"' % ( unsorted_bam_filename, sorting_prefix, output_filename )
+ proc = subprocess.Popen( args=cmd, stderr=open( sorted_stderr_filename, 'wb' ), shell=True, cwd=tmp_dir )
+ return_code = proc.wait()
+
+ if return_code:
+ stderr_target = sys.stderr
+ else:
+ stderr_target = sys.stdout
+ stderr = open( sorted_stderr_filename )
+ while True:
+ chunk = stderr.read( CHUNK_SIZE )
+ if chunk:
+ stderr_target.write( chunk )
+ else:
+ break
+ stderr.close()
+
+ cleanup_before_exit( tmp_dir )
+
+if __name__=="__main__": __main__()
diff --git a/lib/galaxy/datatypes/converters/sam_to_bam.xml b/lib/galaxy/datatypes/converters/sam_to_bam.xml
index 3b9c37c8355..1a5ce77b794 100644
--- a/lib/galaxy/datatypes/converters/sam_to_bam.xml
+++ b/lib/galaxy/datatypes/converters/sam_to_bam.xml
@@ -1,11 +1,11 @@
-
+
- samtools view -bS $input1 > $output 2> /dev/null
+ sam_to_bam.py $input1 $output
diff --git a/lib/galaxy/datatypes/data.py b/lib/galaxy/datatypes/data.py
index f68c9f8a07f..f1d7cc3949c 100644
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -3,11 +3,39 @@ from galaxy import util
from galaxy.util.odict import odict
from galaxy.util.bunch import Bunch
from galaxy.util import inflector
+from galaxy.util.sanitize_html import sanitize_html
from cgi import escape
+import mimetypes
import metadata
import zipfile
from metadata import MetadataElement #import directly to maintain ease of use in Datatype class definitions
+
+if sys.version_info[:2] < ( 2, 6 ):
+ zipfile.BadZipFile = zipfile.error
+if sys.version_info[:2] < ( 2, 5 ):
+ zipfile.LargeZipFile = zipfile.error
+
+tmpd = tempfile.mkdtemp()
+comptypes=[]
+ziptype = '32'
+tmpf = os.path.join( tmpd, 'compression_test.zip' )
+try:
+ archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED, True )
+ archive.close()
+ comptypes.append( 'zip' )
+ ziptype = '64'
+except RuntimeError:
+ log.exception( "Compression error when testing zip compression. This option will be disabled for library downloads." )
+except (TypeError, zipfile.LargeZipFile): # ZIP64 is only in Python2.5+. Remove TypeError when 2.4 support is dropped
+ log.warning( 'Max zip file size is 2GB, ZIP64 not supported' )
+ comptypes.append( 'zip' )
+try:
+ os.unlink( tmpf )
+except OSError:
+ pass
+os.rmdir( tmpd )
+
log = logging.getLogger(__name__)
# Valid first column and strand column values vor bed, other formats
@@ -39,7 +67,7 @@ class Data( object ):
'test'
>>> type( DataTest.metadata_spec.test.param )
-
+
"""
__metaclass__ = DataMeta
# Add metadata elements
@@ -60,7 +88,7 @@ class Data( object ):
primary_file_name = 'index'
#A per datatype setting (inherited): max file size (in bytes) for setting optional metadata
_max_optional_metadata_filesize = None
-
+
def __init__(self, **kwd):
"""Initialize the datatype"""
object.__init__(self, **kwd)
@@ -118,7 +146,7 @@ class Data( object ):
to_check = dataset.metadata.items()
for key, value in to_check:
if key in skip or ( not check and dataset.metadata.spec[key].get( "optional" ) ):
- continue #we skip check for optional and nonrequested values here
+ continue #we skip check for optional and nonrequested values here
if not value:
return True
return False
@@ -142,6 +170,7 @@ class Data( object ):
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek(self, dataset ):
"""Create HTML table, used for displaying peek"""
out = ['
']
@@ -163,6 +192,151 @@ class Data( object ):
except Exception, exc:
out = "Can't create peek %s" % str( exc )
return out
+
+ def _archive_composite_dataset( self, trans, data=None, **kwd ):
+ # save a composite object into a compressed archive for downloading
+ params = util.Params( kwd )
+ valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ outfname = data.name[0:150]
+ outfname = ''.join(c in valid_chars and c or '_' for c in outfname)
+ if (params.do_action == None):
+ params.do_action = 'zip' # default
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ if not data:
+ msg = "You must select at least one dataset"
+ messagetype = 'error'
+ else:
+ error = False
+ try:
+ if (params.do_action == 'zip'):
+ # Can't use mkstemp - the file must not exist first
+ tmpd = tempfile.mkdtemp()
+ tmpf = os.path.join( tmpd, 'library_download.' + params.do_action )
+ if ziptype == '64':
+ archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED, True )
+ else:
+ archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED )
+ archive.add = lambda x, y: archive.write( x, y.encode('CP437') )
+ elif params.do_action == 'tgz':
+ archive = util.streamball.StreamBall( 'w|gz' )
+ elif params.do_action == 'tbz':
+ archive = util.streamball.StreamBall( 'w|bz2' )
+ except (OSError, zipfile.BadZipFile):
+ error = True
+ log.exception( "Unable to create archive for download" )
+ msg = "Unable to create archive for %s for download, please report this error" % outfname
+ messagetype = 'error'
+ if not error:
+ current_user_roles = trans.get_current_user_roles()
+ ext = data.extension
+ path = data.file_name
+ fname = os.path.split(path)[-1]
+ efp = data.extra_files_path
+ htmlname = os.path.splitext(outfname)[0]
+ if not htmlname.endswith(ext):
+ htmlname = '%s_%s' % (htmlname,ext)
+ archname = '%s.html' % htmlname # fake the real nature of the html file
+ try:
+ archive.add(data.file_name,archname)
+ except IOError:
+ error = True
+ log.exception( "Unable to add composite parent %s to temporary library download archive" % data.file_name)
+ msg = "Unable to create archive for download, please report this error"
+ messagetype = 'error'
+ for root, dirs, files in os.walk(efp):
+ for fname in files:
+ fpath = os.path.join(root,fname)
+ rpath = os.path.relpath(fpath,efp)
+ try:
+ archive.add( fpath,rpath )
+ except IOError:
+ error = True
+ log.exception( "Unable to add %s to temporary library download archive" % rpath)
+ msg = "Unable to create archive for download, please report this error"
+ messagetype = 'error'
+ continue
+ if not error:
+ if params.do_action == 'zip':
+ archive.close()
+ tmpfh = open( tmpf )
+ # CANNOT clean up - unlink/rmdir was always failing because file handle retained to return - must rely on a cron job to clean up tmp
+ trans.response.set_content_type( "application/x-zip-compressed" )
+ trans.response.headers[ "Content-Disposition" ] = 'attachment; filename="%s.zip"' % outfname
+ return tmpfh
+ else:
+ trans.response.set_content_type( "application/x-tar" )
+ outext = 'tgz'
+ if params.do_action == 'tbz':
+ outext = 'tbz'
+ trans.response.headers[ "Content-Disposition" ] = 'attachment; filename="%s.%s"' % (outfname,outext)
+ archive.wsgi_status = trans.response.wsgi_status()
+ archive.wsgi_headeritems = trans.response.wsgi_headeritems()
+ return archive.stream
+ return trans.show_error_message( msg )
+
+ def _serve_raw(self, trans, dataset, to_ext):
+ trans.response.headers['Content-Length'] = int( os.stat( dataset.file_name ).st_size )
+ valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ fname = ''.join(c in valid_chars and c or '_' for c in dataset.name)[0:150]
+ trans.response.set_content_type( "application/octet-stream" ) #force octet-stream so Safari doesn't append mime extensions to filename
+ trans.response.headers["Content-Disposition"] = 'attachment; filename="Galaxy%s-[%s].%s"' % (dataset.hid, fname, to_ext)
+ return open( dataset.file_name )
+
+ def display_data(self, trans, data, preview=False, filename=None, to_ext=None, size=None, offset=None, **kwd):
+ """ Old display method, for transition """
+ #Relocate all composite datatype display to a common location.
+ composite_extensions = trans.app.datatypes_registry.get_composite_extensions( )
+ composite_extensions.append('html') # for archiving composite datatypes
+ if isinstance( data, basestring ):
+ return data
+ if filename and filename != "index":
+ # For files in extra_files_path
+ file_path = trans.app.object_store.get_filename(data.dataset, extra_dir='dataset_%s_files' % data.dataset.id, alt_name=filename)
+ if os.path.exists( file_path ):
+ if os.path.isdir( file_path ):
+ return trans.show_error_message( "Directory listing is not allowed." ) #TODO: Reconsider allowing listing of directories?
+ mime, encoding = mimetypes.guess_type( file_path )
+ if not mime:
+ try:
+ mime = trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( file_path )[-1] )
+ except:
+ mime = "text/plain"
+ trans.response.set_content_type( mime )
+ return open( file_path )
+ else:
+ return trans.show_error_message( "Could not find '%s' on the extra files path %s." % ( filename, file_path ) )
+ trans.response.set_content_type(data.get_mime())
+ trans.log_event( "Display dataset id: %s" % str( data.id ) )
+ from galaxy import datatypes #DBTODO REMOVE THIS AT REFACTOR
+ if to_ext or isinstance(data.datatype, datatypes.binary.Binary): # Saving the file, or binary file
+ if data.extension in composite_extensions:
+ return self._archive_composite_dataset( trans, data, **kwd )
+ else:
+ trans.response.headers['Content-Length'] = int( os.stat( data.file_name ).st_size )
+ if not to_ext:
+ to_ext = data.extension
+ valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ fname = ''.join(c in valid_chars and c or '_' for c in data.name)[0:150]
+ trans.response.set_content_type( "application/octet-stream" ) #force octet-stream so Safari doesn't append mime extensions to filename
+ trans.response.headers["Content-Disposition"] = 'attachment; filename="Galaxy%s-[%s].%s"' % (data.hid, fname, to_ext)
+ return open( data.file_name )
+ if not os.path.exists( data.file_name ):
+ raise paste.httpexceptions.HTTPNotFound( "File Not Found (%s)." % data.file_name )
+ max_peek_size = 1000000 # 1 MB
+ if isinstance(data.datatype, datatypes.images.Html):
+ max_peek_size = 10000000 # 10 MB for html
+ if not preview or isinstance(data.datatype, datatypes.images.Image) or os.stat( data.file_name ).st_size < max_peek_size:
+ if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html":
+ # Sanitize anytime we respond with plain text/html content.
+ return sanitize_html(open( data.file_name ).read())
+ return open( data.file_name )
+ else:
+ trans.response.set_content_type( "text/html" )
+ return trans.stream_template_mako( "/dataset/large_file.mako",
+ truncated_data = open( data.file_name ).read(max_peek_size),
+ data = data)
+
def display_name(self, dataset):
"""Returns formatted html of dataset name"""
try:
@@ -183,11 +357,11 @@ class Data( object ):
info = info.replace( '\r', ' ' )
if info.find( '\n' ) >= 0:
info = info.replace( '\n', ' ' )
-
+
# Convert to unicode to display non-ascii characters.
if type( info ) is not unicode:
info = unicode( info, 'utf-8')
-
+
return info
except:
return "info unavailable"
@@ -272,7 +446,7 @@ class Data( object ):
def convert_dataset(self, trans, original_dataset, target_type, return_output=False, visible=True, deps=None, set_output_history=True):
"""This function adds a job to the queue to convert a dataset to another type. Returns a message about success/failure."""
converter = trans.app.datatypes_registry.get_converter_by_target_type( original_dataset.ext, target_type )
-
+
if converter is None:
raise Exception( "A converter does not exist for %s to %s." % ( original_dataset.ext, target_type ) )
#Generate parameter dictionary
@@ -284,7 +458,7 @@ class Data( object ):
params[value.name] = deps[value.name]
elif value.type == 'data':
input_name = key
-
+
params[input_name] = original_dataset
#Run converter, job is dispatched through Queue
converted_dataset = converter.execute( trans, incoming=params, set_output_hid=visible, set_output_history=set_output_history)[1]
@@ -351,18 +525,18 @@ class Data( object ):
@property
def has_resolution(self):
return False
-
-
- def merge( split_files, output_file):
+
+
+ def merge( split_files, output_file):
"""
TODO: Do we need to merge gzip files using gzjoin? cat seems to work,
but might be brittle. Need to revisit this.
"""
if len(split_files) == 1:
- cmd = 'mv -f %s %s' % ( split_files[0], output_file )
+ cmd = 'mv -f %s %s' % ( split_files[0], output_file )
else:
- cmd = 'cat %s > %s' % ( ' '.join(split_files), output_file )
+ cmd = 'cat %s > %s' % ( ' '.join(split_files), output_file )
result = os.system(cmd)
if result != 0:
raise Exception('Result %s from %s' % (result, cmd))
@@ -377,7 +551,7 @@ class Text( Data ):
def write_from_stream(self, dataset, stream):
"""Writes data from a stream"""
- # write it twice for now
+ # write it twice for now
fd, temp_name = tempfile.mkstemp()
while 1:
chunk = stream.read(1048576)
@@ -468,11 +642,11 @@ class Text( Data ):
"""
if split_params is None:
return
-
+
if len(input_datasets) > 1:
raise Exception("Text file splitting does not support multiple files")
input_files = [ds.file_name for ds in input_datasets]
-
+
lines_per_file = None
chunk_size = None
if split_params['split_mode'] == 'number_of_parts':
@@ -501,7 +675,7 @@ class Text( Data ):
chunk_size = int(split_params['split_size'])
else:
raise Exception('Unsupported split mode %s' % split_params['split_mode'])
-
+
f = open(input_files[0], 'rt')
try:
chunk_idx = 0
@@ -562,7 +736,7 @@ def get_test_fname( fname ):
def get_file_peek( file_name, is_multi_byte=False, WIDTH=256, LINE_COUNT=5, skipchars=[] ):
"""
Returns the first LINE_COUNT lines wrapped to WIDTH
-
+
## >>> fname = get_test_fname('4.bed')
## >>> get_file_peek(fname)
## 'chr22 30128507 31828507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +\n'
@@ -601,11 +775,12 @@ def get_file_peek( file_name, is_multi_byte=False, WIDTH=256, LINE_COUNT=5, skip
lines.append( line )
count += 1
temp.close()
- if file_type in [ 'gzipped', 'binary' ]:
- text = "%s file" % file_type
+ if file_type in [ 'gzipped', 'binary' ]:
+ text = "%s file" % file_type
else:
try:
text = unicode( '\n'.join( lines ), 'utf-8' )
except UnicodeDecodeError:
text = "binary/unknown file"
return text
+
diff --git a/lib/galaxy/datatypes/interval.py b/lib/galaxy/datatypes/interval.py
index 351ef0ddda4..c022183b90a 100644
--- a/lib/galaxy/datatypes/interval.py
+++ b/lib/galaxy/datatypes/interval.py
@@ -328,6 +328,9 @@ class Interval( Tabular ):
def get_track_resolution( self, dataset, start, end):
return None
+
+ def get_track_type( self ):
+ return "FeatureTrack", {"data": "tabix", "index": "summary_tree"}
class BedGraph( Interval ):
"""Tab delimited chrom/start/end/datavalue dataset"""
@@ -950,6 +953,9 @@ class Gtf( Gff ):
dataset.metadata.attribute_types = attribute_types
dataset.metadata.attributes = len( attribute_types )
Gff.set_meta( self, dataset, overwrite = overwrite, skip = i )
+
+ def get_track_type( self ):
+ return "FeatureTrack", {"data": "tabix", "index": "summary_tree"}
class Wiggle( Tabular, _RemoteCallMixin ):
diff --git a/lib/galaxy/datatypes/registry.py b/lib/galaxy/datatypes/registry.py
index 6686927bd78..50315904e00 100644
--- a/lib/galaxy/datatypes/registry.py
+++ b/lib/galaxy/datatypes/registry.py
@@ -2,7 +2,7 @@
Provides mapping between extensions and datatypes, mime-types, etc.
"""
import os, sys, tempfile, threading, logging
-import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo, binary, assembly, ngsindex, wsf
+import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo, binary, assembly, ngsindex
import galaxy.util
from galaxy.util.odict import odict
from display_applications.application import DisplayApplication
@@ -141,7 +141,7 @@ class Registry( object ):
if hasattr( imported_module, datatype_class_name ):
datatype_class = getattr( imported_module, datatype_class_name )
except Exception, e:
- full_path = os.path.join( full_path, proprietary_datatype_module )
+ full_path = os.path.join( proprietary_path, proprietary_datatype_module )
self.log.debug( "Exception importing proprietary code file %s: %s" % ( str( full_path ), str( e ) ) )
finally:
lock.release()
diff --git a/lib/galaxy/datatypes/tabular.py b/lib/galaxy/datatypes/tabular.py
index 73584ea2f27..bf9fda1f88e 100644
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -13,34 +13,37 @@ from galaxy.datatypes import metadata
from galaxy.datatypes.metadata import MetadataElement
import galaxy_utils.sequence.vcf
from sniff import *
+from galaxy.util.json import to_json_string
log = logging.getLogger(__name__)
class Tabular( data.Text ):
"""Tab delimited data"""
+ CHUNK_SIZE = 20000
"""Add metadata elements"""
MetadataElement( name="comment_lines", default=0, desc="Number of comment lines", readonly=False, optional=True, no_value=0 )
MetadataElement( name="columns", default=0, desc="Number of columns", readonly=True, visible=False, no_value=0 )
MetadataElement( name="column_types", default=[], desc="Column types", param=metadata.ColumnTypesParameter, readonly=True, visible=False, no_value=[] )
+ MetadataElement( name="column_names", default=[], desc="Column names", readonly=True, visible=False, optional=True, no_value=[] )
def init_meta( self, dataset, copy_from=None ):
data.Text.init_meta( self, dataset, copy_from=copy_from )
- def set_meta( self, dataset, overwrite = True, skip = None, max_data_lines = 100000, **kwd ):
+ def set_meta( self, dataset, overwrite = True, skip = None, max_data_lines = 100000, max_guess_type_data_lines = None, **kwd ):
"""
Tries to determine the number of columns as well as those columns
that contain numerical values in the dataset. A skip parameter is
used because various tabular data types reuse this function, and
their data type classes are responsible to determine how many invalid
- comment lines should be skipped. Using None for skip will cause skip
- to be zero, but the first line will be processed as a header. A
- max_data_lines parameter is used because various tabular data types
- reuse this function, and their data type classes are responsible to
+ comment lines should be skipped. Using None for skip will cause skip
+ to be zero, but the first line will be processed as a header. A
+ max_data_lines parameter is used because various tabular data types
+ reuse this function, and their data type classes are responsible to
determine how many data lines should be processed to ensure that the
- non-optional metadata parameters are properly set; if used, optional
- metadata parameters will be set to None, unless the entire file has
- already been read. Using None (default) for max_data_lines will
- process all data lines.
+ non-optional metadata parameters are properly set; if used, optional
+ metadata parameters will be set to None, unless the entire file has
+ already been read. Using None (default) for max_data_lines will
+ process all data lines.
Items of interest:
1. We treat 'overwrite' as always True (we always want to set tabular metadata when called).
@@ -57,7 +60,7 @@ class Tabular( data.Text ):
column_type_set_order = [ 'int', 'float', 'list', 'str' ] #Order to set column types in
default_column_type = column_type_set_order[-1] # Default column type is lowest in list
column_type_compare_order = list( column_type_set_order ) #Order to compare column types
- column_type_compare_order.reverse()
+ column_type_compare_order.reverse()
def type_overrules_type( column_type1, column_type2 ):
if column_type1 is None or column_type1 == column_type2:
return False
@@ -74,13 +77,13 @@ class Tabular( data.Text ):
try:
int( column_text )
return True
- except:
+ except:
return False
def is_float( column_text ):
try:
float( column_text )
return True
- except:
+ except:
if column_text.strip().lower() == 'na':
return True #na is special cased to be a float
return False
@@ -116,15 +119,16 @@ class Tabular( data.Text ):
comment_lines += 1
else:
data_lines += 1
- fields = line.split( '\t' )
- for field_count, field in enumerate( fields ):
- if field_count >= len( column_types ): #found a previously unknown column, we append None
- column_types.append( None )
- column_type = guess_column_type( field )
- if type_overrules_type( column_type, column_types[field_count] ):
- column_types[field_count] = column_type
+ if max_guess_type_data_lines is None or data_lines <= max_guess_type_data_lines:
+ fields = line.split( '\t' )
+ for field_count, field in enumerate( fields ):
+ if field_count >= len( column_types ): #found a previously unknown column, we append None
+ column_types.append( None )
+ column_type = guess_column_type( field )
+ if type_overrules_type( column_type, column_types[field_count] ):
+ column_types[field_count] = column_type
if i == 0 and requested_skip is None:
- # This is our first line, people seem to like to upload files that have a header line, but do not
+ # This is our first line, people seem to like to upload files that have a header line, but do not
# start with '#' (i.e. all column types would then most likely be detected as str). We will assume
# that the first line is always a header (this was previous behavior - it was always skipped). When
# the requested skip is None, we only use the data from the first line if we have no other data for
@@ -146,7 +150,7 @@ class Tabular( data.Text ):
break
i += 1
dataset_fh.close()
-
+
#we error on the larger number of columns
#first we pad our column_types by using data from first line
if len( first_line_column_types ) > len( column_types ):
@@ -175,9 +179,19 @@ class Tabular( data.Text ):
except Exception, exc:
out = "Can't create peek %s" % str( exc )
return out
- def make_html_peek_header( self, dataset, skipchars=[], column_names=[], column_number_format='%s', column_parameter_alias={}, **kwargs ):
+
+ def make_html_peek_header( self, dataset, skipchars=None, column_names=None, column_number_format='%s', column_parameter_alias=None, **kwargs ):
+ if skipchars is None:
+ skipchars = []
+ if column_names is None:
+ column_names = []
+ if column_parameter_alias is None:
+ column_parameter_alias = {}
out = []
try:
+ if not column_names and dataset.metadata.column_names:
+ column_names = dataset.metadata.column_names
+
column_headers = [None] * dataset.metadata.columns
# fill in empty headers with data from column_names
@@ -207,7 +221,10 @@ class Tabular( data.Text ):
except Exception, exc:
raise Exception, "Can't create peek header %s" % str( exc )
return "".join( out )
- def make_html_peek_rows( self, dataset, skipchars=[], **kwargs ):
+
+ def make_html_peek_rows( self, dataset, skipchars=None, **kwargs ):
+ if skipchars is None:
+ skipchars = []
out = []
try:
if not dataset.peek:
@@ -228,6 +245,28 @@ class Tabular( data.Text ):
except Exception, exc:
raise Exception, "Can't create peek rows %s" % str( exc )
return "".join( out )
+
+ def display_data(self, trans, dataset, preview=False, filename=None, to_ext=None, chunk=None):
+ #TODO Prevent failure when displaying extremely long > 50kb lines.
+ if to_ext:
+ return self._serve_raw(trans, dataset, to_ext)
+ if chunk:
+ ck_index = int(chunk)
+ f = open(dataset.file_name)
+ f.seek(ck_index * self.CHUNK_SIZE)
+ # If we aren't at the start of the file, seek to next newline. Do this better eventually.
+ if f.tell() != 0:
+ cursor = f.read(1)
+ while cursor and cursor != '\n':
+ cursor = f.read(1)
+ ck_data = f.read(self.CHUNK_SIZE)
+ cursor = f.read(1)
+ while cursor and ck_data[-1] != '\n':
+ ck_data += cursor
+ cursor = f.read(1)
+ return to_json_string({'ck_data': ck_data, 'ck_index': ck_index+1})
+ return trans.fill_template( "/dataset/tabular_chunked.mako",dataset = dataset)
+
def set_peek( self, dataset, line_count=None, is_multi_byte=False):
super(Tabular, self).set_peek( dataset, line_count=line_count, is_multi_byte=is_multi_byte)
if dataset.metadata.comment_lines:
@@ -276,7 +315,7 @@ class Sam( Tabular ):
def sniff( self, filename ):
"""
Determines whether the file is in SAM format
-
+
A file in SAM format consists of lines of tab-separated data.
The following header line may be the first line:
@QNAME FLAG RNAME POS MAPQ CIGAR MRNM MPOS ISIZE SEQ QUAL
@@ -285,12 +324,12 @@ class Sam( Tabular ):
Data in the OPT column is optional and can consist of tab-separated data
For complete details see http://samtools.sourceforge.net/SAM1.pdf
-
+
Rules for sniffing as True:
There must be 11 or more columns of data on each line
Columns 2 (FLAG), 4(POS), 5 (MAPQ), 8 (MPOS), and 9 (ISIZE) must be numbers (9 can be negative)
We will only check that up to the first 5 alignments are correctly formatted.
-
+
>>> fname = get_test_fname( 'sequence.maf' )
>>> Sam().sniff( fname )
False
@@ -306,7 +345,7 @@ class Sam( Tabular ):
line = line.strip()
if not line:
break #EOF
- if line:
+ if line:
if line[0] != '@':
linePieces = line.split('\t')
if len(linePieces) < 11:
@@ -368,10 +407,10 @@ class Sam( Tabular ):
if result != 0:
raise Exception('Result %s from %s' % (result, cmd))
merge = staticmethod(merge)
-
+
def get_track_type( self ):
return "ReadTrack", {"data": "bam", "index": "summary_tree"}
-
+
class Pileup( Tabular ):
"""Tab delimited data in pileup (6- or 10-column) format"""
file_ext = "pileup"
@@ -397,7 +436,7 @@ class Pileup( Tabular ):
"""
Checks for 'pileup-ness'
- There are two main types of pileup: 6-column and 10-column. For both,
+ There are two main types of pileup: 6-column and 10-column. For both,
the first three and last two columns are the same. We only check the
first three to allow for some personalization of the format.
@@ -431,27 +470,27 @@ class Pileup( Tabular ):
class ElandMulti( Tabular ):
file_ext = 'elandmulti'
-
+
def sniff( self, filename ):
return False
-
+
class Vcf( Tabular ):
""" Variant Call Format for describing SNPs and other simple genome variations. """
-
+
file_ext = 'vcf'
column_names = [ 'Chrom', 'Pos', 'ID', 'Ref', 'Alt', 'Qual', 'Filter', 'Info', 'Format', 'data' ]
-
+
MetadataElement( name="columns", default=10, desc="Number of columns", readonly=True, visible=False )
MetadataElement( name="column_types", default=['str','int','str','str','str','int','str','list','str','str'], param=metadata.ColumnTypesParameter, desc="Column types", readonly=True, visible=False )
MetadataElement( name="viz_filter_cols", desc="Score column for visualization", default=[5], param=metadata.ColumnParameter, multiple=True )
-
+
def sniff( self, filename ):
headers = get_headers( filename, '\n', count=1 )
return headers[0][0].startswith("##fileformat=VCF")
def display_peek( self, dataset ):
"""Returns formated html of peek"""
return Tabular.make_html_table( self, dataset, column_names=self.column_names )
-
+
def get_track_type( self ):
return "VcfTrack", {"data": "tabix", "index": "summary_tree"}
@@ -473,8 +512,10 @@ class Eland( Tabular ):
'POSITION', 'STRAND', 'DESC', 'SRAS', 'PRAS', 'PART_CHROM'
'PART_CONTIG', 'PART_OFFSET', 'PART_STRAND', 'FILT'
]
- def make_html_table( self, dataset, skipchars=[] ):
+ def make_html_table( self, dataset, skipchars=None ):
"""Create HTML table, used for displaying peek"""
+ if skipchars is None:
+ skipchars = []
out = ['
']
try:
# Generate column header
@@ -495,10 +536,10 @@ class Eland( Tabular ):
def sniff( self, filename ):
"""
Determines whether the file is in ELAND export format
-
+
A file in ELAND export format consists of lines of tab-separated data.
There is no header.
-
+
Rules for sniffing as True:
There must be 22 columns on each line
LANE, TILEm X, Y, INDEX, READ_NO, SEQ, QUAL, POSITION, *STRAND, FILT must be correct
@@ -517,7 +558,7 @@ class Eland( Tabular ):
line = line.strip()
if not line:
break #EOF
- if line:
+ if line:
linePieces = line.split('\t')
if len(linePieces) != 22:
return False
@@ -563,7 +604,7 @@ class Eland( Tabular ):
#else:
# # Otherwise, read the whole thing and set num data lines.
for i, line in enumerate(dataset_fh):
- if line:
+ if line:
linePieces = line.split('\t')
if len(linePieces) != 22:
raise Exception('%s:%d:Corrupt line!' % (dataset.file_name,i))
@@ -581,5 +622,5 @@ class Eland( Tabular ):
dataset.metadata.tiles = ["%04d" % int(t) for t in tiles.keys()]
dataset.metadata.barcodes = filter(lambda x: x != '0', barcodes.keys()) + ['NoIndex' for x in barcodes.keys() if x == '0']
dataset.metadata.reads = reads.keys()
-
-
+
+
diff --git a/lib/galaxy/datatypes/util/gff_util.py b/lib/galaxy/datatypes/util/gff_util.py
index 0a960e9e47a..680bde245f6 100644
--- a/lib/galaxy/datatypes/util/gff_util.py
+++ b/lib/galaxy/datatypes/util/gff_util.py
@@ -10,8 +10,8 @@ class GFFInterval( GenomicInterval ):
A GFF interval, including attributes. If file is strictly a GFF file,
only attribute is 'group.'
"""
- def __init__( self, reader, fields, chrom_col, feature_col, start_col, end_col, \
- strand_col, score_col, default_strand, fix_strand=False ):
+ def __init__( self, reader, fields, chrom_col=0, feature_col=2, start_col=3, end_col=4, \
+ strand_col=6, score_col=5, default_strand='.', fix_strand=False ):
# HACK: GFF format allows '.' for strand but GenomicInterval does not. To get around this,
# temporarily set strand and then unset after initing GenomicInterval.
unknown_strand = False
@@ -45,8 +45,8 @@ class GFFFeature( GFFInterval ):
"""
A GFF feature, which can include multiple intervals.
"""
- def __init__( self, reader, chrom_col, feature_col, start_col, end_col, \
- strand_col, score_col, default_strand, fix_strand=False, intervals=[], \
+ def __init__( self, reader, chrom_col=0, feature_col=2, start_col=3, end_col=4, \
+ strand_col=6, score_col=5, default_strand='.', fix_strand=False, intervals=[], \
raw_size=0 ):
GFFInterval.__init__( self, reader, intervals[0].fields, chrom_col, feature_col, \
start_col, end_col, strand_col, score_col, default_strand, \
diff --git a/lib/galaxy/datatypes/wsf.py b/lib/galaxy/datatypes/wsf.py
deleted file mode 100644
index 551c10515d2..00000000000
--- a/lib/galaxy/datatypes/wsf.py
+++ /dev/null
@@ -1,156 +0,0 @@
-"""
-SnpFile datatype
-"""
-
-import re
-import data
-from galaxy import util
-from galaxy.datatypes.sniff import *
-from galaxy.datatypes.tabular import Tabular
-from galaxy.datatypes import metadata
-from galaxy.datatypes.metadata import MetadataElement
-
-class SnpFile( Tabular ):
- """ Webb's SNP file format """
- file_ext = 'wsf'
- species_regex = re.compile('species=(\S+)')
- MetadataElement( name="species", desc="species", default='', no_value='', visible=False, readonly=True )
- MetadataElement( name="scaffold", desc="scaffold column", param=metadata.ColumnParameter, default=0 )
- MetadataElement( name="pos", desc="pos column", param=metadata.ColumnParameter, default=0 )
- MetadataElement( name="ref", desc="ref column", param=metadata.ColumnParameter, default=0 )
- MetadataElement( name="rPos", desc="rPos column", param=metadata.ColumnParameter, default=0 )
- MetadataElement( name="labels", desc="Number of labels", default=0, no_value=0, visible=False, readonly=True )
- MetadataElement( name="label_for_column", desc="Mapping from column to label", default=[], no_value=[], visible=False, readonly=True )
- MetadataElement( name="columns_with_label", desc="Mapping from label to columns", param=metadata.DictParameter, default={}, no_value={}, visible=False, readonly=True )
- MetadataElement( name="column_headers", desc="Column headers", default=[], no_value=[], visible=False, readonly=True )
-
-
- def set_meta( self, dataset, overwrite = True, **kwd ):
- Tabular.set_meta( self, dataset, overwrite=overwrite, max_data_lines=None, **kwd )
- # these two if statements work around a potential bug in metadata.py
- if dataset.metadata.labels is None or dataset.metadata.labels == dataset.metadata.spec['labels'].no_value:
- self._set_column_labels_metadata( dataset )
- if dataset.metadata.column_headers is None or dataset.metadata.column_headers == dataset.metadata.spec['column_headers'].no_value:
- self._set_column_headers_metadata( dataset )
- self._set_columnParameter_metadata( dataset )
-
-
- def _set_column_labels_metadata( self, dataset ):
- def build_map_from_label_to_comma_separated_column_list( labels ):
- map = {}
- for index, label in enumerate( labels ):
- map.setdefault( label, [] ).append( index )
-
- for label in map:
- map[label] = ','.join( [ str( index + 1 ) for index in map[label] ] )
- return map
-
- def strip_list_elements( list ):
- return [ element.strip() for element in list ]
-
- def initial_comment_lines_of_dataset( dataset ):
- comment_lines = []
- if dataset.has_data():
- try:
- fh = open( dataset.file_name, 'r' )
- for line in fh:
- if not line.startswith('#'):
- break
- line = line[1:]
- line = line.rstrip( '\r\n' )
- if line:
- comment_lines.append( line )
- fh.close()
- except:
- pass
- return comment_lines
-
- def set_metadata_from_comment_lines( dataset ):
- labels = []
- comment_lines = initial_comment_lines_of_dataset( dataset )
-
- for line in comment_lines:
- match = SnpFile.species_regex.match( line )
- if match:
- dataset.metadata.species = match.group(1)
- continue
- elems = line.split( '\t' )
- if len(elems) > 1:
- labels = strip_list_elements( elems )
-
- dataset.metadata.labels = len( labels )
- dataset.metadata.label_for_column = labels[:]
- if labels:
- dataset.metadata.label_for_column.insert(0, '')
- dataset.metadata.columns_with_label = build_map_from_label_to_comma_separated_column_list( labels )
-
- set_metadata_from_comment_lines( dataset )
-
-
- def _set_column_headers_metadata( self, dataset ):
- if dataset.metadata.labels < dataset.metadata.columns:
- column_headers = dataset.metadata.label_for_column[1:] + [ '' ] * ( dataset.metadata.columns - dataset.metadata.labels )
- else:
- column_headers = dataset.metadata.label_for_column[1:dataset.metadata.columns+1]
-
- dataset.metadata.column_headers = column_headers
-
-
- def _set_columnParameter_metadata( self, dataset ):
- def unique_column_number_or_zero( string ):
- try:
- val = int( string )
- except:
- val = 0
- return val
-
- for name in self._metadata_columnParameter_names( dataset ):
- if name in dataset.metadata.columns_with_label:
- if dataset.metadata.columns_with_label[name]:
- column = unique_column_number_or_zero( dataset.metadata.columns_with_label[name] )
- if column:
- setattr( dataset.metadata, name, column )
-
-
- def _metadata_columnParameter_names( self, dataset ):
- for name, spec in dataset.metadata.spec.items():
- if isinstance( spec.param, metadata.ColumnParameter ):
- yield name
-
-
- def set_peek( self, dataset, line_count=None, is_multi_byte=False ):
- super(Tabular, self).set_peek( dataset, line_count=line_count, is_multi_byte=is_multi_byte, skipchars=[ '#' ])
-
-
- def make_html_table( self, dataset, skipchars=[ '#' ] ):
- """Create HTML table, used for displaying peek"""
- def table_header_values( dataset ):
- headers = dataset.metadata.column_headers[:]
- for name in self._metadata_columnParameter_names( dataset ):
- col = getattr( dataset.metadata, name )
- assert col <= dataset.metadata.columns, Exception( 'ColumnParameter %s %d > %d columns for dataset %s.' % ( name, col, dataset.metadata.columns, dataset.id ) )
- if col > 0:
- headers[ col - 1 ] = name
- return headers
-
- def table_headers( dataset ):
- out = [ '
' ]
- headers = table_header_values( dataset )
- for index, header in enumerate( headers ):
- column = index + 1
- if header:
- out.append( "