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
August 2013
- 1 participants
- 149 discussions
commit/galaxy-central: greg: Rename ~/lib/galaxy/webapps/tool_shed/util/common_util.py to be ratings_util.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/dd8329aa8d9e/
Changeset: dd8329aa8d9e
User: greg
Date: 2013-08-26 20:37:28
Summary: Rename ~/lib/galaxy/webapps/tool_shed/util/common_util.py to be ratings_util.
Affected #: 5 files
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -17,7 +17,7 @@
from galaxy.util import json
from galaxy.model.orm import and_
import tool_shed.util.shed_util_common as suc
-from tool_shed.util import common_util as scu
+from tool_shed.util import common_util
from tool_shed.util import container_util
from tool_shed.util import encoding_util
from tool_shed.util import export_util
@@ -31,7 +31,7 @@
from tool_shed.util import tool_util
from tool_shed.util import workflow_util
from tool_shed.galaxy_install import repository_util
-from galaxy.webapps.tool_shed.util import common_util
+from galaxy.webapps.tool_shed.util import ratings_util
import galaxy.tools
import tool_shed.grids.repository_grids as repository_grids
import tool_shed.grids.util as grids_util
@@ -51,7 +51,7 @@
malicious_error_can_push = " Correct this changeset as soon as possible, it potentially produces malicious behavior or contains inappropriate content."
-class RepositoryController( BaseUIController, common_util.ItemRatings ):
+class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
category_grid = repository_grids.CategoryGrid()
datatypes_grid = repository_grids.DatatypesGrid()
@@ -1233,7 +1233,7 @@
return self.install_matched_repository_grid( trans, **kwd )
else:
kwd[ 'message' ] = "tool id: <b>%s</b><br/>tool name: <b>%s</b><br/>tool version: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
- ( common_util.stringify( tool_ids ), common_util.stringify( tool_names ), common_util.stringify( tool_versions ), str( exact_matches_checked ) )
+ ( suc.stringify( tool_ids ), suc.stringify( tool_names ), suc.stringify( tool_versions ), str( exact_matches_checked ) )
self.matched_repository_grid.title = "Repositories with matching tools"
return self.matched_repository_grid( trans, **kwd )
else:
@@ -1241,9 +1241,9 @@
status = "error"
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
return trans.fill_template( '/webapps/tool_shed/repository/find_tools.mako',
- tool_id=common_util.stringify( tool_ids ),
- tool_name=common_util.stringify( tool_names ),
- tool_version=common_util.stringify( tool_versions ),
+ tool_id=suc.stringify( tool_ids ),
+ tool_name=suc.stringify( tool_names ),
+ tool_version=suc.stringify( tool_versions ),
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
@@ -1317,7 +1317,7 @@
return self.install_matched_repository_grid( trans, **kwd )
else:
kwd[ 'message' ] = "workflow name: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
- ( common_util.stringify( workflow_names ), str( exact_matches_checked ) )
+ ( suc.stringify( workflow_names ), str( exact_matches_checked ) )
self.matched_repository_grid.title = "Repositories with matching workflows"
return self.matched_repository_grid( trans, **kwd )
else:
@@ -1328,7 +1328,7 @@
workflow_names = []
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
return trans.fill_template( '/webapps/tool_shed/repository/find_workflows.mako',
- workflow_name=common_util.stringify( workflow_names ),
+ workflow_name=suc.stringify( workflow_names ),
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
@@ -1645,7 +1645,8 @@
encoded_repository_ids = []
changeset_revisions = []
for required_repository_tup in decoded_required_repository_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = scu.parse_repository_dependency_tuple( required_repository_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = \
+ common_util.parse_repository_dependency_tuple( required_repository_tup )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
encoded_repository_ids.append( trans.security.encode_id( repository.id ) )
changeset_revisions.append( changeset_revision )
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/controllers/repository_review.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
@@ -4,7 +4,7 @@
from galaxy.web.form_builder import SelectField, CheckboxField
from sqlalchemy.sql.expression import func
from galaxy.model.orm import and_
-from galaxy.webapps.tool_shed.util import common_util
+from galaxy.webapps.tool_shed.util import ratings_util
from tool_shed.util.container_util import STRSEP
import tool_shed.util.shed_util_common as suc
from tool_shed.util import review_util
@@ -19,7 +19,7 @@
log = logging.getLogger( __name__ )
-class RepositoryReviewController( BaseUIController, common_util.ItemRatings ):
+class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
component_grid = repository_review_grids.ComponentGrid()
repositories_ready_for_review_grid = repository_review_grids.RepositoriesReadyForReviewGrid()
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/util/common_util.py
--- a/lib/galaxy/webapps/tool_shed/util/common_util.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import logging
-from galaxy.model.item_attrs import UsesItemRatings
-
-log = logging.getLogger( __name__ )
-
-class ItemRatings( UsesItemRatings ):
- """Overrides rate_item method since we also allow for comments"""
- def rate_item( self, trans, user, item, rating, comment='' ):
- """ Rate an item. Return type is <item_class>RatingAssociation. """
- item_rating = self.get_user_item_rating( trans.sa_session, user, item, webapp_model=trans.model )
- if not item_rating:
- # User has not yet rated item; create rating.
- item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=trans.model )
- item_rating = item_rating_assoc_class()
- item_rating.user = trans.user
- item_rating.set_item( item )
- item_rating.rating = rating
- item_rating.comment = comment
- trans.sa_session.add( item_rating )
- trans.sa_session.flush()
- elif item_rating.rating != rating or item_rating.comment != comment:
- # User has previously rated item; update rating.
- item_rating.rating = rating
- item_rating.comment = comment
- trans.sa_session.add( item_rating )
- trans.sa_session.flush()
- return item_rating
-
-def stringify( list ):
- if list:
- return ','.join( list )
- return ''
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/util/ratings_util.py
--- /dev/null
+++ b/lib/galaxy/webapps/tool_shed/util/ratings_util.py
@@ -0,0 +1,27 @@
+import logging
+from galaxy.model.item_attrs import UsesItemRatings
+
+log = logging.getLogger( __name__ )
+
+class ItemRatings( UsesItemRatings ):
+ """Overrides rate_item method since we also allow for comments"""
+ def rate_item( self, trans, user, item, rating, comment='' ):
+ """ Rate an item. Return type is <item_class>RatingAssociation. """
+ item_rating = self.get_user_item_rating( trans.sa_session, user, item, webapp_model=trans.model )
+ if not item_rating:
+ # User has not yet rated item; create rating.
+ item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=trans.model )
+ item_rating = item_rating_assoc_class()
+ item_rating.user = trans.user
+ item_rating.set_item( item )
+ item_rating.rating = rating
+ item_rating.comment = comment
+ trans.sa_session.add( item_rating )
+ trans.sa_session.flush()
+ elif item_rating.rating != rating or item_rating.comment != comment:
+ # User has previously rated item; update rating.
+ item_rating.rating = rating
+ item_rating.comment = comment
+ trans.sa_session.add( item_rating )
+ trans.sa_session.flush()
+ return item_rating
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -1401,7 +1401,12 @@
# Return the boolean value of prior_installation_required, which defaults to False.
return required_rd_tup[ 4 ]
return False
-
+
+def stringify( list ):
+ if list:
+ return ','.join( list )
+ return ''
+
def strip_path( fpath ):
"""Attempt to strip the path from a file name."""
if not fpath:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix imports in the tool shed's metadata_util.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a8baee5722c3/
Changeset: a8baee5722c3
User: greg
Date: 2013-08-26 20:12:43
Summary: Fix imports in the tool shed's metadata_util.
Affected #: 1 file
diff -r f5791b418b4e1d0be9d94895f0642083f795e61f -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -19,7 +19,7 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import xml_util
-import tool_shed.galaxy_install.tool_dependencies.common_util as cu
+from tool_shed.galaxy_install.tool_dependencies import td_common_util
import pkg_resources
@@ -1124,7 +1124,7 @@
if not toolshed:
# Default to the current tool shed.
toolshed = str( url_for( '/', qualified=True ) ).rstrip( '/' )
- cleaned_toolshed = cu.clean_tool_shed_url( toolshed )
+ cleaned_toolshed = td_common_util.clean_tool_shed_url( toolshed )
name = repository_elem.get( 'name' )
owner = repository_elem.get( 'owner' )
changeset_revision = repository_elem.get( 'changeset_revision' )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Rename ~/tool_shed/galaxy_install/tool_dependencies/common_util.py to be td_common_util.py
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f5791b418b4e/
Changeset: f5791b418b4e
User: greg
Date: 2013-08-26 20:09:11
Summary: Rename ~/tool_shed/galaxy_install/tool_dependencies/common_util.py to be td_common_util.py
Affected #: 4 files
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
+++ /dev/null
@@ -1,314 +0,0 @@
-import logging
-import os
-import shutil
-import sys
-import tarfile
-import traceback
-import urllib2
-import zipfile
-import tool_shed.util.shed_util_common as suc
-from galaxy.datatypes import checkers
-from urllib2 import HTTPError
-
-log = logging.getLogger( __name__ )
-
-def clean_tool_shed_url( base_url ):
- if base_url:
- protocol, base = base_url.split( '://' )
- return base.rstrip( '/' )
- return base_url
-
-def create_env_var_dict( elem, tool_dependency_install_dir=None, tool_shed_repository_install_dir=None ):
- env_var_name = elem.get( 'name', 'PATH' )
- env_var_action = elem.get( 'action', 'prepend_to' )
- env_var_text = None
- if elem.text and elem.text.find( 'REPOSITORY_INSTALL_DIR' ) >= 0:
- if tool_shed_repository_install_dir and elem.text.find( '$REPOSITORY_INSTALL_DIR' ) != -1:
- env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_shed_repository_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- else:
- env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_dependency_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- if elem.text and elem.text.find( 'INSTALL_DIR' ) >= 0:
- if tool_dependency_install_dir:
- env_var_text = elem.text.replace( '$INSTALL_DIR', tool_dependency_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- else:
- env_var_text = elem.text.replace( '$INSTALL_DIR', tool_shed_repository_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- if elem.text:
- # Allow for environment variables that contain neither REPOSITORY_INSTALL_DIR nor INSTALL_DIR since there may be command line
- # parameters that are tuned for a Galaxy instance. Allowing them to be set in one location rather than being hard coded into
- # each tool config is the best approach. For example:
- # <environment_variable name="GATK2_SITE_OPTIONS" action="set_to">
- # "--num_threads 4 --num_cpu_threads_per_data_thread 3 --phone_home STANDARD"
- # </environment_variable>
- return dict( name=env_var_name, action=env_var_action, value=elem.text)
- return None
-
-def create_or_update_env_shell_file( install_dir, env_var_dict ):
- env_var_name = env_var_dict[ 'name' ]
- env_var_action = env_var_dict[ 'action' ]
- env_var_value = env_var_dict[ 'value' ]
- if env_var_action == 'prepend_to':
- changed_value = '%s:$%s' % ( env_var_value, env_var_name )
- elif env_var_action == 'set_to':
- changed_value = '%s' % env_var_value
- elif env_var_action == 'append_to':
- changed_value = '$%s:%s' % ( env_var_name, env_var_value )
- line = "%s=%s; export %s" % (env_var_name, changed_value, env_var_name)
- return create_or_update_env_shell_file_with_command(install_dir, line)
-
-
-def create_or_update_env_shell_file_with_command( install_dir, command ):
- """
- Return a shell expression which when executed will create or update
- a Galaxy env.sh dependency file in the specified install_dir containing
- the supplied command.
- """
- env_shell_file_path = '%s/env.sh' % install_dir
- if os.path.exists( env_shell_file_path ):
- write_action = '>>'
- else:
- write_action = '>'
- cmd = "echo %s %s %s;chmod +x %s" % ( __shellquote(command),
- write_action,
- __shellquote(env_shell_file_path),
- __shellquote(env_shell_file_path))
- return cmd
-
-def download_binary( url, work_dir ):
- '''
- Download a pre-compiled binary from the specified URL.
- '''
- downloaded_filename = os.path.split( url )[ -1 ]
- dir = url_download( work_dir, downloaded_filename, url, extract=False )
- return downloaded_filename
-
-def extract_tar( file_name, file_path ):
- if isgzip( file_name ) or isbz2( file_name ):
- # Open for reading with transparent compression.
- tar = tarfile.open( file_name, 'r:*', errorlevel=0 )
- else:
- tar = tarfile.open( file_name, errorlevel=0 )
- tar.extractall( path=file_path )
- tar.close()
-
-def extract_zip( archive_path, extraction_path ):
- # TODO: change this method to use zipfile.Zipfile.extractall() when we stop supporting Python 2.5.
- if not zipfile_ok( archive_path ):
- return False
- zip_archive = zipfile.ZipFile( archive_path, 'r' )
- for name in zip_archive.namelist():
- uncompressed_path = os.path.join( extraction_path, name )
- if uncompressed_path.endswith( '/' ):
- if not os.path.isdir( uncompressed_path ):
- os.makedirs( uncompressed_path )
- else:
- file( uncompressed_path, 'wb' ).write( zip_archive.read( name ) )
- zip_archive.close()
- return True
-
-def format_traceback():
- ex_type, ex, tb = sys.exc_info()
- return ''.join( traceback.format_tb( tb ) )
-
-def get_env_shell_file_path( installation_directory ):
- env_shell_file_name = 'env.sh'
- default_location = os.path.abspath( os.path.join( installation_directory, env_shell_file_name ) )
- if os.path.exists( default_location ):
- return default_location
- for root, dirs, files in os.walk( installation_directory ):
- for name in files:
- if name == env_shell_file_name:
- return os.path.abspath( os.path.join( root, name ) )
- return None
-
-def get_env_shell_file_paths( app, elem ):
- # Currently only the following tag set is supported.
- # <repository toolshed="http://localhost:9009/" name="package_numpy_1_7" owner="test" changeset_revision="c84c6a8be056">
- # <package name="numpy" version="1.7.1" />
- # </repository>
- env_shell_file_paths = []
- toolshed = elem.get( 'toolshed', None )
- repository_name = elem.get( 'name', None )
- repository_owner = elem.get( 'owner', None )
- changeset_revision = elem.get( 'changeset_revision', None )
- if toolshed and repository_name and repository_owner and changeset_revision:
- toolshed = clean_tool_shed_url( toolshed )
- repository = suc.get_repository_for_dependency_relationship( app, toolshed, repository_name, repository_owner, changeset_revision )
- if repository:
- for sub_elem in elem:
- tool_dependency_type = sub_elem.tag
- tool_dependency_name = sub_elem.get( 'name' )
- tool_dependency_version = sub_elem.get( 'version' )
- if tool_dependency_type and tool_dependency_name and tool_dependency_version:
- # Get the tool_dependency so we can get it's installation directory.
- tool_dependency = None
- for tool_dependency in repository.tool_dependencies:
- if tool_dependency.type == tool_dependency_type and tool_dependency.name == tool_dependency_name and tool_dependency.version == tool_dependency_version:
- break
- if tool_dependency:
- tool_dependency_key = '%s/%s' % ( tool_dependency_name, tool_dependency_version )
- installation_directory = tool_dependency.installation_directory( app )
- env_shell_file_path = get_env_shell_file_path( installation_directory )
- if env_shell_file_path:
- env_shell_file_paths.append( env_shell_file_path )
- else:
- error_message = "Skipping tool dependency definition because unable to locate env.sh file for tool dependency "
- error_message += "type %s, name %s, version %s for repository %s" % \
- ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
- log.debug( error_message )
- continue
- else:
- error_message = "Skipping tool dependency definition because unable to locate tool dependency "
- error_message += "type %s, name %s, version %s for repository %s" % \
- ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
- log.debug( error_message )
- continue
- else:
- error_message = "Skipping invalid tool dependency definition: type %s, name %s, version %s." % \
- ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ) )
- log.debug( error_message )
- continue
- else:
- error_message = "Skipping set_environment_for_install definition because unable to locate required installed tool shed repository: "
- error_message += "toolshed %s, name %s, owner %s, changeset_revision %s." % \
- ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
- log.debug( error_message )
- else:
- error_message = "Skipping invalid set_environment_for_install definition: toolshed %s, name %s, owner %s, changeset_revision %s." % \
- ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
- log.debug( error_message )
- return env_shell_file_paths
-
-def get_env_var_values( install_dir ):
- env_var_dict = {}
- env_var_dict[ 'INSTALL_DIR' ] = install_dir
- env_var_dict[ 'system_install' ] = install_dir
- # If the Python interpreter is 64bit then we can safely assume that the underlying system is also 64bit.
- env_var_dict[ '__is64bit__' ] = sys.maxsize > 2**32
- return env_var_dict
-
-def isbz2( file_path ):
- return checkers.is_bz2( file_path )
-
-def isgzip( file_path ):
- return checkers.is_gzip( file_path )
-
-def isjar( file_path ):
- return iszip( file_path ) and file_path.endswith( '.jar' )
-
-def istar( file_path ):
- return tarfile.is_tarfile( file_path )
-
-def iszip( file_path ):
- return checkers.check_zip( file_path )
-
-def is_compressed( file_path ):
- if isjar( file_path ):
- return False
- else:
- return iszip( file_path ) or isgzip( file_path ) or istar( file_path ) or isbz2( file_path )
-
-def make_directory( full_path ):
- if not os.path.exists( full_path ):
- os.makedirs( full_path )
-
-def move_directory_files( current_dir, source_dir, destination_dir ):
- source_directory = os.path.abspath( os.path.join( current_dir, source_dir ) )
- destination_directory = os.path.join( destination_dir )
- if not os.path.isdir( destination_directory ):
- os.makedirs( destination_directory )
- for file_name in os.listdir( source_directory ):
- source_file = os.path.join( source_directory, file_name )
- destination_file = os.path.join( destination_directory, file_name )
- shutil.move( source_file, destination_file )
-
-def move_file( current_dir, source, destination_dir ):
- source_file = os.path.abspath( os.path.join( current_dir, source ) )
- destination_directory = os.path.join( destination_dir )
- if not os.path.isdir( destination_directory ):
- os.makedirs( destination_directory )
- shutil.move( source_file, destination_directory )
-
-def tar_extraction_directory( file_path, file_name ):
- """Try to return the correct extraction directory."""
- file_name = file_name.strip()
- extensions = [ '.tar.gz', '.tgz', '.tar.bz2', '.tar', '.zip' ]
- for extension in extensions:
- if file_name.find( extension ) > 0:
- dir_name = file_name[ :-len( extension ) ]
- if os.path.exists( os.path.abspath( os.path.join( file_path, dir_name ) ) ):
- return dir_name
- if os.path.exists( os.path.abspath( os.path.join( file_path, file_name ) ) ):
- return os.path.abspath( file_path )
- raise ValueError( 'Could not find path to file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
-
-def url_download( install_dir, downloaded_file_name, download_url, extract=True ):
- file_path = os.path.join( install_dir, downloaded_file_name )
- src = None
- dst = None
- try:
- src = urllib2.urlopen( download_url )
- dst = open( file_path, 'wb' )
- while True:
- chunk = src.read( suc.CHUNK_SIZE )
- if chunk:
- dst.write( chunk )
- else:
- break
- except:
- raise
- finally:
- if src:
- src.close()
- if dst:
- dst.close()
- if extract:
- if istar( file_path ):
- # <action type="download_by_url">http://sourceforge.net/projects/samtools/files/samtools/0.1.18/samtools-0.1…</action>
- extract_tar( file_path, install_dir )
- dir = tar_extraction_directory( install_dir, downloaded_file_name )
- elif isjar( file_path ):
- dir = os.path.curdir
- elif iszip( file_path ):
- # <action type="download_by_url">http://downloads.sourceforge.net/project/picard/picard-tools/1.56/picard-to…</action>
- zip_archive_extracted = extract_zip( file_path, install_dir )
- dir = zip_extraction_directory( install_dir, downloaded_file_name )
- else:
- dir = os.path.abspath( install_dir )
- else:
- dir = os.path.abspath( install_dir )
- return dir
-
-def zip_extraction_directory( file_path, file_name ):
- """Try to return the correct extraction directory."""
- files = [ filename for filename in os.listdir( file_path ) if not filename.endswith( '.zip' ) ]
- if len( files ) > 1:
- return os.path.abspath( file_path )
- elif len( files ) == 1:
- # If there is only on file it should be a directory.
- if os.path.isdir( os.path.join( file_path, files[ 0 ] ) ):
- return os.path.abspath( os.path.join( file_path, files[ 0 ] ) )
- raise ValueError( 'Could not find directory for the extracted file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
-
-def zipfile_ok( path_to_archive ):
- """
- This function is a bit pedantic and not functionally necessary. It checks whether there is no file pointing outside of the extraction,
- because ZipFile.extractall() has some potential security holes. See python zipfile documentation for more details.
- """
- basename = os.path.realpath( os.path.dirname( path_to_archive ) )
- zip_archive = zipfile.ZipFile( path_to_archive )
- for member in zip_archive.namelist():
- member_path = os.path.realpath( os.path.join( basename, member ) )
- if not member_path.startswith( basename ):
- return False
- return True
-
-
-def __shellquote(s):
- """
- Quote and escape the supplied string for use in shell expressions.
- """
- return "'" + s.replace("'", "'\\''") + "'"
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -1,12 +1,12 @@
# For Python 2.5
from __future__ import with_statement
-import common_util
import logging
import os
import shutil
import tempfile
import shutil
+import td_common_util
from contextlib import contextmanager
from galaxy.util.template import fill_template
from galaxy import eggs
@@ -155,10 +155,10 @@
if not os.path.exists( venv_dir ):
with make_tmp_dir() as work_dir:
downloaded_filename = VIRTUALENV_URL.rsplit('/', 1)[-1]
- downloaded_file_path = common_util.url_download( work_dir, downloaded_filename, VIRTUALENV_URL )
- if common_util.istar( downloaded_file_path ):
- common_util.extract_tar( downloaded_file_path, work_dir )
- dir = common_util.tar_extraction_directory( work_dir, downloaded_filename )
+ downloaded_file_path = td_common_util.url_download( work_dir, downloaded_filename, VIRTUALENV_URL )
+ if td_common_util.istar( downloaded_file_path ):
+ td_common_util.extract_tar( downloaded_file_path, work_dir )
+ dir = td_common_util.tar_extraction_directory( work_dir, downloaded_filename )
else:
log.error( "Failed to download virtualenv: Downloaded file '%s' is not a tar file", downloaded_filename )
return False
@@ -188,7 +188,7 @@
log.debug( 'Attempting to download from %s to %s', url, str( target_directory ) )
downloaded_filename = None
try:
- downloaded_filename = common_util.download_binary( url, work_dir )
+ downloaded_filename = td_common_util.download_binary( url, work_dir )
# Filter out any actions that are not download_binary, chmod, or set_environment.
filtered_actions = filter_actions_after_binary_installation( actions[ 1: ] )
# Set actions to the same, so that the current download_binary doesn't get re-run in the filtered actions below.
@@ -210,9 +210,9 @@
full_path_to_dir = os.path.abspath( install_dir )
else:
full_path_to_dir = os.path.abspath( install_dir )
- common_util.move_file( current_dir=work_dir,
- source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ td_common_util.move_file( current_dir=work_dir,
+ source=downloaded_filename,
+ destination_dir=full_path_to_dir )
if action_type == 'download_by_url':
# Eliminate the download_by_url action so remaining actions can be processed correctly.
filtered_actions = actions[ 1: ]
@@ -223,7 +223,7 @@
downloaded_filename = action_dict[ 'target_filename' ]
else:
downloaded_filename = os.path.split( url )[ -1 ]
- dir = common_util.url_download( work_dir, downloaded_filename, url, extract=True )
+ dir = td_common_util.url_download( work_dir, downloaded_filename, url, extract=True )
elif action_type == 'shell_command':
# <action type="shell_command">git clone --recursive git://github.com/ekg/freebayes.git</action>
# Eliminate the shell_command clone action so remaining actions can be processed correctly.
@@ -243,7 +243,7 @@
filename = action_dict[ 'target_filename' ]
else:
filename = url.split( '/' )[ -1 ]
- common_util.url_download( work_dir, filename, url )
+ td_common_util.url_download( work_dir, filename, url )
dir = os.path.curdir
else:
# We're handling a complex repository dependency where we only have a set_environment tag set.
@@ -263,17 +263,17 @@
with lcd( current_dir ):
action_type, action_dict = action_tup
if action_type == 'make_directory':
- common_util.make_directory( full_path=action_dict[ 'full_path' ] )
+ td_common_util.make_directory( full_path=action_dict[ 'full_path' ] )
elif action_type == 'move_directory_files':
- common_util.move_directory_files( current_dir=current_dir,
- source_dir=os.path.join( action_dict[ 'source_directory' ] ),
- destination_dir=os.path.join( action_dict[ 'destination_directory' ] ) )
+ td_common_util.move_directory_files( current_dir=current_dir,
+ source_dir=os.path.join( action_dict[ 'source_directory' ] ),
+ destination_dir=os.path.join( action_dict[ 'destination_directory' ] ) )
elif action_type == 'move_file':
# TODO: Remove this hack that resets current_dir so that the pre-compiled bwa binary can be found.
# current_dir = '/Users/gvk/workspaces_2008/bwa/bwa-0.5.9'
- common_util.move_file( current_dir=current_dir,
- source=os.path.join( action_dict[ 'source' ] ),
- destination_dir=os.path.join( action_dict[ 'destination' ] ) )
+ td_common_util.move_file( current_dir=current_dir,
+ source=os.path.join( action_dict[ 'source' ] ),
+ destination_dir=os.path.join( action_dict[ 'destination' ] ) )
elif action_type == 'set_environment':
# Currently the only action supported in this category is "environment_variable".
# Build a command line from the prior_installation_required, in case an environment variable is referenced
@@ -289,7 +289,7 @@
for env_var_dict in env_var_dicts:
# Check for the presence of the $ENV[] key string and populate it if possible.
env_var_dict = handle_environment_variables( app, tool_dependency, install_dir, env_var_dict, cmds )
- env_command = common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
+ env_command = td_common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
return_code = handle_command( app, tool_dependency, install_dir, env_command )
if return_code:
return
@@ -331,11 +331,13 @@
if not os.path.exists( output.stdout ):
log.error( "virtualenv's site-packages directory '%s' does not exist", output.stdout )
return
- modify_env_command = common_util.create_or_update_env_shell_file( install_dir, dict( name="PYTHONPATH", action="prepend_to", value=output.stdout ) )
+ modify_env_command_dict = dict( name="PYTHONPATH", action="prepend_to", value=output.stdout )
+ modify_env_command = td_common_util.create_or_update_env_shell_file( install_dir, modify_env_command_dict )
return_code = handle_command( app, tool_dependency, install_dir, modify_env_command )
if return_code:
return
- modify_env_command = common_util.create_or_update_env_shell_file( install_dir, dict( name="PATH", action="prepend_to", value=os.path.join( venv_directory, "bin" ) ) )
+ modify_env_command_dict = dict( name="PATH", action="prepend_to", value=os.path.join( venv_directory, "bin" ) )
+ modify_env_command = td_common_util.create_or_update_env_shell_file( install_dir, modify_env_command_dict )
return_code = handle_command( app, tool_dependency, install_dir, modify_env_command )
if return_code:
return
@@ -362,7 +364,7 @@
env_vars[ env_name ] = env_path
else:
log.debug( 'Invalid file %s specified, ignoring template_command action.', env_shell_file_path )
- env_vars.update( common_util.get_env_var_values( install_dir ) )
+ env_vars.update( td_common_util.get_env_var_values( install_dir ) )
language = action_dict[ 'language' ]
with settings( warn_only=True, **env_vars ):
if language == 'cheetah':
@@ -379,7 +381,7 @@
else:
filename = url.split( '/' )[ -1 ]
extract = action_dict.get( 'extract', False )
- common_util.url_download( current_dir, filename, url, extract=extract )
+ td_common_util.url_download( current_dir, filename, url, extract=extract )
elif action_type == 'change_directory':
target_directory = os.path.realpath( os.path.normpath( os.path.join( current_dir, action_dict[ 'directory' ] ) ) )
if target_directory.startswith( os.path.realpath( current_dir ) ) and os.path.exists( target_directory ):
@@ -398,7 +400,7 @@
url = action_dict[ 'url' ]
target_directory = action_dict.get( 'target_directory', None )
try:
- downloaded_filename = common_util.download_binary( url, work_dir )
+ downloaded_filename = td_common_util.download_binary( url, work_dir )
except Exception, e:
log.exception( str( e ) )
# If the downloaded file exists, move it to $INSTALL_DIR. Put this outside the try/catch above so that
@@ -413,9 +415,9 @@
full_path_to_dir = os.path.abspath( install_dir )
else:
full_path_to_dir = os.path.abspath( install_dir )
- common_util.move_file( current_dir=work_dir,
- source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ td_common_util.move_file( current_dir=work_dir,
+ source=downloaded_filename,
+ destination_dir=full_path_to_dir )
def log_results( command, fabric_AttributeString, file_path ):
"""
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -5,10 +5,10 @@
import subprocess
import tempfile
from string import Template
-import common_util
import fabric_util
+import td_common_util
import tool_shed.util.shed_util_common as suc
-import tool_shed.util.common_util as cu
+from tool_shed.util import common_util
from tool_shed.util import encoding_util
from tool_shed.util import tool_dependency_util
from tool_shed.util import xml_util
@@ -22,7 +22,7 @@
"""Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
url = url_join( tool_shed_url,
'repository/get_tool_dependencies_config_contents?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
- text = cu.tool_shed_get( app, tool_shed_url, url )
+ text = common_util.tool_shed_get( app, tool_shed_url, url )
if text:
# Write the contents to a temporary file on disk so it can be reloaded and parsed.
fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-cttdc" )
@@ -51,7 +51,7 @@
def get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app, tool_shed_url, name, owner, changeset_revision ):
sa_session = app.model.context.current
- tool_shed = common_util.clean_tool_shed_url( tool_shed_url )
+ tool_shed = td_common_util.clean_tool_shed_url( tool_shed_url )
tool_shed_repository = sa_session.query( app.model.ToolShedRepository ) \
.filter( and_( app.model.ToolShedRepository.table.c.tool_shed == tool_shed,
app.model.ToolShedRepository.table.c.name == name,
@@ -103,7 +103,7 @@
"""
url = suc.url_join( tool_shed_url,
'repository/updated_changeset_revisions?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
- text = cu.tool_shed_get( app, tool_shed_url, url )
+ text = common_util.tool_shed_get( app, tool_shed_url, url )
return text
def handle_set_environment_entry_for_package( app, install_dir, tool_shed_repository, package_name, package_version, elem, required_repository ):
@@ -139,7 +139,7 @@
# </action>
for env_elem in action_elem:
if env_elem.tag == 'environment_variable':
- env_var_dict = common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
+ env_var_dict = td_common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
if env_var_dict:
if env_var_dict not in env_var_dicts:
env_var_dicts.append( env_var_dict )
@@ -203,7 +203,7 @@
except Exception, e:
log.exception( 'Error installing tool dependency %s version %s.', str( tool_dependency.name ), str( tool_dependency.version ) )
tool_dependency.status = app.model.ToolDependency.installation_status.ERROR
- tool_dependency.error_message = '%s\n%s' % ( common_util.format_traceback(), str( e ) )
+ tool_dependency.error_message = '%s\n%s' % ( td_common_util.format_traceback(), str( e ) )
sa_session.add( tool_dependency )
sa_session.flush()
if tool_dependency.status != app.model.ToolDependency.installation_status.ERROR:
@@ -362,7 +362,7 @@
def evaluate_template( text ):
""" Substitute variables defined in XML blocks from dependencies file."""
- return Template( text ).safe_substitute( common_util.get_env_var_values( install_dir ) )
+ return Template( text ).safe_substitute( td_common_util.get_env_var_values( install_dir ) )
if not os.path.exists( install_dir ):
os.makedirs( install_dir )
@@ -469,7 +469,7 @@
# </action>
for env_elem in action_elem:
if env_elem.tag == 'environment_variable':
- env_var_dict = common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
+ env_var_dict = td_common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
if env_var_dict:
env_var_dicts.append( env_var_dict )
if env_var_dicts:
@@ -489,7 +489,7 @@
# tool dependency package. See the package_matplotlib_1_2 repository in the test tool shed for a real-world example.
for env_elem in action_elem:
if env_elem.tag == 'repository':
- env_shell_file_paths = common_util.get_env_shell_file_paths( app, env_elem )
+ env_shell_file_paths = td_common_util.get_env_shell_file_paths( app, env_elem )
if env_shell_file_paths:
all_env_shell_file_paths.extend( env_shell_file_paths )
if all_env_shell_file_paths:
@@ -705,7 +705,7 @@
tool_dependency_name=env_var_name,
tool_dependency_version=None )
tool_shed_repository_install_dir = get_tool_shed_repository_install_dir( app, tool_shed_repository )
- env_var_dict = common_util.create_env_var_dict( env_var_elem, tool_shed_repository_install_dir=tool_shed_repository_install_dir )
+ env_var_dict = td_common_util.create_env_var_dict( env_var_elem, tool_shed_repository_install_dir=tool_shed_repository_install_dir )
if env_var_dict:
if not os.path.exists( install_dir ):
os.makedirs( install_dir )
@@ -716,7 +716,7 @@
type='set_environment',
status=app.model.ToolDependency.installation_status.INSTALLING,
set_status=True )
- cmd = common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
+ cmd = td_common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
if env_var_version == '1.0':
# Handle setting environment variables using a fabric method.
fabric_util.handle_command( app, tool_dependency, install_dir, cmd )
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
@@ -0,0 +1,311 @@
+import logging
+import os
+import shutil
+import sys
+import tarfile
+import traceback
+import urllib2
+import zipfile
+import tool_shed.util.shed_util_common as suc
+from galaxy.datatypes import checkers
+from urllib2 import HTTPError
+
+log = logging.getLogger( __name__ )
+
+def clean_tool_shed_url( base_url ):
+ if base_url:
+ protocol, base = base_url.split( '://' )
+ return base.rstrip( '/' )
+ return base_url
+
+def create_env_var_dict( elem, tool_dependency_install_dir=None, tool_shed_repository_install_dir=None ):
+ env_var_name = elem.get( 'name', 'PATH' )
+ env_var_action = elem.get( 'action', 'prepend_to' )
+ env_var_text = None
+ if elem.text and elem.text.find( 'REPOSITORY_INSTALL_DIR' ) >= 0:
+ if tool_shed_repository_install_dir and elem.text.find( '$REPOSITORY_INSTALL_DIR' ) != -1:
+ env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_shed_repository_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ else:
+ env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_dependency_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ if elem.text and elem.text.find( 'INSTALL_DIR' ) >= 0:
+ if tool_dependency_install_dir:
+ env_var_text = elem.text.replace( '$INSTALL_DIR', tool_dependency_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ else:
+ env_var_text = elem.text.replace( '$INSTALL_DIR', tool_shed_repository_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ if elem.text:
+ # Allow for environment variables that contain neither REPOSITORY_INSTALL_DIR nor INSTALL_DIR since there may be command line
+ # parameters that are tuned for a Galaxy instance. Allowing them to be set in one location rather than being hard coded into
+ # each tool config is the best approach. For example:
+ # <environment_variable name="GATK2_SITE_OPTIONS" action="set_to">
+ # "--num_threads 4 --num_cpu_threads_per_data_thread 3 --phone_home STANDARD"
+ # </environment_variable>
+ return dict( name=env_var_name, action=env_var_action, value=elem.text)
+ return None
+
+def create_or_update_env_shell_file( install_dir, env_var_dict ):
+ env_var_name = env_var_dict[ 'name' ]
+ env_var_action = env_var_dict[ 'action' ]
+ env_var_value = env_var_dict[ 'value' ]
+ if env_var_action == 'prepend_to':
+ changed_value = '%s:$%s' % ( env_var_value, env_var_name )
+ elif env_var_action == 'set_to':
+ changed_value = '%s' % env_var_value
+ elif env_var_action == 'append_to':
+ changed_value = '$%s:%s' % ( env_var_name, env_var_value )
+ line = "%s=%s; export %s" % (env_var_name, changed_value, env_var_name)
+ return create_or_update_env_shell_file_with_command(install_dir, line)
+
+
+def create_or_update_env_shell_file_with_command( install_dir, command ):
+ """
+ Return a shell expression which when executed will create or update
+ a Galaxy env.sh dependency file in the specified install_dir containing
+ the supplied command.
+ """
+ env_shell_file_path = '%s/env.sh' % install_dir
+ if os.path.exists( env_shell_file_path ):
+ write_action = '>>'
+ else:
+ write_action = '>'
+ cmd = "echo %s %s %s;chmod +x %s" % ( __shellquote(command),
+ write_action,
+ __shellquote(env_shell_file_path),
+ __shellquote(env_shell_file_path))
+ return cmd
+
+def download_binary( url, work_dir ):
+ '''
+ Download a pre-compiled binary from the specified URL.
+ '''
+ downloaded_filename = os.path.split( url )[ -1 ]
+ dir = url_download( work_dir, downloaded_filename, url, extract=False )
+ return downloaded_filename
+
+def extract_tar( file_name, file_path ):
+ if isgzip( file_name ) or isbz2( file_name ):
+ # Open for reading with transparent compression.
+ tar = tarfile.open( file_name, 'r:*', errorlevel=0 )
+ else:
+ tar = tarfile.open( file_name, errorlevel=0 )
+ tar.extractall( path=file_path )
+ tar.close()
+
+def extract_zip( archive_path, extraction_path ):
+ # TODO: change this method to use zipfile.Zipfile.extractall() when we stop supporting Python 2.5.
+ if not zipfile_ok( archive_path ):
+ return False
+ zip_archive = zipfile.ZipFile( archive_path, 'r' )
+ for name in zip_archive.namelist():
+ uncompressed_path = os.path.join( extraction_path, name )
+ if uncompressed_path.endswith( '/' ):
+ if not os.path.isdir( uncompressed_path ):
+ os.makedirs( uncompressed_path )
+ else:
+ file( uncompressed_path, 'wb' ).write( zip_archive.read( name ) )
+ zip_archive.close()
+ return True
+
+def format_traceback():
+ ex_type, ex, tb = sys.exc_info()
+ return ''.join( traceback.format_tb( tb ) )
+
+def get_env_shell_file_path( installation_directory ):
+ env_shell_file_name = 'env.sh'
+ default_location = os.path.abspath( os.path.join( installation_directory, env_shell_file_name ) )
+ if os.path.exists( default_location ):
+ return default_location
+ for root, dirs, files in os.walk( installation_directory ):
+ for name in files:
+ if name == env_shell_file_name:
+ return os.path.abspath( os.path.join( root, name ) )
+ return None
+
+def get_env_shell_file_paths( app, elem ):
+ # Currently only the following tag set is supported.
+ # <repository toolshed="http://localhost:9009/" name="package_numpy_1_7" owner="test" changeset_revision="c84c6a8be056">
+ # <package name="numpy" version="1.7.1" />
+ # </repository>
+ env_shell_file_paths = []
+ toolshed = elem.get( 'toolshed', None )
+ repository_name = elem.get( 'name', None )
+ repository_owner = elem.get( 'owner', None )
+ changeset_revision = elem.get( 'changeset_revision', None )
+ if toolshed and repository_name and repository_owner and changeset_revision:
+ toolshed = clean_tool_shed_url( toolshed )
+ repository = suc.get_repository_for_dependency_relationship( app, toolshed, repository_name, repository_owner, changeset_revision )
+ if repository:
+ for sub_elem in elem:
+ tool_dependency_type = sub_elem.tag
+ tool_dependency_name = sub_elem.get( 'name' )
+ tool_dependency_version = sub_elem.get( 'version' )
+ if tool_dependency_type and tool_dependency_name and tool_dependency_version:
+ # Get the tool_dependency so we can get it's installation directory.
+ tool_dependency = None
+ for tool_dependency in repository.tool_dependencies:
+ if tool_dependency.type == tool_dependency_type and tool_dependency.name == tool_dependency_name and tool_dependency.version == tool_dependency_version:
+ break
+ if tool_dependency:
+ tool_dependency_key = '%s/%s' % ( tool_dependency_name, tool_dependency_version )
+ installation_directory = tool_dependency.installation_directory( app )
+ env_shell_file_path = get_env_shell_file_path( installation_directory )
+ if env_shell_file_path:
+ env_shell_file_paths.append( env_shell_file_path )
+ else:
+ error_message = "Skipping tool dependency definition because unable to locate env.sh file for tool dependency "
+ error_message += "type %s, name %s, version %s for repository %s" % \
+ ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
+ log.debug( error_message )
+ continue
+ else:
+ error_message = "Skipping tool dependency definition because unable to locate tool dependency "
+ error_message += "type %s, name %s, version %s for repository %s" % \
+ ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
+ log.debug( error_message )
+ continue
+ else:
+ error_message = "Skipping invalid tool dependency definition: type %s, name %s, version %s." % \
+ ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ) )
+ log.debug( error_message )
+ continue
+ else:
+ error_message = "Skipping set_environment_for_install definition because unable to locate required installed tool shed repository: "
+ error_message += "toolshed %s, name %s, owner %s, changeset_revision %s." % \
+ ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ log.debug( error_message )
+ else:
+ error_message = "Skipping invalid set_environment_for_install definition: toolshed %s, name %s, owner %s, changeset_revision %s." % \
+ ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ log.debug( error_message )
+ return env_shell_file_paths
+
+def get_env_var_values( install_dir ):
+ env_var_dict = {}
+ env_var_dict[ 'INSTALL_DIR' ] = install_dir
+ env_var_dict[ 'system_install' ] = install_dir
+ # If the Python interpreter is 64bit then we can safely assume that the underlying system is also 64bit.
+ env_var_dict[ '__is64bit__' ] = sys.maxsize > 2**32
+ return env_var_dict
+
+def isbz2( file_path ):
+ return checkers.is_bz2( file_path )
+
+def isgzip( file_path ):
+ return checkers.is_gzip( file_path )
+
+def isjar( file_path ):
+ return iszip( file_path ) and file_path.endswith( '.jar' )
+
+def istar( file_path ):
+ return tarfile.is_tarfile( file_path )
+
+def iszip( file_path ):
+ return checkers.check_zip( file_path )
+
+def is_compressed( file_path ):
+ if isjar( file_path ):
+ return False
+ else:
+ return iszip( file_path ) or isgzip( file_path ) or istar( file_path ) or isbz2( file_path )
+
+def make_directory( full_path ):
+ if not os.path.exists( full_path ):
+ os.makedirs( full_path )
+
+def move_directory_files( current_dir, source_dir, destination_dir ):
+ source_directory = os.path.abspath( os.path.join( current_dir, source_dir ) )
+ destination_directory = os.path.join( destination_dir )
+ if not os.path.isdir( destination_directory ):
+ os.makedirs( destination_directory )
+ for file_name in os.listdir( source_directory ):
+ source_file = os.path.join( source_directory, file_name )
+ destination_file = os.path.join( destination_directory, file_name )
+ shutil.move( source_file, destination_file )
+
+def move_file( current_dir, source, destination_dir ):
+ source_file = os.path.abspath( os.path.join( current_dir, source ) )
+ destination_directory = os.path.join( destination_dir )
+ if not os.path.isdir( destination_directory ):
+ os.makedirs( destination_directory )
+ shutil.move( source_file, destination_directory )
+
+def tar_extraction_directory( file_path, file_name ):
+ """Try to return the correct extraction directory."""
+ file_name = file_name.strip()
+ extensions = [ '.tar.gz', '.tgz', '.tar.bz2', '.tar', '.zip' ]
+ for extension in extensions:
+ if file_name.find( extension ) > 0:
+ dir_name = file_name[ :-len( extension ) ]
+ if os.path.exists( os.path.abspath( os.path.join( file_path, dir_name ) ) ):
+ return dir_name
+ if os.path.exists( os.path.abspath( os.path.join( file_path, file_name ) ) ):
+ return os.path.abspath( file_path )
+ raise ValueError( 'Could not find path to file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
+
+def url_download( install_dir, downloaded_file_name, download_url, extract=True ):
+ file_path = os.path.join( install_dir, downloaded_file_name )
+ src = None
+ dst = None
+ try:
+ src = urllib2.urlopen( download_url )
+ dst = open( file_path, 'wb' )
+ while True:
+ chunk = src.read( suc.CHUNK_SIZE )
+ if chunk:
+ dst.write( chunk )
+ else:
+ break
+ except:
+ raise
+ finally:
+ if src:
+ src.close()
+ if dst:
+ dst.close()
+ if extract:
+ if istar( file_path ):
+ # <action type="download_by_url">http://sourceforge.net/projects/samtools/files/samtools/0.1.18/samtools-0.1…</action>
+ extract_tar( file_path, install_dir )
+ dir = tar_extraction_directory( install_dir, downloaded_file_name )
+ elif isjar( file_path ):
+ dir = os.path.curdir
+ elif iszip( file_path ):
+ # <action type="download_by_url">http://downloads.sourceforge.net/project/picard/picard-tools/1.56/picard-to…</action>
+ zip_archive_extracted = extract_zip( file_path, install_dir )
+ dir = zip_extraction_directory( install_dir, downloaded_file_name )
+ else:
+ dir = os.path.abspath( install_dir )
+ else:
+ dir = os.path.abspath( install_dir )
+ return dir
+
+def zip_extraction_directory( file_path, file_name ):
+ """Try to return the correct extraction directory."""
+ files = [ filename for filename in os.listdir( file_path ) if not filename.endswith( '.zip' ) ]
+ if len( files ) > 1:
+ return os.path.abspath( file_path )
+ elif len( files ) == 1:
+ # If there is only on file it should be a directory.
+ if os.path.isdir( os.path.join( file_path, files[ 0 ] ) ):
+ return os.path.abspath( os.path.join( file_path, files[ 0 ] ) )
+ raise ValueError( 'Could not find directory for the extracted file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
+
+def zipfile_ok( path_to_archive ):
+ """
+ This function is a bit pedantic and not functionally necessary. It checks whether there is no file pointing outside of the extraction,
+ because ZipFile.extractall() has some potential security holes. See python zipfile documentation for more details.
+ """
+ basename = os.path.realpath( os.path.dirname( path_to_archive ) )
+ zip_archive = zipfile.ZipFile( path_to_archive )
+ for member in zip_archive.namelist():
+ member_path = os.path.realpath( os.path.join( basename, member ) )
+ if not member_path.startswith( basename ):
+ return False
+ return True
+
+def __shellquote(s):
+ """Quote and escape the supplied string for use in shell expressions."""
+ return "'" + s.replace( "'", "'\\''" ) + "'"
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: Dave Bouvier: Update tool migration process to handle orphan tool dependencies.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1520189c271f/
Changeset: 1520189c271f
User: Dave Bouvier
Date: 2013-08-26 17:42:35
Summary: Update tool migration process to handle orphan tool dependencies.
Affected #: 3 files
diff -r d51946b4a19f41ebb77e79774c01b89357aa007f -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -108,7 +108,11 @@
repository_dependencies_dict )
for tool_shed_repository in ordered_tool_shed_repositories:
- self.install_repository( repository_elem, tool_shed_repository, install_dependencies )
+ is_repository_dependency = self.__is_repository_dependency( name, changeset_revision, tool_shed_repository )
+ self.install_repository( repository_elem,
+ tool_shed_repository,
+ install_dependencies,
+ is_repository_dependency=is_repository_dependency )
else:
message = "\nNo tools associated with migration stage %s are defined in your " % str( latest_migration_script_number )
message += "file%s named %s,\nso no repositories will be installed on disk.\n" % ( plural, file_names )
@@ -320,7 +324,7 @@
tool_panel_elems.append( elem )
return tool_panel_elems
- def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies ):
+ def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies, is_repository_dependency=False ):
"""
Generate the metadata for the installed tool shed repository, among other things. If the installed tool_shed_repository contains tools
that are loaded into the Galaxy tool panel, this method will automatically eliminate all entries for each of the tools defined in the
@@ -333,37 +337,38 @@
repo_install_dir = os.path.join( self.tool_path, relative_install_dir )
else:
repo_install_dir = relative_install_dir
- for tool_elem in repository_elem:
- # The tool_elem looks something like this: <tool id="EMBOSS: antigenic1" version="5.0.0" file="emboss_antigenic.xml" />
- tool_config = tool_elem.get( 'file' )
- guid = self.get_guid( repository_clone_url, relative_install_dir, tool_config )
- # See if tool_config is defined inside of a section in self.proprietary_tool_panel_elems.
- is_displayed, tool_sections = self.get_containing_tool_sections( tool_config )
- if is_displayed:
- tool_panel_dict_for_tool_config = tool_util.generate_tool_panel_dict_for_tool_config( guid, tool_config, tool_sections=tool_sections )
- # The tool-panel_dict has the following structure.
- # {<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>}]}
- for k, v in tool_panel_dict_for_tool_config.items():
- tool_panel_dict_for_display[ k ] = v
- for tool_panel_dict in v:
- # Keep track of tool config file names associated with entries that have been made to the migrated_tools_conf.xml file so
- # they can be eliminated from all non-shed-related tool panel configs.
- tool_config_file = tool_panel_dict.get( 'tool_config', None )
- if tool_config_file:
- if tool_config_file not in tool_configs_to_filter:
- tool_configs_to_filter.append( tool_config_file )
- else:
- print 'The tool "%s" (%s) has not been enabled because it is not defined in a proprietary tool config (%s).' \
- % ( guid, tool_config, ", ".join( self.proprietary_tool_confs or [] ) )
- if tool_configs_to_filter:
- lock = threading.Lock()
- lock.acquire( True )
- try:
- self.filter_and_persist_proprietary_tool_panel_configs( tool_configs_to_filter )
- except Exception, e:
- log.exception( "Exception attempting to filter and persist non-shed-related tool panel configs:\n%s" % str( e ) )
- finally:
- lock.release()
+ if not is_repository_dependency:
+ for tool_elem in repository_elem:
+ # The tool_elem looks something like this: <tool id="EMBOSS: antigenic1" version="5.0.0" file="emboss_antigenic.xml" />
+ tool_config = tool_elem.get( 'file' )
+ guid = self.get_guid( repository_clone_url, relative_install_dir, tool_config )
+ # See if tool_config is defined inside of a section in self.proprietary_tool_panel_elems.
+ is_displayed, tool_sections = self.get_containing_tool_sections( tool_config )
+ if is_displayed:
+ tool_panel_dict_for_tool_config = tool_util.generate_tool_panel_dict_for_tool_config( guid, tool_config, tool_sections=tool_sections )
+ # The tool-panel_dict has the following structure.
+ # {<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>}]}
+ for k, v in tool_panel_dict_for_tool_config.items():
+ tool_panel_dict_for_display[ k ] = v
+ for tool_panel_dict in v:
+ # Keep track of tool config file names associated with entries that have been made to the migrated_tools_conf.xml file so
+ # they can be eliminated from all non-shed-related tool panel configs.
+ tool_config_file = tool_panel_dict.get( 'tool_config', None )
+ if tool_config_file:
+ if tool_config_file not in tool_configs_to_filter:
+ tool_configs_to_filter.append( tool_config_file )
+ else:
+ print 'The tool "%s" (%s) has not been enabled because it is not defined in a proprietary tool config (%s).' \
+ % ( guid, tool_config, ", ".join( self.proprietary_tool_confs or [] ) )
+ if tool_configs_to_filter:
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ self.filter_and_persist_proprietary_tool_panel_configs( tool_configs_to_filter )
+ except Exception, e:
+ log.exception( "Exception attempting to filter and persist non-shed-related tool panel configs:\n%s" % str( e ) )
+ finally:
+ lock.release()
metadata_dict, invalid_file_tups = metadata_util.generate_metadata_for_changeset_revision( app=self.app,
repository=tool_shed_repository,
changeset_revision=tool_shed_repository.changeset_revision,
@@ -377,7 +382,8 @@
tool_shed_repository.metadata = metadata_dict
self.app.sa_session.add( tool_shed_repository )
self.app.sa_session.flush()
- if 'tool_dependencies' in metadata_dict:
+ has_tool_dependencies = self.__has_tool_dependencies( metadata_dict )
+ if has_tool_dependencies:
# All tool_dependency objects must be created before the tools are processed even if no tool dependencies will be installed.
tool_dependencies = tool_dependency_util.create_tool_dependency_objects( self.app, tool_shed_repository, relative_install_dir, set_status=True )
else:
@@ -400,30 +406,31 @@
sample_files_copied )
# Copy remaining sample files included in the repository to the ~/tool-data directory of the local Galaxy instance.
tool_util.copy_sample_files( self.app, sample_files, tool_path=self.tool_path, sample_files_copied=sample_files_copied )
- if install_dependencies and tool_dependencies and 'tool_dependencies' in metadata_dict:
- # Install tool dependencies.
- suc.update_tool_shed_repository_status( self.app,
- tool_shed_repository,
- self.app.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
- # Get the tool_dependencies.xml file from disk.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repo_install_dir )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=self.app,
- tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_dependencies )
- for installed_tool_dependency in installed_tool_dependencies:
- if installed_tool_dependency.status == self.app.model.ToolDependency.installation_status.ERROR:
- print '\nThe following error occurred from the InstallManager while installing tool dependency ', installed_tool_dependency.name, ':'
- print installed_tool_dependency.error_message, '\n\n'
- tool_util.add_to_tool_panel( self.app,
- tool_shed_repository.name,
- repository_clone_url,
- tool_shed_repository.installed_changeset_revision,
- repository_tools_tups,
- self.repository_owner,
- self.migrated_tools_config,
- tool_panel_dict=tool_panel_dict_for_display,
- new_install=True )
+ if not is_repository_dependency:
+ tool_util.add_to_tool_panel( self.app,
+ tool_shed_repository.name,
+ repository_clone_url,
+ tool_shed_repository.installed_changeset_revision,
+ repository_tools_tups,
+ self.repository_owner,
+ self.migrated_tools_config,
+ tool_panel_dict=tool_panel_dict_for_display,
+ new_install=True )
+ if install_dependencies and tool_dependencies and has_tool_dependencies:
+ # Install tool dependencies.
+ suc.update_tool_shed_repository_status( self.app,
+ tool_shed_repository,
+ self.app.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
+ # Get the tool_dependencies.xml file from disk.
+ tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repo_install_dir )
+ installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=self.app,
+ tool_shed_repository=tool_shed_repository,
+ tool_dependencies_config=tool_dependencies_config,
+ tool_dependencies=tool_dependencies )
+ for installed_tool_dependency in installed_tool_dependencies:
+ if installed_tool_dependency.status == self.app.model.ToolDependency.installation_status.ERROR:
+ print '\nThe following error occurred from the InstallManager while installing tool dependency ', installed_tool_dependency.name, ':'
+ print installed_tool_dependency.error_message, '\n\n'
if 'datatypes' in metadata_dict:
tool_shed_repository.status = self.app.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES
if not tool_shed_repository.includes_datatypes:
@@ -455,7 +462,7 @@
except:
pass
- def install_repository( self, repository_elem, tool_shed_repository, install_dependencies ):
+ def install_repository( self, repository_elem, tool_shed_repository, install_dependencies, is_repository_dependency=False ):
"""Install a single repository, loading contained tools into the tool panel."""
# Install path is of the form: <tool path>/<tool shed>/repos/<repository owner>/<repository name>/<installed changeset revision>
relative_clone_dir = os.path.join( tool_shed_repository.tool_shed,
@@ -482,7 +489,8 @@
repository_clone_url=repository_clone_url,
relative_install_dir=relative_install_dir,
repository_elem=repository_elem,
- install_dependencies=install_dependencies )
+ install_dependencies=install_dependencies,
+ is_repository_dependency=is_repository_dependency )
self.app.sa_session.refresh( tool_shed_repository )
metadata_dict = tool_shed_repository.metadata
if 'tools' in metadata_dict:
@@ -526,6 +534,12 @@
self.app.sa_session.add( tool_version_association )
self.app.sa_session.flush()
suc.update_tool_shed_repository_status( self.app, tool_shed_repository, self.app.model.ToolShedRepository.installation_status.INSTALLED )
+ else:
+ print 'Error attempting to clone repository %s: %s' % ( str( tool_shed_repository.name ), str( error_message ) )
+ suc.update_tool_shed_repository_status( self.app,
+ tool_shed_repository,
+ self.app.model.ToolShedRepository.installation_status.ERROR,
+ error_message=error_message )
@property
def non_shed_tool_panel_configs( self ):
@@ -565,6 +579,12 @@
break
return ordered_tool_shed_repositories
+ def __has_tool_dependencies( self, metadata_dict ):
+ '''Determine if the provided metadata_dict specifies tool dependencies.'''
+ if 'tool_dependencies' in metadata_dict or 'orphan_tool_dependencies' in metadata_dict:
+ return True
+ return False
+
def __isinstalled( self, clone_dir ):
full_path = os.path.abspath( clone_dir )
if os.path.exists( full_path ):
@@ -574,6 +594,14 @@
return True
return False
+ def __is_repository_dependency( self, name, changeset_revision, tool_shed_repository ):
+ '''Determine if the provided tool shed repository is a repository dependency.'''
+ if str( tool_shed_repository.name ) != str( name ) or \
+ str( tool_shed_repository.owner ) != str( self.repository_owner ) or \
+ str( tool_shed_repository.changeset_revision ) != str( changeset_revision ):
+ return True
+ return False
+
def __is_valid_repository_tag( self, elem ):
# <repository name="emboss_datatypes" description="Datatypes for Emboss tools" changeset_revision="a89163f31369" />
if elem.tag != 'repository':
diff -r d51946b4a19f41ebb77e79774c01b89357aa007f -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -1521,10 +1521,12 @@
# purging is not supported by the mercurial API.
commands.update( get_configured_ui(), repo, rev=ctx_rev )
-def update_tool_shed_repository_status( app, tool_shed_repository, status ):
+def update_tool_shed_repository_status( app, tool_shed_repository, status, error_message=None ):
"""Update the status of a tool shed repository in the process of being installed into Galaxy."""
sa_session = app.model.context.current
tool_shed_repository.status = status
+ if error_message:
+ tool_shed_repository.error_message = str( error_message )
sa_session.add( tool_shed_repository )
sa_session.flush()
diff -r d51946b4a19f41ebb77e79774c01b89357aa007f -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 lib/tool_shed/util/tool_dependency_util.py
--- a/lib/tool_shed/util/tool_dependency_util.py
+++ b/lib/tool_shed/util/tool_dependency_util.py
@@ -39,37 +39,6 @@
tool_dependencies[ dependency_key ] = requirements_dict
return tool_dependencies
-def get_download_url_for_platform( url_templates, platform_info_dict ):
- '''
- Compare the dict returned by get_platform_info() with the values specified in the base_url element. Return
- true if and only if all defined attributes match the corresponding dict entries. If an entry is not
- defined in the base_url element, it is assumed to be irrelevant at this stage. For example,
- <base_url os="darwin">http://hgdownload.cse.ucsc.edu/admin/exe/macOSX.${architecture}/faToTwoBit</base_url>
- where the OS must be 'darwin', but the architecture is filled in later using string.Template.
- '''
- os_ok = False
- architecture_ok = False
- for url_template in url_templates:
- os_name = url_template.get( 'os', None )
- architecture = url_template.get( 'architecture', None )
- if os_name:
- if os_name.lower() == platform_info_dict[ 'os' ]:
- os_ok = True
- else:
- os_ok = False
- else:
- os_ok = True
- if architecture:
- if architecture.lower() == platform_info_dict[ 'architecture' ]:
- architecture_ok = True
- else:
- architecture_ok = False
- else:
- architecture_ok = True
- if os_ok and architecture_ok:
- return url_template
- return None
-
def create_or_update_tool_dependency( app, tool_shed_repository, name, version, type, status, set_status=True ):
# Called from Galaxy (never the tool shed) when a new repository is being installed or when an uninstalled repository is being reinstalled.
sa_session = app.model.context.current
@@ -189,6 +158,37 @@
message += "This repository contains no tools, so it's defined tool dependencies are considered orphans within this repository.<br/>"
return message
+def get_download_url_for_platform( url_templates, platform_info_dict ):
+ '''
+ Compare the dict returned by get_platform_info() with the values specified in the base_url element. Return
+ true if and only if all defined attributes match the corresponding dict entries. If an entry is not
+ defined in the base_url element, it is assumed to be irrelevant at this stage. For example,
+ <base_url os="darwin">http://hgdownload.cse.ucsc.edu/admin/exe/macOSX.${architecture}/faToTwoBit</base_url>
+ where the OS must be 'darwin', but the architecture is filled in later using string.Template.
+ '''
+ os_ok = False
+ architecture_ok = False
+ for url_template in url_templates:
+ os_name = url_template.get( 'os', None )
+ architecture = url_template.get( 'architecture', None )
+ if os_name:
+ if os_name.lower() == platform_info_dict[ 'os' ]:
+ os_ok = True
+ else:
+ os_ok = False
+ else:
+ os_ok = True
+ if architecture:
+ if architecture.lower() == platform_info_dict[ 'architecture' ]:
+ architecture_ok = True
+ else:
+ architecture_ok = False
+ else:
+ architecture_ok = True
+ if os_ok and architecture_ok:
+ return url_template
+ return None
+
def get_installed_and_missing_tool_dependencies( trans, repository, all_tool_dependencies ):
if all_tool_dependencies:
tool_dependencies = {}
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: Move workflows JavaScript code to its own file for modularity and bundling purposes. Pack scripts.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d51946b4a19f/
Changeset: d51946b4a19f
User: jgoecks
Date: 2013-08-26 16:32:07
Summary: Move workflows JavaScript code to its own file for modularity and bundling purposes. Pack scripts.
Affected #: 6 files
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/galaxy.workflows.js
--- /dev/null
+++ b/static/scripts/galaxy.workflows.js
@@ -0,0 +1,617 @@
+$( function() {
+
+ if ( window.lt_ie_7 ) {
+ show_modal(
+ "Browser not supported",
+ "Sorry, the workflow editor is not supported for IE6 and below."
+ );
+ return;
+ }
+
+ // Init searching.
+ $("#tool-search-query").click( function (){
+ $(this).focus();
+ $(this).select();
+ })
+ .keyup( function () {
+ // Remove italics.
+ $(this).css("font-style", "normal");
+ // Don't update if same value as last time
+ if ( this.value.length < 3 ) {
+ reset_tool_search(false);
+ } else if ( this.value != this.lastValue ) {
+ // Add class to denote that searching is active.
+ $(this).addClass("search_active");
+ // input.addClass(config.loadingClass);
+ // Add '*' to facilitate partial matching.
+ var q = this.value + '*';
+ // Stop previous ajax-request
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ // Start a new ajax-request in X ms
+ $("#search-spinner").show();
+ this.timer = setTimeout(function () {
+ $.get(tool_search_url, { query: q }, function (data) {
+ // input.removeClass(config.loadingClass);
+ // Show live-search if results and search-term aren't empty
+ $("#search-no-results").hide();
+ // Hide all tool sections.
+ $(".toolSectionWrapper").hide();
+ // This hides all tools but not workflows link (which is in a .toolTitle div).
+ $(".toolSectionWrapper").find(".toolTitle").hide();
+ if ( data.length != 0 ) {
+ // Map tool ids to element ids and join them.
+ var s = $.map( data, function( n, i ) { return "link-" + n; } );
+ // First pass to show matching tools and their parents.
+ $(s).each( function(index,id) {
+ // Add class to denote match.
+ $("[id='"+id+"']").parent().addClass("search_match");
+ $("[id='"+id+"']").parent().show().parent().parent().show().parent().show();
+ });
+ // Hide labels that have no visible children.
+ $(".toolPanelLabel").each( function() {
+ var this_label = $(this);
+ var next = this_label.next();
+ var no_visible_tools = true;
+ // Look through tools following label and, if none are visible, hide label.
+ while (next.length !== 0 && next.hasClass("toolTitle")) {
+ if (next.is(":visible")) {
+ no_visible_tools = false;
+ break;
+ } else {
+ next = next.next();
+ }
+ }
+ if (no_visible_tools) {
+ this_label.hide();
+ }
+ });
+ } else {
+ $("#search-no-results").show();
+ }
+ $("#search-spinner").hide();
+ }, "json" );
+ }, 200 );
+ }
+ this.lastValue = this.value;
+ });
+
+ // Canvas overview management
+ canvas_manager = new CanvasManager( $("#canvas-viewport"), $("#overview") );
+
+ // Initialize workflow state
+ reset();
+ // Load the datatype info
+ $.ajax( {
+ url: get_datatypes_url,
+ dataType: "json",
+ cache: false,
+ success: function( data ) {
+ populate_datatype_info( data );
+ // Load workflow definition
+ $.ajax( {
+ url: load_workflow_url,
+ data: { id: workflow_id, "_": "true" },
+ dataType: 'json',
+ cache: false,
+ success: function( data ) {
+ reset();
+ workflow.from_simple( data );
+ workflow.has_changes = false;
+ workflow.fit_canvas_to_nodes();
+ scroll_to_nodes();
+ canvas_manager.draw_overview();
+ // Determine if any parameters were 'upgraded' and provide message
+ upgrade_message = "";
+ $.each( data.upgrade_messages, function( k, v ) {
+ upgrade_message += ( "<li>Step " + ( parseInt(k, 10) + 1 ) + ": " + workflow.nodes[k].name + "<ul>");
+ $.each( v, function( i, vv ) {
+ upgrade_message += "<li>" + vv +"</li>";
+ });
+ upgrade_message += "</ul></li>";
+ });
+ if ( upgrade_message ) {
+ show_modal( "Workflow loaded with changes",
+ "Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>" + upgrade_message + "</ul>",
+ { "Continue" : hide_modal } );
+ } else {
+ hide_modal();
+ }
+ show_workflow_parameters();
+ },
+ beforeSubmit: function( data ) {
+ show_message( "Loading workflow", "progress" );
+ }
+ });
+ }
+ });
+
+ // For autosave purposes
+ $(document).ajaxStart( function() {
+ active_ajax_call = true;
+ $(document).bind( "ajaxStop.global", function() {
+ active_ajax_call = false;
+ });
+ });
+
+ $(document).ajaxError( function ( e, x ) {
+ // console.log( e, x );
+ var message = x.responseText || x.statusText || "Could not connect to server";
+ show_modal( "Server error", message, { "Ignore error" : hide_modal } );
+ return false;
+ });
+
+ make_popupmenu( $("#workflow-options-button"), {
+ "Save" : save_current_workflow,
+ "Run": function() {
+ window.location = run_workflow_url;
+ },
+ //"Create New" : create_new_workflow_dialog,
+ "Edit Attributes" : edit_workflow_attributes,
+ //"Edit Workflow Outputs": edit_workflow_outputs,
+ "Auto Re-layout": layout_editor,
+ //"Load a Workflow" : load_workflow,
+ "Close": close_editor
+ });
+
+ function edit_workflow_outputs(){
+ workflow.clear_active_node();
+ $('.right-content').hide();
+ var new_content = "";
+ for (var node_key in workflow.nodes){
+ var node = workflow.nodes[node_key];
+ if(node.type == 'tool'){
+ new_content += "<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step " + node.id + " - " + node.name + "</div>";
+ for (var ot_key in node.output_terminals){
+ var output = node.output_terminals[ot_key];
+ // if (node.workflow_outputs[node.id + "|" + output.name]){
+ if ($.inArray(output.name, node.workflow_outputs) != -1){
+ new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' checked /></p>";
+ }
+ else{
+ new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' /></p>";
+ }
+ }
+ new_content += "</div>";
+ }
+ }
+ $("#output-fill-area").html(new_content);
+ $("#output-fill-area input").bind('click', function(){
+ var node_id = this.name.split('|')[0];
+ var output_name = this.name.split('|')[1];
+ if (this.checked){
+ if($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) == -1){
+ workflow.nodes[node_id].workflow_outputs.push(output_name);
+ }//else it's already in the array. Shouldn't happen, but forget it.
+ }else{
+ while ($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) != -1){
+ var ia = $.inArray(output_name, workflow.nodes[node_id].workflow_outputs);
+ workflow.nodes[node_id].workflow_outputs = workflow.nodes[node_id].workflow_outputs.slice(0,ia).concat( workflow.nodes[node_id].workflow_outputs.slice(ia+1) );
+ }
+ }
+ workflow.has_changes = true;
+ });
+ $('#workflow-output-area').show();
+ }
+
+ function layout_editor() {
+ workflow.layout();
+ workflow.fit_canvas_to_nodes();
+ scroll_to_nodes();
+ canvas_manager.draw_overview();
+ }
+
+ function edit_workflow_attributes() {
+ workflow.clear_active_node();
+ $('.right-content').hide();
+ $('#edit-attributes').show();
+
+ }
+
+ // On load, set the size to the pref stored in local storage if it exists
+ overview_size = $.jStorage.get("overview-size");
+ if (overview_size !== undefined) {
+ $("#overview-border").css( {
+ width: overview_size,
+ height: overview_size
+ });
+ }
+
+ // Show viewport on load unless pref says it's off
+ if ($.jStorage.get("overview-off")) {
+ hide_overview();
+ } else {
+ show_overview();
+ }
+
+ // Stores the size of the overview into local storage when it's resized
+ $("#overview-border").bind( "dragend", function( e, d ) {
+ var op = $(this).offsetParent();
+ var opo = op.offset();
+ var new_size = Math.max( op.width() - ( d.offsetX - opo.left ),
+ op.height() - ( d.offsetY - opo.top ) );
+ $.jStorage.set("overview-size", new_size + "px");
+ });
+
+ function show_overview() {
+ $.jStorage.set("overview-off", false);
+ $("#overview-border").css("right", "0px");
+ $("#close-viewport").css("background-position", "0px 0px");
+ }
+
+ function hide_overview() {
+ $.jStorage.set("overview-off", true);
+ $("#overview-border").css("right", "20000px");
+ $("#close-viewport").css("background-position", "12px 0px");
+ }
+
+ // Lets the overview be toggled visible and invisible, adjusting the arrows accordingly
+ $("#close-viewport").click( function() {
+ if ( $("#overview-border").css("right") === "0px" ) {
+ hide_overview();
+ } else {
+ show_overview();
+ }
+ });
+
+ // Unload handler
+ window.onbeforeunload = function() {
+ if ( workflow && workflow.has_changes ) {
+ return "There are unsaved changes to your workflow which will be lost.";
+ }
+ };
+
+ // Tool menu
+ $( "div.toolSectionBody" ).hide();
+ $( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" );
+ var last_expanded = null;
+ $( "div.toolSectionTitle" ).each( function() {
+ var body = $(this).next( "div.toolSectionBody" );
+ $(this).click( function() {
+ if ( body.is( ":hidden" ) ) {
+ if ( last_expanded ) last_expanded.slideUp( "fast" );
+ last_expanded = body;
+ body.slideDown( "fast" );
+ }
+ else {
+ body.slideUp( "fast" );
+ last_expanded = null;
+ }
+ });
+ });
+
+ // Rename async.
+ async_save_text("workflow-name", "workflow-name", rename_async_url, "new_name");
+
+ // Tag async. Simply have the workflow edit element generate a click on the tag element to activate tagging.
+ $('#workflow-tag').click( function() {
+ $('.tag-area').click();
+ return false;
+ });
+ // Annotate async.
+ async_save_text("workflow-annotation", "workflow-annotation", annotate_async_url, "new_annotation", 25, true, 4);
+});
+
+// Global state for the whole workflow
+function reset() {
+ if ( workflow ) {
+ workflow.remove_all();
+ }
+ workflow = new Workflow( $("#canvas-container") );
+}
+
+function scroll_to_nodes() {
+ var cv = $("#canvas-viewport");
+ var cc = $("#canvas-container");
+ var top, left;
+ if ( cc.width() < cv.width() ) {
+ left = ( cv.width() - cc.width() ) / 2;
+ } else {
+ left = 0;
+ }
+ if ( cc.height() < cv.height() ) {
+ top = ( cv.height() - cc.height() ) / 2;
+ } else {
+ top = 0;
+ }
+ cc.css( { left: left, top: top } );
+}
+
+// Add a new step to the workflow by tool id
+function add_node_for_tool( id, title ) {
+ var node = prebuild_node( 'tool', title, id );
+ workflow.add_node( node );
+ workflow.fit_canvas_to_nodes();
+ canvas_manager.draw_overview();
+ workflow.activate_node( node );
+ $.ajax( {
+ url: get_new_module_info_url,
+ data: { type: "tool", tool_id: id, "_": "true" },
+ global: false,
+ dataType: "json",
+ success: function( data ) {
+ node.init_field_data( data );
+ },
+ error: function( x, e ) {
+ var m = "error loading field data";
+ if ( x.status === 0 ) {
+ m += ", server unavailable";
+ }
+ node.error( m );
+ }
+ });
+}
+
+function add_node_for_module( type, title ) {
+ node = prebuild_node( type, title );
+ workflow.add_node( node );
+ workflow.fit_canvas_to_nodes();
+ canvas_manager.draw_overview();
+ workflow.activate_node( node );
+ $.ajax( {
+ url: get_new_module_info_url,
+ data: { type: type, "_": "true" },
+ dataType: "json",
+ success: function( data ) {
+ node.init_field_data( data );
+ },
+ error: function( x, e ) {
+ var m = "error loading field data"
+ if ( x.status == 0 ) {
+ m += ", server unavailable"
+ }
+ node.error( m );
+ }
+ });
+}
+
+// This function preloads how to display known pja's.
+function display_pja(pja, node) {
+ // DBTODO SANITIZE INPUTS.
+ $("#pja_container").append( get_pja_form(pja) );
+ $("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function (){
+ action_to_rem = $(this).closest(".toolForm", ".action_tag").children(".action_tag:first").text();
+ $(this).closest(".toolForm").remove();
+ delete workflow.active_node.post_job_actions[action_to_rem];
+ workflow.active_form_has_changes = true;
+ });
+}
+
+function display_pja_list(){
+ return pja_list;
+}
+
+function display_file_list(node){
+ addlist = "<select id='node_data_list' name='node_data_list'>";
+ for (var out_terminal in node.output_terminals){
+ addlist += "<option value='" + out_terminal + "'>"+ out_terminal +"</option>";
+ }
+ addlist += "</select>";
+ return addlist;
+}
+
+function new_pja(action_type, target, node){
+ if (node.post_job_actions === undefined){
+ //New tool node, set up dict.
+ node.post_job_actions = {};
+ }
+ if (node.post_job_actions[action_type+target] === undefined){
+ var new_pja = {};
+ new_pja.action_type = action_type;
+ new_pja.output_name = target;
+ node.post_job_actions[action_type+target] = null;
+ node.post_job_actions[action_type+target] = new_pja;
+ display_pja(new_pja, node);
+ workflow.active_form_has_changes = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function show_workflow_parameters(){
+ var parameter_re = /\$\{.+?\}/g;
+ var workflow_parameters = [];
+ var wf_parm_container = $("#workflow-parameters-container");
+ var wf_parm_box = $("#workflow-parameters-box");
+ var new_parameter_content = "";
+ var matches = [];
+ $.each(workflow.nodes, function (k, node){
+ var form_matches = node.form_html.match(parameter_re);
+ if (form_matches){
+ matches = matches.concat(form_matches);
+ }
+ if (node.post_job_actions){
+ $.each(node.post_job_actions, function(k, pja){
+ if (pja.action_arguments){
+ $.each(pja.action_arguments, function(k, action_argument){
+ var arg_matches = action_argument.match(parameter_re);
+ if (arg_matches){
+ matches = matches.concat(arg_matches);
+ }
+ });
+ }
+ });
+ if (matches){
+ $.each(matches, function(k, element){
+ if ($.inArray(element, workflow_parameters) === -1){
+ workflow_parameters.push(element);
+ }
+ });
+ }
+ }
+ });
+ if (workflow_parameters && workflow_parameters.length !== 0){
+ $.each(workflow_parameters, function(k, element){
+ new_parameter_content += "<div>" + element.substring(2, element.length -1) + "</div>";
+ });
+ wf_parm_container.html(new_parameter_content);
+ wf_parm_box.show();
+ }else{
+ wf_parm_container.html(new_parameter_content);
+ wf_parm_box.hide();
+ }
+}
+
+function show_form_for_tool( text, node ) {
+ $('.right-content').hide();
+ $("#right-content").show().html( text );
+ // Add metadata form to tool.
+ if (node) {
+ $("#right-content").find(".toolForm:first").after( "<p><div class='metadataForm'> \
+ <div class='metadataFormTitle'>Edit Step Attributes</div> \
+ <div class='form-row'> \
+ <label>Annotation / Notes:</label> \
+ <div style='margin-right: 10px;'> \
+ <textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \
+ <div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \
+ </div> \
+ </div> \
+ </div>" );
+ }
+ // Add step actions.
+ if (node && node.type=='tool'){
+ pjastr = "<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> \
+ " + display_pja_list() + " <br/> "+ display_file_list(node) + " <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div>\
+ </div><div class='form-row'>\
+ <div style='margin-right: 10px;'><span id='pja_container'></span>";
+ pjastr += "<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";
+ $("#right-content").find(".toolForm").after( pjastr );
+ for (var key in node.post_job_actions){
+ if (key != "undefined"){ //To make sure we haven't just deleted it.
+ display_pja(node.post_job_actions[key], node);
+ }
+ }
+ $("#add_pja").click(function (){
+ new_pja($("#new_pja_list").val(),$("#node_data_list").val(), node);
+ });
+ }
+ $("#right-content").find( "form" ).ajaxForm( {
+ type: 'POST',
+ dataType: 'json',
+ success: function( data ) {
+ workflow.active_form_has_changes = false;
+ node.update_field_data( data );
+ show_workflow_parameters();
+ },
+ beforeSubmit: function( data ) {
+ data.push( { name: 'tool_state', value: node.tool_state } );
+ data.push( { name: '_', value: "true" } );
+ }
+ }).each( function() {
+ var form = this;
+ $(this).find( "select[refresh_on_change='true']").change( function() {
+ $(form).submit();
+ });
+ $(this).find( ".popupmenu" ).each( function() {
+ var id = $(this).parents( "div.form-row" ).attr( 'id' );
+ var b = $('<a class="popup-arrow" id="popup-arrow-for-' + id + '">▼</a>');
+ var options = {};
+ $(this).find( "button" ).each( function() {
+ var name = $(this).attr( 'name' );
+ var value = $(this).attr( 'value' );
+ options[ $(this).text() ] = function() {
+ $(form).append( "<input type='hidden' name='"+name+"' value='"+value+"' />" ).submit();
+ };
+ });
+ b.insertAfter( this );
+ $(this).remove();
+ make_popupmenu( b, options );
+ });
+ // Implements auto-saving based on whether the inputs change. We consider
+ // "changed" to be when a field is accessed and not necessarily modified
+ // because of an issue where "onchange" is not triggered when activating
+ // another node, or saving the workflow.
+ $(this).find("input,textarea,select").each( function() {
+ $(this).bind("focus click", function() {
+ workflow.active_form_has_changes = true;
+ });
+ });
+ });
+}
+
+var close_editor = function() {
+ workflow.check_changes_in_active_form();
+ if ( workflow && workflow.has_changes ) {
+ do_close = function() {
+ window.onbeforeunload = undefined;
+ window.document.location = workflow_index_url;
+ };
+ show_modal( "Close workflow editor",
+ "There are unsaved changes to your workflow which will be lost.",
+ {
+ "Cancel" : hide_modal,
+ "Save Changes" : function() {
+ save_current_workflow( null, do_close );
+ }
+ }, {
+ "Don't Save": do_close
+ } );
+ } else {
+ window.document.location = workflow_index_url;
+ }
+};
+
+var save_current_workflow = function ( eventObj, success_callback ) {
+ show_message( "Saving workflow", "progress" );
+ workflow.check_changes_in_active_form();
+ if (!workflow.has_changes) {
+ hide_modal();
+ if ( success_callback ) {
+ success_callback();
+ }
+ return;
+ }
+ workflow.rectify_workflow_outputs();
+ var savefn = function(callback) {
+ $.ajax( {
+ url: save_workflow_url,
+ type: "POST",
+ data: {
+ id: workflow_id,
+ workflow_data: function() { return JSON.stringify( workflow.to_simple() ); },
+ "_": "true"
+ },
+ dataType: 'json',
+ success: function( data ) {
+ var body = $("<div></div>").text( data.message );
+ if ( data.errors ) {
+ body.addClass( "warningmark" );
+ var errlist = $( "<ul/>" );
+ $.each( data.errors, function( i, v ) {
+ $("<li></li>").text( v ).appendTo( errlist );
+ });
+ body.append( errlist );
+ } else {
+ body.addClass( "donemark" );
+ }
+ workflow.name = data.name;
+ workflow.has_changes = false;
+ workflow.stored = true;
+ show_workflow_parameters();
+ if ( data.errors ) {
+ show_modal( "Saving workflow", body, { "Ok" : hide_modal } );
+ } else {
+ if (callback) {
+ callback();
+ }
+ hide_modal();
+ }
+ }
+ });
+ };
+
+ // We bind to ajaxStop because of auto-saving, since the form submission ajax
+ // call needs to be completed so that the new data is saved
+ if (active_ajax_call) {
+ $(document).bind('ajaxStop.save_workflow', function() {
+ $(document).unbind('ajaxStop.save_workflow');
+ savefn();
+ $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here
+ active_ajax_call = false;
+ });
+ } else {
+ savefn(success_callback);
+ }
+};
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/galaxy.workflows.js
--- /dev/null
+++ b/static/scripts/packed/galaxy.workflows.js
@@ -0,0 +1,1 @@
+$(function(){if(window.lt_ie_7){show_modal("Browser not supported","Sorry, the workflow editor is not supported for IE6 and below.");return}$("#tool-search-query").click(function(){$(this).focus();$(this).select()}).keyup(function(){$(this).css("font-style","normal");if(this.value.length<3){reset_tool_search(false)}else{if(this.value!=this.lastValue){$(this).addClass("search_active");var g=this.value+"*";if(this.timer){clearTimeout(this.timer)}$("#search-spinner").show();this.timer=setTimeout(function(){$.get(tool_search_url,{query:g},function(i){$("#search-no-results").hide();$(".toolSectionWrapper").hide();$(".toolSectionWrapper").find(".toolTitle").hide();if(i.length!=0){var h=$.map(i,function(k,j){return"link-"+k});$(h).each(function(j,k){$("[id='"+k+"']").parent().addClass("search_match");$("[id='"+k+"']").parent().show().parent().parent().show().parent().show()});$(".toolPanelLabel").each(function(){var l=$(this);var k=l.next();var j=true;while(k.length!==0&&k.hasClass("toolTitle")){if(k.is(":visible")){j=false;break}else{k=k.next()}}if(j){l.hide()}})}else{$("#search-no-results").show()}$("#search-spinner").hide()},"json")},200)}}this.lastValue=this.value});canvas_manager=new CanvasManager($("#canvas-viewport"),$("#overview"));reset();$.ajax({url:get_datatypes_url,dataType:"json",cache:false,success:function(g){populate_datatype_info(g);$.ajax({url:load_workflow_url,data:{id:workflow_id,_:"true"},dataType:"json",cache:false,success:function(h){reset();workflow.from_simple(h);workflow.has_changes=false;workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview();upgrade_message="";$.each(h.upgrade_messages,function(j,i){upgrade_message+=("<li>Step "+(parseInt(j,10)+1)+": "+workflow.nodes[j].name+"<ul>");$.each(i,function(k,l){upgrade_message+="<li>"+l+"</li>"});upgrade_message+="</ul></li>"});if(upgrade_message){show_modal("Workflow loaded with changes","Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>"+upgrade_message+"</ul>",{Continue:hide_modal})}else{hide_modal()}show_workflow_parameters()},beforeSubmit:function(h){show_message("Loading workflow","progress")}})}});$(document).ajaxStart(function(){active_ajax_call=true;$(document).bind("ajaxStop.global",function(){active_ajax_call=false})});$(document).ajaxError(function(i,g){var h=g.responseText||g.statusText||"Could not connect to server";show_modal("Server error",h,{"Ignore error":hide_modal});return false});make_popupmenu($("#workflow-options-button"),{Save:save_current_workflow,Run:function(){window.location=run_workflow_url},"Edit Attributes":c,"Auto Re-layout":f,Close:close_editor});function b(){workflow.clear_active_node();$(".right-content").hide();var j="";for(var h in workflow.nodes){var i=workflow.nodes[h];if(i.type=="tool"){j+="<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step "+i.id+" - "+i.name+"</div>";for(var k in i.output_terminals){var g=i.output_terminals[k];if($.inArray(g.name,i.workflow_outputs)!=-1){j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' checked /></p>"}else{j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' /></p>"}}j+="</div>"}}$("#output-fill-area").html(j);$("#output-fill-area input").bind("click",function(){var n=this.name.split("|")[0];var l=this.name.split("|")[1];if(this.checked){if($.inArray(l,workflow.nodes[n].workflow_outputs)==-1){workflow.nodes[n].workflow_outputs.push(l)}}else{while($.inArray(l,workflow.nodes[n].workflow_outputs)!=-1){var m=$.inArray(l,workflow.nodes[n].workflow_outputs);workflow.nodes[n].workflow_outputs=workflow.nodes[n].workflow_outputs.slice(0,m).concat(workflow.nodes[n].workflow_outputs.slice(m+1))}}workflow.has_changes=true});$("#workflow-output-area").show()}function f(){workflow.layout();workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview()}function c(){workflow.clear_active_node();$(".right-content").hide();$("#edit-attributes").show()}overview_size=$.jStorage.get("overview-size");if(overview_size!==undefined){$("#overview-border").css({width:overview_size,height:overview_size})}if($.jStorage.get("overview-off")){d()}else{e()}$("#overview-border").bind("dragend",function(h,j){var k=$(this).offsetParent();var i=k.offset();var g=Math.max(k.width()-(j.offsetX-i.left),k.height()-(j.offsetY-i.top));$.jStorage.set("overview-size",g+"px")});function e(){$.jStorage.set("overview-off",false);$("#overview-border").css("right","0px");$("#close-viewport").css("background-position","0px 0px")}function d(){$.jStorage.set("overview-off",true);$("#overview-border").css("right","20000px");$("#close-viewport").css("background-position","12px 0px")}$("#close-viewport").click(function(){if($("#overview-border").css("right")==="0px"){d()}else{e()}});window.onbeforeunload=function(){if(workflow&&workflow.has_changes){return"There are unsaved changes to your workflow which will be lost."}};$("div.toolSectionBody").hide();$("div.toolSectionTitle > span").wrap("<a href='#'></a>");var a=null;$("div.toolSectionTitle").each(function(){var g=$(this).next("div.toolSectionBody");$(this).click(function(){if(g.is(":hidden")){if(a){a.slideUp("fast")}a=g;g.slideDown("fast")}else{g.slideUp("fast");a=null}})});async_save_text("workflow-name","workflow-name",rename_async_url,"new_name");$("#workflow-tag").click(function(){$(".tag-area").click();return false});async_save_text("workflow-annotation","workflow-annotation",annotate_async_url,"new_annotation",25,true,4)});function reset(){if(workflow){workflow.remove_all()}workflow=new Workflow($("#canvas-container"))}function scroll_to_nodes(){var a=$("#canvas-viewport");var d=$("#canvas-container");var c,b;if(d.width()<a.width()){b=(a.width()-d.width())/2}else{b=0}if(d.height()<a.height()){c=(a.height()-d.height())/2}else{c=0}d.css({left:b,top:c})}function add_node_for_tool(c,b){var a=prebuild_node("tool",b,c);workflow.add_node(a);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(a);$.ajax({url:get_new_module_info_url,data:{type:"tool",tool_id:c,_:"true"},global:false,dataType:"json",success:function(d){a.init_field_data(d)},error:function(f,g){var d="error loading field data";if(f.status===0){d+=", server unavailable"}a.error(d)}})}function add_node_for_module(a,b){node=prebuild_node(a,b);workflow.add_node(node);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(node);$.ajax({url:get_new_module_info_url,data:{type:a,_:"true"},dataType:"json",success:function(c){node.init_field_data(c)},error:function(d,f){var c="error loading field data";if(d.status==0){c+=", server unavailable"}node.error(c)}})}function display_pja(b,a){$("#pja_container").append(get_pja_form(b));$("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function(){action_to_rem=$(this).closest(".toolForm",".action_tag").children(".action_tag:first").text();$(this).closest(".toolForm").remove();delete workflow.active_node.post_job_actions[action_to_rem];workflow.active_form_has_changes=true})}function display_pja_list(){return pja_list}function display_file_list(b){addlist="<select id='node_data_list' name='node_data_list'>";for(var a in b.output_terminals){addlist+="<option value='"+a+"'>"+a+"</option>"}addlist+="</select>";return addlist}function new_pja(d,b,a){if(a.post_job_actions===undefined){a.post_job_actions={}}if(a.post_job_actions[d+b]===undefined){var c={};c.action_type=d;c.output_name=b;a.post_job_actions[d+b]=null;a.post_job_actions[d+b]=c;display_pja(c,a);workflow.active_form_has_changes=true;return true}else{return false}}function show_workflow_parameters(){var c=/\$\{.+?\}/g;var b=[];var f=$("#workflow-parameters-container");var e=$("#workflow-parameters-box");var a="";var d=[];$.each(workflow.nodes,function(g,h){var i=h.form_html.match(c);if(i){d=d.concat(i)}if(h.post_job_actions){$.each(h.post_job_actions,function(j,l){if(l.action_arguments){$.each(l.action_arguments,function(m,n){var o=n.match(c);if(o){d=d.concat(o)}})}});if(d){$.each(d,function(j,l){if($.inArray(l,b)===-1){b.push(l)}})}}});if(b&&b.length!==0){$.each(b,function(g,h){a+="<div>"+h.substring(2,h.length-1)+"</div>"});f.html(a);e.show()}else{f.html(a);e.hide()}}function show_form_for_tool(c,b){$(".right-content").hide();$("#right-content").show().html(c);if(b){$("#right-content").find(".toolForm:first").after("<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Attributes</div><div class='form-row'><label>Annotation / Notes:</label><div style='margin-right: 10px;'><textarea name='annotation' rows='3' style='width: 100%'>"+b.annotation+"</textarea><div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div></div></div></div>")}if(b&&b.type=="tool"){pjastr="<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> "+display_pja_list()+" <br/> "+display_file_list(b)+" <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div></div><div class='form-row'><div style='margin-right: 10px;'><span id='pja_container'></span>";pjastr+="<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";$("#right-content").find(".toolForm").after(pjastr);for(var a in b.post_job_actions){if(a!="undefined"){display_pja(b.post_job_actions[a],b)}}$("#add_pja").click(function(){new_pja($("#new_pja_list").val(),$("#node_data_list").val(),b)})}$("#right-content").find("form").ajaxForm({type:"POST",dataType:"json",success:function(d){workflow.active_form_has_changes=false;b.update_field_data(d);show_workflow_parameters()},beforeSubmit:function(d){d.push({name:"tool_state",value:b.tool_state});d.push({name:"_",value:"true"})}}).each(function(){var d=this;$(this).find("select[refresh_on_change='true']").change(function(){$(d).submit()});$(this).find(".popupmenu").each(function(){var g=$(this).parents("div.form-row").attr("id");var e=$('<a class="popup-arrow" id="popup-arrow-for-'+g+'">▼</a>');var f={};$(this).find("button").each(function(){var h=$(this).attr("name");var i=$(this).attr("value");f[$(this).text()]=function(){$(d).append("<input type='hidden' name='"+h+"' value='"+i+"' />").submit()}});e.insertAfter(this);$(this).remove();make_popupmenu(e,f)});$(this).find("input,textarea,select").each(function(){$(this).bind("focus click",function(){workflow.active_form_has_changes=true})})})}var close_editor=function(){workflow.check_changes_in_active_form();if(workflow&&workflow.has_changes){do_close=function(){window.onbeforeunload=undefined;window.document.location=workflow_index_url};show_modal("Close workflow editor","There are unsaved changes to your workflow which will be lost.",{Cancel:hide_modal,"Save Changes":function(){save_current_workflow(null,do_close)}},{"Don't Save":do_close})}else{window.document.location=workflow_index_url}};var save_current_workflow=function(b,c){show_message("Saving workflow","progress");workflow.check_changes_in_active_form();if(!workflow.has_changes){hide_modal();if(c){c()}return}workflow.rectify_workflow_outputs();var a=function(d){$.ajax({url:save_workflow_url,type:"POST",data:{id:workflow_id,workflow_data:function(){return JSON.stringify(workflow.to_simple())},_:"true"},dataType:"json",success:function(g){var e=$("<div></div>").text(g.message);if(g.errors){e.addClass("warningmark");var f=$("<ul/>");$.each(g.errors,function(j,h){$("<li></li>").text(h).appendTo(f)});e.append(f)}else{e.addClass("donemark")}workflow.name=g.name;workflow.has_changes=false;workflow.stored=true;show_workflow_parameters();if(g.errors){show_modal("Saving workflow",e,{Ok:hide_modal})}else{if(d){d()}hide_modal()}}})};if(active_ajax_call){$(document).bind("ajaxStop.save_workflow",function(){$(document).unbind("ajaxStop.save_workflow");a();$(document).unbind("ajaxStop.save_workflow");active_ajax_call=false})}else{a(c)}};
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/mvc/tools.js
--- a/static/scripts/packed/mvc/tools.js
+++ b/static/scripts/packed/mvc/tools.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/backbone-relational"],function(t,a,u){var f={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},get_samples:function(){var w=this.get("type"),v=null;if(w==="number"){v=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(w==="select"){v=t.map(this.get("options"),function(x){return x[0]})}}return v},set_value:function(v){this.set("value",v||"")}},{TYPE_DICT:{number:d},create:function(v){var w=e.TYPE_DICT[v.type]||e;return new w(v)}});var d=e.extend({defaults:t.extend({},e.prototype.defaults,{min:null,max:null}),initialize:function(){e.prototype.initialize.call(this);if(this.attributes.min){this.attributes.min=parseInt(this.attributes.min,10)}if(this.attributes.max){this.attributes.max=parseInt(this.attributes.max,10)}},set_value:function(v){this.set("value",parseInt(v,10))}});var h=Backbone.RelationalModel.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[]},initialize:function(v){this.attributes.inputs=new Backbone.Collection(t.map(v.inputs,function(w){return e.create(w)}))},urlRoot:galaxy_config.root+"api/tools",copy:function(w){var x=new h(this.toJSON());if(w){var v=new Backbone.Collection();x.get("inputs").each(function(y){if(y.get_samples()){v.push(y)}});x.set("inputs",v)}return x},apply_search_results:function(v){(t.indexOf(v,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(v,w){this.get("inputs").find(function(x){return x.get("name")===v}).set("value",w)},set_input_values:function(w){var v=this;t.each(t.keys(w),function(x){v.set_input_value(x,w[x])})},run:function(){return this._run()},rerun:function(w,v){return this._run({action:"rerun",target_dataset_id:w.id,regions:v})},get_inputs_dict:function(){var v={};this.get("inputs").each(function(w){v[w.get("name")]=w.get("value")});return v},_run:function(x){var y=t.extend({tool_id:this.id,inputs:this.get_inputs_dict()},x);var w=$.Deferred(),v=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(y),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(z){return z!=="pending"}});$.when(v.go()).then(function(z){w.resolve(new u.DatasetCollection().reset(z))});return w}});t.extend(h.prototype,f);var n=Backbone.View.extend({});var k=Backbone.Collection.extend({model:h});var r=Backbone.Model.extend(f);var i=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){t.each(this.attributes.elems,function(v){v.show()});this.show();this.set("open",false)},apply_search_results:function(w){var x=true,v;t.each(this.attributes.elems,function(y){if(y instanceof r){v=y;v.hide()}else{if(y instanceof h){if(y.apply_search_results(w)){x=false;if(v){v.show()}}}}});if(x){this.hide()}else{this.show();this.set("open",true)}}});t.extend(i.prototype,f);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var x=this.attributes.query;if(x.length<this.attributes.min_chars_for_search){this.set("results",null);return}var w=x+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var v=this;this.timer=setTimeout(function(){$.get(v.attributes.search_url,{query:w},function(y){v.set("results",y);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});t.extend(c.prototype,f);var l=Backbone.Model.extend({initialize:function(v){this.attributes.tool_search=v.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=v.tools;this.attributes.layout=new Backbone.Collection(this.parse(v.layout))},parse:function(w){var v=this,x=function(A){var z=A.model_class;if(z.indexOf("Tool")===z.length-4){return v.attributes.tools.get(A.id)}else{if(z==="ToolSection"){var y=t.map(A.elems,x);A.elems=y;return new i(A)}else{if(z==="ToolSectionLabel"){return new r(A)}}}};return t.map(w,x)},clear_search_results:function(){this.get("layout").each(function(v){if(v instanceof i){v.clear_search_results()}else{v.show()}})},apply_search_results:function(){var w=this.get("tool_search").get("results");if(w===null){this.clear_search_results();return}var v=null;this.get("layout").each(function(x){if(x instanceof r){v=x;v.hide()}else{if(x instanceof h){if(x.apply_search_results(w)){if(v){v.show()}}}else{v=null;x.apply_search_results(w)}}})}});var p=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var j=p.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var b=p.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var o=p.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){p.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var v=this.$el.find(".toolSectionBody");t.each(this.model.attributes.elems,function(w){if(w instanceof h){var x=new j({model:w,className:"toolTitle"});x.render();v.append(x.$el)}else{if(w instanceof r){var y=new b({model:w});y.render();v.append(y.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var m=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(v){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===v.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var s=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var v=this;var w=new m({model:this.model.get("tool_search")});w.render();v.$el.append(w.$el);this.model.get("layout").each(function(y){if(y instanceof i){var x=new o({model:y});x.render();v.$el.append(x.$el)}else{if(y instanceof h){var z=new j({model:y,className:"toolTitleNoSection"});z.render();v.$el.append(z.$el)}else{if(y instanceof r){var A=new b({model:y});A.render();v.$el.append(A.$el)}}}});v.$el.find("a.tool-link").click(function(z){var y=$(this).attr("class").split(/\s+/)[0],x=v.model.get("tools").get(y);v.trigger("tool_link_click",z,x)});return this},handle_search_results:function(){var v=this.model.get("tool_search").get("results");if(v&&v.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var q=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var g=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new s({collection:this.collection});this.tool_form_view=new q()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var v=this;this.tool_panel_view.on("tool_link_click",function(x,w){x.preventDefault();v.show_tool(w)})},show_tool:function(w){var v=this;w.fetch().done(function(){v.tool_form_view.model=w;v.tool_form_view.render();v.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,Tool:h,ToolCollection:k,ToolSearch:c,ToolPanel:l,ToolPanelView:s,ToolFormView:q}});
\ No newline at end of file
+define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/backbone-relational"],function(x,a,y){var g={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},subModelTypes:{integer:"IntegerToolParameter","float":"FloatToolParameter",data:"DataToolParameter",select:"SelectToolParameter"},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},set_value:function(z){this.set("value",z||"")}});var o={};Backbone.Relational.store.addModelScope(o);var j=o.DataToolParameter=e.extend({});var d=o.IntegerToolParameter=e.extend({set_value:function(z){this.set("value",parseInt(z,10))},get_samples:function(){return d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}});var f=o.FloatToolParameter=d.extend({set_value:function(z){this.set("value",parseFloat(z))}});var t=o.SelectToolParameter=e.extend({get_samples:function(){return x.map(this.get("options"),function(z){return z[0]})}});var i=Backbone.RelationalModel.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[],outputs:[]},relations:[{type:Backbone.HasMany,key:"inputs",relatedModel:e}],urlRoot:galaxy_config.root+"api/tools",remove_inputs:function(A){var z=this,B=z.get("inputs").filter(function(C){return(A.indexOf(C.get("type"))!==-1)});z.get("inputs").remove(B)},copy:function(A){var B=new i(this.toJSON());if(A){var z=new Backbone.Collection();B.get("inputs").each(function(C){if(C.get_samples()){z.push(C)}});B.set("inputs",z)}return B},apply_search_results:function(z){(x.indexOf(z,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(z,A){this.get("inputs").find(function(B){return B.get("name")===z}).set("value",A)},set_input_values:function(A){var z=this;x.each(x.keys(A),function(B){z.set_input_value(B,A[B])})},run:function(){return this._run()},rerun:function(A,z){return this._run({action:"rerun",target_dataset_id:A.id,regions:z})},get_inputs_dict:function(){var z={};this.get("inputs").each(function(A){z[A.get("name")]=A.get("value")});return z},_run:function(B){var C=x.extend({tool_id:this.id,inputs:this.get_inputs_dict()},B);var A=$.Deferred(),z=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(C),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(D){return D!=="pending"}});$.when(z.go()).then(function(D){A.resolve(new y.DatasetCollection().reset(D))});return A}});x.extend(i.prototype,g);var q=Backbone.View.extend({});var m=Backbone.Collection.extend({model:i});var v=Backbone.Model.extend(g);var k=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){x.each(this.attributes.elems,function(z){z.show()});this.show();this.set("open",false)},apply_search_results:function(A){var B=true,z;x.each(this.attributes.elems,function(C){if(C instanceof v){z=C;z.hide()}else{if(C instanceof i){if(C.apply_search_results(A)){B=false;if(z){z.show()}}}}});if(B){this.hide()}else{this.show();this.set("open",true)}}});x.extend(k.prototype,g);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var B=this.attributes.query;if(B.length<this.attributes.min_chars_for_search){this.set("results",null);return}var A=B+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var z=this;this.timer=setTimeout(function(){$.get(z.attributes.search_url,{query:A},function(C){z.set("results",C);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});x.extend(c.prototype,g);var n=Backbone.Model.extend({initialize:function(z){this.attributes.tool_search=z.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=z.tools;this.attributes.layout=new Backbone.Collection(this.parse(z.layout))},parse:function(A){var z=this,B=function(E){var D=E.model_class;if(D.indexOf("Tool")===D.length-4){return z.attributes.tools.get(E.id)}else{if(D==="ToolSection"){var C=x.map(E.elems,B);E.elems=C;return new k(E)}else{if(D==="ToolSectionLabel"){return new v(E)}}}};return x.map(A,B)},clear_search_results:function(){this.get("layout").each(function(z){if(z instanceof k){z.clear_search_results()}else{z.show()}})},apply_search_results:function(){var A=this.get("tool_search").get("results");if(A===null){this.clear_search_results();return}var z=null;this.get("layout").each(function(B){if(B instanceof v){z=B;z.hide()}else{if(B instanceof i){if(B.apply_search_results(A)){if(z){z.show()}}}else{z=null;B.apply_search_results(A)}}})}});var s=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var l=s.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var b=s.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var r=s.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){s.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var z=this.$el.find(".toolSectionBody");x.each(this.model.attributes.elems,function(A){if(A instanceof i){var B=new l({model:A,className:"toolTitle"});B.render();z.append(B.$el)}else{if(A instanceof v){var C=new b({model:A});C.render();z.append(C.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var p=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(z){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===z.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var w=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var z=this;var A=new p({model:this.model.get("tool_search")});A.render();z.$el.append(A.$el);this.model.get("layout").each(function(C){if(C instanceof k){var B=new r({model:C});B.render();z.$el.append(B.$el)}else{if(C instanceof i){var D=new l({model:C,className:"toolTitleNoSection"});D.render();z.$el.append(D.$el)}else{if(C instanceof v){var E=new b({model:C});E.render();z.$el.append(E.$el)}}}});z.$el.find("a.tool-link").click(function(D){var C=$(this).attr("class").split(/\s+/)[0],B=z.model.get("tools").get(C);z.trigger("tool_link_click",D,B)});return this},handle_search_results:function(){var z=this.model.get("tool_search").get("results");if(z&&z.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var u=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var h=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new w({collection:this.collection});this.tool_form_view=new u()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var z=this;this.tool_panel_view.on("tool_link_click",function(B,A){B.preventDefault();z.show_tool(A)})},show_tool:function(A){var z=this;A.fetch().done(function(){z.tool_form_view.model=A;z.tool_form_view.render();z.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,SelectToolParameter:t,Tool:i,ToolCollection:m,ToolSearch:c,ToolPanel:n,ToolPanelView:w,ToolFormView:u}});
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/viz/sweepster.js
--- a/static/scripts/packed/viz/sweepster.js
+++ b/static/scripts/packed/viz/sweepster.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","libs/d3","viz/trackster/util","viz/visualization","viz/trackster/tracks","mvc/tools","mvc/data"],function(m,q,f,o,h,g,d){var n=Backbone.Model.extend({defaults:{inputs:null,values:null}});var p=Backbone.RelationalModel.extend({defaults:{tool:null,tree_data:null},initialize:function(s){var r=this;this.get("tool").get("inputs").each(function(t){if(!t.get_samples()){return}t.on("change:min change:max change:num_samples",function(u){if(u.get("in_ptree")){r.set_tree_data()}},r);t.on("change:in_ptree",function(u){if(u.get("in_ptree")){r.add_param(u)}else{r.remove_param(u)}r.set_tree_data()},r)});if(s.config){m.each(s.config,function(u){var t=r.get("tool").get("inputs").find(function(v){return v.get("name")===u.name});r.add_param(t);t.set(u)})}},add_param:function(r){if(r.get("ptree_index")){return}r.set("in_ptree",true);r.set("ptree_index",this.get_tree_params().length)},remove_param:function(r){r.set("in_ptree",false);r.set("ptree_index",null);m(this.get_tree_params()).each(function(s,t){s.set("ptree_index",t+1)})},set_tree_data:function(){var s=m.map(this.get_tree_params(),function(u){return{param:u,samples:u.get_samples()}});var r=0,t=function(x,u){var z=x[u],y=z.param,w=y.get("label"),v=z.samples;if(x.length-1===u){return m.map(v,function(A){return{id:r++,name:A,param:y,value:A}})}return m.map(v,function(A){return{id:r++,name:A,param:y,value:A,children:t(x,u+1)}})};this.set("tree_data",{name:"Root",id:r++,children:(s.length!==0?t(s,0):null)})},get_tree_params:function(){return m(this.get("tool").get("inputs").where({in_ptree:true})).sortBy(function(r){return r.get("ptree_index")})},get_num_leaves:function(){return this.get_tree_params().reduce(function(r,s){return r*s.get_samples().length},1)},get_node_settings:function(v){var t=this.get("tool").get_inputs_dict();var w=v.parent;if(w){while(w.depth!==0){t[w.param.get("name")]=w.value;w=w.parent}}var r=this,s=function(y,x){if(y.param){x[y.param.get("name")]=y.value}if(!y.children){return new n({inputs:r.get("tool").get("inputs"),values:x})}else{return m.flatten(m.map(y.children,function(z){return s(z,m.clone(x))}))}},u=s(v,t);if(!m.isArray(u)){u=[u]}return u},get_connected_nodes:function(t){var u=function(v){if(!v.children){return v}else{return m.flatten([v,m.map(v.children,function(w){return u(w)})])}};var s=[],r=t.parent;while(r){s.push(r);r=r.parent}return m.flatten([s,u(t)])},get_leaf:function(s){var t=this.get("tree_data"),r=function(u){return m.find(u,function(v){return s[v.param.get("name")]===v.value})};while(t.children){t=r(t.children)}return t},toJSON:function(){return this.get_tree_params().map(function(r){return{name:r.get("name"),min:r.get("min"),max:r.get("max"),num_samples:r.get("num_samples")}})}});var c=Backbone.RelationalModel.extend({defaults:{track:null,mode:"Pack",settings:null,regions:null},relations:[{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion}],initialize:function(r){if(r.track){var s=m.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},r.track);this.set("track",h.object_from_template(s,{},null))}},same_settings:function(r){var s=this.get("settings"),t=r.get("settings");for(var u in s){if(!t[u]||s[u]!==t[u]){return false}}return true},toJSON:function(){return{track:this.get("track").to_dict(),settings:this.get("settings"),regions:this.get("regions")}}});var a=Backbone.Collection.extend({model:c});var i=o.Visualization.extend({defaults:m.extend({},o.Visualization.prototype.defaults,{dataset:null,tool:null,parameter_tree:null,regions:null,tracks:null,default_mode:"Pack"}),relations:[{type:Backbone.HasOne,key:"dataset",relatedModel:d.Dataset},{type:Backbone.HasOne,key:"tool",relatedModel:g.Tool},{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion},{type:Backbone.HasMany,key:"tracks",relatedModel:c}],initialize:function(r){var s=this.get("tool").copy(true);this.set("tool_with_samplable_inputs",s);this.set("parameter_tree",new p({tool:s,config:r.tree_config}))},add_track:function(r){this.get("tracks").add(r)},toJSON:function(){return{id:this.get("id"),title:"Parameter exploration for dataset '"+this.get("dataset").get("name")+"'",type:"sweepster",dataset_id:this.get("dataset").id,tool_id:this.get("tool").id,regions:this.get("regions").toJSON(),tree_config:this.get("parameter_tree").toJSON(),tracks:this.get("tracks").toJSON()}}});var l=Backbone.View.extend({tagName:"tr",TILE_LEN:250,initialize:function(r){this.canvas_manager=r.canvas_manager;this.render();this.model.on("change:track change:mode",this.draw_tiles,this)},render:function(){var w=this.model.get("settings"),s=w.get("values"),u=$("<td/>").addClass("settings").appendTo(this.$el),t=$("<div/>").addClass("track-info").hide().appendTo(u);t.append($("<div/>").css("font-weight","bold").text("Track Settings"));w.get("inputs").each(function(y){t.append(y.get("label")+": "+s[y.get("name")]+"<br/>")});var r=this,x=$("<button/>").appendTo(t).text("Run on complete dataset").click(function(){t.toggle();r.trigger("run_on_dataset",w)});var v=create_icon_buttons_menu([{title:"Settings",icon_class:"gear track-settings",on_click:function(){t.toggle()}},{title:"Remove",icon_class:"cross-circle",on_click:function(){r.$el.remove();$(".bs-tooltip").remove()}}]);u.prepend(v.$el);this.model.get("regions").each(function(){r.$el.append($("<td/>").addClass("tile").html($("<img/>").attr("src",galaxy_paths.get("image_path")+"/loading_large_white_bg.gif")))});if(this.model.get("track")){this.draw_tiles()}},draw_tiles:function(){var s=this,r=this.model.get("track"),u=this.model.get("regions"),t=this.$el.find("td.tile");if(!r){return}$.when(r.data_manager.data_is_ready()).then(function(v){u.each(function(y,x){var w=y.length()/s.TILE_LEN,A=1/w,z=s.model.get("mode");$.when(r.data_manager.get_data(y,z,w,{})).then(function(C){var B=s.canvas_manager.new_canvas();B.width=s.TILE_LEN;B.height=r.get_canvas_height(C,z,A,B.width);r.draw_tile(C,B.getContext("2d"),z,w,y,A);$(t[x]).empty().append(B)})})})}});var b=Backbone.View.extend({number_input_template:'<div class="form-row-input sweep"><input class="min" type="text" size="6" value="<%= min %>"> - <input class="max" type="text" size="6" value="<%= max %>"> samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>"></div>',select_input_template:'<div class="form-row-input sweep"><%= options %></div>',initialize:function(r){this.$el=r.tool_row;this.render()},render:function(){var s=this.model,w=s.get("type"),y=this.$el.find(".form-row-input"),u=null;y.find(":input").change(function(){s.set("value",$(this).val())});if(w==="number"){u=$(m.template(this.number_input_template,this.model.toJSON()))}else{if(w==="select"){var t=m.map(this.$el.find("select option"),function(z){return $(z).val()}),v=t.join(", ");u=$(m.template(this.select_input_template,{options:v}))}}u.insertAfter(y);var r=this,x=create_icon_buttons_menu([{title:"Add parameter to tree",icon_class:"plus-button",on_click:function(){s.set("in_ptree",true);y.hide();u.show();$(this).hide();r.$el.find(".icon-button.toggle").show()}},{title:"Remove parameter from tree",icon_class:"toggle",on_click:function(){s.set("in_ptree",false);u.hide();y.show();$(this).hide();r.$el.find(".icon-button.plus-button").show()}}],{});this.$el.prepend(x.$el);if(s.get("in_ptree")){y.hide();r.$el.find(".icon-button.plus-button").hide()}else{r.$el.find(".icon-button.toggle").hide();u.hide()}m.each(["min","max","num_samples"],function(z){u.find("."+z).change(function(){s.set(z,parseFloat($(this).val()))})})}});var k=Backbone.View.extend({className:"tree-design",initialize:function(r){this.render()},render:function(){var t=new g.ToolFormView({model:this.model.get("tool")});t.render();this.$el.append(t.$el);var s=this,r=s.model.get("tool").get("inputs");this.$el.find(".form-row").not(".form-actions").each(function(u){var v=new b({model:r.at(u),tool_row:$(this)})})}});var j=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(r){this.model.on("change:tree_data",this.render,this)},render:function(){this.$el.children().remove();var z=this.model.get_tree_params();if(!z.length){return}this.width=100*(2+z.length);this.height=15*this.model.get_num_leaves();var y=this;var x=q.layout.cluster().size([this.height,this.width-160]);var t=q.svg.diagonal().projection(function(A){return[A.y,A.x]});var r=x.nodes(this.model.get("tree_data"));var u=m.uniq(m.pluck(r,"y"));m.each(z,function(C,B){var A=u[B+1],D=$("#center").position().left;y.$el.append($("<div>").addClass("label").text(C.get("label")).css("left",A+D))});var s=q.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height+30).append("g").attr("transform","translate(40, 20)");var w=s.selectAll("path.link").data(x.links(r)).enter().append("path").attr("class","link").attr("d",t);var v=s.selectAll("g.node").data(r).enter().append("g").attr("class","node").attr("transform",function(A){return"translate("+A.y+","+A.x+")"}).on("mouseover",function(B){var A=m.pluck(y.model.get_connected_nodes(B),"id");v.filter(function(C){return m.find(A,function(D){return D===C.id})!==undefined}).style("fill","#f00")}).on("mouseout",function(){v.style("fill","#000")});v.append("circle").attr("r",9);v.append("text").attr("dx",function(A){return A.children?-12:12}).attr("dy",3).attr("text-anchor",function(A){return A.children?"end":"start"}).text(function(A){return A.name})}});var e=Backbone.View.extend({className:"Sweepster",helpText:"<div><h4>Getting Started</h4><ol><li>Create a parameter tree by using the icons next to the tool's parameter names to add or remove parameters.<li>Adjust the tree by using parameter inputs to select min, max, and number of samples<li>Run the tool with different settings by clicking on tree nodes</ol></div>",initialize:function(s){this.canvas_manager=new o.CanvasManager(this.$el.parents("body"));this.tool_param_tree_view=new j({model:this.model.get("parameter_tree")});this.track_collection_container=$("<table/>").addClass("tracks");this.model.get("parameter_tree").on("change:tree_data",this.handle_node_clicks,this);var r=this;this.model.get("tracks").each(function(t){t.get("track").view=r});this.block_color=f.get_random_color();this.reverse_strand_color=f.get_random_color([this.block_color,"#ffffff"])},render:function(){var x=new k({model:this.model.get("parameter_tree")});$("#left").append(x.$el);var A=this,u=A.model.get("regions"),y=$("<tr/>").appendTo(this.track_collection_container);u.each(function(B){y.append($("<th>").text(B.toString()))});y.children().first().attr("colspan",2);var v=$("<div>").addClass("tiles");$("#right").append(v.append(this.track_collection_container));A.model.get("tracks").each(function(B){A.add_track(B)});var z=$(this.helpText).addClass("help"),w=create_icon_buttons_menu([{title:"Close",icon_class:"cross-circle",on_click:function(){$(".bs-tooltip").remove();z.remove()}}]);z.prepend(w.$el.css("float","right"));$("#center").append(z);this.tool_param_tree_view.render();$("#center").append(this.tool_param_tree_view.$el);this.handle_node_clicks();var t=create_icon_buttons_menu([{icon_class:"chevron-expand",title:"Set display mode"},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location="${h.url_for( controller='visualization', action='list' )}"}}],{tooltip_config:{placement:"bottom"}});var s=["Squish","Pack"],r={};m.each(s,function(B){r[B]=function(){A.model.set("default_mode",B);A.model.get("tracks").each(function(C){C.set("mode",B)})}});make_popupmenu(t.$el.find(".chevron-expand"),r);t.$el.attr("style","float: right");$("#right .unified-panel-header-inner").append(t.$el)},run_tool_on_dataset:function(s){var r=this.model.get("tool"),u=r.get("name"),t=this.model.get("dataset");r.set_input_values(s.get("values"));$.when(r.rerun(t)).then(function(v){});show_modal("Running "+u+" on complete dataset",u+" is running on dataset '"+t.get("name")+"'. Outputs are in the dataset's history.",{Ok:function(){hide_modal()}})},add_track:function(u){var s=this,t=this.model.get("parameter_tree");s.model.add_track(u);var r=new l({model:u,canvas_manager:s.canvas_manager});r.on("run_on_dataset",s.run_tool_on_dataset,s);s.track_collection_container.append(r.$el);r.$el.hover(function(){var w=t.get_leaf(u.get("settings").get("values"));var v=m.pluck(t.get_connected_nodes(w),"id");q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").filter(function(x){return m.find(v,function(y){return y===x.id})!==undefined}).style("fill","#f00")},function(){q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").style("fill","#000")});return u},handle_node_clicks:function(){var r=this,s=this.model.get("parameter_tree"),u=this.model.get("regions"),t=q.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");t.on("click",function(A,x){var w=r.model.get("tool"),z=r.model.get("dataset"),y=s.get_node_settings(A),v=$.Deferred();if(y.length>=10){show_modal("Whoa there cowboy!","You clicked on a node to try "+r.model.get("tool").get("name")+" with "+y.length+" different combinations of settings. You can only run 10 jobs at a time.",{Ok:function(){hide_modal();v.resolve(false)}})}else{v.resolve(true)}$.when(v).then(function(B){if(!B){return}var C=m.map(y,function(D){var E=new c({settings:D,regions:u,mode:r.model.get("default_mode")});r.add_track(E);return E});m.each(C,function(E,D){setTimeout(function(){w.set_input_values(E.get("settings").get("values"));$.when(w.rerun(z,u)).then(function(G){var H=m.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},G.first().get("track_config")),F=h.object_from_template(H,r,null);F.data_manager.set("data_type","raw_data");F.prefs.block_color=r.block_color;F.prefs.reverse_strand_color=r.reverse_strand_color;E.set("track",F)})},D*10000)})})})}});return{SweepsterVisualization:i,SweepsterVisualizationView:e}});
\ No newline at end of file
+define(["libs/underscore","libs/d3","viz/trackster/util","viz/visualization","viz/trackster/tracks","mvc/tools","mvc/data"],function(m,q,f,o,h,g,d){var n=Backbone.Model.extend({defaults:{inputs:null,values:null}});var p=Backbone.RelationalModel.extend({defaults:{tool:null,tree_data:null},initialize:function(s){var r=this;this.get("tool").get("inputs").each(function(t){t.on("change:min change:max change:num_samples",function(u){if(u.get("in_ptree")){r.set_tree_data()}},r);t.on("change:in_ptree",function(u){if(u.get("in_ptree")){r.add_param(u)}else{r.remove_param(u)}r.set_tree_data()},r)});if(s.config){m.each(s.config,function(u){var t=r.get("tool").get("inputs").find(function(v){return v.get("name")===u.name});r.add_param(t);t.set(u)})}},add_param:function(r){if(r.get("ptree_index")){return}r.set("in_ptree",true);r.set("ptree_index",this.get_tree_params().length)},remove_param:function(r){r.set("in_ptree",false);r.set("ptree_index",null);m(this.get_tree_params()).each(function(s,t){s.set("ptree_index",t+1)})},set_tree_data:function(){var s=m.map(this.get_tree_params(),function(u){return{param:u,samples:u.get_samples()}});var r=0,t=function(x,u){var z=x[u],y=z.param,w=y.get("label"),v=z.samples;if(x.length-1===u){return m.map(v,function(A){return{id:r++,name:A,param:y,value:A}})}return m.map(v,function(A){return{id:r++,name:A,param:y,value:A,children:t(x,u+1)}})};this.set("tree_data",{name:"Root",id:r++,children:(s.length!==0?t(s,0):null)})},get_tree_params:function(){return m(this.get("tool").get("inputs").where({in_ptree:true})).sortBy(function(r){return r.get("ptree_index")})},get_num_leaves:function(){return this.get_tree_params().reduce(function(r,s){return r*s.get_samples().length},1)},get_node_settings:function(v){var t=this.get("tool").get_inputs_dict();var w=v.parent;if(w){while(w.depth!==0){t[w.param.get("name")]=w.value;w=w.parent}}var r=this,s=function(y,x){if(y.param){x[y.param.get("name")]=y.value}if(!y.children){return new n({inputs:r.get("tool").get("inputs"),values:x})}else{return m.flatten(m.map(y.children,function(z){return s(z,m.clone(x))}))}},u=s(v,t);if(!m.isArray(u)){u=[u]}return u},get_connected_nodes:function(t){var u=function(v){if(!v.children){return v}else{return m.flatten([v,m.map(v.children,function(w){return u(w)})])}};var s=[],r=t.parent;while(r){s.push(r);r=r.parent}return m.flatten([s,u(t)])},get_leaf:function(s){var t=this.get("tree_data"),r=function(u){return m.find(u,function(v){return s[v.param.get("name")]===v.value})};while(t.children){t=r(t.children)}return t},toJSON:function(){return this.get_tree_params().map(function(r){return{name:r.get("name"),min:r.get("min"),max:r.get("max"),num_samples:r.get("num_samples")}})}});var c=Backbone.RelationalModel.extend({defaults:{track:null,mode:"Pack",settings:null,regions:null},relations:[{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion}],initialize:function(r){if(r.track){var s=m.extend({data_url:galaxy_config.root+"dummy1",converted_datasets_state_url:galaxy_config.root+"dummy2"},r.track);this.set("track",h.object_from_template(s,{},null))}},same_settings:function(r){var s=this.get("settings"),t=r.get("settings");for(var u in s){if(!t[u]||s[u]!==t[u]){return false}}return true},toJSON:function(){return{track:this.get("track").to_dict(),settings:this.get("settings"),regions:this.get("regions")}}});var a=Backbone.Collection.extend({model:c});var i=o.Visualization.extend({defaults:m.extend({},o.Visualization.prototype.defaults,{dataset:null,tool:null,parameter_tree:null,regions:null,tracks:null,default_mode:"Pack"}),relations:[{type:Backbone.HasOne,key:"dataset",relatedModel:d.Dataset},{type:Backbone.HasOne,key:"tool",relatedModel:g.Tool},{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion},{type:Backbone.HasMany,key:"tracks",relatedModel:c}],initialize:function(r){var s=this.get("tool");this.set("tool_with_samplable_inputs",s);s.remove_inputs(["data","hidden_data","conditional"]);this.set("parameter_tree",new p({tool:s,config:r.tree_config}))},add_track:function(r){this.get("tracks").add(r)},toJSON:function(){return{id:this.get("id"),title:"Parameter exploration for dataset '"+this.get("dataset").get("name")+"'",type:"sweepster",dataset_id:this.get("dataset").id,tool_id:this.get("tool").id,regions:this.get("regions").toJSON(),tree_config:this.get("parameter_tree").toJSON(),tracks:this.get("tracks").toJSON()}}});var l=Backbone.View.extend({tagName:"tr",TILE_LEN:250,initialize:function(r){this.canvas_manager=r.canvas_manager;this.render();this.model.on("change:track change:mode",this.draw_tiles,this)},render:function(){var w=this.model.get("settings"),s=w.get("values"),u=$("<td/>").addClass("settings").appendTo(this.$el),t=$("<div/>").addClass("track-info").hide().appendTo(u);t.append($("<div/>").css("font-weight","bold").text("Track Settings"));w.get("inputs").each(function(y){t.append(y.get("label")+": "+s[y.get("name")]+"<br/>")});var r=this,x=$("<button/>").appendTo(t).text("Run on complete dataset").click(function(){t.toggle();r.trigger("run_on_dataset",w)});var v=create_icon_buttons_menu([{title:"Settings",icon_class:"gear track-settings",on_click:function(){t.toggle()}},{title:"Remove",icon_class:"cross-circle",on_click:function(){r.$el.remove();$(".bs-tooltip").remove()}}]);u.prepend(v.$el);this.model.get("regions").each(function(){r.$el.append($("<td/>").addClass("tile").html($("<img/>").attr("src",galaxy_config.root+"images/loading_large_white_bg.gif")))});if(this.model.get("track")){this.draw_tiles()}},draw_tiles:function(){var s=this,r=this.model.get("track"),u=this.model.get("regions"),t=this.$el.find("td.tile");if(!r){return}$.when(r.data_manager.data_is_ready()).then(function(v){u.each(function(y,x){var w=y.length()/s.TILE_LEN,A=1/w,z=s.model.get("mode");$.when(r.data_manager.get_data(y,z,w,{})).then(function(C){var B=s.canvas_manager.new_canvas();B.width=s.TILE_LEN;B.height=r.get_canvas_height(C,z,A,B.width);r.draw_tile(C,B.getContext("2d"),z,w,y,A);$(t[x]).empty().append(B)})})})}});var b=Backbone.View.extend({number_input_template:'<div class="form-row-input sweep"><input class="min" type="text" size="6" value="<%= min %>"> - <input class="max" type="text" size="6" value="<%= max %>"> samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>"></div>',select_input_template:'<div class="form-row-input sweep"><%= options %></div>',initialize:function(r){this.$el=r.tool_row;this.render()},render:function(){var s=this.model,w=s.get("type"),y=this.$el.find(".form-row-input"),u=null;y.find(":input").change(function(){s.set("value",$(this).val())});if(s instanceof g.IntegerToolParameter){u=$(m.template(this.number_input_template,this.model.toJSON()))}else{if(s instanceof g.SelectToolParameter){var t=m.map(this.$el.find("select option"),function(z){return $(z).val()}),v=t.join(", ");u=$(m.template(this.select_input_template,{options:v}))}}u.insertAfter(y);var r=this,x=create_icon_buttons_menu([{title:"Add parameter to tree",icon_class:"plus-button",on_click:function(){s.set("in_ptree",true);y.hide();u.show();$(this).hide();r.$el.find(".icon-button.toggle").show()}},{title:"Remove parameter from tree",icon_class:"toggle",on_click:function(){s.set("in_ptree",false);u.hide();y.show();$(this).hide();r.$el.find(".icon-button.plus-button").show()}}],{});this.$el.prepend(x.$el);if(s.get("in_ptree")){y.hide();r.$el.find(".icon-button.plus-button").hide()}else{r.$el.find(".icon-button.toggle").hide();u.hide()}m.each(["min","max","num_samples"],function(z){u.find("."+z).change(function(){s.set(z,parseFloat($(this).val()))})})}});var k=Backbone.View.extend({className:"tree-design",initialize:function(r){this.render()},render:function(){var t=new g.ToolFormView({model:this.model.get("tool")});t.render();this.$el.append(t.$el);var s=this,r=s.model.get("tool").get("inputs");this.$el.find(".form-row").not(".form-actions").each(function(u){var v=new b({model:r.at(u),tool_row:$(this)})})}});var j=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(r){this.model.on("change:tree_data",this.render,this)},render:function(){this.$el.children().remove();var z=this.model.get_tree_params();if(!z.length){return}this.width=100*(2+z.length);this.height=15*this.model.get_num_leaves();var y=this;var x=q.layout.cluster().size([this.height,this.width-160]);var t=q.svg.diagonal().projection(function(A){return[A.y,A.x]});var r=x.nodes(this.model.get("tree_data"));var u=m.uniq(m.pluck(r,"y"));m.each(z,function(C,B){var A=u[B+1],D=$("#center").position().left;y.$el.append($("<div>").addClass("label").text(C.get("label")).css("left",A+D))});var s=q.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height+30).append("g").attr("transform","translate(40, 20)");var w=s.selectAll("path.link").data(x.links(r)).enter().append("path").attr("class","link").attr("d",t);var v=s.selectAll("g.node").data(r).enter().append("g").attr("class","node").attr("transform",function(A){return"translate("+A.y+","+A.x+")"}).on("mouseover",function(B){var A=m.pluck(y.model.get_connected_nodes(B),"id");v.filter(function(C){return m.find(A,function(D){return D===C.id})!==undefined}).style("fill","#f00")}).on("mouseout",function(){v.style("fill","#000")});v.append("circle").attr("r",9);v.append("text").attr("dx",function(A){return A.children?-12:12}).attr("dy",3).attr("text-anchor",function(A){return A.children?"end":"start"}).text(function(A){return A.name})}});var e=Backbone.View.extend({className:"Sweepster",helpText:"<div><h4>Getting Started</h4><ol><li>Create a parameter tree by using the icons next to the tool's parameter names to add or remove parameters.<li>Adjust the tree by using parameter inputs to select min, max, and number of samples<li>Run the tool with different settings by clicking on tree nodes</ol></div>",initialize:function(s){this.canvas_manager=new o.CanvasManager(this.$el.parents("body"));this.tool_param_tree_view=new j({model:this.model.get("parameter_tree")});this.track_collection_container=$("<table/>").addClass("tracks");this.model.get("parameter_tree").on("change:tree_data",this.handle_node_clicks,this);var r=this;this.model.get("tracks").each(function(t){t.get("track").view=r});this.block_color=f.get_random_color();this.reverse_strand_color=f.get_random_color([this.block_color,"#ffffff"])},render:function(){var x=new k({model:this.model.get("parameter_tree")});$("#left").append(x.$el);var A=this,u=A.model.get("regions"),y=$("<tr/>").appendTo(this.track_collection_container);u.each(function(B){y.append($("<th>").text(B.toString()))});y.children().first().attr("colspan",2);var v=$("<div>").addClass("tiles");$("#right").append(v.append(this.track_collection_container));A.model.get("tracks").each(function(B){A.add_track(B)});var z=$(this.helpText).addClass("help"),w=create_icon_buttons_menu([{title:"Close",icon_class:"cross-circle",on_click:function(){$(".bs-tooltip").remove();z.remove()}}]);z.prepend(w.$el.css("float","right"));$("#center").append(z);this.tool_param_tree_view.render();$("#center").append(this.tool_param_tree_view.$el);this.handle_node_clicks();var t=create_icon_buttons_menu([{icon_class:"chevron-expand",title:"Set display mode"},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location="${h.url_for( controller='visualization', action='list' )}"}}],{tooltip_config:{placement:"bottom"}});var s=["Squish","Pack"],r={};m.each(s,function(B){r[B]=function(){A.model.set("default_mode",B);A.model.get("tracks").each(function(C){C.set("mode",B)})}});make_popupmenu(t.$el.find(".chevron-expand"),r);t.$el.attr("style","float: right");$("#right .unified-panel-header-inner").append(t.$el)},run_tool_on_dataset:function(s){var r=this.model.get("tool"),u=r.get("name"),t=this.model.get("dataset");r.set_input_values(s.get("values"));$.when(r.rerun(t)).then(function(v){});show_modal("Running "+u+" on complete dataset",u+" is running on dataset '"+t.get("name")+"'. Outputs are in the dataset's history.",{Ok:function(){hide_modal()}})},add_track:function(u){var s=this,t=this.model.get("parameter_tree");s.model.add_track(u);var r=new l({model:u,canvas_manager:s.canvas_manager});r.on("run_on_dataset",s.run_tool_on_dataset,s);s.track_collection_container.append(r.$el);r.$el.hover(function(){var w=t.get_leaf(u.get("settings").get("values"));var v=m.pluck(t.get_connected_nodes(w),"id");q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").filter(function(x){return m.find(v,function(y){return y===x.id})!==undefined}).style("fill","#f00")},function(){q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").style("fill","#000")});return u},handle_node_clicks:function(){var r=this,s=this.model.get("parameter_tree"),u=this.model.get("regions"),t=q.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");t.on("click",function(A,x){var w=r.model.get("tool"),z=r.model.get("dataset"),y=s.get_node_settings(A),v=$.Deferred();if(y.length>=10){show_modal("Whoa there cowboy!","You clicked on a node to try "+r.model.get("tool").get("name")+" with "+y.length+" different combinations of settings. You can only run 10 jobs at a time.",{Ok:function(){hide_modal();v.resolve(false)}})}else{v.resolve(true)}$.when(v).then(function(B){if(!B){return}var C=m.map(y,function(D){var E=new c({settings:D,regions:u,mode:r.model.get("default_mode")});r.add_track(E);return E});m.each(C,function(E,D){setTimeout(function(){w.set_input_values(E.get("settings").get("values"));$.when(w.rerun(z,u)).then(function(G){var H=G.first(),I=H.get("track_config");I.dataset=H;I.tool=null;var F=h.object_from_template(I,r,null);F.init_for_tool_data();F.prefs.block_color=r.block_color;F.prefs.reverse_strand_color=r.reverse_strand_color;E.set("track",F)})},D*10000)})})})}});return{SweepsterVisualization:i,SweepsterVisualizationView:e}});
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/viz/trackster/tracks.js
--- a/static/scripts/packed/viz/trackster/tracks.js
+++ b/static/scripts/packed/viz/trackster/tracks.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","viz/trackster/filters","mvc/data","mvc/tools"],function(ac,w,j,s,L,h,X,R){var o=ac.extend;var l={};var i=function(ad,ae){l[ad.attr("id")]=ae};var k=function(ad,af,ah,ag){ah=".group";var ae={};l[ad.attr("id")]=ag;ad.bind("drag",{handle:"."+af,relative:true},function(ap,aq){var ao=$(this),au=$(this).parent(),al=au.children(),an=l[$(this).attr("id")],ak,aj,ar,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ar=aj.position().top;ai=ar+aj.outerHeight();if(aq.offsetY<ar){$(this).insertBefore(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable_before(an,at);return}else{if(aq.offsetY>ai){$(this).insertAfter(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable(an);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ar=ak.position().top;ai=ar+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&aq.offsetY>=ar&&aq.offsetY<=ai){if(aq.offsetY-ar<ai-aq.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}if(an.container){an.container.remove_drawable(an)}l[ak.attr("id")].add_drawable(an);return}}for(am=0;am<al.length;am++){ak=$(al.get(am));if(aq.offsetY<ak.position().top&&!(ak.hasClass("reference-track")||ak.hasClass("intro"))){break}}if(am===al.length){if(this!==al.get(am-1)){au.append(this);l[au.attr("id")].move_drawable(an,am)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am));l[au.attr("id")].move_drawable(an,(aq.deltaY>0?am-1:am))}}}).bind("dragstart",function(){ae["border-top"]=ad.css("border-top");ae["border-bottom"]=ad.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ae)})};var aa=16,G=9,D=20,z=100,I=12000,S=400,K=5000,v=100,m="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",u="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",x="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20,A=["Histogram","Line","Filled","Intensity"];function V(ae,ad){if(!ad){ad=0}var af=Math.pow(10,ad);return Math.round(ae*af)/af}var p=function(ae,ad,ag){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ag.name;this.view=ae;this.container=ad;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ag.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ah){ah.stopPropagation()});var af=this;this.container_div.hover(function(){af.icons_div.show()},function(){af.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ad){if(ad.content_visible){ad.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ad.hide_contents();ad.content_visible=false}else{ad.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ad.content_visible=true;ad.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ae){var ag=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){ae.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},af=function(ah){if((ah.keyCode||ah.which)===27){ag()}else{if((ah.keyCode||ah.which)===13){ad()}}};$(window).bind("keypress.check_enter_esc",af);show_modal("Configure",ae.config.build_form(),{Cancel:ag,OK:ad})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.remove()}}];o(p.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(ad){},to_dict:function(){},set_name:function(ad){this.old_name=this.name;this.name=ad;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ad=this.view;this.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ae,aj,ai,ah,ad,ag){var af=this;this.action_icons[ae]=$("<a/>").attr("href","javascript:void(0);").attr("title",aj).addClass("icon-button").addClass(ai).tooltip().click(function(){ah(af)}).appendTo(this.icons_div);if(ag){this.action_icons[ae].hide()}},build_action_icons:function(ad){var af;for(var ae=0;ae<ad.length;ae++){af=ad[ae];this.add_action_icon(af.name,af.title,af.css_class,af.on_click_fn,af.prepend,af.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var y=function(ae,ad,af){p.call(this,ae,ad,af);this.obj_type=af.obj_type;this.drawables=[]};o(y.prototype,p.prototype,{unpack_drawables:function(af){this.drawables=[];var ae;for(var ad=0;ad<af.length;ad++){ae=n(af[ad],this.view,this);this.add_drawable(ae)}},init:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].init()}},_draw:function(ad){for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae]._draw(ad)}},to_dict:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ae}},add_drawable:function(ad){this.drawables.push(ad);ad.container=this;this.changed()},add_drawable_before:function(af,ad){this.changed();var ae=this.drawables.indexOf(ad);if(ae!==-1){this.drawables.splice(ae,0,af);return true}return false},replace_drawable:function(af,ad,ae){var ag=this.drawables.indexOf(af);if(ag!==-1){this.drawables[ag]=ad;if(ae){af.container_div.replaceWith(ad.container_div)}this.changed()}return ag},remove_drawable:function(ae){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);ae.container=null;this.changed();return true}return false},move_drawable:function(ae,af){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);this.drawables.splice(af,0,ae);this.changed();return true}return false},get_drawables:function(){return this.drawables},get_tracks:function(ag){var ad=this.drawables.slice(0),ae=[],af;while(ad.length!==0){af=ad.shift();if(af instanceof ag){ae.push(af)}else{if(af.drawables){ad=ad.concat(af.drawables)}}}return ae}});var P=function(ae,ad,ag){o(ag,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});y.call(this,ae,ad,ag);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);i(this.container_div,this);i(this.content_div,this);k(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new h.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ag){this.unpack_drawables(ag.drawables)}if("filters" in ag){var af=this.filters_manager;this.filters_manager=new h.FiltersManager(this,ag.filters);af.parent_div.replaceWith(this.filters_manager.parent_div);if(ag.filters.visible){this.setup_multitrack_filtering()}}};o(P.prototype,p.prototype,y.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters();ad._restore_filter_managers()}else{ad.setup_multitrack_filtering();ad.request_draw({clear_tile_cache:true})}ad.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var ad=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ad)}return ad},build_header_div:function(){var ad=$("<div/>").addClass("track-header");ad.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ad);return ad},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var af=this.drawables.length;if(af===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(af===1){if(this.drawables[0] instanceof e){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var am,al,aj,ap=true,ah=this.drawables[0].get_type(),ad=0;for(am=0;am<af;am++){aj=this.drawables[am];if(aj.get_type()!==ah){can_composite=false;break}if(aj instanceof c){ad++}}if(ap||ad===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ad>1&&ad===this.drawables.length){var aq={},ae;aj=this.drawables[0];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];aq[ae.name]=[ae]}for(am=1;am<this.drawables.length;am++){aj=this.drawables[am];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];if(ae.name in aq){aq[ae.name].push(ae)}}}this.filters_manager.remove_all();var ag,ai,ak,an;for(var ao in aq){ag=aq[ao];if(ag.length===ad){ai=new h.NumberFilter({name:ag[0].name,index:ag[0].index});this.filters_manager.add_filter(ai)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].filters_manager=this.saved_filters_managers[ad]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ad=0;ad<this.drawables.length;ad++){drawable=this.drawables[ad];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ae=new e(this.view,this.view,{name:this.name,drawables:this.drawables});var ad=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);this.update_icons()},remove_drawable:function(ad){y.prototype.remove_drawable.call(this,ad);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ad=o(y.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ad},request_draw:function(ad){ac.each(this.drawables,function(ae){ae.request_draw(ad)})}});var Y=Backbone.View.extend({initialize:function(ad){o(ad,{obj_type:"View"});y.call(this,"View",ad.container,ad);this.chrom=null;this.vis_id=ad.vis_id;this.dbkey=ad.dbkey;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.render();this.canvas_manager=new w.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ad.prefs,onchange:function(){track.request_redraw({clear_tile_cache:true})}})},render:function(){this.requested_redraw=false;var af=this.container,ad=this;this.top_container=$("<div/>").addClass("top-container").appendTo(af);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(af);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(af);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;i(this.viewport_container,ad);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ag=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){w.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":ad.dbkey},function(ah){ac.each(ah,function(ai){ad.add_drawable(n(ai,ad,ad))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-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/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").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").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ae=function(ah){if(ah.type==="focusout"||(ah.keyCode||ah.which)===13||(ah.keyCode||ah.which)===27){if((ah.keyCode||ah.which)!==27){ad.go_to($(this).val())}$(this).hide();$(this).val("");ad.location_span.show();ad.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ae).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ad.location_span.hide();ad.chrom_select.hide();ad.nav_input.val(ad.chrom+":"+ad.low+"-"+ad.high);ad.nav_input.css("display","inline-block");ad.nav_input.select();ad.nav_input.focus();ad.nav_input.autocomplete({source:function(aj,ah){var ak=[],ai=$.map(ad.get_tracks(c),function(al){return al.data_manager.search_features(aj.term).success(function(am){ak=ak.concat(am)})});$.when.apply($,ai).done(function(){ah($.map(ak,function(al){return{label:al[0],value:al[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ad.zoom_out();ad.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ad.zoom_in();ad.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ad.change_chrom(ad.chrom_select.val())});this.browser_content_div.click(function(ah){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ah){ad.zoom_in(ah.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ah,ai){this.current_x=ai.offsetX}).bind("drag",function(ah,aj){var ak=aj.offsetX-this.current_x;this.current_x=aj.offsetX;var ai=Math.round(ak/ad.viewport_container.width()*(ad.max_high-ad.max_low));ad.move_delta(-ai)});this.overview_close.click(function(){ad.reset_overview()});this.viewport_container.bind("draginit",function(ah,ai){if(ah.clientX>ad.viewport_container.width()-16){return false}}).bind("dragstart",function(ah,ai){ai.original_low=ad.low;ai.current_height=ah.clientY;ai.current_x=ai.offsetX}).bind("drag",function(aj,al){var ah=$(this);var am=al.offsetX-al.current_x;var ai=ah.scrollTop()-(aj.clientY-al.current_height);ah.scrollTop(ai);al.current_height=aj.clientY;al.current_x=al.offsetX;var ak=Math.round(am/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}).bind("mousewheel",function(aj,al,ai,ah){if(ai){ai*=50;var ak=Math.round(-ai/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}});this.top_labeltrack.bind("dragstart",function(ah,ai){return $("<div />").css({height:ad.browser_content_div.height()+ad.top_labeltrack.height()+ad.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(al,am){$(am.proxy).css({left:Math.min(al.pageX,am.startX)-ad.container.offset().left,width:Math.abs(al.pageX-am.startX)});var ai=Math.min(al.pageX,am.startX)-ad.container.offset().left,ah=Math.max(al.pageX,am.startX)-ad.container.offset().left,ak=(ad.high-ad.low),aj=ad.viewport_container.width();ad.update_location(Math.round(ai/aj*ak)+ad.low,Math.round(ah/aj*ak)+ad.low)}).bind("dragend",function(am,an){var ai=Math.min(am.pageX,an.startX),ah=Math.max(am.pageX,an.startX),ak=(ad.high-ad.low),aj=ad.viewport_container.width(),al=ad.low;ad.low=Math.round(ai/aj*ak)+al;ad.high=Math.round(ah/aj*ak)+al;$(an.proxy).remove();ad.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ad.resize_window()},500)});$(document).bind("redraw",function(){ad.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ad){return this.config.values[ad.toLowerCase()+"_color"]||this.config.values.n_color}});o(Y.prototype,y.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ae,ag,ad,ah){if(this.timer){clearTimeout(this.timer)}if(ah){var af=this;this.timer=setTimeout(function(){af.trigger("navigate",ae+":"+ag+"-"+ad)},500)}else{view.trigger("navigate",ae+":"+ag+"-"+ad)}},update_location:function(ad,af){this.location_span.text(commatize(ad)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ad)+"-"+commatize(af));var ae=view.chrom_select.val();if(ae!==""){this.trigger_navigate(ae,view.low,view.high,true)}},load_chroms:function(af){af.num=v;var ad=this,ae=$.Deferred();$.ajax({url:galaxy_config.root+"api/genomes/"+this.dbkey,data:af,dataType:"json",success:function(ah){if(ah.chrom_info.length===0){return}if(ah.reference){ad.add_label_track(new B(ad))}ad.chrom_data=ah.chrom_info;var ak='<option value="">Select Chrom/Contig</option>';for(var aj=0,ag=ad.chrom_data.length;aj<ag;aj++){var ai=ad.chrom_data[aj].chrom;ak+='<option value="'+ai+'">'+ai+"</option>"}if(ah.prev_chroms){ak+='<option value="previous">Previous '+v+"</option>"}if(ah.next_chroms){ak+='<option value="next">Next '+v+"</option>"}ad.chrom_select.html(ak);ad.chrom_start_index=ah.start_index;ae.resolve(ah.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ad.dbkey)}});return ae},change_chrom:function(ai,ae,ak){var af=this;if(!af.chrom_data){af.load_chroms_deferred.then(function(){af.change_chrom(ai,ae,ak)});return}if(!ai||ai==="None"){return}if(ai==="previous"){af.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){af.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(af.chrom_data,function(al,am){return al.chrom===ai})[0];if(aj===undefined){af.load_chroms({chrom:ai},function(){af.change_chrom(ai,ae,ak)});return}else{if(ai!==af.chrom){af.chrom=ai;af.chrom_select.val(af.chrom);af.max_high=aj.len-1;af.reset();for(var ah=0,ad=af.drawables.length;ah<ad;ah++){var ag=af.drawables[ah];if(ag.init){ag.init()}}if(af.reference_track){af.reference_track.init()}}if(ae&&ak){af.low=Math.max(ae,0);af.high=Math.min(ak,af.max_high)}else{af.low=0;af.high=af.max_high}af.reset_overview();af.request_redraw()}},go_to:function(ah){ah=ah.replace(/,/g,"");ah=ah.replace(/:|\-/g," ");var ae=ah.split(/\s+/),ag=ae[0],af=(ae[1]?parseInt(ae[1],10):null),ad=(ae[2]?parseInt(ae[2],10):null);if(!ad){af=af-15;ad=af+15}this.change_chrom(ag,af,ad)},move_fraction:function(af){var ad=this;var ae=ad.high-ad.low;this.move_delta(af*ae)},move_delta:function(ag){var ad=this;var af=ad.high-ad.low;if(ad.low-ag<ad.max_low){ad.low=ad.max_low;ad.high=ad.max_low+af}else{if(ad.high-ag>ad.max_high){ad.high=ad.max_high;ad.low=ad.max_high-af}else{ad.high-=ag;ad.low-=ag}}ad.request_redraw({data_fetch:false});if(this.redraw_on_move_fn){clearTimeout(this.redraw_on_move_fn)}this.redraw_on_move_fn=setTimeout(function(){ad.request_redraw()},200);var ae=ad.chrom_select.val();this.trigger_navigate(ae,ad.low,ad.high,true)},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);ad.init();this.changed();this.update_intro_div()},add_label_track:function(ad){ad.view=this;ad.init();this.label_tracks.push(ad)},remove_drawable:function(af,ae){y.prototype.remove_drawable.call(this,af);if(ae){var ad=this;af.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ae,af){var ad=this,ag=(af?[af]:ad.drawables);ac.each(ag,function(ah){var ai=ac.find(ad.tracks_to_be_redrawn,function(aj){return aj[0]===ah});if(ai){ai[1]=ae}else{ad.tracks_to_be_redrawn.push([ah,ae])}});if(!this.requested_redraw){requestAnimationFrame(function(){ad._redraw()});this.requested_redraw=true}},_redraw:function(){this.requested_redraw=false;var ad=this.low,ah=this.high;if(ad<this.max_low){ad=this.max_low}if(ah>this.max_high){ah=this.max_high}var ae=this.high-this.low;if(this.high!==0&&ae<this.min_separation){ah=ad+this.min_separation}this.low=Math.floor(ad);this.high=Math.ceil(ah);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ag=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var af=13;this.overview_box.css({left:ag,width:Math.max(af,ai)}).show();if(ai<af){this.overview_box.css("left",ag-(af-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ag,width:ai})}ac.each(this.tracks_to_be_redrawn,function(al){var aj=al[0],ak=al[1];if(aj){aj._draw(ak)}});this.tracks_to_be_redrawn=[];ac.each(this.label_tracks,function(aj){aj._draw()})},zoom_in:function(ae,af){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ag=this.high-this.low,ah=ag/2+this.low,ad=(ag/this.zoom_factor)/2;if(ae){ah=ae/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ah-ad);this.high=Math.round(ah+ad);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ae=this.high-this.low,af=ae/2+this.low,ad=(ae*this.zoom_factor)/2;this.low=Math.round(af-ad);this.high=Math.round(af+ad);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(af){if(this.overview_drawable){if(this.overview_drawable.dataset.id===af.dataset.id){return}this.overview_viewport.find(".track").remove()}var ae=af.copy({content_div:this.overview_viewport}),ad=this;ae.header_div.hide();ae.is_overview=true;ad.overview_drawable=ae;this.overview_drawable.postdraw_actions=function(){ad.overview_highlight.show().height(ad.overview_drawable.content_div.height());ad.overview_viewport.height(ad.overview_drawable.content_div.height()+ad.overview_box.outerHeight());ad.overview_close.show();ad.resize_window()};ad.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();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();view.overview_drawable=null}});var q=Backbone.RelationalModel.extend({defaults:{track:null,tool:null,},relations:[{type:Backbone.HasOne,key:"tool",relatedModel:R.Tool}],initialize:function(ae){var ad=this.get("tool"),af=ad.get("inputs").filter(function(ag){return(["data","hidden_data","group"].indexOf(ag.get("type"))!==-1)});ad.get("inputs").remove(af)}});var t=Backbone.View.extend({events:{"change input":"update_value"},render:function(){var af=this.$el.addClass("param-row"),ag=this.model;var ad=$("<div>").addClass("param-label").text(ag.get("label")).appendTo(af);var ae=$("<div/>").addClass("param-input").html(ag.get("html")).appendTo(af);ae.find(":input").val(ag.get("value"));$("<div style='clear: both;'/>").appendTo(af)},update_value:function(ad){this.model.set_value($(ad.target).val())}});var ab=Backbone.View.extend({render:function(){var ae=this;tool=this.model.get("tool"),parent_div=this.$el.addClass("dynamic-tool").hide();parent_div.bind("drag",function(ai){ai.stopPropagation()}).click(function(ai){ai.stopPropagation()}).bind("dblclick",function(ai){ai.stopPropagation()}).keydown(function(ai){ai.stopPropagation()});var af=$("<div class='tool-name'>").appendTo(parent_div).text(tool.get("name"));tool.get("inputs").each(function(aj){var ai=new t({model:aj});ai.render();parent_div.append(ai.$el)});parent_div.find("input").click(function(){$(this).select()});var ag=$("<div>").addClass("param-row").appendTo(parent_div);var ah=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ag);var ad=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ag);ad.click(function(){ae.run_on_region()});ah.click(function(){ae.run_on_dataset()})},update_params:function(){for(var ad=0;ad<this.params.length;ad++){this.params[ad].update_value()}},state_dict:function(){var ad=this.model.get("tool").get_param_values_dict();ad.visible=this.parent_div.is(":visible");return ad},run_on_dataset:function(){var ad=this.model.get("tool");this.run({target_dataset_id:this.model.get("track").dataset.id,action:"rerun",tool_id:ad.id},null,function(ae){show_modal(ad.get("name")+" is Running",ad.get("name")+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae=this.model.get("track"),ah=this.model.get("tool"),aj=new w.GenomeRegion({chrom:ae.view.chrom,start:ae.view.low,end:ae.view.high}),ak={target_dataset_id:ae.dataset.id,action:"rerun",tool_id:ah.id,regions:[aj.toJSON()]},ai=ae,am=ak.tool_id+ai.tool_region_and_parameters_str(aj),ad;if(ai.container===view){var al=new P(view,view,{name:this.name});var ag=ai.container.replace_drawable(ai,al,false);al.container_div.insertBefore(ai.view.content_div.children()[ag]);al.add_drawable(ai);ai.container_div.appendTo(al.content_div);ad=al}else{ad=ai.container}var af=new ai.constructor(view,ad,{name:am,hda_ldda:"hda"});af.init_for_tool_data();af.change_mode(ai.mode);af.set_filters_manager(ai.filters_manager.copy(af));af.update_icons();ad.add_drawable(af);af.tiles_div.text("Starting job.");this.run(ak,af,function(an){af.set_dataset(new X.Dataset(an));af.tiles_div.text("Running job.");af.init()})},run:function(ad,af,ag){ad.inputs=this.model.get("tool").get_inputs_dict();var ae=new j.ServerStateDeferred({ajax_settings:{url:galaxy_config.root+"api/tools",data:JSON.stringify(ad),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ah){return ah!=="pending"}});$.when(ae.go()).then(function(ah){if(ah==="no converter"){af.container_div.addClass("error");af.content_div.text(J)}else{if(ah.error){af.container_div.addClass("error");af.content_div.text(x+ah.message)}else{ag(ah)}}})}});var C=function(ad,ae){L.Scaler.call(this,ae);this.filter=ad};C.prototype.gen_val=function(ad){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ad[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ad){this.track=ad.track;this.params=ad.params;this.values={};this.restore_values((ad.saved_values?ad.saved_values:{}));this.onchange=ad.onchange};o(F.prototype,{set_param_default_value:function(ae,ad){var af=ac.find(this.params,function(ag){return ag.key===ae});if(af){af.default_value=ad}},set_param_value:function(ad,ae){var af=ac.find(this.params,function(ag){return ag.key===ad});if(af){if(typeof ae==="string"||ae instanceof String){if(ae.trim()===""){ae=af.default_value}else{if(af.type==="float"){ae=parseFloat(ae)}else{if(af.type==="int"){ae=parseInt(ae,10)}}}}}if(this.values[ad]!==ae){this.values[ad]=ae;return true}else{return false}},restore_values:function(ad){var ae=this;$.each(this.params,function(af,ag){if(ad[ag.key]!==undefined){ae.values[ag.key]=ad[ag.key]}else{ae.values[ag.key]=ag.default_value}})},build_form:function(){var ag=this;var ad=$("<div />");var af;function ae(al,ah){for(var ap=0;ap<al.length;ap++){af=al[ap];if(af.hidden){continue}var aj="param_"+ap;var au=ag.values[af.key];var aw=$("<div class='form-row' />").appendTo(ah);aw.append($("<label />").attr("for",aj).text(af.label+":"));if(af.type==="bool"){aw.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",au))}else{if(af.type==="text"){aw.append($('<input type="text"/>').attr("id",aj).val(au).click(function(){$(this).select()}))}else{if(af.type==="select"){var ar=$("<select />").attr("id",aj);for(var an=0;an<af.options.length;an++){$("<option/>").text(af.options[an].label).attr("value",af.options[an].value).appendTo(ar)}ar.val(au);aw.append(ar)}else{if(af.type==="color"){var av=$("<div/>").appendTo(aw),aq=$("<input />").attr("id",aj).attr("name",aj).val(au).css("float","left").appendTo(av).click(function(ay){$(".bs-tooltip").removeClass("in");var ax=$(this).siblings(".bs-tooltip").addClass("in");ax.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ax).height()/2)+($(this).height()/2)}).show();ax.click(function(az){az.stopPropagation()});$(document).bind("click.color-picker",function(){ax.hide();$(document).unbind("click.color-picker")});ay.stopPropagation()}),ao=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(av).attr("title","Set new random color").tooltip(),at=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(av).hide(),ak=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(at),ai=$("<div class='tooltip-arrow'></div>").appendTo(at),am=$.farbtastic(ak,{width:100,height:100,callback:aq,color:au});av.append($("<div/>").css("clear","both"));(function(ax){ao.click(function(){ax.setColor(j.get_random_color())})})(am)}else{aw.append($("<input />").attr("id",aj).attr("name",aj).val(au))}}}}if(af.help){aw.append($("<div class='help'/>").text(af.help))}}}ae(this.params,ad);return ad},update_from_form:function(ad){var af=this;var ae=false;$.each(this.params,function(ag,ai){if(!ai.hidden){var aj="param_"+ag;var ah=ad.find("#"+aj).val();if(ai.type==="bool"){ah=ad.find("#"+aj).is(":checked")}ae=af.set_param_value(ai.key,ah)||ae}});if(ae){this.onchange();this.track.changed()}}});var b=function(ad,ah,af,ae,ag){this.track=ad;this.region=ah;this.low=ah.get("start");this.high=ah.get("end");this.resolution=af;this.html_elt=$("<div class='track-tile'/>").append(ae).height($(ae).attr("height"));this.data=ag;this.stale=false};b.prototype.predisplay_actions=function(){};var M=function(ad,ah,af,ae,ag){b.call(this,ad,ah,af,ae,ag)};M.prototype.predisplay_actions=function(){};var O=function(ag,ao,ah,af,aj,aq,ak,ar,ae,an){b.call(this,ag,ao,ah,af,aj);this.mode=ak;this.all_slotted=ae;this.feature_mapper=an;this.has_icons=false;if(ar){this.has_icons=true;var al=this;af=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:af.width}).prependTo(this.html_elt);var am=new w.GenomeRegion({chrom:ag.view.chrom,start:this.low,end:this.high}),ap=aj.length,ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ad=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ai.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()});ad.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()})}};o(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ae=this,ad={};if(ae.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ap){if(!this.hovered){return}var ak=$(this).offset(),ao=ap.pageX-ak.left,an=ap.pageY-ak.top,au=ae.feature_mapper.get_feature_data(ao,an),al=(au?au[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!al||$(this).attr("id")!==al.toString()){$(this).remove()}});if(au){var ag=ad[al];if(!ag){var al=au[0],aq={name:au[3],start:au[1],end:au[2],strand:au[4]},aj=ae.track.filters_manager.filters,ai;for(var am=0;am<aj.length;am++){ai=aj[am];aq[ai.name]=au[ai.index]}var ag=$("<div/>").attr("id",al).addClass("feature-popup"),av=$("<table/>"),at,ar,aw;for(at in aq){ar=aq[at];aw=$("<tr/>").appendTo(av);$("<th/>").appendTo(aw).text(at);$("<td/>").attr("align","left").appendTo(aw).text(typeof(ar)==="number"?V(ar,2):ar)}ag.append($("<div class='feature-popup-inner'>").append(av));ad[al]=ag}ag.appendTo($(this).parents(".track-content").children(".overlay"));var ah=ao+parseInt(ae.html_elt.css("left"))-ag.width()/2,af=an+parseInt(ae.html_elt.css("top"))+7;ag.css("left",ah+"px").css("top",af+"px")}else{if(!ap.isPropagationStopped()){ap.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ap)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var f=function(ae,ad,af){o(af,{drag_handle_class:"draghandle"});p.call(this,ae,ad,af);this.dataset=(af.dataset?new X.Dataset(af.dataset):null);this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in af?af.data_query_wait:K);this.data_manager=("data_manager" in af?af.data_manager:new w.GenomeDataManager({dataset:this.dataset,genome:new w.Genome({key:ae.dbkey,chroms_info:{chrom_info:ae.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in af)||af.resize){this.add_resize_handle()}}};o(f.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ad){ad.view.set_overview(ad)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters()}else{ad.filters_manager.init_filters()}ad.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ad){ad.dynamic_tool_div.toggle();if(ad.dynamic_tool_div.is(":visible")){ad.set_name(ad.name+ad.tool_region_and_parameters_str())}else{ad.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ad){var ag='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',af=ac.template(ag,{track:ad});var ai=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(){var ak=$('select[name="regions"] option:selected').val(),am,aj=new w.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),al=ac.map($(".bookmark"),function(an){return new w.GenomeRegion({from_str:$(an).children(".position").text()})});if(ak==="cur"){am=[aj]}else{if(ak==="bookmarks"){am=al}else{am=[aj].concat(al)}}hide_modal();window.location.href=galaxy_config.root+"visualization/sweepster?"+$.param({dataset_id:ad.dataset.id,hda_ldda:ad.dataset.get("hda_ldda"),regions:JSON.stringify(new Backbone.Collection(am).toJSON())})},ah=function(aj){if((aj.keyCode||aj.which)===27){ai()}else{if((aj.keyCode||aj.which)===13){ae()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",af,{No:ai,Yes:ae})}},p.prototype.action_icons_def[2]],can_draw:function(){return this.dataset&&p.prototype.can_draw.call(this)},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ad=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ad)}this.name_div=$("<div/>").addClass("track-name").appendTo(ad).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ad},set_dataset:function(ad){this.dataset=ad;this.data_manager.set("dataset",ad)},on_resize:function(){this.request_draw({clear_tile_cache:true})},add_resize_handle:function(){var ad=this;var ag=false;var af=false;var ae=$("<div class='track-resize'>");$(ad.container_div).hover(function(){if(ad.content_visible){ag=true;ae.show()}},function(){ag=false;if(!af){ae.hide()}});ae.hide().bind("dragstart",function(ah,ai){af=true;ai.original_height=$(ad.content_div).height()}).bind("drag",function(ai,aj){var ah=Math.min(Math.max(aj.original_height+aj.deltaY,ad.min_height_px),ad.max_height_px);$(ad.tiles_div).css("height",ah);ad.visible_height_px=(ad.max_height_px===ah?0:ah);ad.on_resize()}).bind("dragend",function(ah,ai){ad.tile_cache.clear();af=false;if(!ag){ae.hide()}ad.config.values.height=ad.visible_height_px;ad.changed()}).appendTo(ad.container_div)},set_display_modes:function(ag,aj){this.display_modes=ag;this.mode=(aj?aj:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ae=this,ah={};for(var af=0,ad=ae.display_modes.length;af<ad;af++){var ai=ae.display_modes[af];ah[ai]=function(ak){return function(){ae.change_mode(ak);ae.icons_div.show();ae.container_div.mouseleave(function(){ae.icons_div.hide()})}}(ai)}make_popupmenu(this.action_icons.mode_icon,ah)},build_action_icons:function(){p.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof g){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof e){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(af){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.tiles_div.css("height","auto");ae.tiles_div.text("").children().remove();ae.container_div.removeClass("nodata error pending");if(!ae.dataset.id){return}var ad=$.Deferred(),ag={hda_ldda:ae.dataset.get("hda_ldda"),data_type:this.dataset_check_type,chrom:ae.view.chrom,retry:af};$.getJSON(this.dataset.url(),ag,function(ah){if(!ah||ah==="error"||ah.kind==="error"){ae.container_div.addClass("error");ae.tiles_div.text(m);if(ah.message){ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ah.message+"</pre>",{Close:hide_modal})}));ae.tiles_div.append($("<span/>").text(" "));ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ae.init(true)}))}}else{if(ah==="no converter"){ae.container_div.addClass("error");ae.tiles_div.text(J)}else{if(ah==="no data"||(ah.data!==undefined&&(ah.data===null||ah.data.length===0))){ae.container_div.addClass("nodata");ae.tiles_div.text(E)}else{if(ah==="pending"){ae.container_div.addClass("pending");ae.tiles_div.html(u);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(ah==="data"||ah.status==="data"){if(ah.valid_chroms){ae.valid_chroms=ah.valid_chroms;ae.update_icons()}ae.tiles_div.text(U);if(ae.view.chrom){ae.tiles_div.text("");ae.tiles_div.css("height",ae.visible_height_px+"px");ae.enabled=true;$.when.apply($,ae.predraw_init()).done(function(){ad.resolve();ae.container_div.removeClass("nodata error pending");ae.request_draw()})}else{ad.resolve()}}}}}}});this.update_icons();return ad},predraw_init:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){ad.container_div.addClass("line-track");var ag=ae.data;if(ag&&ag.min&&ag.max){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.config.set_param_default_value("min_value",af);ad.config.set_param_default_value("max_value",ah);ad.prefs.min_value=af;ad.prefs.max_value=ah}})},get_drawables:function(){return this}});var N=function(af,ae,ah){f.call(this,af,ae,ah);var ad=this;k(ad.container_div,ad.drag_handle_class,".group",ad);this.filters_manager=new h.FiltersManager(this,("filters" in ah?ah.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=(ah.tool?new q({track:this,tool:ah.tool,tool_state:ah.tool_state}):null);this.tile_cache=new w.Cache(Q);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){var ag=new ab({model:this.tool});ag.render();this.dynamic_tool_div=ag.$el;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(ah.mode){this.change_mode(ah.mode)}};o(N.prototype,p.prototype,f.prototype,{action_icons_def:f.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.slotters[ad.view.resolution_px_b].max_rows*=2;ad.request_draw({clear_tile_cache:true})},hide:true}]),copy:function(ad){var ae=this.to_dict();o(ae,{data_manager:this.data_manager});var af=new this.constructor(this.view,ad,ae);af.change_mode(this.mode);af.enabled=this.enabled;return af},set_filters_manager:function(ad){this.filters_manager=ad;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,dataset:{id:this.dataset.id,hda_ldda:this.dataset.get("hda_ldda")},prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},set_min_max:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){var ag=ae.data;if(isNaN(parseFloat(ad.prefs.min_value))||isNaN(parseFloat(ad.prefs.max_value))){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.prefs.min_value=af;ad.prefs.max_value=ah}})},change_mode:function(ae){var ad=this;ad.mode=ae;ad.config.values.mode=ae;if(ae==="Auto"){this.data_manager.clear()}ad.request_draw({clear_tile_cache:true});this.action_icons.mode_icon.attr("title","Set display mode (now: "+ad.mode+")");return ad},update_icons:function(){var ad=this;if(ad.filters_available){ad.action_icons.filters_icon.show()}else{ad.action_icons.filters_icon.hide()}if(ad.tool){ad.action_icons.tools_icon.show();ad.action_icons.param_space_viz_icon.show()}else{ad.action_icons.tools_icon.hide();ad.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ae,ad){return ae+"_"+ad},request_draw:function(ad){if(ad&&ad.clear_tile_cache){this.tile_cache.clear()}this.view.request_redraw(ad,this)},before_draw:function(){this.max_height_px=0},_draw:function(aq){if(!this.can_draw()){return}var an=aq&&aq.clear_after,al=this.view.low,ah=this.view.high,ak=ah-al,ae=this.view.container.width(),ap=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;ap=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ad=Math.floor(al/(ag*S)),am,ai,aj=[],ao=[];while((ad*S*ag)<ah){am=this._get_tile_bounds(ad,ag);ai=this.draw_helper(am,ag,ap,aq);aj.push(ai);$.when(ai).then(function(ar){ao.push(ar)});ad+=1}if(!an){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;$.when.apply($,aj).then(function(){af.tiles_div.children(".remove").remove();ao=ac.filter(ao,function(ar){return ar!==null});if(ao.length!==0){af.postdraw_actions(ao,ae,ap,an)}})},_add_yaxis_label:function(ag,ai){var ae=this,ah=(ag==="max"?"top":"bottom"),aj=(ag==="max"?"max":"min"),ad=(ag==="max"?"max_value":"min_value"),ai=ai||function(){ae.request_draw({clear_tile_cache:true})},af=this.container_div.find(".yaxislabel."+ah);if(af.length!==0){af.text(ae.prefs[ad])}else{af=$("<div/>").text(ae.prefs[ad]).make_text_editable({num_cols:12,on_finish:function(ak){$(".bs-tooltip").remove();ae.config.set_param_value(ad,ak);ai()},help_text:"Set "+aj+" value"}).addClass("yaxislabel "+ah).css("color",this.prefs.label_color);this.container_div.prepend(af)}},postdraw_actions:function(ag,ah,aj,ad){var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length>0){this.max_height_px=0;var ae=this;ac.each(ag,function(ak){if(!(ak instanceof M)){ak.html_elt.remove();ae.draw_helper(ak.region,ak.resolution,aj,{force:true,mode:"Coverage"})}});ae._add_yaxis_label("max")}else{this.container_div.find(".yaxislabel").remove();var ai=ac.find(ag,function(ak){return ak.has_icons});if(ai){ac.each(ag,function(ak){if(!ak.has_icons){ak.html_elt.css("padding-top",D)}})}}},get_mode:function(ad){return this.mode},update_auto_mode:function(ad){},_get_drawables:function(){return[this]},draw_helper:function(am,ag,ap,aq){if(!aq){aq={}}var ae=aq.force,ao=!(aq.data_fetch===false),aj=aq.mode||this.mode,af=this,ah=this._get_drawables(),an=this._gen_tile_cache_key(ap,am),ai=function(ar){return(ar&&"track" in ar)};var ak=(ae?undefined:af.tile_cache.get_elt(an));if(ak){if(ai(ak)){af.show_tile(ak,ap)}return ak}if(!ao){return null}var al=function(){var ar=(ac.find(A,function(au){return au===aj})?"Coverage":aj);var at=ac.map(ah,function(au){return au.data_manager.get_data(am,ar,ag,af.data_url_extra_params)});if(view.reference_track){at.push(view.reference_track.data_manager.get_data(am,aj,ag,view.reference_track.data_url_extra_params))}return at};var ad=$.Deferred();af.tile_cache.set_elt(an,ad);$.when.apply($,al()).then(function(){var ar=al(),ax=ar,aD;if(view.reference_track){aD=view.reference_track.data_manager.subset_entry(ar.pop(),am)}var ay=[],av=[];ac.each(ah,function(aI,aF){var aH=aI.mode,aG=ax[aF];if(aH==="Auto"){aH=aI.get_mode(aG);aI.update_auto_mode(aH)}ay.push(aH);av.push(aI.get_canvas_height(aG,aH,ap,at))});var aw=af.view.canvas_manager.new_canvas(),az=am.get("start"),aE=am.get("end"),au=0,at=Math.ceil((aE-az)*ap)+af.left_offset,aB=ac.max(av),aA;aw.width=at;aw.height=(aq.height||aB);var aC=aw.getContext("2d");aC.translate(af.left_offset,0);if(ah.length>1){aC.globalAlpha=0.5;aC.globalCompositeOperation="source-over"}ac.each(ah,function(aG,aF){aA=aG.draw_tile(ax[aF],aC,ay[aF],ag,am,ap,aD)});if(aA!==undefined){af.tile_cache.set_elt(an,aA);af.show_tile(aA,ap)}ad.resolve(aA)});return ad},get_canvas_height:function(ad,af,ag,ae){return this.visible_height_px},_draw_line_track_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.LinePainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new M(this,ai,ah,ag,ad.data)},draw_tile:function(ad,ae,ai,ag,ah,aj,af){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(af,ai){var ae=this,ad=af.html_elt;af.predisplay_actions();var ah=(af.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ah-=this.left_offset}ad.css({position:"absolute",top:0,left:ah});if(ad.hasClass("remove")){ad.removeClass("remove")}else{this.tiles_div.append(ad)}af.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,af.html_elt.height());af.html_elt.parent().children().css("height",this.max_height_px+"px");var ag=this.max_height_px;if(this.visible_height_px!==0){ag=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",ag+"px")},_get_tile_bounds:function(ad,ae){var ag=Math.floor(ad*S*ae),ah=Math.ceil(S*ae),af=(ag+ah<=this.view.max_high?ag+ah:this.view.max_high);return new w.GenomeRegion({chrom:this.view.chrom,start:ag,end:af})},tool_region_and_parameters_str:function(ag){var ad=this,af=(ag!==undefined?ag.toString():"all"),ae=ac.values(ad.tool.get("tool").get_inputs_dict()).join(", ");return" - region=["+af+"], parameters=["+ae+"]"},data_and_mode_compatible:function(ad,ae){if(ae==="Auto"){return true}else{if(ae==="Coverage"){return ad.dataset_type==="bigwig"}else{if(ad.extra_info==="no_detail"){return false}else{return true}}}},can_subset:function(ad){if(ad.dataset_type==="bigwig"||ad.message||ad.extra_info==="no_detail"){return false}return true},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(af,ag,ai,ad){var ae=this;ae.normal_postdraw_actions(af,ag,ai,ad);ae.dataset_check_type="converted_datasets_state";ae.data_query_wait=K;var ah=new j.ServerStateDeferred({url:ae.dataset_state_url,url_params:{dataset_id:ae.dataset.id,hda_ldda:ae.dataset.get("hda_ldda")},interval:ae.data_query_wait,success_fn:function(aj){return aj!=="pending"}});$.when(ah.go()).then(function(){ae.data_manager.set("data_type","data")});ae.postdraw_actions=ae.normal_postdraw_actions}}});var W=function(ae,ad){var af={resize:false};f.call(this,ae,ad,af);this.container_div.addClass("label-track")};o(W.prototype,f.prototype,{build_header_div:function(){},init:function(){this.enabled=true},predraw_init:function(){},_draw:function(ah){var af=this.view,ag=af.high-af.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ag)/Math.log(10)))),ad=Math.floor(af.low/ak)*ak,ai=this.view.container.width(),ae=$("<div style='position: relative; height: 1.3em;'></div>");while(ad<af.high){var aj=(ad-af.low)/ag*ai;ae.append($("<div class='label'>"+commatize(ad)+"</div>").css({position:"absolute",left:aj-1}));ad+=ak}this.content_div.children(":first").remove();this.content_div.append(ae)}});var e=function(ae,ad,ah){this.display_modes=A;N.call(this,ae,ad,ah);this.drawables=[];if("drawables" in ah){var ag;for(var af=0;af<ah.drawables.length;af++){ag=ah.drawables[af];this.drawables[af]=n(ag,ae,null);if(ag.left_offset>this.left_offset){this.left_offset=ag.left_offset}}this.enabled=true}ac.each(this.drawables,function(ai){if(ai instanceof c||ai instanceof T){ai.change_mode("Coverage")}});this.update_icons();this.obj_type="CompositeTrack"};o(e.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_group()}}].concat(N.prototype.action_icons_def),to_dict:y.prototype.to_dict,add_drawable:y.prototype.add_drawable,unpack_drawables:y.prototype.unpack_drawables,change_mode:function(ad){N.prototype.change_mode.call(this,ad);for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae].change_mode(ad)}},init:function(){var af=[];for(var ae=0;ae<this.drawables.length;ae++){af.push(this.drawables[ae].init())}var ad=this;$.when.apply($,af).then(function(){ad.enabled=true;ad.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:p.prototype.can_draw,_get_drawables:function(){return this.drawables},show_group:function(){var ag=new P(this.view,this.container,{name:this.name}),ad;for(var af=0;af<this.drawables.length;af++){ad=this.drawables[af];ad.update_icons();ag.add_drawable(ad);ad.container=ag;ag.content_div.append(ad.container_div)}var ae=this.container.replace_drawable(this,ag,true);ag.request_draw({clear_tile_cache:true})},before_draw:function(){N.prototype.before_draw.call(this);var ae=ac.min(ac.map(this.drawables,function(af){return af.prefs.min_value})),ad=ac.max(ac.map(this.drawables,function(af){return af.prefs.max_value}));this.prefs.min_value=ae;this.prefs.max_value=ad;ac.each(this.drawables,function(af){af.prefs.min_value=ae;af.prefs.max_value=ad})},update_all_min_max:function(){var ad=this;ac.each(this.drawables,function(ae){ae.prefs.min_value=ad.prefs.min_value;ae.prefs.max_value=ad.prefs.max_value});this.request_draw({clear_tile_cache:true})},postdraw_actions:function(aj,ad,am,ai){N.prototype.postdraw_actions.call(this,aj,ad,am,ai);var ah=-1;for(var af=0;af<aj.length;af++){var ak=aj[af].html_elt.find("canvas").height();if(ak>ah){ah=ak}}for(var af=0;af<aj.length;af++){var ag=aj[af];if(ag.html_elt.find("canvas").height()!==ah){this.draw_helper(ag.region,ag.resolution,am,{force:true,height:ah});ag.html_elt.remove()}}var ae=this,al=function(){ae.update_all_min_max()};this._add_yaxis_label("min",al);this._add_yaxis_label("max",al)}});var B=function(ad){N.call(this,ad,{content_div:ad.top_labeltrack},{resize:false});ad.reference_track=this;this.left_offset=200;this.visible_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=galaxy_config.root+"api/genomes//"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new w.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};o(B.prototype,p.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},predraw_init:function(){},can_draw:p.prototype.can_draw,draw_helper:function(af,ae,ag,ad){if(ag>this.view.canvas_manager.char_width_px){this.tiles_div.show();return N.prototype.draw_helper.call(this,af,ae,ag,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ad){return true},draw_tile:function(ag,am,ah,ae,aj,an){var af=this.data_manager.subset_entry(ag,aj),al=af.data;var ad=am.canvas;am.font=am.canvas.manager.default_font;am.textAlign="center";for(var ai=0,ak=al.length;ai<ak;ai++){am.fillStyle=this.view.get_base_color(al[ai]);am.fillText(al[ai],Math.floor(ai*an),10)}return new b(this,aj,ae,ad,af)}});var g=function(af,ae,ag){var ad=this;this.display_modes=A;this.mode="Histogram";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:j.get_random_color()},{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:32,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(g.prototype,p.prototype,N.prototype,{before_draw:function(){},draw_tile:function(ad,ae,ah,af,ag,ai){return this._draw_line_track_tile(ad,ae,ah,af,ag,ai)},can_subset:function(ad){return(ad.data[1][0]-ad.data[0][0]===1)},postdraw_actions:function(ae,af,ag,ad){this._add_yaxis_label("max");this._add_yaxis_label("min")}});var r=function(af,ae,ag){var ad=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);this.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(r.prototype,p.prototype,N.prototype,{draw_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.DiagonalHeatmapPainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new b(this,ai,ah,ag,ad.data)}});var c=function(ag,af,ai){var ae=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ag,af,ai);var ah=j.get_random_color(),ad=j.get_random_color([ah,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ah},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ai.prefs,onchange:function(){ae.set_name(ae.prefs.name);ae.set_painter_from_config();ae.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};o(c.prototype,p.prototype,N.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},postdraw_actions:function(an,af,ao,am){N.prototype.postdraw_actions.call(this,an,af,ao,am);var ah=this,ai;if(ah.filters_manager){var ag=ah.filters_manager.filters;for(var ak=0;ak<ag.length;ak++){ag[ak].update_ui_elt()}var aj=false,al,ae;for(ai=0;ai<an.length;ai++){if(an[ai].data.length){al=an[ai].data[0];for(var ak=0;ak<ag.length;ak++){ae=ag[ak];if(ae.applies_to(al)&&ae.min!==ae.max){aj=true;break}}}}if(ah.filters_available!==aj){ah.filters_available=aj;if(!ah.filters_available){ah.filters_manager.hide()}ah.update_icons()}}if(an[0] instanceof O){var ad=true;for(ai=0;ai<an.length;ai++){if(!an[ai].all_slotted){ad=false;break}}if(!ad){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ad){var ad;if(this.mode==="Auto"){if(ad==="no_detail"){ad="feature spans"}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ad+")")}},incremental_slots:function(ah,ad,ag){var ae=this.view.canvas_manager.dummy_context,af=this.slotters[ah];if(!af||(af.mode!==ag)){af=new (s.FeatureSlotter)(ah,ag,z,function(ai){return ae.measureText(ai)});this.slotters[ah]=af}return af.slot_features(ad)},get_mode:function(ad){if(ad.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}return mode},get_canvas_height:function(ad,ah,ai,ae){if(ah==="Coverage"||ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=this.incremental_slots(ai,ad.data,ah);var af=new (this.painter)(null,null,null,this.prefs,ah);return Math.max(aa,af.get_required_height(ag,ae))}},draw_tile:function(an,ar,ap,at,ag,ak,af){var aq=this,ae=ar.canvas,az=ag.get("start"),ad=ag.get("end"),ah=this.left_offset;if(an.dataset_type==="bigwig"){return this._draw_line_track_tile(an,ar,ap,at,ag,ak)}var aj=[],ao=this.slotters[ak].slots;all_slotted=true;if(an.data){var al=this.filters_manager.filters;for(var au=0,aw=an.data.length;au<aw;au++){var ai=an.data[au];var av=false;var am;for(var ay=0,aD=al.length;ay<aD;ay++){am=al[ay];am.update_attrs(ai);if(!am.keep(ai)){av=true;break}}if(!av){aj.push(ai);if(!(ai[0] in ao)){all_slotted=false}}}}var aC=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),aA=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aB=new (this.painter)(aj,az,ad,this.prefs,ap,aC,aA,af,function(aE){return aq.view.get_base_color(aE)});var ax=null;ar.fillStyle=this.prefs.block_color;ar.font=ar.canvas.manager.default_font;ar.textAlign="right";if(an.data){ax=aB.draw(ar,ae.width,ae.height,ak,ao);ax.translation=-ah}return new O(aq,ag,at,ae,an.data,ak,ap,an.message,all_slotted,ax)}});var Z=function(ae,ad,af){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Histogram color",type:"color",default_value:j.get_random_color()},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};o(Z.prototype,p.prototype,N.prototype,{draw_tile:function(ad,ag,aj,ah,ai,ak){if(ad.dataset_type==="bigwig"){return this._draw_line_track_tile(ad,ag,"Histogram",ah,ai,ak)}else{var af=this.view,ae=new (this.painter)(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj,function(al){return af.get_base_color(al)});ae.draw(ag,ag.canvas.width,ag.canvas.height,ak);return new b(this,ai,ah,ag.canvas,ad.data)}},get_canvas_height:function(ad,ah,ai,af){if(ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=new (this.painter)(null,null,null,this.prefs,ah);var ae=(this.dataset.get_metadata("sample_names")?this.dataset.get_metadata("sample_names").length:0);if(ae===0&&ad.data.length!==0){ae=ad.data[0][7].match(/,/g);if(ae===null){ae=1}else{ae=ae.length+1}}return ag.get_required_height(ae)}},predraw_init:function(){var ad=[f.prototype.predraw_init.call(this)];if(!this.dataset.get_metadata("sample_names")){ad.push(this.dataset.fetch())}return ad},postdraw_actions:function(ag,ah,aj,ae){N.prototype.postdraw_actions.call(this,ag,ah,aj,ae);var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length===0&&this.prefs.show_labels){var ad;if(this.container_div.find(".yaxislabel.variant").length===0){ad=this.prefs.summary_height/2;this.tiles_div.prepend($("<div/>").text("Summary").addClass("yaxislabel variant top").css({"font-size":ad+"px",top:(this.prefs.summary_height-ad)/2+"px"}));if(this.prefs.show_sample_data){var ai=this.dataset.get("metadata").get("sample_names").join("<br/>");this.tiles_div.prepend($("<div/>").html(ai).addClass("yaxislabel variant top sample").css({top:this.prefs.summary_height+2,}))}}ad=(this.mode==="Squish"?5:10)+"px";$(this.tiles_div).find(".sample").css({"font-size":ad,"line-height":ad});$(this.tiles_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel.variant").remove()}}});var T=function(af,ae,ah){c.call(this,af,ae,ah);var ag=j.get_random_color(),ad=j.get_random_color([ag,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{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},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"}],saved_values:ah.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=(af.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};o(T.prototype,p.prototype,N.prototype,c.prototype);var d={CompositeTrack:e,DrawableGroup:P,DiagonalHeatmapTrack:r,FeatureTrack:c,LineTrack:g,ReadTrack:T,VariantTrack:Z,VcfTrack:Z};var n=function(af,ae,ad){if("copy" in af){return af.copy(ad)}else{var ag=af.obj_type;if(!ag){ag=af.track_type}return new d[ag](ae,ad,af)}};return{TracksterView:Y,DrawableGroup:P,LineTrack:g,FeatureTrack:c,DiagonalHeatmapTrack:r,ReadTrack:T,VariantTrack:Z,CompositeTrack:e,object_from_template:n}});
\ No newline at end of file
+define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","viz/trackster/filters","mvc/data","mvc/tools"],function(ac,w,j,s,L,h,X,R){var o=ac.extend;var l={};var i=function(ad,ae){l[ad.attr("id")]=ae};var k=function(ad,af,ah,ag){ah=".group";var ae={};l[ad.attr("id")]=ag;ad.bind("drag",{handle:"."+af,relative:true},function(ap,aq){var ao=$(this),au=$(this).parent(),al=au.children(),an=l[$(this).attr("id")],ak,aj,ar,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ar=aj.position().top;ai=ar+aj.outerHeight();if(aq.offsetY<ar){$(this).insertBefore(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable_before(an,at);return}else{if(aq.offsetY>ai){$(this).insertAfter(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable(an);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ar=ak.position().top;ai=ar+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&aq.offsetY>=ar&&aq.offsetY<=ai){if(aq.offsetY-ar<ai-aq.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}if(an.container){an.container.remove_drawable(an)}l[ak.attr("id")].add_drawable(an);return}}for(am=0;am<al.length;am++){ak=$(al.get(am));if(aq.offsetY<ak.position().top&&!(ak.hasClass("reference-track")||ak.hasClass("intro"))){break}}if(am===al.length){if(this!==al.get(am-1)){au.append(this);l[au.attr("id")].move_drawable(an,am)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am));l[au.attr("id")].move_drawable(an,(aq.deltaY>0?am-1:am))}}}).bind("dragstart",function(){ae["border-top"]=ad.css("border-top");ae["border-bottom"]=ad.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ae)})};var aa=16,G=9,D=20,z=100,I=12000,S=400,K=5000,v=100,m="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",u="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",x="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20,A=["Histogram","Line","Filled","Intensity"];function V(ae,ad){if(!ad){ad=0}var af=Math.pow(10,ad);return Math.round(ae*af)/af}var p=function(ae,ad,ag){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ag.name;this.view=ae;this.container=ad;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ag.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ah){ah.stopPropagation()});var af=this;this.container_div.hover(function(){af.icons_div.show()},function(){af.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ad){if(ad.content_visible){ad.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ad.hide_contents();ad.content_visible=false}else{ad.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ad.content_visible=true;ad.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ae){var ag=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){ae.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},af=function(ah){if((ah.keyCode||ah.which)===27){ag()}else{if((ah.keyCode||ah.which)===13){ad()}}};$(window).bind("keypress.check_enter_esc",af);show_modal("Configure",ae.config.build_form(),{Cancel:ag,OK:ad})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.remove()}}];o(p.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(ad){},to_dict:function(){},set_name:function(ad){this.old_name=this.name;this.name=ad;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ad=this.view;this.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ae,aj,ai,ah,ad,ag){var af=this;this.action_icons[ae]=$("<a/>").attr("href","javascript:void(0);").attr("title",aj).addClass("icon-button").addClass(ai).tooltip().click(function(){ah(af)}).appendTo(this.icons_div);if(ag){this.action_icons[ae].hide()}},build_action_icons:function(ad){var af;for(var ae=0;ae<ad.length;ae++){af=ad[ae];this.add_action_icon(af.name,af.title,af.css_class,af.on_click_fn,af.prepend,af.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var y=function(ae,ad,af){p.call(this,ae,ad,af);this.obj_type=af.obj_type;this.drawables=[]};o(y.prototype,p.prototype,{unpack_drawables:function(af){this.drawables=[];var ae;for(var ad=0;ad<af.length;ad++){ae=n(af[ad],this.view,this);this.add_drawable(ae)}},init:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].init()}},_draw:function(ad){for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae]._draw(ad)}},to_dict:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ae}},add_drawable:function(ad){this.drawables.push(ad);ad.container=this;this.changed()},add_drawable_before:function(af,ad){this.changed();var ae=this.drawables.indexOf(ad);if(ae!==-1){this.drawables.splice(ae,0,af);return true}return false},replace_drawable:function(af,ad,ae){var ag=this.drawables.indexOf(af);if(ag!==-1){this.drawables[ag]=ad;if(ae){af.container_div.replaceWith(ad.container_div)}this.changed()}return ag},remove_drawable:function(ae){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);ae.container=null;this.changed();return true}return false},move_drawable:function(ae,af){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);this.drawables.splice(af,0,ae);this.changed();return true}return false},get_drawables:function(){return this.drawables},get_tracks:function(ag){var ad=this.drawables.slice(0),ae=[],af;while(ad.length!==0){af=ad.shift();if(af instanceof ag){ae.push(af)}else{if(af.drawables){ad=ad.concat(af.drawables)}}}return ae}});var P=function(ae,ad,ag){o(ag,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});y.call(this,ae,ad,ag);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);i(this.container_div,this);i(this.content_div,this);k(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new h.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ag){this.unpack_drawables(ag.drawables)}if("filters" in ag){var af=this.filters_manager;this.filters_manager=new h.FiltersManager(this,ag.filters);af.parent_div.replaceWith(this.filters_manager.parent_div);if(ag.filters.visible){this.setup_multitrack_filtering()}}};o(P.prototype,p.prototype,y.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters();ad._restore_filter_managers()}else{ad.setup_multitrack_filtering();ad.request_draw({clear_tile_cache:true})}ad.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var ad=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ad)}return ad},build_header_div:function(){var ad=$("<div/>").addClass("track-header");ad.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ad);return ad},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var af=this.drawables.length;if(af===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(af===1){if(this.drawables[0] instanceof e){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var am,al,aj,ap=true,ah=this.drawables[0].get_type(),ad=0;for(am=0;am<af;am++){aj=this.drawables[am];if(aj.get_type()!==ah){can_composite=false;break}if(aj instanceof c){ad++}}if(ap||ad===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ad>1&&ad===this.drawables.length){var aq={},ae;aj=this.drawables[0];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];aq[ae.name]=[ae]}for(am=1;am<this.drawables.length;am++){aj=this.drawables[am];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];if(ae.name in aq){aq[ae.name].push(ae)}}}this.filters_manager.remove_all();var ag,ai,ak,an;for(var ao in aq){ag=aq[ao];if(ag.length===ad){ai=new h.NumberFilter({name:ag[0].name,index:ag[0].index});this.filters_manager.add_filter(ai)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].filters_manager=this.saved_filters_managers[ad]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ad=0;ad<this.drawables.length;ad++){drawable=this.drawables[ad];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ae=new e(this.view,this.view,{name:this.name,drawables:this.drawables});var ad=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);this.update_icons()},remove_drawable:function(ad){y.prototype.remove_drawable.call(this,ad);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ad=o(y.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ad},request_draw:function(ad){ac.each(this.drawables,function(ae){ae.request_draw(ad)})}});var Y=Backbone.View.extend({initialize:function(ad){o(ad,{obj_type:"View"});y.call(this,"View",ad.container,ad);this.chrom=null;this.vis_id=ad.vis_id;this.dbkey=ad.dbkey;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.render();this.canvas_manager=new w.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"}],saved_values:ad.prefs,onchange:function(){track.request_redraw({clear_tile_cache:true})}})},render:function(){this.requested_redraw=false;var af=this.container,ad=this;this.top_container=$("<div/>").addClass("top-container").appendTo(af);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(af);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(af);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;i(this.viewport_container,ad);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ag=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){w.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":ad.dbkey},function(ah){ac.each(ah,function(ai){ad.add_drawable(n(ai,ad,ad))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-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/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").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").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ae=function(ah){if(ah.type==="focusout"||(ah.keyCode||ah.which)===13||(ah.keyCode||ah.which)===27){if((ah.keyCode||ah.which)!==27){ad.go_to($(this).val())}$(this).hide();$(this).val("");ad.location_span.show();ad.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ae).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ad.location_span.hide();ad.chrom_select.hide();ad.nav_input.val(ad.chrom+":"+ad.low+"-"+ad.high);ad.nav_input.css("display","inline-block");ad.nav_input.select();ad.nav_input.focus();ad.nav_input.autocomplete({source:function(aj,ah){var ak=[],ai=$.map(ad.get_tracks(c),function(al){return al.data_manager.search_features(aj.term).success(function(am){ak=ak.concat(am)})});$.when.apply($,ai).done(function(){ah($.map(ak,function(al){return{label:al[0],value:al[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ad.zoom_out();ad.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ad.zoom_in();ad.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ad.change_chrom(ad.chrom_select.val())});this.browser_content_div.click(function(ah){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ah){ad.zoom_in(ah.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ah,ai){this.current_x=ai.offsetX}).bind("drag",function(ah,aj){var ak=aj.offsetX-this.current_x;this.current_x=aj.offsetX;var ai=Math.round(ak/ad.viewport_container.width()*(ad.max_high-ad.max_low));ad.move_delta(-ai)});this.overview_close.click(function(){ad.reset_overview()});this.viewport_container.bind("draginit",function(ah,ai){if(ah.clientX>ad.viewport_container.width()-16){return false}}).bind("dragstart",function(ah,ai){ai.original_low=ad.low;ai.current_height=ah.clientY;ai.current_x=ai.offsetX}).bind("drag",function(aj,al){var ah=$(this);var am=al.offsetX-al.current_x;var ai=ah.scrollTop()-(aj.clientY-al.current_height);ah.scrollTop(ai);al.current_height=aj.clientY;al.current_x=al.offsetX;var ak=Math.round(am/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}).bind("mousewheel",function(aj,al,ai,ah){if(ai){ai*=50;var ak=Math.round(-ai/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}});this.top_labeltrack.bind("dragstart",function(ah,ai){return $("<div />").css({height:ad.browser_content_div.height()+ad.top_labeltrack.height()+ad.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(al,am){$(am.proxy).css({left:Math.min(al.pageX,am.startX)-ad.container.offset().left,width:Math.abs(al.pageX-am.startX)});var ai=Math.min(al.pageX,am.startX)-ad.container.offset().left,ah=Math.max(al.pageX,am.startX)-ad.container.offset().left,ak=(ad.high-ad.low),aj=ad.viewport_container.width();ad.update_location(Math.round(ai/aj*ak)+ad.low,Math.round(ah/aj*ak)+ad.low)}).bind("dragend",function(am,an){var ai=Math.min(am.pageX,an.startX),ah=Math.max(am.pageX,an.startX),ak=(ad.high-ad.low),aj=ad.viewport_container.width(),al=ad.low;ad.low=Math.round(ai/aj*ak)+al;ad.high=Math.round(ah/aj*ak)+al;$(an.proxy).remove();ad.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ad.resize_window()},500)});$(document).bind("redraw",function(){ad.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ad){return this.config.values[ad.toLowerCase()+"_color"]||this.config.values.n_color}});o(Y.prototype,y.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ae,ag,ad,ah){if(this.timer){clearTimeout(this.timer)}if(ah){var af=this;this.timer=setTimeout(function(){af.trigger("navigate",ae+":"+ag+"-"+ad)},500)}else{view.trigger("navigate",ae+":"+ag+"-"+ad)}},update_location:function(ad,af){this.location_span.text(commatize(ad)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ad)+"-"+commatize(af));var ae=view.chrom_select.val();if(ae!==""){this.trigger_navigate(ae,view.low,view.high,true)}},load_chroms:function(af){af.num=v;var ad=this,ae=$.Deferred();$.ajax({url:galaxy_config.root+"api/genomes/"+this.dbkey,data:af,dataType:"json",success:function(ah){if(ah.chrom_info.length===0){return}if(ah.reference){ad.add_label_track(new B(ad))}ad.chrom_data=ah.chrom_info;var ak='<option value="">Select Chrom/Contig</option>';for(var aj=0,ag=ad.chrom_data.length;aj<ag;aj++){var ai=ad.chrom_data[aj].chrom;ak+='<option value="'+ai+'">'+ai+"</option>"}if(ah.prev_chroms){ak+='<option value="previous">Previous '+v+"</option>"}if(ah.next_chroms){ak+='<option value="next">Next '+v+"</option>"}ad.chrom_select.html(ak);ad.chrom_start_index=ah.start_index;ae.resolve(ah.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ad.dbkey)}});return ae},change_chrom:function(ai,ae,ak){var af=this;if(!af.chrom_data){af.load_chroms_deferred.then(function(){af.change_chrom(ai,ae,ak)});return}if(!ai||ai==="None"){return}if(ai==="previous"){af.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){af.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(af.chrom_data,function(al,am){return al.chrom===ai})[0];if(aj===undefined){af.load_chroms({chrom:ai},function(){af.change_chrom(ai,ae,ak)});return}else{if(ai!==af.chrom){af.chrom=ai;af.chrom_select.val(af.chrom);af.max_high=aj.len-1;af.reset();for(var ah=0,ad=af.drawables.length;ah<ad;ah++){var ag=af.drawables[ah];if(ag.init){ag.init()}}if(af.reference_track){af.reference_track.init()}}if(ae&&ak){af.low=Math.max(ae,0);af.high=Math.min(ak,af.max_high)}else{af.low=0;af.high=af.max_high}af.reset_overview();af.request_redraw()}},go_to:function(ah){ah=ah.replace(/,/g,"");ah=ah.replace(/:|\-/g," ");var ae=ah.split(/\s+/),ag=ae[0],af=(ae[1]?parseInt(ae[1],10):null),ad=(ae[2]?parseInt(ae[2],10):null);if(!ad){af=af-15;ad=af+15}this.change_chrom(ag,af,ad)},move_fraction:function(af){var ad=this;var ae=ad.high-ad.low;this.move_delta(af*ae)},move_delta:function(ag){var ad=this;var af=ad.high-ad.low;if(ad.low-ag<ad.max_low){ad.low=ad.max_low;ad.high=ad.max_low+af}else{if(ad.high-ag>ad.max_high){ad.high=ad.max_high;ad.low=ad.max_high-af}else{ad.high-=ag;ad.low-=ag}}ad.request_redraw({data_fetch:false});if(this.redraw_on_move_fn){clearTimeout(this.redraw_on_move_fn)}this.redraw_on_move_fn=setTimeout(function(){ad.request_redraw()},200);var ae=ad.chrom_select.val();this.trigger_navigate(ae,ad.low,ad.high,true)},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);ad.init();this.changed();this.update_intro_div()},add_label_track:function(ad){ad.view=this;ad.init();this.label_tracks.push(ad)},remove_drawable:function(af,ae){y.prototype.remove_drawable.call(this,af);if(ae){var ad=this;af.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ae,af){var ad=this,ag=(af?[af]:ad.drawables);ac.each(ag,function(ah){var ai=ac.find(ad.tracks_to_be_redrawn,function(aj){return aj[0]===ah});if(ai){ai[1]=ae}else{ad.tracks_to_be_redrawn.push([ah,ae])}});if(!this.requested_redraw){requestAnimationFrame(function(){ad._redraw()});this.requested_redraw=true}},_redraw:function(){this.requested_redraw=false;var ad=this.low,ah=this.high;if(ad<this.max_low){ad=this.max_low}if(ah>this.max_high){ah=this.max_high}var ae=this.high-this.low;if(this.high!==0&&ae<this.min_separation){ah=ad+this.min_separation}this.low=Math.floor(ad);this.high=Math.ceil(ah);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ag=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var af=13;this.overview_box.css({left:ag,width:Math.max(af,ai)}).show();if(ai<af){this.overview_box.css("left",ag-(af-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ag,width:ai})}ac.each(this.tracks_to_be_redrawn,function(al){var aj=al[0],ak=al[1];if(aj){aj._draw(ak)}});this.tracks_to_be_redrawn=[];ac.each(this.label_tracks,function(aj){aj._draw()})},zoom_in:function(ae,af){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ag=this.high-this.low,ah=ag/2+this.low,ad=(ag/this.zoom_factor)/2;if(ae){ah=ae/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ah-ad);this.high=Math.round(ah+ad);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ae=this.high-this.low,af=ae/2+this.low,ad=(ae*this.zoom_factor)/2;this.low=Math.round(af-ad);this.high=Math.round(af+ad);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(af){if(this.overview_drawable){if(this.overview_drawable.dataset.id===af.dataset.id){return}this.overview_viewport.find(".track").remove()}var ae=af.copy({content_div:this.overview_viewport}),ad=this;ae.header_div.hide();ae.is_overview=true;ad.overview_drawable=ae;this.overview_drawable.postdraw_actions=function(){ad.overview_highlight.show().height(ad.overview_drawable.content_div.height());ad.overview_viewport.height(ad.overview_drawable.content_div.height()+ad.overview_box.outerHeight());ad.overview_close.show();ad.resize_window()};ad.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();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();view.overview_drawable=null}});var q=Backbone.RelationalModel.extend({defaults:{track:null,tool:null,},relations:[{type:Backbone.HasOne,key:"tool",relatedModel:R.Tool}],initialize:function(ad){this.get("tool").remove_inputs(["data","hidden_data","conditional"])}});var t=Backbone.View.extend({events:{"change input":"update_value"},render:function(){var af=this.$el.addClass("param-row"),ag=this.model;var ad=$("<div>").addClass("param-label").text(ag.get("label")).appendTo(af);var ae=$("<div/>").addClass("param-input").html(ag.get("html")).appendTo(af);ae.find(":input").val(ag.get("value"));$("<div style='clear: both;'/>").appendTo(af)},update_value:function(ad){this.model.set_value($(ad.target).val())}});var ab=Backbone.View.extend({render:function(){var ae=this;tool=this.model.get("tool"),parent_div=this.$el.addClass("dynamic-tool").hide();parent_div.bind("drag",function(ai){ai.stopPropagation()}).click(function(ai){ai.stopPropagation()}).bind("dblclick",function(ai){ai.stopPropagation()}).keydown(function(ai){ai.stopPropagation()});var af=$("<div class='tool-name'>").appendTo(parent_div).text(tool.get("name"));tool.get("inputs").each(function(aj){var ai=new t({model:aj});ai.render();parent_div.append(ai.$el)});parent_div.find("input").click(function(){$(this).select()});var ag=$("<div>").addClass("param-row").appendTo(parent_div);var ah=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ag);var ad=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ag);ad.click(function(){ae.run_on_region()});ah.click(function(){ae.run_on_dataset()})},update_params:function(){for(var ad=0;ad<this.params.length;ad++){this.params[ad].update_value()}},state_dict:function(){var ad=this.model.get("tool").get_param_values_dict();ad.visible=this.parent_div.is(":visible");return ad},run_on_dataset:function(){var ad=this.model.get("tool");this.run({target_dataset_id:this.model.get("track").dataset.id,action:"rerun",tool_id:ad.id},null,function(ae){show_modal(ad.get("name")+" is Running",ad.get("name")+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae=this.model.get("track"),ah=this.model.get("tool"),aj=new w.GenomeRegion({chrom:ae.view.chrom,start:ae.view.low,end:ae.view.high}),ak={target_dataset_id:ae.dataset.id,action:"rerun",tool_id:ah.id,regions:[aj.toJSON()]},ai=ae,am=ak.tool_id+ai.tool_region_and_parameters_str(aj),ad;if(ai.container===view){var al=new P(view,view,{name:this.name});var ag=ai.container.replace_drawable(ai,al,false);al.container_div.insertBefore(ai.view.content_div.children()[ag]);al.add_drawable(ai);ai.container_div.appendTo(al.content_div);ad=al}else{ad=ai.container}var af=new ai.constructor(view,ad,{name:am,hda_ldda:"hda"});af.init_for_tool_data();af.change_mode(ai.mode);af.set_filters_manager(ai.filters_manager.copy(af));af.update_icons();ad.add_drawable(af);af.tiles_div.text("Starting job.");this.run(ak,af,function(an){af.set_dataset(new X.Dataset(an));af.tiles_div.text("Running job.");af.init()})},run:function(ad,af,ag){ad.inputs=this.model.get("tool").get_inputs_dict();var ae=new j.ServerStateDeferred({ajax_settings:{url:galaxy_config.root+"api/tools",data:JSON.stringify(ad),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ah){return ah!=="pending"}});$.when(ae.go()).then(function(ah){if(ah==="no converter"){af.container_div.addClass("error");af.content_div.text(J)}else{if(ah.error){af.container_div.addClass("error");af.content_div.text(x+ah.message)}else{ag(ah)}}})}});var C=function(ad,ae){L.Scaler.call(this,ae);this.filter=ad};C.prototype.gen_val=function(ad){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ad[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ad){this.track=ad.track;this.params=ad.params;this.values={};this.restore_values((ad.saved_values?ad.saved_values:{}));this.onchange=ad.onchange};o(F.prototype,{set_param_default_value:function(ae,ad){var af=ac.find(this.params,function(ag){return ag.key===ae});if(af){af.default_value=ad}},set_param_value:function(ad,ae){var af=ac.find(this.params,function(ag){return ag.key===ad});if(af){if(typeof ae==="string"||ae instanceof String){if(ae.trim()===""){ae=af.default_value}else{if(af.type==="float"){ae=parseFloat(ae)}else{if(af.type==="int"){ae=parseInt(ae,10)}}}}}if(this.values[ad]!==ae){this.values[ad]=ae;return true}else{return false}},restore_values:function(ad){var ae=this;$.each(this.params,function(af,ag){if(ad[ag.key]!==undefined){ae.values[ag.key]=ad[ag.key]}else{ae.values[ag.key]=ag.default_value}})},build_form:function(){var ag=this;var ad=$("<div />");var af;function ae(al,ah){for(var ap=0;ap<al.length;ap++){af=al[ap];if(af.hidden){continue}var aj="param_"+ap;var au=ag.values[af.key];var aw=$("<div class='form-row' />").appendTo(ah);aw.append($("<label />").attr("for",aj).text(af.label+":"));if(af.type==="bool"){aw.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",au))}else{if(af.type==="text"){aw.append($('<input type="text"/>').attr("id",aj).val(au).click(function(){$(this).select()}))}else{if(af.type==="select"){var ar=$("<select />").attr("id",aj);for(var an=0;an<af.options.length;an++){$("<option/>").text(af.options[an].label).attr("value",af.options[an].value).appendTo(ar)}ar.val(au);aw.append(ar)}else{if(af.type==="color"){var av=$("<div/>").appendTo(aw),aq=$("<input />").attr("id",aj).attr("name",aj).val(au).css("float","left").appendTo(av).click(function(ay){$(".bs-tooltip").removeClass("in");var ax=$(this).siblings(".bs-tooltip").addClass("in");ax.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ax).height()/2)+($(this).height()/2)}).show();ax.click(function(az){az.stopPropagation()});$(document).bind("click.color-picker",function(){ax.hide();$(document).unbind("click.color-picker")});ay.stopPropagation()}),ao=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(av).attr("title","Set new random color").tooltip(),at=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(av).hide(),ak=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(at),ai=$("<div class='tooltip-arrow'></div>").appendTo(at),am=$.farbtastic(ak,{width:100,height:100,callback:aq,color:au});av.append($("<div/>").css("clear","both"));(function(ax){ao.click(function(){ax.setColor(j.get_random_color())})})(am)}else{aw.append($("<input />").attr("id",aj).attr("name",aj).val(au))}}}}if(af.help){aw.append($("<div class='help'/>").text(af.help))}}}ae(this.params,ad);return ad},update_from_form:function(ad){var af=this;var ae=false;$.each(this.params,function(ag,ai){if(!ai.hidden){var aj="param_"+ag;var ah=ad.find("#"+aj).val();if(ai.type==="bool"){ah=ad.find("#"+aj).is(":checked")}ae=af.set_param_value(ai.key,ah)||ae}});if(ae){this.onchange();this.track.changed()}}});var b=function(ad,ah,af,ae,ag){this.track=ad;this.region=ah;this.low=ah.get("start");this.high=ah.get("end");this.resolution=af;this.html_elt=$("<div class='track-tile'/>").append(ae).height($(ae).attr("height"));this.data=ag;this.stale=false};b.prototype.predisplay_actions=function(){};var M=function(ad,ah,af,ae,ag){b.call(this,ad,ah,af,ae,ag)};M.prototype.predisplay_actions=function(){};var O=function(ag,ao,ah,af,aj,aq,ak,ar,ae,an){b.call(this,ag,ao,ah,af,aj);this.mode=ak;this.all_slotted=ae;this.feature_mapper=an;this.has_icons=false;if(ar){this.has_icons=true;var al=this;af=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:af.width}).prependTo(this.html_elt);var am=new w.GenomeRegion({chrom:ag.view.chrom,start:this.low,end:this.high}),ap=aj.length,ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ad=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ai.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()});ad.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()})}};o(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ae=this,ad={};if(ae.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ap){if(!this.hovered){return}var ak=$(this).offset(),ao=ap.pageX-ak.left,an=ap.pageY-ak.top,au=ae.feature_mapper.get_feature_data(ao,an),al=(au?au[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!al||$(this).attr("id")!==al.toString()){$(this).remove()}});if(au){var ag=ad[al];if(!ag){var al=au[0],aq={name:au[3],start:au[1],end:au[2],strand:au[4]},aj=ae.track.filters_manager.filters,ai;for(var am=0;am<aj.length;am++){ai=aj[am];aq[ai.name]=au[ai.index]}var ag=$("<div/>").attr("id",al).addClass("feature-popup"),av=$("<table/>"),at,ar,aw;for(at in aq){ar=aq[at];aw=$("<tr/>").appendTo(av);$("<th/>").appendTo(aw).text(at);$("<td/>").attr("align","left").appendTo(aw).text(typeof(ar)==="number"?V(ar,2):ar)}ag.append($("<div class='feature-popup-inner'>").append(av));ad[al]=ag}ag.appendTo($(this).parents(".track-content").children(".overlay"));var ah=ao+parseInt(ae.html_elt.css("left"))-ag.width()/2,af=an+parseInt(ae.html_elt.css("top"))+7;ag.css("left",ah+"px").css("top",af+"px")}else{if(!ap.isPropagationStopped()){ap.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ap)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var f=function(ae,ad,af){o(af,{drag_handle_class:"draghandle"});p.call(this,ae,ad,af);this.dataset=null;if(af.dataset){this.dataset=(af.dataset instanceof Backbone.Model?af.dataset:new X.Dataset(af.dataset))}this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in af?af.data_query_wait:K);this.data_manager=("data_manager" in af?af.data_manager:new w.GenomeDataManager({dataset:this.dataset,genome:new w.Genome({key:ae.dbkey,chroms_info:{chrom_info:ae.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in af)||af.resize){this.add_resize_handle()}}};o(f.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ad){ad.view.set_overview(ad)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters()}else{ad.filters_manager.init_filters()}ad.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ad){ad.dynamic_tool_div.toggle();if(ad.dynamic_tool_div.is(":visible")){ad.set_name(ad.name+ad.tool_region_and_parameters_str())}else{ad.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ad){var ag='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',af=ac.template(ag,{track:ad});var ai=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(){var ak=$('select[name="regions"] option:selected').val(),am,aj=new w.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),al=ac.map($(".bookmark"),function(an){return new w.GenomeRegion({from_str:$(an).children(".position").text()})});if(ak==="cur"){am=[aj]}else{if(ak==="bookmarks"){am=al}else{am=[aj].concat(al)}}hide_modal();window.location.href=galaxy_config.root+"visualization/sweepster?"+$.param({dataset_id:ad.dataset.id,hda_ldda:ad.dataset.get("hda_ldda"),regions:JSON.stringify(new Backbone.Collection(am).toJSON())})},ah=function(aj){if((aj.keyCode||aj.which)===27){ai()}else{if((aj.keyCode||aj.which)===13){ae()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",af,{No:ai,Yes:ae})}},p.prototype.action_icons_def[2]],can_draw:function(){return this.dataset&&p.prototype.can_draw.call(this)},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ad=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ad)}this.name_div=$("<div/>").addClass("track-name").appendTo(ad).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ad},set_dataset:function(ad){this.dataset=ad;this.data_manager.set("dataset",ad)},on_resize:function(){this.request_draw({clear_tile_cache:true})},add_resize_handle:function(){var ad=this;var ag=false;var af=false;var ae=$("<div class='track-resize'>");$(ad.container_div).hover(function(){if(ad.content_visible){ag=true;ae.show()}},function(){ag=false;if(!af){ae.hide()}});ae.hide().bind("dragstart",function(ah,ai){af=true;ai.original_height=$(ad.content_div).height()}).bind("drag",function(ai,aj){var ah=Math.min(Math.max(aj.original_height+aj.deltaY,ad.min_height_px),ad.max_height_px);$(ad.tiles_div).css("height",ah);ad.visible_height_px=(ad.max_height_px===ah?0:ah);ad.on_resize()}).bind("dragend",function(ah,ai){ad.tile_cache.clear();af=false;if(!ag){ae.hide()}ad.config.values.height=ad.visible_height_px;ad.changed()}).appendTo(ad.container_div)},set_display_modes:function(ag,aj){this.display_modes=ag;this.mode=(aj?aj:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ae=this,ah={};for(var af=0,ad=ae.display_modes.length;af<ad;af++){var ai=ae.display_modes[af];ah[ai]=function(ak){return function(){ae.change_mode(ak);ae.icons_div.show();ae.container_div.mouseleave(function(){ae.icons_div.hide()})}}(ai)}make_popupmenu(this.action_icons.mode_icon,ah)},build_action_icons:function(){p.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof g){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof e){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(af){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.tiles_div.css("height","auto");ae.tiles_div.text("").children().remove();ae.container_div.removeClass("nodata error pending");if(!ae.dataset.id){return}var ad=$.Deferred(),ag={hda_ldda:ae.dataset.get("hda_ldda"),data_type:this.dataset_check_type,chrom:ae.view.chrom,retry:af};$.getJSON(this.dataset.url(),ag,function(ah){if(!ah||ah==="error"||ah.kind==="error"){ae.container_div.addClass("error");ae.tiles_div.text(m);if(ah.message){ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ah.message+"</pre>",{Close:hide_modal})}));ae.tiles_div.append($("<span/>").text(" "));ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ae.init(true)}))}}else{if(ah==="no converter"){ae.container_div.addClass("error");ae.tiles_div.text(J)}else{if(ah==="no data"||(ah.data!==undefined&&(ah.data===null||ah.data.length===0))){ae.container_div.addClass("nodata");ae.tiles_div.text(E)}else{if(ah==="pending"){ae.container_div.addClass("pending");ae.tiles_div.html(u);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(ah==="data"||ah.status==="data"){if(ah.valid_chroms){ae.valid_chroms=ah.valid_chroms;ae.update_icons()}ae.tiles_div.text(U);if(ae.view.chrom){ae.tiles_div.text("");ae.tiles_div.css("height",ae.visible_height_px+"px");ae.enabled=true;$.when.apply($,ae.predraw_init()).done(function(){ad.resolve();ae.container_div.removeClass("nodata error pending");ae.request_draw()})}else{ad.resolve()}}}}}}});this.update_icons();return ad},predraw_init:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){ad.container_div.addClass("line-track");var ag=ae.data;if(ag&&ag.min&&ag.max){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.config.set_param_default_value("min_value",af);ad.config.set_param_default_value("max_value",ah);ad.prefs.min_value=af;ad.prefs.max_value=ah}})},get_drawables:function(){return this}});var N=function(af,ae,ah){f.call(this,af,ae,ah);var ad=this;k(ad.container_div,ad.drag_handle_class,".group",ad);this.filters_manager=new h.FiltersManager(this,("filters" in ah?ah.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=(ah.tool?new q({track:this,tool:ah.tool,tool_state:ah.tool_state}):null);this.tile_cache=new w.Cache(Q);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){var ag=new ab({model:this.tool});ag.render();this.dynamic_tool_div=ag.$el;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(ah.mode){this.change_mode(ah.mode)}};o(N.prototype,p.prototype,f.prototype,{action_icons_def:f.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.slotters[ad.view.resolution_px_b].max_rows*=2;ad.request_draw({clear_tile_cache:true})},hide:true}]),copy:function(ad){var ae=this.to_dict();o(ae,{data_manager:this.data_manager});var af=new this.constructor(this.view,ad,ae);af.change_mode(this.mode);af.enabled=this.enabled;return af},set_filters_manager:function(ad){this.filters_manager=ad;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,dataset:{id:this.dataset.id,hda_ldda:this.dataset.get("hda_ldda")},prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},set_min_max:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){var ag=ae.data;if(isNaN(parseFloat(ad.prefs.min_value))||isNaN(parseFloat(ad.prefs.max_value))){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.prefs.min_value=af;ad.prefs.max_value=ah}})},change_mode:function(ae){var ad=this;ad.mode=ae;ad.config.values.mode=ae;if(ae==="Auto"){this.data_manager.clear()}ad.request_draw({clear_tile_cache:true});this.action_icons.mode_icon.attr("title","Set display mode (now: "+ad.mode+")");return ad},update_icons:function(){var ad=this;if(ad.filters_available){ad.action_icons.filters_icon.show()}else{ad.action_icons.filters_icon.hide()}if(ad.tool){ad.action_icons.tools_icon.show();ad.action_icons.param_space_viz_icon.show()}else{ad.action_icons.tools_icon.hide();ad.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ae,ad){return ae+"_"+ad},request_draw:function(ad){if(ad&&ad.clear_tile_cache){this.tile_cache.clear()}this.view.request_redraw(ad,this)},before_draw:function(){this.max_height_px=0},_draw:function(aq){if(!this.can_draw()){return}var an=aq&&aq.clear_after,al=this.view.low,ah=this.view.high,ak=ah-al,ae=this.view.container.width(),ap=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;ap=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ad=Math.floor(al/(ag*S)),am,ai,aj=[],ao=[];while((ad*S*ag)<ah){am=this._get_tile_bounds(ad,ag);ai=this.draw_helper(am,ag,ap,aq);aj.push(ai);$.when(ai).then(function(ar){ao.push(ar)});ad+=1}if(!an){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;$.when.apply($,aj).then(function(){af.tiles_div.children(".remove").remove();ao=ac.filter(ao,function(ar){return ar!==null});if(ao.length!==0){af.postdraw_actions(ao,ae,ap,an)}})},_add_yaxis_label:function(ag,ai){var ae=this,ah=(ag==="max"?"top":"bottom"),aj=(ag==="max"?"max":"min"),ad=(ag==="max"?"max_value":"min_value"),ai=ai||function(){ae.request_draw({clear_tile_cache:true})},af=this.container_div.find(".yaxislabel."+ah);if(af.length!==0){af.text(ae.prefs[ad])}else{af=$("<div/>").text(ae.prefs[ad]).make_text_editable({num_cols:12,on_finish:function(ak){$(".bs-tooltip").remove();ae.config.set_param_value(ad,ak);ai()},help_text:"Set "+aj+" value"}).addClass("yaxislabel "+ah).css("color",this.prefs.label_color);this.container_div.prepend(af)}},postdraw_actions:function(ag,ah,aj,ad){var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length>0){this.max_height_px=0;var ae=this;ac.each(ag,function(ak){if(!(ak instanceof M)){ak.html_elt.remove();ae.draw_helper(ak.region,ak.resolution,aj,{force:true,mode:"Coverage"})}});ae._add_yaxis_label("max")}else{this.container_div.find(".yaxislabel").remove();var ai=ac.find(ag,function(ak){return ak.has_icons});if(ai){ac.each(ag,function(ak){if(!ak.has_icons){ak.html_elt.css("padding-top",D)}})}}},get_mode:function(ad){return this.mode},update_auto_mode:function(ad){},_get_drawables:function(){return[this]},draw_helper:function(am,ag,ap,aq){if(!aq){aq={}}var ae=aq.force,ao=!(aq.data_fetch===false),aj=aq.mode||this.mode,af=this,ah=this._get_drawables(),an=this._gen_tile_cache_key(ap,am),ai=function(ar){return(ar&&"track" in ar)};var ak=(ae?undefined:af.tile_cache.get_elt(an));if(ak){if(ai(ak)){af.show_tile(ak,ap)}return ak}if(!ao){return null}var al=function(){var ar=(ac.find(A,function(au){return au===aj})?"Coverage":aj);var at=ac.map(ah,function(au){return au.data_manager.get_data(am,ar,ag,af.data_url_extra_params)});if(view.reference_track){at.push(view.reference_track.data_manager.get_data(am,aj,ag,view.reference_track.data_url_extra_params))}return at};var ad=$.Deferred();af.tile_cache.set_elt(an,ad);$.when.apply($,al()).then(function(){var ar=al(),ax=ar,aD;if(view.reference_track){aD=view.reference_track.data_manager.subset_entry(ar.pop(),am)}var ay=[],av=[];ac.each(ah,function(aI,aF){var aH=aI.mode,aG=ax[aF];if(aH==="Auto"){aH=aI.get_mode(aG);aI.update_auto_mode(aH)}ay.push(aH);av.push(aI.get_canvas_height(aG,aH,ap,at))});var aw=af.view.canvas_manager.new_canvas(),az=am.get("start"),aE=am.get("end"),au=0,at=Math.ceil((aE-az)*ap)+af.left_offset,aB=ac.max(av),aA;aw.width=at;aw.height=(aq.height||aB);var aC=aw.getContext("2d");aC.translate(af.left_offset,0);if(ah.length>1){aC.globalAlpha=0.5;aC.globalCompositeOperation="source-over"}ac.each(ah,function(aG,aF){aA=aG.draw_tile(ax[aF],aC,ay[aF],ag,am,ap,aD)});if(aA!==undefined){af.tile_cache.set_elt(an,aA);af.show_tile(aA,ap)}ad.resolve(aA)});return ad},get_canvas_height:function(ad,af,ag,ae){return this.visible_height_px},_draw_line_track_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.LinePainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new M(this,ai,ah,ag,ad.data)},draw_tile:function(ad,ae,ai,ag,ah,aj,af){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(af,ai){var ae=this,ad=af.html_elt;af.predisplay_actions();var ah=(af.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ah-=this.left_offset}ad.css({position:"absolute",top:0,left:ah});if(ad.hasClass("remove")){ad.removeClass("remove")}else{this.tiles_div.append(ad)}af.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,af.html_elt.height());af.html_elt.parent().children().css("height",this.max_height_px+"px");var ag=this.max_height_px;if(this.visible_height_px!==0){ag=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",ag+"px")},_get_tile_bounds:function(ad,ae){var ag=Math.floor(ad*S*ae),ah=Math.ceil(S*ae),af=(ag+ah<=this.view.max_high?ag+ah:this.view.max_high);return new w.GenomeRegion({chrom:this.view.chrom,start:ag,end:af})},tool_region_and_parameters_str:function(ag){var ad=this,af=(ag!==undefined?ag.toString():"all"),ae=ac.values(ad.tool.get("tool").get_inputs_dict()).join(", ");return" - region=["+af+"], parameters=["+ae+"]"},data_and_mode_compatible:function(ad,ae){if(ae==="Auto"){return true}else{if(ae==="Coverage"){return ad.dataset_type==="bigwig"}else{if(ad.extra_info==="no_detail"){return false}else{return true}}}},can_subset:function(ad){if(ad.dataset_type==="bigwig"||ad.message||ad.extra_info==="no_detail"){return false}return true},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state"}});var W=function(ae,ad){var af={resize:false};f.call(this,ae,ad,af);this.container_div.addClass("label-track")};o(W.prototype,f.prototype,{build_header_div:function(){},init:function(){this.enabled=true},predraw_init:function(){},_draw:function(ah){var af=this.view,ag=af.high-af.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ag)/Math.log(10)))),ad=Math.floor(af.low/ak)*ak,ai=this.view.container.width(),ae=$("<div style='position: relative; height: 1.3em;'></div>");while(ad<af.high){var aj=(ad-af.low)/ag*ai;ae.append($("<div class='label'>"+commatize(ad)+"</div>").css({position:"absolute",left:aj-1}));ad+=ak}this.content_div.children(":first").remove();this.content_div.append(ae)}});var e=function(ae,ad,ah){this.display_modes=A;N.call(this,ae,ad,ah);this.drawables=[];if("drawables" in ah){var ag;for(var af=0;af<ah.drawables.length;af++){ag=ah.drawables[af];this.drawables[af]=n(ag,ae,null);if(ag.left_offset>this.left_offset){this.left_offset=ag.left_offset}}this.enabled=true}ac.each(this.drawables,function(ai){if(ai instanceof c||ai instanceof T){ai.change_mode("Coverage")}});this.update_icons();this.obj_type="CompositeTrack"};o(e.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_group()}}].concat(N.prototype.action_icons_def),to_dict:y.prototype.to_dict,add_drawable:y.prototype.add_drawable,unpack_drawables:y.prototype.unpack_drawables,change_mode:function(ad){N.prototype.change_mode.call(this,ad);for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae].change_mode(ad)}},init:function(){var af=[];for(var ae=0;ae<this.drawables.length;ae++){af.push(this.drawables[ae].init())}var ad=this;$.when.apply($,af).then(function(){ad.enabled=true;ad.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:p.prototype.can_draw,_get_drawables:function(){return this.drawables},show_group:function(){var ag=new P(this.view,this.container,{name:this.name}),ad;for(var af=0;af<this.drawables.length;af++){ad=this.drawables[af];ad.update_icons();ag.add_drawable(ad);ad.container=ag;ag.content_div.append(ad.container_div)}var ae=this.container.replace_drawable(this,ag,true);ag.request_draw({clear_tile_cache:true})},before_draw:function(){N.prototype.before_draw.call(this);var ae=ac.min(ac.map(this.drawables,function(af){return af.prefs.min_value})),ad=ac.max(ac.map(this.drawables,function(af){return af.prefs.max_value}));this.prefs.min_value=ae;this.prefs.max_value=ad;ac.each(this.drawables,function(af){af.prefs.min_value=ae;af.prefs.max_value=ad})},update_all_min_max:function(){var ad=this;ac.each(this.drawables,function(ae){ae.prefs.min_value=ad.prefs.min_value;ae.prefs.max_value=ad.prefs.max_value});this.request_draw({clear_tile_cache:true})},postdraw_actions:function(aj,ad,am,ai){N.prototype.postdraw_actions.call(this,aj,ad,am,ai);var ah=-1;for(var af=0;af<aj.length;af++){var ak=aj[af].html_elt.find("canvas").height();if(ak>ah){ah=ak}}for(var af=0;af<aj.length;af++){var ag=aj[af];if(ag.html_elt.find("canvas").height()!==ah){this.draw_helper(ag.region,ag.resolution,am,{force:true,height:ah});ag.html_elt.remove()}}var ae=this,al=function(){ae.update_all_min_max()};this._add_yaxis_label("min",al);this._add_yaxis_label("max",al)}});var B=function(ad){N.call(this,ad,{content_div:ad.top_labeltrack},{resize:false});ad.reference_track=this;this.left_offset=200;this.visible_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=galaxy_config.root+"api/genomes//"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new w.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};o(B.prototype,p.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},predraw_init:function(){},can_draw:p.prototype.can_draw,draw_helper:function(af,ae,ag,ad){if(ag>this.view.canvas_manager.char_width_px){this.tiles_div.show();return N.prototype.draw_helper.call(this,af,ae,ag,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ad){return true},draw_tile:function(ag,am,ah,ae,aj,an){var af=this.data_manager.subset_entry(ag,aj),al=af.data;var ad=am.canvas;am.font=am.canvas.manager.default_font;am.textAlign="center";for(var ai=0,ak=al.length;ai<ak;ai++){am.fillStyle=this.view.get_base_color(al[ai]);am.fillText(al[ai],Math.floor(ai*an),10)}return new b(this,aj,ae,ad,af)}});var g=function(af,ae,ag){var ad=this;this.display_modes=A;this.mode="Histogram";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:j.get_random_color()},{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:32,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(g.prototype,p.prototype,N.prototype,{before_draw:function(){},draw_tile:function(ad,ae,ah,af,ag,ai){return this._draw_line_track_tile(ad,ae,ah,af,ag,ai)},can_subset:function(ad){return(ad.data[1][0]-ad.data[0][0]===1)},postdraw_actions:function(ae,af,ag,ad){this._add_yaxis_label("max");this._add_yaxis_label("min")}});var r=function(af,ae,ag){var ad=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);this.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(r.prototype,p.prototype,N.prototype,{draw_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.DiagonalHeatmapPainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new b(this,ai,ah,ag,ad.data)}});var c=function(ag,af,ai){var ae=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ag,af,ai);var ah=j.get_random_color(),ad=j.get_random_color([ah,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ah},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ai.prefs,onchange:function(){ae.set_name(ae.prefs.name);ae.set_painter_from_config();ae.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};o(c.prototype,p.prototype,N.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},postdraw_actions:function(an,af,ao,am){N.prototype.postdraw_actions.call(this,an,af,ao,am);var ah=this,ai;if(ah.filters_manager){var ag=ah.filters_manager.filters;for(var ak=0;ak<ag.length;ak++){ag[ak].update_ui_elt()}var aj=false,al,ae;for(ai=0;ai<an.length;ai++){if(an[ai].data.length){al=an[ai].data[0];for(var ak=0;ak<ag.length;ak++){ae=ag[ak];if(ae.applies_to(al)&&ae.min!==ae.max){aj=true;break}}}}if(ah.filters_available!==aj){ah.filters_available=aj;if(!ah.filters_available){ah.filters_manager.hide()}ah.update_icons()}}if(an[0] instanceof O){var ad=true;for(ai=0;ai<an.length;ai++){if(!an[ai].all_slotted){ad=false;break}}if(!ad){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ad){var ad;if(this.mode==="Auto"){if(ad==="no_detail"){ad="feature spans"}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ad+")")}},incremental_slots:function(ah,ad,ag){var ae=this.view.canvas_manager.dummy_context,af=this.slotters[ah];if(!af||(af.mode!==ag)){af=new (s.FeatureSlotter)(ah,ag,z,function(ai){return ae.measureText(ai)});this.slotters[ah]=af}return af.slot_features(ad)},get_mode:function(ad){if(ad.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}return mode},get_canvas_height:function(ad,ah,ai,ae){if(ah==="Coverage"||ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=this.incremental_slots(ai,ad.data,ah);var af=new (this.painter)(null,null,null,this.prefs,ah);return Math.max(aa,af.get_required_height(ag,ae))}},draw_tile:function(an,ar,ap,at,ag,ak,af){var aq=this,ae=ar.canvas,az=ag.get("start"),ad=ag.get("end"),ah=this.left_offset;if(an.dataset_type==="bigwig"){return this._draw_line_track_tile(an,ar,ap,at,ag,ak)}var aj=[],ao=this.slotters[ak].slots;all_slotted=true;if(an.data){var al=this.filters_manager.filters;for(var au=0,aw=an.data.length;au<aw;au++){var ai=an.data[au];var av=false;var am;for(var ay=0,aD=al.length;ay<aD;ay++){am=al[ay];am.update_attrs(ai);if(!am.keep(ai)){av=true;break}}if(!av){aj.push(ai);if(!(ai[0] in ao)){all_slotted=false}}}}var aC=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),aA=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aB=new (this.painter)(aj,az,ad,this.prefs,ap,aC,aA,af,function(aE){return aq.view.get_base_color(aE)});var ax=null;ar.fillStyle=this.prefs.block_color;ar.font=ar.canvas.manager.default_font;ar.textAlign="right";if(an.data){ax=aB.draw(ar,ae.width,ae.height,ak,ao);ax.translation=-ah}return new O(aq,ag,at,ae,an.data,ak,ap,an.message,all_slotted,ax)}});var Z=function(ae,ad,af){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Histogram color",type:"color",default_value:j.get_random_color()},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};o(Z.prototype,p.prototype,N.prototype,{draw_tile:function(ad,ag,aj,ah,ai,ak){if(ad.dataset_type==="bigwig"){return this._draw_line_track_tile(ad,ag,"Histogram",ah,ai,ak)}else{var af=this.view,ae=new (this.painter)(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj,function(al){return af.get_base_color(al)});ae.draw(ag,ag.canvas.width,ag.canvas.height,ak);return new b(this,ai,ah,ag.canvas,ad.data)}},get_canvas_height:function(ad,ah,ai,af){if(ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=new (this.painter)(null,null,null,this.prefs,ah);var ae=(this.dataset.get_metadata("sample_names")?this.dataset.get_metadata("sample_names").length:0);if(ae===0&&ad.data.length!==0){ae=ad.data[0][7].match(/,/g);if(ae===null){ae=1}else{ae=ae.length+1}}return ag.get_required_height(ae)}},predraw_init:function(){var ad=[f.prototype.predraw_init.call(this)];if(!this.dataset.get_metadata("sample_names")){ad.push(this.dataset.fetch())}return ad},postdraw_actions:function(ag,ah,aj,ae){N.prototype.postdraw_actions.call(this,ag,ah,aj,ae);var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length===0&&this.prefs.show_labels){var ad;if(this.container_div.find(".yaxislabel.variant").length===0){ad=this.prefs.summary_height/2;this.tiles_div.prepend($("<div/>").text("Summary").addClass("yaxislabel variant top").css({"font-size":ad+"px",top:(this.prefs.summary_height-ad)/2+"px"}));if(this.prefs.show_sample_data){var ai=this.dataset.get("metadata").get("sample_names").join("<br/>");this.tiles_div.prepend($("<div/>").html(ai).addClass("yaxislabel variant top sample").css({top:this.prefs.summary_height+2,}))}}ad=(this.mode==="Squish"?5:10)+"px";$(this.tiles_div).find(".sample").css({"font-size":ad,"line-height":ad});$(this.tiles_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel.variant").remove()}}});var T=function(af,ae,ah){c.call(this,af,ae,ah);var ag=j.get_random_color(),ad=j.get_random_color([ag,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{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},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"}],saved_values:ah.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=(af.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};o(T.prototype,p.prototype,N.prototype,c.prototype);var d={CompositeTrack:e,DrawableGroup:P,DiagonalHeatmapTrack:r,FeatureTrack:c,LineTrack:g,ReadTrack:T,VariantTrack:Z,VcfTrack:Z};var n=function(af,ae,ad){if("copy" in af){return af.copy(ad)}else{var ag=af.obj_type;if(!ag){ag=af.track_type}return new d[ag](ae,ad,af)}};return{TracksterView:Y,DrawableGroup:P,LineTrack:g,FeatureTrack:c,DiagonalHeatmapTrack:r,ReadTrack:T,VariantTrack:Z,CompositeTrack:e,object_from_template:n}});
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f templates/webapps/galaxy/workflow/editor.mako
--- a/templates/webapps/galaxy/workflow/editor.mako
+++ b/templates/webapps/galaxy/workflow/editor.mako
@@ -32,7 +32,8 @@
"libs/jquery/jstorage",
"galaxy.workflow_editor.canvas",
"libs/jquery/jquery.autocomplete",
- "galaxy.autocom_tagging")}
+ "galaxy.autocom_tagging",
+ "galaxy.workflows" )}
<!--[if lt IE 7]><script type='text/javascript'>
@@ -41,639 +42,37 @@
<![endif]--><script type='text/javascript'>
- // Globals
- workflow = null;
- canvas_manager = null;
- active_ajax_call = false;
- var galaxy_async = new GalaxyAsync();
- galaxy_async.set_func_url(galaxy_async.set_user_pref, "${h.url_for( controller='user', action='set_user_pref_async' )}");
+ // Globals
+ workflow = null;
+ canvas_manager = null;
+ active_ajax_call = false;
- // jQuery onReady
- $( function() {
+ var workflow_id = "${trans.security.encode_id( stored.id ) }";
- if ( window.lt_ie_7 ) {
- show_modal(
- "Browser not supported",
- "Sorry, the workflow editor is not supported for IE6 and below."
- );
- return;
- }
+ // URLs used by galaxy.workflows.js
+ var tool_search_url = "${h.url_for( controller='root', action='tool_search' )}",
+ get_datatypes_url = "${h.url_for( controller='workflow', action='get_datatypes' )}",
+ load_workflow_url = "${h.url_for( controller='workflow', action='load_workflow' )}",
+ run_workflow_url = "${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id(stored.id))}",
+ rename_async_url = "${h.url_for( controller='workflow', action='rename_async', id=trans.security.encode_id(stored.id) )}",
+ annotate_async_url = "${h.url_for( controller='workflow', action='annotate_async', id=trans.security.encode_id(stored.id) )}",
+ get_new_module_info_url = "${h.url_for(controller='workflow', action='get_new_module_info' )}",
+ workflow_index_url = "${h.url_for( controller='workflow', action='index' )}",
+ save_workflow_url = "${h.url_for(controller='workflow', action='save_workflow' )}";
- // Init searching.
- $("#tool-search-query").click( function (){
- $(this).focus();
- $(this).select();
- })
- .keyup( function () {
- // Remove italics.
- $(this).css("font-style", "normal");
- // Don't update if same value as last time
- if ( this.value.length < 3 ) {
- reset_tool_search(false);
- } else if ( this.value != this.lastValue ) {
- // Add class to denote that searching is active.
- $(this).addClass("search_active");
- // input.addClass(config.loadingClass);
- // Add '*' to facilitate partial matching.
- var q = this.value + '*';
- // Stop previous ajax-request
- if (this.timer) {
- clearTimeout(this.timer);
- }
- // Start a new ajax-request in X ms
- $("#search-spinner").show();
- this.timer = setTimeout(function () {
- $.get("${h.url_for( controller='root', action='tool_search' )}", { query: q }, function (data) {
- // input.removeClass(config.loadingClass);
- // Show live-search if results and search-term aren't empty
- $("#search-no-results").hide();
- // Hide all tool sections.
- $(".toolSectionWrapper").hide();
- // This hides all tools but not workflows link (which is in a .toolTitle div).
- $(".toolSectionWrapper").find(".toolTitle").hide();
- if ( data.length != 0 ) {
- // Map tool ids to element ids and join them.
- var s = $.map( data, function( n, i ) { return "link-" + n; } );
- // First pass to show matching tools and their parents.
- $(s).each( function(index,id) {
- // Add class to denote match.
- $("[id='"+id+"']").parent().addClass("search_match");
- $("[id='"+id+"']").parent().show().parent().parent().show().parent().show();
- });
- // Hide labels that have no visible children.
- $(".toolPanelLabel").each( function() {
- var this_label = $(this);
- var next = this_label.next();
- var no_visible_tools = true;
- // Look through tools following label and, if none are visible, hide label.
- while (next.length !== 0 && next.hasClass("toolTitle")) {
- if (next.is(":visible")) {
- no_visible_tools = false;
- break;
- } else {
- next = next.next();
- }
- }
- if (no_visible_tools) {
- this_label.hide();
- }
- });
- } else {
- $("#search-no-results").show();
- }
- $("#search-spinner").hide();
- }, "json" );
- }, 200 );
- }
- this.lastValue = this.value;
- });
+ <%
+ from galaxy.jobs.actions.post import ActionBox
+ %>
+ // Post-job action vars.
+ var pja_list = "${ActionBox.get_add_list()}",
+ get_pja_form = function(pja) {
+ var p_str = '';
+ // FIXME: this writes JS code; this logic should be codified in galaxy.workflows.js
+ ${ActionBox.get_forms(trans)}
+ return p_str;
+ };
- // Canvas overview management
- canvas_manager = new CanvasManager( $("#canvas-viewport"), $("#overview") );
-
- // Initialize workflow state
- reset();
- // Load the datatype info
- $.ajax( {
- url: "${h.url_for( controller='workflow', action='get_datatypes' )}",
- dataType: "json",
- cache: false,
- success: function( data ) {
- populate_datatype_info( data );
- // Load workflow definition
- $.ajax( {
- url: "${h.url_for( controller='workflow', action='load_workflow' )}",
- data: { id: "${trans.security.encode_id( stored.id )}", "_": "true" },
- dataType: 'json',
- cache: false,
- success: function( data ) {
- reset();
- workflow.from_simple( data );
- workflow.has_changes = false;
- workflow.fit_canvas_to_nodes();
- scroll_to_nodes();
- canvas_manager.draw_overview();
- // Determine if any parameters were 'upgraded' and provide message
- upgrade_message = "";
- $.each( data.upgrade_messages, function( k, v ) {
- upgrade_message += ( "<li>Step " + ( parseInt(k, 10) + 1 ) + ": " + workflow.nodes[k].name + "<ul>");
- $.each( v, function( i, vv ) {
- upgrade_message += "<li>" + vv +"</li>";
- });
- upgrade_message += "</ul></li>";
- });
- if ( upgrade_message ) {
- show_modal( "Workflow loaded with changes",
- "Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>" + upgrade_message + "</ul>",
- { "Continue" : hide_modal } );
- } else {
- hide_modal();
- }
- show_workflow_parameters();
- },
- beforeSubmit: function( data ) {
- show_message( "Loading workflow", "progress" );
- }
- });
- }
- });
-
- // For autosave purposes
- $(document).ajaxStart( function() {
- active_ajax_call = true;
- $(document).bind( "ajaxStop.global", function() {
- active_ajax_call = false;
- });
- });
-
- $(document).ajaxError( function ( e, x ) {
- // console.log( e, x );
- var message = x.responseText || x.statusText || "Could not connect to server";
- show_modal( "Server error", message, { "Ignore error" : hide_modal } );
- return false;
- });
-
- make_popupmenu( $("#workflow-options-button"), {
- "Save" : save_current_workflow,
- "Run": function() {
- window.location = "${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id(stored.id))}";
- },
- ##"Create New" : create_new_workflow_dialog,
- "Edit Attributes" : edit_workflow_attributes,
- ##"Edit Workflow Outputs": edit_workflow_outputs,
- "Auto Re-layout": layout_editor,
- ##"Load a Workflow" : load_workflow,
- "Close": close_editor
- });
-
- function edit_workflow_outputs(){
- workflow.clear_active_node();
- $('.right-content').hide();
- var new_content = "";
- for (var node_key in workflow.nodes){
- var node = workflow.nodes[node_key];
- if(node.type == 'tool'){
- new_content += "<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step " + node.id + " - " + node.name + "</div>";
- for (var ot_key in node.output_terminals){
- var output = node.output_terminals[ot_key];
- // if (node.workflow_outputs[node.id + "|" + output.name]){
- if ($.inArray(output.name, node.workflow_outputs) != -1){
- new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' checked /></p>";
- }
- else{
- new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' /></p>";
- }
- }
- new_content += "</div>";
- }
- }
- $("#output-fill-area").html(new_content);
- $("#output-fill-area input").bind('click', function(){
- var node_id = this.name.split('|')[0];
- var output_name = this.name.split('|')[1];
- if (this.checked){
- if($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) == -1){
- workflow.nodes[node_id].workflow_outputs.push(output_name);
- }//else it's already in the array. Shouldn't happen, but forget it.
- }else{
- while ($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) != -1){
- var ia = $.inArray(output_name, workflow.nodes[node_id].workflow_outputs);
- workflow.nodes[node_id].workflow_outputs = workflow.nodes[node_id].workflow_outputs.slice(0,ia).concat( workflow.nodes[node_id].workflow_outputs.slice(ia+1) );
- }
- }
- workflow.has_changes = true;
- });
- $('#workflow-output-area').show();
- }
-
- function layout_editor() {
- workflow.layout();
- workflow.fit_canvas_to_nodes();
- scroll_to_nodes();
- canvas_manager.draw_overview();
- }
-
- function edit_workflow_attributes() {
- workflow.clear_active_node();
- $('.right-content').hide();
- $('#edit-attributes').show();
-
- }
-
- // On load, set the size to the pref stored in local storage if it exists
- overview_size = $.jStorage.get("overview-size");
- if (overview_size !== undefined) {
- $("#overview-border").css( {
- width: overview_size,
- height: overview_size
- });
- }
-
- // Show viewport on load unless pref says it's off
- if ($.jStorage.get("overview-off")) {
- hide_overview();
- } else {
- show_overview();
- }
-
- // Stores the size of the overview into local storage when it's resized
- $("#overview-border").bind( "dragend", function( e, d ) {
- var op = $(this).offsetParent();
- var opo = op.offset();
- var new_size = Math.max( op.width() - ( d.offsetX - opo.left ),
- op.height() - ( d.offsetY - opo.top ) );
- $.jStorage.set("overview-size", new_size + "px");
- });
-
- function show_overview() {
- $.jStorage.set("overview-off", false);
- $("#overview-border").css("right", "0px");
- $("#close-viewport").css("background-position", "0px 0px");
- }
-
- function hide_overview() {
- $.jStorage.set("overview-off", true);
- $("#overview-border").css("right", "20000px");
- $("#close-viewport").css("background-position", "12px 0px");
- }
-
- // Lets the overview be toggled visible and invisible, adjusting the arrows accordingly
- $("#close-viewport").click( function() {
- if ( $("#overview-border").css("right") === "0px" ) {
- hide_overview();
- } else {
- show_overview();
- }
- });
-
- // Unload handler
- window.onbeforeunload = function() {
- if ( workflow && workflow.has_changes ) {
- return "There are unsaved changes to your workflow which will be lost.";
- }
- };
-
- // Tool menu
- $( "div.toolSectionBody" ).hide();
- $( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" );
- var last_expanded = null;
- $( "div.toolSectionTitle" ).each( function() {
- var body = $(this).next( "div.toolSectionBody" );
- $(this).click( function() {
- if ( body.is( ":hidden" ) ) {
- if ( last_expanded ) last_expanded.slideUp( "fast" );
- last_expanded = body;
- body.slideDown( "fast" );
- }
- else {
- body.slideUp( "fast" );
- last_expanded = null;
- }
- });
- });
-
- // Rename async.
- async_save_text("workflow-name", "workflow-name", "${h.url_for( controller='workflow', action='rename_async', id=trans.security.encode_id(stored.id) )}", "new_name");
-
- // Tag async. Simply have the workflow edit element generate a click on the tag element to activate tagging.
- $('#workflow-tag').click( function() {
- $('.tag-area').click();
- return false;
- });
- // Annotate async.
- async_save_text("workflow-annotation", "workflow-annotation", "${h.url_for( controller='workflow', action='annotate_async', id=trans.security.encode_id(stored.id) )}", "new_annotation", 25, true, 4);
- });
-
- // Global state for the whole workflow
- function reset() {
- if ( workflow ) {
- workflow.remove_all();
- }
- workflow = new Workflow( $("#canvas-container") );
- }
-
- function scroll_to_nodes() {
- var cv = $("#canvas-viewport");
- var cc = $("#canvas-container");
- var top, left;
- if ( cc.width() < cv.width() ) {
- left = ( cv.width() - cc.width() ) / 2;
- } else {
- left = 0;
- }
- if ( cc.height() < cv.height() ) {
- top = ( cv.height() - cc.height() ) / 2;
- } else {
- top = 0;
- }
- cc.css( { left: left, top: top } );
- }
-
- // Add a new step to the workflow by tool id
- function add_node_for_tool( id, title ) {
- var node = prebuild_node( 'tool', title, id );
- workflow.add_node( node );
- workflow.fit_canvas_to_nodes();
- canvas_manager.draw_overview();
- workflow.activate_node( node );
- $.ajax( {
- url: "${h.url_for(controller='workflow', action='get_new_module_info' )}",
- data: { type: "tool", tool_id: id, "_": "true" },
- global: false,
- dataType: "json",
- success: function( data ) {
- node.init_field_data( data );
- },
- error: function( x, e ) {
- var m = "error loading field data";
- if ( x.status === 0 ) {
- m += ", server unavailable";
- }
- node.error( m );
- }
- });
- }
-
- function add_node_for_module( type, title ) {
- node = prebuild_node( type, title );
- workflow.add_node( node );
- workflow.fit_canvas_to_nodes();
- canvas_manager.draw_overview();
- workflow.activate_node( node );
- $.ajax( {
- url: "${h.url_for(controller='workflow', action='get_new_module_info' )}",
- data: { type: type, "_": "true" },
- dataType: "json",
- success: function( data ) {
- node.init_field_data( data );
- },
- error: function( x, e ) {
- var m = "error loading field data"
- if ( x.status == 0 ) {
- m += ", server unavailable"
- }
- node.error( m );
- }
- });
- }
-
-<%
- from galaxy.jobs.actions.post import ActionBox
-%>
-
- // This function preloads how to display known pja's.
- function display_pja(pja, node){
- // DBTODO SANITIZE INPUTS.
- p_str = '';
- ${ActionBox.get_forms(trans)}
- $("#pja_container").append(p_str);
- $("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function (){
- action_to_rem = $(this).closest(".toolForm", ".action_tag").children(".action_tag:first").text();
- $(this).closest(".toolForm").remove();
- delete workflow.active_node.post_job_actions[action_to_rem];
- workflow.active_form_has_changes = true;
- });
- }
-
- function display_pja_list(){
- return "${ActionBox.get_add_list()}";
- }
-
- function display_file_list(node){
- addlist = "<select id='node_data_list' name='node_data_list'>";
- for (var out_terminal in node.output_terminals){
- addlist += "<option value='" + out_terminal + "'>"+ out_terminal +"</option>";
- }
- addlist += "</select>";
- return addlist;
- }
-
- function new_pja(action_type, target, node){
- if (node.post_job_actions === undefined){
- //New tool node, set up dict.
- node.post_job_actions = {};
- }
- if (node.post_job_actions[action_type+target] === undefined){
- var new_pja = {};
- new_pja.action_type = action_type;
- new_pja.output_name = target;
- node.post_job_actions[action_type+target] = null;
- node.post_job_actions[action_type+target] = new_pja;
- display_pja(new_pja, node);
- workflow.active_form_has_changes = true;
- return true;
- } else {
- return false;
- }
- }
-
- function show_workflow_parameters(){
- var parameter_re = /\$\{.+?\}/g;
- var workflow_parameters = [];
- var wf_parm_container = $("#workflow-parameters-container");
- var wf_parm_box = $("#workflow-parameters-box");
- var new_parameter_content = "";
- var matches = [];
- $.each(workflow.nodes, function (k, node){
- var form_matches = node.form_html.match(parameter_re);
- if (form_matches){
- matches = matches.concat(form_matches);
- }
- if (node.post_job_actions){
- $.each(node.post_job_actions, function(k, pja){
- if (pja.action_arguments){
- $.each(pja.action_arguments, function(k, action_argument){
- var arg_matches = action_argument.match(parameter_re);
- if (arg_matches){
- matches = matches.concat(arg_matches);
- }
- });
- }
- });
- if (matches){
- $.each(matches, function(k, element){
- if ($.inArray(element, workflow_parameters) === -1){
- workflow_parameters.push(element);
- }
- });
- }
- }
- });
- if (workflow_parameters && workflow_parameters.length !== 0){
- $.each(workflow_parameters, function(k, element){
- new_parameter_content += "<div>" + element.substring(2, element.length -1) + "</div>";
- });
- wf_parm_container.html(new_parameter_content);
- wf_parm_box.show();
- }else{
- wf_parm_container.html(new_parameter_content);
- wf_parm_box.hide();
- }
- }
-
- function show_form_for_tool( text, node ) {
- $('.right-content').hide();
- $("#right-content").show().html( text );
- // Add metadata form to tool.
- if (node) {
- $("#right-content").find(".toolForm:first").after( "<p><div class='metadataForm'> \
- <div class='metadataFormTitle'>Edit Step Attributes</div> \
- <div class='form-row'> \
- <label>Annotation / Notes:</label> \
- <div style='margin-right: 10px;'> \
- <textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \
- <div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \
- </div> \
- </div> \
- </div>" );
- }
- // Add step actions.
- if (node && node.type=='tool'){
- pjastr = "<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> \
- " + display_pja_list() + " <br/> "+ display_file_list(node) + " <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div>\
- </div><div class='form-row'>\
- <div style='margin-right: 10px;'><span id='pja_container'></span>";
- pjastr += "<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";
- $("#right-content").find(".toolForm").after( pjastr );
- for (var key in node.post_job_actions){
- if (key != "undefined"){ //To make sure we haven't just deleted it.
- display_pja(node.post_job_actions[key], node);
- }
- }
- $("#add_pja").click(function (){
- new_pja($("#new_pja_list").val(),$("#node_data_list").val(), node);
- });
- }
- $("#right-content").find( "form" ).ajaxForm( {
- type: 'POST',
- dataType: 'json',
- success: function( data ) {
- workflow.active_form_has_changes = false;
- node.update_field_data( data );
- show_workflow_parameters();
- },
- beforeSubmit: function( data ) {
- data.push( { name: 'tool_state', value: node.tool_state } );
- data.push( { name: '_', value: "true" } );
- }
- }).each( function() {
- var form = this;
- $(this).find( "select[refresh_on_change='true']").change( function() {
- $(form).submit();
- });
- $(this).find( ".popupmenu" ).each( function() {
- var id = $(this).parents( "div.form-row" ).attr( 'id' );
- var b = $('<a class="popup-arrow" id="popup-arrow-for-' + id + '">▼</a>');
- var options = {};
- $(this).find( "button" ).each( function() {
- var name = $(this).attr( 'name' );
- var value = $(this).attr( 'value' );
- options[ $(this).text() ] = function() {
- $(form).append( "<input type='hidden' name='"+name+"' value='"+value+"' />" ).submit();
- };
- });
- b.insertAfter( this );
- $(this).remove();
- make_popupmenu( b, options );
- });
- // Implements auto-saving based on whether the inputs change. We consider
- // "changed" to be when a field is accessed and not necessarily modified
- // because of an issue where "onchange" is not triggered when activating
- // another node, or saving the workflow.
- $(this).find("input,textarea,select").each( function() {
- $(this).bind("focus click", function() {
- workflow.active_form_has_changes = true;
- });
- });
- });
- }
-
- var close_editor = function() {
- <% next_url = h.url_for( controller='workflow', action='index' ) %>
- workflow.check_changes_in_active_form();
- if ( workflow && workflow.has_changes ) {
- do_close = function() {
- window.onbeforeunload = undefined;
- window.document.location = "${next_url}"
- };
- show_modal( "Close workflow editor",
- "There are unsaved changes to your workflow which will be lost.",
- {
- "Cancel" : hide_modal,
- "Save Changes" : function() {
- save_current_workflow( null, do_close );
- }
- }, {
- "Don't Save": do_close
- } );
- } else {
- window.document.location = "${next_url}";
- }
- };
-
- var save_current_workflow = function ( eventObj, success_callback ) {
- show_message( "Saving workflow", "progress" );
- workflow.check_changes_in_active_form();
- if (!workflow.has_changes) {
- hide_modal();
- if ( success_callback ) {
- success_callback();
- }
- return;
- }
- workflow.rectify_workflow_outputs();
- var savefn = function(callback) {
- $.ajax( {
- url: "${h.url_for(controller='workflow', action='save_workflow' )}",
- type: "POST",
- data: {
- id: "${trans.security.encode_id( stored.id )}",
- workflow_data: function() { return JSON.stringify( workflow.to_simple() ); },
- "_": "true"
- },
- dataType: 'json',
- success: function( data ) {
- var body = $("<div></div>").text( data.message );
- if ( data.errors ) {
- body.addClass( "warningmark" );
- var errlist = $( "<ul/>" );
- $.each( data.errors, function( i, v ) {
- $("<li></li>").text( v ).appendTo( errlist );
- });
- body.append( errlist );
- } else {
- body.addClass( "donemark" );
- }
- workflow.name = data.name;
- workflow.has_changes = false;
- workflow.stored = true;
- show_workflow_parameters();
- if ( data.errors ) {
- show_modal( "Saving workflow", body, { "Ok" : hide_modal } );
- } else {
- if (callback) {
- callback();
- }
- hide_modal();
- }
- }
- });
- };
-
- // We bind to ajaxStop because of auto-saving, since the form submission ajax
- // call needs to be completed so that the new data is saved
- if (active_ajax_call) {
- $(document).bind('ajaxStop.save_workflow', function() {
- $(document).unbind('ajaxStop.save_workflow');
- savefn();
- $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here
- active_ajax_call = false;
- });
- } else {
- savefn(success_callback);
- }
- };
-
+ // NOTE: code to initialize and edit workflows is in galaxy.workflows.js
</script></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Enhance the Galaxy tool migration framework to support restricted repository dependency definitions. Repository dependency definitions contained in repositories that contain tools migrated from the Galaxy code base cannot define a dependency to a repository that contains a tool at any level of the dependency hierarchy.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/89813e684db6/
Changeset: 89813e684db6
User: greg
Date: 2013-08-26 15:57:18
Summary: Enhance the Galaxy tool migration framework to support restricted repository dependency definitions. Repository dependency definitions contained in repositories that contain tools migrated from the Galaxy code base cannot define a dependency to a repository that contains a tool at any level of the dependency hierarchy.
Affected #: 9 files
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -17,6 +17,7 @@
from galaxy.util import json
from galaxy.model.orm import and_
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import common_util as scu
from tool_shed.util import container_util
from tool_shed.util import encoding_util
from tool_shed.util import export_util
@@ -1579,6 +1580,8 @@
changeset_revision = kwd.get( 'changeset_revision', None )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
repository_id = trans.security.encode_id( repository.id )
+ # We aren't concerned with repository's of type tool_dependency_definition here if a repository_metadata record is not returned
+ # because repositories of this type will never have repository dependencies.
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
@@ -1642,7 +1645,7 @@
encoded_repository_ids = []
changeset_revisions = []
for required_repository_tup in decoded_required_repository_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( required_repository_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = scu.parse_repository_dependency_tuple( required_repository_tup )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
encoded_repository_ids.append( trans.security.encode_id( repository.id ) )
changeset_revisions.append( changeset_revision )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -54,7 +54,8 @@
print error_message
else:
root = tree.getroot()
- self.tool_shed = suc.clean_tool_shed_url( root.get( 'name' ) )
+ self.tool_shed_url = suc.get_url_from_tool_shed( self.app, root.get( 'name' ) )
+ self.tool_shed = suc.clean_tool_shed_url( self.tool_shed_url )
self.repository_owner = common_util.REPOSITORY_OWNER
index, self.shed_config_dict = suc.get_shed_tool_conf_dict( app, self.migrated_tools_config )
# Since tool migration scripts can be executed any number of times, we need to make sure the appropriate tools are defined in
@@ -85,7 +86,29 @@
for repository_elem in root:
# Make sure we have a valid repository tag.
if self.__is_valid_repository_tag( repository_elem ):
- self.install_repository( repository_elem, install_dependencies )
+ # Get all repository dependencies for the repository defined by the current repository_elem. Repository dependency
+ # definitions contained in tool shed repositories with migrated tools must never define a relationship to a repository
+ # dependency that contains a tool. The repository dependency can only contain items that are not loaded into the Galaxy
+ # tool panel (e.g., tool dependency definitions, custom datatypes, etc). This restriction must be followed down the
+ # entire dependency hierarchy.
+ name = repository_elem.get( 'name' )
+ changeset_revision = repository_elem.get( 'changeset_revision' )
+ tool_shed_accessible, repository_dependencies_dict = \
+ common_util.get_repository_dependencies( app, self.tool_shed_url, name, self.repository_owner, changeset_revision )
+ # Make sure all repository dependency records exist (as tool_shed_repository table rows) in the Galaxy database.
+ created_tool_shed_repositories = self.create_or_update_tool_shed_repository_records( name,
+ changeset_revision,
+ repository_dependencies_dict )
+ # Order the repositories for proper installation. This process is similar to the process used when installing tool
+ # shed repositories (i.e., the order_components_for_installation() method in ~/lib/tool_shed/galaxy_install/
+ # repository_util), but does not handle managing tool panel sections and other components since repository dependency
+ # definitions contained in tool shed repositories with migrated tools must never define a relationship to a repository
+ # dependency that contains a tool.
+ ordered_tool_shed_repositories = self.order_repositories_for_installation( created_tool_shed_repositories,
+ repository_dependencies_dict )
+
+ for tool_shed_repository in ordered_tool_shed_repositories:
+ self.install_repository( repository_elem, tool_shed_repository, install_dependencies )
else:
message = "\nNo tools associated with migration stage %s are defined in your " % str( latest_migration_script_number )
message += "file%s named %s,\nso no repositories will be installed on disk.\n" % ( plural, file_names )
@@ -95,6 +118,52 @@
message += "Try again later.\n"
print message
+ def create_or_update_tool_shed_repository_record( self, name, owner, changeset_revision, description=None ):
+
+ # Install path is of the form: <tool path>/<tool shed>/repos/<repository owner>/<repository name>/<installed changeset revision>
+ relative_clone_dir = os.path.join( self.tool_shed, 'repos', owner, name, changeset_revision )
+ clone_dir = os.path.join( self.tool_path, relative_clone_dir )
+ if not self.__isinstalled( clone_dir ):
+ repository_clone_url = os.path.join( self.tool_shed_url, 'repos', owner, name )
+ relative_install_dir = os.path.join( relative_clone_dir, name )
+ install_dir = os.path.join( clone_dir, name )
+ ctx_rev = suc.get_ctx_rev( self.app, self.tool_shed_url, name, owner, changeset_revision )
+ tool_shed_repository = suc.create_or_update_tool_shed_repository( app=self.app,
+ name=name,
+ description=description,
+ installed_changeset_revision=changeset_revision,
+ ctx_rev=ctx_rev,
+ repository_clone_url=repository_clone_url,
+ metadata_dict={},
+ status=self.app.model.ToolShedRepository.installation_status.NEW,
+ current_changeset_revision=None,
+ owner=self.repository_owner,
+ dist_to_shed=True )
+ return tool_shed_repository
+ return None
+
+ def create_or_update_tool_shed_repository_records( self, name, changeset_revision, repository_dependencies_dict ):
+ """
+ Make sure the repository defined by name and changeset_revision and all of it's repository dependencies have associated tool_shed_repository
+ table rows in the Galaxy database.
+ """
+ created_tool_shed_repositories = []
+ description = repository_dependencies_dict.get( 'description', None )
+ tool_shed_repository = self.create_or_update_tool_shed_repository_record( name, self.repository_owner, changeset_revision, description=description )
+ if tool_shed_repository:
+ created_tool_shed_repositories.append( tool_shed_repository )
+ for rd_key, rd_tups in repository_dependencies_dict.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ rd_tool_shed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = \
+ common_util.parse_repository_dependency_tuple( rd_tup )
+ # TODO: Make sure the repository description is applied to the new repository record during installation.
+ tool_shed_repository = self.create_or_update_tool_shed_repository_record( rd_name, rd_owner, rd_changeset_revision, description=None )
+ if tool_shed_repository:
+ created_tool_shed_repositories.append( tool_shed_repository )
+ return created_tool_shed_repositories
+
def filter_and_persist_proprietary_tool_panel_configs( self, tool_configs_to_filter ):
"""Eliminate all entries in all non-shed-related tool panel configs for all tool config file names in the received tool_configs_to_filter."""
for proprietary_tool_conf in self.proprietary_tool_confs:
@@ -131,7 +200,38 @@
fh.close()
shutil.move( tmp_filename, os.path.abspath( proprietary_tool_conf ) )
os.chmod( proprietary_tool_conf, 0644 )
-
+
+ def get_containing_tool_sections( self, tool_config ):
+ """
+ If tool_config is defined somewhere in self.proprietary_tool_panel_elems, return True and a list of ToolSections in which the
+ tool is displayed. If the tool is displayed outside of any sections, None is appended to the list.
+ """
+ tool_sections = []
+ is_displayed = False
+ for proprietary_tool_panel_elem in self.proprietary_tool_panel_elems:
+ if proprietary_tool_panel_elem.tag == 'tool':
+ # The proprietary_tool_panel_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
+ proprietary_tool_config = proprietary_tool_panel_elem.get( 'file' )
+ proprietary_name = suc.strip_path( proprietary_tool_config )
+ if tool_config == proprietary_name:
+ # The tool is loaded outside of any sections.
+ tool_sections.append( None )
+ if not is_displayed:
+ is_displayed = True
+ if proprietary_tool_panel_elem.tag == 'section':
+ # The proprietary_tool_panel_elem looks something like <section name="EMBOSS" id="EMBOSSLite">.
+ for section_elem in proprietary_tool_panel_elem:
+ if section_elem.tag == 'tool':
+ # The section_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
+ proprietary_tool_config = section_elem.get( 'file' )
+ proprietary_name = suc.strip_path( proprietary_tool_config )
+ if tool_config == proprietary_name:
+ # The tool is loaded inside of the section_elem.
+ tool_sections.append( ToolSection( proprietary_tool_panel_elem ) )
+ if not is_displayed:
+ is_displayed = True
+ return is_displayed, tool_sections
+
def get_guid( self, repository_clone_url, relative_install_dir, tool_config ):
if self.shed_config_dict.get( 'tool_path' ):
relative_install_dir = os.path.join( self.shed_config_dict['tool_path'], relative_install_dir )
@@ -150,6 +250,30 @@
tool = self.toolbox.load_tool( full_path )
return suc.generate_tool_guid( repository_clone_url, tool )
+ def get_prior_install_required_dict( self, tool_shed_repositories, repository_dependencies_dict ):
+ """
+ Return a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained in the received
+ list of tsr_ids and whose associated repository must be installed prior to the repository associated with the tsr_id key.
+ """
+ # Initialize the dictionary.
+ prior_install_required_dict = {}
+ tsr_ids = [ tool_shed_repository.id for tool_shed_repository in tool_shed_repositories ]
+ for tsr_id in tsr_ids:
+ prior_install_required_dict[ tsr_id ] = []
+ # Inspect the repository dependencies about to be installed and populate the dictionary.
+ for rd_key, rd_tups in repository_dependencies_dict.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ prior_install_ids = []
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
+ if util.asbool( prior_installation_required ):
+ for tsr in tool_shed_repositories:
+ if tsr.name == name and tsr.owner == owner and tsr.changeset_revision == changeset_revision:
+ prior_install_ids.append( tsr.id )
+ prior_install_required_dict[ tsr.id ] = prior_install_ids
+ return prior_install_required_dict
+
def get_proprietary_tool_panel_elems( self, latest_tool_migration_script_number ):
"""
Parse each config in self.proprietary_tool_confs (the default is tool_conf.xml) and generate a list of Elements that are
@@ -196,37 +320,6 @@
tool_panel_elems.append( elem )
return tool_panel_elems
- def get_containing_tool_sections( self, tool_config ):
- """
- If tool_config is defined somewhere in self.proprietary_tool_panel_elems, return True and a list of ToolSections in which the
- tool is displayed. If the tool is displayed outside of any sections, None is appended to the list.
- """
- tool_sections = []
- is_displayed = False
- for proprietary_tool_panel_elem in self.proprietary_tool_panel_elems:
- if proprietary_tool_panel_elem.tag == 'tool':
- # The proprietary_tool_panel_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
- proprietary_tool_config = proprietary_tool_panel_elem.get( 'file' )
- proprietary_name = suc.strip_path( proprietary_tool_config )
- if tool_config == proprietary_name:
- # The tool is loaded outside of any sections.
- tool_sections.append( None )
- if not is_displayed:
- is_displayed = True
- if proprietary_tool_panel_elem.tag == 'section':
- # The proprietary_tool_panel_elem looks something like <section name="EMBOSS" id="EMBOSSLite">.
- for section_elem in proprietary_tool_panel_elem:
- if section_elem.tag == 'tool':
- # The section_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
- proprietary_tool_config = section_elem.get( 'file' )
- proprietary_name = suc.strip_path( proprietary_tool_config )
- if tool_config == proprietary_name:
- # The tool is loaded inside of the section_elem.
- tool_sections.append( ToolSection( proprietary_tool_panel_elem ) )
- if not is_displayed:
- is_displayed = True
- return is_displayed, tool_sections
-
def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies ):
"""
Generate the metadata for the installed tool shed repository, among other things. If the installed tool_shed_repository contains tools
@@ -362,33 +455,26 @@
except:
pass
- def install_repository( self, repository_elem, install_dependencies ):
- # Install a single repository, loading contained tools into the tool panel.
- name = repository_elem.get( 'name' )
- description = repository_elem.get( 'description' )
- installed_changeset_revision = repository_elem.get( 'changeset_revision' )
+ def install_repository( self, repository_elem, tool_shed_repository, install_dependencies ):
+ """Install a single repository, loading contained tools into the tool panel."""
# Install path is of the form: <tool path>/<tool shed>/repos/<repository owner>/<repository name>/<installed changeset revision>
- relative_clone_dir = os.path.join( self.tool_shed, 'repos', self.repository_owner, name, installed_changeset_revision )
+ relative_clone_dir = os.path.join( tool_shed_repository.tool_shed,
+ 'repos',
+ tool_shed_repository.owner,
+ tool_shed_repository.name,
+ tool_shed_repository.installed_changeset_revision )
clone_dir = os.path.join( self.tool_path, relative_clone_dir )
if self.__isinstalled( clone_dir ):
- print "Skipping automatic install of repository '", name, "' because it has already been installed in location ", clone_dir
+ print "Skipping automatic install of repository '", tool_shed_repository.name, "' because it has already been installed in location ", clone_dir
else:
- tool_shed_url = suc.get_url_from_tool_shed( self.app, self.tool_shed )
- repository_clone_url = os.path.join( tool_shed_url, 'repos', self.repository_owner, name )
- relative_install_dir = os.path.join( relative_clone_dir, name )
- install_dir = os.path.join( clone_dir, name )
- ctx_rev = suc.get_ctx_rev( self.app, tool_shed_url, name, self.repository_owner, installed_changeset_revision )
- tool_shed_repository = suc.create_or_update_tool_shed_repository( app=self.app,
- name=name,
- description=description,
- installed_changeset_revision=installed_changeset_revision,
- ctx_rev=ctx_rev,
- repository_clone_url=repository_clone_url,
- metadata_dict={},
- status=self.app.model.ToolShedRepository.installation_status.NEW,
- current_changeset_revision=None,
- owner=self.repository_owner,
- dist_to_shed=True )
+ repository_clone_url = os.path.join( self.tool_shed_url, 'repos', tool_shed_repository.owner, tool_shed_repository.name )
+ relative_install_dir = os.path.join( relative_clone_dir, tool_shed_repository.name )
+ install_dir = os.path.join( clone_dir, tool_shed_repository.name )
+ ctx_rev = suc.get_ctx_rev( self.app,
+ self.tool_shed_url,
+ tool_shed_repository.name,
+ tool_shed_repository.owner,
+ tool_shed_repository.installed_changeset_revision )
suc.update_tool_shed_repository_status( self.app, tool_shed_repository, self.app.model.ToolShedRepository.installation_status.CLONING )
cloned_ok, error_message = suc.clone_repository( repository_clone_url, os.path.abspath( install_dir ), ctx_rev )
if cloned_ok:
@@ -405,8 +491,8 @@
self.app.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS )
# Get the tool_versions from the tool shed for each tool in the installed change set.
url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s' % \
- ( tool_shed_url, tool_shed_repository.name, self.repository_owner, installed_changeset_revision )
- text = common_util.tool_shed_get( self.app, tool_shed_url, url )
+ ( self.tool_shed_url, tool_shed_repository.name, self.repository_owner, tool_shed_repository.installed_changeset_revision )
+ text = common_util.tool_shed_get( self.app, self.tool_shed_url, url )
if text:
tool_version_dicts = from_json_string( text )
tool_util.handle_tool_versions( self.app, tool_version_dicts, tool_shed_repository )
@@ -445,6 +531,40 @@
def non_shed_tool_panel_configs( self ):
return common_util.get_non_shed_tool_panel_configs( self.app )
+ def order_repositories_for_installation( self, tool_shed_repositories, repository_dependencies_dict ):
+ """
+ Some repositories may have repository dependencies that are required to be installed before the dependent repository. This method will
+ inspect the list of repositories about to be installed and make sure to order them appropriately. For each repository about to be installed,
+ if required repositories are not contained in the list of repositories about to be installed, then they are not considered. Repository
+ dependency definitions that contain circular dependencies should not result in an infinite loop, but obviously prior installation will not be
+ handled for one or more of the repositories that require prior installation. This process is similar to the process used when installing tool
+ shed repositories (i.e., the order_components_for_installation() method in ~/lib/tool_shed/galaxy_install/repository_util), but does not handle
+ managing tool panel sections and other components since repository dependency definitions contained in tool shed repositories with migrated
+ tools must never define a relationship to a repository dependency that contains a tool.
+ """
+ ordered_tool_shed_repositories = []
+ ordered_tsr_ids = []
+ processed_tsr_ids = []
+ prior_install_required_dict = self.get_prior_install_required_dict( tool_shed_repositories, repository_dependencies_dict )
+ tsr_ids = [ tool_shed_repository.id for tool_shed_repository in tool_shed_repositories ]
+ while len( processed_tsr_ids ) != len( prior_install_required_dict.keys() ):
+ tsr_id = suc.get_next_prior_import_or_install_required_dict_entry( prior_install_required_dict, processed_tsr_ids )
+ processed_tsr_ids.append( tsr_id )
+ # Create the ordered_tsr_ids, the ordered_repo_info_dicts and the ordered_tool_panel_section_keys lists.
+ if tsr_id not in ordered_tsr_ids:
+ prior_install_required_ids = prior_install_required_dict[ tsr_id ]
+ for prior_install_required_id in prior_install_required_ids:
+ if prior_install_required_id not in ordered_tsr_ids:
+ # Install the associated repository dependency first.
+ ordered_tsr_ids.append( prior_install_required_id )
+ ordered_tsr_ids.append( tsr_id )
+ for ordered_tsr_id in ordered_tsr_ids:
+ for tool_shed_repository in tool_shed_repositories:
+ if tool_shed_repository.id == ordered_tsr_id:
+ ordered_tool_shed_repositories.append( tool_shed_repository )
+ break
+ return ordered_tool_shed_repositories
+
def __isinstalled( self, clone_dir ):
full_path = os.path.abspath( clone_dir )
if os.path.exists( full_path ):
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -211,7 +211,7 @@
if key in [ 'description', 'root_key' ]:
continue
for rd_tup in rd_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
# Updates to installed repository revisions may have occurred, so make sure to locate the appropriate repository revision if one exists.
# We need to create a temporary repo_info_tuple that includes the correct repository owner which we get from the current rd_tup. The current
# tuple looks like: ( description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, installed_td )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/common_util.py
--- a/lib/tool_shed/util/common_util.py
+++ b/lib/tool_shed/util/common_util.py
@@ -1,11 +1,20 @@
import os
import urllib2
+from galaxy.util import json
from galaxy.util.odict import odict
from tool_shed.util import encoding_util
from tool_shed.util import xml_util
REPOSITORY_OWNER = 'devteam'
+def accumulate_tool_dependencies( tool_shed_accessible, tool_dependencies, all_tool_dependencies ):
+ if tool_shed_accessible:
+ if tool_dependencies:
+ for tool_dependency in tool_dependencies:
+ if tool_dependency not in all_tool_dependencies:
+ all_tool_dependencies.append( tool_dependency )
+ return all_tool_dependencies
+
def check_for_missing_tools( app, tool_panel_configs, latest_tool_migration_script_number ):
# Get the 000x_tools.xml file associated with the current migrate_tools version number.
tools_xml_file_path = os.path.abspath( os.path.join( 'scripts', 'migrate_tools', '%04d_tools.xml' % latest_tool_migration_script_number ) )
@@ -23,30 +32,38 @@
if tool_shed_url:
for elem in root:
if elem.tag == 'repository':
- tool_dependencies = []
- tool_dependencies_dict = {}
+ repository_dependencies = []
+ all_tool_dependencies = []
repository_name = elem.get( 'name' )
changeset_revision = elem.get( 'changeset_revision' )
- url = '%s/repository/get_tool_dependencies?name=%s&owner=%s&changeset_revision=%s&from_install_manager=True' % \
- ( tool_shed_url, repository_name, REPOSITORY_OWNER, changeset_revision )
- try:
- text = tool_shed_get( app, tool_shed_url, url )
- tool_shed_accessible = True
- except Exception, e:
- # Tool shed may be unavailable - we have to set tool_shed_accessible since we're looping.
- tool_shed_accessible = False
- print "The URL\n%s\nraised the exception:\n%s\n" % ( url, str( e ) )
- if tool_shed_accessible:
- if text:
- tool_dependencies_dict = encoding_util.tool_shed_decode( text )
- for dependency_key, requirements_dict in tool_dependencies_dict.items():
- tool_dependency_name = requirements_dict[ 'name' ]
- tool_dependency_version = requirements_dict[ 'version' ]
- tool_dependency_type = requirements_dict[ 'type' ]
- tool_dependency_readme = requirements_dict.get( 'readme', '' )
- tool_dependencies.append( ( tool_dependency_name, tool_dependency_version, tool_dependency_type, tool_dependency_readme ) )
- for tool_elem in elem.findall( 'tool' ):
- migrated_tool_configs_dict[ tool_elem.get( 'file' ) ] = tool_dependencies
+ tool_shed_accessible, repository_dependencies_dict = get_repository_dependencies( app,
+ tool_shed_url,
+ repository_name,
+ REPOSITORY_OWNER,
+ changeset_revision )
+ # Accumulate all tool dependencies defined for repository dependencies for display to the user.
+ for rd_key, rd_tups in repository_dependencies_dict.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ tool_shed, name, owner, changeset_revision, prior_installation_required = parse_repository_dependency_tuple( rd_tup )
+ tool_shed_accessible, tool_dependencies = get_tool_dependencies( app,
+ tool_shed,
+ name,
+ owner,
+ changeset_revision )
+ all_tool_dependencies = accumulate_tool_dependencies( tool_shed_accessible, tool_dependencies, all_tool_dependencies )
+ tool_shed_accessible, tool_dependencies = get_tool_dependencies( app, tool_shed_url, repository_name, REPOSITORY_OWNER, changeset_revision )
+ all_tool_dependencies = accumulate_tool_dependencies( tool_shed_accessible, tool_dependencies, all_tool_dependencies )
+ for tool_elem in elem.findall( 'tool' ):
+ tool_config_file_name = tool_elem.get( 'file' )
+ if tool_config_file_name:
+ # We currently do nothing with repository dependencies except install them (we do not display repositories that will be
+ # installed to the user). However, we'll store them in the following dictionary in case we choose to display them in the
+ # future.
+ dependencies_dict = dict( tool_dependencies=all_tool_dependencies,
+ repository_dependencies=repository_dependencies )
+ migrated_tool_configs_dict[ tool_config_file_name ] = dependencies_dict
if tool_shed_accessible:
# Parse the proprietary tool_panel_configs (the default is tool_conf.xml) and generate the list of missing tool config file names.
for tool_panel_config in tool_panel_configs:
@@ -90,6 +107,44 @@
config_filenames.append( config_filename )
return config_filenames
+def get_repository_dependencies( app, tool_shed_url, repository_name, repository_owner, changeset_revision ):
+ repository_dependencies_dict = {}
+ tool_shed_accessible = True
+ url = '%s/repository/get_repository_dependencies?name=%s&owner=%s&changeset_revision=%s' % \
+ ( tool_shed_url, repository_name, repository_owner, changeset_revision )
+ try:
+ raw_text = tool_shed_get( app, tool_shed_url, url )
+ tool_shed_accessible = True
+ except Exception, e:
+ tool_shed_accessible = False
+ print "The URL\n%s\nraised the exception:\n%s\n" % ( url, str( e ) )
+ if tool_shed_accessible:
+ if len( raw_text ) > 2:
+ encoded_text = json.from_json_string( raw_text )
+ repository_dependencies_dict = encoding_util.tool_shed_decode( encoded_text )
+ return tool_shed_accessible, repository_dependencies_dict
+
+def get_tool_dependencies( app, tool_shed_url, repository_name, repository_owner, changeset_revision ):
+ tool_dependencies = []
+ tool_shed_accessible = True
+ url = '%s/repository/get_tool_dependencies?name=%s&owner=%s&changeset_revision=%s&from_install_manager=True' % \
+ ( tool_shed_url, repository_name, repository_owner, changeset_revision )
+ try:
+ text = tool_shed_get( app, tool_shed_url, url )
+ tool_shed_accessible = True
+ except Exception, e:
+ tool_shed_accessible = False
+ print "The URL\n%s\nraised the exception:\n%s\n" % ( url, str( e ) )
+ if tool_shed_accessible:
+ if text:
+ tool_dependencies_dict = encoding_util.tool_shed_decode( text )
+ for dependency_key, requirements_dict in tool_dependencies_dict.items():
+ tool_dependency_name = requirements_dict[ 'name' ]
+ tool_dependency_version = requirements_dict[ 'version' ]
+ tool_dependency_type = requirements_dict[ 'type' ]
+ tool_dependencies.append( ( tool_dependency_name, tool_dependency_version, tool_dependency_type ) )
+ return tool_shed_accessible, tool_dependencies
+
def get_tool_shed_url_from_tools_xml_file_path( app, tool_shed ):
search_str = '://%s' % tool_shed
for shed_name, shed_url in app.tool_shed_registry.tool_sheds.items():
@@ -98,7 +153,29 @@
shed_url = shed_url.rstrip( '/' )
return shed_url
return None
-
+
+def parse_repository_dependency_tuple( repository_dependency_tuple, contains_error=False ):
+ if contains_error:
+ if len( repository_dependency_tuple ) == 5:
+ # Metadata should have been reset on the repository containing this repository_dependency definition.
+ tool_shed, name, owner, changeset_revision, error = repository_dependency_tuple
+ # Default prior_installation_required to False.
+ prior_installation_required = False
+ elif len( repository_dependency_tuple ) == 6:
+ toolshed, name, owner, changeset_revision, prior_installation_required, error = repository_dependency_tuple
+ prior_installation_required = str( prior_installation_required )
+ return toolshed, name, owner, changeset_revision, prior_installation_required, error
+ else:
+ if len( repository_dependency_tuple ) == 4:
+ # Metadata should have been reset on the repository containing this repository_dependency definition.
+ tool_shed, name, owner, changeset_revision = repository_dependency_tuple
+ # Default prior_installation_required to False.
+ prior_installation_required = False
+ elif len( repository_dependency_tuple ) == 5:
+ tool_shed, name, owner, changeset_revision, prior_installation_required = repository_dependency_tuple
+ prior_installation_required = str( prior_installation_required )
+ return tool_shed, name, owner, changeset_revision, prior_installation_required
+
def tool_shed_get( app, tool_shed_url, uri ):
"""Make contact with the tool shed via the uri provided."""
registry = app.tool_shed_registry
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/container_util.py
--- a/lib/tool_shed/util/container_util.py
+++ b/lib/tool_shed/util/container_util.py
@@ -3,6 +3,7 @@
import threading
from galaxy.util import asbool
from galaxy.web.framework.helpers import time_ago
+from tool_shed.util import common_util
from tool_shed.util import readme_util
import tool_shed.util.shed_util_common as suc
@@ -63,7 +64,7 @@
self.repository_dependencies.remove( contained_repository_dependency )
def to_repository_dependency( self, repository_dependency_id ):
- toolshed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( self.key.split( STRSEP ) )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( self.key.split( STRSEP ) )
return RepositoryDependency( id=repository_dependency_id,
toolshed=toolshed,
repository_name=name,
@@ -463,7 +464,7 @@
folder_id += 1
invalid_repository_dependency_id += 1
toolshed, name, owner, changeset_revision, prior_installation_required, error = \
- suc.parse_repository_dependency_tuple( invalid_repository_dependency, contains_error=True )
+ common_util.parse_repository_dependency_tuple( invalid_repository_dependency, contains_error=True )
key = generate_repository_dependencies_key_for_repository( toolshed, name, owner, changeset_revision, prior_installation_required )
label = "Repository <b>%s</b> revision <b>%s</b> owned by <b>%s</b>" % ( name, changeset_revision, owner )
folder = Folder( id=folder_id,
@@ -1336,7 +1337,7 @@
can_create_dependency = not is_subfolder_of( sub_folder, repository_dependency )
if can_create_dependency:
toolshed, repository_name, repository_owner, changeset_revision, prior_installation_required = \
- suc.parse_repository_dependency_tuple( repository_dependency )
+ common_util.parse_repository_dependency_tuple( repository_dependency )
repository_dependency_id += 1
repository_dependency = RepositoryDependency( id=repository_dependency_id,
toolshed=toolshed,
@@ -1352,7 +1353,7 @@
def is_subfolder_of( folder, repository_dependency ):
toolshed, repository_name, repository_owner, changeset_revision, prior_installation_required = \
- suc.parse_repository_dependency_tuple( repository_dependency )
+ common_util.parse_repository_dependency_tuple( repository_dependency )
key = generate_repository_dependencies_key_for_repository( toolshed, repository_name, repository_owner, changeset_revision, asbool( prior_installation_required ) )
for sub_folder in folder.folders:
if key == sub_folder.key:
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/encoding_util.py
--- a/lib/tool_shed/util/encoding_util.py
+++ b/lib/tool_shed/util/encoding_util.py
@@ -44,4 +44,4 @@
value = val
a = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
b = binascii.hexlify( value )
- return "%s:%s" % ( a, b )
\ No newline at end of file
+ return "%s:%s" % ( a, b )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -354,9 +354,9 @@
Determine if the only difference between rd_tup and a dependency definition in the list of repository_dependencies is the changeset_revision value.
"""
new_metadata_required = False
- rd_tool_shed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
+ rd_tool_shed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
for repository_dependency in repository_dependencies:
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
if rd_tool_shed == tool_shed and rd_name == name and rd_owner == owner:
# Determine if the repository represented by the dependency tuple is an instance of the repository type TipOnly.
required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -54,7 +54,7 @@
for repository_dependency_components_list in val:
required_repository = None
rd_toolshed, rd_name, rd_owner, rd_changeset_revision, prior_installation_required = \
- suc.parse_repository_dependency_tuple( repository_dependency_components_list )
+ common_util.parse_repository_dependency_tuple( repository_dependency_components_list )
# Get the the tool_shed_repository defined by rd_name, rd_owner and rd_changeset_revision. This is the repository that will be
# required by the current dependent_repository.
# TODO: Check tool_shed_repository.tool_shed as well when repository dependencies across tool sheds is supported.
@@ -254,7 +254,7 @@
invalid_repository_dependencies = invalid_repository_dependencies_dict.get( 'invalid_repository_dependencies', [] )
for repository_dependency_tup in invalid_repository_dependencies:
toolshed, name, owner, changeset_revision, prior_installation_required, error = \
- suc.parse_repository_dependency_tuple( repository_dependency_tup, contains_error=True )
+ common_util.parse_repository_dependency_tuple( repository_dependency_tup, contains_error=True )
if error:
message = '%s ' % str( error )
return message
@@ -279,7 +279,7 @@
if rd_key in [ 'root_key', 'description' ]:
continue
for rd_tup in rd_tups:
- rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
if rd_toolshed == toolshed_base_url and \
rd_name == repository.name and \
rd_owner == repository.user.username and \
@@ -370,7 +370,8 @@
for key_rd_dict in key_rd_dicts:
key = key_rd_dict.keys()[ 0 ]
repository_dependency = key_rd_dict[ key ]
- rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = \
+ common_util.parse_repository_dependency_tuple( repository_dependency )
if suc.tool_shed_is_this_tool_shed( rd_toolshed ):
repository = suc.get_repository_by_name_and_owner( trans.app, rd_name, rd_owner )
if repository:
@@ -457,7 +458,7 @@
def handle_key_rd_dicts_for_repository( trans, current_repository_key, repository_key_rd_dicts, key_rd_dicts_to_be_processed, handled_key_rd_dicts, circular_repository_dependencies ):
key_rd_dict = repository_key_rd_dicts.pop( 0 )
repository_dependency = key_rd_dict[ current_repository_key ]
- toolshed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
if suc.tool_shed_is_this_tool_shed( toolshed ):
required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
required_repository_metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
@@ -686,11 +687,11 @@
clean_key_rd_dicts = []
key = key_rd_dicts[ 0 ].keys()[ 0 ]
repository_tup = key.split( container_util.STRSEP )
- rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( repository_tup )
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = common_util.parse_repository_dependency_tuple( repository_tup )
for key_rd_dict in key_rd_dicts:
k = key_rd_dict.keys()[ 0 ]
repository_dependency = key_rd_dict[ k ]
- toolshed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
if rd_toolshed == toolshed and rd_name == name and rd_owner == owner:
log.debug( "Removing repository dependency for repository %s owned by %s since it refers to a revision within itself." % ( name, owner ) )
else:
@@ -700,7 +701,7 @@
return clean_key_rd_dicts
def get_repository_dependency_as_key( repository_dependency ):
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
return container_util.generate_repository_dependencies_key_for_repository( tool_shed, name, owner, changeset_revision, str( prior_installation_required ) )
def get_repository_dependency_by_repository_id( trans, decoded_repository_id ):
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -237,8 +237,8 @@
def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url, metadata_dict,
status, current_changeset_revision=None, owner='', dist_to_shed=False ):
"""
- Update a tool shed repository record in the Galaxy database with the new information received. If a record defined by the received tool shed, repository name
- and owner does not exists, create a new record with the received information.
+ Update a tool shed repository record in the Galaxy database with the new information received. If a record defined by the received tool shed,
+ repository name and owner does not exist, create a new record with the received information.
"""
# The received value for dist_to_shed will be True if the InstallManager is installing a repository that contains tools or datatypes that used
# to be in the Galaxy distribution, but have been moved to the main Galaxy tool shed.
@@ -312,7 +312,7 @@
def generate_clone_url_from_repo_info_tup( repo_info_tup ):
"""Generate teh URL for cloning a repositoyr given a tuple of toolshed, name, owner, changeset_revision."""
# Example tuple: ['http://localhost:9009', 'blast_datatypes', 'test', '461a4216e8ab', False]
- toolshed, name, owner, changeset_revision, prior_installation_required = parse_repository_dependency_tuple( repo_info_tup )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repo_info_tup )
# Don't include the changeset_revision in clone urls.
return url_join( toolshed, 'repos', owner, name )
@@ -947,7 +947,7 @@
This method is used in the Tool Shed when exporting a repository and it's dependencies, and in Galaxy when a repository and it's dependencies
are being installed. Inspect the received repository_dependencies and determine if the encoded id of each required repository is in the received
tsr_ids. If so, then determine whether that required repository should be imported / installed prior to it's dependent repository. Return a list
- of encoded repository ids, each of which is contained in the received list of tsr_ids, and whose associated repositories must be impoerted / installed
+ of encoded repository ids, each of which is contained in the received list of tsr_ids, and whose associated repositories must be imported / installed
prior to the dependent repository associated with the received repository_dependencies.
"""
prior_tsr_ids = []
@@ -956,7 +956,7 @@
if key in [ 'description', 'root_key' ]:
continue
for rd_tup in rd_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = parse_repository_dependency_tuple( rd_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
if asbool( prior_installation_required ):
if trans.webapp.name == 'galaxy':
repository = get_repository_for_dependency_relationship( trans.app, tool_shed, name, owner, changeset_revision )
@@ -983,7 +983,7 @@
.order_by( trans.model.RepositoryMetadata.table.c.update_time.desc() ) \
.all()
if len( all_metadata_records ) > 1:
- # Delete all recrds older than the last one updated.
+ # Delete all records older than the last one updated.
for repository_metadata in all_metadata_records[ 1: ]:
trans.sa_session.delete( repository_metadata )
trans.sa_session.flush()
@@ -1308,28 +1308,6 @@
folder_contents.append( node )
return folder_contents
-def parse_repository_dependency_tuple( repository_dependency_tuple, contains_error=False ):
- if contains_error:
- if len( repository_dependency_tuple ) == 5:
- # Metadata should have been reset on the repository containing this repository_dependency definition.
- tool_shed, name, owner, changeset_revision, error = repository_dependency_tuple
- # Default prior_installation_required to False.
- prior_installation_required = False
- elif len( repository_dependency_tuple ) == 6:
- toolshed, name, owner, changeset_revision, prior_installation_required, error = repository_dependency_tuple
- prior_installation_required = str( prior_installation_required )
- return toolshed, name, owner, changeset_revision, prior_installation_required, error
- else:
- if len( repository_dependency_tuple ) == 4:
- # Metadata should have been reset on the repository containing this repository_dependency definition.
- tool_shed, name, owner, changeset_revision = repository_dependency_tuple
- # Default prior_installation_required to False.
- prior_installation_required = False
- elif len( repository_dependency_tuple ) == 5:
- tool_shed, name, owner, changeset_revision, prior_installation_required = repository_dependency_tuple
- prior_installation_required = str( prior_installation_required )
- return tool_shed, name, owner, changeset_revision, prior_installation_required
-
def pretty_print( dict=None ):
if dict:
return json.to_json_string( dict, sort_keys=True, indent=4 * ' ' )
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: Dave Bouvier: Another instance of the API referencing the wrong attribute.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e97f613a4948/
Changeset: e97f613a4948
User: Dave Bouvier
Date: 2013-08-26 15:07:54
Summary: Another instance of the API referencing the wrong attribute.
Affected #: 1 file
diff -r a86290c120d3aafb321f73d5ff57e777e8946a41 -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -3440,7 +3440,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Fix Sweepster bug that prevented changing parameter tree after running sweeps.
by commits-noreply@bitbucket.org 24 Aug '13
by commits-noreply@bitbucket.org 24 Aug '13
24 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a86290c120d3/
Changeset: a86290c120d3
User: jgoecks
Date: 2013-08-24 16:31:23
Summary: Fix Sweepster bug that prevented changing parameter tree after running sweeps.
Affected #: 1 file
diff -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c -r a86290c120d3aafb321f73d5ff57e777e8946a41 static/scripts/viz/sweepster.js
--- a/static/scripts/viz/sweepster.js
+++ b/static/scripts/viz/sweepster.js
@@ -920,11 +920,16 @@
// Set inputs and run tool.
tool.set_input_values(pm_track.get('settings').get('values'));
$.when(tool.rerun(dataset, regions)).then(function(output) {
- // HACK: output is an HDA with track config attribute. To create a track, rearrange
- // track config to point to HDA.
+ // HACKish: output is an HDA with track config attribute. To create a track
+ // that works correctly with Backbone relational, it is necessary to
+ // use a modified version of the track config.
var dataset = output.first(),
track_config = dataset.get('track_config');
+ // Set dataset to be the tool's output.
track_config.dataset = dataset;
+ // Set tool to null so that it is not unpacked; unpacking it messes with
+ // the tool parameters and parameter tree.
+ track_config.tool = null;
// Create and add track for output dataset.
var track_obj = tracks.object_from_template(track_config, self, null);
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: Tools and visual analytics: (a) add tool parameter types to client-side code and automatically unpack tools; (b) update Sweepster to work with recent tool parameter enhancements; and (c) fix additional warts.
by commits-noreply@bitbucket.org 23 Aug '13
by commits-noreply@bitbucket.org 23 Aug '13
23 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5b4c4cf9bc96/
Changeset: 5b4c4cf9bc96
User: jgoecks
Date: 2013-08-23 22:09:22
Summary: Tools and visual analytics: (a) add tool parameter types to client-side code and automatically unpack tools; (b) update Sweepster to work with recent tool parameter enhancements; and (c) fix additional warts.
Affected #: 6 files
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -236,7 +236,7 @@
ValueError: An integer is required
"""
- dict_colletion_visible_keys = ToolParameter.dict_collection_visible_keys + ( 'min', 'max' )
+ dict_collection_visible_keys = ToolParameter.dict_collection_visible_keys + ( 'min', 'max' )
def __init__( self, tool, elem ):
TextToolParameter.__init__( self, tool, elem )
@@ -251,12 +251,12 @@
self.max = elem.get( 'max' )
if self.min:
try:
- int( self.min )
+ self.min = int( self.min )
except:
raise ValueError( "An integer is required" )
if self.max:
try:
- int( self.max )
+ self.max = int( self.max )
except:
raise ValueError( "An integer is required" )
if self.min and self.max:
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -37,7 +37,7 @@
from galaxy.datatypes.interval import ChromatinInteractions
from galaxy.datatypes.data import Text
-from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation,HistoryDatasetAssociation
+from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation
from galaxy.datatypes.display_applications import util as da_util
from galaxy.datatypes.metadata import FileParameter
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -873,8 +873,8 @@
# Add tool, dataset attributes to config based on id.
tool = trans.app.toolbox.get_tool( viz_config[ 'tool_id' ] )
- viz_config[ 'tool' ] = tool.dictify( trans, for_display=True )
- viz_config[ 'dataset' ] = dataset.dictify()
+ viz_config[ 'tool' ] = tool.dictify( trans, io_details=True )
+ viz_config[ 'dataset' ] = trans.security.encode_dict_ids( dataset.dictify() )
return trans.fill_template_mako( "visualization/sweepster.mako", config=viz_config )
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c static/scripts/mvc/tools.js
--- a/static/scripts/mvc/tools.js
+++ b/static/scripts/mvc/tools.js
@@ -1,16 +1,12 @@
/**
* Model, view, and controller objects for Galaxy tools and tool panel.
- *
- * Models have no references to views, instead using events to indicate state
- * changes; this is advantageous because multiple views can use the same object
- * and models can be used without views.
*/
define( ["libs/underscore", "viz/trackster/util", "mvc/data", "libs/backbone/backbone-relational" ],
function(_, util, data) {
/**
- * Mixin to enable model to track visibility.
+ * Mixin for tracking model visibility.
*/
var VisibilityMixin = {
hidden: false,
@@ -41,6 +37,13 @@
html: null,
num_samples: 5
},
+
+ subModelTypes: {
+ 'integer': 'IntegerToolParameter',
+ 'float': 'FloatToolParameter',
+ 'data': 'DataToolParameter',
+ 'select': 'SelectToolParameter'
+ },
initialize: function() {
this.attributes.html = unescape(this.attributes.html);
@@ -49,69 +52,57 @@
copy: function() {
return new ToolParameter(this.toJSON());
},
-
+
+ set_value: function(value) {
+ this.set('value', value || '');
+ }
+});
+
+// In order to resolve subModelTypes for tool parameters, use a custom scope here rather
+// than polluting the global scope.
+var tools_scope = {};
+Backbone.Relational.store.addModelScope(tools_scope);
+
+/**
+ * A data tool parameter.
+ */
+var DataToolParameter = tools_scope.DataToolParameter = ToolParameter.extend({});
+
+/**
+ * An integer tool parameter.
+ */
+var IntegerToolParameter = tools_scope.IntegerToolParameter = ToolParameter.extend({
+ set_value: function(value) {
+ this.set('value', parseInt(value, 10));
+ },
+
/**
* Returns samples from a tool input.
*/
get_samples: function() {
- var type = this.get('type'),
- samples = null;
- if (type === 'number') {
- samples = d3.scale.linear()
+ return d3.scale.linear()
.domain([this.get('min'), this.get('max')])
.ticks(this.get('num_samples'));
- }
- else if (type === 'select') {
- samples = _.map(this.get('options'), function(option) {
- return option[0];
- });
- }
-
- return samples;
- },
-
- set_value: function(value) {
- this.set('value', value || '');
- }
-},
-{
- /**
- * Dictionary mapping parameter type strings to parameter classes.
- */
- TYPE_DICT: {
- 'number': IntegerToolParameter
- },
-
- /**
- * Create new parameter from a dictionary.
- */
- create: function(options) {
- var param_class = ToolParameter.TYPE_DICT[options.type] || ToolParameter;
- return new param_class(options);
}
});
-/**
- * A number tool parameter.
+var FloatToolParameter = tools_scope.FloatToolParameter = IntegerToolParameter.extend({
+ set_value: function(value) {
+ this.set('value', parseFloat(value));
+ }
+});
+
+/**
+ * A select tool parameter.
*/
-var IntegerToolParameter = ToolParameter.extend({
- defaults: _.extend({}, ToolParameter.prototype.defaults, {
- min: null,
- max: null
- }),
-
- initialize: function() {
- ToolParameter.prototype.initialize.call(this);
- if (this.attributes.min) {
- this.attributes.min = parseInt(this.attributes.min, 10);
- }
- if (this.attributes.max) {
- this.attributes.max = parseInt(this.attributes.max, 10);
- }
- },
-
- set_value: function(value) {
- this.set('value', parseInt(value, 10))
+var SelectToolParameter = tools_scope.SelectToolParameter = ToolParameter.extend({
+ /**
+ * Returns tool options.
+ */
+ get_samples: function() {
+ return _.map(this.get('options'), function(option) {
+ return option[0];
+ });
}
});
@@ -125,21 +116,32 @@
name: null,
description: null,
target: null,
- inputs: []
+ inputs: [],
+ outputs: []
},
- initialize: function(options) {
- // Unpack parameters manually so that different parameter types can be created.
- this.attributes.inputs = new Backbone.Collection( _.map(options.inputs, function(param_dict) {
- // FIXME: it is still useful to be able to save/restore tool state?
- // Update parameter value from tool state dict.
- //param_dict.value = tool_state_dict[ param_dict[name] ] || param_dict.value;
- return ToolParameter.create(param_dict);
- }));
+ relations: [
+ {
+ type: Backbone.HasMany,
+ key: 'inputs',
+ relatedModel: ToolParameter
+ }
+ ],
+
+ urlRoot: galaxy_config.root + 'api/tools',
+
+ /**
+ * Removes inputs of a particular type; this is useful because not all inputs can be handled by
+ * client and server yet.
+ */
+ remove_inputs: function(types) {
+ var tool = this,
+ incompatible_inputs = tool.get('inputs').filter( function(input) {
+ return ( types.indexOf( input.get('type') ) !== -1);
+ });
+ tool.get('inputs').remove(incompatible_inputs);
},
- urlRoot: galaxy_config.root + 'api/tools',
-
/**
* Returns object copy, optionally including only inputs that can be sampled.
*/
@@ -735,6 +737,7 @@
return {
ToolParameter: ToolParameter,
IntegerToolParameter: IntegerToolParameter,
+ SelectToolParameter: SelectToolParameter,
Tool: Tool,
ToolCollection: ToolCollection,
ToolSearch: ToolSearch,
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c static/scripts/viz/sweepster.js
--- a/static/scripts/viz/sweepster.js
+++ b/static/scripts/viz/sweepster.js
@@ -30,8 +30,6 @@
// Set up tool parameters to work with tree.
var self = this;
this.get('tool').get('inputs').each(function(input) {
- if (!input.get_samples()) { return; }
-
// Listen for changes to input's attributes.
input.on('change:min change:max change:num_samples', function(input) {
if (input.get('in_ptree')) {
@@ -270,8 +268,8 @@
if (options.track) {
// FIXME: find a better way to deal with needed URLs:
var track_config = _.extend({
- data_url: galaxy_paths.get('raw_data_url'),
- converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
+ data_url: galaxy_config.root + 'dummy1',
+ converted_datasets_state_url: galaxy_config.root + 'dummy2'
}, options.track);
this.set('track', tracks.object_from_template(track_config, {}, null));
}
@@ -340,8 +338,10 @@
],
initialize: function(options) {
- var tool_with_samplable_inputs = this.get('tool').copy(true);
+ var tool_with_samplable_inputs = this.get('tool');
this.set('tool_with_samplable_inputs', tool_with_samplable_inputs);
+ // Remove complex parameters for now.
+ tool_with_samplable_inputs.remove_inputs( [ 'data', 'hidden_data', 'conditional' ] );
this.set('parameter_tree', new ToolParameterTree({
tool: tool_with_samplable_inputs,
@@ -425,7 +425,7 @@
// Render tile placeholders.
this.model.get('regions').each(function() {
self.$el.append($('<td/>').addClass('tile').html(
- $('<img/>').attr('src', galaxy_paths.get('image_path') + '/loading_large_white_bg.gif')
+ $('<img/>').attr('src', galaxy_config.root + 'images/loading_large_white_bg.gif')
));
});
@@ -497,10 +497,10 @@
});
// Add row for parameter sweep inputs.
- if (type === 'number') {
+ if (input instanceof tools.IntegerToolParameter) {
sweep_inputs_row = $(_.template(this.number_input_template, this.model.toJSON()));
}
- else if (type === 'select') {
+ else if (input instanceof tools.SelectToolParameter) {
var options = _.map(this.$el.find('select option'), function(option) {
return $(option).val();
}),
@@ -918,19 +918,18 @@
_.each(new_tracks, function(pm_track, index) {
setTimeout(function() {
// Set inputs and run tool.
- // console.log('running with settings', pm_track.get('settings'));
tool.set_input_values(pm_track.get('settings').get('values'));
$.when(tool.rerun(dataset, regions)).then(function(output) {
+ // HACK: output is an HDA with track config attribute. To create a track, rearrange
+ // track config to point to HDA.
+ var dataset = output.first(),
+ track_config = dataset.get('track_config');
+ track_config.dataset = dataset;
+
// Create and add track for output dataset.
- var track_config = _.extend({
- data_url: galaxy_paths.get('raw_data_url'),
- converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
- }, output.first().get('track_config')),
- track_obj = tracks.object_from_template(track_config, self, null);
-
- // Track uses raw data.
- track_obj.data_manager.set('data_type', 'raw_data');
-
+ var track_obj = tracks.object_from_template(track_config, self, null);
+ track_obj.init_for_tool_data();
+
// Set track block colors.
track_obj.prefs.block_color = self.block_color;
track_obj.prefs.reverse_strand_color = self.reverse_strand_color;
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -919,7 +919,7 @@
{ key: 'c_color', label: 'C Color', type: 'color', default_value: "#00FF00" },
{ key: 'g_color', label: 'G Color', type: 'color', default_value: "#0000FF" },
{ key: 't_color', label: 'T Color', type: 'color', default_value: "#FF00FF" },
- { key: 'n_color', label: 'N Color', type: 'color', default_value: "#AAAAAA" },
+ { key: 'n_color', label: 'N Color', type: 'color', default_value: "#AAAAAA" }
],
saved_values: obj_dict.prefs,
onchange: function() {
@@ -1393,7 +1393,7 @@
//
// Redraw without requesting more data immediately.
- view.request_redraw({ data_fetch: false })
+ view.request_redraw({ data_fetch: false });
// Set up timeout to redraw with more data when moving stops.
if (this.redraw_on_move_fn) {
@@ -1637,15 +1637,11 @@
],
initialize: function(options) {
- // HACK: remove data and group tool inputs because Trackster
- // does not work with them right now.
- var tool = this.get('tool'),
- incompatible_inputs = tool.get('inputs').filter( function(input) {
- return ( [ 'data', 'hidden_data', 'group'].indexOf( input.get('type') ) !== -1);
- });
- tool.get('inputs').remove(incompatible_inputs);
+ // HACK: remove some inputs because Trackster does yet not work with them.
+ this.get('tool').remove_inputs( [ 'data', 'hidden_data', 'conditional' ] );
+
+ // FIXME: need to restore tool values/visibility.
}
-
});
/**
@@ -2320,8 +2316,12 @@
// Attribute init.
//
- // Only create dataset if it is defined.
- this.dataset = (obj_dict.dataset ? new data.Dataset(obj_dict.dataset) : null);
+ // Set or create dataset.
+ this.dataset = null;
+ if (obj_dict.dataset) {
+ // Dataset can be a Backbone model or a dict that can be used to create a model.
+ this.dataset = (obj_dict.dataset instanceof Backbone.Model ? obj_dict.dataset : new data.Dataset(obj_dict.dataset) );
+ }
this.dataset_check_type = 'converted_datasets_state';
this.data_url_extra_params = {};
this.data_query_wait = ('data_query_wait' in obj_dict ? obj_dict.data_query_wait : DEFAULT_DATA_QUERY_WAIT);
@@ -3452,9 +3452,13 @@
this.data_query_wait = 1000;
this.dataset_check_type = 'state';
+ // FIXME: this is optional and is disabled for now because it creates
+ // additional converter jobs without a clear benefit because indexing
+ // such a small dataset provides little benefit.
//
// Set up one-time, post-draw to clear tool execution settings.
//
+ /*
this.normal_postdraw_actions = this.postdraw_actions;
this.postdraw_actions = function(tiles, width, w_scale, clear_after) {
var self = this;
@@ -3484,6 +3488,7 @@
// Reset post-draw actions function.
self.postdraw_actions = self.normal_postdraw_actions;
};
+ */
}
});
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: Dave Bouvier: Update tool shed API dictify methods to reference the correct attribute.
by commits-noreply@bitbucket.org 23 Aug '13
by commits-noreply@bitbucket.org 23 Aug '13
23 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ab74f2d80173/
Changeset: ab74f2d80173
User: Dave Bouvier
Date: 2013-08-23 20:55:56
Summary: Update tool shed API dictify methods to reference the correct attribute.
Affected #: 1 file
diff -r e2bca7e8fe7e0f3022c1e1afb4a6eed54dec2bcf -r ab74f2d8017306fb909778aafcd51b78b24e3e56 lib/galaxy/webapps/tool_shed/model/__init__.py
--- a/lib/galaxy/webapps/tool_shed/model/__init__.py
+++ b/lib/galaxy/webapps/tool_shed/model/__init__.py
@@ -180,7 +180,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
@@ -291,7 +291,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
@@ -322,7 +322,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
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