galaxy-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions

commit/galaxy-central: jgoecks: Trackster: simplify track iteration during save.
by Bitbucket 02 Sep '11
by Bitbucket 02 Sep '11
02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c6416712537b/
changeset: c6416712537b
user: jgoecks
date: 2011-09-03 00:32:13
summary: Trackster: simplify track iteration during save.
affected #: 1 file (292 bytes)
--- a/templates/tracks/browser.mako Fri Sep 02 18:00:16 2011 -0400
+++ b/templates/tracks/browser.mako Fri Sep 02 18:32:13 2011 -0400
@@ -204,32 +204,25 @@
"Save": function() {
// Show saving dialog box
show_modal("Saving...", "<img src='${h.url_for('/static/images/yui/rel_interstitial_loading.gif')}'/>");
+
+ // TODO: make save into its own function.
// Save tracks.
- var tracks = [];
- $(".viewport-container .track").each(function () {
- // ID has form track_<main_track_id>_<child_track_id>
- var
- id_split = $(this).attr("id").split("_"),
- track_id = id_split[1],
- child_id = id_split[2];
-
- // Get track.
- var track = view.tracks[track_id];
- if (child_id) {
- track = track.child_tracks[child_id];
- }
+ var saved_tracks = [], tracks;
+ for (var i = 0; i < view.tracks.length; i++) {
+ track = view.tracks[i];
// Add track.
- tracks.push({
+ saved_tracks.push({
"track_type": track.get_type(),
"name": track.name,
"hda_ldda": track.hda_ldda,
"dataset_id": track.dataset_id,
"prefs": track.prefs,
- "is_child": (child_id ? true : false )
+ // TODO: remove parent-child relationships in favor of a group.
+ "is_child": false
});
- });
+ };
// Save bookmarks.
var bookmarks = [];
@@ -242,7 +235,7 @@
var overview_track_name = (view.overview_track ? view.overview_track.name : null);
var payload = {
- 'tracks': tracks,
+ 'tracks': saved_tracks,
'viewport': { 'chrom': view.chrom, 'start': view.low , 'end': view.high, 'overview': overview_track_name },
'bookmarks': bookmarks
};
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Trackster: properly remove tracks from view's track array.
by Bitbucket 02 Sep '11
by Bitbucket 02 Sep '11
02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/a02763fbe84a/
changeset: a02763fbe84a
user: jgoecks
date: 2011-09-03 00:00:16
summary: Trackster: properly remove tracks from view's track array.
affected #: 1 file (3 bytes)
--- a/static/scripts/trackster.js Fri Sep 02 15:53:04 2011 -0400
+++ b/static/scripts/trackster.js Fri Sep 02 18:00:16 2011 -0400
@@ -896,7 +896,7 @@
*/
remove_track: function(track) {
this.has_changes = true;
- delete this.tracks[this.tracks.indexOf(track)];
+ this.tracks.splice(this.tracks.indexOf(track), 1);
this.num_tracks -= 1;
var view = this;
track.container_div.fadeOut('slow', function() {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: A couple of bug fixes in handling tool shed installs.
by Bitbucket 02 Sep '11
by Bitbucket 02 Sep '11
02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/cf8748a743a7/
changeset: cf8748a743a7
user: greg
date: 2011-09-02 21:53:04
summary: A couple of bug fixes in handling tool shed installs.
affected #: 1 file (524 bytes)
--- a/lib/galaxy/web/base/controller.py Fri Sep 02 14:59:31 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 02 15:53:04 2011 -0400
@@ -2768,10 +2768,15 @@
try:
repository_tool = trans.app.toolbox.load_tool( full_path )
if repository_tool:
- repository_tools_tups.append( ( relative_path.lstrip( '%s/' % tool_path ), repository_tool ) )
+ # At this point, we need to lstrip tool_path from relative_path,m but we
+ # have to be careful, so we do this the following way instead of using lstrip().
+ items = relative_path.split( '/' )
+ lstriped_items = items[ 2: ]
+ tup_path = '/'.join( lstriped_items )
+ repository_tools_tups.append( ( tup_path, repository_tool ) )
except Exception, e:
# We have an inavlid .xml file, so not a tool config.
- log.debug("Ignoring invalid tool config (%s)." % str( relative_path ))
+ log.debug( "Ignoring invalid tool config (%s). Error: %s" % ( str( relative_path ), str( e ) ) )
if repository_tools_tups:
# Generate an in-memory tool conf section that includes the new tools.
new_tool_section = self.__generate_tool_panel_section( repository_name,
@@ -2865,7 +2870,7 @@
if tool_shed_url.find( ':' ) > 0:
# Eliminate the port, if any, since it will result in an invalid directory name.
return tool_shed_url.split( ':' )[ 0 ]
- return tool_shed_url
+ return tool_shed_url.rstrip( '/' )
def __clean_repository_clone_url( self, repository_clone_url ):
if repository_clone_url.find( '@' ) > 0:
# We have an url that includes an authenticated user, something like:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/29a8fa81b603/
changeset: 29a8fa81b603
user: greg
date: 2011-09-02 20:59:31
summary: Add the ability for a Galaxy administrator to automatically install tools from a configured Galaxy tool shed into their local Galaxy installation. Documentation will be available in the tool shed wiki shortly.
affected #: 9 files (44.9 KB)
--- a/lib/galaxy/web/base/controller.py Fri Sep 02 14:57:33 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 02 14:59:31 2011 -0400
@@ -1,8 +1,9 @@
"""
Contains functionality needed in every web interface
"""
-import os, time, logging, re, string, sys, glob
-from datetime import datetime, timedelta
+import os, time, logging, re, string, sys, glob, shutil, tempfile, subprocess
+from datetime import *
+from time import strftime
from galaxy import config, tools, web, util
from galaxy.web import error, form, url_for
from galaxy.model.orm import *
@@ -15,6 +16,10 @@
from Cheetah.Template import Template
+
+pkg_resources.require( 'elementtree' )
+from elementtree import ElementTree, ElementInclude
+
log = logging.getLogger( __name__ )
# States for passing messages
@@ -1153,22 +1158,14 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
+ toolbox = self.app.toolbox
+ if params.get( 'reload_tool_button', False ):
+ tool_id = params.tool_id
+ message, status = toolbox.reload_tool_by_id( tool_id )
return trans.fill_template( '/admin/reload_tool.mako',
- toolbox=self.app.toolbox,
+ toolbox=toolbox,
message=message,
status=status )
- @web.expose
- @web.require_admin
- def tool_reload( self, trans, tool_version=None, **kwd ):
- params = util.Params( kwd )
- tool_id = params.tool_id
- self.app.toolbox.reload( tool_id )
- message = 'Reloaded tool: ' + tool_id
- return trans.fill_template( '/admin/reload_tool.mako',
- toolbox=self.app.toolbox,
- message=message,
- status='done' )
-
# Galaxy Role Stuff
@web.expose
@web.require_admin
@@ -2693,9 +2690,268 @@
msg = msg,
status = status,
job_lock = trans.app.job_manager.job_queue.job_lock )
+ @web.expose
+ @web.require_admin
+ def browse_tool_shed( self, trans, **kwd ):
+ tool_shed_name = kwd[ 'tool_shed_name' ]
+ tool_shed_url = kwd[ 'tool_shed_url' ]
+ galaxy_url = trans.request.host
+ url = '%s/repository/browse_downloadable_repositories?tool_shed_name=%s&galaxy_url=%s&webapp=community' % ( tool_shed_url, tool_shed_name, galaxy_url )
+ return trans.response.send_redirect( url )
+ @web.expose
+ @web.require_admin
+ def install_tool_shed_repository( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ tool_shed_url = kwd[ 'tool_shed_url' ]
+ repository_name = kwd[ 'repository_name' ]
+ changeset_revision = kwd[ 'changeset_revision' ]
+ repository_clone_url = kwd[ 'repository_clone_url' ]
+ if kwd.get( 'select_tool_panel_section_button', False ):
+ shed_tool_conf = kwd[ 'shed_tool_conf' ]
+ # Get the tool path.
+ for k, tool_path in trans.app.toolbox.shed_tool_confs.items():
+ if k == shed_tool_conf:
+ break
+ if 'tool_panel_section' in kwd:
+ section_key = 'section_%s' % kwd[ 'tool_panel_section' ]
+ tool_section = trans.app.toolbox.tool_panel[ section_key ]
+ # Clone the repository to the configured location.
+ current_working_dir = os.getcwd()
+ clone_dir = os.path.join( tool_path, self.__generate_tool_path( repository_clone_url, changeset_revision ) )
+ if os.path.exists( clone_dir ):
+ # Repository and revision has already been cloned.
+ # TODO: implement the ability to re-install or revert an existing repository.
+ message = 'Revision <b>%s</b> of repository <b>%s</b> has already been installed. Updating an existing repository is not yet supported.' % \
+ ( changeset_revision, repository_name )
+ status = 'error'
+ else:
+ os.makedirs( clone_dir )
+ cmd = 'hg clone %s' % repository_clone_url
+ log.debug( 'Cloning: %s' % repository_clone_url )
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( clone_dir )
+ proc = subprocess.Popen( args=cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode == 0:
+ repo_files_dir = os.path.join( clone_dir, repository_name )
+ log.debug( 'Updating cloned repository to revision: %s' % changeset_revision )
+ cmd = 'hg update -r %s' % changeset_revision
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( repo_files_dir )
+ proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode == 0:
+ # The repository_tools_tups list contains tuples of ( relative_path_to_tool_config, tool ) pairs
+ repository_tools_tups = []
+ for root, dirs, files in os.walk( repo_files_dir ):
+ if not root.find( '.hg' ) >= 0 and not root.find( 'hgrc' ) >= 0:
+ if '.hg' in dirs:
+ # Don't visit .hg directories - should be impossible since we don't
+ # allow uploaded archives that contain .hg dirs, but just in case...
+ dirs.remove( '.hg' )
+ if 'hgrc' in files:
+ # Don't include hgrc files in commit.
+ files.remove( 'hgrc' )
+ for name in files:
+ # Find all tool configs.
+ if name.endswith( '.xml' ):
+ relative_path = os.path.join( root, name )
+ full_path = os.path.abspath( os.path.join( root, name ) )
+ try:
+ repository_tool = trans.app.toolbox.load_tool( full_path )
+ if repository_tool:
+ repository_tools_tups.append( ( relative_path.lstrip( '%s/' % tool_path ), repository_tool ) )
+ except Exception, e:
+ # We have an inavlid .xml file, so not a tool config.
+ log.debug("Ignoring invalid tool config (%s)." % str( relative_path ))
+ if repository_tools_tups:
+ # Generate an in-memory tool conf section that includes the new tools.
+ new_tool_section = self.__generate_tool_panel_section( repository_name,
+ repository_clone_url,
+ changeset_revision,
+ tool_section,
+ repository_tools_tups )
+ # Create a temporary file to persist the in-memory tool section
+ # TODO: Figure out how to do this in-memory using xml.etree.
+ tmp_name = tempfile.NamedTemporaryFile().name
+ persisted_new_tool_section = open( tmp_name, 'wb' )
+ persisted_new_tool_section.write( new_tool_section )
+ persisted_new_tool_section.close()
+ # Parse the persisted tool panel section
+ tree = ElementTree.parse( tmp_name )
+ root = tree.getroot()
+ ElementInclude.include( root )
+ # Load the tools in the section into the tool panel.
+ trans.app.toolbox.load_section_tag_set( root, trans.app.toolbox.tool_panel, tool_path )
+ # Remove the temporary file
+ try:
+ os.unlink( tmp_name )
+ except:
+ pass
+ # Append the new section to the shed_tool_config file.
+ self.__add_shed_tool_conf_entry( trans, shed_tool_conf, new_tool_section )
+ message = 'Revision <b>%s</b> of repository <b>%s</b> has been installed in tool panel section <b>%s</b>.' % \
+ ( changeset_revision, repository_name, tool_section.name )
+ return trans.show_ok_message( message )
+ else:
+ tmp_stderr = open( tmp_name, 'rb' )
+ message = tmp_stderr.read()
+ tmp_stderr.close()
+ status = 'error'
+ else:
+ tmp_stderr = open( tmp_name, 'rb' )
+ message = tmp_stderr.read()
+ tmp_stderr.close()
+ status = 'error'
+ else:
+ message = 'Choose the section in your tool panel to contain the installed tools.'
+ status = 'error'
+ if len( trans.app.toolbox.shed_tool_confs.keys() ) > 1:
+ shed_tool_conf_select_field = build_shed_tool_conf_select_field( trans )
+ shed_tool_conf = None
+ else:
+ shed_tool_conf = trans.app.toolbox.shed_tool_confs.keys()[0].lstrip( './' )
+ shed_tool_conf_select_field = None
+ tool_panel_section_select_field = build_tool_panel_section_select_field( trans )
+ return trans.fill_template( '/admin/select_tool_panel_section.mako',
+ tool_shed_url=tool_shed_url,
+ repository_name=repository_name,
+ changeset_revision=changeset_revision,
+ repository_clone_url=repository_clone_url,
+ shed_tool_conf=shed_tool_conf,
+ shed_tool_conf_select_field=shed_tool_conf_select_field,
+ tool_panel_section_select_field=tool_panel_section_select_field,
+ message=message,
+ status=status )
+ def __add_shed_tool_conf_entry( self, trans, shed_tool_conf, new_tool_section ):
+ # Add an entry in the shed_tool_conf file. An entry looks something like:
+ # <section name="Filter and Sort" id="filter">
+ # <tool file="filter/filtering.xml" guid="toolshed.g2.bx.psu.edu/repos/test/filter/1.0.2"/>
+ # </section>
+ # Make a backup of the hgweb.config file since we're going to be changing it.
+ if not os.path.exists( shed_tool_conf ):
+ output = open( shed_tool_conf, 'w' )
+ output.write( '<?xml version="1.0"?>\n' )
+ output.write( '<toolbox tool_path="%s">\n' % tool_path )
+ output.write( '</toolbox>\n' )
+ output.close()
+ self.__make_shed_tool_conf_copy( trans, shed_tool_conf )
+ tmp_fd, tmp_fname = tempfile.mkstemp()
+ new_shed_tool_conf = open( tmp_fname, 'wb' )
+ for i, line in enumerate( open( shed_tool_conf ) ):
+ if line.startswith( '</toolbox>' ):
+ # We're at the end of the original config file, so add our entry.
+ new_shed_tool_conf.write( new_tool_section )
+ new_shed_tool_conf.write( line )
+ else:
+ new_shed_tool_conf.write( line )
+ new_shed_tool_conf.close()
+ shutil.move( tmp_fname, os.path.abspath( shed_tool_conf ) )
+ def __make_shed_tool_conf_copy( self, trans, shed_tool_conf ):
+ # Make a backup of the shed_tool_conf file.
+ today = date.today()
+ backup_date = today.strftime( "%Y_%m_%d" )
+ shed_tool_conf_copy = '%s/%s_%s_backup' % ( trans.app.config.root, shed_tool_conf, backup_date )
+ shutil.copy( os.path.abspath( shed_tool_conf ), os.path.abspath( shed_tool_conf_copy ) )
+ def __clean_tool_shed_url( self, tool_shed_url ):
+ if tool_shed_url.find( ':' ) > 0:
+ # Eliminate the port, if any, since it will result in an invalid directory name.
+ return tool_shed_url.split( ':' )[ 0 ]
+ return tool_shed_url
+ def __clean_repository_clone_url( self, repository_clone_url ):
+ if repository_clone_url.find( '@' ) > 0:
+ # We have an url that includes an authenticated user, something like:
+ # http://test@bx.psu.edu:9009/repos/some_username/column
+ items = repository_clone_url.split( '@' )
+ tmp_url = items[ 1 ]
+ elif repository_clone_url.find( '\/\/' ) > 0:
+ # We have an url that includes only a protocol, something like:
+ # http://bx.psu.edu:9009/repos/some_username/column
+ items = repository_clone_url.split( '\/\/' )
+ tmp_url = items[ 1 ]
+ else:
+ tmp_url = repository_clone_url
+ return tmp_url
+ def __get_repository_owner( self, cleaned_repository_url ):
+ items = cleaned_repository_url.split( 'repos' )
+ repo_path = items[ 1 ]
+ return repo_path.lstrip( '/' ).split( '/' )[ 0 ]
+ def __generate_tool_path( self, repository_clone_url, changeset_revision ):
+ """
+ Generate a tool path that guarantees repositories with the same name will always be installed
+ in different directories. The tool path will be of the form:
+ <tool shed url>/repos/<repository owner>/<repository name>/<changeset revision>
+ http://test@gvk.bx.psu.edu:9009/repos/test/filter
+ """
+ tmp_url = self.__clean_repository_clone_url( repository_clone_url )
+ # Now tmp_url is something like: bx.psu.edu:9009/repos/some_username/column
+ items = tmp_url.split( 'repos' )
+ tool_shed_url = items[ 0 ]
+ repo_path = items[ 1 ]
+ tool_shed_url = self.__clean_tool_shed_url( tool_shed_url )
+ return '%s/repos%s/%s' % ( tool_shed_url, repo_path, changeset_revision )
+ def __generate_tool_guid( self, repository_clone_url, tool ):
+ """
+ Generate a guid for the installed tool. It is critical that this guid matches the guid for
+ the tool in the Galaxy tool shed from which it is being installed. The form of the guid is
+ <tool shed host>/repos/<repository owner>/<repository name>/<tool id>/<tool version>
+ """
+ tmp_url = self.__clean_repository_clone_url( repository_clone_url )
+ return '%s/%s/%s' % ( tmp_url, tool.id, tool.version )
+ def __generate_tool_panel_section( self, repository_name, repository_clone_url, changeset_revision, tool_section, repository_tools_tups ):
+ """
+ Write an in-memory tool panel section so we can load it into the tool panel and then
+ append it to the appropriate shed tool config.
+ """
+ tmp_url = self.__clean_repository_clone_url( repository_clone_url )
+ section_str = ''
+ section_str += ' <section name="%s" id="%s">\n' % ( tool_section.name, tool_section.id )
+ for repository_tool_tup in repository_tools_tups:
+ tool_file_path, tool = repository_tool_tup
+ guid = self.__generate_tool_guid( repository_clone_url, tool )
+ section_str += ' <tool file="%s" guid="%s">\n' % ( tool_file_path, guid )
+ section_str += ' <tool_shed>%s</tool_shed>\n' % tmp_url.split( 'repos' )[ 0 ].rstrip( '/' )
+ section_str += ' <repository_name>%s</repository_name>\n' % repository_name
+ section_str += ' <repository_owner>%s</repository_owner>\n' % self.__get_repository_owner( tmp_url )
+ section_str += ' <changeset_revision>%s</changeset_revision>\n' % changeset_revision
+ section_str += ' <id>%s</id>\n' % tool.id
+ section_str += ' <version>%s</version>\n' % tool.version
+ section_str += ' </tool>\n'
+ section_str += ' </section>\n'
+ return section_str
## ---- Utility methods -------------------------------------------------------
+def build_shed_tool_conf_select_field( trans ):
+ """
+ Build a SelectField whose options are the keys in trans.app.toolbox.shed_tool_confs.
+ """
+ options = []
+ for shed_tool_conf_filename, tool_path in trans.app.toolbox.shed_tool_confs.items():
+ options.append( ( shed_tool_conf_filename.lstrip( './' ), shed_tool_conf_filename ) )
+ select_field = SelectField( name='shed_tool_conf' )
+ for option_tup in options:
+ select_field.add_option( option_tup[0], option_tup[1] )
+ return select_field
+def build_tool_panel_section_select_field( trans ):
+ """
+ Build a SelectField whose options are the sections of the current in-memory toolbox.
+ """
+ options = []
+ for k, tool_section in trans.app.toolbox.tool_panel.items():
+ options.append( ( tool_section.name, tool_section.id ) )
+ select_field = SelectField( name='tool_panel_section', display='radio' )
+ for option_tup in options:
+ select_field.add_option( option_tup[0], option_tup[1] )
+ return select_field
def get_user( trans, id ):
"""Get a User from the database by id."""
# Load user from database
--- a/lib/galaxy/webapps/community/controllers/common.py Fri Sep 02 14:57:33 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/common.py Fri Sep 02 14:59:31 2011 -0400
@@ -145,6 +145,14 @@
# The received metadata_dict includes no metadata for workflows, so a new repository_metadata table
# record is not needed.
return False
+def generate_clone_url( trans, repository_id ):
+ repository = get_repository( trans, repository_id )
+ protocol, base = trans.request.base.split( '://' )
+ if trans.user:
+ username = '%s@' % trans.user.username
+ else:
+ username = ''
+ return '%s://%s%s/repos/%s/%s' % ( protocol, username, base, repository.user.username, repository.name )
def generate_tool_guid( trans, repository, tool ):
"""
Generate a guid for the received tool. The form of the guid is
@@ -478,7 +486,7 @@
ToolClass = Tool
return ToolClass( config_file, root, trans.app )
return None
-def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True ):
+def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True, galaxy_url=None ):
"""
Build a SelectField whose options are the changeset_revision
strings of all downloadable_revisions of the received repository.
@@ -492,9 +500,15 @@
options.append( ( revision_label, changeset_revision ) )
refresh_on_change_values.append( changeset_revision )
if add_id_to_name:
- name = 'changeset_revision_%d' % repository.id
+ if galaxy_url:
+ name = '%s_changeset_revision_%d' % ( galaxy_url, repository.id )
+ else:
+ name = 'changeset_revision_%d' % repository.id
else:
- name = 'changeset_revision'
+ if galaxy_url:
+ name = '%s_changeset_revision' % galaxy_url
+ else:
+ name = 'changeset_revision'
select_field = SelectField( name=name,
refresh_on_change=True,
refresh_on_change_values=refresh_on_change_values )
--- a/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 02 14:57:33 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 02 14:59:31 2011 -0400
@@ -123,6 +123,7 @@
return 'yes'
return ''
# Grid definition
+ galaxy_url = None
title = "Repositories"
model_class = model.Repository
template='/webapps/community/repository/grid.mako'
@@ -183,8 +184,48 @@
.outerjoin( model.RepositoryCategoryAssociation.table ) \
.outerjoin( model.Category.table )
+class DownloadableRepositoryListGrid( RepositoryListGrid ):
+ class RevisionColumn( grids.GridColumn ):
+ def __init__( self, col_name ):
+ grids.GridColumn.__init__( self, col_name )
+ def get_value( self, trans, grid, repository ):
+ """
+ Display a SelectField whose options are the changeset_revision
+ strings of all downloadable_revisions of this repository.
+ """
+ select_field = build_changeset_revision_select_field( trans,
+ repository,
+ galaxy_url=grid.galaxy_url )
+ if len( select_field.options ) > 1:
+ return select_field.get_html()
+ return repository.revision
+ columns = [
+ RepositoryListGrid.NameColumn( "Name",
+ key="name",
+ attach_popup=True ),
+ RepositoryListGrid.DescriptionColumn( "Synopsis",
+ key="description",
+ attach_popup=False ),
+ RevisionColumn( "Revision" ),
+ RepositoryListGrid.UserColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ operations = []
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( self.model_class ) \
+ .join( model.RepositoryMetadata.table ) \
+ .join( model.User.table )
+
class RepositoryController( BaseController, ItemRatings ):
+ downloadable_repository_list_grid = DownloadableRepositoryListGrid()
repository_list_grid = RepositoryListGrid()
category_list_grid = CategoryListGrid()
@@ -215,6 +256,111 @@
# Render the list view
return self.category_list_grid( trans, **kwd )
@web.expose
+ def browse_downloadable_repositories( self, trans, **kwd ):
+ tool_shed_name = kwd.get( 'tool_shed_name', None )
+ repository_id = kwd.get( 'id', None )
+ galaxy_url = kwd.get( 'galaxy_url', None )
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "preview_tools_in_changeset":
+ repository = get_repository( trans, repository_id )
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='preview_tools_in_changeset',
+ repository_id=repository_id,
+ changeset_revision=repository.tip,
+ galaxy_url=galaxy_url ) )
+
+ # The changeset_revision_select_field in the RepositoryListGrid performs a refresh_on_change
+ # which sends in request parameters like changeset_revison_1, changeset_revision_2, etc. One
+ # of the many select fields on the grid performed the refresh_on_change, so we loop through
+ # all of the received values to see which value is not the repository tip. If we find it, we
+ # know the refresh_on_change occurred, and we have the necessary repository id and change set
+ # revision to pass on.
+ for k, v in kwd.items():
+ changset_revision_str = 'changeset_revision_'
+ if k.startswith( changset_revision_str ):
+ repository_id = trans.security.encode_id( int( k.lstrip( changset_revision_str ) ) )
+ repository = get_repository( trans, repository_id )
+ if repository.tip != v:
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='preview_tools_in_changeset',
+ repository_id=trans.security.encode_id( repository.id ),
+ changeset_revision=v,
+ galaxy_url=galaxy_url ) )
+ elif k.find( changset_revision_str ) > 0:
+ # Keys look like: 'localhost:8763_changeset_revision_3' and values: '4ef2cf631604'.
+ items = k.split( '_%s' % changset_revision_str )
+ galaxy_url = items[0]
+ repository_id = trans.security.encode_id( int( items[1] ) )
+ repository = get_repository( trans, repository_id )
+ if repository.tip != v:
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='preview_tools_in_changeset',
+ repository_id=trans.security.encode_id( repository.id ),
+ changeset_revision=v,
+ galaxy_url=galaxy_url ) )
+
+ if tool_shed_name:
+ title = "%s downloadable repositories" % tool_shed_name
+ else:
+ title = "Downloadable repositories"
+ self.downloadable_repository_list_grid.title = title
+ self.downloadable_repository_list_grid.galaxy_url = galaxy_url
+ url_args = dict( action='browse_downloadable_repositories',
+ operation='preview_tools_in_changeset',
+ repository_id=repository_id,
+ galaxy_url=galaxy_url )
+ self.downloadable_repository_list_grid.operations = [ grids.GridOperation( "Preview and install tools",
+ url_args=url_args,
+ allow_multiple=False,
+ async_compatible=False ) ]
+
+ # Render the list view
+ return self.downloadable_repository_list_grid( trans, **kwd )
+ @web.expose
+ def preview_tools_in_changeset( self, trans, repository_id, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ galaxy_url = util.restore_text( params.get( 'galaxy_url', '' ) )
+ repository = get_repository( trans, repository_id )
+ changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip ) )
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ else:
+ metadata = None
+ revision_label = get_revision_label( trans, repository, changeset_revision )
+ changeset_revision_select_field = build_changeset_revision_select_field( trans,
+ repository,
+ selected_value=changeset_revision,
+ add_id_to_name=False )
+ return trans.fill_template( '/webapps/community/repository/preview_tools_in_changeset.mako',
+ repository=repository,
+ changeset_revision=changeset_revision,
+ revision_label=revision_label,
+ changeset_revision_select_field=changeset_revision_select_field,
+ metadata=metadata,
+ galaxy_url=galaxy_url,
+ display_for_install=True,
+ message=message,
+ status=status )
+ @web.expose
+ def install_repository_revision( self, trans, repository_id, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ galaxy_url = util.restore_text( params.get( 'galaxy_url', '' ) )
+ repository = get_repository( trans, repository_id )
+ changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip ) )
+ # Redirect back to local Galaxy to perform install.
+ tool_shed_url = trans.request.host
+ repository_clone_url = generate_clone_url( trans, repository_id )
+ # TODO: support https in the following url.
+ url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&repository_name=%s&repository_clone_url=%s&changeset_revision=%s' % \
+ ( galaxy_url, tool_shed_url, repository.name, repository_clone_url, changeset_revision )
+ return trans.response.send_redirect( url )
+ @web.expose
def browse_repositories( self, trans, **kwd ):
# We add params to the keyword dict in this method in order to rename the param
# with an "f-" prefix, simulating filtering by clicking a search link. We have
@@ -1079,45 +1225,57 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
+ galaxy_url = util.restore_text( params.get( 'galaxy_url', '' ) )
+ display_for_install = util.string_as_bool( params.get( 'display_for_install', False ) )
repository = get_repository( trans, repository_id )
- old_version_msg = "The path to your selected version of this tool does not exist in the repository tip, " + \
- "so it cannot be previewed, but you can inspect the tool version's metadata using it's pop-up menu " + \
- "and you can download your selected version of this tool from the <b>Repository Actions</b> menu."
+ repo = hg.repository( get_configured_ui(), repository.repo_path )
try:
- tool = load_tool( trans, os.path.abspath( tool_config ) )
- can_preview = True
- if changeset_revision != repository.tip:
- # See if we are attempting to preview an old version of a tool.
- # TODO: Previewing an old version of a tool is not currently supported because
- # the received tool_config is a file on the file system. We need to implement
- # an enhancement here to look at the repository manifest files if previewing an
- # old version of a tool.
- repo_changeset_repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
- repo_changeset_metadata = repo_changeset_repository_metadata.metadata
- if 'tools' in repo_changeset_metadata:
- for tool_metadata_dict in repo_changeset_metadata[ 'tools' ]:
- if tool_metadata_dict[ 'id' ] == tool.id:
- if tool_metadata_dict[ 'version' ] != tool.version:
- can_preview = False
- message = old_version_msg
- if can_preview:
- tool_state = self.__new_state( trans )
- is_malicious = change_set_is_malicious( trans, repository_id, repository.tip )
- return trans.fill_template( "/webapps/community/repository/tool_form.mako",
- repository=repository,
- tool=tool,
- tool_state=tool_state,
- is_malicious=is_malicious,
- message=message,
- status=status )
+ if changeset_revision == repository.tip:
+ # Get the tool config from the file system we use for browsing.
+ tool = load_tool( trans, os.path.abspath( tool_config ) )
+ else:
+ # Get the tool config file name from the hgweb url, something like:
+ # /repos/test/convert_chars1/file/e58dcf0026c7/convert_characters.xml
+ old_tool_config_file_name = tool_config.split( '/' )[ -1 ]
+ ctx = get_changectx_for_changeset( trans, repo, changeset_revision )
+ for filename in ctx:
+ if filename == old_tool_config_file_name:
+ fctx = ctx[ filename ]
+ break
+ # Write the contents of the old tool config to a temporary file.
+ fh = tempfile.NamedTemporaryFile( 'w' )
+ tmp_filename = fh.name
+ fh.close()
+ fh = open( tmp_filename, 'w' )
+ fh.write( fctx.data() )
+ fh.close()
+ tool = load_tool( trans, tmp_filename )
+ try:
+ os.unlink( tmp_filename )
+ except:
+ pass
+ tool_state = self.__new_state( trans )
+ is_malicious = change_set_is_malicious( trans, repository_id, repository.tip )
+ return trans.fill_template( "/webapps/community/repository/tool_form.mako",
+ repository=repository,
+ changeset_revision=changeset_revision,
+ tool=tool,
+ tool_state=tool_state,
+ is_malicious=is_malicious,
+ display_for_install=display_for_install,
+ galaxy_url=galaxy_url,
+ message=message,
+ status=status )
except Exception, e:
- # TODO: enhance this to check the repository manifest for the files and
- # display the tool using them.
- exception_str = str( e )
- if exception_str.find( 'No such file or directory' ) >= 0:
- message = old_version_msg
- else:
- message = "Error loading tool: %s. Click <b>Reset metadata</b> to correct this error." % exception_str
+ message = "Error loading tool: %s. Click <b>Reset metadata</b> to correct this error." % str( e )
+ if display_for_install:
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='preview_tools_in_changeset',
+ repository_id=repository_id,
+ changeset_revision=changeset_revision,
+ galaxy_url=galaxy_url,
+ message=message,
+ status='error' ) )
return trans.response.send_redirect( web.url_for( controller='repository',
action='browse_repositories',
operation='view_or_manage_repository',
--- a/templates/webapps/community/repository/common.mako Fri Sep 02 14:57:33 2011 -0400
+++ b/templates/webapps/community/repository/common.mako Fri Sep 02 14:59:31 2011 -0400
@@ -77,12 +77,121 @@
<%def name="render_clone_str( repository )"><%
- protocol, base = trans.request.base.split( '://' )
- if trans.user:
- username = '%s@' % trans.user.username
- else:
- username = ''
- clone_str = '%s://%s%s/repos/%s/%s' % ( protocol, username, base, repository.user.username, repository.name )
+ from galaxy.webapps.community.controllers.common import generate_clone_url
+ clone_str = generate_clone_url( trans, trans.security.encode_id( repository.id ) )
%>
hg clone <a href="${clone_str}">${clone_str}</a></%def>
+
+<%def name="render_repository_tools_and_workflows( metadata, can_set_metadata=False, display_for_install=False, galaxy_url=None )">
+ %if metadata or can_set_metadata:
+ <p/>
+ <div class="toolForm">
+ <div class="toolFormTitle">Preview tools and inspect metadata by tool version</div>
+ <div class="toolFormBody">
+ %if metadata:
+ %if 'tools' in metadata:
+ <div class="form-row">
+ <table width="100%">
+ <tr bgcolor="#D8D8D8" width="100%">
+ <td><b>Tools</b><i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i></td>
+ </tr>
+ </table>
+ </div>
+ <div class="form-row">
+ <% tool_dicts = metadata[ 'tools' ] %>
+ <table class="grid">
+ <tr>
+ <td><b>name</b></td>
+ <td><b>description</b></td>
+ <td><b>version</b></td>
+ <td><b>requirements</b></td>
+ </tr>
+ %for tool_dict in tool_dicts:
+ <tr>
+ <td>
+ <div style="float: left; margin-left: 1px;" class="menubutton split popup" id="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
+ <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ], changeset_revision=changeset_revision, display_for_install=display_for_install, galaxy_url=galaxy_url )}">
+ ${tool_dict[ 'name' ]}
+ </a>
+ </div>
+ <div popupmenu="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, tool_id=tool_dict[ 'id' ], display_for_install=display_for_install, galaxy_url=galaxy_url )}">View tool metadata</a>
+ </div>
+ </td>
+ <td>${tool_dict[ 'description' ]}</td>
+ <td>${tool_dict[ 'version' ]}</td>
+ <td>
+ <%
+ if 'requirements' in tool_dict:
+ requirements = tool_dict[ 'requirements' ]
+ else:
+ requirements = None
+ %>
+ %if requirements:
+ <%
+ requirements_str = ''
+ for requirement_dict in tool_dict[ 'requirements' ]:
+ requirements_str += '%s (%s), ' % ( requirement_dict[ 'name' ], requirement_dict[ 'type' ] )
+ requirements_str = requirements_str.rstrip( ', ' )
+ %>
+ ${requirements_str}
+ %else:
+ none
+ %endif
+ </td>
+ </tr>
+ %endfor
+ </table>
+ </div>
+ <div style="clear: both"></div>
+ %endif
+ %if 'workflows' in metadata:
+ <div class="form-row">
+ <table width="100%">
+ <tr bgcolor="#D8D8D8" width="100%">
+ <td><b>Workflows</b></td>
+ </tr>
+ </table>
+ </div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <% workflow_dicts = metadata[ 'workflows' ] %>
+ <table class="grid">
+ <tr>
+ <td><b>name</b></td>
+ <td><b>format-version</b></td>
+ <td><b>annotation</b></td>
+ </tr>
+ %for workflow_dict in workflow_dicts:
+ <tr>
+ <td>${workflow_dict[ 'name' ]}</td>
+ <td>${workflow_dict[ 'format-version' ]}</td>
+ <td>${workflow_dict[ 'annotation' ]}</td>
+ </tr>
+ %endfor
+ </table>
+ </div>
+ <div style="clear: both"></div>
+ %endif
+ %endif
+ %if can_set_metadata:
+ %if repository.tip == changeset_revision:
+ ## TODO: when we support previewing older versions of tools, we
+ ## should allow resetting metadata on the older versions as well.
+ <form name="set_metadata" action="${h.url_for( controller='repository', action='set_metadata', id=trans.security.encode_id( repository.id ), ctx_str=changeset_revision )}" method="post">
+ <div class="form-row">
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="submit" name="set_metadata_button" value="Reset metadata"/>
+ </div>
+ <div class="toolParamHelp" style="clear: both;">
+ Inspect the repository and reset the above attributes for the repository tip.
+ </div>
+ </div>
+ </form>
+ %endif
+ %endif
+ </div>
+ </div>
+ %endif
+</%def>
--- a/templates/webapps/community/repository/manage_repository.mako Fri Sep 02 14:57:33 2011 -0400
+++ b/templates/webapps/community/repository/manage_repository.mako Fri Sep 02 14:59:31 2011 -0400
@@ -184,114 +184,7 @@
</form></div></div>
-%if can_set_metadata:
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Preview tools in repository tip and inspect metadata by tool version</div>
- <div class="toolFormBody">
- %if metadata:
- %if 'tools' in metadata:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Tools</b><i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i></td>
- </tr>
- </table>
- </div>
- <div class="form-row">
- <% tool_dicts = metadata[ 'tools' ] %>
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>description</b></td>
- <td><b>version</b></td>
- <td><b>requirements</b></td>
- </tr>
- %for tool_dict in tool_dicts:
- <tr>
- <td>
- <div style="float: left; margin-left: 1px;" class="menubutton split popup" id="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
- <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ], changeset_revision=changeset_revision )}">
- ${tool_dict[ 'name' ]}
- </a>
- </div>
- <div popupmenu="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, tool_id=tool_dict[ 'id' ] )}">View tool metadata</a>
- </div>
- </td>
- <td>${tool_dict[ 'description' ]}</td>
- <td>${tool_dict[ 'version' ]}</td>
- <td>
- <%
- if 'requirements' in tool_dict:
- requirements = tool_dict[ 'requirements' ]
- else:
- requirements = None
- %>
- %if requirements:
- <%
- requirements_str = ''
- for requirement_dict in tool_dict[ 'requirements' ]:
- requirements_str += '%s (%s), ' % ( requirement_dict[ 'name' ], requirement_dict[ 'type' ] )
- requirements_str = requirements_str.rstrip( ', ' )
- %>
- ${requirements_str}
- %else:
- none
- %endif
- </td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %if 'workflows' in metadata:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Workflows</b></td>
- </tr>
- </table>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <% workflow_dicts = metadata[ 'workflows' ] %>
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>format-version</b></td>
- <td><b>annotation</b></td>
- </tr>
- %for workflow_dict in workflow_dicts:
- <tr>
- <td>${workflow_dict[ 'name' ]}</td>
- <td>${workflow_dict[ 'format-version' ]}</td>
- <td>${workflow_dict[ 'annotation' ]}</td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %endif
- %if repository.tip == changeset_revision:
- ## TODO: when we support previewing older versions of tools, we
- ## should allow resetting metadata on the older versions as well.
- <form name="set_metadata" action="${h.url_for( controller='repository', action='set_metadata', id=trans.security.encode_id( repository.id ), ctx_str=changeset_revision )}" method="post">
- <div class="form-row">
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="submit" name="set_metadata_button" value="Reset metadata"/>
- </div>
- <div class="toolParamHelp" style="clear: both;">
- Inspect the repository and reset the above attributes for the repository tip.
- </div>
- </div>
- </form>
- %endif
- </div>
- </div>
-%endif
+${render_repository_tools_and_workflows( metadata, can_set_metadata=True )}
<p/><div class="toolForm"><div class="toolFormTitle">Manage categories</div>
--- a/templates/webapps/community/repository/tool_form.mako Fri Sep 02 14:57:33 2011 -0400
+++ b/templates/webapps/community/repository/tool_form.mako Fri Sep 02 14:59:31 2011 -0400
@@ -25,7 +25,7 @@
<html><head>
- <title>Galaxy tool display</title>
+ <title>Galaxy tool preview</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
${h.css( "base" )}
</head>
@@ -110,37 +110,41 @@
<br/><br/><ul class="manage-table-actions">
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %if display_for_install:
+ <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp='community', changeset_revision=changeset_revision, galaxy_url=galaxy_url )}">Install to local Galaxy</a>
%else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp='community' )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
+ %if is_new:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
+ %endif
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp='community' )}">Contact repository owner</a>
+ %endif
+ %if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
+ %endif
+ </div>
+ %endif
%endif
</ul>
@@ -149,7 +153,7 @@
%endif
<div class="toolForm" id="${tool.id}">
- <div class="toolFormTitle">${tool.name} ${tool.version}</div>
+ <div class="toolFormTitle">${tool.name} (version ${tool.version})</div><div class="toolFormBody"><form id="tool_form" name="tool_form" action="" method="get"><input type="hidden" name="tool_state" value="${util.object_to_string( tool_state.encode( tool, app ) )}">
--- a/templates/webapps/community/repository/view_repository.mako Fri Sep 02 14:57:33 2011 -0400
+++ b/templates/webapps/community/repository/view_repository.mako Fri Sep 02 14:59:31 2011 -0400
@@ -176,98 +176,7 @@
%endif
</div></div>
-%if metadata:
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Preview tools in repository tip and inspect metadata by tool version</div>
- <div class="toolFormBody">
- %if 'tools' in metadata:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Tools</b><i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i></td>
- </tr>
- </table>
- </div>
- <div class="form-row">
- <% tool_dicts = metadata[ 'tools' ] %>
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>description</b></td>
- <td><b>version</b></td>
- <td><b>requirements</b></td>
- </tr>
- %for tool_dict in tool_dicts:
- <tr>
- <td>
- <div style="float: left; margin-left: 1px;" class="menubutton split popup" id="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
- <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ], changeset_revision=changeset_revision )}">
- ${tool_dict[ 'name' ]}
- </a>
- </div>
- <div popupmenu="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, tool_id=tool_dict[ 'id' ] )}">View tool metadata</a>
- </div>
- </td>
- <td>${tool_dict[ 'description' ]}</td>
- <td>${tool_dict[ 'version' ]}</td>
- <td>
- <%
- if 'requirements' in tool_dict:
- requirements = tool_dict[ 'requirements' ]
- else:
- requirements = None
- %>
- %if requirements:
- <%
- requirements_str = ''
- for requirement_dict in tool_dict[ 'requirements' ]:
- requirements_str += '%s (%s), ' % ( requirement_dict[ 'name' ], requirement_dict[ 'type' ] )
- requirements_str = requirements_str.rstrip( ', ' )
- %>
- ${requirements_str}
- %else:
- none
- %endif
- </td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %if 'workflows' in metadata:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Workflows</b></td>
- </tr>
- </table>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <% workflow_dicts = metadata[ 'workflows' ] %>
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>format-version</b></td>
- <td><b>annotation</b></td>
- </tr>
- %for workflow_dict in workflow_dicts:
- <tr>
- <td>${workflow_dict[ 'name' ]}</td>
- <td>${workflow_dict[ 'format-version' ]}</td>
- <td>${workflow_dict[ 'annotation' ]}</td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- </div>
- </div>
-%endif
+${render_repository_tools_and_workflows( metadata )}
%if repository.categories:
<p/><div class="toolForm">
--- a/templates/webapps/galaxy/admin/index.mako Fri Sep 02 14:57:33 2011 -0400
+++ b/templates/webapps/galaxy/admin/index.mako Fri Sep 02 14:59:31 2011 -0400
@@ -39,57 +39,59 @@
<div class="page-container" style="padding: 10px;"><div class="toolMenu"><div class="toolSectionList">
- <div class="toolSectionTitle">
- Security
- </div>
+ <div class="toolSectionTitle">Security</div><div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='users', webapp=webapp )}" target="galaxy_main">Manage users</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='groups', webapp=webapp )}" target="galaxy_main">Manage groups</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='roles', webapp=webapp )}" target="galaxy_main">Manage roles</a></div>
- </div>
+ <div class="toolSectionBg">
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='users', webapp=webapp )}" target="galaxy_main">Manage users</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='groups', webapp=webapp )}" target="galaxy_main">Manage groups</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='roles', webapp=webapp )}" target="galaxy_main">Manage roles</a></div>
+ </div></div><div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Data
- </div>
+ <div class="toolSectionTitle">Data</div><div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='quotas', webapp=webapp )}" target="galaxy_main">Manage quotas</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='library_admin', action='browse_libraries' )}" target="galaxy_main">Manage data libraries</a></div>
- </div>
+ <div class="toolSectionBg">
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='quotas', webapp=webapp )}" target="galaxy_main">Manage quotas</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='library_admin', action='browse_libraries' )}" target="galaxy_main">Manage data libraries</a></div>
+ </div></div><div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Server
+ <div class="toolSectionTitle">Server</div>
+ <div class="toolSectionBody">
+ <div class="toolSectionBg">
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='reload_tool' )}" target="galaxy_main">Reload a tool's configuration</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='memdump' )}" target="galaxy_main">Profile memory usage</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='jobs' )}" target="galaxy_main">Manage jobs</a></div>
+ </div></div>
+ %if trans.app.tool_shed_registry and trans.app.tool_shed_registry.tool_sheds:
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">Tool sheds</div>
+ <div class="toolSectionBody">
+ <div class="toolSectionBg">
+ %for name, url in trans.app.tool_shed_registry.tool_sheds.items():
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_tool_shed', tool_shed_name=name, tool_shed_url=url )}" target="galaxy_main">${name}</a></div>
+ %endfor
+ </div>
+ </div>
+ </div>
+ %endif
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">Form Definitions</div><div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='reload_tool' )}" target="galaxy_main">Reload a tool's configuration</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='memdump' )}" target="galaxy_main">Profile memory usage</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='jobs' )}" target="galaxy_main">Manage jobs</a></div>
- </div>
+ <div class="toolSectionBg">
+ <div class="toolTitle"><a href="${h.url_for( controller='forms', action='browse_form_definitions' )}" target="galaxy_main">Manage form definitions</a></div>
+ </div></div><div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Form Definitions
- </div>
+ <div class="toolSectionTitle">Sample Tracking</div><div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle"><a href="${h.url_for( controller='forms', action='browse_form_definitions' )}" target="galaxy_main">Manage form definitions</a></div>
- </div>
- </div>
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Sample Tracking
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle"><a href="${h.url_for( controller='external_service', action='browse_external_services' )}" target="galaxy_main">Manage sequencers and external services</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='request_type', action='browse_request_types' )}" target="galaxy_main">Manage request types</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='requests_admin', action='browse_requests' )}" target="galaxy_main">Sequencing requests</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='requests_common', action='find_samples', cntrller='requests_admin' )}" target="galaxy_main">Find samples</a></div>
- </div>
+ <div class="toolSectionBg">
+ <div class="toolTitle"><a href="${h.url_for( controller='external_service', action='browse_external_services' )}" target="galaxy_main">Manage sequencers and external services</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='request_type', action='browse_request_types' )}" target="galaxy_main">Manage request types</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='requests_admin', action='browse_requests' )}" target="galaxy_main">Sequencing requests</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='requests_common', action='find_samples', cntrller='requests_admin' )}" target="galaxy_main">Find samples</a></div>
+ </div></div></div></div>
@@ -97,8 +99,6 @@
</%def><%def name="center_panel()">
- <%
- center_url = h.url_for( action='center', webapp='galaxy' )
- %>
+ <% center_url = h.url_for( action='center', webapp='galaxy' ) %><iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Enhance Galaxy tool initialization to do the following:
by Bitbucket 02 Sep '11
by Bitbucket 02 Sep '11
02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ad227f6403bb/
changeset: ad227f6403bb
user: greg
date: 2011-09-02 20:57:33
summary: Enhance Galaxy tool initialization to do the following:
1. Support multiple tool_conf.xml files with tool_conf.xml being the default. Additional files must use the tool shed XML rules.
2. Allow new added tools to be loaded into a selected tool panel section wothout requiring a Galaxy server restart.
3. Add a new tool shed registry, enabling configuring of tool sheds for communication with the local Galaxy instance.
Also add the version of the tool to the form heading when loaded into tool_fom.mako, and clean up the code for reloading a tool in the tool panel.
affected #: 9 files (2.5 KB)
--- a/lib/galaxy/app.py Fri Sep 02 14:37:09 2011 -0400
+++ b/lib/galaxy/app.py Fri Sep 02 14:57:33 2011 -0400
@@ -3,6 +3,7 @@
from galaxy import config, jobs, util, tools, web
import galaxy.tools.search
import galaxy.tools.data
+import galaxy.tools.tool_shed_registry
from galaxy.web import security
import galaxy.model
import galaxy.datatypes.registry
@@ -23,6 +24,11 @@
# Set up datatypes registry
self.datatypes_registry = galaxy.datatypes.registry.Registry( self.config.root, self.config.datatypes_config )
galaxy.model.set_datatypes_registry( self.datatypes_registry )
+ # Set up the tool sheds registry
+ if os.path.isfile( self.config.tool_sheds_config ):
+ self.tool_shed_registry = galaxy.tools.tool_shed_registry.Registry( self.config.root, self.config.tool_sheds_config )
+ else:
+ self.tool_shed_registry = None
# Determine the database url
if self.config.database_connection:
db_url = self.config.database_connection
@@ -44,7 +50,7 @@
# Tool data tables
self.tool_data_tables = galaxy.tools.data.ToolDataTableManager( self.config.tool_data_table_config_path )
# Initialize the tools
- self.toolbox = tools.ToolBox( self.config.tool_config, self.config.tool_path, self )
+ self.toolbox = tools.ToolBox( self.config.tool_configs, self.config.tool_path, self )
# Search support for tools
self.toolbox_search = galaxy.tools.search.ToolBoxSearch( self.toolbox )
# Load datatype converters
--- a/lib/galaxy/config.py Fri Sep 02 14:37:09 2011 -0400
+++ b/lib/galaxy/config.py Fri Sep 02 14:57:33 2011 -0400
@@ -5,7 +5,7 @@
import sys, os, tempfile
import logging, logging.config
import ConfigParser
-from galaxy.util import string_as_bool
+from galaxy.util import string_as_bool, listify
from galaxy import eggs
import pkg_resources
@@ -46,11 +46,12 @@
self.enable_api = string_as_bool( kwargs.get( 'enable_api', False ) )
self.enable_openid = string_as_bool( kwargs.get( 'enable_openid', False ) )
self.enable_quotas = string_as_bool( kwargs.get( 'enable_quotas', False ) )
+ self.tool_sheds_config = kwargs.get( 'tool_sheds_config_file', 'tool_sheds_conf.xml' )
self.tool_path = resolve_path( kwargs.get( "tool_path", "tools" ), self.root )
self.tool_data_path = resolve_path( kwargs.get( "tool_data_path", "tool-data" ), os.getcwd() )
self.len_file_path = kwargs.get( "len_file_path", resolve_path(os.path.join(self.tool_data_path, 'shared','ucsc','chrom'), self.root) )
self.test_conf = resolve_path( kwargs.get( "test_conf", "" ), self.root )
- self.tool_config = resolve_path( kwargs.get( 'tool_config_file', 'tool_conf.xml' ), self.root )
+ self.tool_configs = [ resolve_path( p, self.root ) for p in listify( kwargs.get( 'tool_config_file', 'tool_conf.xml' ) ) ]
self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root )
self.tool_secret = kwargs.get( "tool_secret", "" )
self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" )
@@ -194,9 +195,11 @@
except Exception, e:
raise ConfigurationError( "Unable to create missing directory: %s\n%s" % ( path, e ) )
# Check that required files exist
- for path in self.tool_config, self.datatypes_config:
+ for path in self.tool_configs:
if not os.path.isfile(path):
raise ConfigurationError("File not found: %s" % path )
+ if not os.path.isfile( self.datatypes_config ):
+ raise ConfigurationError("File not found: %s" % path )
# Check for deprecated options.
for key in self.config_dict.keys():
if key in self.deprecated_options:
--- a/lib/galaxy/tools/__init__.py Fri Sep 02 14:37:09 2011 -0400
+++ b/lib/galaxy/tools/__init__.py Fri Sep 02 14:57:33 2011 -0400
@@ -28,6 +28,7 @@
from galaxy.datatypes import sniff
from cgi import FieldStorage
from galaxy.util.hash_util import *
+from galaxy.util import listify
log = logging.getLogger( __name__ )
@@ -39,23 +40,28 @@
Container for a collection of tools
"""
- def __init__( self, config_filename, tool_root_dir, app ):
+ def __init__( self, config_filenames, tool_root_dir, app ):
"""
Create a toolbox from the config file names by `config_filename`,
using `tool_root_directory` as the base directory for finding
individual tool config files.
"""
+ # The shed_tool_confs dictionary contains shed_conf_filename : tool_path pairs.
+ self.shed_tool_confs = {}
self.tools_by_id = {}
self.workflows_by_id = {}
self.tool_panel = odict()
+ # The following refers to the tool_path config setting for backward compatibility.
+ # Additional newer (e.g., shed_tool_conf.xml) files include the tool_path attribute
+ # within the <toolbox> tag.
self.tool_root_dir = tool_root_dir
self.app = app
self.init_dependency_manager()
- try:
- self.init_tools( config_filename )
- except:
- log.exception( "ToolBox error reading %s", config_filename )
-
+ for config_filename in listify( config_filenames ):
+ try:
+ self.init_tools( config_filename )
+ except:
+ log.exception( "ToolBox error reading %s", config_filename )
def init_tools( self, config_filename ):
"""
Read the configuration file and load each tool.
@@ -71,83 +77,99 @@
</section></toolbox>
"""
- def load_tool( elem, panel_dict ):
- try:
- path = elem.get( "file" )
- tool = self.load_tool( os.path.join( self.tool_root_dir, path ) )
- if self.app.config.get_bool( 'enable_tool_tags', False ):
- tag_names = elem.get( "tags", "" ).split( "," )
- for tag_name in tag_names:
- if tag_name == '':
- continue
- tag = self.sa_session.query( self.app.model.Tag ).filter_by( name=tag_name ).first()
- if not tag:
- tag = self.app.model.Tag( name=tag_name )
- self.sa_session.add( tag )
- self.sa_session.flush()
- tta = self.app.model.ToolTagAssociation( tool_id=tool.id, tag_id=tag.id )
- self.sa_session.add( tta )
- self.sa_session.flush()
- else:
- for tagged_tool in tag.tagged_tools:
- if tagged_tool.tool_id == tool.id:
- break
- else:
- tta = self.app.model.ToolTagAssociation( tool_id=tool.id, tag_id=tag.id )
- self.sa_session.add( tta )
- self.sa_session.flush()
- self.tools_by_id[ tool.id ] = tool
- key = 'tool_' + tool.id
- panel_dict[ key ] = tool
- log.debug( "Loaded tool: %s %s" % ( tool.id, tool.version ) )
- except:
- log.exception( "error reading tool from path: %s" % path )
- def load_workflow( elem, panel_dict ):
- try:
- # TODO: should id be encoded?
- workflow_id = elem.get( 'id' )
- workflow = self.load_workflow( workflow_id )
- self.workflows_by_id[ workflow_id ] = workflow
- key = 'workflow_' + workflow_id
- panel_dict[ key ] = workflow
- log.debug( "Loaded workflow: %s %s" % ( workflow_id, workflow.name ) )
- except:
- log.exception( "error loading workflow: %s" % workflow_id )
- def load_label( elem, panel_dict ):
- label = ToolSectionLabel( elem )
- key = 'label_' + label.id
- panel_dict[ key ] = label
- def load_section( elem, panel_dict ):
- section = ToolSection( elem )
- log.debug( "Loading section: %s" % section.name )
- for section_elem in elem:
- if section_elem.tag == 'tool':
- load_tool( section_elem, section.elems )
- elif section_elem.tag == 'workflow':
- load_workflow( section_elem, section.elems )
- elif section_elem.tag == 'label':
- load_label( section_elem, section.elems )
- key = 'section_' + section.id
- panel_dict[ key ] = section
-
if self.app.config.get_bool( 'enable_tool_tags', False ):
log.info("removing all tool tag associations (" + str( self.sa_session.query( self.app.model.ToolTagAssociation ).count() ) + ")")
self.sa_session.query( self.app.model.ToolTagAssociation ).delete()
self.sa_session.flush()
- log.info("parsing the tool configuration")
+ log.info( "parsing the tool configuration %s" % config_filename )
tree = util.parse_xml( config_filename )
root = tree.getroot()
+ tool_path = root.get( 'tool_path' )
+ if tool_path:
+ # We're parsing a shed_tool_conf file since we have a tool_path attribute.
+ self.shed_tool_confs[ config_filename ] = tool_path
+ else:
+ # Default to backward compatible config setting.
+ tool_path = self.tool_root_dir
for elem in root:
if elem.tag == 'tool':
- load_tool( elem, self.tool_panel )
+ self.load_tool_tag_set( elem, self.tool_panel, tool_path, guid=elem.get( 'guid' ) )
elif elem.tag == 'workflow':
- load_workflow( elem, self.tool_panel )
+ self.load_workflow_tag_set( elem, self.tool_panel )
elif elem.tag == 'section' :
- load_section( elem, self.tool_panel )
+ self.load_section_tag_set( elem, self.tool_panel, tool_path )
elif elem.tag == 'label':
- load_label( elem, self.tool_panel )
-
- def load_tool( self, config_file ):
+ self.load_label_tag_set( elem, self.tool_panel )
+ def load_tool_tag_set( self, elem, panel_dict, tool_path, guid=None ):
+ try:
+ path = elem.get( "file" )
+ tool = self.load_tool( os.path.join( tool_path, path ), guid=guid )
+ if self.app.config.get_bool( 'enable_tool_tags', False ):
+ tag_names = elem.get( "tags", "" ).split( "," )
+ for tag_name in tag_names:
+ if tag_name == '':
+ continue
+ tag = self.sa_session.query( self.app.model.Tag ).filter_by( name=tag_name ).first()
+ if not tag:
+ tag = self.app.model.Tag( name=tag_name )
+ self.sa_session.add( tag )
+ self.sa_session.flush()
+ tta = self.app.model.ToolTagAssociation( tool_id=tool.id, tag_id=tag.id )
+ self.sa_session.add( tta )
+ self.sa_session.flush()
+ else:
+ for tagged_tool in tag.tagged_tools:
+ if tagged_tool.tool_id == tool.id:
+ break
+ else:
+ tta = self.app.model.ToolTagAssociation( tool_id=tool.id, tag_id=tag.id )
+ self.sa_session.add( tta )
+ self.sa_session.flush()
+ if tool.id in self.tools_by_id:
+ raise Exception( "Tool with id %s already loaded." % tool.id )
+ else:
+ self.tools_by_id[ tool.id ] = tool
+ key = 'tool_' + tool.id
+ panel_dict[ key ] = tool
+ log.debug( "Loaded tool: %s %s" % ( tool.id, tool.version ) )
+ except:
+ log.exception( "error reading tool from path: %s" % path )
+ def load_workflow_tag_set( self, elem, panel_dict ):
+ try:
+ # TODO: should id be encoded?
+ workflow_id = elem.get( 'id' )
+ workflow = self.load_workflow( workflow_id )
+ self.workflows_by_id[ workflow_id ] = workflow
+ key = 'workflow_' + workflow_id
+ panel_dict[ key ] = workflow
+ log.debug( "Loaded workflow: %s %s" % ( workflow_id, workflow.name ) )
+ except:
+ log.exception( "error loading workflow: %s" % workflow_id )
+ def load_label_tag_set( self, elem, panel_dict ):
+ label = ToolSectionLabel( elem )
+ key = 'label_' + label.id
+ panel_dict[ key ] = label
+ def load_section_tag_set( self, elem, panel_dict, tool_path ):
+ key = 'section_' + elem.get( "id" )
+ if key in panel_dict:
+ # Appending a tool to an existing section in self.tool_panel
+ elems = panel_dict[ key ].elems
+ log.debug( "Appending to section: %s" % elem.get( "name" ) )
+ else:
+ # Appending a new section to self.tool_panel
+ section = ToolSection( elem )
+ elems = section.elems
+ log.debug( "Loading section: %s" % section.name )
+ for section_elem in elem:
+ if section_elem.tag == 'tool':
+ self.load_tool_tag_set( section_elem, elems, tool_path, guid=section_elem.get( 'guid' ) )
+ elif section_elem.tag == 'workflow':
+ self.load_workflow_tag_set( section_elem, elems )
+ elif section_elem.tag == 'label':
+ self.load_label_tag_set( section_elem, elems )
+ if key not in panel_dict:
+ panel_dict[ key ] = section
+ def load_tool( self, config_file, guid=None ):
"""
Load a single tool from the file named by `config_file` and return
an instance of `Tool`.
@@ -160,38 +182,43 @@
type_elem = root.find( "type" )
module = type_elem.get( 'module', 'galaxy.tools' )
cls = type_elem.get( 'class' )
- mod = __import__( module, globals(), locals(), [cls])
+ mod = __import__( module, globals(), locals(), [cls] )
ToolClass = getattr( mod, cls )
elif root.get( 'tool_type', None ) is not None:
ToolClass = tool_types.get( root.get( 'tool_type' ) )
else:
ToolClass = Tool
- return ToolClass( config_file, root, self.app )
-
- def reload( self, tool_id ):
+ return ToolClass( config_file, root, self.app, guid=guid )
+ def reload_tool_by_id( self, tool_id ):
"""
Attempt to reload the tool identified by 'tool_id', if successful
replace the old tool.
"""
if tool_id not in self.tools_by_id:
- raise ToolNotFoundException( "No tool with id %s" % tool_id )
- old_tool = self.tools_by_id[ tool_id ]
- new_tool = self.load_tool( old_tool.config_file )
- # Replace old_tool with new_tool in self.tool_panel
- tool_key = 'tool_' + tool_id
- for key, val in self.tool_panel.items():
- if key == tool_key:
- self.tool_panel[ key ] = new_tool
- break
- elif key.startswith( 'section' ):
- section = val
- for section_key, section_val in section.elems.items():
- if section_key == tool_key:
- self.tool_panel[ key ].elems[ section_key ] = new_tool
- break
- self.tools_by_id[ tool_id ] = new_tool
- log.debug( "Reloaded tool %s %s" %( old_tool.id, old_tool.version ) )
-
+ message = "No tool with id %s" % tool_id
+ status = 'error'
+ else:
+ old_tool = self.tools_by_id[ tool_id ]
+ new_tool = self.load_tool( old_tool.config_file )
+ # Replace old_tool with new_tool in self.tool_panel
+ tool_key = 'tool_' + tool_id
+ for key, val in self.tool_panel.items():
+ if key == tool_key:
+ self.tool_panel[ key ] = new_tool
+ break
+ elif key.startswith( 'section' ):
+ section = val
+ for section_key, section_val in section.elems.items():
+ if section_key == tool_key:
+ self.tool_panel[ key ].elems[ section_key ] = new_tool
+ break
+ self.tools_by_id[ tool_id ] = new_tool
+ message = "Reloaded the tool:<br/>"
+ message += "<b>name:</b> %s<br/>" % old_tool.name
+ message += "<b>id:</b> %s<br/>" % old_tool.id
+ message += "<b>version:</b> %s" % old_tool.version
+ status = 'done'
+ return message, status
def load_workflow( self, workflow_id ):
"""
Return an instance of 'Workflow' identified by `id`,
@@ -328,7 +355,7 @@
tool_type = 'default'
- def __init__( self, config_file, root, app ):
+ def __init__( self, config_file, root, app, guid=None ):
"""
Load a tool from the config named by `config_file`
"""
@@ -337,7 +364,7 @@
self.tool_dir = os.path.dirname( config_file )
self.app = app
# Parse XML element containing configuration
- self.parse( root )
+ self.parse( root, guid=guid )
@property
def sa_session( self ):
@@ -346,7 +373,7 @@
"""
return self.app.model.context
- def parse( self, root ):
+ def parse( self, root, guid=None ):
"""
Read tool configuration from the element `root` and fill in `self`.
"""
@@ -356,7 +383,10 @@
raise Exception, "Missing tool 'name'"
# Get the UNIQUE id for the tool
# TODO: can this be generated automatically?
- self.id = root.get( "id" )
+ if guid is not None:
+ self.id = guid
+ else:
+ self.id = root.get( "id" )
if not self.id:
raise Exception, "Missing tool 'id'"
self.version = root.get( "version" )
--- a/templates/admin/reload_tool.mako Fri Sep 02 14:37:09 2011 -0400
+++ b/templates/admin/reload_tool.mako Fri Sep 02 14:57:33 2011 -0400
@@ -8,7 +8,7 @@
<div class="toolForm"><div class="toolFormTitle">Reload Tool</div><div class="toolFormBody">
- <form name="tool_reload" action="${h.url_for( controller='admin', action='tool_reload' )}" method="post" >
+ <form name="reload_tool" id="reload_tool" action="${h.url_for( controller='admin', action='reload_tool' )}" method="post" ><div class="form-row"><label>
Tool to reload:
@@ -30,7 +30,7 @@
</select></div><div class="form-row">
- <input type="submit" name="action" value="Reload"/>
+ <input type="submit" name="reload_tool_button" value="Reload"/></div></form></div>
--- a/templates/tool_form.mako Fri Sep 02 14:37:09 2011 -0400
+++ b/templates/tool_form.mako Fri Sep 02 14:57:33 2011 -0400
@@ -260,7 +260,7 @@
%if tool.has_multiple_pages:
<div class="toolFormTitle">${tool.name} (step ${tool_state.page+1} of ${tool.npages})</div>
%else:
- <div class="toolFormTitle">${tool.name}</div>
+ <div class="toolFormTitle">${tool.name} (version ${tool.version})</div>
%endif
<div class="toolFormBody"><form id="tool_form" name="tool_form" action="${tool_url}" enctype="${tool.enctype}" target="${tool.target}" method="${tool.method}">
--- a/universe_wsgi.ini.sample Fri Sep 02 14:37:09 2011 -0400
+++ b/universe_wsgi.ini.sample Fri Sep 02 14:57:33 2011 -0400
@@ -123,10 +123,12 @@
# Temporary files are stored in this directory.
#new_file_path = database/tmp
-# Tool config file, defines what tools are available in Galaxy.
+# Tool config files, defines what tools are available in Galaxy.
+# Tools can be locally developed or installed from tool sheds.
#tool_config_file = tool_conf.xml
-# Path to the directory containing the tools defined in the config.
+# Default path to the directory containing the tools defined in tool_conf.xml.
+# Other tool config files must include the tool_path as an attribute in the <toolbox> tag.
#tool_path = tools
# Directory where data used by tools is located, see the samples in that
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/fb6c47e5d039/
changeset: fb6c47e5d039
user: natefoo
date: 2011-09-02 20:37:09
summary: Typo in scramble.py.
affected #: 1 file (0 bytes)
--- a/scripts/scramble.py Fri Sep 02 14:08:53 2011 -0400
+++ b/scripts/scramble.py Fri Sep 02 14:37:09 2011 -0400
@@ -45,7 +45,7 @@
degg = e.eggs[0]
print "%s build dependency %s %s couldn't be downloaded" % ( egg.name, degg.name, degg.version )
print "automatically. You can try building it by hand with:"
- print " python scripts/scramble.py %s-e %s" % ( config_agr, degg.name )
+ print " python scripts/scramble.py %s-e %s" % ( config_arg, degg.name )
sys.exit( 1 )
egg.scramble()
sys.exit( 0 )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Trackster: fix bug in computing tile_high and refactor tile bounds computation into own method.
by Bitbucket 02 Sep '11
by Bitbucket 02 Sep '11
02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/f5efbe15e22c/
changeset: f5efbe15e22c
user: jgoecks
date: 2011-09-02 20:08:53
summary: Trackster: fix bug in computing tile_high and refactor tile bounds computation into own method.
affected #: 1 file (660 bytes)
--- a/static/scripts/trackster.js Fri Sep 02 10:16:07 2011 -0400
+++ b/static/scripts/trackster.js Fri Sep 02 14:08:53 2011 -0400
@@ -2313,7 +2313,7 @@
var tile_count = 0;
// Draw or fetch and show tiles.
while ( ( tile_index * DENSITY * resolution ) < high ) {
- tile = this.draw_helper( force, width, tile_index, resolution, parent_element, w_scale )
+ tile = this.draw_helper( force, width, tile_index, resolution, parent_element, w_scale );
if ( tile ) {
drawn_tiles.push( tile );
} else {
@@ -2486,7 +2486,18 @@
track.max_height = Math.max(track.max_height, tile_element.height());
track.content_div.css("height", track.max_height + "px");
parent_element.children().css("height", track.max_height + "px");
- },
+ },
+ /**
+ * Returns tile bounds--tile low and tile high--based on a tile index. Return value is an array
+ * with values tile_low and tile_high.
+ */
+ _get_tile_bounds: function(tile_index, resolution) {
+ var tile_low = tile_index * DENSITY * resolution,
+ tile_length = DENSITY * resolution,
+ // Tile high cannot be larger than view.max_high, which the chromosome length.
+ tile_high = (tile_low + tile_length <= this.view.max ? tile_low + tile_length : this.view.max_high);
+ return [tile_low, tile_high];
+ },
/**
* Utility function that creates a label string describing the region and parameters of a track's tool.
*/
@@ -2713,9 +2724,11 @@
return;
}
- var tile_low = tile_index * DENSITY * resolution,
- tile_length = DENSITY * resolution,
- width = Math.ceil( tile_length * w_scale ),
+ var
+ tile_bounds = this._get_tile_bounds(tile_index, resolution),
+ tile_low = tile_bounds[0],
+ tile_high = tile_bounds[1],
+ width = Math.ceil( (tile_high - tile_low) * w_scale ),
height = this.height_px;
// Create canvas
@@ -2725,7 +2738,7 @@
// Paint line onto full canvas
var ctx = canvas.getContext("2d");
- var painter = new painters.LinePainter(result.data, tile_low, tile_low + tile_length, this.prefs, mode);
+ var painter = new painters.LinePainter(result.data, tile_low, tile_high, this.prefs, mode);
painter.draw(ctx, width, height);
return new Tile(tile_index, resolution, canvas, result.data);
@@ -2990,8 +3003,9 @@
*/
draw_tile: function(result, mode, resolution, tile_index, w_scale, ref_seq) {
var track = this,
- tile_low = tile_index * DENSITY * resolution,
- tile_high = (tile_index + 1) * DENSITY * resolution,
+ tile_bounds = track._get_tile_bounds(tile_index, resolution),
+ tile_low = tile_bounds[0],
+ tile_high = tile_bounds[1],
tile_span = tile_high - tile_low,
width = Math.ceil(tile_span * w_scale),
min_height = 25,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/2790c2083719/
changeset: 2790c2083719
user: natefoo
date: 2011-09-02 16:16:07
summary: Bugfix for tool tests without attributes.
affected #: 1 file (15 bytes)
--- a/test/base/twilltestcase.py Fri Sep 02 08:57:55 2011 -0400
+++ b/test/base/twilltestcase.py Fri Sep 02 10:16:07 2011 -0400
@@ -655,10 +655,9 @@
self.home()
self.visit_page( "display?hid=" + hid )
data = self.last_page()
- assert_list = attributes["assert_list"]
- if assert_list is not None:
+ if attributes is not None and attributes.get( "assert_list", None ) is not None:
try:
- verify_assertions(data, assert_list)
+ verify_assertions(data, attributes["assert_list"])
except AssertionError, err:
errmsg = 'History item %s different than expected\n' % (hid)
errmsg += str( err )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Fix bug in setting Cufflinks' reference annotation.
by Bitbucket 02 Sep '11
by Bitbucket 02 Sep '11
02 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ff7c8c0bef60/
changeset: ff7c8c0bef60
user: jgoecks
date: 2011-09-02 14:57:55
summary: Fix bug in setting Cufflinks' reference annotation.
affected #: 1 file (6 bytes)
--- a/tools/ngs_rna/cufflinks_wrapper.xml Thu Sep 01 14:01:00 2011 -0400
+++ b/tools/ngs_rna/cufflinks_wrapper.xml Fri Sep 02 08:57:55 2011 -0400
@@ -14,11 +14,11 @@
-j $pre_mrna_fraction
## Include reference annotation?
- #if $reference_annotation.use_ref == "use reference annotation":
+ #if $reference_annotation.use_ref == "Use reference annotation":
-G $reference_annotation.reference_annotation_file
#end if
- #if $reference_annotation.use_ref == "use reference annotation guide":
- -g $reference_annotation_guide.reference_annotation_guide_file
+ #if $reference_annotation.use_ref == "Use reference annotation guide":
+ -g $reference_annotation.reference_annotation_guide_file
#end if
## Set paired-end parameters?
@@ -63,7 +63,7 @@
<when value="Use reference annotation"><param format="gff3,gtf" name="reference_annotation_file" type="data" label="Reference Aonnotation" help="Make sure your annotation file is in GTF format and that Galaxy knows that your file is GTF--not GFF."/></when>
- <when value="Use reference annotation guide">
+ <when value="Use reference annotation guide"><param format="gff3,gtf" name="reference_annotation_guide_file" type="data" label="Reference Aonnotation" help="Make sure your annotation file is in GTF format and that Galaxy knows that your file is GTF--not GFF."/></when></conditional>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Trackster: enable track renaming through config dialog.
by Bitbucket 01 Sep '11
by Bitbucket 01 Sep '11
01 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/97de244f9565/
changeset: 97de244f9565
user: jgoecks
date: 2011-09-01 20:01:00
summary: Trackster: enable track renaming through config dialog.
affected #: 2 files (917 bytes)
--- a/static/scripts/packed/trackster.js Thu Sep 01 12:35:20 2011 -0400
+++ b/static/scripts/packed/trackster.js Thu Sep 01 14:01:00 2011 -0400
@@ -1,1 +1,1 @@
-var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,W){var p=f("class").extend,r=f("slotting"),K=f("painters");var ad=function(ae,af){this.document=ae;this.default_font=af!==undefined?af:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};p(ad.prototype,{load_pattern:function(ae,ai){var af=this.patterns,ag=this.dummy_context,ah=new Image();ah.src=image_path+ai;ah.onload=function(){af[ae]=ag.createPattern(ah,"repeat")}},get_pattern:function(ae){return this.patterns[ae]},new_canvas:function(){var ae=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ae)}ae.manager=this;return ae}});var m=function(ae,ag,ah){ah=".group";var af={};ae.bind("drag",{handle:ag,relative:true},function(an,ao){var aq=$(this).parent(),al=aq.children(),ak,aj,ap,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ap=aj.position().top;ai=ap+aj.outerHeight();if(ao.offsetY<ap){$(this).insertBefore(aj);return}else{if(ao.offsetY>ai){$(this).insertAfter(aj);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ap=ak.position().top;ai=ap+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&ao.offsetY>=ap&&ao.offsetY<=ai){if(ao.offsetY-ap<ai-ao.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}return}}for(am=0;am<al.length;am++){if(ao.offsetY<$(al.get(am)).position().top){break}}if(am===al.length){if(this!==al.get(am-1)){aq.append(this)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am))}}}).bind("dragstart",function(){af["border-top"]=ae.css("border-top");af["border-bottom"]=ae.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(af)})};W.moveable=m;var ac=16,F=9,D=20,R=F+2,z=100,H=12000,P=200,C=5,u=10,J=5000,v=100,n="There was an error in indexing this dataset. ",I="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",s="Currently indexing... please wait",x="Tool cannot be rerun: ",a="Loading data...",X="Ready for display",d=10,t=5,B=5;function w(ae){return Math.round(ae*1000)/1000}var c=function(ae){this.num_elements=ae;this.clear()};p(c.prototype,{get:function(af){var ae=this.key_ary.indexOf(af);if(ae!==-1){if(this.obj_cache[af].stale){this.key_ary.splice(ae,1);delete this.obj_cache[af]}else{this.move_key_to_end(af,ae)}}return this.obj_cache[af]},set:function(af,ag){if(!this.obj_cache[af]){if(this.key_ary.length>=this.num_elements){var ae=this.key_ary.shift();delete this.obj_cache[ae]}this.key_ary.push(af)}this.obj_cache[af]=ag;return ag},move_key_to_end:function(af,ae){this.key_ary.splice(ae,1);this.key_ary.push(af)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var Q=function(af,ae,ag){c.call(this,af);this.track=ae;this.subset=(ag!==undefined?ag:true)};p(Q.prototype,c.prototype,{load_data:function(an,ai,al,af,ak){var am=this.track.view.chrom,ah={chrom:am,low:an,high:ai,mode:al,resolution:af,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ah,ak);if(this.track.filters_manager){var ao=[];var ae=this.track.filters_manager.filters;for(var aj=0;aj<ae.length;aj++){ao[ao.length]=ae[aj].name}ah.filter_cols=JSON.stringify(ao)}var ag=this;return $.getJSON(this.track.data_url,ah,function(ap){ag.set_data(an,ai,al,ap)})},get_data:function(ae,ai,aj,af,ah){var ag=this.get_data_from_cache(ae,ai,aj);if(ag){return ag}ag=this.load_data(ae,ai,aj,af,ah);this.set_data(ae,ai,aj,ag);return ag},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(am,ah,al,ag,ak,ai){var an=this.get_data_from_cache(am,ah,al);if(!an){console.log("ERROR: no current data for: ",this.track,am,ah,al,ag,ak);return}an.stale=true;var af=am;if(ai===this.DEEP_DATA_REQ){$.extend(ak,{start_val:an.data.length+1})}else{if(ai===this.BROAD_DATA_REQ){af=an.data[an.data.length-1][2]+1}}var ae=this,aj=this.load_data(af,ah,al,ag,ak);new_data_available=$.Deferred();this.set_data(am,ah,al,new_data_available);$.when(aj).then(function(ao){if(ao.data){ao.data=an.data.concat(ao.data);if(ao.message){ao.message=ao.message.replace(/[0-9]+/,ao.data.length)}}ae.set_data(am,ah,al,ao);new_data_available.resolve(ao)});return new_data_available},get_data_from_cache:function(ae,af,ag){return this.get(this.gen_key(ae,af,ag))},set_data:function(af,ag,ah,ae){return this.set(this.gen_key(af,ag,ah),ae)},gen_key:function(ae,ag,ah){var af=ae+"_"+ag+"_"+ah;return af},split_key:function(ae){return ae.split("_")}});var G=function(af,ae,ag){Q.call(this,af,ae,ag)};p(G.prototype,Q.prototype,c.prototype,{load_data:function(ag,ae,ai,aj,af,ah){if(af>1){return}return Q.prototype.load_data.call(this,ag,ae,ai,aj,af,ah)}});var ab=function(ae,ah,ag,af,ai){this.container=ae;this.chrom=null;this.vis_id=ag;this.dbkey=af;this.title=ah;this.tracks=[];this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(ai);this.canvas_manager=new ad(ae.get(0).ownerDocument);this.reset()};p(ab.prototype,{init:function(ai){var ag=this.container,ae=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ag);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ag);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ag);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ah=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var af=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){ae.go_to($(this).val())}$(this).hide();$(this).val("");ae.location_span.show();ae.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",af).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ae.location_span.hide();ae.chrom_select.hide();ae.nav_input.val(ae.chrom+":"+ae.low+"-"+ae.high);ae.nav_input.css("display","inline-block");ae.nav_input.select();ae.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ae.zoom_out();ae.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ae.zoom_in();ae.request_redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},ai);this.chrom_select.bind("change",function(){ae.change_chrom(ae.chrom_select.val())});this.content_div.click(function(aj){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(aj){ae.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/ae.viewport_container.width()*(ae.max_high-ae.max_low));ae.move_delta(-ak)});this.overview_close.click(function(){ae.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>ae.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=ae.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){var am=Math.round(-ak/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:ae.content_div.height()+ae.top_labeltrack.height()+ae.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX),width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-ae.container.offset().left,aj=Math.max(an.pageX,ao.startX)-ae.container.offset().left,am=(ae.high-ae.low),al=ae.viewport_container.width();ae.update_location(Math.round(ak/al*am)+ae.low,Math.round(aj/al*am)+ae.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(ae.high-ae.low),al=ae.viewport_container.width(),an=ae.low;ae.low=Math.round(ak/al*am)+an;ae.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();ae.request_redraw()});this.add_label_track(new aa(this,this.top_labeltrack));this.add_label_track(new aa(this,this.nav_labeltrack));$(window).bind("resize",function(){ae.resize_window()});$(document).bind("redraw",function(){ae.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.show()}else{this.intro_div.hide()}},update_location:function(ae,af){this.location_span.text(commatize(ae)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ae)+"-"+commatize(af))},load_chroms:function(af,ag){af.num=v;$.extend(af,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ae=this;$.ajax({url:chrom_url,data:af,dataType:"json",success:function(ai){if(ai.chrom_info.length===0){alert("Invalid chromosome: "+af.chrom);return}if(ai.reference){ae.add_label_track(new A(ae))}ae.chrom_data=ai.chrom_info;var al='<option value="">Select Chrom/Contig</option>';for(var ak=0,ah=ae.chrom_data.length;ak<ah;ak++){var aj=ae.chrom_data[ak].chrom;al+='<option value="'+aj+'">'+aj+"</option>"}if(ai.prev_chroms){al+='<option value="previous">Previous '+v+"</option>"}if(ai.next_chroms){al+='<option value="next">Next '+v+"</option>"}ae.chrom_select.html(al);if(ag){ag()}ae.chrom_start_index=ai.start_index},error:function(){alert("Could not load chroms for this dbkey:",ae.dbkey)}})},change_chrom:function(ai,af,ak){if(!ai||ai==="None"){return}var ah=this;if(ai==="previous"){ah.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){ah.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(ah.chrom_data,function(am,an){return am.chrom===ai})[0];if(aj===undefined){ah.load_chroms({chrom:ai},function(){ah.change_chrom(ai,af,ak)});return}else{if(ai!==ah.chrom){ah.chrom=ai;ah.chrom_select.val(ah.chrom);ah.max_high=aj.len-1;ah.reset();ah.request_redraw(true);for(var al=0,ae=ah.tracks.length;al<ae;al++){var ag=ah.tracks[al];if(ag.init){ag.init()}}}if(af!==undefined&&ak!==undefined){ah.low=Math.max(af,0);ah.high=Math.min(ak,ah.max_high)}ah.reset_overview();ah.request_redraw()}},go_to:function(ai){var am=this,ae,ah,af=ai.split(":"),ak=af[0],al=af[1];if(al!==undefined){try{var aj=al.split("-");ae=parseInt(aj[0].replace(/,/g,""),10);ah=parseInt(aj[1].replace(/,/g,""),10)}catch(ag){return false}}am.change_chrom(ak,ae,ah)},move_fraction:function(ag){var ae=this;var af=ae.high-ae.low;this.move_delta(ag*af)},move_delta:function(ag){var ae=this;var af=ae.high-ae.low;if(ae.low-ag<ae.max_low){ae.low=ae.max_low;ae.high=ae.max_low+af}else{if(ae.high-ag>ae.max_high){ae.high=ae.max_high;ae.low=ae.max_high-af}else{ae.high-=ag;ae.low-=ag}}ae.request_redraw()},add_track:function(ae){ae.view=this;ae.track_id=this.track_id_counter;this.tracks.push(ae);if(ae.init){ae.init()}ae.container_div.attr("id","track_"+ae.track_id);m(ae.container_div,ae.drag_handle);this.track_id_counter+=1;this.num_tracks+=1;this.has_changes=true;this.update_intro_div()},add_label_track:function(ae){ae.view=this;this.label_tracks.push(ae)},remove_track:function(af){this.has_changes=true;delete this.tracks[this.tracks.indexOf(af)];this.num_tracks-=1;var ae=this;af.container_div.fadeOut("slow",function(){$(this).remove();ae.update_intro_div()})},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(am,ae,al,af){var ak=this,ai=(af?[af]:ak.tracks),ag;var af;for(var aj=0;aj<ai.length;aj++){af=ai[aj];ag=-1;for(var ah=0;ah<ak.tracks_to_be_redrawn.length;ah++){if(ak.tracks_to_be_redrawn[ah][0]===af){ag=ah;break}}if(ag<0){ak.tracks_to_be_redrawn.push([af,ae,al])}else{ak.tracks_to_be_redrawn[aj][1]=ae;ak.tracks_to_be_redrawn[aj][2]=al}}requestAnimationFrame(function(){ak._redraw(am)})},_redraw:function(ao){var al=this.low,ah=this.high;if(al<this.max_low){al=this.max_low}if(ah>this.max_high){ah=this.max_high}var an=this.high-this.low;if(this.high!==0&&an<this.min_separation){ah=al+this.min_separation}this.low=Math.floor(al);this.high=Math.ceil(ah);this.resolution=Math.pow(C,Math.ceil(Math.log((this.high-this.low)/P)/Math.log(C)));this.zoom_res=Math.pow(u,Math.max(0,Math.ceil(Math.log(this.resolution,u)/Math.log(u))));var ae=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ak=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ap=13;this.overview_box.css({left:ae,width:Math.max(ap,ak)}).show();if(ak<ap){this.overview_box.css("left",ae-(ap-ak)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ae,width:ak})}this.update_location(this.low,this.high);if(!ao){var ag,af,am;for(var ai=0,aj=this.tracks_to_be_redrawn.length;ai<aj;ai++){ag=this.tracks_to_be_redrawn[ai][0];af=this.tracks_to_be_redrawn[ai][1];am=this.tracks_to_be_redrawn[ai][2];if(ag&&ag.enabled){ag._draw(af,am)}}this.tracks_to_be_redrawn=[];for(ai=0,aj=this.label_tracks.length;ai<aj;ai++){this.label_tracks[ai]._draw()}}},zoom_in:function(af,ag){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ah=this.high-this.low,ai=ah/2+this.low,ae=(ah/this.zoom_factor)/2;if(af){ai=af/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ai-ae);this.high=Math.round(ai+ae);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var af=this.high-this.low,ag=af/2+this.low,ae=(af*this.zoom_factor)/2;this.low=Math.round(ag-ae);this.high=Math.round(ag+ae);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ae){$.when(ae.get_overview_tile()).then(function(af){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(af.canvas);view.overview_highlight.show().height(af.canvas.height());view.overview_viewport.height(af.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ae;ae.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var q=function(ag,ak){this.track=ag;this.name=ak.name;this.params=[];var ar=ak.params;for(var ah=0;ah<ar.length;ah++){var am=ar[ah],af=am.name,aq=am.label,ai=unescape(am.html),at=am.value,ao=am.type;if(ao==="number"){this.params[this.params.length]=new g(af,aq,ai,at,am.min,am.max)}else{if(ao=="select"){this.params[this.params.length]=new M(af,aq,ai,at)}else{console.log("WARNING: unrecognized tool parameter type:",af,ao)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(av){av.stopPropagation()}).click(function(av){av.stopPropagation()}).bind("dblclick",function(av){av.stopPropagation()});var ap=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var an=this.params;var al=this;$.each(this.params,function(aw,az){var ay=$("<div>").addClass("param-row").appendTo(al.parent_div);var av=$("<div>").addClass("param-label").text(az.label).appendTo(ay);var ax=$("<div/>").addClass("slider").html(az.html).appendTo(ay);ax.find(":input").val(az.value);$("<div style='clear: both;'/>").appendTo(ay)});this.parent_div.find("input").click(function(){$(this).select()});var au=$("<div>").addClass("param-row").appendTo(this.parent_div);var aj=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(au);var ae=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(au);var al=this;ae.click(function(){al.run_on_region()});aj.click(function(){al.run_on_dataset()})};p(q.prototype,{get_param_values_dict:function(){var ae={};this.parent_div.find(":input").each(function(){var af=$(this).attr("name"),ag=$(this).val();ae[af]=JSON.stringify(ag)});return ae},get_param_values:function(){var af=[];var ae={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();if(ag){af[af.length]=ah}});return af},run_on_dataset:function(){var ae=this;ae.run({dataset_id:this.track.original_dataset_id,tool_id:ae.name},null,function(af){show_modal(ae.name+" is Running",ae.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},ag=this.track,af=ae.tool_id+ag.tool_region_and_parameters_str(ae.chrom,ae.low,ae.high),ah;if(ag instanceof e){ah=new T(af,view,ag.hda_ldda,undefined,{},{},ag);ah.change_mode(ag.mode)}this.track.add_track(ah);ah.content_div.text("Starting job.");this.run(ae,ah,function(ai){ah.dataset_id=ai.dataset_id;ah.content_div.text("Running job.");ah.init()})},run:function(af,ag,ah){$.extend(af,this.get_param_values_dict());var ae=function(){$.getJSON(rerun_tool_url,af,function(ai){if(ai==="no converter"){ag.container_div.addClass("error");ag.content_div.text(I)}else{if(ai.error){ag.container_div.addClass("error");ag.content_div.text(x+ai.message)}else{if(ai==="pending"){ag.container_div.addClass("pending");ag.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ae,2000)}else{ah(ai)}}}})};ae()}});var M=function(af,ae,ag,ah){this.name=af;this.label=ae;this.html=ag;this.value=ah};var g=function(ag,af,ai,aj,ah,ae){M.call(this,ag,af,ai,aj);this.min=ah;this.max=ae};var h=function(af,ae,ag,ah){this.name=af;this.index=ae;this.tool_id=ag;this.tool_exp_name=ah};var U=function(af,ae,ag,ah){h.call(this,af,ae,ag,ah);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};p(U.prototype,{applies_to:function(ae){if(ae.length>this.index){return true}return false},keep:function(ae){if(!this.applies_to(ae)){return true}var af=parseFloat(ae[this.index]);return(isNaN(af)||(af>=this.low&&af<=this.high))},update_attrs:function(af){var ae=false;if(!this.applies_to(af)){return ae}if(af[this.index]<this.min){this.min=Math.floor(af[this.index]);ae=true}if(af[this.index]>this.max){this.max=Math.ceil(af[this.index]);ae=true}return ae},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var ag=function(aj,ah){var ai=ah-aj;return(ai<=2?0.01:1)};var af=this.slider.slider("option","min"),ae=this.slider.slider("option","max");if(this.min<af||this.max>ae){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",ag(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var Z=function(ao,av){this.track=ao;this.filters=[];for(var ap=0;ap<av.length;ap++){var aq=av[ap],aw=aq.name,ae=aq.type,ah=aq.index,au=aq.tool_id,at=aq.tool_exp_name;if(ae==="int"||ae==="float"){this.filters[ap]=new U(aw,ah,au,at)}else{console.log("ERROR: unsupported filter: ",aw,ae)}}var ai=function(ax,ay,az){ax.click(function(){var aA=ay.text();max=parseFloat(az.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(az.slider("option","values")){input_size=2*input_size+1;multi_value=true}ay.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aA).appendTo(ay).focus().select().click(function(aB){aB.stopPropagation()}).blur(function(){$(this).remove();ay.text(aA)}).keyup(function(aF){if(aF.keyCode===27){$(this).trigger("blur")}else{if(aF.keyCode===13){var aD=az.slider("option","min"),aB=az.slider("option","max"),aE=function(aG){return(isNaN(aG)||aG>aB||aG<aD)},aC=$(this).val();if(!multi_value){aC=parseFloat(aC);if(aE(aC)){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}else{aC=aC.split("-");aC=[parseFloat(aC[0]),parseFloat(aC[1])];if(aE(aC[0])||aE(aC[1])){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}az.slider((multi_value?"values":"value"),aC)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ax){ax.stopPropagation()}).click(function(ax){ax.stopPropagation()}).bind("dblclick",function(ax){ax.stopPropagation()}).bind("keydown",function(ax){ax.stopPropagation()});var ar=$("<div/>").addClass("sliders").appendTo(this.parent_div);var am=this;$.each(this.filters,function(aA,aC){aC.container=$("<div/>").addClass("slider-row").appendTo(ar);var aB=$("<div/>").addClass("elt-label").appendTo(aC.container);var az=$("<span/>").addClass("slider-name").text(aC.name+" ").appendTo(aB);var ay=$("<span/>");var aE=$("<span/>").addClass("slider-value").appendTo(aB).append("[").append(ay).append("]");var ax=$("<div/>").addClass("slider").appendTo(aC.container);aC.control_element=$("<div/>").attr("id",aC.name+"-filter-control").appendTo(ax);var aD=[0,0];aC.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aG,aH){var aF=aH.values;ay.text(aF[0]+"-"+aF[1]);aC.low=aF[0];aC.high=aF[1];am.track.request_draw(true,true)},change:function(aF,aG){aC.control_element.slider("option","slide").call(aC.control_element,aF,aG)}});aC.slider=aC.control_element;aC.slider_label=ay;ai(aE,ay,aC.control_element);$("<div style='clear: both;'/>").appendTo(aC.container)});if(this.filters.length!==0){var aj=$("<div/>").addClass("param-row").appendTo(ar);var al=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(aj);var ag=this;al.click(function(){ag.run_on_dataset()})}var an=$("<div/>").addClass("display-controls").appendTo(this.parent_div),ak=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(an),af=$("<select/>").attr("name","alpha_dropdown").appendTo(an);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(af);for(var ap=0;ap<this.filters.length;ap++){$("<option/>").attr("value",ap).text(this.filters[ap].name).appendTo(af)}af.change(function(){$(this).children("option:selected").each(function(){var ax=parseInt($(this).val());am.alpha_filter=(ax>=0?am.filters[ax]:null);am.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};p(Z.prototype,{reset_filters:function(){for(var ae=0;ae<this.filters.length;ae++){filter=this.filters[ae];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var am=function(aq,ao,ap){if(!(ao in aq)){aq[ao]=ap}return aq[ao]};var ag={},ae,af,ah;for(var ai=0;ai<this.filters.length;ai++){ae=this.filters[ai];if(ae.tool_id){if(ae.min!=ae.low){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" >= "+ae.low}if(ae.max!=ae.high){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" <= "+ae.high}}}var ak=[];for(var an in ag){ak[ak.length]=[an,ag[an]]}var al=ak.length;(function aj(av,ar){var ap=ar[0],aq=ap[0],au=ap[1],at="("+au.join(") and (")+")",ao={cond:at,input:av,target_dataset_id:av,tool_id:aq},ar=ar.slice(1);$.getJSON(run_tool_url,ao,function(aw){if(aw.error){show_modal("Filter Dataset","Error running tool "+aq,{Close:hide_modal})}else{if(ar.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aj(aw.dataset_id,ar)}}})})(this.track.dataset_id,ak)}});var N=function(af,ae){K.AlphaGenerator.call(this,ae);this.filter=af};N.prototype.gen_alpha=function(ae){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ae[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var Y=function(ae){this.track=ae.track;this.params=ae.params;this.values={};if(ae.saved_values){this.restore_values(ae.saved_values)}this.onchange=ae.onchange};p(Y.prototype,{restore_values:function(ae){var af=this;$.each(this.params,function(ag,ah){if(ae[ah.key]!==undefined){af.values[ah.key]=ae[ah.key]}else{af.values[ah.key]=ah.default_value}})},build_form:function(){var af=this;var ae=$("<div />");$.each(this.params,function(aj,ah){if(!ah.hidden){var ag="param_"+aj;var ao=$("<div class='form-row' />").appendTo(ae);ao.append($("<label />").attr("for",ag).text(ah.label+":"));if(ah.type==="bool"){ao.append($('<input type="checkbox" />').attr("id",ag).attr("name",ag).attr("checked",af.values[ah.key]))}else{if(ah.type==="color"){var al=af.values[ah.key];var ak=$("<input />").attr("id",ag).attr("name",ag).val(al);var am=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var ai=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am);var an=$("<div/>").appendTo(ai).farbtastic({width:100,height:100,callback:ak,color:al});$("<div />").append(ak).append(am).appendTo(ao).bind("click",function(ap){am.css({left:$(this).position().left+($(ak).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){am.hide();$(document).unbind("click.color-picker")});ap.stopPropagation()})}else{ao.append($("<input />").attr("id",ag).attr("name",ag).val(af.values[ah.key]))}}}});return ae},update_from_form:function(ae){var ag=this;var af=false;$.each(this.params,function(ah,aj){if(!aj.hidden){var ak="param_"+ah;var ai=ae.find("#"+ak).val();if(aj.type==="float"){ai=parseFloat(ai)}else{if(aj.type==="int"){ai=parseInt(ai)}else{if(aj.type==="bool"){ai=ae.find("#"+ak).is(":checked")}}}if(ai!==ag.values[aj.key]){ag.values[aj.key]=ai;af=true}}});if(af){this.onchange()}}});var b=function(ag,af,ae,ah){this.index=ag;this.low=ag*P*af;this.high=(ag+1)*P*af;this.resolution=af;this.canvas=$("<div class='track-tile'/>").append(ae);this.data=ah;this.stale=false};var l=function(ag,af,ae,ah,ai){b.call(this,ag,af,ae,ah);this.max_val=ai};var O=function(ag,af,ae,ai,ah){b.call(this,ag,af,ae,ai);this.message=ah};var o=function(af,ae){this.name=af;this.view=ae;this.parent_element=ae.viewport_container};o.prototype.request_draw=function(){};o.prototype.draw=function(){};var y=function(af,ae){o.call(this,af,ae);this.members=[];this.drag_handle_class="group-handle";this.container_div=$("<div/>").addClass("group").appendTo(this.parent_element);this.container_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);this.content_div=$("<div/>").addClass("content-div").appendTo(this.container_div)};p(y.prototype,o.prototype,{request_draw:function(af,ae){},draw:function(){}});var j=function(af,ae,ai,ag,ah){this.name=af;this.view=ae;this.parent_element=ai;this.data_url=(ag?ag:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ah?ah:J);this.dataset_check_url=converted_datasets_state_url;this.drag_handle_class="draghandle";this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};p(j.prototype,{get_type:function(){if(this instanceof aa){return"LabelTrack"}else{if(this instanceof A){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof V){return"ReadTrack"}else{if(this instanceof T){return"ToolDataFeatureTrack"}else{if(this instanceof S){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.initial_canvas=undefined;ae.content_div.css("height","auto");ae.container_div.removeClass("nodata error pending");if(!ae.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id,chrom:ae.view.chrom},function(af){if(!af||af==="error"||af.kind==="error"){ae.container_div.addClass("error");ae.content_div.text(n);if(af.message){var ah=ae.view.tracks.indexOf(ae);var ag=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+af.message+"</pre>",{Close:hide_modal})});ae.content_div.append(ag)}}else{if(af==="no converter"){ae.container_div.addClass("error");ae.content_div.text(I)}else{if(af==="no data"||(af.data!==undefined&&(af.data===null||af.data.length===0))){ae.container_div.addClass("nodata");ae.content_div.text(E)}else{if(af==="pending"){ae.container_div.addClass("pending");ae.content_div.text(s);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(af.status==="data"){if(af.valid_chroms){ae.valid_chroms=af.valid_chroms;ae.make_name_popup_menu()}ae.content_div.text(X);if(ae.view.chrom){ae.content_div.text("");ae.content_div.css("height",ae.height_px+"px");ae.enabled=true;$.when(ae.predraw_init()).done(function(){ae.container_div.removeClass("nodata error pending");ae.request_draw()})}}}}}}})},predraw_init:function(){},update_name:function(ae){this.old_name=this.name;this.name=ae;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var L=function(al,aj,am){var af=this,an=af.view;this.filters_manager=(al!==undefined?new Z(this,al):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(aj!==undefined&&obj_length(aj)>0?new q(this,aj):undefined);this.is_overview=false;this.parent_track=am;this.child_tracks=[];if(af.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}af.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();af.container_div.append(af.child_tracks_container);if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(af.display_modes!==undefined){if(af.mode_div===undefined){af.mode_div=$("<div class='right-float menubutton popup' />").appendTo(af.header_div);var ag=(af.track_config&&af.track_config.values.mode?af.track_config.values.mode:af.display_modes[0]);af.mode=ag;af.mode_div.text(ag);var ae={};for(var ah=0,ak=af.display_modes.length;ah<ak;ah++){var ai=af.display_modes[ah];ae[ai]=function(ao){return function(){af.change_mode(ao)}}(ai)}make_popupmenu(af.mode_div,ae)}else{af.mode_div.hide()}}this.make_name_popup_menu()};p(L.prototype,j.prototype,{change_mode:function(af){var ae=this;ae.mode_div.text(af);ae.mode=af;ae.track_config.values.mode=af;ae.tile_cache.clear();ae.request_draw()},make_name_popup_menu:function(){var af=this;var ae={};ae[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(af.is_overview){af.view.reset_overview()}else{af.view.set_overview(af)}};ae["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){af.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Track",af.track_config.build_form(),{Cancel:al,OK:aj})};if(af.filters_available>0){var ai=(af.filters_div.is(":visible")?"Hide filters":"Show filters");ae[ai]=function(){af.filters_visible=(af.filters_div.is(":visible"));if(af.filters_visible){af.filters_manager.reset_filters()}af.filters_div.toggle();af.make_name_popup_menu()}}if(af.tool){var ai=(af.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ae[ai]=function(){if(!af.dynamic_tool_div.is(":visible")){af.update_name(af.name+af.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";af.revert_name()}af.dynamic_tool_div.toggle();af.make_name_popup_menu()}}if(af.valid_chroms){ae["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+af.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var ag=view;var ah=function(){$("#no-tracks").show()};if(this.parent_track){ag=this.parent_track;ah=function(){}}ae.Remove=function(){ag.remove_track(af);if(ag.num_tracks===0){ah()}};make_popupmenu(af.name_div,ae)},set_is_overview:function(ae){this.is_overview=ae;this.make_name_popup_menu()},get_overview_tile:function(){var ae=this;view=ae.view,resolution=Math.pow(C,Math.ceil(Math.log((view.max_high-view.max_low)/P)/Math.log(C))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ae.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ae.data_url_extra_params)).then(function(af){var ah=ae._gen_tile_cache_key(view_width,w_scale,0),aj=ae.tile_cache.get(ah);if(!aj){aj=ae.draw_tile(af,resolution,0,w_scale);ae.tile_cache.set(ah,aj)}var am=$(aj.canvas.find("canvas")),ai=am.clone(),al=am.get(0).getContext("2d"),ag=ai.get(0).getContext("2d"),ak=al.getImageData(0,0,al.canvas.width,al.canvas.height);ag.putImageData(ak,-ae.left_offset,(aj.data.dataset_type==="summary_tree"?R:0));new_tile=new b(-1,resolution,ai);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(af,ag,ae){return af+"_"+ag+"_"+ae},request_draw:function(af,ae){this.view.request_redraw(false,af,ae,this)},_draw:function(ag,ap){if(!this.dataset_id){return}var ao=this.view.low,ak=this.view.high,am=ak-ao,ah=this.view.container.width(),at=ah/am,aj=this.view.resolution,ar=$("<div style='position: relative;'></div>");if(!ap){this.content_div.children().remove()}this.content_div.append(ar);this.max_height=0;var af=Math.floor(ao/aj/P);var an=true;var aq=[];var ae=0;while((af*P*aj)<ak){tile=this.draw_helper(ag,ah,af,aj,ar,at);if(tile){aq.push(tile)}else{an=false}af+=1;ae++}var ai=this;if(an){ai.postdraw_actions(aq,ah,at,ap)}for(var al=0;al<this.child_tracks.length;al++){this.child_tracks[al].request_draw(ag,ap)}},postdraw_actions:function(ai,aj,ak,ae){var ag=this;var ah=false;for(var af=0;af<ai.length;af++){if(ai[af].message){ah=true;break}}if(ah){for(var af=0;af<ai.length;af++){tile=ai[af];if(!tile.message){tile.canvas.css("padding-top",D)}}}},draw_helper:function(af,ag,ah,ak,aq,av,ar,al){var ai=this,ap=this._gen_tile_cache_key(ag,av,ah),am=ah*P*ak,au=am+P*ak;var an=(af?undefined:ai.tile_cache.get(ap));if(an){ai.show_tile(an,aq,av);return an}var ao=function(aw){return("isResolved" in aw)};var aj=true;var ae=ai.data_manager.get_data(am,au,ai.mode,ak,ai.data_url_extra_params);if(ao(ae)){aj=false}var at;if(view.reference_track&&av>view.canvas_manager.char_width_px){at=view.reference_track.data_manager.get_data(am,au,ai.mode,ak,view.reference_track.data_url_extra_params);if(ao(at)){aj=false}}if(aj){p(ae,al);var an=ai.draw_tile(ae,ak,ah,av,at);ai.tile_cache.set(ap,an);if(an!==undefined){ai.show_tile(an,aq,av)}return an}$.when(ae,at).then(function(){view.request_redraw()});return null},show_tile:function(al,an,ao){var ag=this,af=al.canvas,ak=af;if(al.message){var ap=$("<div/>"),am=$("<div/>").addClass("tile-message").text(al.message).css({height:D-1,width:al.canvas.width}).appendTo(ap),ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(am),ae=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(am);ap.append(af);ak=ap;ai.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()});ae.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()})}var aj=this.view.high-this.view.low,ah=(al.low-this.view.low)*ao;if(this.left_offset){ah-=this.left_offset}ak.css({position:"absolute",top:0,left:ah,height:""});an.append(ak);ag.max_height=Math.max(ag.max_height,ak.height());ag.content_div.css("height",ag.max_height+"px");an.children().css("height",ag.max_height+"px")},tool_region_and_parameters_str:function(ag,ae,ah){var af=this,ai=(ag!==undefined&&ae!==undefined&&ah!==undefined?ag+":"+ae+"-"+ah:"all");return" - region=["+ai+"], parameters=["+af.tool.get_param_values().join(", ")+"]"},add_track:function(ae){ae.track_id=this.track_id+"_"+this.child_tracks.length;ae.container_div.attr("id","track_"+ae.track_id);this.child_tracks_container.append(ae.container_div);m(ae.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(ae);this.view.has_changes=true},remove_track:function(ae){ae.container_div.fadeOut("slow",function(){$(this).remove()})}});var aa=function(ae,af){this.hidden=true;j.call(this,null,ae,af);this.container_div.addClass("label-track")};p(aa.prototype,j.prototype,{_draw:function(){var ag=this.view,ah=ag.high-ag.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ah)/Math.log(10)))),ae=Math.floor(ag.low/ak)*ak,ai=this.view.container.width(),af=$("<div style='position: relative; height: 1.3em;'></div>");while(ae<ag.high){var aj=(ae-ag.low)/ah*ai;af.append($("<div class='label'>"+commatize(ae)+"</div>").css({position:"absolute",left:aj-1}));ae+=ak}this.content_div.children(":first").remove();this.content_div.append(af)}});var A=function(ae){this.hidden=true;j.call(this,null,ae,ae.top_labeltrack);L.call(this);ae.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ae.dbkey};this.data_manager=new G(B,this,false);this.tile_cache=new c(t)};p(A.prototype,L.prototype,{draw_tile:function(am,aj,af,ao){var ai=this,ag=P*aj;if(ao>this.view.canvas_manager.char_width_px){if(am===null){ai.content_div.css("height","0px");return}var ah=this.view.canvas_manager.new_canvas();var an=ah.getContext("2d");ah.width=Math.ceil(ag*ao+ai.left_offset);ah.height=ai.height_px;an.font=an.canvas.manager.default_font;an.textAlign="center";for(var ak=0,al=am.length;ak<al;ak++){var ae=Math.round(ak*ao);an.fillText(am[ak],ae+ai.left_offset,10)}return new b(af,aj,ah,am)}this.content_div.css("height","0px")}});var k=function(ai,ag,aj,ae,ah){var af=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,ai,ag,ag.viewport_container);L.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=aj;this.dataset_id=ae;this.original_dataset_id=ae;this.data_manager=new Q(B,this);this.tile_cache=new c(t);this.track_config=new Y({track:this,params:[{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:ah,onchange:function(){af.vertical_range=af.prefs.max_value-af.prefs.min_value;$("#linetrack_"+af.track_id+"_minval").text(af.prefs.min_value);$("#linetrack_"+af.track_id+"_maxval").text(af.prefs.max_value);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};p(k.prototype,L.prototype,{add_resize_handle:function(){var ae=this;var ah=false;var ag=false;var af=$("<div class='track-resize'>");$(ae.container_div).hover(function(){ah=true;af.show()},function(){ah=false;if(!ag){af.hide()}});af.hide().bind("dragstart",function(ai,aj){ag=true;aj.original_height=$(ae.content_div).height()}).bind("drag",function(aj,ak){var ai=Math.min(Math.max(ak.original_height+ak.deltaY,ae.min_height_px),ae.max_height_px);$(ae.content_div).css("height",ai);ae.height_px=ai;ae.request_draw(true)}).bind("dragend",function(ai,aj){ae.tile_cache.clear();ag=false;if(!ah){af.hide()}ae.track_config.values.height=ae.height_px}).appendTo(ae.container_div)},predraw_init:function(){var ae=this,af=ae.view.tracks.indexOf(ae);ae.vertical_range=undefined;return $.getJSON(ae.data_url,{stats:true,chrom:ae.view.chrom,low:null,high:null,hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id},function(ag){ae.container_div.addClass("line-track");var ai=ag.data;if(isNaN(parseFloat(ae.prefs.min_value))||isNaN(parseFloat(ae.prefs.max_value))){ae.prefs.min_value=ai.min;ae.prefs.max_value=ai.max;$("#track_"+af+"_minval").val(ae.prefs.min_value);$("#track_"+af+"_maxval").val(ae.prefs.max_value)}ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.total_frequency=ai.total_frequency;ae.container_div.find(".yaxislabel").remove();var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_minval").text(w(ae.prefs.min_value));var ah=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_maxval").text(w(ae.prefs.max_value));ah.css({position:"absolute",top:"24px",left:"10px"});ah.prependTo(ae.container_div);aj.css({position:"absolute",bottom:"2px",left:"10px"});aj.prependTo(ae.container_div)})},draw_tile:function(ao,ai,af,an){if(this.vertical_range===undefined){return}var aj=af*P*ai,ah=P*ai,ae=Math.ceil(ah*an),al=this.height_px;var ag=this.view.canvas_manager.new_canvas();ag.width=ae,ag.height=al;var am=ag.getContext("2d");var ak=new K.LinePainter(ao.data,aj,aj+ah,this.prefs,this.mode);ak.draw(am,ae,al);return new b(af,ai,ag,ao.data)}});var e=function(ae,aj,ai,am,al,ag,ah,ak){var af=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];this.track_config=new Y({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:al,onchange:function(){af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;j.call(this,ae,aj,aj.viewport_container);L.call(this,ag,ah,ak);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=ai;this.dataset_id=am;this.original_dataset_id=am;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new Q(20,this);this.left_offset=200;this.painter=K.LinkedFeaturePainter};p(e.prototype,L.prototype,{postdraw_actions:function(au,ae,av,at){L.prototype.postdraw_actions.call(this,au,at);var ah=this;if(at){var aj=ah.content_div.children();var ak=false;for(var ai=aj.length-1,ao=0;ai>=ao;ai--){var ag=$(aj[ai]);if(ak){ag.remove()}else{if(ag.children().length!==0){ak=true}}}}if(ah.mode=="Histogram"){var an=-1;for(var ai=0;ai<au.length;ai++){var ar=au[ai].max_val;if(ar>an){an=ar}}for(var ai=0;ai<au.length;ai++){var aq=au[ai];if(aq.max_val!==an){aq.canvas.remove();ah.draw_helper(true,ae,aq.index,aq.resolution,aq.canvas.parent(),av,[],{max:an})}}}if(ah.filters_manager){var af=ah.filters_manager.filters;for(var am=0;am<af.length;am++){af[am].update_ui_elt()}var al=false,ap;for(var ai=0;ai<au.length;ai++){if(au[ai].data.length){ap=au[ai].data[0];for(var am=0;am<af.length;am++){if(af[am].applies_to(ap)){al=true;break}}}}if(ah.filters_available!==al){ah.filters_available=al;if(!ah.filters_available){ah.filters_div.hide()}ah.make_name_popup_menu()}}},update_auto_mode:function(ae){if(this.mode=="Auto"){if(ae=="no_detail"){ae="feature spans"}else{if(ae=="summary_tree"){ae="coverage histogram"}}this.mode_div.text("Auto ("+ae+")")}},incremental_slots:function(ai,af,ah){var ag=this.view.canvas_manager.dummy_context,ae=this.inc_slots[ai];if(!ae||(ae.mode!==ah)){ae=new (r.FeatureSlotter)(ai,ah==="Pack",z,function(aj){return ag.measureText(aj)});ae.mode=ah;this.inc_slots[ai]=ae}return ae.slot_features(af)},get_summary_tree_data:function(ai,al,ag,au){if(au>ag-al){au=ag-al}var ap=Math.floor((ag-al)/au),at=[],ah=0;var aj=0,ak=0,ao,ar=0,am=[],aq,an;var af=function(ax,aw,ay,av){ax[0]=aw+ay*av;ax[1]=aw+(ay+1)*av};while(ar<au&&aj!==ai.length){var ae=false;for(;ar<au&&!ae;ar++){af(am,al,ar,ap);for(ak=aj;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){ae=true;break}}if(ae){break}}data_start_index=ak;at[at.length]=aq=[am[0],0];for(;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){aq[1]++}else{break}}if(aq[1]>ah){ah=aq[1]}ar++}return{max:ah,delta:ap,data:at}},draw_tile:function(ar,aA,aE,an,ah){var ax=this,aG=aE*P*aA,af=(aE+1)*P*aA,au=af-aG,ay=Math.ceil(au*an),av=this.mode,aK=25,ai=this.left_offset,at,aj;if(av==="Auto"){if(ar.dataset_type==="summary_tree"){av=ar.dataset_type}else{if(ar.extra_info==="no_detail"){av="no_detail"}else{var aJ=ar.data;if(this.view.high-this.view.low>H){av="Squish"}else{av="Pack"}}}this.update_auto_mode(av)}if(av==="summary_tree"||av==="Histogram"){aj=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ae=$("<div />").addClass("yaxislabel");ae.text(ar.max);ae.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ae.prependTo(this.container_div);var ag=this.view.canvas_manager.new_canvas();ag.width=ay+ai;ag.height=aj+R;if(ar.dataset_type!="summary_tree"){var ao=this.get_summary_tree_data(ar.data,aG,af,200);if(ar.max){ao.max=ar.max}ar=ao}var aH=new K.SummaryTreePainter(ar,aG,af,this.prefs);var az=ag.getContext("2d");az.translate(ai,R);aH.draw(az,ay,aj);return new l(aE,aA,ag,ar.data,ar.max)}var at,al=1;if(av==="no_detail"||av==="Squish"||av==="Pack"){al=this.incremental_slots(an,ar.data,av);at=this.inc_slots[an].slots}var am=[];if(ar.data){var ap=this.filters_manager.filters;for(var aB=0,aD=ar.data.length;aB<aD;aB++){var ak=ar.data[aB];var aC=false;var aq;for(var aF=0,aI=ap.length;aF<aI;aF++){aq=ap[aF];aq.update_attrs(ak);if(!aq.keep(ak)){aC=true;break}}if(!aC){am.push(ak)}}}var aw=(this.filters_manager.alpha_filter?new N(this.filters_manager.alpha_filter):null);var aH=new (this.painter)(am,aG,af,this.prefs,av,aw,ah);var aj=Math.max(ac,aH.get_required_height(al));var ag=this.view.canvas_manager.new_canvas();ag.width=ay+ai;ag.height=aj;var az=ag.getContext("2d");az.fillStyle=this.prefs.block_color;az.font=az.canvas.manager.default_font;az.textAlign="right";this.container_div.find(".yaxislabel").remove();if(ar.data){az.translate(ai,0);aH.draw(az,ay,aj,at)}return new O(aE,aA,ag,ar.data,ar.message)}});var S=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.painter=K.VariantPainter};p(S.prototype,L.prototype,e.prototype);var V=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.track_config=new Y({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ag,onchange:function(){this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.track_config.values;this.painter=K.ReadPainter;this.make_name_popup_menu()};p(V.prototype,L.prototype,e.prototype);var T=function(ai,ag,ak,ae,ah,aj,af){e.call(this,ai,ag,ak,ae,ah,aj,{},af);this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};p(T.prototype,L.prototype,e.prototype,{predraw_init:function(){var af=this;var ae=function(){if(af.data_manager.size()===0){setTimeout(ae,300)}else{af.data_url=default_data_url;af.data_query_wait=J;af.dataset_state_url=converted_datasets_state_url;$.getJSON(af.dataset_state_url,{dataset_id:af.dataset_id,hda_ldda:af.hda_ldda},function(ag){})}};ae()}});W.View=ab;W.DrawableCollection=y;W.LineTrack=k;W.FeatureTrack=e;W.ReadTrack=V};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,W){var p=f("class").extend,r=f("slotting"),K=f("painters");var ad=function(ae,af){this.document=ae;this.default_font=af!==undefined?af:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};p(ad.prototype,{load_pattern:function(ae,ai){var af=this.patterns,ag=this.dummy_context,ah=new Image();ah.src=image_path+ai;ah.onload=function(){af[ae]=ag.createPattern(ah,"repeat")}},get_pattern:function(ae){return this.patterns[ae]},new_canvas:function(){var ae=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ae)}ae.manager=this;return ae}});var m=function(ae,ag,ah){ah=".group";var af={};ae.bind("drag",{handle:"."+ag,relative:true},function(an,ao){var aq=$(this).parent(),al=aq.children(),ak,aj,ap,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ap=aj.position().top;ai=ap+aj.outerHeight();if(ao.offsetY<ap){$(this).insertBefore(aj);return}else{if(ao.offsetY>ai){$(this).insertAfter(aj);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ap=ak.position().top;ai=ap+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&ao.offsetY>=ap&&ao.offsetY<=ai){if(ao.offsetY-ap<ai-ao.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}return}}for(am=0;am<al.length;am++){if(ao.offsetY<$(al.get(am)).position().top){break}}if(am===al.length){if(this!==al.get(am-1)){aq.append(this)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am))}}}).bind("dragstart",function(){af["border-top"]=ae.css("border-top");af["border-bottom"]=ae.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(af)})};W.moveable=m;var ac=16,F=9,D=20,R=F+2,z=100,H=12000,P=200,C=5,u=10,J=5000,v=100,n="There was an error in indexing this dataset. ",I="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",s="Currently indexing... please wait",x="Tool cannot be rerun: ",a="Loading data...",X="Ready for display",d=10,t=5,B=5;function w(ae){return Math.round(ae*1000)/1000}var c=function(ae){this.num_elements=ae;this.clear()};p(c.prototype,{get:function(af){var ae=this.key_ary.indexOf(af);if(ae!==-1){if(this.obj_cache[af].stale){this.key_ary.splice(ae,1);delete this.obj_cache[af]}else{this.move_key_to_end(af,ae)}}return this.obj_cache[af]},set:function(af,ag){if(!this.obj_cache[af]){if(this.key_ary.length>=this.num_elements){var ae=this.key_ary.shift();delete this.obj_cache[ae]}this.key_ary.push(af)}this.obj_cache[af]=ag;return ag},move_key_to_end:function(af,ae){this.key_ary.splice(ae,1);this.key_ary.push(af)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var Q=function(af,ae,ag){c.call(this,af);this.track=ae;this.subset=(ag!==undefined?ag:true)};p(Q.prototype,c.prototype,{load_data:function(an,ai,al,af,ak){var am=this.track.view.chrom,ah={chrom:am,low:an,high:ai,mode:al,resolution:af,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ah,ak);if(this.track.filters_manager){var ao=[];var ae=this.track.filters_manager.filters;for(var aj=0;aj<ae.length;aj++){ao[ao.length]=ae[aj].name}ah.filter_cols=JSON.stringify(ao)}var ag=this;return $.getJSON(this.track.data_url,ah,function(ap){ag.set_data(an,ai,al,ap)})},get_data:function(ae,ai,aj,af,ah){var ag=this.get_data_from_cache(ae,ai,aj);if(ag){return ag}ag=this.load_data(ae,ai,aj,af,ah);this.set_data(ae,ai,aj,ag);return ag},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(am,ah,al,ag,ak,ai){var an=this.get_data_from_cache(am,ah,al);if(!an){console.log("ERROR: no current data for: ",this.track,am,ah,al,ag,ak);return}an.stale=true;var af=am;if(ai===this.DEEP_DATA_REQ){$.extend(ak,{start_val:an.data.length+1})}else{if(ai===this.BROAD_DATA_REQ){af=an.data[an.data.length-1][2]+1}}var ae=this,aj=this.load_data(af,ah,al,ag,ak);new_data_available=$.Deferred();this.set_data(am,ah,al,new_data_available);$.when(aj).then(function(ao){if(ao.data){ao.data=an.data.concat(ao.data);if(ao.message){ao.message=ao.message.replace(/[0-9]+/,ao.data.length)}}ae.set_data(am,ah,al,ao);new_data_available.resolve(ao)});return new_data_available},get_data_from_cache:function(ae,af,ag){return this.get(this.gen_key(ae,af,ag))},set_data:function(af,ag,ah,ae){return this.set(this.gen_key(af,ag,ah),ae)},gen_key:function(ae,ag,ah){var af=ae+"_"+ag+"_"+ah;return af},split_key:function(ae){return ae.split("_")}});var G=function(af,ae,ag){Q.call(this,af,ae,ag)};p(G.prototype,Q.prototype,c.prototype,{load_data:function(ag,ae,ai,aj,af,ah){if(af>1){return}return Q.prototype.load_data.call(this,ag,ae,ai,aj,af,ah)}});var ab=function(ae,ah,ag,af,ai){this.container=ae;this.chrom=null;this.vis_id=ag;this.dbkey=af;this.title=ah;this.tracks=[];this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(ai);this.canvas_manager=new ad(ae.get(0).ownerDocument);this.reset()};p(ab.prototype,{init:function(ai){var ag=this.container,ae=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ag);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ag);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ag);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ah=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var af=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){ae.go_to($(this).val())}$(this).hide();$(this).val("");ae.location_span.show();ae.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",af).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ae.location_span.hide();ae.chrom_select.hide();ae.nav_input.val(ae.chrom+":"+ae.low+"-"+ae.high);ae.nav_input.css("display","inline-block");ae.nav_input.select();ae.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ae.zoom_out();ae.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ae.zoom_in();ae.request_redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},ai);this.chrom_select.bind("change",function(){ae.change_chrom(ae.chrom_select.val())});this.content_div.click(function(aj){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(aj){ae.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/ae.viewport_container.width()*(ae.max_high-ae.max_low));ae.move_delta(-ak)});this.overview_close.click(function(){ae.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>ae.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=ae.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){var am=Math.round(-ak/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:ae.content_div.height()+ae.top_labeltrack.height()+ae.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX),width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-ae.container.offset().left,aj=Math.max(an.pageX,ao.startX)-ae.container.offset().left,am=(ae.high-ae.low),al=ae.viewport_container.width();ae.update_location(Math.round(ak/al*am)+ae.low,Math.round(aj/al*am)+ae.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(ae.high-ae.low),al=ae.viewport_container.width(),an=ae.low;ae.low=Math.round(ak/al*am)+an;ae.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();ae.request_redraw()});this.add_label_track(new aa(this,this.top_labeltrack));this.add_label_track(new aa(this,this.nav_labeltrack));$(window).bind("resize",function(){ae.resize_window()});$(document).bind("redraw",function(){ae.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.show()}else{this.intro_div.hide()}},update_location:function(ae,af){this.location_span.text(commatize(ae)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ae)+"-"+commatize(af))},load_chroms:function(af,ag){af.num=v;$.extend(af,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ae=this;$.ajax({url:chrom_url,data:af,dataType:"json",success:function(ai){if(ai.chrom_info.length===0){alert("Invalid chromosome: "+af.chrom);return}if(ai.reference){ae.add_label_track(new A(ae))}ae.chrom_data=ai.chrom_info;var al='<option value="">Select Chrom/Contig</option>';for(var ak=0,ah=ae.chrom_data.length;ak<ah;ak++){var aj=ae.chrom_data[ak].chrom;al+='<option value="'+aj+'">'+aj+"</option>"}if(ai.prev_chroms){al+='<option value="previous">Previous '+v+"</option>"}if(ai.next_chroms){al+='<option value="next">Next '+v+"</option>"}ae.chrom_select.html(al);if(ag){ag()}ae.chrom_start_index=ai.start_index},error:function(){alert("Could not load chroms for this dbkey:",ae.dbkey)}})},change_chrom:function(ai,af,ak){if(!ai||ai==="None"){return}var ah=this;if(ai==="previous"){ah.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){ah.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(ah.chrom_data,function(am,an){return am.chrom===ai})[0];if(aj===undefined){ah.load_chroms({chrom:ai},function(){ah.change_chrom(ai,af,ak)});return}else{if(ai!==ah.chrom){ah.chrom=ai;ah.chrom_select.val(ah.chrom);ah.max_high=aj.len-1;ah.reset();ah.request_redraw(true);for(var al=0,ae=ah.tracks.length;al<ae;al++){var ag=ah.tracks[al];if(ag.init){ag.init()}}}if(af!==undefined&&ak!==undefined){ah.low=Math.max(af,0);ah.high=Math.min(ak,ah.max_high)}ah.reset_overview();ah.request_redraw()}},go_to:function(ai){var am=this,ae,ah,af=ai.split(":"),ak=af[0],al=af[1];if(al!==undefined){try{var aj=al.split("-");ae=parseInt(aj[0].replace(/,/g,""),10);ah=parseInt(aj[1].replace(/,/g,""),10)}catch(ag){return false}}am.change_chrom(ak,ae,ah)},move_fraction:function(ag){var ae=this;var af=ae.high-ae.low;this.move_delta(ag*af)},move_delta:function(ag){var ae=this;var af=ae.high-ae.low;if(ae.low-ag<ae.max_low){ae.low=ae.max_low;ae.high=ae.max_low+af}else{if(ae.high-ag>ae.max_high){ae.high=ae.max_high;ae.low=ae.max_high-af}else{ae.high-=ag;ae.low-=ag}}ae.request_redraw()},add_track:function(ae){ae.view=this;ae.track_id=this.track_id_counter;this.tracks.push(ae);if(ae.init){ae.init()}ae.container_div.attr("id","track_"+ae.track_id);m(ae.container_div,ae.drag_handle_class);this.track_id_counter+=1;this.num_tracks+=1;this.has_changes=true;this.update_intro_div()},add_label_track:function(ae){ae.view=this;this.label_tracks.push(ae)},remove_track:function(af){this.has_changes=true;delete this.tracks[this.tracks.indexOf(af)];this.num_tracks-=1;var ae=this;af.container_div.fadeOut("slow",function(){$(this).remove();ae.update_intro_div()})},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(am,ae,al,af){var ak=this,ai=(af?[af]:ak.tracks),ag;var af;for(var aj=0;aj<ai.length;aj++){af=ai[aj];ag=-1;for(var ah=0;ah<ak.tracks_to_be_redrawn.length;ah++){if(ak.tracks_to_be_redrawn[ah][0]===af){ag=ah;break}}if(ag<0){ak.tracks_to_be_redrawn.push([af,ae,al])}else{ak.tracks_to_be_redrawn[aj][1]=ae;ak.tracks_to_be_redrawn[aj][2]=al}}requestAnimationFrame(function(){ak._redraw(am)})},_redraw:function(ao){var al=this.low,ah=this.high;if(al<this.max_low){al=this.max_low}if(ah>this.max_high){ah=this.max_high}var an=this.high-this.low;if(this.high!==0&&an<this.min_separation){ah=al+this.min_separation}this.low=Math.floor(al);this.high=Math.ceil(ah);this.resolution=Math.pow(C,Math.ceil(Math.log((this.high-this.low)/P)/Math.log(C)));this.zoom_res=Math.pow(u,Math.max(0,Math.ceil(Math.log(this.resolution,u)/Math.log(u))));var ae=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ak=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ap=13;this.overview_box.css({left:ae,width:Math.max(ap,ak)}).show();if(ak<ap){this.overview_box.css("left",ae-(ap-ak)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ae,width:ak})}this.update_location(this.low,this.high);if(!ao){var ag,af,am;for(var ai=0,aj=this.tracks_to_be_redrawn.length;ai<aj;ai++){ag=this.tracks_to_be_redrawn[ai][0];af=this.tracks_to_be_redrawn[ai][1];am=this.tracks_to_be_redrawn[ai][2];if(ag&&ag.enabled){ag._draw(af,am)}}this.tracks_to_be_redrawn=[];for(ai=0,aj=this.label_tracks.length;ai<aj;ai++){this.label_tracks[ai]._draw()}}},zoom_in:function(af,ag){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ah=this.high-this.low,ai=ah/2+this.low,ae=(ah/this.zoom_factor)/2;if(af){ai=af/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ai-ae);this.high=Math.round(ai+ae);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var af=this.high-this.low,ag=af/2+this.low,ae=(af*this.zoom_factor)/2;this.low=Math.round(ag-ae);this.high=Math.round(ag+ae);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ae){$.when(ae.get_overview_tile()).then(function(af){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(af.canvas);view.overview_highlight.show().height(af.canvas.height());view.overview_viewport.height(af.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ae;ae.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var q=function(ag,ak){this.track=ag;this.name=ak.name;this.params=[];var ar=ak.params;for(var ah=0;ah<ar.length;ah++){var am=ar[ah],af=am.name,aq=am.label,ai=unescape(am.html),at=am.value,ao=am.type;if(ao==="number"){this.params[this.params.length]=new g(af,aq,ai,at,am.min,am.max)}else{if(ao=="select"){this.params[this.params.length]=new M(af,aq,ai,at)}else{console.log("WARNING: unrecognized tool parameter type:",af,ao)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(av){av.stopPropagation()}).click(function(av){av.stopPropagation()}).bind("dblclick",function(av){av.stopPropagation()});var ap=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var an=this.params;var al=this;$.each(this.params,function(aw,az){var ay=$("<div>").addClass("param-row").appendTo(al.parent_div);var av=$("<div>").addClass("param-label").text(az.label).appendTo(ay);var ax=$("<div/>").addClass("slider").html(az.html).appendTo(ay);ax.find(":input").val(az.value);$("<div style='clear: both;'/>").appendTo(ay)});this.parent_div.find("input").click(function(){$(this).select()});var au=$("<div>").addClass("param-row").appendTo(this.parent_div);var aj=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(au);var ae=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(au);var al=this;ae.click(function(){al.run_on_region()});aj.click(function(){al.run_on_dataset()})};p(q.prototype,{get_param_values_dict:function(){var ae={};this.parent_div.find(":input").each(function(){var af=$(this).attr("name"),ag=$(this).val();ae[af]=JSON.stringify(ag)});return ae},get_param_values:function(){var af=[];var ae={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();if(ag){af[af.length]=ah}});return af},run_on_dataset:function(){var ae=this;ae.run({dataset_id:this.track.original_dataset_id,tool_id:ae.name},null,function(af){show_modal(ae.name+" is Running",ae.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},ag=this.track,af=ae.tool_id+ag.tool_region_and_parameters_str(ae.chrom,ae.low,ae.high),ah;if(ag instanceof e){ah=new T(af,view,ag.hda_ldda,undefined,{},{},ag);ah.change_mode(ag.mode)}this.track.add_track(ah);ah.content_div.text("Starting job.");this.run(ae,ah,function(ai){ah.dataset_id=ai.dataset_id;ah.content_div.text("Running job.");ah.init()})},run:function(af,ag,ah){$.extend(af,this.get_param_values_dict());var ae=function(){$.getJSON(rerun_tool_url,af,function(ai){if(ai==="no converter"){ag.container_div.addClass("error");ag.content_div.text(I)}else{if(ai.error){ag.container_div.addClass("error");ag.content_div.text(x+ai.message)}else{if(ai==="pending"){ag.container_div.addClass("pending");ag.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ae,2000)}else{ah(ai)}}}})};ae()}});var M=function(af,ae,ag,ah){this.name=af;this.label=ae;this.html=ag;this.value=ah};var g=function(ag,af,ai,aj,ah,ae){M.call(this,ag,af,ai,aj);this.min=ah;this.max=ae};var h=function(af,ae,ag,ah){this.name=af;this.index=ae;this.tool_id=ag;this.tool_exp_name=ah};var U=function(af,ae,ag,ah){h.call(this,af,ae,ag,ah);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};p(U.prototype,{applies_to:function(ae){if(ae.length>this.index){return true}return false},keep:function(ae){if(!this.applies_to(ae)){return true}var af=parseFloat(ae[this.index]);return(isNaN(af)||(af>=this.low&&af<=this.high))},update_attrs:function(af){var ae=false;if(!this.applies_to(af)){return ae}if(af[this.index]<this.min){this.min=Math.floor(af[this.index]);ae=true}if(af[this.index]>this.max){this.max=Math.ceil(af[this.index]);ae=true}return ae},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var ag=function(aj,ah){var ai=ah-aj;return(ai<=2?0.01:1)};var af=this.slider.slider("option","min"),ae=this.slider.slider("option","max");if(this.min<af||this.max>ae){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",ag(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var Z=function(ao,av){this.track=ao;this.filters=[];for(var ap=0;ap<av.length;ap++){var aq=av[ap],aw=aq.name,ae=aq.type,ah=aq.index,au=aq.tool_id,at=aq.tool_exp_name;if(ae==="int"||ae==="float"){this.filters[ap]=new U(aw,ah,au,at)}else{console.log("ERROR: unsupported filter: ",aw,ae)}}var ai=function(ax,ay,az){ax.click(function(){var aA=ay.text();max=parseFloat(az.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(az.slider("option","values")){input_size=2*input_size+1;multi_value=true}ay.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aA).appendTo(ay).focus().select().click(function(aB){aB.stopPropagation()}).blur(function(){$(this).remove();ay.text(aA)}).keyup(function(aF){if(aF.keyCode===27){$(this).trigger("blur")}else{if(aF.keyCode===13){var aD=az.slider("option","min"),aB=az.slider("option","max"),aE=function(aG){return(isNaN(aG)||aG>aB||aG<aD)},aC=$(this).val();if(!multi_value){aC=parseFloat(aC);if(aE(aC)){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}else{aC=aC.split("-");aC=[parseFloat(aC[0]),parseFloat(aC[1])];if(aE(aC[0])||aE(aC[1])){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}az.slider((multi_value?"values":"value"),aC)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ax){ax.stopPropagation()}).click(function(ax){ax.stopPropagation()}).bind("dblclick",function(ax){ax.stopPropagation()}).bind("keydown",function(ax){ax.stopPropagation()});var ar=$("<div/>").addClass("sliders").appendTo(this.parent_div);var am=this;$.each(this.filters,function(aA,aC){aC.container=$("<div/>").addClass("slider-row").appendTo(ar);var aB=$("<div/>").addClass("elt-label").appendTo(aC.container);var az=$("<span/>").addClass("slider-name").text(aC.name+" ").appendTo(aB);var ay=$("<span/>");var aE=$("<span/>").addClass("slider-value").appendTo(aB).append("[").append(ay).append("]");var ax=$("<div/>").addClass("slider").appendTo(aC.container);aC.control_element=$("<div/>").attr("id",aC.name+"-filter-control").appendTo(ax);var aD=[0,0];aC.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aG,aH){var aF=aH.values;ay.text(aF[0]+"-"+aF[1]);aC.low=aF[0];aC.high=aF[1];am.track.request_draw(true,true)},change:function(aF,aG){aC.control_element.slider("option","slide").call(aC.control_element,aF,aG)}});aC.slider=aC.control_element;aC.slider_label=ay;ai(aE,ay,aC.control_element);$("<div style='clear: both;'/>").appendTo(aC.container)});if(this.filters.length!==0){var aj=$("<div/>").addClass("param-row").appendTo(ar);var al=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(aj);var ag=this;al.click(function(){ag.run_on_dataset()})}var an=$("<div/>").addClass("display-controls").appendTo(this.parent_div),ak=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(an),af=$("<select/>").attr("name","alpha_dropdown").appendTo(an);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(af);for(var ap=0;ap<this.filters.length;ap++){$("<option/>").attr("value",ap).text(this.filters[ap].name).appendTo(af)}af.change(function(){$(this).children("option:selected").each(function(){var ax=parseInt($(this).val());am.alpha_filter=(ax>=0?am.filters[ax]:null);am.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};p(Z.prototype,{reset_filters:function(){for(var ae=0;ae<this.filters.length;ae++){filter=this.filters[ae];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var am=function(aq,ao,ap){if(!(ao in aq)){aq[ao]=ap}return aq[ao]};var ag={},ae,af,ah;for(var ai=0;ai<this.filters.length;ai++){ae=this.filters[ai];if(ae.tool_id){if(ae.min!=ae.low){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" >= "+ae.low}if(ae.max!=ae.high){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" <= "+ae.high}}}var ak=[];for(var an in ag){ak[ak.length]=[an,ag[an]]}var al=ak.length;(function aj(av,ar){var ap=ar[0],aq=ap[0],au=ap[1],at="("+au.join(") and (")+")",ao={cond:at,input:av,target_dataset_id:av,tool_id:aq},ar=ar.slice(1);$.getJSON(run_tool_url,ao,function(aw){if(aw.error){show_modal("Filter Dataset","Error running tool "+aq,{Close:hide_modal})}else{if(ar.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aj(aw.dataset_id,ar)}}})})(this.track.dataset_id,ak)}});var N=function(af,ae){K.AlphaGenerator.call(this,ae);this.filter=af};N.prototype.gen_alpha=function(ae){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ae[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var Y=function(ae){this.track=ae.track;this.params=ae.params;this.values={};if(ae.saved_values){this.restore_values(ae.saved_values)}this.onchange=ae.onchange};p(Y.prototype,{restore_values:function(ae){var af=this;$.each(this.params,function(ag,ah){if(ae[ah.key]!==undefined){af.values[ah.key]=ae[ah.key]}else{af.values[ah.key]=ah.default_value}})},build_form:function(){var af=this;var ae=$("<div />");$.each(this.params,function(aj,ah){if(!ah.hidden){var ag="param_"+aj;var al=af.values[ah.key];var ao=$("<div class='form-row' />").appendTo(ae);ao.append($("<label />").attr("for",ag).text(ah.label+":"));if(ah.type==="bool"){ao.append($('<input type="checkbox" />').attr("id",ag).attr("name",ag).attr("checked",al))}else{if(ah.type==="text"){ao.append($('<input type="text"/>').attr("id",ag).val(al).click(function(){$(this).select()}))}else{if(ah.type==="color"){var ak=$("<input />").attr("id",ag).attr("name",ag).val(al);var am=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var ai=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am);var an=$("<div/>").appendTo(ai).farbtastic({width:100,height:100,callback:ak,color:al});$("<div />").append(ak).append(am).appendTo(ao).bind("click",function(ap){am.css({left:$(this).position().left+($(ak).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){am.hide();$(document).unbind("click.color-picker")});ap.stopPropagation()})}else{ao.append($("<input />").attr("id",ag).attr("name",ag).val(al))}}}}});return ae},update_from_form:function(ae){var ag=this;var af=false;$.each(this.params,function(ah,aj){if(!aj.hidden){var ak="param_"+ah;var ai=ae.find("#"+ak).val();if(aj.type==="float"){ai=parseFloat(ai)}else{if(aj.type==="int"){ai=parseInt(ai)}else{if(aj.type==="bool"){ai=ae.find("#"+ak).is(":checked")}}}if(ai!==ag.values[aj.key]){ag.values[aj.key]=ai;af=true}}});if(af){this.onchange()}}});var b=function(ag,af,ae,ah){this.index=ag;this.low=ag*P*af;this.high=(ag+1)*P*af;this.resolution=af;this.canvas=$("<div class='track-tile'/>").append(ae);this.data=ah;this.stale=false};var l=function(ag,af,ae,ah,ai){b.call(this,ag,af,ae,ah);this.max_val=ai};var O=function(ag,af,ae,ai,ah){b.call(this,ag,af,ae,ai);this.message=ah};var o=function(af,ae){this.name=af;this.view=ae;this.parent_element=ae.viewport_container};o.prototype.request_draw=function(){};o.prototype.draw=function(){};var y=function(af,ae){o.call(this,af,ae);this.members=[];this.drag_handle_class="group-handle";this.container_div=$("<div/>").addClass("group").appendTo(this.parent_element);this.container_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);this.content_div=$("<div/>").addClass("content-div").appendTo(this.container_div)};p(y.prototype,o.prototype,{request_draw:function(af,ae){},draw:function(){}});var j=function(af,ae,ai,ag,ah){this.name=af;this.view=ae;this.parent_element=ai;this.data_url=(ag?ag:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ah?ah:J);this.dataset_check_url=converted_datasets_state_url;this.drag_handle_class="draghandle";this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};p(j.prototype,{get_type:function(){if(this instanceof aa){return"LabelTrack"}else{if(this instanceof A){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof V){return"ReadTrack"}else{if(this instanceof T){return"ToolDataFeatureTrack"}else{if(this instanceof S){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.initial_canvas=undefined;ae.content_div.css("height","auto");ae.container_div.removeClass("nodata error pending");if(!ae.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id,chrom:ae.view.chrom},function(af){if(!af||af==="error"||af.kind==="error"){ae.container_div.addClass("error");ae.content_div.text(n);if(af.message){var ah=ae.view.tracks.indexOf(ae);var ag=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+af.message+"</pre>",{Close:hide_modal})});ae.content_div.append(ag)}}else{if(af==="no converter"){ae.container_div.addClass("error");ae.content_div.text(I)}else{if(af==="no data"||(af.data!==undefined&&(af.data===null||af.data.length===0))){ae.container_div.addClass("nodata");ae.content_div.text(E)}else{if(af==="pending"){ae.container_div.addClass("pending");ae.content_div.text(s);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(af.status==="data"){if(af.valid_chroms){ae.valid_chroms=af.valid_chroms;ae.make_name_popup_menu()}ae.content_div.text(X);if(ae.view.chrom){ae.content_div.text("");ae.content_div.css("height",ae.height_px+"px");ae.enabled=true;$.when(ae.predraw_init()).done(function(){ae.container_div.removeClass("nodata error pending");ae.request_draw()})}}}}}}})},predraw_init:function(){},set_name:function(ae){this.old_name=this.name;this.name=ae;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var L=function(al,aj,am){var af=this,an=af.view;this.filters_manager=(al!==undefined?new Z(this,al):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(aj!==undefined&&obj_length(aj)>0?new q(this,aj):undefined);this.is_overview=false;this.parent_track=am;this.child_tracks=[];if(af.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}af.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();af.container_div.append(af.child_tracks_container);if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(af.display_modes!==undefined){if(af.mode_div===undefined){af.mode_div=$("<div class='right-float menubutton popup' />").appendTo(af.header_div);var ag=(af.track_config&&af.track_config.values.mode?af.track_config.values.mode:af.display_modes[0]);af.mode=ag;af.mode_div.text(ag);var ae={};for(var ah=0,ak=af.display_modes.length;ah<ak;ah++){var ai=af.display_modes[ah];ae[ai]=function(ao){return function(){af.change_mode(ao)}}(ai)}make_popupmenu(af.mode_div,ae)}else{af.mode_div.hide()}}this.make_name_popup_menu()};p(L.prototype,j.prototype,{change_mode:function(af){var ae=this;ae.mode_div.text(af);ae.mode=af;ae.track_config.values.mode=af;ae.tile_cache.clear();ae.request_draw()},make_name_popup_menu:function(){var af=this;var ae={};ae[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(af.is_overview){af.view.reset_overview()}else{af.view.set_overview(af)}};ae["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){af.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Track",af.track_config.build_form(),{Cancel:al,OK:aj})};if(af.filters_available>0){var ai=(af.filters_div.is(":visible")?"Hide filters":"Show filters");ae[ai]=function(){af.filters_visible=(af.filters_div.is(":visible"));if(af.filters_visible){af.filters_manager.reset_filters()}af.filters_div.toggle();af.make_name_popup_menu()}}if(af.tool){var ai=(af.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ae[ai]=function(){if(!af.dynamic_tool_div.is(":visible")){af.set_name(af.name+af.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";af.revert_name()}af.dynamic_tool_div.toggle();af.make_name_popup_menu()}}if(af.valid_chroms){ae["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+af.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var ag=view;var ah=function(){$("#no-tracks").show()};if(this.parent_track){ag=this.parent_track;ah=function(){}}ae.Remove=function(){ag.remove_track(af);if(ag.num_tracks===0){ah()}};make_popupmenu(af.name_div,ae)},set_is_overview:function(ae){this.is_overview=ae;this.make_name_popup_menu()},get_overview_tile:function(){var ae=this;view=ae.view,resolution=Math.pow(C,Math.ceil(Math.log((view.max_high-view.max_low)/P)/Math.log(C))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ae.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ae.data_url_extra_params)).then(function(af){var ah=ae._gen_tile_cache_key(view_width,w_scale,0),aj=ae.tile_cache.get(ah);if(!aj){aj=ae.draw_tile(af,"Auto",resolution,0,w_scale);ae.tile_cache.set(ah,aj)}var am=$(aj.canvas.find("canvas")),ai=am.clone(),al=am.get(0).getContext("2d"),ag=ai.get(0).getContext("2d"),ak=al.getImageData(0,0,al.canvas.width,al.canvas.height);ag.putImageData(ak,-ae.left_offset,(aj.data.dataset_type==="summary_tree"?R:0));new_tile=new b(-1,resolution,ai);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(af,ag,ae){return af+"_"+ag+"_"+ae},request_draw:function(af,ae){this.view.request_redraw(false,af,ae,this)},_draw:function(ag,ap){if(!this.dataset_id){return}var ao=this.view.low,ak=this.view.high,am=ak-ao,ah=this.view.container.width(),at=ah/am,aj=this.view.resolution,ar=$("<div style='position: relative;'></div>");if(!ap){this.content_div.children().remove()}this.content_div.append(ar);this.max_height=0;var af=Math.floor(ao/aj/P);var an=true;var aq=[];var ae=0;while((af*P*aj)<ak){tile=this.draw_helper(ag,ah,af,aj,ar,at);if(tile){aq.push(tile)}else{an=false}af+=1;ae++}var ai=this;if(an){ai.postdraw_actions(aq,ah,at,ap)}for(var al=0;al<this.child_tracks.length;al++){this.child_tracks[al].request_draw(ag,ap)}},postdraw_actions:function(ai,aj,ak,ae){var ag=this;var ah=false;for(var af=0;af<ai.length;af++){if(ai[af].message){ah=true;break}}if(ah){for(var af=0;af<ai.length;af++){tile=ai[af];if(!tile.message){tile.canvas.css("padding-top",D)}}}},draw_helper:function(af,ag,ah,ak,aq,av,ar,al){var ai=this,ap=this._gen_tile_cache_key(ag,av,ah),am=ah*P*ak,au=am+P*ak;var an=(af?undefined:ai.tile_cache.get(ap));if(an){ai.show_tile(an,aq,av);return an}var ao=function(aw){return("isResolved" in aw)};var aj=true;var ae=ai.data_manager.get_data(am,au,ai.mode,ak,ai.data_url_extra_params);if(ao(ae)){aj=false}var at;if(view.reference_track&&av>view.canvas_manager.char_width_px){at=view.reference_track.data_manager.get_data(am,au,ai.mode,ak,view.reference_track.data_url_extra_params);if(ao(at)){aj=false}}if(aj){p(ae,al);var an=ai.draw_tile(ae,ai.mode,ak,ah,av,at);ai.tile_cache.set(ap,an);if(an!==undefined){ai.show_tile(an,aq,av)}return an}$.when(ae,at).then(function(){view.request_redraw()});return null},show_tile:function(al,an,ao){var ag=this,af=al.canvas,ak=af;if(al.message){var ap=$("<div/>"),am=$("<div/>").addClass("tile-message").text(al.message).css({height:D-1,width:al.canvas.width}).appendTo(ap),ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(am),ae=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(am);ap.append(af);ak=ap;ai.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()});ae.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()})}var aj=this.view.high-this.view.low,ah=(al.low-this.view.low)*ao;if(this.left_offset){ah-=this.left_offset}ak.css({position:"absolute",top:0,left:ah,height:""});an.append(ak);ag.max_height=Math.max(ag.max_height,ak.height());ag.content_div.css("height",ag.max_height+"px");an.children().css("height",ag.max_height+"px")},tool_region_and_parameters_str:function(ag,ae,ah){var af=this,ai=(ag!==undefined&&ae!==undefined&&ah!==undefined?ag+":"+ae+"-"+ah:"all");return" - region=["+ai+"], parameters=["+af.tool.get_param_values().join(", ")+"]"},add_track:function(ae){ae.track_id=this.track_id+"_"+this.child_tracks.length;ae.container_div.attr("id","track_"+ae.track_id);this.child_tracks_container.append(ae.container_div);m(ae.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(ae);this.view.has_changes=true},remove_track:function(ae){ae.container_div.fadeOut("slow",function(){$(this).remove()})}});var aa=function(ae,af){this.hidden=true;j.call(this,null,ae,af);this.container_div.addClass("label-track")};p(aa.prototype,j.prototype,{_draw:function(){var ag=this.view,ah=ag.high-ag.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ah)/Math.log(10)))),ae=Math.floor(ag.low/ak)*ak,ai=this.view.container.width(),af=$("<div style='position: relative; height: 1.3em;'></div>");while(ae<ag.high){var aj=(ae-ag.low)/ah*ai;af.append($("<div class='label'>"+commatize(ae)+"</div>").css({position:"absolute",left:aj-1}));ae+=ak}this.content_div.children(":first").remove();this.content_div.append(af)}});var A=function(ae){this.hidden=true;j.call(this,null,ae,ae.top_labeltrack);L.call(this);ae.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ae.dbkey};this.data_manager=new G(B,this,false);this.tile_cache=new c(t)};p(A.prototype,L.prototype,{draw_tile:function(ao,ak,aj,af,ap){var ai=this,ag=P*aj;if(ap>this.view.canvas_manager.char_width_px){if(ao===null){ai.content_div.css("height","0px");return}var ah=this.view.canvas_manager.new_canvas();var an=ah.getContext("2d");ah.width=Math.ceil(ag*ap+ai.left_offset);ah.height=ai.height_px;an.font=an.canvas.manager.default_font;an.textAlign="center";for(var al=0,am=ao.length;al<am;al++){var ae=Math.round(al*ap);an.fillText(ao[al],ae+ai.left_offset,10)}return new b(af,aj,ah,ao)}this.content_div.css("height","0px")}});var k=function(ai,ag,aj,ae,ah){var af=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,ai,ag,ag.viewport_container);L.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=aj;this.dataset_id=ae;this.original_dataset_id=ae;this.data_manager=new Q(B,this);this.tile_cache=new c(t);this.left_offset=0;this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ai},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:ah,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;$("#linetrack_"+af.track_id+"_minval").text(af.prefs.min_value);$("#linetrack_"+af.track_id+"_maxval").text(af.prefs.max_value);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};p(k.prototype,L.prototype,{add_resize_handle:function(){var ae=this;var ah=false;var ag=false;var af=$("<div class='track-resize'>");$(ae.container_div).hover(function(){ah=true;af.show()},function(){ah=false;if(!ag){af.hide()}});af.hide().bind("dragstart",function(ai,aj){ag=true;aj.original_height=$(ae.content_div).height()}).bind("drag",function(aj,ak){var ai=Math.min(Math.max(ak.original_height+ak.deltaY,ae.min_height_px),ae.max_height_px);$(ae.content_div).css("height",ai);ae.height_px=ai;ae.request_draw(true)}).bind("dragend",function(ai,aj){ae.tile_cache.clear();ag=false;if(!ah){af.hide()}ae.track_config.values.height=ae.height_px}).appendTo(ae.container_div)},predraw_init:function(){var ae=this,af=ae.view.tracks.indexOf(ae);ae.vertical_range=undefined;return $.getJSON(ae.data_url,{stats:true,chrom:ae.view.chrom,low:null,high:null,hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id},function(ag){ae.container_div.addClass("line-track");var ai=ag.data;if(isNaN(parseFloat(ae.prefs.min_value))||isNaN(parseFloat(ae.prefs.max_value))){ae.prefs.min_value=ai.min;ae.prefs.max_value=ai.max;$("#track_"+af+"_minval").val(ae.prefs.min_value);$("#track_"+af+"_maxval").val(ae.prefs.max_value)}ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.total_frequency=ai.total_frequency;ae.container_div.find(".yaxislabel").remove();var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_minval").text(w(ae.prefs.min_value));var ah=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_maxval").text(w(ae.prefs.max_value));ah.css({position:"absolute",top:"24px",left:"10px"});ah.prependTo(ae.container_div);aj.css({position:"absolute",bottom:"2px",left:"10px"});aj.prependTo(ae.container_div)})},draw_tile:function(ap,aj,ai,af,ao){if(this.vertical_range===undefined){return}var ak=af*P*ai,ah=P*ai,ae=Math.ceil(ah*ao),am=this.height_px;var ag=this.view.canvas_manager.new_canvas();ag.width=ae,ag.height=am;var an=ag.getContext("2d");var al=new K.LinePainter(ap.data,ak,ak+ah,this.prefs,aj);al.draw(an,ae,am);return new b(af,ai,ag,ap.data)}});var e=function(ae,aj,ai,am,al,ag,ah,ak){var af=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ae},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:al,onchange:function(){af.set_name(af.prefs.name);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;j.call(this,ae,aj,aj.viewport_container);L.call(this,ag,ah,ak);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=ai;this.dataset_id=am;this.original_dataset_id=am;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new Q(20,this);this.left_offset=200;this.painter=K.LinkedFeaturePainter};p(e.prototype,L.prototype,{postdraw_actions:function(au,ae,av,at){L.prototype.postdraw_actions.call(this,au,at);var ah=this;if(at){var aj=ah.content_div.children();var ak=false;for(var ai=aj.length-1,ao=0;ai>=ao;ai--){var ag=$(aj[ai]);if(ak){ag.remove()}else{if(ag.children().length!==0){ak=true}}}}if(ah.mode=="Histogram"){var an=-1;for(var ai=0;ai<au.length;ai++){var ar=au[ai].max_val;if(ar>an){an=ar}}for(var ai=0;ai<au.length;ai++){var aq=au[ai];if(aq.max_val!==an){aq.canvas.remove();ah.draw_helper(true,ae,aq.index,aq.resolution,aq.canvas.parent(),av,[],{max:an})}}}if(ah.filters_manager){var af=ah.filters_manager.filters;for(var am=0;am<af.length;am++){af[am].update_ui_elt()}var al=false,ap;for(var ai=0;ai<au.length;ai++){if(au[ai].data.length){ap=au[ai].data[0];for(var am=0;am<af.length;am++){if(af[am].applies_to(ap)){al=true;break}}}}if(ah.filters_available!==al){ah.filters_available=al;if(!ah.filters_available){ah.filters_div.hide()}ah.make_name_popup_menu()}}},update_auto_mode:function(ae){if(this.mode=="Auto"){if(ae=="no_detail"){ae="feature spans"}else{if(ae=="summary_tree"){ae="coverage histogram"}}this.mode_div.text("Auto ("+ae+")")}},incremental_slots:function(ai,af,ah){var ag=this.view.canvas_manager.dummy_context,ae=this.inc_slots[ai];if(!ae||(ae.mode!==ah)){ae=new (r.FeatureSlotter)(ai,ah==="Pack",z,function(aj){return ag.measureText(aj)});ae.mode=ah;this.inc_slots[ai]=ae}return ae.slot_features(af)},get_summary_tree_data:function(ai,al,ag,au){if(au>ag-al){au=ag-al}var ap=Math.floor((ag-al)/au),at=[],ah=0;var aj=0,ak=0,ao,ar=0,am=[],aq,an;var af=function(ax,aw,ay,av){ax[0]=aw+ay*av;ax[1]=aw+(ay+1)*av};while(ar<au&&aj!==ai.length){var ae=false;for(;ar<au&&!ae;ar++){af(am,al,ar,ap);for(ak=aj;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){ae=true;break}}if(ae){break}}data_start_index=ak;at[at.length]=aq=[am[0],0];for(;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){aq[1]++}else{break}}if(aq[1]>ah){ah=aq[1]}ar++}return{max:ah,delta:ap,data:at}},draw_tile:function(ar,av,aA,aE,an,ah){var ax=this,aG=aE*P*aA,af=(aE+1)*P*aA,au=af-aG,ay=Math.ceil(au*an),aK=25,ai=this.left_offset,at,aj;if(av==="Auto"){if(ar.dataset_type==="summary_tree"){av=ar.dataset_type}else{if(ar.extra_info==="no_detail"){av="no_detail"}else{var aJ=ar.data;if(this.view.high-this.view.low>H){av="Squish"}else{av="Pack"}}}this.update_auto_mode(av)}if(av==="summary_tree"||av==="Histogram"){aj=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ae=$("<div />").addClass("yaxislabel");ae.text(ar.max);ae.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ae.prependTo(this.container_div);var ag=this.view.canvas_manager.new_canvas();ag.width=ay+ai;ag.height=aj+R;if(ar.dataset_type!="summary_tree"){var ao=this.get_summary_tree_data(ar.data,aG,af,200);if(ar.max){ao.max=ar.max}ar=ao}var aH=new K.SummaryTreePainter(ar,aG,af,this.prefs);var az=ag.getContext("2d");az.translate(ai,R);aH.draw(az,ay,aj);return new l(aE,aA,ag,ar.data,ar.max)}var at,al=1;if(av==="no_detail"||av==="Squish"||av==="Pack"){al=this.incremental_slots(an,ar.data,av);at=this.inc_slots[an].slots}var am=[];if(ar.data){var ap=this.filters_manager.filters;for(var aB=0,aD=ar.data.length;aB<aD;aB++){var ak=ar.data[aB];var aC=false;var aq;for(var aF=0,aI=ap.length;aF<aI;aF++){aq=ap[aF];aq.update_attrs(ak);if(!aq.keep(ak)){aC=true;break}}if(!aC){am.push(ak)}}}var aw=(this.filters_manager.alpha_filter?new N(this.filters_manager.alpha_filter):null);var aH=new (this.painter)(am,aG,af,this.prefs,av,aw,ah);var aj=Math.max(ac,aH.get_required_height(al));var ag=this.view.canvas_manager.new_canvas();ag.width=ay+ai;ag.height=aj;var az=ag.getContext("2d");az.fillStyle=this.prefs.block_color;az.font=az.canvas.manager.default_font;az.textAlign="right";this.container_div.find(".yaxislabel").remove();if(ar.data){az.translate(ai,0);aH.draw(az,ay,aj,at)}return new O(aE,aA,ag,ar.data,ar.message)}});var S=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.painter=K.VariantPainter};p(S.prototype,L.prototype,e.prototype);var V=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ag,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.track_config.values;this.painter=K.ReadPainter;this.make_name_popup_menu()};p(V.prototype,L.prototype,e.prototype);var T=function(ai,ag,ak,ae,ah,aj,af){e.call(this,ai,ag,ak,ae,ah,aj,{},af);this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};p(T.prototype,L.prototype,e.prototype,{predraw_init:function(){var af=this;var ae=function(){if(af.data_manager.size()===0){setTimeout(ae,300)}else{af.data_url=default_data_url;af.data_query_wait=J;af.dataset_state_url=converted_datasets_state_url;$.getJSON(af.dataset_state_url,{dataset_id:af.dataset_id,hda_ldda:af.hda_ldda},function(ag){})}};ae()}});W.View=ab;W.DrawableCollection=y;W.LineTrack=k;W.FeatureTrack=e;W.ReadTrack=V};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
--- a/static/scripts/trackster.js Thu Sep 01 12:35:20 2011 -0400
+++ b/static/scripts/trackster.js Thu Sep 01 14:01:00 2011 -0400
@@ -1709,7 +1709,8 @@
this.restore_values( options.saved_values );
}
this.onchange = options.onchange
-}
+};
+
extend(TrackConfig.prototype, {
restore_values: function( values ) {
var track_config = this;
@@ -1727,12 +1728,14 @@
$.each( this.params, function( index, param ) {
if ( ! param.hidden ) {
var id = 'param_' + index;
+ var value = track_config.values[ param.key ];
var row = $("<div class='form-row' />").appendTo( container );
row.append( $('<label />').attr("for", id ).text( param.label + ":" ) );
if ( param.type === 'bool' ) {
- row.append( $('<input type="checkbox" />').attr("id", id ).attr("name", id ).attr( 'checked', track_config.values[ param.key ] ) );
+ row.append( $('<input type="checkbox" />').attr("id", id ).attr("name", id ).attr( 'checked', value ) );
+ } else if ( param.type === 'text' ) {
+ row.append( $('<input type="text"/>').attr("id", id ).val(value).click( function() { $(this).select() }));
} else if ( param.type === 'color' ) {
- var value = track_config.values[ param.key ];
var input = $('<input />').attr("id", id ).attr("name", id ).val( value );
// Color picker in tool tip style float
var tip = $( "<div class='tipsy tipsy-north' style='position: absolute;' />" ).hide();
@@ -1754,8 +1757,9 @@
});
e.stopPropagation();
});
- } else {
- row.append( $('<input />').attr("id", id ).attr("name", id ).val( track_config.values[ param.key ] ) );
+ }
+ else {
+ row.append( $('<input />').attr("id", id ).attr("name", id ).val( value ) );
}
}
});
@@ -1775,7 +1779,7 @@
value = parseInt( value );
} else if ( param.type === 'bool' ) {
value = container.find( '#' + id ).is( ':checked' );
- }
+ }
// Save value only if changed
if ( value !== track_config.values[ param.key ] ) {
track_config.values[ param.key ] = value;
@@ -1994,12 +1998,17 @@
* Additional initialization required before drawing track for the first time.
*/
predraw_init: function() {},
- // Provide support for updating and reverting track name. Currently, it's only possible to revert once.
- update_name: function(new_name) {
+ /**
+ * Set track name.
+ */
+ set_name: function(new_name) {
this.old_name = this.name;
this.name = new_name;
this.name_div.text(this.name);
},
+ /**
+ * Revert track name; currently name can be reverted only once.
+ */
revert_name: function() {
this.name = this.old_name;
this.name_div.text(this.name);
@@ -2173,7 +2182,7 @@
track_dropdown[text] = function() {
// Set track name, toggle tool div, and remake menu.
if (!track.dynamic_tool_div.is(":visible")) {
- track.update_name(track.name + track.tool_region_and_parameters_str());
+ track.set_name(track.name + track.tool_region_and_parameters_str());
}
else {
menu_option_text = "Show dynamic tool";
@@ -2605,6 +2614,7 @@
this.track_config = new TrackConfig( {
track: this,
params: [
+ { key: 'name', label: 'Name', type: 'text', default_value: name },
{ key: 'color', label: 'Color', type: 'color', default_value: 'black' },
{ key: 'min_value', label: 'Min Value', type: 'float', default_value: undefined },
{ key: 'max_value', label: 'Max Value', type: 'float', default_value: undefined },
@@ -2613,6 +2623,7 @@
],
saved_values: prefs,
onchange: function() {
+ track.set_name(track.prefs.name);
track.vertical_range = track.prefs.max_value - track.prefs.min_value;
// Update the y-axis
$('#linetrack_' + track.track_id + '_minval').text(track.prefs.min_value);
@@ -2732,6 +2743,7 @@
this.track_config = new TrackConfig( {
track: this,
params: [
+ { key: 'name', label: 'Name', type: 'text', default_value: name },
{ key: 'block_color', label: 'Block color', type: 'color', default_value: '#444' },
{ key: 'label_color', label: 'Label color', type: 'color', default_value: 'black' },
{ key: 'show_counts', label: 'Show summary counts', type: 'bool', default_value: true },
@@ -2739,6 +2751,7 @@
],
saved_values: prefs,
onchange: function() {
+ track.set_name(track.prefs.name);
track.tile_cache.clear();
track.request_draw();
}
@@ -3119,6 +3132,7 @@
this.track_config = new TrackConfig( {
track: this,
params: [
+ { key: 'name', label: 'Name', type: 'text', default_value: name },
{ key: 'block_color', label: 'Block color', type: 'color', default_value: '#444' },
{ key: 'label_color', label: 'Label color', type: 'color', default_value: 'black' },
{ key: 'show_insertions', label: 'Show insertions', type: 'bool', default_value: false },
@@ -3128,6 +3142,7 @@
],
saved_values: prefs,
onchange: function() {
+ this.track.set_name(this.track.prefs.name);
this.track.tile_cache.clear();
this.track.request_draw();
}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Improve GTF sniffing by doing proper parsing of attributes.
by Bitbucket 01 Sep '11
by Bitbucket 01 Sep '11
01 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/eae23586cb6a/
changeset: eae23586cb6a
user: jgoecks
date: 2011-09-01 18:35:20
summary: Improve GTF sniffing by doing proper parsing of attributes.
affected #: 1 file (687 bytes)
--- a/lib/galaxy/datatypes/interval.py Thu Sep 01 12:13:45 2011 -0400
+++ b/lib/galaxy/datatypes/interval.py Thu Sep 01 12:35:20 2011 -0400
@@ -939,23 +939,11 @@
return False
# Check attributes for gene_id, transcript_id
- attributes = hdr[8].split(";")
+ attributes = parse_gff_attributes( hdr[8] )
if len( attributes ) >= 2:
- try:
- # Imprecise: should check for a single space per the spec.
- # strip() needed b/c Ensembl GTF files include an (illegal)
- # space before attributes string.
- attr_name, attr_value = attributes[0].strip().split(" ")
- if attr_name != 'gene_id':
- return False
- except:
+ if 'gene_id' not in attributes:
return False
- try:
- # Imprecise: should check for a single space per the spec.
- attr_name, attr_value = attributes[1][1:].split(" ")
- if attr_name != 'transcript_id':
- return False
- except:
+ if 'transcript_id' not in attributes:
return False
else:
return False
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

01 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/63e15e4cc0aa/
changeset: 63e15e4cc0aa
user: jgoecks
date: 2011-09-01 18:13:45
summary: Fix Trackster dragging/moving bugs.
affected #: 1 file (79 bytes)
--- a/static/scripts/trackster.js Thu Sep 01 11:08:34 2011 -0400
+++ b/static/scripts/trackster.js Thu Sep 01 12:13:45 2011 -0400
@@ -145,11 +145,12 @@
/**
* Make `element` moveable within parent and sibling elements by dragging `handle` (a selector).
*/
-var moveable = function( element, handle, container_selector ) {
+var moveable = function( element, handle_class, container_selector ) {
// HACK: set default value for container selector.
container_selector = ".group";
var css_border_props = {};
- element.bind( "drag", { handle: handle, relative: true }, function ( e, d ) {
+ // Need to provide selector for handle, not class.
+ element.bind( "drag", { handle: "." + handle_class, relative: true }, function ( e, d ) {
var
parent = $(this).parent(),
children = parent.children(),
@@ -880,7 +881,7 @@
this.tracks.push(track);
if (track.init) { track.init(); }
track.container_div.attr('id', 'track_' + track.track_id);
- moveable(track.container_div, track.drag_handle);
+ moveable(track.container_div, track.drag_handle_class);
this.track_id_counter += 1;
this.num_tracks += 1;
this.has_changes = true;
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/20215fcf6da7/
changeset: 20215fcf6da7
user: dan
date: 2011-09-01 17:08:34
summary: Update existing GATK tools. Add 4 new GATK tools: VariantAnnotator, VariantFiltration, VariantRecalibrator, ApplyRecalibration, ValidateVariants, VariantEval and CombineVariants. All GATK tool wrappers are still considered BETA and (workflow/rerun/etc) backwards-incompatible changes should be expected.
affected #: 28 files (9.1 KB)
Diff too large to display.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/d3349e062ed8/
changeset: d3349e062ed8
user: dan
date: 2011-09-01 15:38:16
summary: Update tests for samtools rmdup.
affected #: 1 file (11 bytes)
--- a/tools/samtools/samtools_rmdup.xml Thu Sep 01 09:24:18 2011 -0400
+++ b/tools/samtools/samtools_rmdup.xml Thu Sep 01 09:38:16 2011 -0400
@@ -32,21 +32,21 @@
</outputs><tests><test>
- <param name="input1" value="3unsorted.bam" ftype="bam" />
+ <param name="input1" value="1.bam" ftype="bam" /><param name="bam_paired_end_type_selector" value="SE" />
- <output name="output1" file="3unsorted.bam" ftype="bam"/>
+ <output name="output1" file="1.bam" ftype="bam" sort="True"/></test><test>
- <param name="input1" value="3unsorted.bam" ftype="bam" />
+ <param name="input1" value="1.bam" ftype="bam" /><param name="bam_paired_end_type_selector" value="PE" /><param name="force_se" value="True" />
- <output name="output1" file="3unsorted.bam" ftype="bam"/>
+ <output name="output1" file="1.bam" ftype="bam" sort="True"/></test><test>
- <param name="input1" value="3unsorted.bam" ftype="bam" />
+ <param name="input1" value="1.bam" ftype="bam" /><param name="bam_paired_end_type_selector" value="PE" /><param name="force_se" />
- <output name="output1" file="3unsorted.bam" ftype="bam"/>
+ <output name="output1" file="1.bam" ftype="bam" sort="True" /></test></tests><help>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
6 new changesets in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/5ed1946867e3/
changeset: 5ed1946867e3
user: jmchilton
date: 2011-05-17 22:29:02
summary: Enhancements to Galaxy's functional testing framework as outlined in issue 490. https://bitbucket.org/galaxy/galaxy-central/issue/490/enabling-iterative-te…
affected #: 6 files (10.7 KB)
--- a/lib/galaxy/tools/__init__.py Tue May 17 13:14:15 2011 -0400
+++ b/lib/galaxy/tools/__init__.py Tue May 17 15:29:02 2011 -0500
@@ -662,8 +662,31 @@
name = attrib.pop( 'name', None )
if name is None:
raise Exception( "Test output does not have a 'name'" )
+
+ assert_elem = output_elem.find("assert_contents")
+ assert_list = None
+ # Trying to keep testing patch as localized as
+ # possible, this function should be relocated
+ # somewhere more conventional.
+ def convert_elem(elem):
+ """ Converts and XML element to a dictionary format, used by assertion checking code. """
+ tag = elem.tag
+ attributes = dict( elem.attrib )
+ child_elems = list( elem.getchildren() )
+ converted_children = []
+ for child_elem in child_elems:
+ converted_children.append( convert_elem(child_elem) )
+ return {"tag" : tag, "attributes" : attributes, "children" : converted_children}
+
+ if assert_elem is not None:
+ assert_list = []
+ for assert_child in list(assert_elem):
+ assert_list.append(convert_elem(assert_child))
+
+
file = attrib.pop( 'file', None )
- if file is None:
+ # File no longer required if an list of assertions was present.
+ if assert_list is None and file is None:
raise Exception( "Test output does not have a 'file'")
attributes = {}
# Method of comparison
@@ -674,6 +697,9 @@
attributes['delta'] = int( attrib.pop( 'delta', '10000' ) )
attributes['sort'] = util.string_as_bool( attrib.pop( 'sort', False ) )
attributes['extra_files'] = []
+ attributes['assert_list'] = assert_list
+
+
if 'ftype' in attrib:
attributes['ftype'] = attrib['ftype']
for extra in output_elem.findall( 'extra_files' ):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/base/asserts/__init__.py Tue May 17 15:29:02 2011 -0500
@@ -0,0 +1,76 @@
+import inspect
+import logging
+import sys
+log = logging.getLogger( __name__ )
+
+assertion_module_names = ['text', 'tabular', 'xml']
+
+# Code for loading modules containing assertion checking functions, to
+# create a new module of assertion functions, create the needed python
+# source file "test/base/asserts/<MODULE_NAME>.py" and add
+# <MODULE_NAME> to the list of assertion module names defined above.
+assertion_modules = []
+for assertion_module_name in assertion_module_names:
+ full_assertion_module_name = 'base.asserts.' + assertion_module_name
+ log.debug(full_assertion_module_name)
+ try:
+ #Dynamically import module
+ __import__(full_assertion_module_name)
+ assertion_module = sys.modules[full_assertion_module_name]
+ assertion_modules.append(assertion_module)
+ except Exception, e:
+ log.exception( 'Failed to load assertion module: %s %s' % (assertion_module_name, str(e)))
+
+def verify_assertions(data, assertion_description_list):
+ """ This function takes a list of assertions and a string to check
+ these assertions against. """
+ for assertion_description in assertion_description_list:
+ verify_assertion(data, assertion_description)
+
+def verify_assertion(data, assertion_description):
+ tag = assertion_description["tag"]
+ assert_function_name = "assert_" + tag
+ assert_function = None
+ for assertion_module in assertion_modules:
+ if hasattr(assertion_module, assert_function_name):
+ assert_function = getattr(assertion_module, assert_function_name)
+
+ if assert_function is None:
+ errmsg = "Unable to find test function associated with XML tag '%s'. Check your tool file syntax." % tag
+ raise AssertionError(errmsg)
+
+ assert_function_args = inspect.getargspec(assert_function).args
+ args = {}
+ for attribute, value in assertion_description["attributes"].iteritems():
+ if attribute in assert_function_args:
+ args[attribute] = value
+
+ # Three special arguments automatically populated independently of
+ # tool XML attributes. output is passed in as the contents of the
+ # output file. verify_assertions_function is passed in as the
+ # verify_assertions function defined above, this allows
+ # recursively checking assertions on subsections of
+ # output. children is the parsed version of the child elements of
+ # the XML element describing this assertion. See
+ # assert_element_text in test/base/asserts/xml.py as an example of
+ # how to use verify_assertions_function and children in conjuction
+ # to apply assertion checking to a subset of the input. The parsed
+ # version of an elements child elements do not need to just define
+ # assertions, developers of assertion functions can also use the
+ # child elements in novel ways to define inputs the assertion
+ # checking function (for instance consider the following fictional
+ # assertion function for checking column titles of tabular output
+ # - <has_column_titles><with_name name="sequence"><with_name
+ # name="probability"></has_column_titles>.)
+ if "output" in assert_function_args:
+ args["output"] = data
+
+ if "verify_assertions_function" in assert_function_args:
+ args["verify_assertions_function"] = verify_assertions
+
+ if "children" in assert_function_args:
+ args["children"] = assertion_description["children"]
+
+ # TODO: Verify all needed function arguments are specified.
+ assert_function(**args)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/base/asserts/tabular.py Tue May 17 15:29:02 2011 -0500
@@ -0,0 +1,17 @@
+import re
+
+def get_first_line(output):
+ match = re.search("^(.*)$", output, flags = re.MULTILINE)
+ if match is None:
+ return None
+ else:
+ return match.group(1)
+
+def assert_has_n_columns(output, n, sep = '\t'):
+ """ Asserts the tabular output contains n columns. The optional
+ sep argument specifies the column seperator used to determine the
+ number of columns."""
+ n = int(n)
+ first_line = get_first_line(output)
+ assert first_line is not None, "Was expecting output with %d columns, but output was empty." % n
+ assert len(first_line.split(sep)) == n, "Output does not have %d columns." % n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/base/asserts/text.py Tue May 17 15:29:02 2011 -0500
@@ -0,0 +1,30 @@
+import re
+
+def assert_has_text(output, text):
+ """ Asserts specified output contains the substring specified by
+ the argument text."""
+ assert output.find(text) >= 0, "Output file did not contain expected text '%s' (ouptut '%s')" % (text, output)
+
+def assert_not_has_text(output, text):
+ """ Asserts specified output does not contain the substring
+ specified the argument text."""
+ assert output.find(text) < 0, "Output file contains unexpected text '%s'" % text
+
+def assert_has_line(output, line):
+ """ Asserts the specified output contains the line specified the
+ argument line."""
+ match = re.search("^%s$" % re.escape(line), output, flags = re.MULTILINE)
+ assert match != None, "No line of output file was '%s' (output was '%s') " % (line, output)
+
+def assert_has_text_matching(output, expression):
+ """ Asserts the specified output contains text matching the
+ regular expression specified by the argument expression."""
+ match = re.search(expression, output)
+ assert match != None, "No text matching expression '%s' was found in output file." % expression
+
+def assert_has_line_matching(output, expression):
+ """ Asserts the specified output contains a line matching the
+ regular expression specified by the argument expression."""
+ match = re.search("^%s$" % expression, output, flags = re.MULTILINE)
+ assert match != None, "No line matching expression '%s' was found in output file." % expression
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/base/asserts/xml.py Tue May 17 15:29:02 2011 -0500
@@ -0,0 +1,77 @@
+import elementtree.ElementTree
+import re
+
+# Helper functions used to work with XML output.
+def to_xml(output):
+ return elementtree.ElementTree.fromstring(output)
+
+def xml_find_text(output, path):
+ xml = to_xml(output)
+ text = xml.findtext(path)
+ return text
+
+def xml_find(output, path):
+ xml = to_xml(output)
+ return xml.find(path)
+
+def assert_is_valid_xml(output):
+ """ Simple assertion that just verifies the specified output
+ is valid XML."""
+ try:
+ to_xml(output)
+ except Exception, e:
+ # TODO: Narrow caught exception to just parsing failure
+ raise AssertionError("Expected valid XML, but could not parse output. %s" % str(e))
+
+def assert_has_element_with_path(output, path):
+ """ Asserts the specified output has at least one XML element with a
+ path matching the specified path argument. Valid paths are the
+ simplified subsets of XPath implemented by elementtree (currently
+ Galaxy makes use of elementtree 1.2). See
+ http://effbot.org/zone/element-xpath.htm for more information."""
+ if xml_find(output, path) is None:
+ errmsg = "Expected to find XML element matching expression %s, not such match was found." % path
+ raise AssertionError(errmsg)
+
+def assert_has_n_elements_with_path(output, path, n):
+ """ Asserts the specified output has exactly n elements matching the
+ path specified."""
+ xml = to_xml(output)
+ n = int(n)
+ num_elements = len(xml.findall(path))
+ if num_elements != n:
+ errmsg = "Expected to find %d elements with path %s, but %d were found." % (n, path, num_elements)
+ raise AssertionError(errmsg)
+
+def assert_element_text_matches(output, path, expression):
+ """ Asserts the text of the first element matching the specified
+ path matches the specified regular expression."""
+ text = xml_find_text(output, path)
+ if re.match(expression, text) is None:
+ errmsg = "Expected element with path '%s' to contain text matching '%s', instead text '%s' was found." % (path, text, actual_text)
+ raise AssertionError(errmsg)
+
+def assert_element_text_is(output, path, text):
+ """ Asserts the text of the first element matching the specified
+ path matches exactly the specified text. """
+ assert_element_text_matches(output, path, re.escape(text))
+
+def assert_attribute_matches(output, path, attribute, expression):
+ """ Asserts the specified attribute of the first element matching
+ the specified path matches the specified regular expression."""
+ xml = xml_find(output, path)
+ attribute_value = xml.attrib[attribute]
+ if re.match(expression, attribute_value) is None:
+ errmsg = "Expected attribute '%s' on element with path '%s' to match '%s', instead attribute value was '%s'." % (attribute, path, expression, attribute_value)
+ raise AssertionError(errmsg)
+
+def assert_attribute_is(output, path, attribute, text):
+ """ Asserts the specified attribute of the first element matching
+ the specified path matches exactly the specified text."""
+ assert_attribute_matches(output, path, attribute, re.escape(text))
+
+def assert_element_text(output, path, verify_assertions_function, children):
+ """ Recursively checks the specified assertions against the text of
+ the first element matching the specified path."""
+ text = xml_find_text(output, path)
+ verify_assertions_function(text, children)
--- a/test/base/twilltestcase.py Tue May 17 13:14:15 2011 -0400
+++ b/test/base/twilltestcase.py Tue May 17 15:29:02 2011 -0500
@@ -11,6 +11,7 @@
from elementtree import ElementTree
from galaxy.web import security
from galaxy.web.framework.helpers import iff
+from base.asserts import verify_assertions
buffer = StringIO.StringIO()
@@ -635,7 +636,7 @@
elem = elems[0]
self.assertTrue( hid )
self._assert_dataset_state( elem, 'ok' )
- if self.is_zipped( filename ):
+ if filename is not None and self.is_zipped( filename ):
errmsg = 'History item %s is a zip archive which includes invalid files:\n' % hid
zip_file = zipfile.ZipFile( filename, "r" )
name = zip_file.namelist()[0]
@@ -647,50 +648,59 @@
if ext != test_ext:
raise AssertionError( errmsg )
else:
- local_name = self.get_filename( filename )
- temp_name = self.makeTfname(fname = filename)
self.home()
self.visit_page( "display?hid=" + hid )
data = self.last_page()
- file( temp_name, 'wb' ).write(data)
- if self.keepOutdir > '':
- ofn = os.path.join(self.keepOutdir,os.path.basename(local_name))
- shutil.copy(temp_name,ofn)
- log.debug('## GALAXY_TEST_SAVE=%s. saved %s' % (self.keepOutdir,ofn))
- try:
- # have to nest try-except in try-finally to handle 2.4
+ assert_list = attributes["assert_list"]
+ if assert_list is not None:
try:
- if attributes is None:
- attributes = {}
- compare = attributes.get( 'compare', 'diff' )
- if attributes.get( 'ftype', None ) == 'bam':
- local_fh, temp_name = self._bam_to_sam( local_name, temp_name )
- local_name = local_fh.name
- extra_files = attributes.get( 'extra_files', None )
- if compare == 'diff':
- self.files_diff( local_name, temp_name, attributes=attributes )
- elif compare == 're_match':
- self.files_re_match( local_name, temp_name, attributes=attributes )
- elif compare == 're_match_multiline':
- self.files_re_match_multiline( local_name, temp_name, attributes=attributes )
- elif compare == 'sim_size':
- delta = attributes.get('delta','100')
- s1 = len(data)
- s2 = os.path.getsize(local_name)
- if abs(s1-s2) > int(delta):
- raise Exception, 'Files %s=%db but %s=%db - compare (delta=%s) failed' % (temp_name,s1,local_name,s2,delta)
- elif compare == "contains":
- self.files_contains( local_name, temp_name, attributes=attributes )
- else:
- raise Exception, 'Unimplemented Compare type: %s' % compare
- if extra_files:
- self.verify_extra_files_content( extra_files, elem.get( 'id' ) )
+ verify_assertions(data, assert_list)
except AssertionError, err:
- errmsg = 'History item %s different than expected, difference (using %s):\n' % ( hid, compare )
+ errmsg = 'History item %s different than expected\n' % (hid)
errmsg += str( err )
raise AssertionError( errmsg )
- finally:
- os.remove( temp_name )
+ if filename is not None:
+ local_name = self.get_filename( filename )
+ temp_name = self.makeTfname(fname = filename)
+ file( temp_name, 'wb' ).write(data)
+ if self.keepOutdir > '':
+ ofn = os.path.join(self.keepOutdir,os.path.basename(local_name))
+ shutil.copy(temp_name,ofn)
+ log.debug('## GALAXY_TEST_SAVE=%s. saved %s' % (self.keepOutdir,ofn))
+ try:
+ # have to nest try-except in try-finally to handle 2.4
+ try:
+ if attributes is None:
+ attributes = {}
+ compare = attributes.get( 'compare', 'diff' )
+ if attributes.get( 'ftype', None ) == 'bam':
+ local_fh, temp_name = self._bam_to_sam( local_name, temp_name )
+ local_name = local_fh.name
+ extra_files = attributes.get( 'extra_files', None )
+ if compare == 'diff':
+ self.files_diff( local_name, temp_name, attributes=attributes )
+ elif compare == 're_match':
+ self.files_re_match( local_name, temp_name, attributes=attributes )
+ elif compare == 're_match_multiline':
+ self.files_re_match_multiline( local_name, temp_name, attributes=attributes )
+ elif compare == 'sim_size':
+ delta = attributes.get('delta','100')
+ s1 = len(data)
+ s2 = os.path.getsize(local_name)
+ if abs(s1-s2) > int(delta):
+ raise Exception, 'Files %s=%db but %s=%db - compare (delta=%s) failed' % (temp_name,s1,local_name,s2,delta)
+ elif compare == "contains":
+ self.files_contains( local_name, temp_name, attributes=attributes )
+ else:
+ raise Exception, 'Unimplemented Compare type: %s' % compare
+ if extra_files:
+ self.verify_extra_files_content( extra_files, elem.get( 'id' ) )
+ except AssertionError, err:
+ errmsg = 'History item %s different than expected, difference (using %s):\n' % ( hid, compare )
+ errmsg += str( err )
+ raise AssertionError( errmsg )
+ finally:
+ os.remove( temp_name )
def _bam_to_sam( self, local_name, temp_name ):
temp_local = tempfile.NamedTemporaryFile( suffix='.sam', prefix='local_bam_converted_to_sam_' )
http://bitbucket.org/galaxy/galaxy-central/changeset/4b922a226f58/
changeset: 4b922a226f58
user: jmchilton
date: 2011-05-17 22:34:22
summary: $ hg diff lib/galaxy/web/buildapp.py
affected #: 2 files (263 bytes)
--- a/lib/galaxy/web/buildapp.py Tue May 17 15:29:02 2011 -0500
+++ b/lib/galaxy/web/buildapp.py Tue May 17 15:34:22 2011 -0500
@@ -94,6 +94,8 @@
webapp.add_route( '/async/:tool_id/:data_id/:data_secret', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='root', action='index' )
+ # allow for subdirectories in extra_files_path
+ webapp.add_route( '/datasets/:dataset_id/display/{filename:.+?}', controller='dataset', action='display', dataset_id=None, filename=None)
webapp.add_route( '/datasets/:dataset_id/:action/:filename', controller='dataset', action='index', dataset_id=None, filename=None)
webapp.add_route( '/display_application/:dataset_id/:app_name/:link_name/:user_id/:app_action/:action_param', controller='dataset', action='display_application', dataset_id=None, user_id=None, app_name = None, link_name = None, app_action = None, action_param = None )
webapp.add_route( '/u/:username/d/:slug', controller='dataset', action='display_by_username_and_slug' )
--- a/lib/galaxy/web/controllers/dataset.py Tue May 17 15:29:02 2011 -0500
+++ b/lib/galaxy/web/controllers/dataset.py Tue May 17 15:34:22 2011 -0500
@@ -267,17 +267,18 @@
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'
- flist = glob.glob(os.path.join(efp,'*.*')) # glob returns full paths
- for fpath in flist:
- efp,fname = os.path.split(fpath)
- try:
- archive.add( fpath,fname )
- except IOError:
- error = True
- log.exception( "Unable to add %s to temporary library download archive" % fname)
- msg = "Unable to create archive for download, please report this error"
- messagetype = 'error'
- continue
+ 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()
http://bitbucket.org/galaxy/galaxy-central/changeset/b8292228e13b/
changeset: b8292228e13b
user: jmchilton
date: 2011-05-19 22:42:25
summary: Added API for assigning roles to a data library.
affected #: 2 files (2.3 KB)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/web/api/permissions.py Thu May 19 15:42:25 2011 -0500
@@ -0,0 +1,51 @@
+"""
+API operations on the permissions of a library.
+"""
+import logging, os, string, shutil, urllib, re, socket
+from cgi import escape, FieldStorage
+from galaxy import util, datatypes, jobs, web, util
+from galaxy.web.base.controller import *
+from galaxy.util.sanitize_html import sanitize_html
+from galaxy.model.orm import *
+
+log = logging.getLogger( __name__ )
+
+class PermissionsController( BaseController ):
+
+ # Method not ideally named
+ @web.expose_api
+ def create( self, trans, library_id, payload, **kwd ):
+ """
+ POST /api/libraries/{encoded_library_id}/permissions
+ Updates the library permissions.
+ """
+ if not trans.user_is_admin():
+ trans.response.status = 403
+ return "You are not authorized to update library permissions."
+
+ params = util.Params( payload )
+ try:
+ decoded_library_id = trans.security.decode_id( library_id )
+ except TypeError:
+ trans.response.status = 400
+ return "Malformed library id ( %s ) specified, unable to decode." % str( library_id )
+
+ try:
+ library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
+ except:
+ library = None
+
+ permissions = {}
+ for k, v in trans.app.model.Library.permitted_actions.items():
+ role_params = params.get( k + '_in', [] )
+ in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in util.listify( role_params ) ]
+ permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
+ trans.app.security_agent.set_all_library_permissions( library, permissions )
+ trans.sa_session.refresh( library )
+ # Copy the permissions to the root folder
+ trans.app.security_agent.copy_library_permissions( library, library.root_folder )
+ message = "Permissions updated for library '%s'." % library.name
+
+ item = library.get_api_value( view='element' )
+ return item
+
--- a/lib/galaxy/web/buildapp.py Tue May 17 15:34:22 2011 -0500
+++ b/lib/galaxy/web/buildapp.py Thu May 19 15:42:25 2011 -0500
@@ -110,6 +110,10 @@
'contents',
path_prefix='/api/libraries/:library_id',
parent_resources=dict( member_name='library', collection_name='libraries' ) )
+ webapp.api_mapper.resource( 'permission',
+ 'permissions',
+ path_prefix='/api/libraries/:library_id',
+ parent_resources=dict( member_name='library', collection_name='libraries' ) )
webapp.api_mapper.resource( 'library', 'libraries', path_prefix='/api' )
webapp.api_mapper.resource( 'sample', 'samples', path_prefix='/api' )
webapp.api_mapper.resource( 'request', 'requests', path_prefix='/api' )
http://bitbucket.org/galaxy/galaxy-central/changeset/e9c02513efcc/
changeset: e9c02513efcc
user: jmchilton
date: 2011-07-25 20:13:17
summary: Merged latest galaxy-central changes.
affected #: 346 files (1.2 MB)
Diff too large to display.
http://bitbucket.org/galaxy/galaxy-central/changeset/87b627323347/
changeset: 87b627323347
user: jmchilton
date: 2011-08-31 18:08:30
summary: Merged latest galaxy-central.
affected #: 244 files (4.0 MB)
Diff too large to display.
http://bitbucket.org/galaxy/galaxy-central/changeset/9e77d9f39ff9/
changeset: 9e77d9f39ff9
user: jmchilton
date: 2011-08-31 18:31:23
summary: Small whitespace fix for bug introduced by last merge.
affected #: 1 file (1 byte)
--- a/test/base/twilltestcase.py Wed Aug 31 11:08:30 2011 -0500
+++ b/test/base/twilltestcase.py Wed Aug 31 11:31:23 2011 -0500
@@ -691,7 +691,7 @@
delta = attributes.get('delta','100')
s1 = len(data)
s2 = os.path.getsize(local_name)
- if abs(s1-s2) > int(delta):
+ if abs(s1-s2) > int(delta):
raise Exception, 'Files %s=%db but %s=%db - compare (delta=%s) failed' % (temp_name,s1,local_name,s2,delta)
elif compare == "contains":
self.files_contains( local_name, temp_name, attributes=attributes )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/55f8f2d8ac18/
changeset: 55f8f2d8ac18
user: dan
date: 2011-08-31 22:50:58
summary: Add samtools rmdup tool.
affected #: 4 files (105 bytes)
--- a/tool_conf.xml.main Wed Aug 31 11:44:52 2011 -0400
+++ b/tool_conf.xml.main Wed Aug 31 16:50:58 2011 -0400
@@ -382,6 +382,7 @@
<tool file="samtools/pileup_parser.xml" /><tool file="samtools/pileup_interval.xml" /><tool file="samtools/samtools_flagstat.xml" />
+ <tool file="samtools/samtools_rmdup.xml" /></section><section name="NGS: Indel Analysis" id="indel_analysis"><tool file="indels/sam_indel_filter.xml" />
--- a/tool_conf.xml.sample Wed Aug 31 11:44:52 2011 -0400
+++ b/tool_conf.xml.sample Wed Aug 31 16:50:58 2011 -0400
@@ -352,8 +352,9 @@
<tool file="samtools/pileup_parser.xml" /><tool file="samtools/pileup_interval.xml" /><tool file="samtools/samtools_flagstat.xml" />
+ <tool file="samtools/samtools_rmdup.xml" /></section>
- <section name="NGS: GATK Tools" id="gatk">
+ <section name="NGS: GATK Tools (beta)" id="gatk"><label text="Realignment" id="gatk_realignment" /><tool file="gatk/realigner_target_creator.xml" /><tool file="gatk/indel_realigner.xml" />
--- a/tools/samtools/samtools_flagstat.xml Wed Aug 31 11:44:52 2011 -0400
+++ b/tools/samtools/samtools_flagstat.xml Wed Aug 31 16:50:58 2011 -0400
@@ -3,7 +3,7 @@
<requirement type="package">samtools</requirement></requirements><description>provides simple stats on BAM files</description>
- <command>samtools flagstat $input1 > $output1
+ <command>samtools flagstat "$input1" > "$output1"
</command><inputs><param name="input1" type="data" format="bam" label="BAM File to Convert" />
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Trackster: add mode parameter to draw_tile and use to support better overview drawing.
by Bitbucket 31 Aug '11
by Bitbucket 31 Aug '11
31 Aug '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/52e6f9a13e34/
changeset: 52e6f9a13e34
user: jgoecks
date: 2011-08-31 17:44:52
summary: Trackster: add mode parameter to draw_tile and use to support better overview drawing.
affected #: 1 file (38 bytes)
--- a/static/scripts/trackster.js Tue Aug 30 16:56:52 2011 -0400
+++ b/static/scripts/trackster.js Wed Aug 31 11:44:52 2011 -0400
@@ -2240,7 +2240,7 @@
// Draw tile if necessary.
if (!tile) {
- tile = track.draw_tile(overview_data, resolution, 0, w_scale);
+ tile = track.draw_tile(overview_data, "Auto", resolution, 0, w_scale);
track.tile_cache.set(key, tile);
}
@@ -2395,7 +2395,7 @@
// If we can draw now, do so
if ( can_draw_now ) {
extend( tile_data, more_tile_data );
- var tile = track.draw_tile(tile_data, resolution, tile_index, w_scale, seq_data);
+ var tile = track.draw_tile(tile_data, track.mode, resolution, tile_index, w_scale, seq_data);
track.tile_cache.set(key, tile);
// Don't show if no tile
if (tile !== undefined) {
@@ -2558,7 +2558,7 @@
/**
* Draw ReferenceTrack tile.
*/
- draw_tile: function(seq, resolution, tile_index, w_scale) {
+ draw_tile: function(seq, mode, resolution, tile_index, w_scale) {
var track = this,
tile_length = DENSITY * resolution;
@@ -2696,7 +2696,7 @@
/**
* Draw LineTrack tile.
*/
- draw_tile: function(result, resolution, tile_index, w_scale) {
+ draw_tile: function(result, mode, resolution, tile_index, w_scale) {
if (this.vertical_range === undefined) {
return;
}
@@ -2713,7 +2713,7 @@
// Paint line onto full canvas
var ctx = canvas.getContext("2d");
- var painter = new painters.LinePainter(result.data, tile_low, tile_low + tile_length, this.prefs, this.mode);
+ var painter = new painters.LinePainter(result.data, tile_low, tile_low + tile_length, this.prefs, mode);
painter.draw(ctx, width, height);
return new Tile(tile_index, resolution, canvas, result.data);
@@ -2968,18 +2968,18 @@
/**
* Draw FeatureTrack tile.
* @param result result from server
+ * @param mode mode to draw in
* @param resolution view resolution
* @param tile_index index of tile to be drawn
* @param w_scale base pairs per pixel
* @param ref_seq reference sequence data
*/
- draw_tile: function(result, resolution, tile_index, w_scale, ref_seq) {
+ draw_tile: function(result, mode, resolution, tile_index, w_scale, ref_seq) {
var track = this,
tile_low = tile_index * DENSITY * resolution,
tile_high = (tile_index + 1) * DENSITY * resolution,
tile_span = tile_high - tile_low,
width = Math.ceil(tile_span * w_scale),
- mode = this.mode,
min_height = 25,
left_offset = this.left_offset,
slots,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/de06e2e6cc7f/
changeset: de06e2e6cc7f
user: dan
date: 2011-08-30 22:56:52
summary: Add basic VCF4.1 support.
affected #: 1 file (78 bytes)
--- a/lib/galaxy_utils/sequence/vcf.py Tue Aug 30 15:52:10 2011 -0400
+++ b/lib/galaxy_utils/sequence/vcf.py Tue Aug 30 16:56:52 2011 -0400
@@ -55,9 +55,12 @@
def __init__( self, vcf_line, metadata, sample_names ):
VariantCall33.__init__( self, vcf_line, metadata, sample_names)
+class VariantCall41( VariantCall40 ):
+ version = 'VCFv4.1'
+
#VCF Format version lookup dict
VCF_FORMATS = {}
-for format in [ VariantCall33, VariantCall40 ]:
+for format in [ VariantCall33, VariantCall40, VariantCall41 ]:
VCF_FORMATS[format.version] = format
class Reader( object ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/95c6e622b350/
changeset: 95c6e622b350
user: dan
date: 2011-08-30 21:52:10
summary: Update FIMO test datasets.
affected #: 5 files (174.7 KB)
Diff too large to display.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/5d2a2ac4710f/
changeset: 5d2a2ac4710f
user: dan
date: 2011-08-30 16:02:17
summary: Add SICER to tool_conf.xml.main.
affected #: 1 file (50 bytes)
--- a/tool_conf.xml.main Tue Aug 30 09:33:10 2011 -0400
+++ b/tool_conf.xml.main Tue Aug 30 10:02:17 2011 -0400
@@ -390,6 +390,7 @@
</section><section name="NGS: Peak Calling" id="peak_calling"><tool file="peak_calling/macs_wrapper.xml" />
+ <tool file="peak_calling/sicer_wrapper.xml" /><tool file="genetrack/genetrack_indexer.xml" /><tool file="genetrack/genetrack_peak_prediction.xml" /></section>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: dan: Update for wavelet variance tool contributed by Erika Kvikstad.
by Bitbucket 30 Aug '11
by Bitbucket 30 Aug '11
30 Aug '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/cddcdadea10d/
changeset: cddcdadea10d
user: dan
date: 2011-08-30 15:33:10
summary: Update for wavelet variance tool contributed by Erika Kvikstad.
affected #: 1 file (72 bytes)
--- a/tools/discreteWavelet/execute_dwt_var_perFeature.pl Mon Aug 29 14:42:04 2011 -0400
+++ b/tools/discreteWavelet/execute_dwt_var_perFeature.pl Tue Aug 30 09:33:10 2011 -0400
@@ -41,10 +41,10 @@
#library(\"wavethresh\");
#library(\"waveslim\");
# turn off diagnostics for de-bugging only, turn back on for functional tests on test
- require(\"Rwave\",quietly=TRUE,warn.conflicts = FALSE);
- require(\"wavethresh\",quietly=TRUE,warn.conflicts = FALSE);
- require(\"waveslim\",quietly=TRUE,warn.conflicts = FALSE);
- require(\"bitops\",quietly=TRUE,warn.conflicts = FALSE);
+ suppressMessages(require(\"Rwave\",quietly=TRUE,warn.conflicts = FALSE));
+ suppressMessages(require(\"wavethresh\",quietly=TRUE,warn.conflicts = FALSE));
+ suppressMessages(require(\"waveslim\",quietly=TRUE,warn.conflicts = FALSE));
+ suppressMessages(require(\"bitops\",quietly=TRUE,warn.conflicts = FALSE));
# to determine if data is properly formatted 2^N observations
is.power2<- function(x){x && !(bitAnd(x,x - 1));}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

29 Aug '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/949e4f5fa03a/
changeset: 949e4f5fa03a
user: natefoo
date: 2011-08-29 20:42:04
summary: Missing import in library_contents.py
affected #: 2 files (77 bytes)
--- a/lib/galaxy/web/api/library_contents.py Mon Aug 29 11:29:31 2011 -0400
+++ b/lib/galaxy/web/api/library_contents.py Mon Aug 29 14:42:04 2011 -0400
@@ -7,6 +7,7 @@
from galaxy.web.base.controller import *
from galaxy.util.sanitize_html import sanitize_html
from galaxy.model.orm import *
+from galaxy.web.api.util import *
log = logging.getLogger( __name__ )
--- a/scripts/api/common.py Mon Aug 29 11:29:31 2011 -0400
+++ b/scripts/api/common.py Mon Aug 29 14:42:04 2011 -0400
@@ -88,6 +88,8 @@
print '------------------'
for k, v in r.items():
print '%s: %s' % ( k, v )
+ elif type( r ) == str:
+ print r
else:
print 'response is unknown type: %s' % type( r )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Add a guid to tool shed repository tool metadata and add some fixes for previewing tool shed repository tools.
by Bitbucket 29 Aug '11
by Bitbucket 29 Aug '11
29 Aug '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/e08716dfa2d5/
changeset: e08716dfa2d5
user: greg
date: 2011-08-29 17:29:31
summary: Add a guid to tool shed repository tool metadata and add some fixes for previewing tool shed repository tools.
affected #: 5 files (1.6 KB)
--- a/lib/galaxy/webapps/community/app.py Mon Aug 29 11:22:54 2011 -0400
+++ b/lib/galaxy/webapps/community/app.py Mon Aug 29 11:29:31 2011 -0400
@@ -13,6 +13,8 @@
self.config = config.Configuration( **kwargs )
self.config.check()
config.configure_logging( self.config )
+ # Set up datatypes registry
+ self.datatypes_registry = galaxy.datatypes.registry.Registry( self.config.root, self.config.datatypes_config )
# Determine the database url
if self.config.database_connection:
db_url = self.config.database_connection
--- a/lib/galaxy/webapps/community/config.py Mon Aug 29 11:22:54 2011 -0400
+++ b/lib/galaxy/webapps/community/config.py Mon Aug 29 11:29:31 2011 -0400
@@ -39,11 +39,21 @@
self.file_path = resolve_path( kwargs.get( "file_path", "database/files" ), self.root )
self.new_file_path = resolve_path( kwargs.get( "new_file_path", "database/tmp" ), self.root )
self.cookie_path = kwargs.get( "cookie_path", "/" )
+ self.datatypes_config = kwargs.get( 'datatypes_config_file', 'datatypes_conf.xml' )
self.test_conf = resolve_path( kwargs.get( "test_conf", "" ), self.root )
self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" )
+ # Tool stuff
self.tool_secret = kwargs.get( "tool_secret", "" )
self.tool_data_path = resolve_path( kwargs.get( "tool_data_path", "tool-data" ), os.getcwd() )
self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root )
+ self.ftp_upload_dir = kwargs.get( 'ftp_upload_dir', None )
+ # Location for dependencies
+ if 'tool_dependency_dir' in kwargs:
+ self.tool_dependency_dir = resolve_path( kwargs.get( "tool_dependency_dir" ), self.root )
+ self.use_tool_dependencies = True
+ else:
+ self.tool_dependency_dir = None
+ self.use_tool_dependencies = False
self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) )
self.remote_user_maildomain = kwargs.get( "remote_user_maildomain", None )
self.remote_user_logout_href = kwargs.get( "remote_user_logout_href", None )
--- a/lib/galaxy/webapps/community/controllers/common.py Mon Aug 29 11:22:54 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/common.py Mon Aug 29 11:29:31 2011 -0400
@@ -145,11 +145,22 @@
# The received metadata_dict includes no metadata for workflows, so a new repository_metadata table
# record is not needed.
return False
+def generate_tool_guid( trans, repository, tool ):
+ """
+ Generate a guid for the received tool. The form of the guid is
+ <tool shed host>/repos/<tool shed username>/<tool shed repo name>/<tool id>/<tool version>
+ """
+ return '%s/repos/%s/%s/%s/%s' % ( trans.request.host,
+ repository.user.username,
+ repository.name,
+ tool.id,
+ tool.version )
def generate_tool_metadata( trans, id, changeset_revision, root, name, tool, metadata_dict ):
"""
Update the received metadata_dict with changes that have been
applied to the received tool.
"""
+ repository = get_repository( trans, id )
tool_requirements = []
for tr in tool.requirements:
requirement_dict = dict( name=tr.name,
@@ -165,6 +176,7 @@
outputs=ttb.outputs )
tool_tests.append( test_dict )
tool_dict = dict( id=tool.id,
+ guid = generate_tool_guid( trans, repository, tool ),
name=tool.name,
version=tool.version,
description=tool.description,
--- a/templates/webapps/community/repository/tool_form.mako Mon Aug 29 11:22:54 2011 -0400
+++ b/templates/webapps/community/repository/tool_form.mako Mon Aug 29 11:29:31 2011 -0400
@@ -4,7 +4,7 @@
<%
from galaxy.util.expressions import ExpressionContext
from galaxy import util
- from galaxy.tools.parameters.basic import DataToolParameter, ColumnListParameter, SelectToolParameter
+ from galaxy.tools.parameters.basic import DataToolParameter, ColumnListParameter, GenomeBuildParameter, SelectToolParameter
from galaxy.web.form_builder import SelectField
is_admin = trans.user_is_admin()
@@ -60,8 +60,8 @@
%endif
%elif input.type == "upload_dataset":
%if input.get_datatype( trans, other_values ).composite_type is None:
- # Have non-composite upload appear as before
- ${do_inputs( input.inputs, tool_state[input.name][0], prefix + input.name + "_" + str( 0 ) + "|", other_values )}
+ ## Have non-composite upload appear as before
+ ${do_inputs( input.inputs, 'files', prefix + input.name + "_" + str( 0 ) + "|", other_values )}
%else:
<div class="repeat-group"><div class="form-title-row">
@@ -82,7 +82,7 @@
<%def name="row_for_param( prefix, param, parent_state, other_values )"><%
label = param.get_label()
- if isinstance( param, DataToolParameter ) or isinstance( param, ColumnListParameter ):
+ if isinstance( param, DataToolParameter ) or isinstance( param, ColumnListParameter ) or isinstance( param, GenomeBuildParameter ):
field = SelectField( param.name )
field.add_option( param.name, param.name )
field_html = field.get_html()
--- a/templates/webapps/community/repository/view_tool_metadata.mako Mon Aug 29 11:22:54 2011 -0400
+++ b/templates/webapps/community/repository/view_tool_metadata.mako Mon Aug 29 11:29:31 2011 -0400
@@ -137,6 +137,13 @@
<div style="clear: both"></div></div>
%endif
+ %if 'guid' in metadata:
+ <div class="form-row">
+ <label>Guid:</label>
+ ${metadata[ 'guid' ]}
+ <div style="clear: both"></div>
+ </div>
+ %endif
%if 'version' in metadata:
<div class="form-row"><label>Version:</label>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: dan: Add wavelet variance tool contributed by Erika Kvikstad.
by Bitbucket 29 Aug '11
by Bitbucket 29 Aug '11
29 Aug '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c8d224f51d7e/
changeset: c8d224f51d7e
user: dan
date: 2011-08-29 17:22:54
summary: Add wavelet variance tool contributed by Erika Kvikstad.
affected #: 6 files (80 bytes)
--- a/tool_conf.xml.sample Mon Aug 29 10:57:08 2011 -0400
+++ b/tool_conf.xml.sample Mon Aug 29 11:22:54 2011 -0400
@@ -146,15 +146,16 @@
<label text="GFF" id="gff" /><tool file="stats/count_gff_features.xml" /></section>
- <!--
- Keep this section commented until all of the tools have functional tests
<section name="Wavelet Analysis" id="dwt">
+ <tool file="discreteWavelet/execute_dwt_var_perFeature.xml" />
+ <!--
+ Keep this section/tools commented until all of the tools have functional tests
<tool file="discreteWavelet/execute_dwt_IvC_all.xml" /><tool file="discreteWavelet/execute_dwt_cor_aVa_perClass.xml" /><tool file="discreteWavelet/execute_dwt_cor_aVb_all.xml" /><tool file="discreteWavelet/execute_dwt_var_perClass.xml" />
+ --></section>
- --><section name="Graph/Display Data" id="plots"><tool file="plotting/histogram2.xml" /><tool file="plotting/scatterplot.xml" />
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: Properly handle error conditions in library_common.upload_dataset when uploading via the API.
by Bitbucket 29 Aug '11
by Bitbucket 29 Aug '11
29 Aug '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/832538ba7258/
changeset: 832538ba7258
user: natefoo
date: 2011-08-29 16:57:08
summary: Properly handle error conditions in library_common.upload_dataset when uploading via the API.
affected #: 1 file (152 bytes)
--- a/lib/galaxy/web/controllers/library_common.py Mon Aug 29 09:32:26 2011 -0400
+++ b/lib/galaxy/web/controllers/library_common.py Mon Aug 29 10:57:08 2011 -0400
@@ -852,6 +852,8 @@
# created_outputs_dict can be a string only if cntrller == 'api'
if type( created_outputs_dict ) == str:
return 400, created_outputs_dict
+ elif type( created_outputs_dict ) == tuple:
+ return created_outputs_dict[0], created_outputs_dict[1]
return 200, created_outputs_dict
total_added = len( created_outputs_dict.keys() )
ldda_id_list = [ str( v.id ) for k, v in created_outputs_dict.items() ]
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0