galaxy-commits
Threads by month
- ----- 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
October 2011
- 1 participants
- 109 discussions
10 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/540ff06d44b4/
changeset: 540ff06d44b4
user: greg
date: 2011-10-10 21:51:43
summary: Miscellaneous enhancements for the tool shed:
1. Enable the same behavior for the config settings named "tool_config_file" and "tool_config_files" since this config setting can now be a comma-separated list of file names.
2. Display an error message if a user attempts to install a Galaxy tool shed repository but they do not have a shed tool config file named in the "tool_config_file" setting in universe_wsgi.ini.
3. If tool search using whoosh is enabled, re-index the tool box when new tools are installed from a tool shed.
affected #: 3 files (-1 bytes)
--- a/lib/galaxy/config.py Mon Oct 10 15:45:31 2011 -0400
+++ b/lib/galaxy/config.py Mon Oct 10 15:51:43 2011 -0400
@@ -52,7 +52,13 @@
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_configs = [ resolve_path( p, self.root ) for p in listify( kwargs.get( 'tool_config_file', 'tool_conf.xml' ) ) ]
+ if 'tool_config_file' in kwargs:
+ tcf = kwargs[ 'tool_config_file' ]
+ elif 'tool_config_files' in kwargs:
+ tcf = kwargs[ 'tool_config_files' ]
+ else:
+ tcf = 'tool_conf.xml'
+ self.tool_configs = [ resolve_path( p, self.root ) for p in listify( tcf ) ]
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!" )
--- a/lib/galaxy/web/controllers/admin.py Mon Oct 10 15:45:31 2011 -0400
+++ b/lib/galaxy/web/controllers/admin.py Mon Oct 10 15:51:43 2011 -0400
@@ -2,6 +2,7 @@
from galaxy import model
from galaxy.model.orm import *
from galaxy.web.framework.helpers import time_ago, iff, grids
+from galaxy.tools.search import ToolBoxSearch
import logging
log = logging.getLogger( __name__ )
@@ -693,6 +694,15 @@
@web.expose
@web.require_admin
def install_tool_shed_repository( self, trans, **kwd ):
+ if not trans.app.toolbox.shed_tool_confs:
+ message = 'The <b>tool_config_file</b> setting in <b>universe_wsgi.ini</b> must include at least one shed tool configuration file name with a '
+ message += '<b><toolbox></b> tag that includes a <b>tool_path</b> attribute value which is a directory relative to the Galaxy installation '
+ message += 'directory in order to automatically install tools from a Galaxy tool shed (e.g., the file name <b>shed_tool_conf.xml</b> whose '
+ message += '<b><toolbox></b> tag is <b><toolbox tool_path="../shed_tools"></b>).<p/>See the '
+ message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed#Automatic_installation_of_Galaxy_tool…" '
+ message += 'target=_blank">Automatic installation of Galaxy tool shed repository tools into a local Galaxy instance</a> section of the '
+ message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed" target="_blank">Galaxy tool shed wiki</a> for all of the details.'
+ return trans.show_error_message( message )
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
@@ -782,6 +792,9 @@
pass
# Append the new section to the shed_tool_config file.
self.__add_shed_tool_conf_entry( trans, shed_tool_conf, new_tool_section )
+ if trans.app.toolbox_search.enabled:
+ # If search support for tools is enabled, index the new installed tools.
+ trans.app.toolbox_search = ToolBoxSearch( trans.app.toolbox )
message = 'Revision <b>%s</b> of repository <b>%s</b> has been installed in tool panel section <b>%s</b>.' % \
( changeset_revision, name, tool_section.name )
return trans.show_ok_message( message )
--- a/universe_wsgi.ini.sample Mon Oct 10 15:45:31 2011 -0400
+++ b/universe_wsgi.ini.sample Mon Oct 10 15:51:43 2011 -0400
@@ -124,8 +124,8 @@
#new_file_path = database/tmp
# 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
+# Tools can be locally developed or installed from Galaxy tool sheds.
+#tool_config_file = tool_conf.xml,shed_tool_conf.xml
# 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.
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: Make purged histories visible in the history list grid, make any history viewable from the grid.
by Bitbucket 10 Oct '11
by Bitbucket 10 Oct '11
10 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/3c1f3268512d/
changeset: 3c1f3268512d
user: natefoo
date: 2011-10-10 21:45:31
summary: Make purged histories visible in the history list grid, make any history viewable from the grid.
affected #: 3 files (-1 bytes)
--- a/lib/galaxy/web/controllers/history.py Mon Oct 10 09:39:20 2011 -0400
+++ b/lib/galaxy/web/controllers/history.py Mon Oct 10 15:45:31 2011 -0400
@@ -59,6 +59,21 @@
if not history.deleted:
link = dict( operation="Switch", id=history.id, use_panels=grid.use_panels )
return link
+ class DeletedColumn( grids.DeletedColumn ):
+ def get_value( self, trans, grid, history ):
+ if history == trans.history:
+ return "<strong>current history</strong>"
+ if history.purged:
+ return "deleted permanently"
+ elif history.deleted:
+ return "deleted"
+ return ""
+ def sort( self, trans, query, ascending, column_name=None ):
+ if ascending:
+ query = query.order_by( self.model_class.table.c.purged.asc(), self.model_class.table.c.update_time.desc() )
+ else:
+ query = query.order_by( self.model_class.table.c.purged.desc(), self.model_class.table.c.update_time.desc() )
+ return query
# Grid definition
title = "Saved Histories"
@@ -74,8 +89,7 @@
grids.GridColumn( "Size on Disk", key="get_disk_size_bytes", format=nice_size, sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
- # Columns that are valid for filtering but are not visible.
- grids.DeletedColumn( "Status", key="deleted", visible=False, filterable="advanced" )
+ DeletedColumn( "Status", key="deleted", filterable="advanced" )
]
columns.append(
grids.MulticolFilterColumn(
@@ -85,11 +99,12 @@
)
operations = [
grids.GridOperation( "Switch", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
+ grids.GridOperation( "View", allow_multiple=False ),
grids.GridOperation( "Share or Publish", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
grids.GridOperation( "Rename", condition=( lambda item: not item.deleted ), async_compatible=False ),
grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), async_compatible=True ),
- grids.GridOperation( "Delete Permanently", confirm="History contents will be removed from disk, this cannot be undone. Continue?", async_compatible=True ),
- grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ), async_compatible=True ),
+ grids.GridOperation( "Delete Permanently", condition=( lambda item: not item.purged ), confirm="History contents will be removed from disk, this cannot be undone. Continue?", async_compatible=True ),
+ grids.GridOperation( "Undelete", condition=( lambda item: item.deleted and not item.purged ), async_compatible=True ),
]
standard_filters = [
grids.GridColumnFilter( "Active", args=dict( deleted=False ) ),
@@ -104,7 +119,7 @@
def get_current_item( self, trans, **kwargs ):
return trans.get_history()
def apply_query_filter( self, trans, query, **kwargs ):
- return query.filter_by( user=trans.user, purged=False, importing=False )
+ return query.filter_by( user=trans.user, importing=False )
class SharedHistoryListGrid( grids.Grid ):
# Custom column types
@@ -212,6 +227,15 @@
if 'name' in kwargs:
del kwargs['name'] # Remove ajax name param that rename method uses
return self.rename( trans, **kwargs )
+ if operation == "view":
+ history = self.get_history( trans, kwargs.get( 'id', None ) )
+ if history:
+ return trans.response.send_redirect( url_for( controller='history',
+ action='view',
+ id=kwargs['id'],
+ show_deleted=history.deleted,
+ use_panels=False ) )
+ #return self.view( trans, id=kwargs['id'], show_deleted=history.deleted, use_panels=False )
history_ids = util.listify( kwargs.get( 'id', [] ) )
# Display no message by default
status, message = None, None
@@ -793,7 +817,7 @@
""" % ( web.url_for( id=id, confirm=True, referer=trans.request.referer ), referer_message ), use_panels=True )
@web.expose
- def view( self, trans, id=None, show_deleted=False ):
+ def view( self, trans, id=None, show_deleted=False, use_panels=True ):
"""View a history. If a history is importable, then it is viewable by any user."""
# Get history to view.
if not id:
@@ -808,10 +832,15 @@
# View history.
show_deleted = util.string_as_bool( show_deleted )
datasets = self.get_history_datasets( trans, history_to_view, show_deleted=show_deleted )
+ try:
+ use_panels = util.string_as_bool( use_panels )
+ except:
+ pass # already a bool
return trans.stream_template_mako( "history/view.mako",
history = history_to_view,
datasets = datasets,
- show_deleted = show_deleted )
+ show_deleted = show_deleted,
+ use_panels = use_panels )
@web.expose
def display_by_username_and_slug( self, trans, username, slug ):
--- a/templates/display_common.mako Mon Oct 10 09:39:20 2011 -0400
+++ b/templates/display_common.mako Mon Oct 10 15:45:31 2011 -0400
@@ -138,7 +138,7 @@
%if history.slug and history.user.username:
<% return h.url_for( controller='/history', action='display_by_username_and_slug', username=history.user.username, slug=history.slug, qualified=qualify ) %>
%else:
- <% return h.url_for( controller='/history', action='view', id=trans.security.encode_id( history.id ), qualified=qualify ) %>
+ <% return h.url_for( controller='/history', action='view', id=trans.security.encode_id( history.id ), qualified=qualify, use_panels=context.get('use_panels', True) ) %>
%endif
</%def>
--- a/templates/history/view.mako Mon Oct 10 09:39:20 2011 -0400
+++ b/templates/history/view.mako Mon Oct 10 15:45:31 2011 -0400
@@ -1,8 +1,16 @@
-<%inherit file="/webapps/galaxy/base_panels.mako"/><%namespace file="/display_common.mako" import="get_history_link, get_controller_name" /><%namespace file="/root/history_common.mako" import="render_dataset" /><%namespace file="/tagging_common.mako" import="render_individual_tagging_element, render_community_tagging_element" />
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/galaxy/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
<%def name="javascripts()">
${parent.javascripts()}
${h.js( "galaxy.base", "jquery", "json2", "jstorage" )}
@@ -63,6 +71,10 @@
%></%def>
+<%def name="body()">
+ ${center_panel()}
+</%def>
+
<%def name="center_panel()">
## Get URL to other histories owned by user that owns this history.
<%
@@ -81,14 +93,16 @@
<div style="overflow: auto; height: 100%;">
## Render view of history.
<div id="top-links" class="historyLinks" style="padding: 0px 0px 5px 0px">
+ %if not history.purged:
<a href="${h.url_for( action='imp', id=trans.security.encode_id(history.id) )}">import and start using history</a> |
- <a href="${get_history_link( history )}">${_('refresh')}</a>
+ <a href="${get_history_link( history )}">${_('refresh')}</a> |
+ %endif
%if show_deleted:
- | <a href="${h.url_for( id=trans.security.encode_id(history.id), show_deleted=False )}">${_('hide deleted')}</a>
+ <a href="${h.url_for( id=trans.security.encode_id(history.id), show_deleted=False, use_panels=use_panels )}">${_('hide deleted')}</a> |
%else:
- | <a href="${h.url_for( id=trans.security.encode_id(history.id), show_deleted=True )}">${_('show deleted')}</a>
+ <a href="${h.url_for( id=trans.security.encode_id(history.id), show_deleted=True, use_panels=use_panels )}">${_('show deleted')}</a> |
%endif
- | <a href="#" class="toggle">collapse all</a>
+ <a href="#" class="toggle">collapse all</a></div><div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold; padding: 0px 0px 5px 0px">
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
3 new changesets in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/feee8fdcdaeb/
changeset: feee8fdcdaeb
user: John Duddy
date: 2011-08-18 23:16:03
summary: Allow 2 new optional parameters to workflow/run controller method:
history_id: an encoded history id to use. Will not permantently switch user's
current id
hide_fixed_params: Initially hides all workflow parameters that are not
"Set at Runtime" and all workflow steps that only contain them.
Intended to reduce clutter when launching "canned" workflows.
Also added configurable feature that governs how initial values are selected
from the history for workflow runtime input. When enabled, this feature
causes Galaxy to use each input only once until it has used them all. This
is for the paired-end scenario, to attempt to match inputs correctly by default.
affected #: 5 files (-1 bytes)
--- a/lib/galaxy/config.py Thu Aug 18 14:20:48 2011 -0400
+++ b/lib/galaxy/config.py Thu Aug 18 14:16:03 2011 -0700
@@ -46,6 +46,7 @@
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.enable_unique_workflow_defaults = string_as_bool ( kwargs.get ('enable_unique_workflow_defaults', False ) )
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) )
--- a/lib/galaxy/tools/parameters/basic.py Thu Aug 18 14:20:48 2011 -0400
+++ b/lib/galaxy/tools/parameters/basic.py Thu Aug 18 14:16:03 2011 -0700
@@ -75,6 +75,16 @@
"""
return None
+ def get_initial_value_from_history_prevent_repeats( self, trans, context, already_used ):
+ """
+ Get the starting value for the parameter, but if fetching from the history, try
+ to find a value that has not yet been used. already_used is a list of objects that
+ tools must manipulate (by adding to it) to store a memento that they can use to detect
+ if a value has already been chosen from the history. This is to support the capability to
+ choose each dataset once
+ """
+ return self.get_initial_value(trans, context);
+
def get_required_enctype( self ):
"""
If this parameter needs the form to have a specific encoding
@@ -1385,6 +1395,9 @@
return field
def get_initial_value( self, trans, context ):
+ return self.get_initial_value_from_history_prevent_repeats(trans, context, None);
+
+ def get_initial_value_from_history_prevent_repeats( self, trans, context, already_used ):
"""
NOTE: This is wasteful since dynamic options and dataset collection
happens twice (here and when generating HTML).
@@ -1397,7 +1410,7 @@
assert history is not None, "DataToolParameter requires a history"
if self.optional:
return None
- most_recent_dataset = [None]
+ most_recent_dataset = []
filter_value = None
if self.options:
try:
@@ -1423,15 +1436,19 @@
data = converted_dataset
if not is_valid or ( self.options and self._options_filter_attribute( data ) != filter_value ):
continue
- most_recent_dataset[0] = data
+ most_recent_dataset.append(data)
# Also collect children via association object
dataset_collector( data.children )
dataset_collector( history.datasets )
- most_recent_dataset = most_recent_dataset.pop()
- if most_recent_dataset is not None:
- return most_recent_dataset
- else:
- return ''
+ most_recent_dataset.reverse()
+ if already_used is not None:
+ for val in most_recent_dataset:
+ if val is not None and val not in already_used:
+ already_used.append(val)
+ return val
+ if len(most_recent_dataset) > 0:
+ return most_recent_dataset[0]
+ return ''
def from_html( self, value, trans, other_values={} ):
# Can't look at history in workflow mode, skip validation and such,
--- a/lib/galaxy/web/controllers/workflow.py Thu Aug 18 14:20:48 2011 -0400
+++ b/lib/galaxy/web/controllers/workflow.py Thu Aug 18 14:16:03 2011 -0700
@@ -1258,7 +1258,7 @@
## % ( workflow_name, web.url_for( action='editor', id=trans.security.encode_id(stored.id) ) ) )
@web.expose
- def run( self, trans, id, **kwargs ):
+ def run( self, trans, id, history_id=None, hide_fixed_params=False, **kwargs ):
stored = self.get_stored_workflow( trans, id, check_ownership=False )
user = trans.get_user()
if stored.user != user:
@@ -1279,163 +1279,185 @@
errors = {}
has_upgrade_messages = False
has_errors = False
- if kwargs:
- # If kwargs were provided, the states for each step should have
- # been POSTed
- # Get the kwarg keys for data inputs
- input_keys = filter(lambda a: a.endswith('|input'), kwargs)
- # Example: prefixed='2|input'
- # Check if one of them is a list
- multiple_input_key = None
- multiple_inputs = [None]
- for input_key in input_keys:
- if isinstance(kwargs[input_key], list):
- multiple_input_key = input_key
- multiple_inputs = kwargs[input_key]
- # List to gather values for the template
- invocations=[]
- for input_number, single_input in enumerate(multiple_inputs):
- # Example: single_input='1', single_input='2', etc...
- # 'Fix' the kwargs, to have only the input for this iteration
- if multiple_input_key:
- kwargs[multiple_input_key] = single_input
+ saved_history = None
+ if history_id is not None:
+ saved_history = trans.get_history();
+ try:
+ decoded_history_id = trans.security.decode_id( history_id )
+ history = trans.sa_session.query(trans.app.model.History).get(decoded_history_id)
+ if history.user != trans.user and not trans.user_is_admin():
+ if trans.sa_session.query(trans.app.model.HistoryUserShareAssociation).filter_by(user=trans.user, history=history).count() == 0:
+ error("History is not owned by or shared with current user")
+ trans.set_history(history)
+ except TypeError:
+ error("Malformed history id ( %s ) specified, unable to decode." % str( history_id ))
+ except:
+ error("That history does not exist.")
+ try: # use a try/finally block to restore the user's current history
+ if kwargs:
+ # If kwargs were provided, the states for each step should have
+ # been POSTed
+ # Get the kwarg keys for data inputs
+ input_keys = filter(lambda a: a.endswith('|input'), kwargs)
+ # Example: prefixed='2|input'
+ # Check if one of them is a list
+ multiple_input_key = None
+ multiple_inputs = [None]
+ for input_key in input_keys:
+ if isinstance(kwargs[input_key], list):
+ multiple_input_key = input_key
+ multiple_inputs = kwargs[input_key]
+ # List to gather values for the template
+ invocations=[]
+ for input_number, single_input in enumerate(multiple_inputs):
+ # Example: single_input='1', single_input='2', etc...
+ # 'Fix' the kwargs, to have only the input for this iteration
+ if multiple_input_key:
+ kwargs[multiple_input_key] = single_input
+ for step in workflow.steps:
+ step.upgrade_messages = {}
+ # Connections by input name
+ step.input_connections_by_name = \
+ dict( ( conn.input_name, conn ) for conn in step.input_connections )
+ # Extract just the arguments for this step by prefix
+ p = "%s|" % step.id
+ l = len(p)
+ step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
+ step_errors = None
+ if step.type == 'tool' or step.type is None:
+ module = module_factory.from_workflow_step( trans, step )
+ # Fix any missing parameters
+ step.upgrade_messages = module.check_and_update_state()
+ if step.upgrade_messages:
+ has_upgrade_messages = True
+ # Any connected input needs to have value DummyDataset (these
+ # are not persisted so we need to do it every time)
+ module.add_dummy_datasets( connections=step.input_connections )
+ # Get the tool
+ tool = module.tool
+ # Get the state
+ step.state = state = module.state
+ # Get old errors
+ old_errors = state.inputs.pop( "__errors__", {} )
+ # Update the state
+ step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
+ update_only=True, old_errors=old_errors )
+ else:
+ # Fix this for multiple inputs
+ module = step.module = module_factory.from_workflow_step( trans, step )
+ state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
+ step_errors = module.update_runtime_state( trans, state, step_args )
+ if step_errors:
+ errors[step.id] = state.inputs["__errors__"] = step_errors
+ if 'run_workflow' in kwargs and not errors:
+ new_history = None
+ if 'new_history' in kwargs:
+ if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
+ nh_name = kwargs['new_history_name']
+ else:
+ nh_name = "History from %s workflow" % workflow.name
+ if multiple_input_key:
+ nh_name = '%s %d' % (nh_name, input_number + 1)
+ new_history = trans.app.model.History( user=trans.user, name=nh_name )
+ trans.sa_session.add( new_history )
+ # Run each step, connecting outputs to inputs
+ workflow_invocation = model.WorkflowInvocation()
+ workflow_invocation.workflow = workflow
+ outputs = odict()
+ for i, step in enumerate( workflow.steps ):
+ # Execute module
+ job = None
+ if step.type == 'tool' or step.type is None:
+ tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ input_values = step.state.inputs
+ # Connect up
+ def callback( input, value, prefixed_name, prefixed_label ):
+ if isinstance( input, DataToolParameter ):
+ if prefixed_name in step.input_connections_by_name:
+ conn = step.input_connections_by_name[ prefixed_name ]
+ return outputs[ conn.output_step.id ][ conn.output_name ]
+ visit_input_values( tool.inputs, step.state.inputs, callback )
+ # Execute it
+ job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
+ outputs[ step.id ] = out_data
+ # Create new PJA associations with the created job, to be run on completion.
+ # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
+ # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
+ replacement_dict = {}
+ for k, v in kwargs.iteritems():
+ if k.startswith('wf_parm|'):
+ replacement_dict[k[8:]] = v
+ for pja in step.post_job_actions:
+ if pja.action_type in ActionBox.immediate_actions:
+ ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
+ else:
+ job.add_post_job_action(pja)
+ else:
+ job, out_data = step.module.execute( trans, step.state )
+ outputs[ step.id ] = out_data
+ # Record invocation
+ workflow_invocation_step = model.WorkflowInvocationStep()
+ workflow_invocation_step.workflow_invocation = workflow_invocation
+ workflow_invocation_step.workflow_step = step
+ workflow_invocation_step.job = job
+ # All jobs ran sucessfully, so we can save now
+ trans.sa_session.add( workflow_invocation )
+ invocations.append({'outputs': outputs,
+ 'new_history': new_history})
+ trans.sa_session.flush()
+ return trans.fill_template( "workflow/run_complete.mako",
+ workflow=stored,
+ invocations=invocations )
+ else:
+ # Prepare each step
+ missing_tools = []
for step in workflow.steps:
step.upgrade_messages = {}
- # Connections by input name
- step.input_connections_by_name = \
- dict( ( conn.input_name, conn ) for conn in step.input_connections )
- # Extract just the arguments for this step by prefix
- p = "%s|" % step.id
- l = len(p)
- step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
- step_errors = None
+ # Contruct modules
if step.type == 'tool' or step.type is None:
- module = module_factory.from_workflow_step( trans, step )
- # Fix any missing parameters
- step.upgrade_messages = module.check_and_update_state()
+ # Restore the tool state for the step
+ step.module = module_factory.from_workflow_step( trans, step )
+ if not step.module:
+ if step.tool_id not in missing_tools:
+ missing_tools.append(step.tool_id)
+ continue
+ step.upgrade_messages = step.module.check_and_update_state()
if step.upgrade_messages:
has_upgrade_messages = True
# Any connected input needs to have value DummyDataset (these
# are not persisted so we need to do it every time)
- module.add_dummy_datasets( connections=step.input_connections )
- # Get the tool
- tool = module.tool
- # Get the state
- step.state = state = module.state
- # Get old errors
- old_errors = state.inputs.pop( "__errors__", {} )
- # Update the state
- step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
- update_only=True, old_errors=old_errors )
+ step.module.add_dummy_datasets( connections=step.input_connections )
+ # Store state with the step
+ step.state = step.module.state
+ # Error dict
+ if step.tool_errors:
+ has_errors = True
+ errors[step.id] = step.tool_errors
else:
- # Fix this for multiple inputs
- module = step.module = module_factory.from_workflow_step( trans, step )
- state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
- step_errors = module.update_runtime_state( trans, state, step_args )
- if step_errors:
- errors[step.id] = state.inputs["__errors__"] = step_errors
- if 'run_workflow' in kwargs and not errors:
- new_history = None
- if 'new_history' in kwargs:
- if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
- nh_name = kwargs['new_history_name']
- else:
- nh_name = "History from %s workflow" % workflow.name
- if multiple_input_key:
- nh_name = '%s %d' % (nh_name, input_number + 1)
- new_history = trans.app.model.History( user=trans.user, name=nh_name )
- trans.sa_session.add( new_history )
- # Run each step, connecting outputs to inputs
- workflow_invocation = model.WorkflowInvocation()
- workflow_invocation.workflow = workflow
- outputs = odict()
- for i, step in enumerate( workflow.steps ):
- # Execute module
- job = None
- if step.type == 'tool' or step.type is None:
- tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
- input_values = step.state.inputs
- # Connect up
- def callback( input, value, prefixed_name, prefixed_label ):
- if isinstance( input, DataToolParameter ):
- if prefixed_name in step.input_connections_by_name:
- conn = step.input_connections_by_name[ prefixed_name ]
- return outputs[ conn.output_step.id ][ conn.output_name ]
- visit_input_values( tool.inputs, step.state.inputs, callback )
- # Execute it
- job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
- outputs[ step.id ] = out_data
- # Create new PJA associations with the created job, to be run on completion.
- # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
- # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
- replacement_dict = {}
- for k, v in kwargs.iteritems():
- if k.startswith('wf_parm|'):
- replacement_dict[k[8:]] = v
- for pja in step.post_job_actions:
- if pja.action_type in ActionBox.immediate_actions:
- ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
- else:
- job.add_post_job_action(pja)
- else:
- job, out_data = step.module.execute( trans, step.state )
- outputs[ step.id ] = out_data
- # Record invocation
- workflow_invocation_step = model.WorkflowInvocationStep()
- workflow_invocation_step.workflow_invocation = workflow_invocation
- workflow_invocation_step.workflow_step = step
- workflow_invocation_step.job = job
- # All jobs ran sucessfully, so we can save now
- trans.sa_session.add( workflow_invocation )
- invocations.append({'outputs': outputs,
- 'new_history': new_history})
- trans.sa_session.flush()
- return trans.fill_template( "workflow/run_complete.mako",
- workflow=stored,
- invocations=invocations )
- else:
- # Prepare each step
- missing_tools = []
- for step in workflow.steps:
- step.upgrade_messages = {}
- # Contruct modules
- if step.type == 'tool' or step.type is None:
- # Restore the tool state for the step
- step.module = module_factory.from_workflow_step( trans, step )
- if not step.module:
- if step.tool_id not in missing_tools:
- missing_tools.append(step.tool_id)
- continue
- step.upgrade_messages = step.module.check_and_update_state()
- if step.upgrade_messages:
- has_upgrade_messages = True
- # Any connected input needs to have value DummyDataset (these
- # are not persisted so we need to do it every time)
- step.module.add_dummy_datasets( connections=step.input_connections )
- # Store state with the step
- step.state = step.module.state
- # Error dict
- if step.tool_errors:
- has_errors = True
- errors[step.id] = step.tool_errors
- else:
- ## Non-tool specific stuff?
- step.module = module_factory.from_workflow_step( trans, step )
- step.state = step.module.get_runtime_state()
- # Connections by input name
- step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
- if missing_tools:
- stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
- return trans.fill_template("workflow/run.mako", steps=[], workflow=stored, missing_tools = missing_tools)
- # Render the form
- stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
- return trans.fill_template(
- "workflow/run.mako",
- steps=workflow.steps,
- workflow=stored,
- has_upgrade_messages=has_upgrade_messages,
- errors=errors,
- incoming=kwargs )
+ ## Non-tool specific stuff?
+ step.module = module_factory.from_workflow_step( trans, step )
+ step.state = step.module.get_runtime_state()
+ # Connections by input name
+ step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
+ if missing_tools:
+ stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
+ return trans.fill_template("workflow/run.mako", steps=[], workflow=stored, missing_tools = missing_tools)
+ # Render the form
+ stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
+ return trans.fill_template(
+ "workflow/run.mako",
+ steps=workflow.steps,
+ workflow=stored,
+ has_upgrade_messages=has_upgrade_messages,
+ errors=errors,
+ incoming=kwargs,
+ history_id=history_id,
+ hide_fixed_params=hide_fixed_params,
+ enable_unique_defaults=trans.app.config.enable_unique_workflow_defaults)
+ finally:
+ # restore the active history
+ if saved_history is not None:
+ trans.set_history(saved_history)
def get_item( self, trans, id ):
return self.get_stored_workflow( trans, id )
--- a/templates/workflow/run.mako Thu Aug 18 14:20:48 2011 -0400
+++ b/templates/workflow/run.mako Thu Aug 18 14:16:03 2011 -0700
@@ -6,8 +6,12 @@
<script type="text/javascript">
$( function() {
function show_tool_body(title){
- title.parent().css('border-bottom-width', '1px');
+ title.parent().show().css('border-bottom-width', '1px');
title.next().show('fast');
+ if ('${hide_fixed_params}'.toLowerCase() == 'true') {
+ // show previously hidden parameters
+ title.next().children(".form-row").show();
+ }
}
function hide_tool_body(title){
title.parent().css('border-bottom-width', '0px');
@@ -46,8 +50,15 @@
$("div.toolFormTitle").click(function(){
toggle_tool_body($(this));
});
- // Collapse non-interactive run-workflow panels by default.
- $("div.toolFormBody:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide().parent().css('border-bottom-width', '0px');
+ if ('${hide_fixed_params}'.toLowerCase() == 'true') {
+ // hide parameters that are not runtime inputs
+ $("div.form-row:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide();
+ $("div.toolForm:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide();
+ }
+ else {
+ // Collapse non-interactive run-workflow panels by default.
+ $("div.toolFormBody:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide().parent().css('border-bottom-width', '0px');
+ }
$("#show_all_tool_body").click(function(){
$("div.toolFormTitle").each(function(){
show_tool_body($(this));
@@ -163,6 +174,8 @@
import colorsys
import random
+used_accumulator = []
+
wf_parms = {}
for step in steps:
for v in [ActionBox.get_short_str(pja) for pja in step.post_job_actions] + step.state.inputs.values():
@@ -178,7 +191,7 @@
hue += hue_offset
%>
-<%def name="do_inputs( inputs, values, errors, prefix, step, other_values = None )">
+<%def name="do_inputs( inputs, values, errors, prefix, step, other_values = None, already_used = None )">
%if other_values is None:
<% other_values = values %>
%endif
@@ -196,7 +209,7 @@
<div class="repeat-group-item"><% index = repeat_values[i]['__index__'] %><div class="form-title-row"><b>${input.title} ${i + 1}</b></div>
- ${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(index) + "|", step, other_values )}
+ ${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(index) + "|", step, other_values, already_used )}
## <div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_${i}_remove" value="Remove ${input.title} ${i+1}" /></div></div>
%endfor
@@ -207,15 +220,15 @@
<% current_case = group_values['__current_case__'] %><% new_prefix = prefix + input.name + "|" %><% group_errors = errors.get( input.name, {} ) %>
- ${row_for_param( input.test_param, group_values[ input.test_param.name ], other_values, group_errors, prefix, step )}
- ${do_inputs( input.cases[ current_case ].inputs, group_values, group_errors, new_prefix, step, other_values )}
+ ${row_for_param( input.test_param, group_values[ input.test_param.name ], other_values, group_errors, prefix, step, already_used )}
+ ${do_inputs( input.cases[ current_case ].inputs, group_values, group_errors, new_prefix, step, other_values, already_used )}
%else:
- ${row_for_param( input, values[ input.name ], other_values, errors, prefix, step )}
+ ${row_for_param( input, values[ input.name ], other_values, errors, prefix, step, already_used )}
%endif
%endfor
</%def>
-<%def name="row_for_param( param, value, other_values, error_dict, prefix, step )">
+<%def name="row_for_param( param, value, other_values, error_dict, prefix, step, already_used )">
## -- ${param.name} -- ${step.state.inputs} --
%if error_dict.has_key( param.name ):
<% cls = "form-row form-row-error" %>
@@ -235,7 +248,9 @@
## FIXME: Initialize in the controller
<%
if value is None:
- value = other_values[ param.name ] = param.get_initial_value( t, other_values )
+ value = other_values[ param.name ] = param.get_initial_value_from_history_prevent_repeats( t, other_values, already_used )
+ if not enable_unique_defaults:
+ del already_used[:]
%>
${param.get_html_field( t, value, other_values ).get_html( str(step.id) + "|" + prefix )}
<input type="hidden" name="${step.id}|__force_update__${prefix}${param.name}" value="true" />
@@ -250,7 +265,11 @@
## controller should go through the inputs on the first
## load, fill in initial values where needed, and mark
## all that are runtime modifiable in some way.
- <% value = other_values[ param.name ] = param.get_initial_value( t, other_values ) %>
+ <%
+ value = other_values[ param.name ] = param.get_initial_value_from_history_prevent_repeats( t, other_values, already_used )
+ if not enable_unique_defaults:
+ del already_used[:]
+ %>
${param.get_html_field( t, value, other_values ).get_html( str(step.id) + "|" + prefix )}
<input type="hidden" name="${step.id}|__runtime__${prefix}${param.name}" value="true" />
%else:
@@ -342,7 +361,6 @@
});
</script>
%endif
-
%for i, step in enumerate( steps ):
%if step.type == 'tool' or step.type is None:
<% tool = app.toolbox.tools_by_id[step.tool_id] %>
@@ -355,36 +373,36 @@
% endif
</div><div class="toolFormBody">
- ${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step )}
- % if step.post_job_actions:
- <hr/>
- <div class='form-row'>
- % if len(step.post_job_actions) > 1:
- <label>Actions:</label>
- % else:
- <label>Action:</label>
+ ${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step, None, used_accumulator )}
+ % if step.post_job_actions:
+ <hr/>
+ <div class='form-row'>
+ % if len(step.post_job_actions) > 1:
+ <label>Actions:</label>
+ % else:
+ <label>Action:</label>
+ % endif
+ <%
+ pja_ss_all = []
+ for pja_ss in [ActionBox.get_short_str(pja) for pja in step.post_job_actions]:
+ for rematch in re.findall('\$\{.+?\}', pja_ss):
+ pja_ss = pja_ss.replace(rematch, '<span style="background-color:%s" class="wfpspan wf_parm__%s pja_wfp">%s</span>' % (wf_parms[rematch[2:-1]], rematch[2:-1], rematch[2:-1]))
+ pja_ss_all.append(pja_ss)
+ %>
+ ${'<br/>'.join(pja_ss_all)}
+ </div>
% endif
- <%
- pja_ss_all = []
- for pja_ss in [ActionBox.get_short_str(pja) for pja in step.post_job_actions]:
- for rematch in re.findall('\$\{.+?\}', pja_ss):
- pja_ss = pja_ss.replace(rematch, '<span style="background-color:%s" class="wfpspan wf_parm__%s pja_wfp">%s</span>' % (wf_parms[rematch[2:-1]], rematch[2:-1], rematch[2:-1]))
- pja_ss_all.append(pja_ss)
- %>
- ${'<br/>'.join(pja_ss_all)}
- </div>
- % endif
+ </div></div>
- </div>
- %else:
- <% module = step.module %>
- <input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}">
- <div class="toolForm">
- <div class="toolFormTitle">
- <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name}</span>
- % if step.annotations:
- <div class="step-annotation">${step.annotations[0].annotation}</div>
- % endif
+ %else:
+ <% module = step.module %>
+ <input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}">
+ <div class="toolForm">
+ <div class="toolFormTitle">
+ <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name}</span>
+ % if step.annotations:
+ <div class="step-annotation">${step.annotations[0].annotation}</div>
+ % endif
</div><div class="toolFormBody"><%
@@ -397,7 +415,7 @@
if not type_filter:
type_filter = ['data']
%>
- ${do_inputs( module.get_runtime_inputs(type_filter), step.state.inputs, errors.get( step.id, dict() ), "", step )}
+ ${do_inputs( module.get_runtime_inputs(type_filter), step.state.inputs, errors.get( step.id, dict() ), "", step, None, used_accumulator )}
</div></div>
%endif
@@ -411,10 +429,12 @@
%endfor
</ul>
%else:
+ %if history_id is None:
<p id='new_history_p'><input type="checkbox" name='new_history' value="true" id='new_history_cbx'/><label for='new_history_cbx'>Send results to a new history </label><span id="new_history_input">named: <input type='text' name='new_history_name' value='${h.to_unicode( workflow.name )}'/></span></p>
+ %endif
<input type="submit" name="run_workflow" value="Run workflow" /></form>
%endif
--- a/universe_wsgi.ini.sample Thu Aug 18 14:20:48 2011 -0400
+++ b/universe_wsgi.ini.sample Thu Aug 18 14:16:03 2011 -0700
@@ -444,6 +444,14 @@
# large servers.
#enable_tool_tags = False
+# Enable a feature when running workflows. When enabled, default datasets
+# are selected for "Set at Runtime" inputs from the history such that the
+# same input will not be selected twice, unless there are more inputs than
+# compatible datasets in the history.
+# When False, the most recently added compatible item in the history will
+# be used for each "Set at Runtime" input, independent of others in the Workflow
+#enable_unique_workflow_defaults = False
+
# Enable Galaxy's "Upload via FTP" interface. You'll need to install and
# configure an FTP server (we've used ProFTPd since it can use Galaxy's
# database for authentication) and set the following two options.
@@ -459,6 +467,15 @@
# Enable enforcement of quotas. Quotas can be set from the Admin interface.
#enable_quotas = False
+# Enable a feature when running workflows. When enabled, default datasets
+# are selected for "Set at Runtime" inputs from the history such that the
+# same input will not be selected twice, unless there are more inputs than
+# compatible datasets in the history.
+# When False, the most recently added compatible item in the history will
+# be used for each "Set at Runtime" input, independent of others in the Workflow
+#enable_unique_workflow_defaults = False
+
+
# -- Job Execution
# If running multiple Galaxy processes, one can be designated as the job
http://bitbucket.org/galaxy/galaxy-central/changeset/b58453168699/
changeset: b58453168699
user: John Duddy
date: 2011-08-18 23:38:26
summary: Removed duplicate section (merge error)
affected #: 1 file (-1 bytes)
--- a/universe_wsgi.ini.sample Thu Aug 18 14:16:03 2011 -0700
+++ b/universe_wsgi.ini.sample Thu Aug 18 14:38:26 2011 -0700
@@ -444,14 +444,6 @@
# large servers.
#enable_tool_tags = False
-# Enable a feature when running workflows. When enabled, default datasets
-# are selected for "Set at Runtime" inputs from the history such that the
-# same input will not be selected twice, unless there are more inputs than
-# compatible datasets in the history.
-# When False, the most recently added compatible item in the history will
-# be used for each "Set at Runtime" input, independent of others in the Workflow
-#enable_unique_workflow_defaults = False
-
# Enable Galaxy's "Upload via FTP" interface. You'll need to install and
# configure an FTP server (we've used ProFTPd since it can use Galaxy's
# database for authentication) and set the following two options.
http://bitbucket.org/galaxy/galaxy-central/changeset/553cdfbd3ad7/
changeset: 553cdfbd3ad7
user: dannon
date: 2011-10-10 15:39:20
summary: Workflow unique default inputs: Merge in from John Duddy.
affected #: 5 files (-1 bytes)
--- a/lib/galaxy/config.py Fri Oct 07 15:24:27 2011 -0400
+++ b/lib/galaxy/config.py Mon Oct 10 09:39:20 2011 -0400
@@ -47,6 +47,7 @@
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.enable_unique_workflow_defaults = string_as_bool ( kwargs.get ('enable_unique_workflow_defaults', False ) )
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) )
--- a/lib/galaxy/tools/parameters/basic.py Fri Oct 07 15:24:27 2011 -0400
+++ b/lib/galaxy/tools/parameters/basic.py Mon Oct 10 09:39:20 2011 -0400
@@ -75,6 +75,16 @@
"""
return None
+ def get_initial_value_from_history_prevent_repeats( self, trans, context, already_used ):
+ """
+ Get the starting value for the parameter, but if fetching from the history, try
+ to find a value that has not yet been used. already_used is a list of objects that
+ tools must manipulate (by adding to it) to store a memento that they can use to detect
+ if a value has already been chosen from the history. This is to support the capability to
+ choose each dataset once
+ """
+ return self.get_initial_value(trans, context);
+
def get_required_enctype( self ):
"""
If this parameter needs the form to have a specific encoding
@@ -1389,6 +1399,9 @@
return field
def get_initial_value( self, trans, context ):
+ return self.get_initial_value_from_history_prevent_repeats(trans, context, None);
+
+ def get_initial_value_from_history_prevent_repeats( self, trans, context, already_used ):
"""
NOTE: This is wasteful since dynamic options and dataset collection
happens twice (here and when generating HTML).
@@ -1401,7 +1414,7 @@
assert history is not None, "DataToolParameter requires a history"
if self.optional:
return None
- most_recent_dataset = [None]
+ most_recent_dataset = []
filter_value = None
if self.options:
try:
@@ -1427,15 +1440,19 @@
data = converted_dataset
if not is_valid or ( self.options and self._options_filter_attribute( data ) != filter_value ):
continue
- most_recent_dataset[0] = data
+ most_recent_dataset.append(data)
# Also collect children via association object
dataset_collector( data.children )
dataset_collector( history.datasets )
- most_recent_dataset = most_recent_dataset.pop()
- if most_recent_dataset is not None:
- return most_recent_dataset
- else:
- return ''
+ most_recent_dataset.reverse()
+ if already_used is not None:
+ for val in most_recent_dataset:
+ if val is not None and val not in already_used:
+ already_used.append(val)
+ return val
+ if len(most_recent_dataset) > 0:
+ return most_recent_dataset[0]
+ return ''
def from_html( self, value, trans, other_values={} ):
# Can't look at history in workflow mode, skip validation and such,
--- a/lib/galaxy/web/controllers/workflow.py Fri Oct 07 15:24:27 2011 -0400
+++ b/lib/galaxy/web/controllers/workflow.py Mon Oct 10 09:39:20 2011 -0400
@@ -1258,7 +1258,7 @@
## % ( workflow_name, web.url_for( action='editor', id=trans.security.encode_id(stored.id) ) ) )
@web.expose
- def run( self, trans, id, **kwargs ):
+ def run( self, trans, id, history_id=None, hide_fixed_params=False, **kwargs ):
stored = self.get_stored_workflow( trans, id, check_ownership=False )
user = trans.get_user()
if stored.user != user:
@@ -1279,163 +1279,185 @@
errors = {}
has_upgrade_messages = False
has_errors = False
- if kwargs:
- # If kwargs were provided, the states for each step should have
- # been POSTed
- # Get the kwarg keys for data inputs
- input_keys = filter(lambda a: a.endswith('|input'), kwargs)
- # Example: prefixed='2|input'
- # Check if one of them is a list
- multiple_input_key = None
- multiple_inputs = [None]
- for input_key in input_keys:
- if isinstance(kwargs[input_key], list):
- multiple_input_key = input_key
- multiple_inputs = kwargs[input_key]
- # List to gather values for the template
- invocations=[]
- for input_number, single_input in enumerate(multiple_inputs):
- # Example: single_input='1', single_input='2', etc...
- # 'Fix' the kwargs, to have only the input for this iteration
- if multiple_input_key:
- kwargs[multiple_input_key] = single_input
+ saved_history = None
+ if history_id is not None:
+ saved_history = trans.get_history();
+ try:
+ decoded_history_id = trans.security.decode_id( history_id )
+ history = trans.sa_session.query(trans.app.model.History).get(decoded_history_id)
+ if history.user != trans.user and not trans.user_is_admin():
+ if trans.sa_session.query(trans.app.model.HistoryUserShareAssociation).filter_by(user=trans.user, history=history).count() == 0:
+ error("History is not owned by or shared with current user")
+ trans.set_history(history)
+ except TypeError:
+ error("Malformed history id ( %s ) specified, unable to decode." % str( history_id ))
+ except:
+ error("That history does not exist.")
+ try: # use a try/finally block to restore the user's current history
+ if kwargs:
+ # If kwargs were provided, the states for each step should have
+ # been POSTed
+ # Get the kwarg keys for data inputs
+ input_keys = filter(lambda a: a.endswith('|input'), kwargs)
+ # Example: prefixed='2|input'
+ # Check if one of them is a list
+ multiple_input_key = None
+ multiple_inputs = [None]
+ for input_key in input_keys:
+ if isinstance(kwargs[input_key], list):
+ multiple_input_key = input_key
+ multiple_inputs = kwargs[input_key]
+ # List to gather values for the template
+ invocations=[]
+ for input_number, single_input in enumerate(multiple_inputs):
+ # Example: single_input='1', single_input='2', etc...
+ # 'Fix' the kwargs, to have only the input for this iteration
+ if multiple_input_key:
+ kwargs[multiple_input_key] = single_input
+ for step in workflow.steps:
+ step.upgrade_messages = {}
+ # Connections by input name
+ step.input_connections_by_name = \
+ dict( ( conn.input_name, conn ) for conn in step.input_connections )
+ # Extract just the arguments for this step by prefix
+ p = "%s|" % step.id
+ l = len(p)
+ step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
+ step_errors = None
+ if step.type == 'tool' or step.type is None:
+ module = module_factory.from_workflow_step( trans, step )
+ # Fix any missing parameters
+ step.upgrade_messages = module.check_and_update_state()
+ if step.upgrade_messages:
+ has_upgrade_messages = True
+ # Any connected input needs to have value DummyDataset (these
+ # are not persisted so we need to do it every time)
+ module.add_dummy_datasets( connections=step.input_connections )
+ # Get the tool
+ tool = module.tool
+ # Get the state
+ step.state = state = module.state
+ # Get old errors
+ old_errors = state.inputs.pop( "__errors__", {} )
+ # Update the state
+ step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
+ update_only=True, old_errors=old_errors )
+ else:
+ # Fix this for multiple inputs
+ module = step.module = module_factory.from_workflow_step( trans, step )
+ state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
+ step_errors = module.update_runtime_state( trans, state, step_args )
+ if step_errors:
+ errors[step.id] = state.inputs["__errors__"] = step_errors
+ if 'run_workflow' in kwargs and not errors:
+ new_history = None
+ if 'new_history' in kwargs:
+ if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
+ nh_name = kwargs['new_history_name']
+ else:
+ nh_name = "History from %s workflow" % workflow.name
+ if multiple_input_key:
+ nh_name = '%s %d' % (nh_name, input_number + 1)
+ new_history = trans.app.model.History( user=trans.user, name=nh_name )
+ trans.sa_session.add( new_history )
+ # Run each step, connecting outputs to inputs
+ workflow_invocation = model.WorkflowInvocation()
+ workflow_invocation.workflow = workflow
+ outputs = odict()
+ for i, step in enumerate( workflow.steps ):
+ # Execute module
+ job = None
+ if step.type == 'tool' or step.type is None:
+ tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ input_values = step.state.inputs
+ # Connect up
+ def callback( input, value, prefixed_name, prefixed_label ):
+ if isinstance( input, DataToolParameter ):
+ if prefixed_name in step.input_connections_by_name:
+ conn = step.input_connections_by_name[ prefixed_name ]
+ return outputs[ conn.output_step.id ][ conn.output_name ]
+ visit_input_values( tool.inputs, step.state.inputs, callback )
+ # Execute it
+ job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
+ outputs[ step.id ] = out_data
+ # Create new PJA associations with the created job, to be run on completion.
+ # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
+ # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
+ replacement_dict = {}
+ for k, v in kwargs.iteritems():
+ if k.startswith('wf_parm|'):
+ replacement_dict[k[8:]] = v
+ for pja in step.post_job_actions:
+ if pja.action_type in ActionBox.immediate_actions:
+ ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
+ else:
+ job.add_post_job_action(pja)
+ else:
+ job, out_data = step.module.execute( trans, step.state )
+ outputs[ step.id ] = out_data
+ # Record invocation
+ workflow_invocation_step = model.WorkflowInvocationStep()
+ workflow_invocation_step.workflow_invocation = workflow_invocation
+ workflow_invocation_step.workflow_step = step
+ workflow_invocation_step.job = job
+ # All jobs ran sucessfully, so we can save now
+ trans.sa_session.add( workflow_invocation )
+ invocations.append({'outputs': outputs,
+ 'new_history': new_history})
+ trans.sa_session.flush()
+ return trans.fill_template( "workflow/run_complete.mako",
+ workflow=stored,
+ invocations=invocations )
+ else:
+ # Prepare each step
+ missing_tools = []
for step in workflow.steps:
step.upgrade_messages = {}
- # Connections by input name
- step.input_connections_by_name = \
- dict( ( conn.input_name, conn ) for conn in step.input_connections )
- # Extract just the arguments for this step by prefix
- p = "%s|" % step.id
- l = len(p)
- step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
- step_errors = None
+ # Contruct modules
if step.type == 'tool' or step.type is None:
- module = module_factory.from_workflow_step( trans, step )
- # Fix any missing parameters
- step.upgrade_messages = module.check_and_update_state()
+ # Restore the tool state for the step
+ step.module = module_factory.from_workflow_step( trans, step )
+ if not step.module:
+ if step.tool_id not in missing_tools:
+ missing_tools.append(step.tool_id)
+ continue
+ step.upgrade_messages = step.module.check_and_update_state()
if step.upgrade_messages:
has_upgrade_messages = True
# Any connected input needs to have value DummyDataset (these
# are not persisted so we need to do it every time)
- module.add_dummy_datasets( connections=step.input_connections )
- # Get the tool
- tool = module.tool
- # Get the state
- step.state = state = module.state
- # Get old errors
- old_errors = state.inputs.pop( "__errors__", {} )
- # Update the state
- step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
- update_only=True, old_errors=old_errors )
+ step.module.add_dummy_datasets( connections=step.input_connections )
+ # Store state with the step
+ step.state = step.module.state
+ # Error dict
+ if step.tool_errors:
+ has_errors = True
+ errors[step.id] = step.tool_errors
else:
- # Fix this for multiple inputs
- module = step.module = module_factory.from_workflow_step( trans, step )
- state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
- step_errors = module.update_runtime_state( trans, state, step_args )
- if step_errors:
- errors[step.id] = state.inputs["__errors__"] = step_errors
- if 'run_workflow' in kwargs and not errors:
- new_history = None
- if 'new_history' in kwargs:
- if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
- nh_name = kwargs['new_history_name']
- else:
- nh_name = "History from %s workflow" % workflow.name
- if multiple_input_key:
- nh_name = '%s %d' % (nh_name, input_number + 1)
- new_history = trans.app.model.History( user=trans.user, name=nh_name )
- trans.sa_session.add( new_history )
- # Run each step, connecting outputs to inputs
- workflow_invocation = model.WorkflowInvocation()
- workflow_invocation.workflow = workflow
- outputs = odict()
- for i, step in enumerate( workflow.steps ):
- # Execute module
- job = None
- if step.type == 'tool' or step.type is None:
- tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
- input_values = step.state.inputs
- # Connect up
- def callback( input, value, prefixed_name, prefixed_label ):
- if isinstance( input, DataToolParameter ):
- if prefixed_name in step.input_connections_by_name:
- conn = step.input_connections_by_name[ prefixed_name ]
- return outputs[ conn.output_step.id ][ conn.output_name ]
- visit_input_values( tool.inputs, step.state.inputs, callback )
- # Execute it
- job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
- outputs[ step.id ] = out_data
- # Create new PJA associations with the created job, to be run on completion.
- # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
- # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
- replacement_dict = {}
- for k, v in kwargs.iteritems():
- if k.startswith('wf_parm|'):
- replacement_dict[k[8:]] = v
- for pja in step.post_job_actions:
- if pja.action_type in ActionBox.immediate_actions:
- ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
- else:
- job.add_post_job_action(pja)
- else:
- job, out_data = step.module.execute( trans, step.state )
- outputs[ step.id ] = out_data
- # Record invocation
- workflow_invocation_step = model.WorkflowInvocationStep()
- workflow_invocation_step.workflow_invocation = workflow_invocation
- workflow_invocation_step.workflow_step = step
- workflow_invocation_step.job = job
- # All jobs ran sucessfully, so we can save now
- trans.sa_session.add( workflow_invocation )
- invocations.append({'outputs': outputs,
- 'new_history': new_history})
- trans.sa_session.flush()
- return trans.fill_template( "workflow/run_complete.mako",
- workflow=stored,
- invocations=invocations )
- else:
- # Prepare each step
- missing_tools = []
- for step in workflow.steps:
- step.upgrade_messages = {}
- # Contruct modules
- if step.type == 'tool' or step.type is None:
- # Restore the tool state for the step
- step.module = module_factory.from_workflow_step( trans, step )
- if not step.module:
- if step.tool_id not in missing_tools:
- missing_tools.append(step.tool_id)
- continue
- step.upgrade_messages = step.module.check_and_update_state()
- if step.upgrade_messages:
- has_upgrade_messages = True
- # Any connected input needs to have value DummyDataset (these
- # are not persisted so we need to do it every time)
- step.module.add_dummy_datasets( connections=step.input_connections )
- # Store state with the step
- step.state = step.module.state
- # Error dict
- if step.tool_errors:
- has_errors = True
- errors[step.id] = step.tool_errors
- else:
- ## Non-tool specific stuff?
- step.module = module_factory.from_workflow_step( trans, step )
- step.state = step.module.get_runtime_state()
- # Connections by input name
- step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
- if missing_tools:
- stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
- return trans.fill_template("workflow/run.mako", steps=[], workflow=stored, missing_tools = missing_tools)
- # Render the form
- stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
- return trans.fill_template(
- "workflow/run.mako",
- steps=workflow.steps,
- workflow=stored,
- has_upgrade_messages=has_upgrade_messages,
- errors=errors,
- incoming=kwargs )
+ ## Non-tool specific stuff?
+ step.module = module_factory.from_workflow_step( trans, step )
+ step.state = step.module.get_runtime_state()
+ # Connections by input name
+ step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
+ if missing_tools:
+ stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
+ return trans.fill_template("workflow/run.mako", steps=[], workflow=stored, missing_tools = missing_tools)
+ # Render the form
+ stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
+ return trans.fill_template(
+ "workflow/run.mako",
+ steps=workflow.steps,
+ workflow=stored,
+ has_upgrade_messages=has_upgrade_messages,
+ errors=errors,
+ incoming=kwargs,
+ history_id=history_id,
+ hide_fixed_params=hide_fixed_params,
+ enable_unique_defaults=trans.app.config.enable_unique_workflow_defaults)
+ finally:
+ # restore the active history
+ if saved_history is not None:
+ trans.set_history(saved_history)
def get_item( self, trans, id ):
return self.get_stored_workflow( trans, id )
--- a/templates/workflow/run.mako Fri Oct 07 15:24:27 2011 -0400
+++ b/templates/workflow/run.mako Mon Oct 10 09:39:20 2011 -0400
@@ -6,8 +6,12 @@
<script type="text/javascript">
$( function() {
function show_tool_body(title){
- title.parent().css('border-bottom-width', '1px');
+ title.parent().show().css('border-bottom-width', '1px');
title.next().show('fast');
+ if ('${hide_fixed_params}'.toLowerCase() == 'true') {
+ // show previously hidden parameters
+ title.next().children(".form-row").show();
+ }
}
function hide_tool_body(title){
title.parent().css('border-bottom-width', '0px');
@@ -46,8 +50,15 @@
$("div.toolFormTitle").click(function(){
toggle_tool_body($(this));
});
- // Collapse non-interactive run-workflow panels by default.
- $("div.toolFormBody:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide().parent().css('border-bottom-width', '0px');
+ if ('${hide_fixed_params}'.toLowerCase() == 'true') {
+ // hide parameters that are not runtime inputs
+ $("div.form-row:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide();
+ $("div.toolForm:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide();
+ }
+ else {
+ // Collapse non-interactive run-workflow panels by default.
+ $("div.toolFormBody:not(:has(select, textarea, input[type!=hidden], .wfpspan))").hide().parent().css('border-bottom-width', '0px');
+ }
$("#show_all_tool_body").click(function(){
$("div.toolFormTitle").each(function(){
show_tool_body($(this));
@@ -163,6 +174,8 @@
import colorsys
import random
+used_accumulator = []
+
wf_parms = {}
for step in steps:
for v in [ActionBox.get_short_str(pja) for pja in step.post_job_actions] + step.state.inputs.values():
@@ -178,7 +191,7 @@
hue += hue_offset
%>
-<%def name="do_inputs( inputs, values, errors, prefix, step, other_values = None )">
+<%def name="do_inputs( inputs, values, errors, prefix, step, other_values = None, already_used = None )">
%if other_values is None:
<% other_values = values %>
%endif
@@ -196,7 +209,7 @@
<div class="repeat-group-item"><% index = repeat_values[i]['__index__'] %><div class="form-title-row"><b>${input.title} ${i + 1}</b></div>
- ${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(index) + "|", step, other_values )}
+ ${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(index) + "|", step, other_values, already_used )}
## <div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_${i}_remove" value="Remove ${input.title} ${i+1}" /></div></div>
%endfor
@@ -207,15 +220,15 @@
<% current_case = group_values['__current_case__'] %><% new_prefix = prefix + input.name + "|" %><% group_errors = errors.get( input.name, {} ) %>
- ${row_for_param( input.test_param, group_values[ input.test_param.name ], other_values, group_errors, prefix, step )}
- ${do_inputs( input.cases[ current_case ].inputs, group_values, group_errors, new_prefix, step, other_values )}
+ ${row_for_param( input.test_param, group_values[ input.test_param.name ], other_values, group_errors, prefix, step, already_used )}
+ ${do_inputs( input.cases[ current_case ].inputs, group_values, group_errors, new_prefix, step, other_values, already_used )}
%else:
- ${row_for_param( input, values[ input.name ], other_values, errors, prefix, step )}
+ ${row_for_param( input, values[ input.name ], other_values, errors, prefix, step, already_used )}
%endif
%endfor
</%def>
-<%def name="row_for_param( param, value, other_values, error_dict, prefix, step )">
+<%def name="row_for_param( param, value, other_values, error_dict, prefix, step, already_used )">
## -- ${param.name} -- ${step.state.inputs} --
%if error_dict.has_key( param.name ):
<% cls = "form-row form-row-error" %>
@@ -235,7 +248,9 @@
## FIXME: Initialize in the controller
<%
if value is None:
- value = other_values[ param.name ] = param.get_initial_value( t, other_values )
+ value = other_values[ param.name ] = param.get_initial_value_from_history_prevent_repeats( t, other_values, already_used )
+ if not enable_unique_defaults:
+ del already_used[:]
%>
${param.get_html_field( t, value, other_values ).get_html( str(step.id) + "|" + prefix )}
<input type="hidden" name="${step.id}|__force_update__${prefix}${param.name}" value="true" />
@@ -250,7 +265,11 @@
## controller should go through the inputs on the first
## load, fill in initial values where needed, and mark
## all that are runtime modifiable in some way.
- <% value = other_values[ param.name ] = param.get_initial_value( t, other_values ) %>
+ <%
+ value = other_values[ param.name ] = param.get_initial_value_from_history_prevent_repeats( t, other_values, already_used )
+ if not enable_unique_defaults:
+ del already_used[:]
+ %>
${param.get_html_field( t, value, other_values ).get_html( str(step.id) + "|" + prefix )}
<input type="hidden" name="${step.id}|__runtime__${prefix}${param.name}" value="true" />
%else:
@@ -342,7 +361,6 @@
});
</script>
%endif
-
%for i, step in enumerate( steps ):
%if step.type == 'tool' or step.type is None:
<% tool = app.toolbox.tools_by_id[step.tool_id] %>
@@ -355,36 +373,36 @@
% endif
</div><div class="toolFormBody">
- ${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step )}
- % if step.post_job_actions:
- <hr/>
- <div class='form-row'>
- % if len(step.post_job_actions) > 1:
- <label>Actions:</label>
- % else:
- <label>Action:</label>
+ ${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step, None, used_accumulator )}
+ % if step.post_job_actions:
+ <hr/>
+ <div class='form-row'>
+ % if len(step.post_job_actions) > 1:
+ <label>Actions:</label>
+ % else:
+ <label>Action:</label>
+ % endif
+ <%
+ pja_ss_all = []
+ for pja_ss in [ActionBox.get_short_str(pja) for pja in step.post_job_actions]:
+ for rematch in re.findall('\$\{.+?\}', pja_ss):
+ pja_ss = pja_ss.replace(rematch, '<span style="background-color:%s" class="wfpspan wf_parm__%s pja_wfp">%s</span>' % (wf_parms[rematch[2:-1]], rematch[2:-1], rematch[2:-1]))
+ pja_ss_all.append(pja_ss)
+ %>
+ ${'<br/>'.join(pja_ss_all)}
+ </div>
% endif
- <%
- pja_ss_all = []
- for pja_ss in [ActionBox.get_short_str(pja) for pja in step.post_job_actions]:
- for rematch in re.findall('\$\{.+?\}', pja_ss):
- pja_ss = pja_ss.replace(rematch, '<span style="background-color:%s" class="wfpspan wf_parm__%s pja_wfp">%s</span>' % (wf_parms[rematch[2:-1]], rematch[2:-1], rematch[2:-1]))
- pja_ss_all.append(pja_ss)
- %>
- ${'<br/>'.join(pja_ss_all)}
- </div>
- % endif
+ </div></div>
- </div>
- %else:
- <% module = step.module %>
- <input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}">
- <div class="toolForm">
- <div class="toolFormTitle">
- <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name}</span>
- % if step.annotations:
- <div class="step-annotation">${step.annotations[0].annotation}</div>
- % endif
+ %else:
+ <% module = step.module %>
+ <input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}">
+ <div class="toolForm">
+ <div class="toolFormTitle">
+ <span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name}</span>
+ % if step.annotations:
+ <div class="step-annotation">${step.annotations[0].annotation}</div>
+ % endif
</div><div class="toolFormBody"><%
@@ -397,7 +415,7 @@
if not type_filter:
type_filter = ['data']
%>
- ${do_inputs( module.get_runtime_inputs(type_filter), step.state.inputs, errors.get( step.id, dict() ), "", step )}
+ ${do_inputs( module.get_runtime_inputs(type_filter), step.state.inputs, errors.get( step.id, dict() ), "", step, None, used_accumulator )}
</div></div>
%endif
@@ -411,10 +429,12 @@
%endfor
</ul>
%else:
+ %if history_id is None:
<p id='new_history_p'><input type="checkbox" name='new_history' value="true" id='new_history_cbx'/><label for='new_history_cbx'>Send results to a new history </label><span id="new_history_input">named: <input type='text' name='new_history_name' value='${h.to_unicode( workflow.name )}'/></span></p>
+ %endif
<input type="submit" name="run_workflow" value="Run workflow" /></form>
%endif
--- a/universe_wsgi.ini.sample Fri Oct 07 15:24:27 2011 -0400
+++ b/universe_wsgi.ini.sample Mon Oct 10 09:39:20 2011 -0400
@@ -461,6 +461,15 @@
# Enable enforcement of quotas. Quotas can be set from the Admin interface.
#enable_quotas = False
+# Enable a feature when running workflows. When enabled, default datasets
+# are selected for "Set at Runtime" inputs from the history such that the
+# same input will not be selected twice, unless there are more inputs than
+# compatible datasets in the history.
+# When False, the most recently added compatible item in the history will
+# be used for each "Set at Runtime" input, independent of others in the Workflow
+#enable_unique_workflow_defaults = False
+
+
# -- Job Execution
# If running multiple Galaxy processes, one can be designated as the job
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: Bug fixes: (a) trackster: don't cache tile if undefined and (b) define init_operation_buttons differently to prevent ordering issue. Pack scripts.
by Bitbucket 07 Oct '11
by Bitbucket 07 Oct '11
07 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/886ad9798488/
changeset: 886ad9798488
user: jgoecks
date: 2011-10-07 21:24:27
summary: Bug fixes: (a) trackster: don't cache tile if undefined and (b) define init_operation_buttons differently to prevent ordering issue. Pack scripts.
affected #: 3 files (-1 bytes)
--- a/static/scripts/packed/trackster.js Fri Oct 07 11:47:00 2011 -0400
+++ b/static/scripts/packed/trackster.js Fri Oct 07 15:24:27 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,aa){var q=f("class").extend,t=f("slotting"),N=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"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")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}if(ar.container){ar.container.remove_drawable(ar)}o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};aa.moveable=n;var af=16,I=9,F=20,V=I+2,B=100,K=12000,T=200,E=5,w=10,M=5000,x=100,p="There was an error in indexing this dataset. ",L="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",z="Tool cannot be rerun: ",a="Loading data...",ab="Ready for display",d=10,v=5,D=5;function y(ah){return Math.round(ah*1000)/1000}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var U=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(U.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var J=function(ai,ah,aj){U.call(this,ai,ah,aj)};q(J.prototype,U.prototype,c.prototype,{load_data:function(aj,ah,al,am,ai,ak){if(ai>1){return}return U.prototype.load_data.call(this,aj,ah,al,am,ai,ak)}});var r=function(ak,ai,ah,aj,al){this.name=ak;this.view=ai;this.container=ah;this.drag_handle_class=al;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak}],saved_values:aj,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values};q(r.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},make_name_popup_menu:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var A=function(al,ak,ai,ah,aj,am){r.call(this,ak,ai,ah,aj,am);this.obj_type=al;this.drawables=[]};q(A.prototype,r.prototype,{init:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah].init()}},_draw:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah]._draw()}},to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){ai.push(this.drawables[ah].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ai}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var S=function(ak,ai,ah,aj){A.call(this,"DrawableGroup",ak,ai,ah,aj,"group-handle");if(!S.id_counter){S.id_counter=0}var al=S.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+al).appendTo(this.container.content_div);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+al+"_content_div").appendTo(this.container_div);m(this.container_div,this);m(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.make_name_popup_menu()};q(S.prototype,r.prototype,A.prototype,{make_name_popup_menu:function(){var ai=this;var ah={};ah["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){ai.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 Group",ai.config.build_form(),{Cancel:al,OK:aj})};ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)}});var ae=function(ah,ak,aj,ai){A.call(this,"View");this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;this.tracks=this.drawables;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.init();this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,A.prototype,{init:function(){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<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 ai=function(al){if(al.type==="focusout"||(al.keyCode||al.which)===13||(al.keyCode||al.which)===27){if((al.keyCode||al.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.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(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.browser_content_div.click(function(al){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(al){ah.zoom_in(al.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(al,am){this.current_x=am.offsetX}).bind("drag",function(al,an){var ao=an.offsetX-this.current_x;this.current_x=an.offsetX;var am=Math.round(ao/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-am)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(al,am){if(al.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(al,am){am.original_low=ah.low;am.current_height=al.clientY;am.current_x=am.offsetX}).bind("drag",function(an,ap){var al=$(this);var aq=ap.offsetX-ap.current_x;var am=al.scrollTop()-(an.clientY-ap.current_height);al.scrollTop(am);ap.current_height=an.clientY;ap.current_x=ap.offsetX;var ao=Math.round(aq/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}).bind("mousewheel",function(an,ap,am,al){if(am){var ao=Math.round(-am/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}});this.top_labeltrack.bind("dragstart",function(al,am){return $("<div />").css({height:ah.browser_content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ap,aq){$(aq.proxy).css({left:Math.min(ap.pageX,aq.startX),width:Math.abs(ap.pageX-aq.startX)});var am=Math.min(ap.pageX,aq.startX)-ah.container.offset().left,al=Math.max(ap.pageX,aq.startX)-ah.container.offset().left,ao=(ah.high-ah.low),an=ah.viewport_container.width();ah.update_location(Math.round(am/an*ao)+ah.low,Math.round(al/an*ao)+ah.low)}).bind("dragend",function(aq,ar){var am=Math.min(aq.pageX,ar.startX),al=Math.max(aq.pageX,ar.startX),ao=(ah.high-ah.low),an=ah.viewport_container.width(),ap=ah.low;ah.low=Math.round(am/an*ao)+ap;ah.high=Math.round(al/an*ao)+ap;$(ar.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,{content_div:this.top_labeltrack}));this.add_label_track(new ad(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(aj){aj.num=x;$.extend(aj,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this,ai=$.Deferred();$.ajax({url:chrom_url,data:aj,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+aj.chrom);return}if(al.reference){ah.add_label_track(new C(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);ah.chrom_start_index=al.start_index;ai.resolve(al)},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}});return ai},change_chrom:function(al,ai,an){if(!al||al==="None"){return}var ak=this;if(al==="previous"){ak.load_chroms({low:this.chrom_start_index-x});return}if(al==="next"){ak.load_chroms({low:this.chrom_start_index+x});return}var am=$.grep(ak.chrom_data,function(ap,aq){return ap.chrom===al})[0];if(am===undefined){ak.load_chroms({chrom:al},function(){ak.change_chrom(al,ai,an)});return}else{if(al!==ak.chrom){ak.chrom=al;ak.chrom_select.val(ak.chrom);ak.max_high=am.len-1;ak.reset();ak.request_redraw(true);for(var ao=0,ah=ak.tracks.length;ao<ah;ao++){var aj=ak.tracks[ao];if(aj.init){aj.init()}}}if(ai!==undefined&&an!==undefined){ak.low=Math.max(ai,0);ak.high=Math.min(an,ak.max_high)}ak.reset_overview();ak.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_drawable:function(ah){A.prototype.add_drawable.call(this,ah);ah.init();this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;ah.init();this.label_tracks.push(ah)},remove_drawable:function(aj,ai){A.prototype.remove_drawable.call(this,aj);if(ai){var ah=this;aj.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.tracks),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(E,Math.ceil(Math.log((this.high-this.low)/T)/Math.log(E)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);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(ah){$.when(ah.get_overview_tile()).then(function(ai){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(ai.canvas);view.overview_highlight.show().height(ai.canvas.height());view.overview_viewport.height(ai.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ah;ah.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 s=function(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new P(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai={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},al=this.track,aj=ai.tool_id+al.tool_region_and_parameters_str(ai.chrom,ai.low,ai.high),ah,am;if(al.container===view){var ak=new S(this.name,this.track.view,this.track.container);al.container.add_drawable(ak);al.container.remove_drawable(al);ak.add_drawable(al);al.container_div.appendTo(ak.content_div);ah=ak}else{ah=al.container}if(al instanceof e){am=new X(aj,view,ah,"hda");am.change_mode(al.mode);ah.add_drawable(am)}am.content_div.text("Starting job.");this.run(ai,am,function(an){am.dataset_id=an.dataset_id;am.content_div.text("Running job.");am.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(L)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(z+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var P=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){P.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var Y=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);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};q(Y.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=parseFloat(ah[this.index]);return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(ar,ay){this.track=ar;this.filters=[];for(var at=0;at<ay.length;at++){var au=ay[at],az=au.name,ah=au.type,ak=au.index,ax=au.tool_id,aw=au.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[at]=new Y(az,ak,ax,aw)}else{console.log("ERROR: unsupported filter: ",az,ah)}}var al=function(aA,aB,aC){aA.click(function(){var aD=aB.text();max=parseFloat(aC.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aC.slider("option","values")){input_size=2*input_size+1;multi_value=true}aB.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aD).appendTo(aB).focus().select().click(function(aE){aE.stopPropagation()}).blur(function(){$(this).remove();aB.text(aD)}).keyup(function(aI){if(aI.keyCode===27){$(this).trigger("blur")}else{if(aI.keyCode===13){var aG=aC.slider("option","min"),aE=aC.slider("option","max"),aH=function(aJ){return(isNaN(aJ)||aJ>aE||aJ<aG)},aF=$(this).val();if(!multi_value){aF=parseFloat(aF);if(aH(aF)){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}else{aF=aF.split("-");aF=[parseFloat(aF[0]),parseFloat(aF[1])];if(aH(aF[0])||aH(aF[1])){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}aC.slider((multi_value?"values":"value"),aF)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aA){aA.stopPropagation()}).click(function(aA){aA.stopPropagation()}).bind("dblclick",function(aA){aA.stopPropagation()}).bind("keydown",function(aA){aA.stopPropagation()});var av=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aD,aF){aF.container=$("<div/>").addClass("slider-row").appendTo(av);var aE=$("<div/>").addClass("elt-label").appendTo(aF.container);var aC=$("<span/>").addClass("slider-name").text(aF.name+" ").appendTo(aE);var aB=$("<span/>");var aH=$("<span/>").addClass("slider-value").appendTo(aE).append("[").append(aB).append("]");var aA=$("<div/>").addClass("slider").appendTo(aF.container);aF.control_element=$("<div/>").attr("id",aF.name+"-filter-control").appendTo(aA);var aG=[0,0];aF.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aJ,aK){var aI=aK.values;aB.text(aI[0]+"-"+aI[1]);aF.low=aI[0];aF.high=aI[1];ap.track.request_draw(true,true)},change:function(aI,aJ){aF.control_element.slider("option","slide").call(aF.control_element,aI,aJ)}});aF.slider=aF.control_element;aF.slider_label=aB;al(aH,aB,aF.control_element);$("<div style='clear: both;'/>").appendTo(aF.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(av);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var aj=this;ao.click(function(){aj.run_on_dataset()})}var aq=$("<div/>").addClass("display-controls").appendTo(this.parent_div),an=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(aq),ai=$("<select/>").attr("name","alpha_dropdown").appendTo(aq);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(ai);for(var at=0;at<this.filters.length;at++){$("<option/>").attr("value",at).text(this.filters[at].name).appendTo(ai)}ai.change(function(){$(this).children("option:selected").each(function(){var aA=parseInt($(this).val());ap.alpha_filter=(aA>=0?ap.filters[aA]:null);ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var Q=function(ai,ah){N.AlphaGenerator.call(this,ah);this.filter=ai};Q.prototype.gen_alpha=function(ah){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(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var H=function(ah){this.track=ah.track;this.params=ah.params;this.values={};this.restore_values((ah.saved_values?ah.saved_values:{}));this.onchange=ah.onchange};q(H.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(aj,ai,ah,ak){this.index=aj;this.low=aj*T*ai;this.high=(aj+1)*T*ai;this.resolution=ai;this.canvas=$("<div class='track-tile'/>").append(ah);this.data=ak;this.stale=false};var l=function(aj,ai,ah,ak,al){b.call(this,aj,ai,ah,ak);this.max_val=al};var R=function(ak,aj,ai,an,am,ah){b.call(this,ak,aj,ai,an);this.message=am;this.feature_mapper=ah;var al=this;$(this.canvas).mousemove(function(ap){var ao=al.feature_mapper.get_feature_data(ap.offsetX,ap.offsetY)})};var j=function(ak,ai,ah,aj,al,am){r.call(this,ak,ai,ah,{},"draghandle");this.data_url=(al?al:default_data_url);this.data_url_extra_params={};this.data_query_wait=(am?am:M);this.dataset_check_url=converted_datasets_state_url;if(!j.id_counter){j.id_counter=0}this.container_div=$("<div />").addClass("track").attr("id","track_"+j.id_counter++).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.container.content_div.append(this.container_div)};q(j.prototype,r.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof C){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Z){return"ReadTrack"}else{if(this instanceof X){return"ToolDataFeatureTrack"}else{if(this instanceof W){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var ak=ah.view.tracks.indexOf(ah);var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(L)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.make_name_popup_menu()}ah.content_div.text(ab);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}})},predraw_init:function(){},});var O=function(ao,am){var ai=this,ap=ai.view;n(ai.container_div,ai.drag_handle_class,".group",ai);this.filters_manager=new ac(this,(ao!==undefined?ao:{}));this.filters_available=false;this.filters_visible=false;this.tool=(am!==undefined&&obj_length(am)>0?new s(this,am):undefined);this.is_overview=false;if(ai.hidden){return}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(ai.display_modes!==undefined){if(ai.mode_div===undefined){ai.mode_div=$("<div class='right-float menubutton popup' />").appendTo(ai.header_div);var aj=(ai.config&&ai.config.values.mode?ai.config.values.mode:ai.display_modes[0]);ai.mode=aj;ai.mode_div.text(aj);var ah={};for(var ak=0,an=ai.display_modes.length;ak<an;ak++){var al=ai.display_modes[ak];ah[al]=function(aq){return function(){ai.change_mode(aq)}}(al)}make_popupmenu(ai.mode_div,ah)}else{ai.mode_div.hide()}}this.make_name_popup_menu()};q(O.prototype,r.prototype,j.prototype,{to_json:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.config.values.mode=ai;ah.tile_cache.clear();ah.request_draw();return ah},make_name_popup_menu:function(){var ai=this;var ah={};ah[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(ai.is_overview){ai.view.reset_overview()}else{ai.view.set_overview(ai)}};ah["Edit configuration"]=function(){var am=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},al=function(an){if((an.keyCode||an.which)===27){am()}else{if((an.keyCode||an.which)===13){ak()}}};$(window).bind("keypress.check_enter_esc",al);show_modal("Configure Track",ai.config.build_form(),{Cancel:am,OK:ak})};if(ai.filters_available>0){var aj=(ai.filters_div.is(":visible")?"Hide filters":"Show filters");ah[aj]=function(){ai.filters_visible=(ai.filters_div.is(":visible"));if(ai.filters_visible){ai.filters_manager.reset_filters()}ai.filters_div.toggle();ai.make_name_popup_menu()}}if(ai.tool){var aj=(ai.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ah[aj]=function(){if(!ai.dynamic_tool_div.is(":visible")){ai.set_name(ai.name+ai.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";ai.revert_name()}ai.dynamic_tool_div.toggle();ai.make_name_popup_menu()}}ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)},set_is_overview:function(ah){this.is_overview=ah;this.make_name_popup_menu()},get_overview_tile:function(){var ah=this;view=ah.view,resolution=Math.pow(E,Math.ceil(Math.log((view.max_high-view.max_low)/T)/Math.log(E))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ah.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ah.data_url_extra_params)).then(function(ai){var ak=ah._gen_tile_cache_key(view_width,w_scale,0),am=ah.tile_cache.get(ak);if(!am){am=ah.draw_tile(ai,"Auto",resolution,0,w_scale);ah.tile_cache.set(ak,am)}var ap=$(am.canvas.find("canvas")),al=ap.clone(),ao=ap.get(0).getContext("2d"),aj=al.get(0).getContext("2d"),an=ao.getImageData(0,0,ao.canvas.width,ao.canvas.height);aj.putImageData(an,-ah.left_offset,(am.data.dataset_type==="summary_tree"?V:0));new_tile=new b(-1,resolution,al);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!this.enabled){return}if(!(this instanceof C)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/T);var ap=true;var at=[];var ah=0;while((ai*T*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*T*an,ax=ap+T*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);al.tile_cache.set(at,aq);if(aq!==undefined){al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw()});return null},show_tile:function(ao,aq,ar){var aj=this,ai=ao.canvas,an=ai;if(ao.message){var at=$("<div/>"),ap=$("<div/>").addClass("tile-message").text(ao.message).css({height:F-1,width:ao.canvas.width}).appendTo(at),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ap),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ap);at.append(ai);an=at;al.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()});ah.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()})}var am=this.view.high-this.view.low,ak=(ao.low-this.view.low)*ar;if(this.left_offset){ak-=this.left_offset}an.css({position:"absolute",top:0,left:ak,height:""});aq.append(an);aj.max_height=Math.max(aj.max_height,an.height());aj.content_div.css("height",aj.max_height+"px");aq.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*T*ai,al=T*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ai,ah){this.hidden=true;j.call(this,"label",ai,ah,{});this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{init:function(){this.enabled=true},_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var C=function(ah){this.hidden=true;j.call(this,"reference",ah,{content_div:ah.top_labeltrack},{});O.call(this);ah.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:ah.dbkey};this.data_manager=new J(D,this,false);this.tile_cache=new c(v)};q(C.prototype,r.prototype,O.prototype,{init:function(){this.enabled=true},draw_tile:function(ar,an,am,ai,at){var al=this,aj=T*am;if(at>this.view.canvas_manager.char_width_px){if(ar===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(am,ak,aj,an,ah,al){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,am,ak,aj,al);O.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=an;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new U(D,this);this.tile_cache=new c(v);this.left_offset=0;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:am},{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:al,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.track_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.track_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};q(k.prototype,r.prototype,O.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this,ai=ah.view.tracks.indexOf(ah);ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(aj){ah.container_div.addClass("line-track");var al=aj.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=al.min;ah.prefs.max_value=al.max;$("#track_"+ai+"_minval").val(ah.prefs.min_value);$("#track_"+ai+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=al.total_frequency;ah.container_div.find(".yaxislabel").remove();var am=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_minval").text(y(ah.prefs.min_value));var ak=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_maxval").text(y(ah.prefs.max_value));ak.css({position:"absolute",top:"24px",left:"10px"});ak.prependTo(ah.container_div);am.css({position:"absolute",bottom:"2px",left:"10px"});am.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new N.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(aj,al,ak,au.data)}});var e=function(ah,an,ai,am,ap,ao,ak,al){var aj=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];j.call(this,ah,an,ai,ao);O.call(this,ak,al);this.config=new H({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_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){aj.set_name(aj.prefs.name);aj.tile_cache.clear();aj.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=am;this.dataset_id=ap;this.original_dataset_id=ap;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 U(20,this);this.left_offset=200;this.painter=N.LinkedFeaturePainter};q(e.prototype,r.prototype,O.prototype,{postdraw_actions:function(ax,ah,ay,aw){O.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.make_name_popup_menu()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",B,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aE,aI,ar,ak){var aB=this,am=aB._get_tile_bounds(aI,aE),aL=am[0],ai=am[1],ay=ai-aL,aC=Math.ceil(ay*ar),aP=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"){az="no_detail"}else{var aO=aw.data;if(this.view.high-this.view.low>K){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an+V;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aL,ai,200);if(aw.max){at.max=aw.max}aw=at}var aM=new N.SummaryTreePainter(aw,aL,ai,this.prefs);var aD=aj.getContext("2d");aD.translate(al,V);aM.draw(aD,aC,an);return new l(aI,aE,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aF=0,aH=aw.data.length;aF<aH;aF++){var ao=aw.data[aF];var aG=false;var av;for(var aK=0,aN=au.length;aK<aN;aK++){av=au[aK];av.update_attrs(ao);if(!av.keep(ao)){aG=true;break}}if(!aG){aq.push(ao)}}}var aA=(this.filters_manager.alpha_filter?new Q(this.filters_manager.alpha_filter):null);var aM=new (this.painter)(aq,aL,ai,this.prefs,az,aA,ak);var an=Math.max(af,aM.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();var aJ=null;aj.width=aC+al;aj.height=an;var aD=aj.getContext("2d");aD.fillStyle=this.prefs.block_color;aD.font=aD.canvas.manager.default_font;aD.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aD.translate(al,0);aJ=aM.draw(aD,aC,an,ax);aJ.translation=-al}return new R(aI,aE,aj,aw.data,aw.message,aJ)}});var W=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.painter=N.VariantPainter};q(W.prototype,r.prototype,O.prototype,e.prototype);var Z=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{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:ak,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=N.ReadPainter;this.make_name_popup_menu()};q(Z.prototype,r.prototype,O.prototype,e.prototype);var X=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am,{});this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(X.prototype,r.prototype,O.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=M;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});aa.View=ae;aa.DrawableGroup=S;aa.LineTrack=k;aa.FeatureTrack=e;aa.ReadTrack=Z};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,y){var v=k("class").extend;var q=function(J,B,H,A,G,E){if(E===undefined){E=4}var D=A-B;var C=G-H;var F=Math.floor(Math.sqrt(D*D+C*C)/E);var K=D/F;var I=C/F;var z;for(z=0;z<F;z++,B+=K,H+=I){if(z%2!==0){continue}J.fillRect(B,H,E,1)}};var r=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(z){this.default_alpha=(z?z:1)};g.prototype.gen_alpha=function(z){return this.default_alpha};var n=function(B,D,z,A,C){this.data=B;this.view_start=D;this.view_end=z;this.prefs=v({},this.default_prefs,A);this.mode=C};n.prototype.default_prefs={};var w=function(B,D,z,A,C){n.call(this,B,D,z,A,C)};w.prototype.default_prefs={show_counts:false};w.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(z,D,F,G,B){n.call(this,z,D,F,G,B);if(this.prefs.min_value===undefined){var H=Infinity;for(var A=0,C=this.data.length;A<C;A++){H=Math.min(H,this.data[A][1])}this.prefs.min_value=H}if(this.prefs.max_value===undefined){var E=-Infinity;for(var A=0,C=this.data.length;A<C;A++){E=Math.max(E,this.data[A][1])}this.prefs.max_value=E}};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(z){this.feature_positions={};this.slot_height=z;this.translation=0};o.prototype.map_feature_data=function(A,C,z,B){if(!this.feature_positions[C]){this.feature_positions[C]=[]}this.feature_positions[C].push({data:A,x_start:z,x_end:B})};o.prototype.get_feature_data=function(z,D){var C=Math.floor(D/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var p=function(C,E,z,B,D,A){n.call(this,C,E,z,B,D);this.alpha_generator=(A?A:new g())};p.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};v(p.prototype,{get_required_height:function(A){var z=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){z=A*y_scale}return z+Math.max(Math.round(y_scale/2),5)},draw:function(L,J,H,G){var R=this.data,E=this.view_start,N=this.view_end;L.save();L.fillStyle=this.prefs.block_color;L.textAlign="right";var I=this.view_end-this.view_start,F=J/I,M=this.get_row_height(),Q=new o(M),C;for(var O=0,P=R.length;O<P;O++){var B=R[O],D=B[0],K=B[1],z=B[2],A=(G&&G[D]!==undefined?G[D]:null);if((K<N&&z>E)&&(this.mode=="Dense"||A!==null)){C=this.draw_element(L,this.mode,B,A,E,N,F,M,J);Q.map_feature_data(B,A,C[0],C[1])}}L.restore();return Q},draw_element:function(F,B,H,D,C,E,G,A,z){console.log("WARNING: Unimplemented function.");return[0,0]}});var d=10,j=3,m=5,x=10,f=1,t=3,e=3,a=9,l=2,h="#ccc";var s=function(C,E,z,B,D,A){p.call(this,C,E,z,B,D,A)};v(s.prototype,p.prototype,{get_row_height:function(){var A=this.mode,z;if(A==="Dense"){z=d}else{if(A==="no_detail"){z=j}else{if(A==="Squish"){z=m}else{z=x}}}return z},draw_element:function(L,E,T,G,N,ae,ai,ak,z){var Q=T[0],ag=T[1],Y=T[2],O=T[3],Z=Math.floor(Math.max(0,(ag-N)*ai)),M=Math.ceil(Math.min(z,Math.max(0,(Y-N)*ai))),X=Z,aj=M,W=(E==="Dense"?0:(0+G))*ak,K,ac,P=null,al=null,C=this.prefs.block_color,ab=this.prefs.label_color;L.globalAlpha=this.alpha_generator.gen_alpha(T);if(E=="Dense"){G=1}if(E==="no_detail"){L.fillStyle=C;L.fillRect(Z,W+5,M-Z,f)}else{var J=T[4],V=T[5],aa=T[6],D=T[7];if(V&&aa){P=Math.floor(Math.max(0,(V-N)*ai));al=Math.ceil(Math.min(z,Math.max(0,(aa-N)*ai)))}var ah,R;if(E==="Squish"||E==="Dense"){ah=1;R=e}else{ah=5;R=a}if(!D){if(T.strand){if(T.strand==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand_inv")}else{if(T.strand==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand_inv")}}}else{L.fillStyle=C}L.fillRect(Z,W,M-Z,R)}else{var I,S;if(E==="Squish"||E==="Dense"){L.fillStyle=h;I=W+Math.floor(e/2)+1;S=1}else{if(J){var I=W;var S=R;if(J==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand")}else{if(J==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand")}}}else{L.fillStyle=h;I+=(e/2)+1;S=1}}L.fillRect(Z,I,M-Z,S);for(var af=0,B=D.length;af<B;af++){var F=D[af],A=Math.floor(Math.max(0,(F[0]-N)*ai)),U=Math.ceil(Math.min(z,Math.max((F[1]-N)*ai)));if(A>U){continue}L.fillStyle=C;L.fillRect(A,W+(R-ah)/2+1,U-A,ah);if(P!==undefined&&aa>V&&!(A>al||U<P)){var ad=Math.max(A,P),H=Math.min(U,al);L.fillRect(ad,W+1,H-ad,R);if(D.length==1&&E=="Pack"){if(J==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand_inv")}else{if(J==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand_inv")}}if(ad+14<H){ad+=2;H-=2}L.fillRect(ad,W+1,H-ad,R)}}}}if(E==="Pack"&&ag>N){L.fillStyle=ab;if(N===0&&Z-L.measureText(O).width<0){L.textAlign="left";L.fillText(O,M+l,W+8);aj+=L.measureText(O).width+l}else{L.textAlign="right";L.fillText(O,Z-l,W+8);X-=L.measureText(O).width+l}}}L.globalAlpha=1;return[X,aj]}});var b=function(C,E,z,B,D,A){p.call(this,C,E,z,B,D,A)};v(b.prototype,p.prototype,{draw_element:function(S,N,H,D,V,B,K,T,Q){var H=data[i],J=H[0],R=H[1],C=H[2],M=H[3],F=Math.floor(Math.max(0,(R-V)*K)),I=Math.ceil(Math.min(Q,Math.max(0,(C-V)*K))),E=(N==="Dense"?0:(0+D))*T,z,W,A=null,L=null;if(no_label){S.fillStyle=block_color;S.fillRect(F+left_offset,E+5,I-F,1)}else{var U=H[4],P=H[5],G=H[6];z=9;W=1;S.fillRect(F+left_offset,E,I-F,z);if(N!=="Dense"&&M!==undefined&&R>V){S.fillStyle=label_color;if(V===0&&F-S.measureText(M).width<0){S.textAlign="left";S.fillText(M,I+2+left_offset,E+8)}else{S.textAlign="right";S.fillText(M,F-2+left_offset,E+8)}S.fillStyle=block_color}var O=U+" / "+P;if(R>V&&S.measureText(O).width<(I-F)){S.fillStyle="white";S.textAlign="center";S.fillText(O,left_offset+F+(I-F)/2,E+8);S.fillStyle=block_color}}return[F,I]}});var u=function(D,F,z,C,E,A,B){p.call(this,D,F,z,C,E,A);this.ref_seq=B};u.prototype.default_prefs=v({},p.prototype.default_prefs,{show_insertions:false});v(u.prototype,p.prototype,{get_row_height:function(){var z,A=this.mode;if(A==="Dense"){z=d}else{if(A==="Squish"){z=m}else{z=x;if(this.prefs.show_insertions){z*=2}}}return z},draw_read:function(V,Q,M,aa,B,U,J,G,F){V.textAlign="center";var T=this,A=[aa,B],P=0,W=0,S=0;ref_seq=this.ref_seq,char_width_px=V.canvas.manager.char_width_px;var af=[];if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){S=Math.round(M/2)}if(!J){J=[[0,G.length]]}for(var N=0,Y=J.length;N<Y;N++){var K=J[N],C="MIDNSHP=X"[K[0]],O=K[1];if(C==="H"||C==="S"){P-=O}var H=U+P,ae=Math.floor(Math.max(0,(H-aa)*M)),I=Math.floor(Math.max(0,(H+O-aa)*M));if(ae===I){I+=1}switch(C){case"H":break;case"S":case"M":case"=":if(is_overlap([H,H+O],A)){var R=G.slice(W,W+O);if(S>0){V.fillStyle=this.prefs.block_color;V.fillRect(ae-S,F+1,I-ae,9);V.fillStyle=h;for(var ac=0,z=R.length;ac<z;ac++){if(this.prefs.show_differences&&ref_seq){var L=ref_seq[H-aa+ac];if(!L||L.toLowerCase()===R[ac].toLowerCase()){continue}}if(H+ac>=aa&&H+ac<=B){var ad=Math.floor(Math.max(0,(H+ac-aa)*M));V.fillText(R[ac],ad,F+9)}}}else{V.fillStyle=this.prefs.block_color;V.fillRect(ae,F+4,I-ae,e)}}W+=O;P+=O;break;case"N":V.fillStyle=h;V.fillRect(ae-S,F+5,I-ae,1);P+=O;break;case"D":V.fillStyle="red";V.fillRect(ae-S,F+4,I-ae,3);P+=O;break;case"P":break;case"I":var Z=ae-S;if(is_overlap([H,H+O],A)){var R=G.slice(W,W+O);if(this.prefs.show_insertions){var E=ae-(I-ae)/2;if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){V.fillStyle="yellow";V.fillRect(E-S,F-9,I-ae,9);af[af.length]={type:"triangle",data:[Z,F+4,5]};V.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):R=R.slice(aa-H);break;case (OVERLAP_END):R=R.slice(0,H-B);break;case (CONTAINED_BY):break;case (CONTAINS):R=R.slice(aa-H,H-B);break}for(var ac=0,z=R.length;ac<z;ac++){var ad=Math.floor(Math.max(0,(H+ac-aa)*M));V.fillText(R[ac],ad-(I-ae)/2,F)}}else{V.fillStyle="yellow";V.fillRect(E,F+(this.mode!=="Dense"?2:5),I-ae,(Q!=="Dense"?e:t))}}else{if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){af[af.length]={type:"text",data:[R.length,Z,F+9]}}else{}}}W+=O;break;case"X":W+=O;break}}V.fillStyle="yellow";var ab,D,ag;for(var X=0;X<af.length;X++){ab=af[X];D=ab.type;ag=ab.data;if(D==="text"){V.save();V.font="bold "+V.font;V.fillText(ag[0],ag[1],ag[2]);V.restore()}else{if(D=="triangle"){r(V,ag[0],ag[1],ag[2])}}}},draw_element:function(S,N,F,C,V,A,J,T,Q){var I=F[0],R=F[1],B=F[2],K=F[3],E=Math.floor(Math.max(0,(R-V)*J)),G=Math.ceil(Math.min(Q,Math.max(0,(B-V)*J))),D=(N==="Dense"?0:(0+C))*T,W=this.prefs.block_color,H=this.prefs.label_color,P=0;if((N==="Pack"||this.mode==="Auto")&&J>S.canvas.manager.char_width_px){var P=Math.round(J/2)}S.fillStyle=W;if(F[5] instanceof Array){var O=Math.floor(Math.max(0,(F[4][0]-V)*J)),M=Math.ceil(Math.min(Q,Math.max(0,(F[4][1]-V)*J))),L=Math.floor(Math.max(0,(F[5][0]-V)*J)),z=Math.ceil(Math.min(Q,Math.max(0,(F[5][1]-V)*J)));if(F[4][1]>=V&&F[4][0]<=A&&F[4][2]){this.draw_read(S,N,J,V,A,F[4][0],F[4][2],F[4][3],D)}if(F[5][1]>=V&&F[5][0]<=A&&F[5][2]){this.draw_read(S,N,J,V,A,F[5][0],F[5][2],F[5][3],D)}if(L>M){S.fillStyle=h;q(S,M-P,D+5,L-P,D+5)}}else{S.fillStyle=W;this.draw_read(S,N,J,V,A,R,F[4],F[5],D)}if(N==="Pack"&&R>V){S.fillStyle=this.prefs.label_color;var U=1;if(U===0&&E-S.measureText(K).width<0){S.textAlign="left";S.fillText(K,G+l-P,D+8)}else{S.textAlign="right";S.fillText(K,E-l-P,D+8)}S.fillStyle=W}return[0,0]}});y.AlphaGenerator=g;y.SummaryTreePainter=w;y.LinePainter=c;y.LinkedFeaturePainter=s;y.ReadPainter=u;y.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,aa){var q=f("class").extend,t=f("slotting"),N=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"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")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}if(ar.container){ar.container.remove_drawable(ar)}o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};aa.moveable=n;var af=16,I=9,F=20,V=I+2,B=100,K=12000,T=200,E=5,w=10,M=5000,x=100,p="There was an error in indexing this dataset. ",L="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",z="Tool cannot be rerun: ",a="Loading data...",ab="Ready for display",d=10,v=5,D=5;function y(ah){return Math.round(ah*1000)/1000}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var U=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(U.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var J=function(ai,ah,aj){U.call(this,ai,ah,aj)};q(J.prototype,U.prototype,c.prototype,{load_data:function(aj,ah,al,am,ai,ak){if(ai>1){return}return U.prototype.load_data.call(this,aj,ah,al,am,ai,ak)}});var r=function(ak,ai,ah,aj,al){this.name=ak;this.view=ai;this.container=ah;this.drag_handle_class=al;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak}],saved_values:aj,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values};q(r.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},make_name_popup_menu:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var A=function(al,ak,ai,ah,aj,am){r.call(this,ak,ai,ah,aj,am);this.obj_type=al;this.drawables=[]};q(A.prototype,r.prototype,{init:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah].init()}},_draw:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah]._draw()}},to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){ai.push(this.drawables[ah].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ai}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var S=function(ak,ai,ah,aj){A.call(this,"DrawableGroup",ak,ai,ah,aj,"group-handle");if(!S.id_counter){S.id_counter=0}var al=S.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+al).appendTo(this.container.content_div);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+al+"_content_div").appendTo(this.container_div);m(this.container_div,this);m(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.make_name_popup_menu()};q(S.prototype,r.prototype,A.prototype,{make_name_popup_menu:function(){var ai=this;var ah={};ah["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){ai.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 Group",ai.config.build_form(),{Cancel:al,OK:aj})};ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)}});var ae=function(ah,ak,aj,ai){A.call(this,"View");this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;this.tracks=this.drawables;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.init();this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,A.prototype,{init:function(){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<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 ai=function(al){if(al.type==="focusout"||(al.keyCode||al.which)===13||(al.keyCode||al.which)===27){if((al.keyCode||al.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.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(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.browser_content_div.click(function(al){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(al){ah.zoom_in(al.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(al,am){this.current_x=am.offsetX}).bind("drag",function(al,an){var ao=an.offsetX-this.current_x;this.current_x=an.offsetX;var am=Math.round(ao/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-am)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(al,am){if(al.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(al,am){am.original_low=ah.low;am.current_height=al.clientY;am.current_x=am.offsetX}).bind("drag",function(an,ap){var al=$(this);var aq=ap.offsetX-ap.current_x;var am=al.scrollTop()-(an.clientY-ap.current_height);al.scrollTop(am);ap.current_height=an.clientY;ap.current_x=ap.offsetX;var ao=Math.round(aq/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}).bind("mousewheel",function(an,ap,am,al){if(am){var ao=Math.round(-am/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}});this.top_labeltrack.bind("dragstart",function(al,am){return $("<div />").css({height:ah.browser_content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ap,aq){$(aq.proxy).css({left:Math.min(ap.pageX,aq.startX),width:Math.abs(ap.pageX-aq.startX)});var am=Math.min(ap.pageX,aq.startX)-ah.container.offset().left,al=Math.max(ap.pageX,aq.startX)-ah.container.offset().left,ao=(ah.high-ah.low),an=ah.viewport_container.width();ah.update_location(Math.round(am/an*ao)+ah.low,Math.round(al/an*ao)+ah.low)}).bind("dragend",function(aq,ar){var am=Math.min(aq.pageX,ar.startX),al=Math.max(aq.pageX,ar.startX),ao=(ah.high-ah.low),an=ah.viewport_container.width(),ap=ah.low;ah.low=Math.round(am/an*ao)+ap;ah.high=Math.round(al/an*ao)+ap;$(ar.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,{content_div:this.top_labeltrack}));this.add_label_track(new ad(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(aj){aj.num=x;$.extend(aj,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this,ai=$.Deferred();$.ajax({url:chrom_url,data:aj,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+aj.chrom);return}if(al.reference){ah.add_label_track(new C(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);ah.chrom_start_index=al.start_index;ai.resolve(al)},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}});return ai},change_chrom:function(al,ai,an){if(!al||al==="None"){return}var ak=this;if(al==="previous"){ak.load_chroms({low:this.chrom_start_index-x});return}if(al==="next"){ak.load_chroms({low:this.chrom_start_index+x});return}var am=$.grep(ak.chrom_data,function(ap,aq){return ap.chrom===al})[0];if(am===undefined){ak.load_chroms({chrom:al},function(){ak.change_chrom(al,ai,an)});return}else{if(al!==ak.chrom){ak.chrom=al;ak.chrom_select.val(ak.chrom);ak.max_high=am.len-1;ak.reset();ak.request_redraw(true);for(var ao=0,ah=ak.tracks.length;ao<ah;ao++){var aj=ak.tracks[ao];if(aj.init){aj.init()}}}if(ai!==undefined&&an!==undefined){ak.low=Math.max(ai,0);ak.high=Math.min(an,ak.max_high)}ak.reset_overview();ak.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_drawable:function(ah){A.prototype.add_drawable.call(this,ah);ah.init();this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;ah.init();this.label_tracks.push(ah)},remove_drawable:function(aj,ai){A.prototype.remove_drawable.call(this,aj);if(ai){var ah=this;aj.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.tracks),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(E,Math.ceil(Math.log((this.high-this.low)/T)/Math.log(E)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);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(ah){$.when(ah.get_overview_tile()).then(function(ai){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(ai.canvas);view.overview_highlight.show().height(ai.canvas.height());view.overview_viewport.height(ai.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ah;ah.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 s=function(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new P(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai={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},al=this.track,aj=ai.tool_id+al.tool_region_and_parameters_str(ai.chrom,ai.low,ai.high),ah,am;if(al.container===view){var ak=new S(this.name,this.track.view,this.track.container);al.container.add_drawable(ak);al.container.remove_drawable(al);ak.add_drawable(al);al.container_div.appendTo(ak.content_div);ah=ak}else{ah=al.container}if(al instanceof e){am=new X(aj,view,ah,"hda");am.change_mode(al.mode);ah.add_drawable(am)}am.content_div.text("Starting job.");this.run(ai,am,function(an){am.dataset_id=an.dataset_id;am.content_div.text("Running job.");am.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(L)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(z+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var P=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){P.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var Y=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);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};q(Y.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=parseFloat(ah[this.index]);return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(ar,ay){this.track=ar;this.filters=[];for(var at=0;at<ay.length;at++){var au=ay[at],az=au.name,ah=au.type,ak=au.index,ax=au.tool_id,aw=au.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[at]=new Y(az,ak,ax,aw)}else{console.log("ERROR: unsupported filter: ",az,ah)}}var al=function(aA,aB,aC){aA.click(function(){var aD=aB.text();max=parseFloat(aC.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aC.slider("option","values")){input_size=2*input_size+1;multi_value=true}aB.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aD).appendTo(aB).focus().select().click(function(aE){aE.stopPropagation()}).blur(function(){$(this).remove();aB.text(aD)}).keyup(function(aI){if(aI.keyCode===27){$(this).trigger("blur")}else{if(aI.keyCode===13){var aG=aC.slider("option","min"),aE=aC.slider("option","max"),aH=function(aJ){return(isNaN(aJ)||aJ>aE||aJ<aG)},aF=$(this).val();if(!multi_value){aF=parseFloat(aF);if(aH(aF)){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}else{aF=aF.split("-");aF=[parseFloat(aF[0]),parseFloat(aF[1])];if(aH(aF[0])||aH(aF[1])){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}aC.slider((multi_value?"values":"value"),aF)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aA){aA.stopPropagation()}).click(function(aA){aA.stopPropagation()}).bind("dblclick",function(aA){aA.stopPropagation()}).bind("keydown",function(aA){aA.stopPropagation()});var av=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aD,aF){aF.container=$("<div/>").addClass("slider-row").appendTo(av);var aE=$("<div/>").addClass("elt-label").appendTo(aF.container);var aC=$("<span/>").addClass("slider-name").text(aF.name+" ").appendTo(aE);var aB=$("<span/>");var aH=$("<span/>").addClass("slider-value").appendTo(aE).append("[").append(aB).append("]");var aA=$("<div/>").addClass("slider").appendTo(aF.container);aF.control_element=$("<div/>").attr("id",aF.name+"-filter-control").appendTo(aA);var aG=[0,0];aF.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aJ,aK){var aI=aK.values;aB.text(aI[0]+"-"+aI[1]);aF.low=aI[0];aF.high=aI[1];ap.track.request_draw(true,true)},change:function(aI,aJ){aF.control_element.slider("option","slide").call(aF.control_element,aI,aJ)}});aF.slider=aF.control_element;aF.slider_label=aB;al(aH,aB,aF.control_element);$("<div style='clear: both;'/>").appendTo(aF.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(av);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var aj=this;ao.click(function(){aj.run_on_dataset()})}var aq=$("<div/>").addClass("display-controls").appendTo(this.parent_div),an=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(aq),ai=$("<select/>").attr("name","alpha_dropdown").appendTo(aq);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(ai);for(var at=0;at<this.filters.length;at++){$("<option/>").attr("value",at).text(this.filters[at].name).appendTo(ai)}ai.change(function(){$(this).children("option:selected").each(function(){var aA=parseInt($(this).val());ap.alpha_filter=(aA>=0?ap.filters[aA]:null);ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var Q=function(ai,ah){N.AlphaGenerator.call(this,ah);this.filter=ai};Q.prototype.gen_alpha=function(ah){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(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var H=function(ah){this.track=ah.track;this.params=ah.params;this.values={};this.restore_values((ah.saved_values?ah.saved_values:{}));this.onchange=ah.onchange};q(H.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(aj,ai,ah,ak){this.index=aj;this.low=aj*T*ai;this.high=(aj+1)*T*ai;this.resolution=ai;this.canvas=$("<div class='track-tile'/>").append(ah);this.data=ak;this.stale=false};var l=function(aj,ai,ah,ak,al){b.call(this,aj,ai,ah,ak);this.max_val=al};var R=function(ak,aj,ai,an,am,ah){b.call(this,ak,aj,ai,an);this.message=am;this.feature_mapper=ah;var al=this;$(this.canvas).mousemove(function(ap){var ao=al.feature_mapper.get_feature_data(ap.offsetX,ap.offsetY)})};var j=function(ak,ai,ah,aj,al,am){r.call(this,ak,ai,ah,{},"draghandle");this.data_url=(al?al:default_data_url);this.data_url_extra_params={};this.data_query_wait=(am?am:M);this.dataset_check_url=converted_datasets_state_url;if(!j.id_counter){j.id_counter=0}this.container_div=$("<div />").addClass("track").attr("id","track_"+j.id_counter++).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.container.content_div.append(this.container_div)};q(j.prototype,r.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof C){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Z){return"ReadTrack"}else{if(this instanceof X){return"ToolDataFeatureTrack"}else{if(this instanceof W){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var ak=ah.view.tracks.indexOf(ah);var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(L)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.make_name_popup_menu()}ah.content_div.text(ab);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}})},predraw_init:function(){},});var O=function(ao,am){var ai=this,ap=ai.view;n(ai.container_div,ai.drag_handle_class,".group",ai);this.filters_manager=new ac(this,(ao!==undefined?ao:{}));this.filters_available=false;this.filters_visible=false;this.tool=(am!==undefined&&obj_length(am)>0?new s(this,am):undefined);this.is_overview=false;if(ai.hidden){return}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(ai.display_modes!==undefined){if(ai.mode_div===undefined){ai.mode_div=$("<div class='right-float menubutton popup' />").appendTo(ai.header_div);var aj=(ai.config&&ai.config.values.mode?ai.config.values.mode:ai.display_modes[0]);ai.mode=aj;ai.mode_div.text(aj);var ah={};for(var ak=0,an=ai.display_modes.length;ak<an;ak++){var al=ai.display_modes[ak];ah[al]=function(aq){return function(){ai.change_mode(aq)}}(al)}make_popupmenu(ai.mode_div,ah)}else{ai.mode_div.hide()}}this.make_name_popup_menu()};q(O.prototype,r.prototype,j.prototype,{to_json:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.config.values.mode=ai;ah.tile_cache.clear();ah.request_draw();return ah},make_name_popup_menu:function(){var ai=this;var ah={};ah[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(ai.is_overview){ai.view.reset_overview()}else{ai.view.set_overview(ai)}};ah["Edit configuration"]=function(){var am=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},al=function(an){if((an.keyCode||an.which)===27){am()}else{if((an.keyCode||an.which)===13){ak()}}};$(window).bind("keypress.check_enter_esc",al);show_modal("Configure Track",ai.config.build_form(),{Cancel:am,OK:ak})};if(ai.filters_available>0){var aj=(ai.filters_div.is(":visible")?"Hide filters":"Show filters");ah[aj]=function(){ai.filters_visible=(ai.filters_div.is(":visible"));if(ai.filters_visible){ai.filters_manager.reset_filters()}ai.filters_div.toggle();ai.make_name_popup_menu()}}if(ai.tool){var aj=(ai.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ah[aj]=function(){if(!ai.dynamic_tool_div.is(":visible")){ai.set_name(ai.name+ai.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";ai.revert_name()}ai.dynamic_tool_div.toggle();ai.make_name_popup_menu()}}ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)},set_is_overview:function(ah){this.is_overview=ah;this.make_name_popup_menu()},get_overview_tile:function(){var ah=this;view=ah.view,resolution=Math.pow(E,Math.ceil(Math.log((view.max_high-view.max_low)/T)/Math.log(E))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ah.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ah.data_url_extra_params)).then(function(ai){var ak=ah._gen_tile_cache_key(view_width,w_scale,0),am=ah.tile_cache.get(ak);if(!am){am=ah.draw_tile(ai,"Auto",resolution,0,w_scale);ah.tile_cache.set(ak,am)}var ap=$(am.canvas.find("canvas")),al=ap.clone(),ao=ap.get(0).getContext("2d"),aj=al.get(0).getContext("2d"),an=ao.getImageData(0,0,ao.canvas.width,ao.canvas.height);aj.putImageData(an,-ah.left_offset,(am.data.dataset_type==="summary_tree"?V:0));new_tile=new b(-1,resolution,al);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!this.enabled){return}if(!(this instanceof C)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/T);var ap=true;var at=[];var ah=0;while((ai*T*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*T*an,ax=ap+T*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);if(aq!==undefined){al.tile_cache.set(at,aq);al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw()});return null},show_tile:function(ao,aq,ar){var aj=this,ai=ao.canvas,an=ai;if(ao.message){var at=$("<div/>"),ap=$("<div/>").addClass("tile-message").text(ao.message).css({height:F-1,width:ao.canvas.width}).appendTo(at),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ap),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ap);at.append(ai);an=at;al.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()});ah.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()})}var am=this.view.high-this.view.low,ak=(ao.low-this.view.low)*ar;if(this.left_offset){ak-=this.left_offset}an.css({position:"absolute",top:0,left:ak,height:""});aq.append(an);aj.max_height=Math.max(aj.max_height,an.height());aj.content_div.css("height",aj.max_height+"px");aq.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*T*ai,al=T*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ai,ah){this.hidden=true;j.call(this,"label",ai,ah,{});this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{init:function(){this.enabled=true},_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var C=function(ah){this.hidden=true;j.call(this,"reference",ah,{content_div:ah.top_labeltrack},{});O.call(this);ah.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:ah.dbkey};this.data_manager=new J(D,this,false);this.tile_cache=new c(v)};q(C.prototype,r.prototype,O.prototype,{init:function(){this.enabled=true},draw_tile:function(ar,an,am,ai,at){var al=this,aj=T*am;if(at>this.view.canvas_manager.char_width_px){if(ar===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(am,ak,aj,an,ah,al){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,am,ak,aj,al);O.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=an;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new U(D,this);this.tile_cache=new c(v);this.left_offset=0;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:am},{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:al,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.track_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.track_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};q(k.prototype,r.prototype,O.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this,ai=ah.view.tracks.indexOf(ah);ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(aj){ah.container_div.addClass("line-track");var al=aj.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=al.min;ah.prefs.max_value=al.max;$("#track_"+ai+"_minval").val(ah.prefs.min_value);$("#track_"+ai+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=al.total_frequency;ah.container_div.find(".yaxislabel").remove();var am=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_minval").text(y(ah.prefs.min_value));var ak=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_maxval").text(y(ah.prefs.max_value));ak.css({position:"absolute",top:"24px",left:"10px"});ak.prependTo(ah.container_div);am.css({position:"absolute",bottom:"2px",left:"10px"});am.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new N.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(aj,al,ak,au.data)}});var e=function(ah,an,ai,am,ap,ao,ak,al){var aj=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];j.call(this,ah,an,ai,ao);O.call(this,ak,al);this.config=new H({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_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){aj.set_name(aj.prefs.name);aj.tile_cache.clear();aj.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=am;this.dataset_id=ap;this.original_dataset_id=ap;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 U(20,this);this.left_offset=200;this.painter=N.LinkedFeaturePainter};q(e.prototype,r.prototype,O.prototype,{postdraw_actions:function(ax,ah,ay,aw){O.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.make_name_popup_menu()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",B,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aE,aI,ar,ak){var aB=this,am=aB._get_tile_bounds(aI,aE),aL=am[0],ai=am[1],ay=ai-aL,aC=Math.ceil(ay*ar),aP=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"){az="no_detail"}else{var aO=aw.data;if(this.view.high-this.view.low>K){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an+V;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aL,ai,200);if(aw.max){at.max=aw.max}aw=at}var aM=new N.SummaryTreePainter(aw,aL,ai,this.prefs);var aD=aj.getContext("2d");aD.translate(al,V);aM.draw(aD,aC,an);return new l(aI,aE,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aF=0,aH=aw.data.length;aF<aH;aF++){var ao=aw.data[aF];var aG=false;var av;for(var aK=0,aN=au.length;aK<aN;aK++){av=au[aK];av.update_attrs(ao);if(!av.keep(ao)){aG=true;break}}if(!aG){aq.push(ao)}}}var aA=(this.filters_manager.alpha_filter?new Q(this.filters_manager.alpha_filter):null);var aM=new (this.painter)(aq,aL,ai,this.prefs,az,aA,ak);var an=Math.max(af,aM.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();var aJ=null;aj.width=aC+al;aj.height=an;var aD=aj.getContext("2d");aD.fillStyle=this.prefs.block_color;aD.font=aD.canvas.manager.default_font;aD.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aD.translate(al,0);aJ=aM.draw(aD,aC,an,ax);aJ.translation=-al}return new R(aI,aE,aj,aw.data,aw.message,aJ)}});var W=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.painter=N.VariantPainter};q(W.prototype,r.prototype,O.prototype,e.prototype);var Z=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{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:ak,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=N.ReadPainter;this.make_name_popup_menu()};q(Z.prototype,r.prototype,O.prototype,e.prototype);var X=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am,{});this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(X.prototype,r.prototype,O.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=M;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});aa.View=ae;aa.DrawableGroup=S;aa.LineTrack=k;aa.FeatureTrack=e;aa.ReadTrack=Z};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,y){var v=k("class").extend;var q=function(J,B,H,A,G,E){if(E===undefined){E=4}var D=A-B;var C=G-H;var F=Math.floor(Math.sqrt(D*D+C*C)/E);var K=D/F;var I=C/F;var z;for(z=0;z<F;z++,B+=K,H+=I){if(z%2!==0){continue}J.fillRect(B,H,E,1)}};var r=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(z){this.default_alpha=(z?z:1)};g.prototype.gen_alpha=function(z){return this.default_alpha};var n=function(B,D,z,A,C){this.data=B;this.view_start=D;this.view_end=z;this.prefs=v({},this.default_prefs,A);this.mode=C};n.prototype.default_prefs={};var w=function(B,D,z,A,C){n.call(this,B,D,z,A,C)};w.prototype.default_prefs={show_counts:false};w.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(z,D,F,G,B){n.call(this,z,D,F,G,B);if(this.prefs.min_value===undefined){var H=Infinity;for(var A=0,C=this.data.length;A<C;A++){H=Math.min(H,this.data[A][1])}this.prefs.min_value=H}if(this.prefs.max_value===undefined){var E=-Infinity;for(var A=0,C=this.data.length;A<C;A++){E=Math.max(E,this.data[A][1])}this.prefs.max_value=E}};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(z){this.feature_positions={};this.slot_height=z;this.translation=0};o.prototype.map_feature_data=function(A,C,z,B){if(!this.feature_positions[C]){this.feature_positions[C]=[]}this.feature_positions[C].push({data:A,x_start:z,x_end:B})};o.prototype.get_feature_data=function(z,D){var C=Math.floor(D/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var p=function(C,E,z,B,D,A){n.call(this,C,E,z,B,D);this.alpha_generator=(A?A:new g())};p.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};v(p.prototype,{get_required_height:function(A){var z=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){z=A*y_scale}return z+Math.max(Math.round(y_scale/2),5)},draw:function(L,J,H,G){var R=this.data,E=this.view_start,N=this.view_end;L.save();L.fillStyle=this.prefs.block_color;L.textAlign="right";var I=this.view_end-this.view_start,F=J/I,M=this.get_row_height(),Q=new o(M),C;for(var O=0,P=R.length;O<P;O++){var B=R[O],D=B[0],K=B[1],z=B[2],A=(G&&G[D]!==undefined?G[D]:null);if((K<N&&z>E)&&(this.mode=="Dense"||A!==null)){C=this.draw_element(L,this.mode,B,A,E,N,F,M,J);Q.map_feature_data(B,A,C[0],C[1])}}L.restore();return Q},draw_element:function(F,B,H,D,C,E,G,A,z){console.log("WARNING: Unimplemented function.");return[0,0]}});var d=10,j=3,m=5,x=10,f=1,t=3,e=3,a=9,l=2,h="#ccc";var s=function(C,E,z,B,D,A){p.call(this,C,E,z,B,D,A)};v(s.prototype,p.prototype,{get_row_height:function(){var A=this.mode,z;if(A==="Dense"){z=d}else{if(A==="no_detail"){z=j}else{if(A==="Squish"){z=m}else{z=x}}}return z},draw_element:function(L,E,T,G,N,ae,ai,ak,z){var Q=T[0],ag=T[1],Y=T[2],O=T[3],Z=Math.floor(Math.max(0,(ag-N)*ai)),M=Math.ceil(Math.min(z,Math.max(0,(Y-N)*ai))),X=Z,aj=M,W=(E==="Dense"?0:(0+G))*ak,K,ac,P=null,al=null,C=this.prefs.block_color,ab=this.prefs.label_color;L.globalAlpha=this.alpha_generator.gen_alpha(T);if(E=="Dense"){G=1}if(E==="no_detail"){L.fillStyle=C;L.fillRect(Z,W+5,M-Z,f)}else{var J=T[4],V=T[5],aa=T[6],D=T[7];if(V&&aa){P=Math.floor(Math.max(0,(V-N)*ai));al=Math.ceil(Math.min(z,Math.max(0,(aa-N)*ai)))}var ah,R;if(E==="Squish"||E==="Dense"){ah=1;R=e}else{ah=5;R=a}if(!D){if(T.strand){if(T.strand==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand_inv")}else{if(T.strand==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand_inv")}}}else{L.fillStyle=C}L.fillRect(Z,W,M-Z,R)}else{var I,S;if(E==="Squish"||E==="Dense"){L.fillStyle=h;I=W+Math.floor(e/2)+1;S=1}else{if(J){var I=W;var S=R;if(J==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand")}else{if(J==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand")}}}else{L.fillStyle=h;I+=(e/2)+1;S=1}}L.fillRect(Z,I,M-Z,S);for(var af=0,B=D.length;af<B;af++){var F=D[af],A=Math.floor(Math.max(0,(F[0]-N)*ai)),U=Math.ceil(Math.min(z,Math.max((F[1]-N)*ai)));if(A>U){continue}L.fillStyle=C;L.fillRect(A,W+(R-ah)/2+1,U-A,ah);if(P!==undefined&&aa>V&&!(A>al||U<P)){var ad=Math.max(A,P),H=Math.min(U,al);L.fillRect(ad,W+1,H-ad,R);if(D.length==1&&E=="Pack"){if(J==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand_inv")}else{if(J==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand_inv")}}if(ad+14<H){ad+=2;H-=2}L.fillRect(ad,W+1,H-ad,R)}}}}if(E==="Pack"&&ag>N){L.fillStyle=ab;if(N===0&&Z-L.measureText(O).width<0){L.textAlign="left";L.fillText(O,M+l,W+8);aj+=L.measureText(O).width+l}else{L.textAlign="right";L.fillText(O,Z-l,W+8);X-=L.measureText(O).width+l}}}L.globalAlpha=1;return[X,aj]}});var b=function(C,E,z,B,D,A){p.call(this,C,E,z,B,D,A)};v(b.prototype,p.prototype,{draw_element:function(S,N,H,D,V,B,K,T,Q){var H=data[i],J=H[0],R=H[1],C=H[2],M=H[3],F=Math.floor(Math.max(0,(R-V)*K)),I=Math.ceil(Math.min(Q,Math.max(0,(C-V)*K))),E=(N==="Dense"?0:(0+D))*T,z,W,A=null,L=null;if(no_label){S.fillStyle=block_color;S.fillRect(F+left_offset,E+5,I-F,1)}else{var U=H[4],P=H[5],G=H[6];z=9;W=1;S.fillRect(F+left_offset,E,I-F,z);if(N!=="Dense"&&M!==undefined&&R>V){S.fillStyle=label_color;if(V===0&&F-S.measureText(M).width<0){S.textAlign="left";S.fillText(M,I+2+left_offset,E+8)}else{S.textAlign="right";S.fillText(M,F-2+left_offset,E+8)}S.fillStyle=block_color}var O=U+" / "+P;if(R>V&&S.measureText(O).width<(I-F)){S.fillStyle="white";S.textAlign="center";S.fillText(O,left_offset+F+(I-F)/2,E+8);S.fillStyle=block_color}}return[F,I]}});var u=function(D,F,z,C,E,A,B){p.call(this,D,F,z,C,E,A);this.ref_seq=B};u.prototype.default_prefs=v({},p.prototype.default_prefs,{show_insertions:false});v(u.prototype,p.prototype,{get_row_height:function(){var z,A=this.mode;if(A==="Dense"){z=d}else{if(A==="Squish"){z=m}else{z=x;if(this.prefs.show_insertions){z*=2}}}return z},draw_read:function(V,Q,M,aa,B,U,J,G,F){V.textAlign="center";var T=this,A=[aa,B],P=0,W=0,S=0;ref_seq=this.ref_seq,char_width_px=V.canvas.manager.char_width_px;var af=[];if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){S=Math.round(M/2)}if(!J){J=[[0,G.length]]}for(var N=0,Y=J.length;N<Y;N++){var K=J[N],C="MIDNSHP=X"[K[0]],O=K[1];if(C==="H"||C==="S"){P-=O}var H=U+P,ae=Math.floor(Math.max(0,(H-aa)*M)),I=Math.floor(Math.max(0,(H+O-aa)*M));if(ae===I){I+=1}switch(C){case"H":break;case"S":case"M":case"=":if(is_overlap([H,H+O],A)){var R=G.slice(W,W+O);if(S>0){V.fillStyle=this.prefs.block_color;V.fillRect(ae-S,F+1,I-ae,9);V.fillStyle=h;for(var ac=0,z=R.length;ac<z;ac++){if(this.prefs.show_differences&&ref_seq){var L=ref_seq[H-aa+ac];if(!L||L.toLowerCase()===R[ac].toLowerCase()){continue}}if(H+ac>=aa&&H+ac<=B){var ad=Math.floor(Math.max(0,(H+ac-aa)*M));V.fillText(R[ac],ad,F+9)}}}else{V.fillStyle=this.prefs.block_color;V.fillRect(ae,F+4,I-ae,e)}}W+=O;P+=O;break;case"N":V.fillStyle=h;V.fillRect(ae-S,F+5,I-ae,1);P+=O;break;case"D":V.fillStyle="red";V.fillRect(ae-S,F+4,I-ae,3);P+=O;break;case"P":break;case"I":var Z=ae-S;if(is_overlap([H,H+O],A)){var R=G.slice(W,W+O);if(this.prefs.show_insertions){var E=ae-(I-ae)/2;if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){V.fillStyle="yellow";V.fillRect(E-S,F-9,I-ae,9);af[af.length]={type:"triangle",data:[Z,F+4,5]};V.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):R=R.slice(aa-H);break;case (OVERLAP_END):R=R.slice(0,H-B);break;case (CONTAINED_BY):break;case (CONTAINS):R=R.slice(aa-H,H-B);break}for(var ac=0,z=R.length;ac<z;ac++){var ad=Math.floor(Math.max(0,(H+ac-aa)*M));V.fillText(R[ac],ad-(I-ae)/2,F)}}else{V.fillStyle="yellow";V.fillRect(E,F+(this.mode!=="Dense"?2:5),I-ae,(Q!=="Dense"?e:t))}}else{if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){af[af.length]={type:"text",data:[R.length,Z,F+9]}}else{}}}W+=O;break;case"X":W+=O;break}}V.fillStyle="yellow";var ab,D,ag;for(var X=0;X<af.length;X++){ab=af[X];D=ab.type;ag=ab.data;if(D==="text"){V.save();V.font="bold "+V.font;V.fillText(ag[0],ag[1],ag[2]);V.restore()}else{if(D=="triangle"){r(V,ag[0],ag[1],ag[2])}}}},draw_element:function(S,N,F,C,V,A,J,T,Q){var I=F[0],R=F[1],B=F[2],K=F[3],E=Math.floor(Math.max(0,(R-V)*J)),G=Math.ceil(Math.min(Q,Math.max(0,(B-V)*J))),D=(N==="Dense"?0:(0+C))*T,W=this.prefs.block_color,H=this.prefs.label_color,P=0;if((N==="Pack"||this.mode==="Auto")&&J>S.canvas.manager.char_width_px){var P=Math.round(J/2)}S.fillStyle=W;if(F[5] instanceof Array){var O=Math.floor(Math.max(0,(F[4][0]-V)*J)),M=Math.ceil(Math.min(Q,Math.max(0,(F[4][1]-V)*J))),L=Math.floor(Math.max(0,(F[5][0]-V)*J)),z=Math.ceil(Math.min(Q,Math.max(0,(F[5][1]-V)*J)));if(F[4][1]>=V&&F[4][0]<=A&&F[4][2]){this.draw_read(S,N,J,V,A,F[4][0],F[4][2],F[4][3],D)}if(F[5][1]>=V&&F[5][0]<=A&&F[5][2]){this.draw_read(S,N,J,V,A,F[5][0],F[5][2],F[5][3],D)}if(L>M){S.fillStyle=h;q(S,M-P,D+5,L-P,D+5)}}else{S.fillStyle=W;this.draw_read(S,N,J,V,A,R,F[4],F[5],D)}if(N==="Pack"&&R>V){S.fillStyle=this.prefs.label_color;var U=1;if(U===0&&E-S.measureText(K).width<0){S.textAlign="left";S.fillText(K,G+l-P,D+8)}else{S.textAlign="right";S.fillText(K,E-l-P,D+8)}S.fillStyle=W}return[0,0]}});y.AlphaGenerator=g;y.SummaryTreePainter=w;y.LinePainter=c;y.LinkedFeaturePainter=s;y.ReadPainter=u;y.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 Fri Oct 07 11:47:00 2011 -0400
+++ b/static/scripts/trackster.js Fri Oct 07 15:24:27 2011 -0400
@@ -2627,16 +2627,16 @@
}
}
- // If we can draw now, do so
+ // If we can draw now, do so.
if ( can_draw_now ) {
extend( tile_data, more_tile_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
+ // Don't cache, show if no tile.
if (tile !== undefined) {
+ track.tile_cache.set(key, tile);
track.show_tile(tile, parent_element, w_scale);
}
- return tile
+ return tile;
}
// Can't draw now, so trigger another redraw when the data is ready
--- a/templates/grid_base.mako Fri Oct 07 11:47:00 2011 -0400
+++ b/templates/grid_base.mako Fri Oct 07 15:24:27 2011 -0400
@@ -117,7 +117,7 @@
%endfor
// Init operation buttons.
- var init_operation_buttons = function() {
+ function init_operation_buttons() {
// Initialize operation buttons.
$('input[name=operation]:submit').each(function() {
$(this).click( 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: jgoecks: Grid UI fixes: (a) make operation buttons work after refresh and (b) show message each time.
by Bitbucket 07 Oct '11
by Bitbucket 07 Oct '11
07 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/89f73f1bf3be/
changeset: 89f73f1bf3be
user: jgoecks
date: 2011-10-07 17:47:00
summary: Grid UI fixes: (a) make operation buttons work after refresh and (b) show message each time.
affected #: 1 file (-1 bytes)
--- a/templates/grid_base.mako Thu Oct 06 17:10:34 2011 -0400
+++ b/templates/grid_base.mako Fri Oct 07 11:47:00 2011 -0400
@@ -116,8 +116,8 @@
async_ops['${operation.label.lower()}'] = "True";
%endfor
- // Initialize grid controls
- function init_grid_controls() {
+ // Init operation buttons.
+ var init_operation_buttons = function() {
// Initialize operation buttons.
$('input[name=operation]:submit').each(function() {
$(this).click( function() {
@@ -132,6 +132,11 @@
do_operation(webapp, operation_name, item_ids);
});
});
+ };
+
+ // Initialize grid controls
+ function init_grid_controls() {
+ init_operation_buttons();
// Initialize submit image elements.
$('.submit-image').each( function() {
@@ -569,6 +574,7 @@
// Init grid.
init_grid_elements();
+ init_operation_buttons();
make_popup_menus();
// Hide loading overlay.
@@ -577,7 +583,7 @@
// Show message if there is one.
var message = $.trim( parsed_response_text[2] );
if (message != "") {
- $('#grid-message').html( message );
+ $('#grid-message').html( message ).show();
setTimeout( function() { $('#grid-message').hide(); }, 5000);
}
}
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: UI enhancements for purging histories and deleted datasets in a history.
by Bitbucket 06 Oct '11
by Bitbucket 06 Oct '11
06 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b034de9877b6/
changeset: b034de9877b6
user: natefoo
date: 2011-10-06 23:10:34
summary: UI enhancements for purging histories and deleted datasets in a history.
affected #: 3 files (-1 bytes)
--- a/lib/galaxy/web/controllers/history.py Thu Oct 06 16:30:46 2011 -0400
+++ b/lib/galaxy/web/controllers/history.py Thu Oct 06 17:10:34 2011 -0400
@@ -88,7 +88,7 @@
grids.GridOperation( "Share or Publish", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
grids.GridOperation( "Rename", condition=( lambda item: not item.deleted ), async_compatible=False ),
grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), async_compatible=True ),
- grids.GridOperation( "Delete and remove datasets from disk", condition=( lambda item: not item.deleted ), async_compatible=True ),
+ grids.GridOperation( "Delete Permanently", confirm="History contents will be removed from disk, this cannot be undone. Continue?", async_compatible=True ),
grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ), async_compatible=True ),
]
standard_filters = [
@@ -240,8 +240,8 @@
return trans.response.send_redirect( url_for( "/" ) )
else:
trans.template_context['refresh_frames'] = ['history']
- elif operation in ( "delete", "delete and remove datasets from disk" ):
- if operation == "delete and remove datasets from disk":
+ elif operation in ( "delete", "delete permanently" ):
+ if operation == "delete permanently":
status, message = self._list_delete( trans, histories, purge=True )
else:
status, message = self._list_delete( trans, histories )
@@ -303,6 +303,9 @@
trans.sa_session.add( hda.dataset )
except:
log.exception( 'Unable to purge dataset (%s) on purge of hda (%s):' % ( hda.dataset.id, hda.id ) )
+ history.purged = True
+ self.sa_session.add( history )
+ self.sa_session.flush()
trans.sa_session.flush()
if n_deleted:
part = "Deleted %d %s" % ( n_deleted, iff( n_deleted != 1, "histories", "history" ) )
@@ -467,7 +470,30 @@
return trans.fill_template( "history/display_structured.mako", items=items )
@web.expose
- def delete_current( self, trans ):
+ def purge_deleted_datasets( self, trans ):
+ count = 0
+ if trans.app.config.allow_user_dataset_purge:
+ for hda in trans.history.datasets:
+ if not hda.deleted or hda.purged:
+ continue
+ if trans.user:
+ trans.user.total_disk_usage -= hda.quota_amount( trans.user )
+ hda.purged = True
+ trans.sa_session.add( hda )
+ trans.log_event( "HDA id %s has been purged" % hda.id )
+ trans.sa_session.flush()
+ if hda.dataset.user_can_purge:
+ try:
+ hda.dataset.full_delete()
+ trans.log_event( "Dataset id %s has been purged upon the the purge of HDA id %s" % ( hda.dataset.id, hda.id ) )
+ trans.sa_session.add( hda.dataset )
+ except:
+ log.exception( 'Unable to purge dataset (%s) on purge of hda (%s):' % ( hda.dataset.id, hda.id ) )
+ count += 1
+ return trans.show_ok_message( "%d datasets have been deleted permanently" % count, refresh_frames=['history'] )
+
+ @web.expose
+ def delete_current( self, trans, purge=False ):
"""Delete just the active history -- this does not require a logged in user."""
history = trans.get_history()
if history.users_shared_with:
@@ -477,6 +503,24 @@
trans.sa_session.add( history )
trans.sa_session.flush()
trans.log_event( "History id %d marked as deleted" % history.id )
+ if purge and trans.app.config.allow_user_dataset_purge:
+ for hda in history.datasets:
+ if trans.user:
+ trans.user.total_disk_usage -= hda.quota_amount( trans.user )
+ hda.purged = True
+ trans.sa_session.add( hda )
+ trans.log_event( "HDA id %s has been purged" % hda.id )
+ trans.sa_session.flush()
+ if hda.dataset.user_can_purge:
+ try:
+ hda.dataset.full_delete()
+ trans.log_event( "Dataset id %s has been purged upon the the purge of HDA id %s" % ( hda.dataset.id, hda.id ) )
+ trans.sa_session.add( hda.dataset )
+ except:
+ log.exception( 'Unable to purge dataset (%s) on purge of hda (%s):' % ( hda.dataset.id, hda.id ) )
+ history.purged = True
+ self.sa_session.add( history )
+ self.sa_session.flush()
# Regardless of whether it was previously deleted, we make a new history active
trans.new_history()
return trans.show_ok_message( "History deleted, a new history is active", refresh_frames=['history'] )
--- a/templates/history/grid.mako Thu Oct 06 16:30:46 2011 -0400
+++ b/templates/history/grid.mako Thu Oct 06 17:10:34 2011 -0400
@@ -15,3 +15,11 @@
%endif
</script></%def>
+
+<%def name="grid_body( grid )">
+ ${self.make_grid( grid )}
+ <br/>
+ <div class="toolParamHelp" style="clear: both;">
+ Histories that have been deleted for more than a time period specified by the Galaxy administrator(s) may be permanently deleted.
+ </div>
+</%def>
--- a/templates/root/index.mako Thu Oct 06 16:30:46 2011 -0400
+++ b/templates/root/index.mako Thu Oct 06 17:10:34 2011 -0400
@@ -43,6 +43,11 @@
"Show Hidden Datasets": function() {
galaxy_history.location = "${h.url_for( controller='root', action='history', show_hidden=True)}";
},
+ "Purge Deleted Datasets": function() {
+ if ( confirm( "Really delete all deleted datasets permanently? This cannot be undone." ) ) {
+ galaxy_main.location = "${h.url_for( controller='history', action='purge_deleted_datasets' )}";
+ }
+ },
"Show Structure": function() {
galaxy_main.location = "${h.url_for( controller='history', action='display_structured' )}";
},
@@ -54,6 +59,11 @@
galaxy_main.location = "${h.url_for( controller='history', action='delete_current' )}";
}
},
+ "Delete Permanently": function() {
+ if ( confirm( "Really delete the current history permanently? This cannot be undone." ) ) {
+ galaxy_main.location = "${h.url_for( controller='history', action='delete_current', purge=True )}";
+ }
+ },
"Other Actions": null,
"Import from File": function() {
galaxy_main.location = "${h.url_for( controller='history', action='import_archive' )}";
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 get info/parameter button to empty datasets in history item view.
by Bitbucket 06 Oct '11
by Bitbucket 06 Oct '11
06 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/95a1cc87043f/
changeset: 95a1cc87043f
user: dan
date: 2011-10-06 22:30:46
summary: Add get info/parameter button to empty datasets in history item view.
affected #: 1 file (-1 bytes)
--- a/templates/root/history_common.mako Thu Oct 06 14:22:59 2011 -0400
+++ b/templates/root/history_common.mako Thu Oct 06 16:30:46 2011 -0400
@@ -263,6 +263,7 @@
<br />
%endfor
%elif for_editing:
+ <a href="${h.url_for( controller='dataset', action='show_params', dataset_id=dataset_id )}" target="galaxy_main" title="View Details" class="icon-button information tooltip"></a><a href="${h.url_for( controller='tool_runner', action='rerun', id=data.id )}" target="galaxy_main" title="Run this job again" class="icon-button arrow-circle tooltip"></a>
%endif
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
06 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/fa7693b1064b/
changeset: fa7693b1064b
user: dan
date: 2011-10-06 20:22:59
summary: Some genomespace_file_browser tweaks.
affected #: 2 files (-1 bytes)
--- a/lib/galaxy/tools/__init__.py Thu Oct 06 13:55:25 2011 -0400
+++ b/lib/galaxy/tools/__init__.py Thu Oct 06 14:22:59 2011 -0400
@@ -2028,6 +2028,7 @@
data_dict = dict( out_data_name = out_name,
ext = data.ext,
dataset_id = data.dataset.id,
+ hda_id = data.id,
file_name = file_name,
extra_files_path = extra_files_path )
--- a/tools/data_source/genomespace_file_browser.py Thu Oct 06 13:55:25 2011 -0400
+++ b/tools/data_source/genomespace_file_browser.py Thu Oct 06 14:22:59 2011 -0400
@@ -109,8 +109,8 @@
assert None not in [ username, token ], "Missing GenomeSpace username or token."
output_filename = datasource_params.get( "output", None )
dataset_id = json_params['output_data'][0]['dataset_id']
+ hda_id = json_params['output_data'][0]['hda_id']
url_opener = get_cookie_opener( username, token )
- file_count = 1
file_url_prefix = "fileUrl"
file_type_prefix = "fileFormat"
metadata_parameter_file = open( json_params['job_config']['TOOL_PROVIDED_JOB_METADATA_FILE'], 'wb' )
@@ -120,19 +120,16 @@
name = name[len( file_url_prefix ):]
file_numbers.append( int( name ) )
file_numbers.sort()
- print 'file_numbers', file_numbers
- #print 'datasource_params', datasource_params
for file_num in file_numbers:
url_key = "%s%i" % ( file_url_prefix, file_num )
download_url = datasource_params.get( url_key, None )
if download_url is None:
- print 'wtf none', file_num
break
filetype_key = "%s%i" % ( file_type_prefix, file_num )
filetype_url = datasource_params.get( filetype_key, None )
galaxy_ext = get_galaxy_ext_from_genomespace_format_url( url_opener, filetype_url )
if output_filename is None:
- output_filename = os.path.join( datasource_params['__new_file_path__'], 'primary_%i_output%i_visible_%s' % ( dataset_id, file_count, galaxy_ext ) )
+ output_filename = os.path.join( datasource_params['__new_file_path__'], 'primary_%i_output%i_visible_%s' % ( hda_id, file_num, galaxy_ext ) )
else:
if dataset_id is not None:
metadata_parameter_file.write( "%s\n" % simplejson.dumps( dict( type = 'dataset',
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 test/development GenomeSpace file importer datasource tool.
by Bitbucket 06 Oct '11
by Bitbucket 06 Oct '11
06 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/98908b114f38/
changeset: 98908b114f38
user: dan
date: 2011-10-06 19:55:25
summary: Add test/development GenomeSpace file importer datasource tool.
affected #: 3 files (-1 bytes)
--- a/tool_conf.xml.sample Thu Oct 06 13:41:27 2011 -0400
+++ b/tool_conf.xml.sample Thu Oct 06 13:55:25 2011 -0400
@@ -26,6 +26,7 @@
<tool file="data_source/epigraph_import.xml" /><tool file="data_source/epigraph_import_test.xml" /><tool file="data_source/hbvar.xml" />
+ <tool file="data_source/genomespace_file_browser_dev.xml" /><tool file="validation/fix_errors.xml" /></section><section name="Send Data" id="send">
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: A much more efficient query for calculating a history's disk usage.
by Bitbucket 06 Oct '11
by Bitbucket 06 Oct '11
06 Oct '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/92ea25658bd1/
changeset: 92ea25658bd1
user: natefoo
date: 2011-10-06 19:41:27
summary: A much more efficient query for calculating a history's disk usage.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/model/__init__.py Thu Oct 06 12:27:48 2011 -0400
+++ b/lib/galaxy/model/__init__.py Thu Oct 06 13:41:27 2011 -0400
@@ -17,6 +17,7 @@
from galaxy.web.form_builder import *
from galaxy.model.item_attrs import UsesAnnotations, APIItem
from sqlalchemy.orm import object_session
+from sqlalchemy.sql.expression import func
import os.path, os, errno, codecs, operator, socket, pexpect, logging, time, shutil
if sys.version_info[:2] < ( 2, 5 ):
@@ -468,7 +469,12 @@
return self.get_disk_size( nice_size=False )
def get_disk_size( self, nice_size=False ):
# unique datasets only
- rval = sum( [ d.get_total_size() for d in list( set( [ hda.dataset for hda in self.datasets if not hda.purged ] ) ) if not d.purged ] )
+ db_session = object_session( self )
+ rval = db_session.query( func.sum( db_session.query( HistoryDatasetAssociation.dataset_id, Dataset.total_size ).join( Dataset )
+ .filter( HistoryDatasetAssociation.table.c.history_id == self.id )
+ .distinct().subquery().c.total_size ) ).first()[0]
+ if rval is None:
+ rval = 0
if nice_size:
rval = galaxy.datatypes.data.nice_size( rval )
return rval
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