galaxy-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: greg: Add RepositoryMetadata attributes that enable improved query abilities for tool shed repository revisions that contain Galaxy utilities.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/153f7f450f4b/
changeset: 153f7f450f4b
user: greg
date: 2013-03-01 17:13:15
summary: Add RepositoryMetadata attributes that enable improved query abilities for tool shed repository revisions that contain Galaxy utilities.
affected #: 6 files
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee 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
@@ -33,6 +33,7 @@
class NameColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, category ):
return category.name
@@ -43,6 +44,7 @@
class RepositoriesColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, category ):
if category.repositories:
viewable_repositories = 0
@@ -82,6 +84,7 @@
class RepositoriesColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, category ):
if category.repositories:
viewable_repositories = 0
@@ -123,6 +126,7 @@
class NameColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
return escape_html( repository.name )
@@ -468,6 +472,7 @@
class CategoryColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
rval = '<ul>'
if repository.categories:
@@ -481,6 +486,7 @@
class RepositoryCategoryColumn( grids.GridColumn ):
+
def filter( self, trans, user, query, column_filter ):
"""Modify query to filter by category."""
if column_filter == "All":
@@ -501,6 +507,7 @@
elif len( select_field.options ) == 1:
return select_field.options[ 0 ][ 0 ]
return ''
+
title = "Valid repositories"
columns = [
RepositoryGrid.NameColumn( "Name",
@@ -633,19 +640,171 @@
attach_popup=False )
+class RepositoryMetadataGrid( grids.Grid ):
+
+
+ class RepositoryNameColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return escape_html( repository_metadata.repository.name )
+
+
+ class RepositoryOwnerColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return escape_html( repository_metadata.user.username )
+
+
+ class ChangesetRevisionColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return escape_html( repository_metadata.changeset_revision )
+
+
+ class MaliciousColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.malicious:
+ return 'yes'
+ return ''
+
+
+ class DownloadableColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.downloadable:
+ return 'yes'
+ return ''
+
+
+ class ToolsFunctionallyCorrectColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.tools_functionally_correct:
+ return 'yes'
+ return ''
+
+
+ class DoNotTestColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.do_not_test:
+ return 'yes'
+ return ''
+
+
+ class TimeLastTestedColumn( grids.DateTimeColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ return repository_metadata.time_last_tested
+
+
+ class HasRepositoryDependenciesColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.has_repository_dependencies:
+ return 'yes'
+ return ''
+
+
+ class IncludesDatatypesColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_datatypes:
+ return 'yes'
+ return ''
+
+
+ class IncludesToolsColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_tools:
+ return 'yes'
+ return ''
+
+
+ class IncludesToolDependenciesColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_tool_dependencies:
+ return 'yes'
+ return ''
+
+
+ class IncludesWorkflowsColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_workflows:
+ return 'yes'
+ return ''
+
+ title = "Repository metadata"
+ model_class = model.RepositoryMetadata
+ template='/webapps/tool_shed/repository/grid.mako'
+ default_sort_key = "Repository.name"
+ columns = [
+ RepositoryNameColumn( "Repository name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ operations = []
+ standard_filters = []
+ default_filter = dict( malicious="False" )
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = True
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .order_by( model.Repository.name )
+
+
+class RepositoryDependenciesGrid( RepositoryMetadataGrid ):
+
+ title = "Repository dependencies available in this Tool Shed"
+ columns = [
+ RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.RepositoryMetadata.table.c.has_repository_dependencies == True,
+ model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .order_by( model.Repository.name )
+
+
class RepositoryController( BaseUIController, common_util.ItemRatings ):
+ category_grid = CategoryGrid()
+ deprecated_repositories_i_own_grid = DeprecatedRepositoriesIOwnGrid()
+ email_alerts_repository_grid = EmailAlertsRepositoryGrid()
install_matched_repository_grid = InstallMatchedRepositoryGrid()
matched_repository_grid = MatchedRepositoryGrid()
+ my_writable_repositories_grid = MyWritableRepositoriesGrid()
+ repositories_by_user_grid = RepositoriesByUserGrid()
+ repositories_i_own_grid = RepositoriesIOwnGrid()
+ repository_grid = RepositoryGrid()
+ # The repository_metadata_grid is not currently displayed, but is sub-classed by several grids.
+ repository_metadata_grid = RepositoryMetadataGrid()
+ valid_category_grid = ValidCategoryGrid()
valid_repository_grid = ValidRepositoryGrid()
- repository_grid = RepositoryGrid()
- email_alerts_repository_grid = EmailAlertsRepositoryGrid()
- category_grid = CategoryGrid()
- valid_category_grid = ValidCategoryGrid()
- my_writable_repositories_grid = MyWritableRepositoriesGrid()
- repositories_i_own_grid = RepositoriesIOwnGrid()
- deprecated_repositories_i_own_grid = DeprecatedRepositoriesIOwnGrid()
- repositories_by_user_grid = RepositoriesByUserGrid()
@web.expose
def browse_categories( self, trans, **kwd ):
@@ -3036,7 +3195,11 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
repository_metadata_id = trans.security.encode_id( repository_metadata.id )
- tool_test_errors = json.from_json_string( repository_metadata.tool_test_errors )
+ # TODO: Fix this when the install and test framework is completed.
+ # if repository_metadata.tool_test_errors:
+ # tool_test_errors = json.from_json_string( repository_metadata.tool_test_errors )
+ # else:
+ # tool_test_errors = None
metadata = repository_metadata.metadata
if metadata:
if 'tools' in metadata:
@@ -3070,7 +3233,7 @@
else:
repository_metadata_id = None
metadata = None
- tool_test_errors = None
+ #tool_test_errors = None
is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
changeset_revision_select_field = build_changeset_revision_select_field( trans,
repository,
@@ -3094,7 +3257,7 @@
tool=tool,
tool_metadata_dict=tool_metadata_dict,
tool_lineage=tool_lineage,
- tool_test_errors=tool_test_errors,
+ #tool_test_errors=tool_test_errors,
changeset_revision=changeset_revision,
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee 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
@@ -191,11 +191,14 @@
fp.close()
class RepositoryMetadata( object, APIItem ):
- api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable' )
+ api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'has_repository_dependencies', 'includes_datatypes',
+ 'includes_tools', 'includes_tool_dependencies', 'includes_workflows' )
api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'tools_functionally_correct',
- 'do_not_test', 'time_last_tested', 'tool_test_errors' )
+ 'do_not_test', 'time_last_tested', 'tool_test_errors', 'has_repository_dependencies', 'includes_datatypes', 'includes_tools',
+ 'includes_tool_dependencies', 'includes_workflows' )
def __init__( self, id=None, repository_id=None, changeset_revision=None, metadata=None, tool_versions=None, malicious=False, downloadable=False,
- tools_functionally_correct=False, do_not_test=False, time_last_tested=None, tool_test_errors=None ):
+ tools_functionally_correct=False, do_not_test=False, time_last_tested=None, tool_test_errors=None, has_repository_dependencies=False,
+ includes_datatypes=False, includes_tools=False, includes_tool_dependencies=False, includes_workflows=False ):
self.id = id
self.repository_id = repository_id
self.changeset_revision = changeset_revision
@@ -207,6 +210,11 @@
self.do_not_test = do_not_test
self.time_last_tested = time_last_tested
self.tool_test_errors = tool_test_errors
+ self.has_repository_dependencies = has_repository_dependencies
+ self.includes_datatypes = includes_datatypes
+ self.includes_tools = includes_tools
+ self.includes_tool_dependencies = includes_tool_dependencies
+ self.includes_workflows = includes_workflows
def as_dict( self, value_mapper=None ):
return self.get_api_value( view='element', value_mapper=value_mapper )
def get_api_value( self, view='collection', value_mapper=None ):
@@ -227,8 +235,8 @@
return rval
class RepositoryReview( object, APIItem ):
- api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating' )
- api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating' )
+ api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating', 'deleted' )
+ api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating', 'deleted' )
approved_states = Bunch( NO='no', YES='yes' )
def __init__( self, repository_id=None, changeset_revision=None, user_id=None, rating=None, deleted=False ):
self.repository_id = repository_id
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee lib/galaxy/webapps/tool_shed/model/mapping.py
--- a/lib/galaxy/webapps/tool_shed/model/mapping.py
+++ b/lib/galaxy/webapps/tool_shed/model/mapping.py
@@ -134,7 +134,12 @@
Column( "tools_functionally_correct", Boolean, default=False, index=True ),
Column( "do_not_test", Boolean, default=False, index=True ),
Column( "time_last_tested", DateTime, default=None, nullable=True ),
- Column( "tool_test_errors", JSONType, nullable=True ) )
+ Column( "tool_test_errors", JSONType, nullable=True ),
+ Column( "has_repository_dependencies", Boolean, default=False, index=True ),
+ Column( "includes_datatypes", Boolean, default=False, index=True ),
+ Column( "includes_tools", Boolean, default=False, index=True ),
+ Column( "includes_tool_dependencies", Boolean, default=False, index=True ),
+ Column( "includes_workflows", Boolean, default=False, index=True ) )
RepositoryReview.table = Table( "repository_review", metadata,
Column( "id", Integer, primary_key=True ),
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee lib/galaxy/webapps/tool_shed/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py
--- /dev/null
+++ b/lib/galaxy/webapps/tool_shed/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py
@@ -0,0 +1,115 @@
+"""
+Migration script to add the includes_datatypes, has_repository_dependencies, includes_tools, includes_tool_dependencies and includes_workflows
+columns to the repository_metadata table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+import sys, logging
+log = logging.getLogger( __name__ )
+log.setLevel(logging.DEBUG)
+handler = logging.StreamHandler( sys.stdout )
+format = "%(name)s %(levelname)s %(asctime)s %(message)s"
+formatter = logging.Formatter( format )
+handler.setFormatter( formatter )
+log.addHandler( handler )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+ # Initialize.
+ if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ default_false = "0"
+ elif migrate_engine.name == 'postgres':
+ default_false = "false"
+ # Create and initialize tools_functionally_correct, do_not_test, time_last_tested, and tool_test_errors columns in repository_metadata table.
+ RepositoryMetadata_table = Table( "repository_metadata", metadata, autoload=True )
+
+ # Create tools_functionally_correct column
+ c = Column( "includes_datatypes", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_datatypes
+ db_session.execute( "UPDATE repository_metadata SET includes_datatypes=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_datatypes column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_datatypes column
+ c = Column( "has_repository_dependencies", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.has_repository_dependencies
+ db_session.execute( "UPDATE repository_metadata SET has_repository_dependencies=%s" % default_false )
+ except Exception, e:
+ print "Adding has_repository_dependencies column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_tools column
+ c = Column( "includes_tools", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_tools
+ db_session.execute( "UPDATE repository_metadata SET includes_tools=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_tools column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_tool_dependencies column
+ c = Column( "includes_tool_dependencies", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_tool_dependencies
+ db_session.execute( "UPDATE repository_metadata SET includes_tool_dependencies=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_tool_dependencies column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_workflows column
+ c = Column( "includes_workflows", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_workflows
+ db_session.execute( "UPDATE repository_metadata SET includes_workflows=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_workflows column to the repository_metadata table failed: %s" % str( e )
+
+def downgrade():
+ metadata.reflect()
+ # Drop tool_test_errors, time_last_tested, do_not_test, and tools_functionally_correct columns from repository_metadata table.
+ RepositoryMetadata_table = Table( "repository_metadata", metadata, autoload=True )
+
+ # Drop the includes_workflows column.
+ try:
+ RepositoryMetadata_table.c.includes_workflows.drop()
+ except Exception, e:
+ print "Dropping column includes_workflows from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the includes_tool_dependencies column.
+ try:
+ RepositoryMetadata_table.c.includes_tool_dependencies.drop()
+ except Exception, e:
+ print "Dropping column includes_tool_dependencies from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the includes_tools column.
+ try:
+ RepositoryMetadata_table.c.includes_tools.drop()
+ except Exception, e:
+ print "Dropping column includes_tools from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the has_repository_dependencies column.
+ try:
+ RepositoryMetadata_table.c.has_repository_dependencies.drop()
+ except Exception, e:
+ print "Dropping column has_repository_dependencies from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the includes_datatypes column.
+ try:
+ RepositoryMetadata_table.c.includes_datatypes.drop()
+ except Exception, e:
+ print "Dropping column includes_datatypes from the repository_metadata table failed: %s" % str( e )
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee 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
@@ -900,16 +900,42 @@
shutil.copy( full_source_path, os.path.join( dest_path, copied_file ) )
def create_or_update_repository_metadata( trans, id, repository, changeset_revision, metadata_dict ):
"""Create or update a repository_metadatqa record in the tool shed."""
- downloadable = is_downloadable( metadata_dict )
+ has_repository_dependencies = False
+ includes_datatypes = False
+ includes_tools = False
+ includes_tool_dependencies = False
+ includes_workflows = False
+ if metadata_dict:
+ if 'repository_dependencies' in metadata_dict:
+ has_repository_dependencies = True
+ if 'datatypes' in metadata_dict:
+ includes_datatypes = True
+ if 'tools' in metadata_dict:
+ includes_tools = True
+ if 'tool_dependencies' in metadata_dict:
+ includes_tool_dependencies = True
+ if 'workflows' in metadata_dict:
+ includes_workflows = True
+ downloadable = has_repository_dependencies or includes_datatypes or includes_tools or includes_tool_dependencies or includes_workflows
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
repository_metadata.metadata = metadata_dict
repository_metadata.downloadable = downloadable
+ repository_metadata.has_repository_dependencies = has_repository_dependencies
+ repository_metadata.includes_datatypes = includes_datatypes
+ repository_metadata.includes_tools = includes_tools
+ repository_metadata.includes_tool_dependencies = includes_tool_dependencies
+ repository_metadata.includes_workflows = includes_workflows
else:
repository_metadata = trans.model.RepositoryMetadata( repository_id=repository.id,
changeset_revision=changeset_revision,
metadata=metadata_dict,
- downloadable=downloadable )
+ downloadable=downloadable,
+ has_repository_dependencies=has_repository_dependencies,
+ includes_datatypes=includes_datatypes,
+ includes_tools=includes_tools,
+ includes_tool_dependencies=includes_tool_dependencies,
+ includes_workflows=includes_workflows )
# Always set the default values for the following columns. When resetting all metadata on a repository, this will reset the values.
repository_metadata.tools_functionally_correct = False
repository_metadata.do_not_test = False
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee templates/webapps/tool_shed/repository/view_tool_metadata.mako
--- a/templates/webapps/tool_shed/repository/view_tool_metadata.mako
+++ b/templates/webapps/tool_shed/repository/view_tool_metadata.mako
@@ -22,6 +22,8 @@
can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
can_upload = can_push
can_view_change_log = trans.webapp.name == 'tool_shed' and not is_new
+ # TODO: fix the following when the install and test buildbot is functional.
+ #can_view_tool_test_errors = tool_test_errors is not None
if can_push:
browse_label = 'Browse or delete repository tip files'
@@ -265,11 +267,26 @@
${tool.force_history_refresh | h}
<div style="clear: both"></div></div>
- <div class="form-row">
- <label>Parallelism:</label>
- ${tool.parallelism | h}
- <div style="clear: both"></div>
- </div>
+ <% parallelism_info = tool.parallelism %>
+ %if parallelism_info:
+ <div class="form-row">
+ <table width="100%">
+ <tr bgcolor="#D8D8D8" width="100%"><td><b>Parallelism</td></tr>
+ </table>
+ </div>
+ <div class="form-row">
+ <label>Method:</label>
+ ${parallelism_info.method | h}
+ <div style="clear: both"></div>
+ </div>
+ %for key, val in parallelism_info.attributes.items():
+ <div class="form-row">
+ <label>${key}:</label>
+ ${val | h}
+ <div style="clear: both"></div>
+ </div>
+ %endfor
+ %endif
%endif
<div class="form-row"><table width="100%">
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 the level 16 database migration script for the tool shed.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/21c69586390a/
changeset: 21c69586390a
user: greg
date: 2013-03-01 16:52:13
summary: Fix the level 16 database migration script for the tool shed.
affected #: 1 file
diff -r 12dc58f5831ef32aff9c69761a251476f567ef69 -r 21c69586390abeefde4a52560321b826473ad041 lib/galaxy/webapps/tool_shed/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py
--- a/lib/galaxy/webapps/tool_shed/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py
+++ b/lib/galaxy/webapps/tool_shed/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py
@@ -65,7 +65,6 @@
log.debug( "Adding time_last_tested column to the repository_metadata table failed: %s" % str( e ) )
c = Column( "tool_test_errors", JSONType, nullable=True )
try:
- pass
# Create tool_test_errors column
c.create( RepositoryMetadata_table )
assert c is RepositoryMetadata_table.c.tool_test_errors
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 for starting up Galaxy after community webapp was renamed to be tool_shed.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/12dc58f5831e/
changeset: 12dc58f5831e
user: greg
date: 2013-03-01 16:16:20
summary: Fix for starting up Galaxy after community webapp was renamed to be tool_shed.
affected #: 1 file
diff -r 5f774e034512d06c497febcf042d3dbc44d91cf8 -r 12dc58f5831ef32aff9c69761a251476f567ef69 lib/tool_shed/galaxy_install/__init__.py
--- a/lib/tool_shed/galaxy_install/__init__.py
+++ b/lib/tool_shed/galaxy_install/__init__.py
@@ -28,9 +28,9 @@
ElementInclude.include( root )
tool_path = root.get( 'tool_path', None )
if tool_path:
- tool_shed = tool_shed.util.shed_util_common.clean_tool_shed_url( tool_shed_repository.tool_shed )
+ ts = tool_shed.util.shed_util_common.clean_tool_shed_url( tool_shed_repository.tool_shed )
relative_path = os.path.join( tool_path,
- tool_shed,
+ ts,
'repos',
tool_shed_repository.owner,
tool_shed_repository.name,
@@ -45,13 +45,13 @@
.order_by( self.model.ToolShedRepository.table.c.id ):
relative_install_dir = self.get_repository_install_dir( tool_shed_repository )
if relative_install_dir:
- installed_repository_dict = galaxy.util.shed_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
+ installed_repository_dict = tool_shed.util.shed_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
if installed_repository_dict:
self.installed_repository_dicts.append( installed_repository_dict )
def load_proprietary_converters_and_display_applications( self, deactivate=False ):
for installed_repository_dict in self.installed_repository_dicts:
if installed_repository_dict[ 'converter_path' ]:
- galaxy.util.shed_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
+ tool_shed.util.shed_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
if installed_repository_dict[ 'display_path' ]:
- galaxy.util.shed_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
+ tool_shed.util.shed_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Add the method for displaying tool functional test errors for a repository in the tool shed to the repository controller in preparation for the upcoming install and test framework.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5f774e034512/
changeset: 5f774e034512
user: greg
date: 2013-03-01 15:14:38
summary: Add the method for displaying tool functional test errors for a repository in the tool shed to the repository controller in preparation for the upcoming install and test framework.
affected #: 1 file
diff -r 15eafd606d97f9700b5ec9bfc92bb8c50badd365 -r 5f774e034512d06c497febcf042d3dbc44d91cf8 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
@@ -1137,6 +1137,9 @@
@web.expose
@web.require_login( "deprecate repository" )
def deprecate( self, trans, **kwd ):
+ """Mark a repository in the tool shed as deprecated or not deprecated."""
+ # Marking a repository in the tool shed as deprecated has no effect on any downloadable changeset revisions that may be associated with the
+ # repository. Revisions are not marked as not downlaodable because those that have installed the repository must be allowed to get updates.
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
@@ -1195,6 +1198,43 @@
status='error' ) )
@web.expose
+ def display_tool_functional_test_errors( self, trans, repository_id, repository_metadata_id, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository = suc.get_repository_by_id( trans.app, repository_id )
+ if repository:
+ repository_metadata = suc.get_repository_metadata_by_id( trans, repository_metadata_id )
+ changeset_revision = repository_metadata.changeset_revision
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ return trans.fill_template( '/webapps/tool_shed/repository/display_tool_functional_test_errors.mako',
+ repository=repository,
+ repository_metadata=repository_metadata,
+ message=message,
+ status=status )
+ else:
+ message = 'Missing metadata for revision <b>%s</b> of repository <b>%s</b> owned by <b>%s</b>.' % \
+ ( str( changeset_revision ), str( repository.name ), str( repository.user.username ) )
+ else:
+ message = 'Invalid repository_metadata_id <b>%s</b> received for displaying functional test errors for repository <b>%s</b>.' % \
+ ( str( repository_metadata_id ), str( repository.name ) )
+ else:
+ message = 'Invalid repository_id received for displaying functional test errors.<b>%s</b>.' % str( repository_id )
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repositories',
+ message=message,
+ status='error' ) )
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repository',
+ operation='view_or_manage_repository',
+ id=repository_id,
+ changeset_revision=changeset_revision,
+ message=message,
+ status='error' ) )
+
+ @web.expose
def download( self, trans, repository_id, changeset_revision, file_type, **kwd ):
# Download an archive of the repository files compressed as zip, gz or bz2.
params = util.Params( kwd )
@@ -2995,6 +3035,8 @@
revision_label = suc.get_revision_label( trans, repository, changeset_revision )
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
+ repository_metadata_id = trans.security.encode_id( repository_metadata.id )
+ tool_test_errors = json.from_json_string( repository_metadata.tool_test_errors )
metadata = repository_metadata.metadata
if metadata:
if 'tools' in metadata:
@@ -3026,7 +3068,9 @@
if guid:
tool_lineage = self.get_versions_of_tool( trans, repository, repository_metadata, guid )
else:
+ repository_metadata_id = None
metadata = None
+ tool_test_errors = None
is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
changeset_revision_select_field = build_changeset_revision_select_field( trans,
repository,
@@ -3045,10 +3089,12 @@
review_id = None
return trans.fill_template( "/webapps/tool_shed/repository/view_tool_metadata.mako",
repository=repository,
+ repository_metadata_id=repository_metadata_id,
metadata=metadata,
tool=tool,
tool_metadata_dict=tool_metadata_dict,
tool_lineage=tool_lineage,
+ tool_test_errors=tool_test_errors,
changeset_revision=changeset_revision,
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cede7e36e826/
changeset: cede7e36e826
user: jmchilton
date: 2013-03-01 06:56:56
summary: Update LWR client to pass along tool id and version, required if LWR server is configured to point to a toolbox. The LWR server uses this information to match the job up with a tool and uses the tool to validate inputs.
For more information see:
https://lwr.readthedocs.org/en/latest/#setting-up-a-public-lwr-server
https://bitbucket.org/jmchilton/lwr/src/tip/test/validator_test.py
Updates the LWR client to revision 8a249f4254eb6aa1eed8669f738c5a9764caccdb of the LWR.
https://bitbucket.org/jmchilton/lwr/commits/8a249f4254eb6aa1eed8669f738c5a9…
affected #: 2 files
diff -r d1ab12313b6acfbfd51a38195d9c5e75716e7752 -r cede7e36e8261b2cd11f04db67dc92292412b74c lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -69,7 +69,8 @@
output_files = self.get_output_files(job_wrapper)
input_files = job_wrapper.get_input_fnames()
working_directory = job_wrapper.working_directory
- file_stager = FileStager(client, command_line, job_wrapper.extra_filenames, input_files, output_files, job_wrapper.tool.tool_dir, working_directory)
+ tool = job_wrapper.tool
+ file_stager = FileStager(client, tool, command_line, job_wrapper.extra_filenames, input_files, output_files, working_directory)
rebuilt_command_line = file_stager.get_rewritten_command_line()
job_id = file_stager.job_id
client.launch( rebuilt_command_line )
@@ -228,4 +229,4 @@
elif job.get_state() == model.Job.states.QUEUED:
# LWR doesn't queue currently, so this indicates galaxy was shutoff while
# job was being staged. Not sure how to recover from that.
- job_state.job_wrapper.fail( "This job was killed when Galaxy was restarted. Please retry the job." )
\ No newline at end of file
+ job_state.job_wrapper.fail( "This job was killed when Galaxy was restarted. Please retry the job." )
diff -r d1ab12313b6acfbfd51a38195d9c5e75716e7752 -r cede7e36e8261b2cd11f04db67dc92292412b74c lib/galaxy/jobs/runners/lwr_client/__init__.py
--- a/lib/galaxy/jobs/runners/lwr_client/__init__.py
+++ b/lib/galaxy/jobs/runners/lwr_client/__init__.py
@@ -132,7 +132,7 @@
"""
- def __init__(self, client, command_line, config_files, input_files, output_files, tool_dir, working_directory):
+ def __init__(self, client, tool, command_line, config_files, input_files, output_files, working_directory):
"""
"""
self.client = client
@@ -140,7 +140,9 @@
self.config_files = config_files
self.input_files = input_files
self.output_files = output_files
- self.tool_dir = os.path.abspath(tool_dir)
+ self.tool_id = tool.id
+ self.tool_version = tool.version
+ self.tool_dir = os.path.abspath(tool.tool_dir)
self.working_directory = working_directory
# Setup job inputs, these will need to be rewritten before
@@ -161,7 +163,7 @@
self.__upload_rewritten_config_files()
def __handle_setup(self):
- job_config = self.client.setup()
+ job_config = self.client.setup(self.tool_id, self.tool_version)
self.new_working_directory = job_config['working_directory']
self.new_outputs_directory = job_config['outputs_directory']
@@ -480,11 +482,16 @@
self.__raw_execute("clean", {"job_id": self.job_id})
@parseJson()
- def setup(self):
+ def setup(self, tool_id=None, tool_version=None):
"""
Setup remote LWR server to run this job.
"""
- return self.__raw_execute("setup", {"job_id": self.job_id})
+ setup_args = {"job_id": self.job_id}
+ if tool_id:
+ setup_args["tool_id"] = tool_id
+ if tool_version:
+ setup_args["tool_version"] = tool_version
+ return self.__raw_execute("setup", setup_args)
def _read(path):
https://bitbucket.org/galaxy/galaxy-central/commits/15eafd606d97/
changeset: 15eafd606d97
user: natefoo
date: 2013-03-01 14:23:58
summary: Merged in jmchilton/galaxy-central-lwr (pull request #132)
Updates required to target LWR servers configured to point to a toolbox.
affected #: 2 files
diff -r 3110de3062acd1eea7f57b717b434a44b0429447 -r 15eafd606d97f9700b5ec9bfc92bb8c50badd365 lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -69,7 +69,8 @@
output_files = self.get_output_files(job_wrapper)
input_files = job_wrapper.get_input_fnames()
working_directory = job_wrapper.working_directory
- file_stager = FileStager(client, command_line, job_wrapper.extra_filenames, input_files, output_files, job_wrapper.tool.tool_dir, working_directory)
+ tool = job_wrapper.tool
+ file_stager = FileStager(client, tool, command_line, job_wrapper.extra_filenames, input_files, output_files, working_directory)
rebuilt_command_line = file_stager.get_rewritten_command_line()
job_id = file_stager.job_id
client.launch( rebuilt_command_line )
@@ -228,4 +229,4 @@
elif job.get_state() == model.Job.states.QUEUED:
# LWR doesn't queue currently, so this indicates galaxy was shutoff while
# job was being staged. Not sure how to recover from that.
- job_state.job_wrapper.fail( "This job was killed when Galaxy was restarted. Please retry the job." )
\ No newline at end of file
+ job_state.job_wrapper.fail( "This job was killed when Galaxy was restarted. Please retry the job." )
diff -r 3110de3062acd1eea7f57b717b434a44b0429447 -r 15eafd606d97f9700b5ec9bfc92bb8c50badd365 lib/galaxy/jobs/runners/lwr_client/__init__.py
--- a/lib/galaxy/jobs/runners/lwr_client/__init__.py
+++ b/lib/galaxy/jobs/runners/lwr_client/__init__.py
@@ -132,7 +132,7 @@
"""
- def __init__(self, client, command_line, config_files, input_files, output_files, tool_dir, working_directory):
+ def __init__(self, client, tool, command_line, config_files, input_files, output_files, working_directory):
"""
"""
self.client = client
@@ -140,7 +140,9 @@
self.config_files = config_files
self.input_files = input_files
self.output_files = output_files
- self.tool_dir = os.path.abspath(tool_dir)
+ self.tool_id = tool.id
+ self.tool_version = tool.version
+ self.tool_dir = os.path.abspath(tool.tool_dir)
self.working_directory = working_directory
# Setup job inputs, these will need to be rewritten before
@@ -161,7 +163,7 @@
self.__upload_rewritten_config_files()
def __handle_setup(self):
- job_config = self.client.setup()
+ job_config = self.client.setup(self.tool_id, self.tool_version)
self.new_working_directory = job_config['working_directory']
self.new_outputs_directory = job_config['outputs_directory']
@@ -480,11 +482,16 @@
self.__raw_execute("clean", {"job_id": self.job_id})
@parseJson()
- def setup(self):
+ def setup(self, tool_id=None, tool_version=None):
"""
Setup remote LWR server to run this job.
"""
- return self.__raw_execute("setup", {"job_id": self.job_id})
+ setup_args = {"job_id": self.job_id}
+ if tool_id:
+ setup_args["tool_id"] = tool_id
+ if tool_version:
+ setup_args["tool_version"] = tool_version
+ return self.__raw_execute("setup", setup_args)
def _read(path):
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: dannon: Bugfix: Missing paste import in data.py, log being used before definition.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3110de3062ac/
changeset: 3110de3062ac
user: dannon
date: 2013-03-01 14:07:56
summary: Bugfix: Missing paste import in data.py, log being used before definition.
affected #: 1 file
diff -r 1ba69c9ded069f0ccdc1e27d349637b96821431e -r 3110de3062acd1eea7f57b717b434a44b0429447 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -1,14 +1,21 @@
-import logging, os, sys, time, tempfile
+import logging
+import metadata
+import mimetypes
+import os
+import sys
+import tempfile
+import zipfile
+from cgi import escape
from galaxy import util
+from galaxy.datatypes.metadata import MetadataElement #import directly to maintain ease of use in Datatype class definitions
+from galaxy.util import inflector
+from galaxy.util.bunch import Bunch
from galaxy.util.odict import odict
-from galaxy.util.bunch import Bunch
-from galaxy.util import inflector
from galaxy.util.sanitize_html import sanitize_html
-from cgi import escape
-import mimetypes
-import metadata
-import zipfile
-from metadata import MetadataElement #import directly to maintain ease of use in Datatype class definitions
+
+from galaxy import eggs
+eggs.require( "Paste" )
+import paste
if sys.version_info[:2] < ( 2, 6 ):
@@ -16,6 +23,8 @@
if sys.version_info[:2] < ( 2, 5 ):
zipfile.LargeZipFile = zipfile.error
+log = logging.getLogger(__name__)
+
tmpd = tempfile.mkdtemp()
comptypes=[]
ziptype = '32'
@@ -36,7 +45,6 @@
pass
os.rmdir( tmpd )
-log = logging.getLogger(__name__)
# Valid first column and strand column values vor bed, other formats
col1_startswith = ['chr', 'chl', 'groupun', 'reftig_', 'scaffold', 'super_', 'vcho']
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: standardize start and end of regions to fall between bases.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1ba69c9ded06/
changeset: 1ba69c9ded06
user: jgoecks
date: 2013-03-01 04:54:11
summary: Trackster: standardize start and end of regions to fall between bases.
affected #: 2 files
diff -r d1ab12313b6acfbfd51a38195d9c5e75716e7752 -r 1ba69c9ded069f0ccdc1e27d349637b96821431e static/scripts/packed/viz/trackster/painters.js
--- a/static/scripts/packed/viz/trackster/painters.js
+++ b/static/scripts/packed/viz/trackster/painters.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,(seq_start-tile_low)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start-gap,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char,x_pos;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];x_pos=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&gap>0){ctx.fillText(seq[c],c_start,y_center+9)}else{ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.floor(Math.max(1,w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start-gap,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start-gap,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color,gap=0;if((mode==="Pack"||this.mode==="Auto")&&w_scale>ctx.canvas.manager.char_width_px){var gap=Math.round(w_scale/2)}if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end-gap,y_center+5,b2_start-gap,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;var tile_index=1;if(tile_index===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING-gap,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING-gap,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}});
\ No newline at end of file
+define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-0.5)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char,x_pos;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];x_pos=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_center+5,b2_start,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;var tile_index=1;if(tile_index===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}});
\ No newline at end of file
diff -r d1ab12313b6acfbfd51a38195d9c5e75716e7752 -r 1ba69c9ded069f0ccdc1e27d349637b96821431e static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -197,8 +197,7 @@
LinePainter.prototype.default_prefs = { min_value: undefined, max_value: undefined, mode: "Histogram", color: "#000", overflow_color: "#F66" };
LinePainter.prototype.draw = function(ctx, width, height, w_scale) {
- var
- in_path = false,
+ var in_path = false,
min_value = this.prefs.min_value,
max_value = this.prefs.max_value,
vertical_range = max_value - min_value,
@@ -222,13 +221,13 @@
var x_scaled, y, delta_x_px;
if (data.length > 1) {
delta_x_px = Math.ceil((data[1][0] - data[0][0]) * w_scale);
- } else {
+ }
+ else {
delta_x_px = 10;
}
// Extract RGB from preference color.
- var
- pref_color = parseInt( this.prefs.color.slice(1), 16 ),
+ var pref_color = parseInt( this.prefs.color.slice(1), 16 ),
pref_r = (pref_color & 0xff0000) >> 16,
pref_g = (pref_color & 0x00ff00) >> 8,
pref_b = pref_color & 0x0000ff;
@@ -236,7 +235,8 @@
// Paint track.
for (var i = 0, len = data.length; i < len; i++) {
ctx.fillStyle = ctx.strokeStyle = this.prefs.color;
- x_scaled = Math.round((data[i][0] - view_start) * w_scale);
+ // -0.5 to offset drawing between bases.
+ x_scaled = Math.round((data[i][0] - view_start - 0.5) * w_scale);
y = data[i][1];
var top_overflow = false, bot_overflow = false;
if (y === null) {
@@ -494,14 +494,14 @@
* Draw a feature. Returns an array with feature's start and end X coordinates.
*/
draw_element: function(ctx, mode, feature, slot, tile_low, tile_high, w_scale, y_scale, width) {
- var
- feature_uid = feature[0],
+ var feature_uid = feature[0],
feature_start = feature[1],
feature_end = feature[2],
feature_name = feature[3],
feature_strand = feature[4],
- f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
- f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
+ // -0.5 to offset region between bases.
+ f_start = Math.floor( Math.max(0, (feature_start - tile_low - 0.5) * w_scale) ),
+ f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low - 0.5) * w_scale)) ),
draw_start = f_start,
draw_end = f_end,
y_center = (mode === "Dense" ? 0 : (0 + slot)) * y_scale + this.get_top_padding(width),
@@ -615,8 +615,9 @@
var start_and_height;
for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
var block = feature_blocks[k],
- block_start = Math.floor( Math.max(0, (block[0] - tile_low) * w_scale) ),
- block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low) * w_scale)) ),
+ // -0.5 to offset block between bases.
+ block_start = Math.floor( Math.max(0, (block[0] - tile_low - 0.5) * w_scale) ),
+ block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low - 0.5) * w_scale)) ),
last_block_start, last_block_end;
// Skip drawing if block not on tile.
@@ -761,8 +762,9 @@
base_offset -= cig_len;
}
var seq_start = feature_start + base_offset,
- s_start = Math.floor( Math.max(0, (seq_start - tile_low) * w_scale) ),
- s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low) * w_scale) );
+ // -0.5 to offset sequence between bases.
+ s_start = Math.floor( Math.max(0, (seq_start - tile_low - 0.5) * w_scale) ),
+ s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low - 0.5) * w_scale) );
// Make sure that read is drawn even if it too small to be rendered officially; in this case,
// read is drawn at 1px.
@@ -783,7 +785,7 @@
if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
// Draw read base as rectangle.
ctx.fillStyle = block_color;
- ctx.fillRect(s_start - gap,
+ ctx.fillRect(s_start,
y_center + (pack_mode ? 1 : 4 ),
s_end - s_start,
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
@@ -816,13 +818,14 @@
// Draw base.
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
ctx.fillStyle = this.base_color_fn(seq[c]);
- if (pack_mode && gap > 0) {
+ if (pack_mode && w_scale > char_width_px) {
ctx.fillText(seq[c], c_start, y_center + 9);
}
- else {
- ctx.fillRect(c_start - gap,
+ // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
+ else if (w_scale > 0.05) {
+ ctx.fillRect(c_start,
y_center + (pack_mode ? 1 : 4),
- Math.floor( Math.max(1, w_scale) ),
+ Math.max( 1, Math.round(w_scale) ),
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
}
@@ -835,14 +838,14 @@
break;
case "N": // Skipped bases.
ctx.fillStyle = CONNECTOR_COLOR;
- ctx.fillRect(s_start - gap, y_center + 5, s_end - s_start, 1);
+ ctx.fillRect(s_start, y_center + 5, s_end - s_start, 1);
//ctx.dashedLine(s_start + this.left_offset, y_center + 5, this.left_offset + s_end, y_center + 5);
// No change in seq_offset because sequence not used when skipping.
base_offset += cig_len;
break;
case "D": // Deletion.
ctx.fillStyle = "red";
- ctx.fillRect(s_start - gap, y_center + 4, s_end - s_start, 3);
+ ctx.fillRect(s_start, y_center + 4, s_end - s_start, 3);
// TODO: is this true? No change in seq_offset because sequence not used when skipping.
base_offset += cig_len;
break;
@@ -951,17 +954,11 @@
feature_start = feature[1],
feature_end = feature[2],
feature_name = feature[3],
- f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
- f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
+ // -0.5 to put element between bases.
+ f_start = Math.floor( Math.max(0, (feature_start - tile_low - 0.5) * w_scale) ),
+ f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low - 0.5) * w_scale)) ),
y_center = (mode === "Dense" ? 0 : (0 + slot)) * y_scale,
- label_color = this.prefs.label_color,
- // Left-gap for label text since we align chrom text to the position tick.
- gap = 0;
-
- // TODO: fix gap usage; also see note on gap in draw_read.
- if ((mode === "Pack" || this.mode === "Auto") && w_scale > ctx.canvas.manager.char_width_px) {
- var gap = Math.round(w_scale/2);
- }
+ label_color = this.prefs.label_color;
// Draw read.
if (feature[5] instanceof Array) {
@@ -994,7 +991,7 @@
// make it possible to put together more easily.
if (connector && b2_start > b1_end) {
ctx.fillStyle = CONNECTOR_COLOR;
- dashedLine(ctx, b1_end - gap, y_center + 5, b2_start - gap, y_center + 5);
+ dashedLine(ctx, b1_end, y_center + 5, b2_start, y_center + 5);
}
} else {
// Read is single.
@@ -1007,10 +1004,10 @@
var tile_index = 1;
if (tile_index === 0 && f_start - ctx.measureText(feature_name).width < 0) {
ctx.textAlign = "left";
- ctx.fillText(feature_name, f_end + LABEL_SPACING - gap, y_center + 8);
+ ctx.fillText(feature_name, f_end + LABEL_SPACING, y_center + 8);
} else {
ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start - LABEL_SPACING - gap, y_center + 8);
+ ctx.fillText(feature_name, f_start - LABEL_SPACING, y_center + 8);
}
}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d09e8f41ffbb/
changeset: d09e8f41ffbb
user: jgoecks
date: 2013-02-28 22:27:31
summary: Trackster: (a) color reference bases and (b) color variants when reference data is available.
affected #: 2 files
diff -r 74aeac7839881a47e691ab80bddaead0970590b8 -r d09e8f41ffbb9948e55c184832c8f8e265bbdb2d static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -702,9 +702,10 @@
}
});
-var ReadPainter = function(data, view_start, view_end, prefs, mode, alpha_scaler, height_scaler, ref_seq) {
+var ReadPainter = function(data, view_start, view_end, prefs, mode, alpha_scaler, height_scaler, ref_seq, base_color_fn) {
FeaturePainter.call(this, data, view_start, view_end, prefs, mode, alpha_scaler, height_scaler);
this.ref_seq = (ref_seq ? ref_seq.data : null);
+ this.base_color_fn = base_color_fn;
};
extend(ReadPainter.prototype, FeaturePainter.prototype, {
@@ -731,30 +732,27 @@
/**
* Draw a single read.
*/
- draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, ref_seq) {
+ draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
ctx.textAlign = "center";
var tile_region = [tile_low, tile_high],
base_offset = 0,
seq_offset = 0,
- gap = 0,
+ gap = Math.round(w_scale/2),
char_width_px = ctx.canvas.manager.char_width_px,
block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color);
// Keep list of items that need to be drawn on top of initial drawing layer.
var draw_last = [];
-
- // Gap is needed so that read is offset and hence first base can be drawn on read.
- // TODO-FIX: using this gap offsets reads so that their start is not visually in sync with other tracks.
- if ((mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) {
- gap = Math.round(w_scale/2);
+
+ // If no cigar string, then assume all matches.
+ if (!cigar) {
+ cigar = [ [0, read_seq.length] ];
}
- if (!cigar) {
- // If no cigar string, then assume all matches
- cigar = [ [0, ref_seq.length] ];
- }
+
+ // Draw read by processing cigar.
for (var cig_id = 0, len = cigar.length; cig_id < len; cig_id++) {
var cig = cigar[cig_id],
- cig_op = "MIDNSHP=X"[cig[0]],
+ cig_op = "MIDNSHP=X"[ cig[0] ],
cig_len = cig[1];
if (cig_op === "H" || cig_op === "S") {
@@ -782,37 +780,53 @@
case "M": // Match.
case "=": // Equals.
if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
- // Draw.
- var seq = ref_seq.slice(seq_offset, seq_offset + cig_len);
- if (gap > 0) {
- ctx.fillStyle = block_color;
- ctx.fillRect(s_start - gap, y_center + 1, s_end - s_start, 9);
- ctx.fillStyle = CONNECTOR_COLOR;
- // TODO: this can be made much more efficient by computing the complete sequence
- // to draw and then drawing it.
- for (var c = 0, str_len = seq.length; c < str_len; c++) {
- if (this.prefs.show_differences) {
- if (this.ref_seq) {
- var ref_char = this.ref_seq[seq_start - tile_low + c];
- if (!ref_char || ref_char.toLowerCase() === seq[c].toLowerCase()) {
- continue;
- }
+ // Draw read base as rectangle.
+ ctx.fillStyle = block_color;
+ ctx.fillRect(s_start - gap,
+ y_center + (mode === 'Pack' ? 1 : 4 ),
+ s_end - s_start,
+ (mode === 'Pack' ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
+
+ // Draw sequence and/or variants.
+ var seq = read_seq.slice(seq_offset, seq_offset + cig_len),
+ ref_char,
+ read_char,
+ x_pos;
+ for (var c = 0, str_len = seq.length; c < str_len; c++) {
+ // Draw base if it's on tile:
+ if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
+ // Get reference and read character.
+ ref_char = (this.ref_seq ? this.ref_seq[seq_start - tile_low + c] : null);
+ read_char = seq[c];
+ x_pos = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
+
+ // Draw base depending on (a) available reference data and (b) config options.
+ if (
+ // If there's reference data and (a) showing all (i.e. not showing
+ // differences) or (b) if there is a variant.
+ (ref_char &&
+ (!this.prefs.show_differences ||
+ (read_char.toLowerCase !== 'n' && (ref_char.toLowerCase() !== read_char.toLowerCase())))
+ ) ||
+ // If there's no reference data and showing all.
+ (!ref_char && !this.prefs.show_differences)
+ ) {
+
+ // Draw base.
+ var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
+ ctx.fillStyle = this.base_color_fn(seq[c]);
+ if (mode === 'Pack') {
+ ctx.fillText(seq[c], c_start, y_center + 9);
}
else {
- // No reference so cannot show differences.
- continue;
+ ctx.fillRect(c_start - gap,
+ y_center + 4,
+ Math.floor( Math.max(1, w_scale) ),
+ SQUISH_FEATURE_HEIGHT);
}
}
- if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
- var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillText(seq[c], c_start, y_center + 9);
- }
+
}
- } else {
- // Not enough detail to draw sequence data.
- ctx.fillStyle = block_color;
- // TODO: This is a pretty hack-ish way to fill rectangle based on mode.
- ctx.fillRect(s_start, y_center + 4, s_end - s_start, SQUISH_FEATURE_HEIGHT);
}
}
seq_offset += cig_len;
diff -r 74aeac7839881a47e691ab80bddaead0970590b8 -r d09e8f41ffbb9948e55c184832c8f8e265bbdb2d static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -880,6 +880,21 @@
this.render();
this.canvas_manager = new visualization.CanvasManager( this.container.get(0).ownerDocument );
this.reset();
+
+ // Define track configuration
+ this.config = new DrawableConfig( {
+ 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" }
+ ],
+ saved_values: obj_dict.prefs,
+ onchange: function() {
+ track.request_redraw(false, true);
+ }
+ });
},
render: function() {
@@ -1102,7 +1117,12 @@
this.reset();
$(window).trigger("resize");
+ },
+
+ get_base_color: function(base) {
+ return this.config.values[ base.toLowerCase() + '_color' ];
}
+
});
// FIXME: need to use this approach to enable inheritance of DrawableCollection functions.
@@ -1983,7 +2003,7 @@
if ( param.type === 'float' ) {
value = parseFloat( value );
} else if ( param.type === 'int' ) {
- value = parseInt( value );
+ value = parseInt( value, 10 );
} else if ( param.type === 'bool' ) {
value = container.find( '#' + id ).is( ':checked' );
}
@@ -3487,8 +3507,9 @@
// Draw sequence data.
var canvas = ctx.canvas;
ctx.font = ctx.canvas.manager.default_font;
- ctx.textAlign = "center";
+ ctx.textAlign = "center";
for (var c = 0, str_len = seq_data.length; c < str_len; c++) {
+ ctx.fillStyle = this.view.get_base_color(seq_data[c]);
ctx.fillText(seq_data[c], Math.floor(c * w_scale), 10);
}
return new Tile(this, region, resolution, canvas, subset);
@@ -4053,10 +4074,13 @@
}
// Create painter.
- var filter_alpha_scaler = (this.filters_manager.alpha_filter ? new FilterScaler(this.filters_manager.alpha_filter) : null);
- var filter_height_scaler = (this.filters_manager.height_filter ? new FilterScaler(this.filters_manager.height_filter) : null);
- // HACK: ref_seq will only be defined for ReadTracks, and only the ReadPainter accepts that argument
- var painter = new (this.painter)(filtered, tile_low, tile_high, this.prefs, mode, filter_alpha_scaler, filter_height_scaler, ref_seq);
+ var filter_alpha_scaler = (this.filters_manager.alpha_filter ? new FilterScaler(this.filters_manager.alpha_filter) : null),
+ filter_height_scaler = (this.filters_manager.height_filter ? new FilterScaler(this.filters_manager.height_filter) : null),
+ painter = new (this.painter)(filtered, tile_low, tile_high, this.prefs, mode, filter_alpha_scaler, filter_height_scaler,
+ // HACK: ref_seq only be defined for ReadTracks, and only the ReadPainter accepts that argument
+ ref_seq,
+ // Only the ReadPainer will use this function
+ function(b) { return track.view.get_base_color(b); });
var feature_mapper = null;
ctx.fillStyle = this.prefs.block_color;
https://bitbucket.org/galaxy/galaxy-central/commits/f2b6054ba376/
changeset: f2b6054ba376
user: jgoecks
date: 2013-02-28 22:54:26
summary: Trackster enhancements: (a) rename reference data manager to more appropriate name; (b) fetch reference data more readily so that variants can be drawn even when not zoomed way in; and (c) use base letters to denote variants only when there is sufficient room.
affected #: 3 files
diff -r d09e8f41ffbb9948e55c184832c8f8e265bbdb2d -r f2b6054ba37646f0cee2c0cd1931fc28353167bf static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -739,7 +739,8 @@
seq_offset = 0,
gap = Math.round(w_scale/2),
char_width_px = ctx.canvas.manager.char_width_px,
- block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color);
+ block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color),
+ pack_mode = (mode === 'Pack');
// Keep list of items that need to be drawn on top of initial drawing layer.
var draw_last = [];
@@ -783,9 +784,9 @@
// Draw read base as rectangle.
ctx.fillStyle = block_color;
ctx.fillRect(s_start - gap,
- y_center + (mode === 'Pack' ? 1 : 4 ),
+ y_center + (pack_mode ? 1 : 4 ),
s_end - s_start,
- (mode === 'Pack' ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
// Draw sequence and/or variants.
var seq = read_seq.slice(seq_offset, seq_offset + cig_len),
@@ -815,14 +816,14 @@
// Draw base.
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
ctx.fillStyle = this.base_color_fn(seq[c]);
- if (mode === 'Pack') {
+ if (pack_mode && gap > 0) {
ctx.fillText(seq[c], c_start, y_center + 9);
}
else {
ctx.fillRect(c_start - gap,
- y_center + 4,
+ y_center + (pack_mode ? 1 : 4),
Math.floor( Math.max(1, w_scale) ),
- SQUISH_FEATURE_HEIGHT);
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
}
diff -r d09e8f41ffbb9948e55c184832c8f8e265bbdb2d -r f2b6054ba37646f0cee2c0cd1931fc28353167bf static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -2928,9 +2928,9 @@
can_draw_now = false;
}
- // Get seq data if needed, maybe a deferred
+ // Get reference data if needed, maybe a deferred
var seq_data;
- if ( view.reference_track && w_scale > view.canvas_manager.char_width_px ) {
+ if ( view.reference_track ) {
seq_data = view.reference_track.data_manager.get_data(region, track.mode, resolution, view.reference_track.data_url_extra_params);
if ( is_deferred( seq_data ) ) {
can_draw_now = false;
@@ -3463,7 +3463,7 @@
this.content_div.css("border", "none");
this.data_url = reference_url + "/" + this.view.dbkey;
this.data_url_extra_params = {reference: true};
- this.data_manager = new visualization.ReferenceTrackDataManager({
+ this.data_manager = new visualization.GenomeReferenceDataManager({
data_url: this.data_url,
can_subset: this.can_subset
});
diff -r d09e8f41ffbb9948e55c184832c8f8e265bbdb2d -r f2b6054ba37646f0cee2c0cd1931fc28353167bf static/scripts/viz/visualization.js
--- a/static/scripts/viz/visualization.js
+++ b/static/scripts/viz/visualization.js
@@ -615,7 +615,7 @@
}
});
-var ReferenceTrackDataManager = GenomeDataManager.extend({
+var GenomeReferenceDataManager = GenomeDataManager.extend({
initialize: function(options) {
// Use generic object in place of dataset and set urlRoot to fetch data.
var dataset_placeholder = new Backbone.Model();
@@ -624,12 +624,10 @@
},
load_data: function(region, mode, resolution, extra_params) {
- if (resolution > 1) {
- // Now that data is pre-fetched before draw, we don't load reference tracks
- // unless it's at the bottom level.
- return { data: null };
- }
- return GenomeDataManager.prototype.load_data.call(this, region, mode, resolution, extra_params);
+ // Fetch data if region is not too large.
+ return ( region.length() <= 100000 ?
+ GenomeDataManager.prototype.load_data.call(this, region, mode, resolution, extra_params) :
+ { data: null, region: region } );
}
});
@@ -999,7 +997,7 @@
GenomeRegion: GenomeRegion,
GenomeRegionCollection: GenomeRegionCollection,
GenomeVisualization: GenomeVisualization,
- ReferenceTrackDataManager: ReferenceTrackDataManager,
+ GenomeReferenceDataManager: GenomeReferenceDataManager,
TrackBrowserRouter: TrackBrowserRouter,
TrackConfig: TrackConfig,
Visualization: Visualization,
https://bitbucket.org/galaxy/galaxy-central/commits/d1ab12313b6a/
changeset: d1ab12313b6a
user: jgoecks
date: 2013-02-28 22:55:33
summary: Pack scripts.
affected #: 3 files
diff -r f2b6054ba37646f0cee2c0cd1931fc28353167bf -r d1ab12313b6acfbfd51a38195d9c5e75716e7752 static/scripts/packed/viz/trackster/painters.js
--- a/static/scripts/packed/viz/trackster/painters.js
+++ b/static/scripts/packed/viz/trackster/painters.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null)};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,ref_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=0,char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color);var draw_last=[];if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){gap=Math.round(w_scale/2)}if(!cigar){cigar=[[0,ref_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,(seq_start-tile_low)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset,seq_offset+cig_len);if(gap>0){ctx.fillStyle=block_color;ctx.fillRect(s_start-gap,y_center+1,s_end-s_start,9);ctx.fillStyle=CONNECTOR_COLOR;for(var c=0,str_len=seq.length;c<str_len;c++){if(this.prefs.show_differences){if(this.ref_seq){var ref_char=this.ref_seq[seq_start-tile_low+c];if(!ref_char||ref_char.toLowerCase()===seq[c].toLowerCase()){continue}}else{continue}}if(seq_start+c>=tile_low&&seq_start+c<=tile_high){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start,y_center+9)}}}else{ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+4,s_end-s_start,SQUISH_FEATURE_HEIGHT)}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start-gap,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start-gap,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color,gap=0;if((mode==="Pack"||this.mode==="Auto")&&w_scale>ctx.canvas.manager.char_width_px){var gap=Math.round(w_scale/2)}if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end-gap,y_center+5,b2_start-gap,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;var tile_index=1;if(tile_index===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING-gap,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING-gap,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}});
\ No newline at end of file
+define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,(seq_start-tile_low)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start-gap,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char,x_pos;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];x_pos=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&gap>0){ctx.fillText(seq[c],c_start,y_center+9)}else{ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.floor(Math.max(1,w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start-gap,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start-gap,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color,gap=0;if((mode==="Pack"||this.mode==="Auto")&&w_scale>ctx.canvas.manager.char_width_px){var gap=Math.round(w_scale/2)}if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end-gap,y_center+5,b2_start-gap,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;var tile_index=1;if(tile_index===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING-gap,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING-gap,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}});
\ No newline at end of file
diff -r f2b6054ba37646f0cee2c0cd1931fc28353167bf -r d1ab12313b6acfbfd51a38195d9c5e75716e7752 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","mvc/data","viz/trackster/filters"],function(ab,x,l,u,L,Y,i){var q=ab.extend;var V=function(ac){return("isResolved" in ac)};var n={};var k=function(ac,ad){n[ac.attr("id")]=ad};var m=function(ac,ae,ag,af){ag=".group";var ad={};n[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=n[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}n[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);n[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));n[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,A=100,I=12000,S=400,K=5000,w=100,o="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.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20;function W(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var r=function(ad,ac,af){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.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(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];q(r.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(){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;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 ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(ad,ac,ae){r.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=p(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac]._draw()}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(ad,ac,af){q(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw(true)}ac.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}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 ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ag=[];for(var ad=0;ad<this.drawables.length;ad++){ag.push(this.drawables[ad].name)}var ae="Composite Track of "+this.drawables.length+" tracks ("+ag.join(", ")+")";var af=new f(this.view,this.view,{name:ae,drawables:this.drawables});var ac=this.container.replace_drawable(this,af,true);af.request_draw()},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){z.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac,ae){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].request_draw(ac,ae)}}});var Z=Backbone.View.extend({initialize:function(ac){q(ac,{obj_type:"View"});z.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.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 x.CanvasManager(this.container.get(0).ownerDocument);this.reset()},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);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;k(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){x.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(p(ah,ac,ac))})})});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 ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).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(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_drawables(),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[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(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new X(this,{content_div:this.top_labeltrack}));this.add_label_track(new X(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")}});q(Z.prototype,z.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(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=w;var ac=this,ad=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+w+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+w+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-w});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+w});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();ae.request_redraw(true);for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad!==undefined&&aj!==undefined){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/ |,/g,"");var ak=this,ac,af,ad=ag.split(":"),ai=ad[0],aj=ad[1];if(aj!==undefined){try{var ah=aj.split("-");ac=parseInt(ah[0],10);af=parseInt(ah[1],10)}catch(ae){return false}}ak.change_chrom(ai,ac,af)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw();var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){z.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ak,ac,aj,al){var ai=this,ah=(al?[al]:ai.drawables),ae;var ad;for(var ag=0;ag<ah.length;ag++){ad=ah[ag];ae=-1;for(var af=0;af<ai.tracks_to_be_redrawn.length;af++){if(ai.tracks_to_be_redrawn[af][0]===ad){ae=af;break}}if(ae<0){ai.tracks_to_be_redrawn.push([ad,ac,aj])}else{ai.tracks_to_be_redrawn[ag][1]=ac;ai.tracks_to_be_redrawn[ag][2]=aj}}if(!this.requested_redraw){requestAnimationFrame(function(){ai._redraw(ak)});this.requested_redraw=true}},_redraw:function(am){this.requested_redraw=false;var aj=this.low,af=this.high;if(aj<this.max_low){aj=this.max_low}if(af>this.max_high){af=this.max_high}var al=this.high-this.low;if(this.high!==0&&al<this.min_separation){af=aj+this.min_separation}this.low=Math.floor(aj);this.high=Math.ceil(af);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 ac=(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 an=13;this.overview_box.css({left:ac,width:Math.max(an,ai)}).show();if(ai<an){this.overview_box.css("left",ac-(an-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ac,width:ai})}if(!am){var ae,ad,ak;for(var ag=0,ah=this.tracks_to_be_redrawn.length;ag<ah;ag++){ae=this.tracks_to_be_redrawn[ag][0];ad=this.tracks_to_be_redrawn[ag][1];ak=this.tracks_to_be_redrawn[ag][2];if(ae){ae._draw(ad,ak)}}this.tracks_to_be_redrawn=[];for(ag=0,ah=this.label_tracks.length;ag<ah;ag++){this.label_tracks[ag]._draw()}}},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);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(ae){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ae.dataset_id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.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 s=function(ae,aj,af){this.track=ae;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new N(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.original_dataset_id,tool_id:ac.name},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new x.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.name,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new P(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new Y.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(y+ag.message)}else{af(ag)}}})}});var N=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){N.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){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(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};q(F.prototype,{restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(l.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="float"){ag=parseFloat(ag)}else{if(ah.type==="int"){ag=parseInt(ag)}else{if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}}}if(ag!==ae.values[ah.key]){ae.values[ah.key]=ag;ad=true}}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ac,ah,ae,ad,af,ag){b.call(this,ac,ah,ae,ad,af);this.max_val=ag};q(j.prototype,b.prototype);var O=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new x.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.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(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?W(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){q(ae,{drag_handle_class:"draghandle"});r.call(this,ad,ac,ae);this.dataset=new Y.Dataset({id:ae.dataset_id,hda_ldda:ae.hda_ldda});this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new x.GenomeDataManager({dataset:this.dataset,genome:new x.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.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 ae)||ae.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<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>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new x.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ac.dataset_id,hda_ldda:ac.hda_ldda,regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},on_resize:function(){},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(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 ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){r.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 X){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof R){return"VcfTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.content_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset_id){return}var ac=$.Deferred(),af={hda_ldda:ad.hda_ldda,data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(o);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(v);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(U);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when(ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;m(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new s(this,af.tool,af.tool_state):null);this.tile_cache=new x.Cache(Q);if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;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(af.mode){this.change_mode(af.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.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(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw(true)},hide:true}]),copy:function(ac){var ad=this.to_dict();q(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;ac.tile_cache.clear();ac.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ad,ac){this.view.request_redraw(false,ad,ac,this)},before_draw:function(){},_draw:function(ad,ao){if(!this.can_draw()){return}var al=this.view.low,ah=this.view.high,aj=ah-al,ae=this.view.container.width(),aq=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;aq=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(al/(ag*S)),ak=true,ap=[],ai=function(ar){return(ar&&"track" in ar)};while((ac*S*ag)<ah){var am=this._get_tile_bounds(ac,ag),an=this.draw_helper(ad,am,ag,this.tiles_div,aq);if(ai(an)){ap.push(an)}else{ak=false}ac+=1}if(!ao){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;if(ak){this.tiles_div.children(".remove").remove();af.postdraw_actions(ap,ae,aq,ao)}},postdraw_actions:function(ad,ae,ag,ac){var af=ab.find(ad,function(ah){return ah.has_icons});if(af){ab.each(ad,function(ah){if(!ah.has_icons){ah.html_elt.css("padding-top",D)}})}},draw_helper:function(ac,af,ar,ah,ai,ao){var an=this,aw=this._gen_tile_cache_key(ai,af);if(!ao){ao={}}var av=(ac?undefined:an.tile_cache.get_elt(aw));if(av){an.show_tile(av,ah,ai);return av}var al=true;var at=an.data_manager.get_data(af,an.mode,ar,an.data_url_extra_params);if(V(at)){al=false}var aj;if(view.reference_track&&ai>view.canvas_manager.char_width_px){aj=view.reference_track.data_manager.get_data(af,an.mode,ar,view.reference_track.data_url_extra_params);if(V(aj)){al=false}}if(al){q(at,ao.more_tile_data);var ak=an.mode;if(ak==="Auto"){ak=an.get_mode(at);an.update_auto_mode(ak)}var ae=an.view.canvas_manager.new_canvas(),au=af.get("start"),ad=af.get("end"),ap=Math.ceil((ad-au)*ai)+an.left_offset,am=an.get_canvas_height(at,ak,ai,ap);ae.width=ap;ae.height=am;var aq=ae.getContext("2d");aq.translate(this.left_offset,0);var av=an.draw_tile(at,aq,ak,ar,af,ai,aj);if(av!==undefined){an.tile_cache.set_elt(aw,av);an.show_tile(av,ah,ai)}return av}var ag=$.Deferred();$.when(at,aj).then(function(){view.request_redraw(false,false,false,an);ag.resolve()});return ag},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah,ai){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{ah.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*S*ad),ag=Math.ceil(S*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){return true},can_subset:function(ac){return false},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(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new l.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset_id,hda_ldda:ad.hda_ldda},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var X=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};q(X.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ae=this.view,af=ae.high-ae.low,ai=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/ai)*ai,ag=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ah=(ac-ae.low)/af*ag;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ah-1}));ac+=ai}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){M.call(this,ad,ac,ag);this.drawables=[];this.left_offset=0;if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=p(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ac){M.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.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:r.prototype.can_draw,draw_helper:function(ad,ah,av,aj,al,at){var aq=this,aB=this._gen_tile_cache_key(al,ah);if(!at){at={}}var aA=(ad?undefined:aq.tile_cache.get_elt(aB));if(aA){aq.show_tile(aA,aj,al);return aA}var ak=[],aq,ao=true,aw,am;for(var ax=0;ax<this.drawables.length;ax++){aq=this.drawables[ax];aw=aq.data_manager.get_data(ah,aq.mode,av,aq.data_url_extra_params);if(V(aw)){ao=false}ak.push(aw);am=null;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ah,aq.mode,av,view.reference_track.data_url_extra_params);if(V(am)){ao=false}}ak.push(am)}if(ao){q(aw,at.more_tile_data);this.tile_predraw_init();var ag=aq.view.canvas_manager.new_canvas(),ay=ah.get("start"),ae=ah.get("end"),az=0,ar=Math.ceil((ae-ay)*al)+this.left_offset,ap=0,af=[],ax;var ac=0;for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}af.push(an);ac=aq.get_canvas_height(aw,an,al,ar);if(ac>ap){ap=ac}}ag.width=ar;ag.height=(at.height?at.height:ap);az=0;var au=ag.getContext("2d");au.translate(this.left_offset,0);au.globalAlpha=0.5;au.globalCompositeOperation="source-over";for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];am=ak[az+1];aA=aq.draw_tile(aw,au,af[ax],av,ah,al,am)}this.tile_cache.set_elt(aB,aA);this.show_tile(aA,aj,al);return aA}var ai=$.Deferred(),aq=this;$.when.apply($,ak).then(function(){view.request_redraw(false,false,false,aq);ai.resolve()});return ai},show_group:function(){var af=new P(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw()},tile_predraw_init:function(){var af=Number.MAX_VALUE,ac=-af,ad;for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];if(ad instanceof h){if(ad.prefs.min_value<af){af=ad.prefs.min_value}if(ad.prefs.max_value>ac){ac=ad.prefs.max_value}}}for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];ad.prefs.min_value=af;ad.prefs.max_value=ac}},postdraw_actions:function(ae,ah,aj,ad){M.prototype.postdraw_actions.call(this,ae,ah,aj,ad);var ag=-1;for(var af=0;af<ae.length;af++){var ac=ae[af].html_elt.find("canvas").height();if(ac>ag){ag=ac}}for(var af=0;af<ae.length;af++){var ai=ae[af];if(ai.html_elt.find("canvas").height()!==ag){this.draw_helper(true,ai.index,ai.resolution,ai.html_elt.parent(),aj,{height:ag});ai.html_elt.remove()}}}});var B=function(ac){M.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.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=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.ReferenceTrackDataManager({data_url:this.data_url});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ae,af,ac,ag,ah,ad){if(ah>this.view.canvas_manager.char_width_px){return M.prototype.draw_helper.call(this,ae,af,ac,ag,ah,ad)}else{this.hide_contents();return null}},draw_tile:function(ak,al,ag,af,ai,am){var ae=this;if(am>this.view.canvas_manager.char_width_px){if(ak.data===null){this.hide_contents();return}var ad=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";ak=ak.data;for(var ah=0,aj=ak.length;ah<aj;ah++){var ac=Math.floor(ah*am);al.fillText(ak[ah],ac,10)}this.show_contents();return new b(ae,ai,af,ad,ak)}this.hide_contents()}});var h=function(ae,ad,af){var ac=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;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:l.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:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ac=this;ac.vertical_range=undefined;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.hda_ldda},function(ad){ac.container_div.addClass("line-track");var ag=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=ag.min,ai=ag.max;ae=Math.floor(Math.min(0,Math.max(ae,ag.mean-2*ag.sd)));ai=Math.ceil(Math.max(0,Math.min(ai,ag.mean+2*ag.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ai;$("#track_"+ac.dataset_id+"_minval").val(ac.prefs.min_value);$("#track_"+ac.dataset_id+"_maxval").val(ac.prefs.max_value)}ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.total_frequency=ag.total_frequency;ac.container_div.find(".yaxislabel").remove();var ah=$("<div/>").text(W(ac.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_min_value(aj)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ac.dataset_id+"_minval").prependTo(ac.container_div),af=$("<div/>").text(W(ac.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_max_value(aj)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ac.dataset_id+"_maxval").prependTo(ac.container_div)})},draw_tile:function(al,aj,ae,ad,ag,ak){var ac=aj.canvas,af=ag.get("start"),ai=ag.get("end"),ah=new L.LinePainter(al.data,af,ai,this.prefs,ae);ah.draw(aj,ac.width,ac.height,ak);return new b(this,ag,ad,ac,al.data)},can_subset:function(ac){return false}});var t=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;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:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;this.tile_cache.clear();this.request_draw()},draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,af,ae,ah);var ag=l.get_random_color(),ac=l.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 color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{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:"histogram_max",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:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.tile_cache.clear();ad.set_painter_from_config();ad.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ah.hda_ldda;this.dataset_id=ah.dataset_id;this.original_dataset_id=ah.dataset_id;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()};q(c.prototype,r.prototype,M.prototype,{set_dataset:function(ac){this.dataset_id=ac.get("id");this.hda_ldda=ac.get("hda_ldda");this.dataset=ac;this.data_manager.set("dataset",ac)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ar,am,ah,ag){M.prototype.postdraw_actions.call(this,ar,ag);var al=this,ao;if(al.mode==="Coverage"){var ad=-1;for(ao=0;ao<ar.length;ao++){var an=ar[ao].max_val;if(an>ad){ad=an}}for(ao=0;ao<ar.length;ao++){var au=ar[ao];if(au.max_val!==ad){au.html_elt.remove();al.draw_helper(true,au.index,au.resolution,au.html_elt.parent(),ah,{more_tile_data:{max:ad}})}}}if(al.filters_manager){var ai=al.filters_manager.filters;for(var aq=0;aq<ai.length;aq++){ai[aq].update_ui_elt()}var at=false,ac,aj;for(ao=0;ao<ar.length;ao++){if(ar[ao].data.length){ac=ar[ao].data[0];for(var aq=0;aq<ai.length;aq++){aj=ai[aq];if(aj.applies_to(ac)&&aj.min!==aj.max){at=true;break}}}}if(al.filters_available!==at){al.filters_available=at;if(!al.filters_available){al.filters_manager.hide()}al.update_icons()}}this.container_div.find(".yaxislabel").remove();var af=ar[0];if(af instanceof j){var ak=(this.prefs.histogram_max?this.prefs.histogram_max:af.max_val),ae=$("<div/>").text(ak).make_text_editable({num_cols:12,on_finish:function(av){$(".bs-tooltip").remove();var av=parseFloat(av);al.prefs.histogram_max=(!isNaN(av)?av:null);al.tile_cache.clear();al.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ae)}if(af instanceof O){var ap=true;for(ao=0;ao<ar.length;ao++){if(!ar[ao].all_slotted){ap=false;break}}if(!ap){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(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}else{if(ac==="summary_tree"){ac="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (u.FeatureSlotter)(ag,af,A,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ac.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(ac,ag,ah,ad){if(ag==="summary_tree"||ag==="Coverage"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(ao==="summary_tree"||ao==="Coverage"){var aA=new L.SummaryTreePainter(am,ay,ac,this.prefs);aA.draw(aq,ad.width,ad.height,aj);return new j(ap,af,ar,ad,am.data,am.max)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null);var az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null);var aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae);var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new O(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="summary_tree"}else{if(ac.extra_info==="no_detail"||ac.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="summary_tree"||ac.message||ac.extra_info==="no_detail"){return false}return true}});var R=function(ad,ac,ae){c.call(this,ad,ac,ae);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:l.get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter};q(R.prototype,r.prototype,M.prototype,c.prototype);var T=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=l.get_random_color(),ac=l.get_random_color([af,"#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:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{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:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter;this.update_icons()};q(T.prototype,r.prototype,M.prototype,c.prototype);var d={LineTrack:h,FeatureTrack:c,VcfTrack:R,ReadTrack:T,DiagonalHeatmapTrack:t,CompositeTrack:f,DrawableGroup:P};var p=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Z,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:T,VcfTrack:R,CompositeTrack:f,object_from_template:p}});
\ No newline at end of file
+define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,x,l,u,L,Y,i){var q=ab.extend;var V=function(ac){return("isResolved" in ac)};var n={};var k=function(ac,ad){n[ac.attr("id")]=ad};var m=function(ac,ae,ag,af){ag=".group";var ad={};n[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=n[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}n[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);n[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));n[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,A=100,I=12000,S=400,K=5000,w=100,o="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.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20;function W(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var r=function(ad,ac,af){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.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(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];q(r.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(){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;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 ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(ad,ac,ae){r.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=p(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac]._draw()}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(ad,ac,af){q(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw(true)}ac.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}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 ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ag=[];for(var ad=0;ad<this.drawables.length;ad++){ag.push(this.drawables[ad].name)}var ae="Composite Track of "+this.drawables.length+" tracks ("+ag.join(", ")+")";var af=new f(this.view,this.view,{name:ae,drawables:this.drawables});var ac=this.container.replace_drawable(this,af,true);af.request_draw()},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){z.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac,ae){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].request_draw(ac,ae)}}});var Z=Backbone.View.extend({initialize:function(ac){q(ac,{obj_type:"View"});z.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.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 x.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"}],saved_values:ac.prefs,onchange:function(){track.request_redraw(false,true)}})},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);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;k(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){x.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(p(ah,ac,ac))})})});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 ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).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(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_drawables(),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[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(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new X(this,{content_div:this.top_labeltrack}));this.add_label_track(new X(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ac){return this.config.values[ac.toLowerCase()+"_color"]}});q(Z.prototype,z.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(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=w;var ac=this,ad=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+w+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+w+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-w});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+w});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();ae.request_redraw(true);for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad!==undefined&&aj!==undefined){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/ |,/g,"");var ak=this,ac,af,ad=ag.split(":"),ai=ad[0],aj=ad[1];if(aj!==undefined){try{var ah=aj.split("-");ac=parseInt(ah[0],10);af=parseInt(ah[1],10)}catch(ae){return false}}ak.change_chrom(ai,ac,af)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw();var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){z.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ak,ac,aj,al){var ai=this,ah=(al?[al]:ai.drawables),ae;var ad;for(var ag=0;ag<ah.length;ag++){ad=ah[ag];ae=-1;for(var af=0;af<ai.tracks_to_be_redrawn.length;af++){if(ai.tracks_to_be_redrawn[af][0]===ad){ae=af;break}}if(ae<0){ai.tracks_to_be_redrawn.push([ad,ac,aj])}else{ai.tracks_to_be_redrawn[ag][1]=ac;ai.tracks_to_be_redrawn[ag][2]=aj}}if(!this.requested_redraw){requestAnimationFrame(function(){ai._redraw(ak)});this.requested_redraw=true}},_redraw:function(am){this.requested_redraw=false;var aj=this.low,af=this.high;if(aj<this.max_low){aj=this.max_low}if(af>this.max_high){af=this.max_high}var al=this.high-this.low;if(this.high!==0&&al<this.min_separation){af=aj+this.min_separation}this.low=Math.floor(aj);this.high=Math.ceil(af);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 ac=(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 an=13;this.overview_box.css({left:ac,width:Math.max(an,ai)}).show();if(ai<an){this.overview_box.css("left",ac-(an-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ac,width:ai})}if(!am){var ae,ad,ak;for(var ag=0,ah=this.tracks_to_be_redrawn.length;ag<ah;ag++){ae=this.tracks_to_be_redrawn[ag][0];ad=this.tracks_to_be_redrawn[ag][1];ak=this.tracks_to_be_redrawn[ag][2];if(ae){ae._draw(ad,ak)}}this.tracks_to_be_redrawn=[];for(ag=0,ah=this.label_tracks.length;ag<ah;ag++){this.label_tracks[ag]._draw()}}},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);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(ae){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ae.dataset_id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.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 s=function(ae,aj,af){this.track=ae;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new N(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.original_dataset_id,tool_id:ac.name},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new x.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.name,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new P(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new Y.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(y+ag.message)}else{af(ag)}}})}});var N=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){N.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){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(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};q(F.prototype,{restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(l.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="float"){ag=parseFloat(ag)}else{if(ah.type==="int"){ag=parseInt(ag,10)}else{if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}}}if(ag!==ae.values[ah.key]){ae.values[ah.key]=ag;ad=true}}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ac,ah,ae,ad,af,ag){b.call(this,ac,ah,ae,ad,af);this.max_val=ag};q(j.prototype,b.prototype);var O=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new x.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.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(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?W(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){q(ae,{drag_handle_class:"draghandle"});r.call(this,ad,ac,ae);this.dataset=new Y.Dataset({id:ae.dataset_id,hda_ldda:ae.hda_ldda});this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new x.GenomeDataManager({dataset:this.dataset,genome:new x.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.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 ae)||ae.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<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>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new x.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ac.dataset_id,hda_ldda:ac.hda_ldda,regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},on_resize:function(){},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(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 ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){r.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 X){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof R){return"VcfTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.content_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset_id){return}var ac=$.Deferred(),af={hda_ldda:ad.hda_ldda,data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(o);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(v);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(U);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when(ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;m(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new s(this,af.tool,af.tool_state):null);this.tile_cache=new x.Cache(Q);if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;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(af.mode){this.change_mode(af.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.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(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw(true)},hide:true}]),copy:function(ac){var ad=this.to_dict();q(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;ac.tile_cache.clear();ac.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ad,ac){this.view.request_redraw(false,ad,ac,this)},before_draw:function(){},_draw:function(ad,ao){if(!this.can_draw()){return}var al=this.view.low,ah=this.view.high,aj=ah-al,ae=this.view.container.width(),aq=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;aq=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(al/(ag*S)),ak=true,ap=[],ai=function(ar){return(ar&&"track" in ar)};while((ac*S*ag)<ah){var am=this._get_tile_bounds(ac,ag),an=this.draw_helper(ad,am,ag,this.tiles_div,aq);if(ai(an)){ap.push(an)}else{ak=false}ac+=1}if(!ao){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;if(ak){this.tiles_div.children(".remove").remove();af.postdraw_actions(ap,ae,aq,ao)}},postdraw_actions:function(ad,ae,ag,ac){var af=ab.find(ad,function(ah){return ah.has_icons});if(af){ab.each(ad,function(ah){if(!ah.has_icons){ah.html_elt.css("padding-top",D)}})}},draw_helper:function(ac,af,ar,ah,ai,ao){var an=this,aw=this._gen_tile_cache_key(ai,af);if(!ao){ao={}}var av=(ac?undefined:an.tile_cache.get_elt(aw));if(av){an.show_tile(av,ah,ai);return av}var al=true;var at=an.data_manager.get_data(af,an.mode,ar,an.data_url_extra_params);if(V(at)){al=false}var aj;if(view.reference_track){aj=view.reference_track.data_manager.get_data(af,an.mode,ar,view.reference_track.data_url_extra_params);if(V(aj)){al=false}else{aj=view.reference_track.data_manager.subset_entry(aj,af)}}if(al){q(at,ao.more_tile_data);var ak=an.mode;if(ak==="Auto"){ak=an.get_mode(at);an.update_auto_mode(ak)}var ae=an.view.canvas_manager.new_canvas(),au=af.get("start"),ad=af.get("end"),ap=Math.ceil((ad-au)*ai)+an.left_offset,am=an.get_canvas_height(at,ak,ai,ap);ae.width=ap;ae.height=am;var aq=ae.getContext("2d");aq.translate(this.left_offset,0);var av=an.draw_tile(at,aq,ak,ar,af,ai,aj);if(av!==undefined){an.tile_cache.set_elt(aw,av);an.show_tile(av,ah,ai)}return av}var ag=$.Deferred();$.when(at,aj).then(function(){view.request_redraw(false,false,false,an);ag.resolve()});return ag},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah,ai){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{ah.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*S*ad),ag=Math.ceil(S*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){return true},can_subset:function(ac){return false},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(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new l.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset_id,hda_ldda:ad.hda_ldda},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var X=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};q(X.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ae=this.view,af=ae.high-ae.low,ai=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/ai)*ai,ag=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ah=(ac-ae.low)/af*ag;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ah-1}));ac+=ai}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){M.call(this,ad,ac,ag);this.drawables=[];this.left_offset=0;if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=p(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ac){M.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.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:r.prototype.can_draw,draw_helper:function(ad,ah,av,aj,al,at){var aq=this,aB=this._gen_tile_cache_key(al,ah);if(!at){at={}}var aA=(ad?undefined:aq.tile_cache.get_elt(aB));if(aA){aq.show_tile(aA,aj,al);return aA}var ak=[],aq,ao=true,aw,am;for(var ax=0;ax<this.drawables.length;ax++){aq=this.drawables[ax];aw=aq.data_manager.get_data(ah,aq.mode,av,aq.data_url_extra_params);if(V(aw)){ao=false}ak.push(aw);am=null;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ah,aq.mode,av,view.reference_track.data_url_extra_params);if(V(am)){ao=false}}ak.push(am)}if(ao){q(aw,at.more_tile_data);this.tile_predraw_init();var ag=aq.view.canvas_manager.new_canvas(),ay=ah.get("start"),ae=ah.get("end"),az=0,ar=Math.ceil((ae-ay)*al)+this.left_offset,ap=0,af=[],ax;var ac=0;for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}af.push(an);ac=aq.get_canvas_height(aw,an,al,ar);if(ac>ap){ap=ac}}ag.width=ar;ag.height=(at.height?at.height:ap);az=0;var au=ag.getContext("2d");au.translate(this.left_offset,0);au.globalAlpha=0.5;au.globalCompositeOperation="source-over";for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];am=ak[az+1];aA=aq.draw_tile(aw,au,af[ax],av,ah,al,am)}this.tile_cache.set_elt(aB,aA);this.show_tile(aA,aj,al);return aA}var ai=$.Deferred(),aq=this;$.when.apply($,ak).then(function(){view.request_redraw(false,false,false,aq);ai.resolve()});return ai},show_group:function(){var af=new P(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw()},tile_predraw_init:function(){var af=Number.MAX_VALUE,ac=-af,ad;for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];if(ad instanceof h){if(ad.prefs.min_value<af){af=ad.prefs.min_value}if(ad.prefs.max_value>ac){ac=ad.prefs.max_value}}}for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];ad.prefs.min_value=af;ad.prefs.max_value=ac}},postdraw_actions:function(ae,ah,aj,ad){M.prototype.postdraw_actions.call(this,ae,ah,aj,ad);var ag=-1;for(var af=0;af<ae.length;af++){var ac=ae[af].html_elt.find("canvas").height();if(ac>ag){ag=ac}}for(var af=0;af<ae.length;af++){var ai=ae[af];if(ai.html_elt.find("canvas").height()!==ag){this.draw_helper(true,ai.index,ai.resolution,ai.html_elt.parent(),aj,{height:ag});ai.html_elt.remove()}}}});var B=function(ac){M.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.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=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ae,af,ac,ag,ah,ad){if(ah>this.view.canvas_manager.char_width_px){this.tiles_div.show();return M.prototype.draw_helper.call(this,ae,af,ac,ag,ah,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ac){return true},draw_tile:function(af,al,ag,ad,ai,am){var ae=this.data_manager.subset_entry(af,ai),ak=ae.data;var ac=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";for(var ah=0,aj=ak.length;ah<aj;ah++){al.fillStyle=this.view.get_base_color(ak[ah]);al.fillText(ak[ah],Math.floor(ah*am),10)}return new b(this,ai,ad,ac,ae)}});var h=function(ae,ad,af){var ac=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;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:l.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:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ac=this;ac.vertical_range=undefined;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.hda_ldda},function(ad){ac.container_div.addClass("line-track");var ag=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=ag.min,ai=ag.max;ae=Math.floor(Math.min(0,Math.max(ae,ag.mean-2*ag.sd)));ai=Math.ceil(Math.max(0,Math.min(ai,ag.mean+2*ag.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ai;$("#track_"+ac.dataset_id+"_minval").val(ac.prefs.min_value);$("#track_"+ac.dataset_id+"_maxval").val(ac.prefs.max_value)}ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.total_frequency=ag.total_frequency;ac.container_div.find(".yaxislabel").remove();var ah=$("<div/>").text(W(ac.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_min_value(aj)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ac.dataset_id+"_minval").prependTo(ac.container_div),af=$("<div/>").text(W(ac.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_max_value(aj)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ac.dataset_id+"_maxval").prependTo(ac.container_div)})},draw_tile:function(al,aj,ae,ad,ag,ak){var ac=aj.canvas,af=ag.get("start"),ai=ag.get("end"),ah=new L.LinePainter(al.data,af,ai,this.prefs,ae);ah.draw(aj,ac.width,ac.height,ak);return new b(this,ag,ad,ac,al.data)},can_subset:function(ac){return(ac.data[1][0]-ac.data[0][0]===1)}});var t=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;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:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;this.tile_cache.clear();this.request_draw()},draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,af,ae,ah);var ag=l.get_random_color(),ac=l.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 color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{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:"histogram_max",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:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.tile_cache.clear();ad.set_painter_from_config();ad.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ah.hda_ldda;this.dataset_id=ah.dataset_id;this.original_dataset_id=ah.dataset_id;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()};q(c.prototype,r.prototype,M.prototype,{set_dataset:function(ac){this.dataset_id=ac.get("id");this.hda_ldda=ac.get("hda_ldda");this.dataset=ac;this.data_manager.set("dataset",ac)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ar,am,ah,ag){M.prototype.postdraw_actions.call(this,ar,ag);var al=this,ao;if(al.mode==="Coverage"){var ad=-1;for(ao=0;ao<ar.length;ao++){var an=ar[ao].max_val;if(an>ad){ad=an}}for(ao=0;ao<ar.length;ao++){var au=ar[ao];if(au.max_val!==ad){au.html_elt.remove();al.draw_helper(true,au.index,au.resolution,au.html_elt.parent(),ah,{more_tile_data:{max:ad}})}}}if(al.filters_manager){var ai=al.filters_manager.filters;for(var aq=0;aq<ai.length;aq++){ai[aq].update_ui_elt()}var at=false,ac,aj;for(ao=0;ao<ar.length;ao++){if(ar[ao].data.length){ac=ar[ao].data[0];for(var aq=0;aq<ai.length;aq++){aj=ai[aq];if(aj.applies_to(ac)&&aj.min!==aj.max){at=true;break}}}}if(al.filters_available!==at){al.filters_available=at;if(!al.filters_available){al.filters_manager.hide()}al.update_icons()}}this.container_div.find(".yaxislabel").remove();var af=ar[0];if(af instanceof j){var ak=(this.prefs.histogram_max?this.prefs.histogram_max:af.max_val),ae=$("<div/>").text(ak).make_text_editable({num_cols:12,on_finish:function(av){$(".bs-tooltip").remove();var av=parseFloat(av);al.prefs.histogram_max=(!isNaN(av)?av:null);al.tile_cache.clear();al.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ae)}if(af instanceof O){var ap=true;for(ao=0;ao<ar.length;ao++){if(!ar[ao].all_slotted){ap=false;break}}if(!ap){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(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}else{if(ac==="summary_tree"){ac="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (u.FeatureSlotter)(ag,af,A,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ac.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(ac,ag,ah,ad){if(ag==="summary_tree"||ag==="Coverage"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(ao==="summary_tree"||ao==="Coverage"){var aA=new L.SummaryTreePainter(am,ay,ac,this.prefs);aA.draw(aq,ad.width,ad.height,aj);return new j(ap,af,ar,ad,am.data,am.max)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae,function(aD){return ap.view.get_base_color(aD)});var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new O(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="summary_tree"}else{if(ac.extra_info==="no_detail"||ac.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="summary_tree"||ac.message||ac.extra_info==="no_detail"){return false}return true}});var R=function(ad,ac,ae){c.call(this,ad,ac,ae);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:l.get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter};q(R.prototype,r.prototype,M.prototype,c.prototype);var T=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=l.get_random_color(),ac=l.get_random_color([af,"#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:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{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:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter;this.update_icons()};q(T.prototype,r.prototype,M.prototype,c.prototype);var d={LineTrack:h,FeatureTrack:c,VcfTrack:R,ReadTrack:T,DiagonalHeatmapTrack:t,CompositeTrack:f,DrawableGroup:P};var p=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Z,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:T,VcfTrack:R,CompositeTrack:f,object_from_template:p}});
\ No newline at end of file
diff -r f2b6054ba37646f0cee2c0cd1931fc28353167bf -r d1ab12313b6acfbfd51a38195d9c5e75716e7752 static/scripts/packed/viz/visualization.js
--- a/static/scripts/packed/viz/visualization.js
+++ b/static/scripts/packed/viz/visualization.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","mvc/data","viz/trackster/util","utils/config"],function(s,i,l,p){var a=function(u,x,w,v){$.ajax({url:u,data:w,error:function(){alert("Grid failed")},success:function(y){show_modal("Select datasets for new tracks",y,{Cancel:function(){hide_modal()},Add:function(){var z=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var A={data_type:"track_config",hda_ldda:"hda"},B=$(this).val();if($(this).attr("name")!=="id"){A.hda_ldda="ldda"}z[z.length]=$.ajax({url:x+"/"+B,data:A,dataType:"json"})});$.when.apply($,z).then(function(){var A=(arguments[0] instanceof Array?$.map(arguments,function(B){return B[0]}):[arguments[0]]);v(A)});hide_modal()}})}})};var j=function(u){return("isResolved" in u)};var f=function(u){this.default_font=u!==undefined?u:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};s.extend(f.prototype,{load_pattern:function(u,y){var v=this.patterns,w=this.dummy_context,x=new Image();x.src=galaxy_paths.attributes.image_path+y;x.onload=function(){v[u]=w.createPattern(x,"repeat")}},get_pattern:function(u){return this.patterns[u]},new_canvas:function(){var u=$("<canvas/>")[0];if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(u)}u.manager=this;return u}});var q=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:null,key_ary:null},initialize:function(u){this.clear()},get_elt:function(v){var w=this.attributes.obj_cache,x=this.attributes.key_ary,u=x.indexOf(v);if(u!==-1){if(w[v].stale){x.splice(u,1);delete w[v]}else{this.move_key_to_end(v,u)}}return w[v]},set_elt:function(v,x){var y=this.attributes.obj_cache,z=this.attributes.key_ary,w=this.attributes.num_elements;if(!y[v]){if(z.length>=w){var u=z.shift();delete y[u]}z.push(v)}y[v]=x;return x},move_key_to_end:function(v,u){this.attributes.key_ary.splice(u,1);this.attributes.key_ary.push(v)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length},most_recently_added:function(){return this.size()===0?null:this.attributes.key_ary[this.attributes.key_ary.length-1]}});var d=q.extend({defaults:s.extend({},q.prototype.defaults,{dataset:null,genome:null,init_data:null,min_region_size:500,filters_manager:null,data_type:"data",data_mode_compatible:function(u,v){return true},can_subset:function(u){return false}}),initialize:function(u){q.prototype.initialize.call(this);var v=this.get("init_data");if(v){this.add_data(v)}},add_data:function(u){if(this.get("num_elements")<u.length){this.set("num_elements",u.length)}var v=this;s.each(u,function(w){v.set_data(w.region,w)})},data_is_ready:function(){var x=this.get("dataset"),w=$.Deferred(),u=(this.get("data_type")==="raw_data"?"state":this.get("data_type")==="data"?"converted_datasets_state":"error"),v=new l.ServerStateDeferred({ajax_settings:{url:this.get("dataset").url(),data:{hda_ldda:x.get("hda_ldda"),data_type:u},dataType:"json"},interval:5000,success_fn:function(y){return y!=="pending"}});$.when(v.go()).then(function(y){w.resolve(y==="ok"||y==="data")});return w},search_features:function(u){var v=this.get("dataset"),w={query:u,hda_ldda:v.get("hda_ldda"),data_type:"features"};return $.getJSON(v.url(),w)},load_data:function(C,B,v,A){var y=this.get("dataset"),x={data_type:this.get("data_type"),chrom:C.get("chrom"),low:C.get("start"),high:C.get("end"),mode:B,resolution:v,hda_ldda:y.get("hda_ldda")};$.extend(x,A);var E=this.get("filters_manager");if(E){var F=[];var u=E.filters;for(var z=0;z<u.length;z++){F.push(u[z].name)}x.filter_cols=JSON.stringify(F)}var w=this,D=$.getJSON(y.url(),x,function(G){w.set_data(C,G)});this.set_data(C,D);return D},get_data:function(A,z,w,y){var B=this.get_elt(A);if(B&&(j(B)||this.get("data_mode_compatible")(B,z))){return B}var C=this.get("key_ary"),v=this.get("obj_cache"),D,u;for(var x=0;x<C.length;x++){D=C[x];u=new g({from_str:D});if(u.contains(A)){B=v[D];if(j(B)||(this.get("data_mode_compatible")(B,z)&&this.get("can_subset")(B))){this.move_key_to_end(D,x);return B}}}if(A.length()<this.attributes.min_region_size){var E=new g({from_str:this.most_recently_added()});if(!E||(A.get("start")>E.get("start"))){A.set("end",A.get("start")+this.attributes.min_region_size)}else{A.set("start",A.get("end")-this.attributes.min_region_size)}A.set("genome",this.attributes.genome);A.trim()}return this.load_data(A,z,w,y)},set_data:function(v,u){this.set_elt(v,u)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(C,B,x,A,y){var E=this._mark_stale(C);if(!(E&&this.get("data_mode_compatible")(E,B))){console.log("ERROR: problem with getting more data: current data is not compatible");return}var w=C.get("start");if(y===this.DEEP_DATA_REQ){$.extend(A,{start_val:E.data.length+1})}else{if(y===this.BROAD_DATA_REQ){w=(E.max_high?E.max_high:E.data[E.data.length-1][2])+1}}var D=C.copy().set("start",w);var v=this,z=this.load_data(D,B,x,A),u=$.Deferred();this.set_data(C,u);$.when(z).then(function(F){if(F.data){F.data=E.data.concat(F.data);if(F.max_low){F.max_low=E.max_low}if(F.message){F.message=F.message.replace(/[0-9]+/,F.data.length)}}v.set_data(C,F);u.resolve(F)});return u},can_get_more_detailed_data:function(v){var u=this.get_elt(v);return(u.dataset_type==="bigwig"&&u.data.length<8000)},get_more_detailed_data:function(x,z,v,y,w){var u=this._mark_stale(x);if(!u){console.log("ERROR getting more detailed data: no current data");return}if(!w){w={}}if(u.dataset_type==="bigwig"){w.num_samples=1000*y}else{if(u.dataset_type==="summary_tree"){w.level=Math.min(u.level-1,2)}}return this.load_data(x,z,v,w)},_mark_stale:function(v){var u=this.get_elt(v);if(!u){console.log("ERROR: no data to mark as stale: ",this.get("dataset"),v.toString())}u.stale=true;return u},get_genome_wide_data:function(u){var w=this,y=true,x=s.map(u.get("chroms_info").chrom_info,function(A){var z=w.get_elt(new g({chrom:A.chrom,start:0,end:A.len}));if(!z){y=false}return z});if(y){return x}var v=$.Deferred();$.getJSON(this.get("dataset").url(),{data_type:"genome_data"},function(z){w.add_data(z.data);v.resolve(z.data)});return v},get_elt:function(u){return q.prototype.get_elt.call(this,u.toString())},set_elt:function(v,u){return q.prototype.set_elt.call(this,v.toString(),u)}});var n=d.extend({initialize:function(u){var v=new Backbone.Model();v.urlRoot=u.data_url;this.set("dataset",v)},load_data:function(w,x,u,v){if(u>1){return{data:null}}return d.prototype.load_data.call(this,w,x,u,v)}});var c=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},initialize:function(u){this.id=u.dbkey},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info},get_chrom_region:function(u){var v=s.find(this.get_chroms_info(),function(w){return w.chrom===u});return new g({chrom:v.chrom,end:v.len})},get_chrom_len:function(u){return s.find(this.get_chroms_info(),function(v){return v.chrom===u}).len}});var g=Backbone.RelationalModel.extend({defaults:{chrom:null,start:0,end:0,genome:null},initialize:function(v){if(v.from_str){var x=v.from_str.split(":"),w=x[0],u=x[1].split("-");this.set({chrom:w,start:parseInt(u[0],10),end:parseInt(u[1],10)})}},copy:function(){return new g({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},length:function(){return this.get("end")-this.get("start")},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},toJSON:function(){return{chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")}},compute_overlap:function(B){var v=this.get("chrom"),A=B.get("chrom"),z=this.get("start"),x=B.get("start"),y=this.get("end"),w=B.get("end"),u;if(v&&A&&v!==A){return g.overlap_results.DIF_CHROMS}if(z<x){if(y<x){u=g.overlap_results.BEFORE}else{if(y<w){u=g.overlap_results.OVERLAP_START}else{u=g.overlap_results.CONTAINS}}}else{if(z>x){if(z>w){u=g.overlap_results.AFTER}else{if(y<=w){u=g.overlap_results.CONTAINED_BY}else{u=g.overlap_results.OVERLAP_END}}}else{u=(y>=w?g.overlap_results.CONTAINS:g.overlap_results.CONTAINED_BY)}}return u},trim:function(u){if(this.attributes.start<0){this.attributes.start=0}if(this.attributes.genome){var v=this.attributes.genome.get_chrom_len(this.attributes.chrom);if(this.attributes.end>v){this.attributes.end=v-1}}return this},contains:function(u){return this.compute_overlap(u)===g.overlap_results.CONTAINS},overlaps:function(u){return s.intersection([this.compute_overlap(u)],[g.overlap_results.DIF_CHROMS,g.overlap_results.BEFORE,g.overlap_results.AFTER]).length===0}},{overlap_results:{DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006}});var m=Backbone.Collection.extend({model:g});var e=Backbone.RelationalModel.extend({defaults:{region:null,note:""},relations:[{type:Backbone.HasOne,key:"region",relatedModel:g}]});var r=Backbone.Collection.extend({model:e});var t=i.Dataset.extend({initialize:function(u){this.set("id",u.dataset_id);this.set("config",p.ConfigSettingCollection.from_config_dict(u.prefs));this.get("config").add([{key:"name",value:this.get("name")},{key:"color"}]);var v=this.get("preloaded_data");if(v){v=v.data}else{v=[]}this.set("data_manager",new d({dataset:this,init_data:v}))}});var o=Backbone.RelationalModel.extend({defaults:{title:"",type:""},url:galaxy_paths.get("visualization_url"),save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var k=o.extend({defaults:s.extend({},o.prototype.defaults,{dbkey:"",tracks:null,bookmarks:null,viewport:null}),relations:[{type:Backbone.HasMany,key:"tracks",relatedModel:t}],add_tracks:function(u){this.get("tracks").add(u)}});var b=Backbone.Model.extend({});var h=Backbone.Router.extend({initialize:function(v){this.view=v.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var u=this;u.view.on("navigate",function(w){u.navigate(w)})},change_location:function(u){this.view.go_to(u)}});return{BackboneTrack:t,BrowserBookmark:e,BrowserBookmarkCollection:r,Cache:q,CanvasManager:f,Genome:c,GenomeDataManager:d,GenomeRegion:g,GenomeRegionCollection:m,GenomeVisualization:k,ReferenceTrackDataManager:n,TrackBrowserRouter:h,TrackConfig:b,Visualization:o,select_datasets:a}});
\ No newline at end of file
+define(["libs/underscore","mvc/data","viz/trackster/util","utils/config"],function(s,i,l,o){var a=function(u,x,w,v){$.ajax({url:u,data:w,error:function(){alert("Grid failed")},success:function(y){show_modal("Select datasets for new tracks",y,{Cancel:function(){hide_modal()},Add:function(){var z=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var A={data_type:"track_config",hda_ldda:"hda"},B=$(this).val();if($(this).attr("name")!=="id"){A.hda_ldda="ldda"}z[z.length]=$.ajax({url:x+"/"+B,data:A,dataType:"json"})});$.when.apply($,z).then(function(){var A=(arguments[0] instanceof Array?$.map(arguments,function(B){return B[0]}):[arguments[0]]);v(A)});hide_modal()}})}})};var j=function(u){return("isResolved" in u)};var f=function(u){this.default_font=u!==undefined?u:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};s.extend(f.prototype,{load_pattern:function(u,y){var v=this.patterns,w=this.dummy_context,x=new Image();x.src=galaxy_paths.attributes.image_path+y;x.onload=function(){v[u]=w.createPattern(x,"repeat")}},get_pattern:function(u){return this.patterns[u]},new_canvas:function(){var u=$("<canvas/>")[0];if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(u)}u.manager=this;return u}});var q=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:null,key_ary:null},initialize:function(u){this.clear()},get_elt:function(v){var w=this.attributes.obj_cache,x=this.attributes.key_ary,u=x.indexOf(v);if(u!==-1){if(w[v].stale){x.splice(u,1);delete w[v]}else{this.move_key_to_end(v,u)}}return w[v]},set_elt:function(v,x){var y=this.attributes.obj_cache,z=this.attributes.key_ary,w=this.attributes.num_elements;if(!y[v]){if(z.length>=w){var u=z.shift();delete y[u]}z.push(v)}y[v]=x;return x},move_key_to_end:function(v,u){this.attributes.key_ary.splice(u,1);this.attributes.key_ary.push(v)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length},most_recently_added:function(){return this.size()===0?null:this.attributes.key_ary[this.attributes.key_ary.length-1]}});var d=q.extend({defaults:s.extend({},q.prototype.defaults,{dataset:null,genome:null,init_data:null,min_region_size:200,filters_manager:null,data_type:"data",data_mode_compatible:function(u,v){return true},can_subset:function(u){return false}}),initialize:function(u){q.prototype.initialize.call(this);var v=this.get("init_data");if(v){this.add_data(v)}},add_data:function(u){if(this.get("num_elements")<u.length){this.set("num_elements",u.length)}var v=this;s.each(u,function(w){v.set_data(w.region,w)})},data_is_ready:function(){var x=this.get("dataset"),w=$.Deferred(),u=(this.get("data_type")==="raw_data"?"state":this.get("data_type")==="data"?"converted_datasets_state":"error"),v=new l.ServerStateDeferred({ajax_settings:{url:this.get("dataset").url(),data:{hda_ldda:x.get("hda_ldda"),data_type:u},dataType:"json"},interval:5000,success_fn:function(y){return y!=="pending"}});$.when(v.go()).then(function(y){w.resolve(y==="ok"||y==="data")});return w},search_features:function(u){var v=this.get("dataset"),w={query:u,hda_ldda:v.get("hda_ldda"),data_type:"features"};return $.getJSON(v.url(),w)},load_data:function(C,B,v,A){var y=this.get("dataset"),x={data_type:this.get("data_type"),chrom:C.get("chrom"),low:C.get("start"),high:C.get("end"),mode:B,resolution:v,hda_ldda:y.get("hda_ldda")};$.extend(x,A);var E=this.get("filters_manager");if(E){var F=[];var u=E.filters;for(var z=0;z<u.length;z++){F.push(u[z].name)}x.filter_cols=JSON.stringify(F)}var w=this,D=$.getJSON(y.url(),x,function(G){G.region=C;w.set_data(C,G)});this.set_data(C,D);return D},get_data:function(B,A,w,y){var C=this.get_elt(B);if(C&&(j(C)||this.get("data_mode_compatible")(C,A))){return C}var D=this.get("key_ary"),v=this.get("obj_cache"),E,u,z;for(var x=0;x<D.length;x++){E=D[x];u=new g({from_str:E});if(u.contains(B)){z=true;C=v[E];if(j(C)||(this.get("data_mode_compatible")(C,A)&&this.get("can_subset")(C))){this.move_key_to_end(E,x);if(!j(C)){var G=this.subset_entry(C,B);this.set(B,G);C=G}return C}}}if(!z&&B.length()<this.attributes.min_region_size){var F=new g({from_str:this.most_recently_added()});if(!F||(B.get("start")>F.get("start"))){B.set("end",B.get("start")+this.attributes.min_region_size)}else{B.set("start",B.get("end")-this.attributes.min_region_size)}B.set("genome",this.attributes.genome);B.trim()}return this.load_data(B,A,w,y)},set_data:function(v,u){this.set_elt(v,u)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(C,B,x,A,y){var E=this._mark_stale(C);if(!(E&&this.get("data_mode_compatible")(E,B))){console.log("ERROR: problem with getting more data: current data is not compatible");return}var w=C.get("start");if(y===this.DEEP_DATA_REQ){$.extend(A,{start_val:E.data.length+1})}else{if(y===this.BROAD_DATA_REQ){w=(E.max_high?E.max_high:E.data[E.data.length-1][2])+1}}var D=C.copy().set("start",w);var v=this,z=this.load_data(D,B,x,A),u=$.Deferred();this.set_data(C,u);$.when(z).then(function(F){if(F.data){F.data=E.data.concat(F.data);if(F.max_low){F.max_low=E.max_low}if(F.message){F.message=F.message.replace(/[0-9]+/,F.data.length)}}v.set_data(C,F);u.resolve(F)});return u},can_get_more_detailed_data:function(v){var u=this.get_elt(v);return(u.dataset_type==="bigwig"&&u.data.length<8000)},get_more_detailed_data:function(x,z,v,y,w){var u=this._mark_stale(x);if(!u){console.log("ERROR getting more detailed data: no current data");return}if(!w){w={}}if(u.dataset_type==="bigwig"){w.num_samples=1000*y}else{if(u.dataset_type==="summary_tree"){w.level=Math.min(u.level-1,2)}}return this.load_data(x,z,v,w)},_mark_stale:function(v){var u=this.get_elt(v);if(!u){console.log("ERROR: no data to mark as stale: ",this.get("dataset"),v.toString())}u.stale=true;return u},get_genome_wide_data:function(u){var w=this,y=true,x=s.map(u.get("chroms_info").chrom_info,function(A){var z=w.get_elt(new g({chrom:A.chrom,start:0,end:A.len}));if(!z){y=false}return z});if(y){return x}var v=$.Deferred();$.getJSON(this.get("dataset").url(),{data_type:"genome_data"},function(z){w.add_data(z.data);v.resolve(z.data)});return v},subset_entry:function(w,x){var u={bigwig:function(y,z){return s.filter(y,function(A){return A[0]>=z.get("start")&&A[0]<=z.get("end")})},refseq:function(z,A){var B=A.get("start")-w.region.get("start"),y=w.data.length-(w.region.get("end")-A.get("end"));return w.data.slice(B,y)}};var v=w.data;if(!w.region.same(x)&&w.dataset_type in u){v=u[w.dataset_type](w.data,x)}return{region:x,data:v,dataset_type:w.dataset_type}},get_elt:function(u){return q.prototype.get_elt.call(this,u.toString())},set_elt:function(v,u){return q.prototype.set_elt.call(this,v.toString(),u)}});var p=d.extend({initialize:function(u){var v=new Backbone.Model();v.urlRoot=u.data_url;this.set("dataset",v)},load_data:function(w,x,u,v){return(w.length()<=100000?d.prototype.load_data.call(this,w,x,u,v):{data:null,region:w})}});var c=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},initialize:function(u){this.id=u.dbkey},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info},get_chrom_region:function(u){var v=s.find(this.get_chroms_info(),function(w){return w.chrom===u});return new g({chrom:v.chrom,end:v.len})},get_chrom_len:function(u){return s.find(this.get_chroms_info(),function(v){return v.chrom===u}).len}});var g=Backbone.RelationalModel.extend({defaults:{chrom:null,start:0,end:0,genome:null},same:function(u){return this.attributes.chrom===u.get("chrom")&&this.attributes.start===u.get("start")&&this.attributes.end===u.get("end")},initialize:function(v){if(v.from_str){var x=v.from_str.split(":"),w=x[0],u=x[1].split("-");this.set({chrom:w,start:parseInt(u[0],10),end:parseInt(u[1],10)})}},copy:function(){return new g({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},length:function(){return this.get("end")-this.get("start")},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},toJSON:function(){return{chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")}},compute_overlap:function(B){var v=this.get("chrom"),A=B.get("chrom"),z=this.get("start"),x=B.get("start"),y=this.get("end"),w=B.get("end"),u;if(v&&A&&v!==A){return g.overlap_results.DIF_CHROMS}if(z<x){if(y<x){u=g.overlap_results.BEFORE}else{if(y<w){u=g.overlap_results.OVERLAP_START}else{u=g.overlap_results.CONTAINS}}}else{if(z>x){if(z>w){u=g.overlap_results.AFTER}else{if(y<=w){u=g.overlap_results.CONTAINED_BY}else{u=g.overlap_results.OVERLAP_END}}}else{u=(y>=w?g.overlap_results.CONTAINS:g.overlap_results.CONTAINED_BY)}}return u},trim:function(u){if(this.attributes.start<0){this.attributes.start=0}if(this.attributes.genome){var v=this.attributes.genome.get_chrom_len(this.attributes.chrom);if(this.attributes.end>v){this.attributes.end=v-1}}return this},contains:function(u){return this.compute_overlap(u)===g.overlap_results.CONTAINS},overlaps:function(u){return s.intersection([this.compute_overlap(u)],[g.overlap_results.DIF_CHROMS,g.overlap_results.BEFORE,g.overlap_results.AFTER]).length===0}},{overlap_results:{DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006}});var m=Backbone.Collection.extend({model:g});var e=Backbone.RelationalModel.extend({defaults:{region:null,note:""},relations:[{type:Backbone.HasOne,key:"region",relatedModel:g}]});var r=Backbone.Collection.extend({model:e});var t=i.Dataset.extend({initialize:function(u){this.set("id",u.dataset_id);this.set("config",o.ConfigSettingCollection.from_config_dict(u.prefs));this.get("config").add([{key:"name",value:this.get("name")},{key:"color"}]);var v=this.get("preloaded_data");if(v){v=v.data}else{v=[]}this.set("data_manager",new d({dataset:this,init_data:v}))}});var n=Backbone.RelationalModel.extend({defaults:{title:"",type:""},url:galaxy_paths.get("visualization_url"),save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var k=n.extend({defaults:s.extend({},n.prototype.defaults,{dbkey:"",tracks:null,bookmarks:null,viewport:null}),relations:[{type:Backbone.HasMany,key:"tracks",relatedModel:t}],add_tracks:function(u){this.get("tracks").add(u)}});var b=Backbone.Model.extend({});var h=Backbone.Router.extend({initialize:function(v){this.view=v.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var u=this;u.view.on("navigate",function(w){u.navigate(w)})},change_location:function(u){this.view.go_to(u)}});return{BackboneTrack:t,BrowserBookmark:e,BrowserBookmarkCollection:r,Cache:q,CanvasManager:f,Genome:c,GenomeDataManager:d,GenomeRegion:g,GenomeRegionCollection:m,GenomeVisualization:k,GenomeReferenceDataManager:p,TrackBrowserRouter:h,TrackConfig:b,Visualization:n,select_datasets:a}});
\ No newline at end of file
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: inithello: Removed unneeded log data from functional test error reports, use url_join to generate api URLs.
by commits-noreply@bitbucket.org 28 Feb '13
by commits-noreply@bitbucket.org 28 Feb '13
28 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/74aeac783988/
changeset: 74aeac783988
user: inithello
date: 2013-02-28 20:41:53
summary: Removed unneeded log data from functional test error reports, use url_join to generate api URLs.
affected #: 1 file
diff -r f9ae3e1162ffd9aba37db4bdb0f849e36ed4ccd9 -r 74aeac7839881a47e691ab80bddaead0970590b8 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -37,6 +37,9 @@
# This should not be required, but it is under certain conditions, thanks to this bug: http://code.google.com/p/python-nose/issues/detail?id=284
eggs.require( "pysqlite" )
+import install_and_test_tool_shed_repositories.functional.test_install_repositories as test_install_repositories
+import functional.test_toolbox as test_toolbox
+
import atexit, logging, os, os.path, sys, tempfile, simplejson
import twill, unittest, time
import sys, threading, random
@@ -151,7 +154,11 @@
listing = file( location, 'r' ).read()
elif source == 'url':
assert tool_shed_api_key is not None, 'Cannot proceed without tool shed API key.'
- params = urllib.urlencode( dict( tools_functionally_correct='false', do_not_test='false', downloadable='true', malicious='false' ) )
+ params = urllib.urlencode( dict( tools_functionally_correct='false',
+ do_not_test='false',
+ downloadable='true',
+ malicious='false',
+ must_include_tools='true' ) )
api_url = get_api_url( base=location, parts=[ 'repository_revisions' ], params=params )
if format == 'json':
return json_from_url( api_url )
@@ -177,11 +184,11 @@
def register_test_failure( url, metadata_id, test_errors ):
params = dict( tools_functionally_correct='false', do_not_test='true', tool_test_errors=test_errors )
- return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params )
+ return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
def register_test_success( url, metadata_id ):
params = dict( tools_functionally_correct='true', do_not_test='false' )
- return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params )
+ return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
def run_tests( test_config ):
loader = nose.loader.TestLoader( config=test_config )
@@ -354,9 +361,6 @@
else:
raise Exception( "Test HTTP server did not return '200 OK' after 10 tries" )
log.info( "Embedded galaxy web server started" )
- # ---- Load the modules to generate installation, testing, and uninstallation methods -------------------
- import install_and_test_tool_shed_repositories.functional.test_install_repositories as test_install_repositories
- import functional.test_toolbox as test_toolbox
if galaxy_test_proxy_port:
log.info( "The embedded Galaxy application is running on %s:%s" % ( galaxy_test_host, galaxy_test_proxy_port ) )
else:
@@ -365,7 +369,7 @@
success = False
repository_status = {}
try:
- # Iterate through a list of repository info dicts
+ # Iterate through a list of repository info dicts.
log.info( "Retrieving repositories to install from the URL:\n%s\n" % str( galaxy_tool_shed_url ) )
repositories_to_install = get_repositories_to_install( galaxy_tool_shed_url, source='url' )
log.info( "Retrieved %d repositories to install..." % len( repositories_to_install ) )
@@ -381,15 +385,15 @@
"""
repository_id = repository_to_install_dict.get( 'repository_id', None )
changeset_revision = repository_to_install_dict.get( 'changeset_revision', None )
- metadata_revision_id = repository_to_install_dict[ 'id' ]
+ metadata_revision_id = repository_to_install_dict.get( 'id', None )
repository_to_install_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
- repository_info = get_repository_info_from_api( galaxy_tool_shed_url, repository_to_install_dict )
+ repository_info_dict = get_repository_info_from_api( galaxy_tool_shed_url, repository_to_install_dict )
# If a repository is deleted or malicious, we don't need to test it.
- if repository_info[ 'deleted' ] or repository_info[ 'deprecated' ]:
+ if repository_info_dict[ 'deleted' ] or repository_info_dict[ 'deprecated' ]:
log.info( "Skipping revision %s of repository id %s since it is either deleted or deprecated..." % ( str( changeset_revision ), str( repository_id ) ) )
continue
log.info( "Installing and testing revision %s of repository id %s..." % ( str( changeset_revision ), str( repository_id ) ) )
- repository_dict = dict( repository_info.items() + repository_to_install_dict.items() )
+ repository_dict = dict( repository_info_dict.items() + repository_to_install_dict.items() )
"""
Each repository_dict looks something like:
{'repository_id': '175812cd7caaf439',
@@ -412,12 +416,11 @@
# If the installation succeeds, set up and run functional tests for this repository. This is equivalent to
# sh run_functional_tests.sh -installed
if success:
- log.debug( 'Installation of %s succeeded, running any defined functional tests.' % repository_dict[ 'name' ] )
+ log.debug( 'Installation of %s succeeded, running all defined functional tests.' % repository_dict[ 'name' ] )
# Parse the tool panel config to get the test-data path for this repository.
if not os.path.exists( galaxy_shed_tools_dict ):
file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( dict() ) )
shed_tools_dict = parse_tool_panel_config( galaxy_shed_tool_conf_file, from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
- log.debug( shed_tools_dict )
# Write this to a file, so the functional test framework can find it.
file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
# Set up the environment so that test.functional.test_toolbox can find the Galaxy server we configured in this framework.
@@ -444,7 +447,7 @@
else:
# If the functional tests fail, log the output and submit it to the tool shed whence the repository was installed.
for failure in result.failures:
- label = str( failure[0] )
+ test_status = dict( test=str( failure[0] ) )
log_output = failure[1].replace( '\\n', '\n' )
log_output = re.sub( r'control \d+:.+', r'', log_output )
log_output = re.sub( r'\n+', r'\n', log_output )
@@ -454,6 +457,8 @@
for line in log_output.split( '\n' ):
if line.startswith( 'Traceback' ):
appending_to = 'traceback'
+ elif '>> end captured' in line:
+ continue
elif 'request returned None from get_history' in line:
continue
elif '>> begin captured logging <<' in line:
@@ -468,9 +473,10 @@
if appending_to not in tmp_output:
tmp_output[ appending_to ] = []
tmp_output[ appending_to ].append( line )
- for output_type in tmp_output:
- output[ output_type ] = '\n'.join( tmp_output[ output_type ] )
- test_errors.append( dict( test=label, output=output ) )
+ for output_type in [ 'stderr', 'stdout', 'traceback' ]:
+ if output_type in tmp_output:
+ test_status[ output_type ] = '\n'.join( tmp_output[ output_type ] )
+ test_errors.append( test_status )
if test_errors:
repository_status[ 'test_environment' ] = get_test_environment()
repository_status[ 'test_errors' ] = test_errors
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: Improve logging and comments in functional test framework for installing and testing tool shed repositories, and do not set test_errors column values unless tests actually failed.
by commits-noreply@bitbucket.org 28 Feb '13
by commits-noreply@bitbucket.org 28 Feb '13
28 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f9ae3e1162ff/
changeset: f9ae3e1162ff
user: greg
date: 2013-02-28 18:15:47
summary: Improve logging and comments in functional test framework for installing and testing tool shed repositories, and do not set test_errors column values unless tests actually failed.
affected #: 1 file
diff -r fb3a05f1f28e0b0652065dc3c87155004e65f0b3 -r f9ae3e1162ffd9aba37db4bdb0f849e36ed4ccd9 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -363,17 +363,42 @@
log.info( "The embedded Galaxy application is running on %s:%s" % ( galaxy_test_host, galaxy_test_port ) )
log.info( "Repositories will be installed from the tool shed at %s" % galaxy_tool_shed_url )
success = False
+ repository_status = {}
try:
- repository_status = {}
- # Iterate through a list of repository info dicts.
- for repository_dict in get_repositories_to_install( galaxy_tool_shed_url, source='url' ):
- metadata_revision_id = repository_dict[ 'id' ]
- repository_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
- repository_info = get_repository_info_from_api( galaxy_tool_shed_url, repository_dict )
+ # Iterate through a list of repository info dicts
+ log.info( "Retrieving repositories to install from the URL:\n%s\n" % str( galaxy_tool_shed_url ) )
+ repositories_to_install = get_repositories_to_install( galaxy_tool_shed_url, source='url' )
+ log.info( "Retrieved %d repositories to install..." % len( repositories_to_install ) )
+ for repository_to_install_dict in repositories_to_install:
+ """
+ Each repository_to_install_dict looks something like:
+ {'repository_id': '175812cd7caaf439',
+ 'url': '/api/repository_revisions/175812cd7caaf439',
+ 'malicious': False,
+ 'downloadable': True,
+ 'changeset_revision': '2388033730f3',
+ 'id': '175812cd7caaf439'}
+ """
+ repository_id = repository_to_install_dict.get( 'repository_id', None )
+ changeset_revision = repository_to_install_dict.get( 'changeset_revision', None )
+ metadata_revision_id = repository_to_install_dict[ 'id' ]
+ repository_to_install_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
+ repository_info = get_repository_info_from_api( galaxy_tool_shed_url, repository_to_install_dict )
# If a repository is deleted or malicious, we don't need to test it.
if repository_info[ 'deleted' ] or repository_info[ 'deprecated' ]:
+ log.info( "Skipping revision %s of repository id %s since it is either deleted or deprecated..." % ( str( changeset_revision ), str( repository_id ) ) )
continue
- repository_dict = dict( repository_info.items() + repository_dict.items() )
+ log.info( "Installing and testing revision %s of repository id %s..." % ( str( changeset_revision ), str( repository_id ) ) )
+ repository_dict = dict( repository_info.items() + repository_to_install_dict.items() )
+ """
+ Each repository_dict looks something like:
+ {'repository_id': '175812cd7caaf439',
+ 'url': '/api/repository_revisions/175812cd7caaf439',
+ 'malicious': False,
+ 'downloadable': True,
+ 'changeset_revision': '2388033730f3',
+ 'id': '175812cd7caaf439'}
+ """
# Generate the method that will install this repository into the running Galaxy instance.
test_install_repositories.generate_install_method( repository_dict )
os.environ[ 'GALAXY_INSTALL_TEST_HOST' ] = galaxy_test_host
@@ -410,8 +435,9 @@
# Run the configured tests.
result = run_tests( test_config )
success = result.wasSuccessful()
+ repository_dict[ 'test_environment' ] = get_test_environment()
repository_dict[ 'functional_tests_passed' ] = success
- repository_status = dict( environment=get_test_environment(), tests=[] )
+ test_errors = []
if success:
register_test_success( galaxy_tool_shed_url, metadata_revision_id )
log.debug( 'Repository %s installed and passed functional tests.' % repository_dict[ 'name' ] )
@@ -444,7 +470,10 @@
tmp_output[ appending_to ].append( line )
for output_type in tmp_output:
output[ output_type ] = '\n'.join( tmp_output[ output_type ] )
- repository_status[ 'tests' ].append( dict( test=label, output=output ) )
+ test_errors.append( dict( test=label, output=output ) )
+ if test_errors:
+ repository_status[ 'test_environment' ] = get_test_environment()
+ repository_status[ 'test_errors' ] = test_errors
register_test_failure( galaxy_tool_shed_url, metadata_revision_id, repository_status )
log.debug( 'Repository %s installed, but did not pass functional tests.' % repository_dict[ 'name' ] )
# Delete the completed tool functional tests from the test_toolbox.__dict__, otherwise nose will find them and try to re-run the
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Add blank lines to the tool_shed repository controller per new dev team coding standards.
by commits-noreply@bitbucket.org 28 Feb '13
by commits-noreply@bitbucket.org 28 Feb '13
28 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fb3a05f1f28e/
changeset: fb3a05f1f28e
user: greg
date: 2013-02-28 17:06:10
summary: Add blank lines to the tool_shed repository controller per new dev team coding standards.
affected #: 1 file
diff -r c494556d21a8c6bde808fccb8d584e8bb9f73662 -r fb3a05f1f28e0b0652065dc3c87155004e65f0b3 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
@@ -27,14 +27,21 @@
VALID_REPOSITORYNAME_RE = re.compile( "^[a-z0-9\_]+$" )
malicious_error = " This changeset cannot be downloaded because it potentially produces malicious behavior or contains inappropriate content."
malicious_error_can_push = " Correct this changeset as soon as possible, it potentially produces malicious behavior or contains inappropriate content."
-
+
+
class CategoryGrid( grids.Grid ):
+
+
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, category ):
return category.name
+
+
class DescriptionColumn( grids.TextColumn ):
def get_value( self, trans, grid, category ):
return category.description
+
+
class RepositoriesColumn( grids.TextColumn ):
def get_value( self, trans, grid, category ):
if category.repositories:
@@ -44,6 +51,7 @@
viewable_repositories += 1
return viewable_repositories
return 0
+
title = "Categories"
model_class = model.Category
template='/webapps/tool_shed/category/grid.mako'
@@ -69,7 +77,10 @@
preserve_state = False
use_paging = True
+
class ValidCategoryGrid( CategoryGrid ):
+
+
class RepositoriesColumn( grids.TextColumn ):
def get_value( self, trans, grid, category ):
if category.repositories:
@@ -80,6 +91,7 @@
viewable_repositories += 1
return viewable_repositories
return 0
+
title = "Categories of valid repositories"
model_class = model.Category
template='/webapps/tool_shed/category/valid_grid.mako'
@@ -106,13 +118,20 @@
preserve_state = False
use_paging = True
+
class RepositoryGrid( grids.Grid ):
+
+
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, repository ):
return escape_html( repository.name )
+
+
class MetadataRevisionColumn( grids.GridColumn ):
+
def __init__( self, col_name ):
grids.GridColumn.__init__( self, col_name )
+
def get_value( self, trans, grid, repository ):
"""Display a SelectField whose options are the changeset_revision strings of all metadata revisions of this repository."""
# A repository's metadata revisions may not all be installable, as some may contain only invalid tools.
@@ -122,16 +141,26 @@
elif len( select_field.options ) == 1:
return select_field.options[ 0 ][ 0 ]
return ''
+
+
class TipRevisionColumn( grids.GridColumn ):
+
def __init__( self, col_name ):
grids.GridColumn.__init__( self, col_name )
+
def get_value( self, trans, grid, repository ):
"""Display the repository tip revision label."""
return escape_html( repository.revision( trans.app ) )
+
+
class DescriptionColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
return escape_html( repository.description )
+
+
class CategoryColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
rval = '<ul>'
if repository.categories:
@@ -142,34 +171,49 @@
rval += '<li>not set</li>'
rval += '</ul>'
return rval
+
+
class RepositoryCategoryColumn( grids.GridColumn ):
+
def filter( self, trans, user, query, column_filter ):
"""Modify query to filter by category."""
if column_filter == "All":
return query
return query.filter( model.Category.name == column_filter )
+
+
class UserColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
if repository.user:
return escape_html( repository.user.username )
return 'no user'
+
+
class EmailColumn( grids.TextColumn ):
+
def filter( self, trans, user, query, column_filter ):
if column_filter == 'All':
return query
return query.filter( and_( model.Repository.table.c.user_id == model.User.table.c.id,
model.User.table.c.email == column_filter ) )
+
+
class EmailAlertsColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
if trans.user and repository.email_alerts and trans.user.email in json.from_json_string( repository.email_alerts ):
return 'yes'
return ''
+
+
class DeprecatedColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
if repository.deprecated:
return 'yes'
return ''
- # Grid definition
+
title = "Repositories"
model_class = model.Repository
template='/webapps/tool_shed/repository/grid.mako'
@@ -217,6 +261,7 @@
num_rows_per_page = 50
preserve_state = False
use_paging = True
+
def build_initial_query( self, trans, **kwd ):
return trans.sa_session.query( model.Repository ) \
.filter( and_( model.Repository.table.c.deleted == False,
@@ -225,6 +270,7 @@
.outerjoin( model.RepositoryCategoryAssociation.table ) \
.outerjoin( model.Category.table )
+
class RepositoriesByUserGrid( RepositoryGrid ):
title = "Repositories by user"
columns = [
@@ -248,6 +294,7 @@
num_rows_per_page = 50
preserve_state = False
use_paging = True
+
def build_initial_query( self, trans, **kwd ):
decoded_user_id = trans.security.decode_id( kwd[ 'user_id' ] )
return trans.sa_session.query( model.Repository ) \
@@ -258,6 +305,7 @@
.outerjoin( model.RepositoryCategoryAssociation.table ) \
.outerjoin( model.Category.table )
+
class RepositoriesIOwnGrid( RepositoryGrid ):
title = "Repositories I own"
columns = [
@@ -287,6 +335,7 @@
allow_multiple=False,
condition=( lambda item: not item.deleted and item.deprecated ),
async_compatible=False ) ]
+
def build_initial_query( self, trans, **kwd ):
return trans.sa_session.query( model.Repository ) \
.filter( and_( model.Repository.table.c.deleted == False,
@@ -295,6 +344,7 @@
.outerjoin( model.RepositoryCategoryAssociation.table ) \
.outerjoin( model.Category.table )
+
class DeprecatedRepositoriesIOwnGrid( RepositoriesIOwnGrid ):
title = "Deprecated repositories I own"
columns = [
@@ -314,6 +364,7 @@
key="free-text-search",
visible=False,
filterable="standard" ) )
+
def build_initial_query( self, trans, **kwd ):
return trans.sa_session.query( model.Repository ) \
.filter( and_( model.Repository.table.c.deleted == False,
@@ -323,6 +374,7 @@
.outerjoin( model.RepositoryCategoryAssociation.table ) \
.outerjoin( model.Category.table )
+
class EmailAlertsRepositoryGrid( RepositoryGrid ):
columns = [
RepositoryGrid.NameColumn( "Name",
@@ -352,6 +404,7 @@
grids.GridAction( "User preferences", dict( controller='user', action='index', cntrller='repository' ) )
]
+
class MyWritableRepositoriesGrid( RepositoryGrid ):
# This grid filters out repositories that have been marked as either deprecated or deleted.
columns = [
@@ -386,6 +439,7 @@
allow_multiple=False,
condition=( lambda item: not item.deleted ),
async_compatible=False ) ]
+
def build_initial_query( self, trans, **kwd ):
# TODO: improve performance by adding a db table associating users with repositories for which they have write access.
username = trans.user.username
@@ -408,8 +462,11 @@
return trans.sa_session.query( model.Repository ) \
.filter( model.Repository.table.c.id < 0 )
+
class ValidRepositoryGrid( RepositoryGrid ):
# This grid filters out repositories that have been marked as either deleted or deprecated.
+
+
class CategoryColumn( grids.TextColumn ):
def get_value( self, trans, grid, repository ):
rval = '<ul>'
@@ -421,15 +478,21 @@
rval += '<li>not set</li>'
rval += '</ul>'
return rval
+
+
class RepositoryCategoryColumn( grids.GridColumn ):
def filter( self, trans, user, query, column_filter ):
"""Modify query to filter by category."""
if column_filter == "All":
return query
return query.filter( model.Category.name == column_filter )
+
+
class RevisionColumn( grids.GridColumn ):
+
def __init__( self, col_name ):
grids.GridColumn.__init__( self, col_name )
+
def get_value( self, trans, grid, repository ):
"""Display a SelectField whose options are the changeset_revision strings of all download-able revisions of this repository."""
select_field = build_changeset_revision_select_field( trans, repository, downloadable=True )
@@ -462,6 +525,7 @@
visible=False,
filterable="standard" ) )
operations = []
+
def build_initial_query( self, trans, **kwd ):
if 'id' in kwd:
# The user is browsing categories of valid repositories, so filter the request by the received id, which is a category id.
@@ -484,22 +548,36 @@
.outerjoin( model.Category.table ) \
.filter( model.RepositoryMetadata.table.c.downloadable == True )
+
class MatchedRepositoryGrid( grids.Grid ):
# This grid filters out repositories that have been marked as deprecated.
+
+
class NameColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository_metadata ):
return repository_metadata.repository.name
+
+
class DescriptionColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository_metadata ):
return repository_metadata.repository.description
+
+
class RevisionColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository_metadata ):
return repository_metadata.changeset_revision
+
+
class UserColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository_metadata ):
if repository_metadata.repository.user:
return repository_metadata.repository.user.username
return 'no user'
+
# Grid definition
title = "Matching repositories"
model_class = model.RepositoryMetadata
@@ -524,6 +602,7 @@
num_rows_per_page = 50
preserve_state = False
use_paging = True
+
def build_initial_query( self, trans, **kwd ):
match_tuples = kwd.get( 'match_tuples', [] )
clause_list = []
@@ -545,6 +624,7 @@
return trans.sa_session.query( model.RepositoryMetadata ) \
.filter( model.RepositoryMetadata.id < 0 )
+
class InstallMatchedRepositoryGrid( MatchedRepositoryGrid ):
columns = [ col for col in MatchedRepositoryGrid.columns ]
# Override the NameColumn
@@ -552,6 +632,7 @@
link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
attach_popup=False )
+
class RepositoryController( BaseUIController, common_util.ItemRatings ):
install_matched_repository_grid = InstallMatchedRepositoryGrid()
@@ -594,6 +675,7 @@
action='browse_repositories',
**kwd ) )
return self.category_grid( trans, **kwd )
+
@web.expose
def browse_invalid_tools( self, trans, **kwd ):
params = util.Params( kwd )
@@ -634,6 +716,7 @@
invalid_tools_dict=invalid_tools_dict,
message=message,
status=status )
+
@web.expose
def browse_repositories( self, trans, **kwd ):
# We add params to the keyword dict in this method in order to rename the param with an "f-" prefix, simulating filtering by clicking a search
@@ -705,6 +788,7 @@
id=trans.security.encode_id( repository.id ),
changeset_revision=selected_changeset_revision ) )
return self.repository_grid( trans, **kwd )
+
@web.expose
def browse_repositories_by_user( self, trans, **kwd ):
"""Display the list of repositories owned by a specified user."""
@@ -735,6 +819,7 @@
user = suc.get_user( trans, kwd[ 'user_id' ] )
self.repositories_by_user_grid.title = "Repositories owned by %s" % user.username
return self.repositories_by_user_grid( trans, **kwd )
+
@web.expose
def browse_repository( self, trans, id, **kwd ):
params = util.Params( kwd )
@@ -754,6 +839,7 @@
is_malicious=is_malicious,
message=message,
status=status )
+
@web.expose
def browse_valid_categories( self, trans, **kwd ):
# The request came from Galaxy, so restrict category links to display only valid repository changeset revisions.
@@ -787,6 +873,7 @@
action='browse_valid_repositories',
**kwd ) )
return self.valid_category_grid( trans, **kwd )
+
@web.expose
def browse_valid_repositories( self, trans, **kwd ):
galaxy_url = kwd.get( 'galaxy_url', None )
@@ -832,6 +919,7 @@
allow_multiple=False,
async_compatible=False ) ]
return self.valid_repository_grid( trans, **kwd )
+
def __build_allow_push_select_field( self, trans, current_push_list, selected_value='none' ):
options = []
for user in trans.sa_session.query( trans.model.User ):
@@ -844,6 +932,7 @@
selected_value=selected_value,
refresh_on_change=False,
multiple=True )
+
def __change_repository_name_in_hgrc_file( self, hgrc_file, new_name ):
config = ConfigParser.ConfigParser()
config.read( hgrc_file )
@@ -852,6 +941,7 @@
new_file = open( hgrc_file, 'wb' )
config.write( new_file )
new_file.close()
+
@web.expose
def check_for_updates( self, trans, **kwd ):
"""Handle a request from a local Galaxy instance."""
@@ -929,6 +1019,7 @@
url += str( latest_changeset_revision )
url += '&latest_ctx_rev=%s' % str( update_to_ctx.rev() )
return trans.response.send_redirect( url )
+
@web.expose
def contact_owner( self, trans, id, **kwd ):
params = util.Params( kwd )
@@ -945,6 +1036,7 @@
else:
# Do all we can to eliminate spam.
return trans.show_error_message( "You must be logged in to contact the owner of a repository." )
+
def __create_hgrc_file( self, trans, repository ):
# At this point, an entry for the repository is required to be in the hgweb.config file so we can call repository.repo_path( trans.app ).
# Since we support both http and https, we set push_ssl to False to override the default (which is True) in the mercurial api. The hg
@@ -962,6 +1054,7 @@
fp.write( '[extensions]\n' )
fp.write( 'hgext.purge=' )
fp.close()
+
@web.expose
def create_repository( self, trans, **kwd ):
params = util.Params( kwd )
@@ -1040,6 +1133,7 @@
categories=categories,
message=message,
status=status )
+
@web.expose
@web.require_login( "deprecate repository" )
def deprecate( self, trans, **kwd ):
@@ -1061,6 +1155,7 @@
operation='repositories_i_own',
message=message,
status=status ) )
+
@web.expose
def display_tool( self, trans, repository_id, tool_config, changeset_revision, **kwd ):
params = util.Params( kwd )
@@ -1098,6 +1193,7 @@
changeset_revision=changeset_revision,
message=message,
status='error' ) )
+
@web.expose
def download( self, trans, repository_id, changeset_revision, file_type, **kwd ):
# Download an archive of the repository files compressed as zip, gz or bz2.
@@ -1118,6 +1214,7 @@
trans.sa_session.flush()
download_url = '/repos/%s/%s/archive/%s' % ( repository.user.username, repository.name, file_type_str )
return trans.response.send_redirect( download_url )
+
@web.expose
def find_tools( self, trans, **kwd ):
params = util.Params( kwd )
@@ -1204,6 +1301,7 @@
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
+
@web.expose
def find_workflows( self, trans, **kwd ):
params = util.Params( kwd )
@@ -1291,10 +1389,12 @@
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
+
@web.expose
def generate_workflow_image( self, trans, workflow_name, repository_metadata_id=None ):
"""Return an svg image representation of a workflow dictionary created when the workflow was exported."""
return workflow_util.generate_workflow_image( trans, workflow_name, repository_metadata_id=repository_metadata_id, repository_id=None )
+
@web.expose
def get_changeset_revision_and_ctx_rev( self, trans, **kwd ):
"""Handle a request from a local Galaxy instance to retrieve the changeset revision hash to which an installed repository can be updated."""
@@ -1392,6 +1492,7 @@
update_dict[ 'changeset_revision' ] = str( latest_changeset_revision )
update_dict[ 'ctx_rev' ] = str( update_to_ctx.rev() )
return encoding_util.tool_shed_encode( update_dict )
+
@web.expose
def get_ctx_rev( self, trans, **kwd ):
"""Given a repository and changeset_revision, return the correct ctx.rev() value."""
@@ -1405,12 +1506,14 @@
if ctx:
return str( ctx.rev() )
return ''
+
@web.json
def get_file_contents( self, trans, file_path ):
# Avoid caching
trans.response.headers['Pragma'] = 'no-cache'
trans.response.headers['Expires'] = '0'
return suc.get_repository_file_contents( file_path )
+
def get_file_from_changeset_revision( self, repo_files_dir, changeset_revision, file_name, dir ):
"""Return file_name from the received changeset_revision of the repository manifest."""
stripped_file_name = suc.strip_path( file_name )
@@ -1418,11 +1521,13 @@
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
named_tmp_file = suc.get_named_tmpfile_from_ctx( ctx, file_name, dir )
return named_tmp_file
+
def get_metadata( self, trans, repository_id, changeset_revision ):
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata and repository_metadata.metadata:
return repository_metadata.metadata
return None
+
@web.json
def get_readme_files( self, trans, **kwd ):
"""
@@ -1435,6 +1540,7 @@
repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision )
return suc.build_readme_files_dict( repository_metadata.metadata )
+
@web.json
def get_repository_dependencies( self, trans, **kwd ):
"""Return an encoded dictionary of all repositories upon which the contents of the received repository depends."""
@@ -1459,6 +1565,7 @@
if repository_dependencies:
return encoding_util.tool_shed_encode( repository_dependencies )
return ''
+
def __get_repository_from_refresh_on_change( self, trans, **kwd ):
# The changeset_revision_select_field in several grids performs a refresh_on_change which sends in request parameters like
# changeset_revison_1, changeset_revision_2, etc. One of the many select fields on the grid performed the refresh_on_change,
@@ -1474,6 +1581,7 @@
return v, repository
# This should never be reached - raise an exception?
return v, None
+
@web.json
def get_repository_information( self, trans, repository_ids, changeset_revisions, **kwd ):
"""
@@ -1517,6 +1625,7 @@
has_repository_dependencies=has_repository_dependencies,
includes_tool_dependencies=includes_tool_dependencies,
repo_info_dicts=repo_info_dicts )
+
@web.json
def get_required_repo_info_dict( self, trans, encoded_str ):
"""
@@ -1540,6 +1649,7 @@
else:
repo_info_dict = {}
return repo_info_dict
+
@web.expose
def get_tool_dependencies( self, trans, **kwd ):
"""Handle a request from a Galaxy instance to get the tool_dependencies entry from the metadata for a specified changeset revision."""
@@ -1556,6 +1666,7 @@
if tool_dependencies:
return encoding_util.tool_shed_encode( tool_dependencies )
return ''
+
@web.expose
def get_tool_dependencies_config_contents( self, trans, **kwd ):
"""Handle a request from a Galaxy instance to get the tool_dependencies.xml file contents for a specified changeset revision."""
@@ -1576,6 +1687,7 @@
tool_dependencies_config_file.close()
return contents
return ''
+
@web.expose
def get_tool_versions( self, trans, **kwd ):
"""
@@ -1599,6 +1711,7 @@
if tool_version_dicts:
return json.to_json_string( tool_version_dicts )
return ''
+
@web.json
def get_updated_repository_information( self, trans, name, owner, changeset_revision, **kwd ):
"""Generate a dictionary that contains the information about a repository that is necessary for installing it into a local Galaxy instance."""
@@ -1655,6 +1768,7 @@
includes_workflows=includes_workflows,
readme_files_dict=readme_files_dict,
repo_info_dict=repo_info_dict )
+
def get_versions_of_tool( self, trans, repository, repository_metadata, guid ):
"""Return the tool lineage in descendant order for the received guid contained in the received repsitory_metadata.tool_versions."""
encoded_id = trans.security.encode_id( repository.id )
@@ -1685,12 +1799,14 @@
current_parent_guid = child_guid
break
return tool_guid_lineage
+
@web.expose
def help( self, trans, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
return trans.fill_template( '/webapps/tool_shed/repository/help.mako', message=message, status=status, **kwd )
+
def __in_tool_dict( self, tool_dict, exact_matches_checked, tool_id=None, tool_name=None, tool_version=None ):
found = False
if tool_id and not tool_name and not tool_version:
@@ -1732,10 +1848,12 @@
tool_dict_tool_name.find( tool_name ) >= 0 and \
tool_dict_tool_id.find( tool_id ) >= 0 )
return found
+
def __in_workflow_dict( self, workflow_dict, exact_matches_checked, workflow_name ):
workflow_dict_workflow_name = workflow_dict[ 'name' ].lower()
return ( workflow_name == workflow_dict_workflow_name ) or \
( not exact_matches_checked and workflow_dict_workflow_name.find( workflow_name ) >= 0 )
+
@web.expose
def index( self, trans, **kwd ):
params = util.Params( kwd )
@@ -1771,6 +1889,7 @@
changeset_revision=changeset_revision,
message=message,
status=status )
+
@web.expose
def install_repositories_by_revision( self, trans, **kwd ):
"""
@@ -1793,6 +1912,7 @@
'admin_toolshed/prepare_for_install?tool_shed_url=%s&repository_ids=%s&changeset_revisions=%s' % \
( web.url_for( '/', qualified=True ), ','.join( util.listify( repository_ids ) ), ','.join( util.listify( changeset_revisions ) ) ) )
return trans.response.send_redirect( url )
+
@web.expose
def load_invalid_tool( self, trans, repository_id, tool_config, changeset_revision, **kwd ):
params = util.Params( kwd )
@@ -1837,6 +1957,7 @@
changeset_revision=changeset_revision,
message=message,
status='error' ) )
+
def __make_same_length( self, list1, list2 ):
# If either list is 1 item, we'll append to it until its length is the same as the other.
if len( list1 ) == 1:
@@ -1846,6 +1967,7 @@
for i in range( 1, len( list1 ) ):
list2.append( list2[ 0 ] )
return list1, list2
+
@web.expose
@web.require_login( "manage email alerts" )
def manage_email_alerts( self, trans, **kwd ):
@@ -1877,6 +1999,7 @@
email_alert_repositories=email_alert_repositories,
message=message,
status=status )
+
@web.expose
@web.require_login( "manage repository" )
def manage_repository( self, trans, id, **kwd ):
@@ -2083,12 +2206,14 @@
can_browse_repository_reviews=can_browse_repository_reviews,
message=message,
status=status )
+
@web.expose
@web.require_login( "review repository revision" )
def manage_repository_reviews_of_revision( self, trans, **kwd ):
return trans.response.send_redirect( web.url_for( controller='repository_review',
action='manage_repository_reviews_of_revision',
**kwd ) )
+
@web.expose
@web.require_login( "multi select email alerts" )
def multi_select_email_alerts( self, trans, **kwd ):
@@ -2110,6 +2235,7 @@
del kwd[ 'operation' ]
self.email_alerts_repository_grid.title = "Set email alerts for repository changes"
return self.email_alerts_repository_grid( trans, **kwd )
+
def __new_state( self, trans, all_pages=False ):
"""
Create a new `DefaultToolState` for this tool. It will not be initialized
@@ -2121,12 +2247,14 @@
state = galaxy.tools.DefaultToolState()
state.inputs = {}
return state
+
@web.json
def open_folder( self, trans, folder_path ):
# Avoid caching
trans.response.headers['Pragma'] = 'no-cache'
trans.response.headers['Expires'] = '0'
return suc.open_repository_files_folder( trans, folder_path )
+
@web.expose
def preview_tools_in_changeset( self, trans, repository_id, **kwd ):
params = util.Params( kwd )
@@ -2173,6 +2301,7 @@
metadata=metadata,
message=message,
status=status )
+
@web.expose
def previous_changeset_revisions( self, trans, **kwd ):
"""
@@ -2201,6 +2330,7 @@
changeset_hashes_str = ','.join( changeset_hashes )
return changeset_hashes_str
return ''
+
@web.expose
@web.require_login( "rate repositories" )
def rate_repository( self, trans, **kwd ):
@@ -2240,6 +2370,7 @@
is_malicious=is_malicious,
message=message,
status=status )
+
@web.expose
def reset_all_metadata( self, trans, id, **kwd ):
# This method is called only from the ~/templates/webapps/tool_shed/repository/manage_repository.mako template.
@@ -2257,24 +2388,28 @@
id=id,
message=message,
status=status ) )
+
def __search_ids_names( self, tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_names ):
for i, tool_id in enumerate( tool_ids ):
tool_name = tool_names[ i ]
if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_id=tool_id, tool_name=tool_name ):
match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
return match_tuples
+
def __search_ids_versions( self, tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_versions ):
for i, tool_id in enumerate( tool_ids ):
tool_version = tool_versions[ i ]
if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_id=tool_id, tool_version=tool_version ):
match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
return match_tuples
+
def __search_names_versions( self, tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_names, tool_versions ):
for i, tool_name in enumerate( tool_names ):
tool_version = tool_versions[ i ]
if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_name=tool_name, tool_version=tool_version ):
match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
return match_tuples
+
def __search_repository_metadata( self, trans, exact_matches_checked, tool_ids='', tool_names='', tool_versions='', workflow_names='', all_workflows=False ):
match_tuples = []
ok = True
@@ -2346,6 +2481,7 @@
elif all_workflows and 'workflows' in metadata:
match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
return ok, match_tuples
+
@web.expose
def select_files_to_delete( self, trans, id, **kwd ):
params = util.Params( kwd )
@@ -2412,6 +2548,7 @@
is_malicious=is_malicious,
message=message,
status=status )
+
@web.expose
def send_to_owner( self, trans, id, message='' ):
repository = suc.get_repository_in_tool_shed( trans, id )
@@ -2450,6 +2587,7 @@
id=id,
message=message,
status=status ) )
+
@web.expose
@web.require_login( "set email alerts" )
def set_email_alerts( self, trans, **kwd ):
@@ -2490,6 +2628,7 @@
return trans.response.send_redirect( web.url_for( controller='repository',
action=caller,
**kwd ) )
+
@web.expose
@web.require_login( "set repository as malicious" )
def set_malicious( self, trans, id, ctx_str, **kwd ):
@@ -2512,6 +2651,7 @@
malicious=malicious,
message=message,
status=status ) )
+
@web.expose
def sharable_owner( self, trans, owner ):
"""Support for sharable URL for each repository owner's tools, e.g. http://example.org/view/owner."""
@@ -2527,6 +2667,7 @@
else:
return trans.show_error_message( "The tool shed <b>%s</b> contains no repositories owned by <b>%s</b>." % \
( web.url_for( '/', qualified=True ).rstrip( '/' ), str( owner ) ) )
+
@web.expose
def sharable_repository( self, trans, owner, name ):
"""Support for sharable URL for a specified repository, e.g. http://example.org/view/owner/name."""
@@ -2556,6 +2697,7 @@
else:
return trans.show_error_message( "The tool shed <b>%s</b> contains no repositories named <b>%s</b> with owner <b>%s</b>." % \
( web.url_for( '/', qualified=True ).rstrip( '/' ), str( name ), str( owner ) ) )
+
@web.expose
def sharable_repository_revision( self, trans, owner, name, changeset_revision ):
"""Support for sharable URL for a specified repository revision, e.g. http://example.org/view/owner/name/changeset_revision."""
@@ -2592,10 +2734,12 @@
return trans.response.send_redirect( web.url_for( controller='repository',
action='sharable_owner',
owner=owner ) )
+
def __stringify( self, list ):
if list:
return ','.join( list )
return ''
+
@web.expose
def updated_changeset_revisions( self, trans, **kwd ):
"""
@@ -2625,6 +2769,7 @@
changeset_hashes_str = ','.join( changeset_hashes )
return changeset_hashes_str
return ''
+
def __validate_repository_name( self, name, user ):
# Repository names must be unique for each user, must be at least four characters
# in length and must contain only lower-case letters, numbers, and the '_' character.
@@ -2642,6 +2787,7 @@
if not( VALID_REPOSITORYNAME_RE.match( name ) ):
return "Repository names must contain only lower-case letters, numbers and underscore <b>_</b>."
return ''
+
@web.expose
def view_changelog( self, trans, id, **kwd ):
params = util.Params( kwd )
@@ -2679,6 +2825,7 @@
is_malicious=is_malicious,
message=message,
status=status )
+
@web.expose
def view_changeset( self, trans, id, ctx_str, **kwd ):
params = util.Params( kwd )
@@ -2719,6 +2866,7 @@
is_malicious=is_malicious,
message=message,
status=status )
+
@web.expose
def view_or_manage_repository( self, trans, **kwd ):
repository = suc.get_repository_in_tool_shed( trans, kwd[ 'id' ] )
@@ -2730,6 +2878,7 @@
return trans.response.send_redirect( web.url_for( controller='repository',
action='view_repository',
**kwd ) )
+
@web.expose
def view_repository( self, trans, id, **kwd ):
params = util.Params( kwd )
@@ -2829,6 +2978,7 @@
can_browse_repository_reviews=can_browse_repository_reviews,
message=message,
status=status )
+
@web.expose
def view_tool_metadata( self, trans, repository_id, changeset_revision, tool_id, **kwd ):
params = util.Params( kwd )
@@ -2907,6 +3057,7 @@
review_id=review_id,
message=message,
status=status )
+
@web.expose
def view_workflow( self, trans, workflow_name, repository_metadata_id, **kwd ):
"""Retrieve necessary information about a workflow from the database so that it can be displayed in an svg image."""
@@ -2927,6 +3078,7 @@
metadata=metadata,
message=message,
status=status )
+
# ----- Utility methods -----
def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/36028c9bc709/
changeset: 36028c9bc709
user: inithello
date: 2013-02-28 16:33:22
summary: Added filter for malicious to repository_revisions API controller.
affected #: 1 file
diff -r f4273b52a432089be730b8fb62d6fd63f89249f1 -r 36028c9bc7096507f3b30f9e3b7789a566f288f5 lib/galaxy/webapps/tool_shed/api/repository_revisions.py
--- a/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
+++ b/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
@@ -35,6 +35,10 @@
downloadable = kwd.get( 'downloadable', None )
if downloadable is not None:
clause_list.append( trans.model.RepositoryMetadata.table.c.downloadable == util.string_as_bool( downloadable ) )
+ # Filter by malicious if received.
+ malicious = kwd.get( 'malicious', None )
+ if malicious is not None:
+ clause_list.append( trans.model.RepositoryMetadata.table.c.malicious == util.string_as_bool( malicious ) )
# Filter by tools_functionally_correct if received.
tools_functionally_correct = kwd.get( 'tools_functionally_correct', None )
if tools_functionally_correct is not None:
https://bitbucket.org/galaxy/galaxy-central/commits/c494556d21a8/
changeset: c494556d21a8
user: inithello
date: 2013-02-28 16:33:59
summary: Add malicious and deleted filters to repository listing.
affected #: 1 file
diff -r 36028c9bc7096507f3b30f9e3b7789a566f288f5 -r c494556d21a8c6bde808fccb8d584e8bb9f73662 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -151,7 +151,7 @@
listing = file( location, 'r' ).read()
elif source == 'url':
assert tool_shed_api_key is not None, 'Cannot proceed without tool shed API key.'
- params = urllib.urlencode( dict( deprecated='false', deleted='false', downloadable='true', tools_functionally_correct='false', do_not_test='false' ) )
+ params = urllib.urlencode( dict( tools_functionally_correct='false', do_not_test='false', downloadable='true', malicious='false' ) )
api_url = get_api_url( base=location, parts=[ 'repository_revisions' ], params=params )
if format == 'json':
return json_from_url( api_url )
@@ -370,6 +370,9 @@
metadata_revision_id = repository_dict[ 'id' ]
repository_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
repository_info = get_repository_info_from_api( galaxy_tool_shed_url, repository_dict )
+ # If a repository is deleted or malicious, we don't need to test it.
+ if repository_info[ 'deleted' ] or repository_info[ 'deprecated' ]:
+ continue
repository_dict = dict( repository_info.items() + repository_dict.items() )
# Generate the method that will install this repository into the running Galaxy instance.
test_install_repositories.generate_install_method( repository_dict )
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: inithello: Added test environment to tool functional test error reporting, made api url generation more robust.
by commits-noreply@bitbucket.org 28 Feb '13
by commits-noreply@bitbucket.org 28 Feb '13
28 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f4273b52a432/
changeset: f4273b52a432
user: inithello
date: 2013-02-28 16:03:35
summary: Added test environment to tool functional test error reporting, made api url generation more robust.
affected #: 1 file
diff -r 4d559a181a5721e5a183ede3fdd59b3e89b8d9f2 -r f4273b52a432089be730b8fb62d6fd63f89249f1 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -4,7 +4,7 @@
# order to run functional tests on repository tools after installation. The install_and_test_tool_shed_repositories.sh
# will execute this script with the appropriate parameters.
-import os, sys, shutil, tempfile, re, string, urllib
+import os, sys, shutil, tempfile, re, string, urllib, platform
# Assume we are run from the galaxy root directory, add lib to the python path
cwd = os.getcwd()
@@ -50,6 +50,8 @@
from galaxy.util import parse_xml
from galaxy.util.json import from_json_string, to_json_string
+from tool_shed.util.shed_util_common import url_join
+
import nose.core
import nose.config
import nose.loader
@@ -115,7 +117,7 @@
parts.insert( 0, 'api' )
elif 'api' not in parts:
parts.insert( 0, 'api' )
- url = '%s/%s' % ( base, '/'.join( parts ) )
+ url = url_join( base, *parts )
if key:
url += '?%s' % urllib.urlencode( dict( key=key ) )
else:
@@ -149,7 +151,7 @@
listing = file( location, 'r' ).read()
elif source == 'url':
assert tool_shed_api_key is not None, 'Cannot proceed without tool shed API key.'
- params = urllib.urlencode( dict( downloadable='true' ) )
+ params = urllib.urlencode( dict( deprecated='false', deleted='false', downloadable='true', tools_functionally_correct='false', do_not_test='false' ) )
api_url = get_api_url( base=location, parts=[ 'repository_revisions' ], params=params )
if format == 'json':
return json_from_url( api_url )
@@ -160,6 +162,14 @@
else:
raise AssertonError( 'Unknown format %s.' % format )
+def get_test_environment():
+ rval = {}
+ rval[ 'python_version' ] = platform.python_version()
+ rval[ 'architecture' ] = platform.machine()
+ os, hostname, os_version, uname, arch, processor = platform.uname()
+ rval[ 'system' ] = '%s %s' % ( os, os_version )
+ return rval
+
def json_from_url( url ):
url_handle = urllib.urlopen( url )
url_contents = url_handle.read()
@@ -167,11 +177,11 @@
def register_test_failure( url, metadata_id, test_errors ):
params = dict( tools_functionally_correct='false', do_not_test='true', tool_test_errors=test_errors )
- return update( tool_shed_api_key, '%s/api/%s' % ( galaxy_tool_shed_url, '/'.join( [ 'repository_revisions', metadata_id ] ) ), params )
+ return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params )
def register_test_success( url, metadata_id ):
params = dict( tools_functionally_correct='true', do_not_test='false' )
- return update( tool_shed_api_key, '%s/api/%s' % ( galaxy_tool_shed_url, '/'.join( [ 'repository_revisions', metadata_id ] ) ), params )
+ return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params )
def run_tests( test_config ):
loader = nose.loader.TestLoader( config=test_config )
@@ -348,12 +358,13 @@
import install_and_test_tool_shed_repositories.functional.test_install_repositories as test_install_repositories
import functional.test_toolbox as test_toolbox
if galaxy_test_proxy_port:
- log.info( "Tests will be run against %s:%s" % ( galaxy_test_host, galaxy_test_proxy_port ) )
+ log.info( "The embedded Galaxy application is running on %s:%s" % ( galaxy_test_host, galaxy_test_proxy_port ) )
else:
- log.info( "Tests will be run against %s:%s" % ( galaxy_test_host, galaxy_test_port ) )
+ log.info( "The embedded Galaxy application is running on %s:%s" % ( galaxy_test_host, galaxy_test_port ) )
+ log.info( "Repositories will be installed from the tool shed at %s" % galaxy_tool_shed_url )
success = False
try:
- repository_status = []
+ repository_status = {}
# Iterate through a list of repository info dicts.
for repository_dict in get_repositories_to_install( galaxy_tool_shed_url, source='url' ):
metadata_revision_id = repository_dict[ 'id' ]
@@ -397,12 +408,12 @@
result = run_tests( test_config )
success = result.wasSuccessful()
repository_dict[ 'functional_tests_passed' ] = success
+ repository_status = dict( environment=get_test_environment(), tests=[] )
if success:
register_test_success( galaxy_tool_shed_url, metadata_revision_id )
log.debug( 'Repository %s installed and passed functional tests.' % repository_dict[ 'name' ] )
else:
# If the functional tests fail, log the output and submit it to the tool shed whence the repository was installed.
- repository_dict[ 'tool_test_errors' ] = []
for failure in result.failures:
label = str( failure[0] )
log_output = failure[1].replace( '\\n', '\n' )
@@ -430,10 +441,9 @@
tmp_output[ appending_to ].append( line )
for output_type in tmp_output:
output[ output_type ] = '\n'.join( tmp_output[ output_type ] )
- repository_dict[ 'tool_test_errors' ].append( dict( test=label, output=output ) )
- register_test_failure( galaxy_tool_shed_url, metadata_revision_id, repository_dict[ 'tool_test_errors' ] )
+ repository_status[ 'tests' ].append( dict( test=label, output=output ) )
+ register_test_failure( galaxy_tool_shed_url, metadata_revision_id, repository_status )
log.debug( 'Repository %s installed, but did not pass functional tests.' % repository_dict[ 'name' ] )
- repository_status.append( repository_dict )
# Delete the completed tool functional tests from the test_toolbox.__dict__, otherwise nose will find them and try to re-run the
# tests after uninstalling the repository.
tests_to_delete = []
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: carlfeberhard: browser tests: fix to error reporting for saved output dir creation
by commits-noreply@bitbucket.org 27 Feb '13
by commits-noreply@bitbucket.org 27 Feb '13
27 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4d559a181a57/
changeset: 4d559a181a57
user: carlfeberhard
date: 2013-02-27 22:52:43
summary: browser tests: fix to error reporting for saved output dir creation
affected #: 1 file
diff -r 65ca85b0d55c57ce44f5b3f12bbf0008ac26e745 -r 4d559a181a5721e5a183ede3fdd59b3e89b8d9f2 test/casperjs/server_env.py
--- a/test/casperjs/server_env.py
+++ b/test/casperjs/server_env.py
@@ -21,7 +21,7 @@
ENV_HISTORY_ID = 'GALAXY_TEST_HISTORY_ID'
ENV_FILE_DIR = 'GALAXY_TEST_FILE_DIR'
ENV_TOOL_SHED_TEST_FILE = 'GALAXY_TOOL_SHED_TEST_FILE'
- ENV_SAVED_FILES_DIR = 'GALAXY_TEST_SAVE'
+ ENV_SAVED_FILES_DIR = 'GALAXY_TEST_SAVE' # AKA: twilltestcase.keepOutdir
DEFAULT_PROTOCOL = 'http'
DEFAULT_HOST = 'localhost'
@@ -54,7 +54,8 @@
'tool_shed_test_file', self.ENV_TOOL_SHED_TEST_FILE, default=None )
self.shed_tools_dict = self._get_shed_tools_dict()
- self.keepOutdir = self._get_setting_from_config_or_env( 'keepOutdir', self.ENV_SAVED_FILES_DIR, default=None )
+ self.keepOutdir = self._get_setting_from_config_or_env(
+ 'saved_output_dir', self.ENV_SAVED_FILES_DIR, default=None )
self._init_saved_files_dir()
def _get_setting_from_config_or_env( self, config_name, env_name, default=False ):
@@ -81,13 +82,15 @@
return {}
def _init_saved_files_dir( self ):
- """Set up the desired directory to save test output
+ """Set up the desired directory to save test output.
"""
- if self.keepOutdir > '':
+ if self.saved_output_dir > '':
try:
- os.makedirs( self.keepOutdir )
- except:
- log.debug( 'unable to create saved files directory: %s' %( self.keepOutDir ) )
+ os.makedirs( self.saved_output_dir )
+ except Exception, exc:
+ log.error( 'unable to create saved files directory "%s": %s',
+ self.saved_output_dir, exc, exc_info=True )
+ self.saved_output_dir = None
@property
def url( self ):
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: inithello: Removed stray reference to webapps.community.
by commits-noreply@bitbucket.org 27 Feb '13
by commits-noreply@bitbucket.org 27 Feb '13
27 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/65ca85b0d55c/
changeset: 65ca85b0d55c
user: inithello
date: 2013-02-27 22:33:06
summary: Removed stray reference to webapps.community.
affected #: 1 file
diff -r dfe68d0a008c7a0cc629a72da488b68b6588f03b -r 65ca85b0d55c57ce44f5b3f12bbf0008ac26e745 lib/galaxy/tags/tag_handler.py
--- a/lib/galaxy/tags/tag_handler.py
+++ b/lib/galaxy/tags/tag_handler.py
@@ -273,5 +273,5 @@
class CommunityTagHandler( TagHandler ):
def __init__( self ):
- from galaxy.webapps.community import model
+ from galaxy.webapps.tool_shed import model
TagHandler.__init__( self )
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: inithello: Added tool_sheds_conf.xml.sample to buildbot_setup.sh.
by commits-noreply@bitbucket.org 27 Feb '13
by commits-noreply@bitbucket.org 27 Feb '13
27 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/81527d3d8962/
changeset: 81527d3d8962
user: inithello
date: 2013-02-27 21:45:43
summary: Added tool_sheds_conf.xml.sample to buildbot_setup.sh.
affected #: 1 file
diff -r 22aaf90bc420bb93862c08c8f24549e76d701b7d -r 81527d3d8962f3d5f5804fa1457f4e7a782c7136 buildbot_setup.sh
--- a/buildbot_setup.sh
+++ b/buildbot_setup.sh
@@ -68,6 +68,7 @@
datatypes_conf.xml.sample
universe_wsgi.ini.sample
tool_data_table_conf.xml.sample
+tool_sheds_conf.xml.sample
shed_tool_data_table_conf.xml.sample
migrated_tools_conf.xml.sample
data_manager_conf.xml.sample
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
5 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f46c9a707af8/
changeset: f46c9a707af8
user: jmchilton
date: 2013-02-23 21:09:53
summary: Implement macro mechanism for tool config XML. This should allow for a drastic reduction in 'code' duplication across XML files in a tool repository or inside of an XML file (repeated blocks in different when statements for instance).
affected #: 1 file
diff -r fa34924860aaa282fe3c3021a257f2523848a6e6 -r f46c9a707af8ae9256b762cf7ef26c38da69c3a2 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -17,6 +17,7 @@
from galaxy.util.template import fill_template
from galaxy import util, jobs, model
from galaxy.jobs import ParallelismInfo
+from copy import deepcopy
from elementtree import ElementTree
from parameters import *
from parameters.grouping import *
@@ -520,7 +521,7 @@
def load_tool( self, config_file, guid=None, **kwds ):
"""Load a single tool from the file named by `config_file` and return an instance of `Tool`."""
# Parse XML configuration file and get the root element
- tree = util.parse_xml( config_file )
+ tree = self._load_and_preprocess_tool_xml( config_file )
root = tree.getroot()
# Allow specifying a different tool subclass to instantiate
if root.find( "type" ) is not None:
@@ -704,7 +705,86 @@
rval = tools
return rval
-
+
+ def _load_and_preprocess_tool_xml(self, config_file):
+ tree = util.parse_xml(config_file)
+ root = tree.getroot()
+ macros_el = root.find('macros')
+ if not macros_el:
+ return tree
+ tool_dir = os.path.dirname(config_file)
+ macros = self._load_macros(macros_el, tool_dir)
+ # HACK for elementtree, newer implementations (etree/lxml) won't
+ # require this parent_map data structure but elementtree does not
+ # track parents or recongnize .find('..').
+ parent_map = dict((c, p) for p in tree.getiterator() for c in p)
+ for expand_el in root.findall('.//expand'):
+ macro_name = expand_el.get('macro')
+ macro_def = macros[macro_name]
+ self._xml_replace(expand_el, macro_def, parent_map)
+ return tree
+
+ def _load_macros(self, macros_el, tool_dir):
+ macros = {}
+ # Import macros from external files.
+ macros.update(self._load_imported_macros(macros_el, tool_dir))
+ # Load all directly defined macros.
+ macros.update(self._load_embedded_macros(macros_el, tool_dir))
+ return macros
+
+ def _load_embedded_macros(self, macros_el, tool_dir):
+ macros = {}
+
+ macro_els = []
+ if macros_el:
+ macro_els = macros_el.findall("macro")
+ for macro in macro_els:
+ macro_name = macro.get("name")
+ macros[macro_name] = self._load_macro_def(macro)
+
+ return macros
+
+ def _load_imported_macros(self, macros_el, tool_dir):
+ macros = {}
+
+ macro_import_els = []
+ if macros_el:
+ macro_import_els = macros_el.findall("import")
+ for macro_import_el in macro_import_els:
+ raw_import_path = macro_import_el.text
+ tool_relative_import_path = \
+ os.path.basename(raw_import_path) # Sanitize this
+ import_path = \
+ os.path.join(tool_dir, tool_relative_import_path)
+ file_macros = self._load_macro_file(import_path, tool_dir)
+ macros.update(file_macros)
+
+ return macros
+
+ def _load_macro_file(self, path, tool_dir):
+ tree = util.parse_xml(path)
+ root = tree.getroot()
+ return self._load_macros(root, tool_dir)
+
+ def _load_macro_def(self, macro):
+ return list(macro.getchildren())
+
+ def _xml_replace(self, query, targets, parent_map):
+ #parent_el = query.find('..') ## Something like this would be better with newer xml library
+ parent_el = parent_map[query]
+ matching_index = -1
+ #for index, el in enumerate(parent_el.iter('.')): ## Something like this for newer implementation
+ for index, el in enumerate(parent_el.getchildren()):
+ if el == query:
+ matching_index = index
+ break
+ assert matching_index >= 0
+ current_index = matching_index
+ for target in targets:
+ current_index += 1
+ parent_el.insert(current_index, deepcopy(target))
+ parent_el.remove(query)
+
class ToolSection( object ):
"""
A group of tools with similar type/purpose that will be displayed as a
https://bitbucket.org/galaxy/galaxy-central/commits/7ae831ebb4aa/
changeset: 7ae831ebb4aa
user: jmchilton
date: 2013-02-23 21:09:53
summary: Extend tool config macro engine so that macros may be rendered inside other macros.
affected #: 1 file
diff -r f46c9a707af8ae9256b762cf7ef26c38da69c3a2 -r 7ae831ebb4aad4989cbf6ecba0e8128413a28403 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -714,16 +714,24 @@
return tree
tool_dir = os.path.dirname(config_file)
macros = self._load_macros(macros_el, tool_dir)
- # HACK for elementtree, newer implementations (etree/lxml) won't
- # require this parent_map data structure but elementtree does not
- # track parents or recongnize .find('..').
- parent_map = dict((c, p) for p in tree.getiterator() for c in p)
- for expand_el in root.findall('.//expand'):
- macro_name = expand_el.get('macro')
- macro_def = macros[macro_name]
- self._xml_replace(expand_el, macro_def, parent_map)
+
+ self._expand_macros([root], macros)
return tree
+ def _expand_macros(self, elements, macros):
+ for element in elements:
+ # HACK for elementtree, newer implementations (etree/lxml) won't
+ # require this parent_map data structure but elementtree does not
+ # track parents or recongnize .find('..').
+ parent_map = dict((c, p) for p in element.getiterator() for c in p)
+ for expand_el in element.findall('.//expand'):
+ macro_name = expand_el.get('macro')
+ macro_def = macros[macro_name]
+
+ # Recursively expand contained macros.
+ self._expand_macros(macro_def, macros)
+ self._xml_replace(expand_el, macro_def, parent_map)
+
def _load_macros(self, macros_el, tool_dir):
macros = {}
# Import macros from external files.
@@ -785,6 +793,7 @@
parent_el.insert(current_index, deepcopy(target))
parent_el.remove(query)
+
class ToolSection( object ):
"""
A group of tools with similar type/purpose that will be displayed as a
https://bitbucket.org/galaxy/galaxy-central/commits/0d78c9da2cc8/
changeset: 0d78c9da2cc8
user: jmchilton
date: 2013-02-23 21:09:53
summary: Add ability to pass sub-blocks of XML to macros and corresponding ability to render those (via the new <yield /> tag) from macros.
affected #: 1 file
diff -r 7ae831ebb4aad4989cbf6ecba0e8128413a28403 -r 0d78c9da2cc82c25f919f1850be39774b46fbb57 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -726,7 +726,16 @@
parent_map = dict((c, p) for p in element.getiterator() for c in p)
for expand_el in element.findall('.//expand'):
macro_name = expand_el.get('macro')
- macro_def = macros[macro_name]
+ macro_def = deepcopy(macros[macro_name]) # deepcopy needed?
+
+ yield_els = [yield_el for macro_def_el in macro_def for yield_el in macro_def_el.findall('.//yield')]
+
+ expand_el_children = expand_el.getchildren()
+ macro_def_parent_map = \
+ dict((c, p) for macro_def_el in macro_def for p in macro_def_el.getiterator() for c in p)
+
+ for yield_el in yield_els:
+ self._xml_replace(yield_el, expand_el_children, macro_def_parent_map)
# Recursively expand contained macros.
self._expand_macros(macro_def, macros)
https://bitbucket.org/galaxy/galaxy-central/commits/f522eea2d4c1/
changeset: f522eea2d4c1
user: jmchilton
date: 2013-02-23 21:09:53
summary: Rework some duplication out tophat wrappers using macros. This dmeonstrates how macros can reduce duplication inside a file (e.g. the dbKeyActions macro) and between files (e.g. the own_junctionsConditional macro).
affected #: 4 files
diff -r 0d78c9da2cc82c25f919f1850be39774b46fbb57 -r f522eea2d4c19d7c7c24209afc1a4dee5bd71aa3 tools/ngs_rna/tophat2_wrapper.xml
--- a/tools/ngs_rna/tophat2_wrapper.xml
+++ b/tools/ngs_rna/tophat2_wrapper.xml
@@ -143,23 +143,12 @@
</param></when></conditional>
- <conditional name="refGenomeSource">
- <param name="genomeSource" type="select" label="Use a built in reference genome or own from your history" help="Built-in genomes were created using default options">
- <option value="indexed" selected="True">Use a built-in genome</option>
- <option value="history">Use a genome from history</option>
- </param>
- <when value="indexed">
- <param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team">
- <options from_data_table="tophat2_indexes">
- <filter type="sort_by" column="2"/>
- <validator type="no_options" message="No genomes are available for the selected input dataset"/>
- </options>
- </param>
- </when>
- <when value="history">
- <param name="ownFile" type="data" format="fasta" metadata_name="dbkey" label="Select the reference genome" />
- </when><!-- history -->
- </conditional><!-- refGenomeSource -->
+ <expand macro="refGenomeSourceConditional">
+ <options from_data_table="tophat2_indexes">
+ <filter type="sort_by" column="2"/>
+ <validator type="no_options" message="No genomes are available for the selected input dataset"/>
+ </options>
+ </expand><conditional name="params"><param name="settingsType" type="select" label="TopHat settings to use" help="You can use the default settings or set custom values for any of Tophat's parameters."><option value="preSet">Use Defaults</option>
@@ -182,17 +171,7 @@
<param name="splice_mismatches" type="integer" value="0" label="Maximum number of mismatches that can appear in the anchor region of spliced alignment" /><param name="min_intron_length" type="integer" value="70" label="The minimum intron length" help="TopHat will ignore donor/acceptor pairs closer than this many bases apart." /><param name="max_intron_length" type="integer" value="500000" label="The maximum intron length" help="When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read." />
- <conditional name="indel_search">
- <param name="allow_indel_search" type="select" label="Allow indel search">
- <option value="Yes">Yes</option>
- <option value="No">No</option>
- </param>
- <when value="No"/>
- <when value="Yes">
- <param name="max_insertion_length" type="integer" value="3" label="Max insertion length." help="The maximum insertion length." />
- <param name="max_deletion_length" type="integer" value="3" label="Max deletion length." help="The maximum deletion length." />
- </when>
- </conditional>
+ <expand macro="indel_searchConditional" />
alignments (number of reads divided by average depth of coverage)" help="0.0 to 1.0 (0 to turn off)" /><param name="max_multihits" type="integer" value="20" label="Maximum number of alignments to be allowed" /><param name="min_segment_intron" type="integer" value="50" label="Minimum intron length that may be found during split-segment (default) search" />
@@ -201,40 +180,7 @@
<param name="seg_length" type="integer" value="25" label="Minimum length of read segments" /><!-- Options for supplying own junctions. -->
- <conditional name="own_junctions">
- <param name="use_junctions" type="select" label="Use Own Junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="Yes">
- <conditional name="gene_model_ann">
- <param name="use_annotations" type="select" label="Use Gene Annotation Model">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="No" />
- <when value="Yes">
- <param format="gtf,gff3" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/>
- </when>
- </conditional>
- <conditional name="raw_juncs">
- <param name="use_juncs" type="select" label="Use Raw Junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="No" />
- <when value="Yes">
- <param format="interval" name="raw_juncs" type="data" label="Raw Junctions" help="Supply TopHat with a list of raw junctions. Junctions are specified one per line, in a tab-delimited format. Records look like: [chrom] [left] [right] [+/-] left and right are zero-based coordinates, and specify the last character of the left sequenced to be spliced to the first character of the right sequence, inclusive."/>
- </when>
- </conditional>
- <param name="no_novel_juncs" type="select" label="Only look for supplied junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- </when>
- <when value="No" />
- </conditional><!-- /own_junctions -->
-
+ <expand macro="own_junctionsConditional" /><!-- Coverage search. --><conditional name="coverage_search"><param name="use_search" type="select" label="Use Coverage Search" help="Enables the coverage based search for junctions. Use when coverage search is disabled by default (such as for reads 75bp or longer), for maximum sensitivity.">
@@ -319,83 +265,40 @@
<filter>(params['settingsType'] == 'full' and params['fusion_search']['do_search'] == 'Yes')</filter></data><data format="bed" name="insertions" label="${tool.name} on ${on_string}: insertions" from_work_dir="tophat_out/insertions.bed">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat2_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data><data format="bed" name="deletions" label="${tool.name} on ${on_string}: deletions" from_work_dir="tophat_out/deletions.bed">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat2_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data><data format="bed" name="junctions" label="${tool.name} on ${on_string}: splice junctions" from_work_dir="tophat_out/junctions.bed">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat2_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data><data format="bam" name="accepted_hits" label="${tool.name} on ${on_string}: accepted_hits" from_work_dir="tophat_out/accepted_hits.bam">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat2_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data></outputs>
-
+ <macros>
+ <import>tophat_macros.xml</import>
+ <macro name="dbKeyActions">
+ <actions>
+ <conditional name="refGenomeSource.genomeSource">
+ <when value="indexed">
+ <action type="metadata" name="dbkey">
+ <option type="from_data_table" name="tophat2_indexes" column="1" offset="0">
+ <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
+ <filter type="param_value" ref="refGenomeSource.index" column="0"/>
+ </option>
+ </action>
+ </when>
+ <when value="history">
+ <action type="metadata" name="dbkey">
+ <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
+ </action>
+ </when>
+ </conditional>
+ </actions>
+ </macro>
+ </macros><tests><!-- Test base-space single-end reads with pre-built index and preset parameters --><test>
diff -r 0d78c9da2cc82c25f919f1850be39774b46fbb57 -r f522eea2d4c19d7c7c24209afc1a4dee5bd71aa3 tools/ngs_rna/tophat_color_wrapper.xml
--- a/tools/ngs_rna/tophat_color_wrapper.xml
+++ b/tools/ngs_rna/tophat_color_wrapper.xml
@@ -154,23 +154,12 @@
</command><inputs><param format="fastqcssanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Color-space: Must have Sanger-scaled quality values with ASCII offset 33" />
- <conditional name="refGenomeSource">
- <param name="genomeSource" type="select" label="Will you select a reference genome from your history or use a built-in index?" help="Built-ins were indexed using default options">
- <option value="indexed">Use a built-in index</option>
- <option value="history">Use one from the history</option>
- </param>
- <when value="indexed">
- <param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team">
- <options from_data_table="tophat_indexes_color">
- <filter type="sort_by" column="2"/>
- <validator type="no_options" message="No indexes are available for the selected input dataset"/>
- </options>
- </param>
- </when>
- <when value="history">
- <param name="ownFile" type="data" format="fasta" metadata_name="dbkey" label="Select the reference genome" />
- </when><!-- history -->
- </conditional><!-- refGenomeSource -->
+ <expand macro="refGenomeSourceConditional">
+ <options from_data_table="tophat_indexes_color">
+ <filter type="sort_by" column="2"/>
+ <validator type="no_options" message="No indexes are available for the selected input dataset"/>
+ </options>
+ </expand><conditional name="singlePaired"><param name="sPaired" type="select" label="Is this library mate-paired?"><option value="single">Single-end</option>
@@ -194,17 +183,7 @@
<param name="splice_mismatches" type="integer" value="0" label="Maximum number of mismatches that can appear in the anchor region of spliced alignment" /><param name="min_intron_length" type="integer" value="70" label="The minimum intron length" help="TopHat will ignore donor/acceptor pairs closer than this many bases apart." /><param name="max_intron_length" type="integer" value="500000" label="The maximum intron length" help="When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read." />
- <conditional name="indel_search">
- <param name="allow_indel_search" type="select" label="Allow indel search">
- <option value="Yes">Yes</option>
- <option value="No">No</option>
- </param>
- <when value="No"/>
- <when value="Yes">
- <param name="max_insertion_length" type="integer" value="3" label="Max insertion length." help="The maximum insertion length." />
- <param name="max_deletion_length" type="integer" value="3" label="Max deletion length." help="The maximum deletion length." />
- </when>
- </conditional>
+ <expand macro="indel_searchConditional" /><param name="junction_filter" type="float" value="0.15" label="Minimum isoform fraction: filter out junctions supported by too few alignments (number of reads divided by average depth of coverage)" help="0.0 to 1.0 (0 to turn off)" /><param name="max_multihits" type="integer" value="40" label="Maximum number of alignments to be allowed" /><param name="min_segment_intron" type="integer" value="50" label="Minimum intron length that may be found during split-segment (default) search" />
@@ -230,20 +209,8 @@
<param format="gtf" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/></when></conditional>
- <conditional name="raw_juncs">
- <param name="use_juncs" type="select" label="Use Raw Junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="No" />
- <when value="Yes">
- <param format="interval" name="raw_juncs" type="data" label="Raw Junctions" help="Supply TopHat with a list of raw junctions. Junctions are specified one per line, in a tab-delimited format. Records look like: [chrom] [left] [right] [+/-] left and right are zero-based coordinates, and specify the last character of the left sequenced to be spliced to the first character of the right sequence, inclusive."/>
- </when>
- </conditional>
- <param name="no_novel_juncs" type="select" label="Only look for supplied junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
+ <expand macro="raw_juncsConditional" />
+ <expand macro="no_novel_juncsParam" /></when><when value="No" /></conditional><!-- /own_junctions -->
@@ -301,17 +268,7 @@
<param name="splice_mismatches" type="integer" value="0" label="Maximum number of mismatches that can appear in the anchor region of spliced alignment" /><param name="min_intron_length" type="integer" value="70" label="The minimum intron length" help="TopHat will ignore donor/acceptor pairs closer than this many bases apart." /><param name="max_intron_length" type="integer" value="500000" label="The maximum intron length" help="When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read." />
- <conditional name="indel_search">
- <param name="allow_indel_search" type="select" label="Allow indel search">
- <option value="Yes">Yes</option>
- <option value="No">No</option>
- </param>
- <when value="No"/>
- <when value="Yes">
- <param name="max_insertion_length" type="integer" value="3" label="Max insertion length." help="The maximum insertion length." />
- <param name="max_deletion_length" type="integer" value="3" label="Max deletion length." help="The maximum deletion length." />
- </when>
- </conditional>
+ <expand macro="indel_searchConditional" /><param name="junction_filter" type="float" value="0.15" label="Minimum isoform fraction: filter out junctions supported by too few alignments (number of reads divided by average depth of coverage)" help="0.0 to 1.0 (0 to turn off)" /><param name="max_multihits" type="integer" value="40" label="Maximum number of alignments to be allowed" /><param name="min_segment_intron" type="integer" value="50" label="Minimum intron length that may be found during split-segment (default) search" />
@@ -399,90 +356,50 @@
( singlePaired['pParams']['indel_search']['allow_indel_search'] == 'Yes' ) )
)
</filter>
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes_color" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data><data format="bed" name="deletions" label="${tool.name} on ${on_string}: deletions" from_work_dir="tophat_out/deletions.bed">
- <filter>
+ <expand macro="dbKeyActions" />
+ </data>
+ <data format="bed" name="junctions" label="${tool.name} on ${on_string}: splice junctions">
+ <expand macro="dbKeyActions" />
+ </data>
+ <data format="bam" name="accepted_hits" label="${tool.name} on ${on_string}: accepted_hits">
+ <expand macro="dbKeyActions" />
+ </data>
+ </outputs>
+ <macros>
+ <import>tophat_macros.xml</import>
+ <macro name="bedFilter">
+ <filter>
(
( ( 'sParams' in singlePaired ) and ( 'indel_search' in singlePaired['sParams'] ) and
( singlePaired['sParams']['indel_search']['allow_indel_search'] == 'Yes' ) ) or
( ( 'pParams' in singlePaired ) and ( 'indel_search' in singlePaired['pParams'] ) and
( singlePaired['pParams']['indel_search']['allow_indel_search'] == 'Yes' ) )
)
- </filter>
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes_color" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
- </data>
- <data format="bed" name="junctions" label="${tool.name} on ${on_string}: splice junctions">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes_color" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
- </data>
- <data format="bam" name="accepted_hits" label="${tool.name} on ${on_string}: accepted_hits">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes_color" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
- </data>
- </outputs>
+ </filter>
+ </macro>
+ <macro name="dbKeyActions">
+ <actions>
+ <conditional name="refGenomeSource.genomeSource">
+ <when value="indexed">
+ <action type="metadata" name="dbkey">
+ <option type="from_data_table" name="tophat_indexes_color" column="1" offset="0">
+ <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
+ <filter type="param_value" ref="refGenomeSource.index" column="0"/>
+ </option>
+ </action>
+ </when>
+ <when value="history">
+ <action type="metadata" name="dbkey">
+ <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
+ </action>
+ </when>
+ </conditional>
+ </actions>
+ </macro>
+ </macros><tests><!-- Test color-space single-end reads with user-supplied reference fasta and preset parameters --><test>
diff -r 0d78c9da2cc82c25f919f1850be39774b46fbb57 -r f522eea2d4c19d7c7c24209afc1a4dee5bd71aa3 tools/ngs_rna/tophat_macros.xml
--- /dev/null
+++ b/tools/ngs_rna/tophat_macros.xml
@@ -0,0 +1,72 @@
+<macros>
+ <macro name="refGenomeSourceConditional">
+ <conditional name="refGenomeSource">
+ <param name="genomeSource" type="select" label="Use a built in reference genome or own from your history" help="Built-ins genomes were created using default options">
+ <option value="indexed" selected="True">Use a built-in genome</option>
+ <option value="history">Use a genome from history</option>
+ </param>
+ <when value="indexed">
+ <param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team">
+ <yield />
+ </param>
+ </when>
+ <when value="history">
+ <param name="ownFile" type="data" format="fasta" metadata_name="dbkey" label="Select the reference genome" />
+ </when><!-- history -->
+ </conditional><!-- refGenomeSource -->
+ </macro>
+ <macro name="indel_searchConditional">
+ <conditional name="indel_search">
+ <param name="allow_indel_search" type="select" label="Allow indel search">
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </param>
+ <when value="No"/>
+ <when value="Yes">
+ <param name="max_insertion_length" type="integer" value="3" label="Max insertion length." help="The maximum insertion length." />
+ <param name="max_deletion_length" type="integer" value="3" label="Max deletion length." help="The maximum deletion length." />
+ </when>
+ </conditional>
+ </macro>
+ <macro name="own_junctionsConditional">
+ <conditional name="own_junctions">
+ <param name="use_junctions" type="select" label="Use Own Junctions">
+ <option value="No">No</option>
+ <option value="Yes">Yes</option>
+ </param>
+ <when value="Yes">
+ <conditional name="gene_model_ann">
+ <param name="use_annotations" type="select" label="Use Gene Annotation Model">
+ <option value="No">No</option>
+ <option value="Yes">Yes</option>
+ </param>
+ <when value="No" />
+ <when value="Yes">
+ <param format="gtf,gff3" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/>
+ </when>
+ </conditional>
+ <expand macro="raw_juncsConditional" />
+ <expand macro="no_novel_juncsParam" />
+ </when>
+ <when value="No" />
+ </conditional><!-- /own_junctions -->
+ </macro>
+ <macro name="raw_juncsConditional">
+ <conditional name="raw_juncs">
+ <param name="use_juncs" type="select" label="Use Raw Junctions">
+ <option value="No">No</option>
+ <option value="Yes">Yes</option>
+ </param>
+ <when value="No" />
+ <when value="Yes">
+ <param format="interval" name="raw_juncs" type="data" label="Raw Junctions" help="Supply TopHat with a list of raw junctions. Junctions are specified one per line, in a tab-delimited format. Records look like: [chrom] [left] [right] [+/-] left and right are zero-based coordinates, and specify the last character of the left sequenced to be spliced to the first character of the right sequence, inclusive."/>
+ </when>
+ </conditional>
+ </macro>
+ <macro name="no_novel_juncsParam">
+ <param name="no_novel_juncs" type="select" label="Only look for supplied junctions">
+ <option value="No">No</option>
+ <option value="Yes">Yes</option>
+ </param>
+ </macro>
+</macros>
diff -r 0d78c9da2cc82c25f919f1850be39774b46fbb57 -r f522eea2d4c19d7c7c24209afc1a4dee5bd71aa3 tools/ngs_rna/tophat_wrapper.xml
--- a/tools/ngs_rna/tophat_wrapper.xml
+++ b/tools/ngs_rna/tophat_wrapper.xml
@@ -151,23 +151,12 @@
</command><inputs><param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Nucleotide-space: Must have Sanger-scaled quality values with ASCII offset 33" />
- <conditional name="refGenomeSource">
- <param name="genomeSource" type="select" label="Use a built in reference genome or own from your history" help="Built-ins genomes were created using default options">
- <option value="indexed" selected="True">Use a built-in genome</option>
- <option value="history">Use a genome from history</option>
- </param>
- <when value="indexed">
- <param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team">
- <options from_data_table="tophat_indexes">
- <filter type="sort_by" column="2"/>
- <validator type="no_options" message="No genomes are available for the selected input dataset"/>
- </options>
- </param>
- </when>
- <when value="history">
- <param name="ownFile" type="data" format="fasta" metadata_name="dbkey" label="Select the reference genome" />
- </when><!-- history -->
- </conditional><!-- refGenomeSource -->
+ <expand macro="refGenomeSourceConditional">
+ <options from_data_table="tophat_indexes">
+ <filter type="sort_by" column="2"/>
+ <validator type="no_options" message="No genomes are available for the selected input dataset"/>
+ </options>
+ </expand><conditional name="singlePaired"><param name="sPaired" type="select" label="Is this library mate-paired?"><option value="single">Single-end</option>
@@ -298,17 +287,7 @@
<param name="splice_mismatches" type="integer" value="0" label="Maximum number of mismatches that can appear in the anchor region of spliced alignment" /><param name="min_intron_length" type="integer" value="70" label="The minimum intron length" help="TopHat will ignore donor/acceptor pairs closer than this many bases apart." /><param name="max_intron_length" type="integer" value="500000" label="The maximum intron length" help="When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read." />
- <conditional name="indel_search">
- <param name="allow_indel_search" type="select" label="Allow indel search">
- <option value="Yes">Yes</option>
- <option value="No">No</option>
- </param>
- <when value="No"/>
- <when value="Yes">
- <param name="max_insertion_length" type="integer" value="3" label="Max insertion length." help="The maximum insertion length." />
- <param name="max_deletion_length" type="integer" value="3" label="Max deletion length." help="The maximum deletion length." />
- </when>
- </conditional>
+ <expand macro="indel_searchConditional" /><param name="max_multihits" type="integer" value="20" label="Maximum number of alignments to be allowed" /><param name="min_segment_intron" type="integer" value="50" label="Minimum intron length that may be found during split-segment (default) search" /><param name="max_segment_intron" type="integer" value="500000" label="Maximum intron length that may be found during split-segment (default) search" />
@@ -316,40 +295,7 @@
<param name="seg_mismatches" type="integer" min="0" max="3" value="2" label="Number of mismatches allowed in each segment alignment for reads mapped independently" /><param name="seg_length" type="integer" value="25" label="Minimum length of read segments" /><!-- Options for supplying own junctions. -->
- <conditional name="own_junctions">
- <param name="use_junctions" type="select" label="Use Own Junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="Yes">
- <conditional name="gene_model_ann">
- <param name="use_annotations" type="select" label="Use Gene Annotation Model">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="No" />
- <when value="Yes">
- <param format="gtf" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/>
- </when>
- </conditional>
- <conditional name="raw_juncs">
- <param name="use_juncs" type="select" label="Use Raw Junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="No" />
- <when value="Yes">
- <param format="interval" name="raw_juncs" type="data" label="Raw Junctions" help="Supply TopHat with a list of raw junctions. Junctions are specified one per line, in a tab-delimited format. Records look like: [chrom] [left] [right] [+/-] left and right are zero-based coordinates, and specify the last character of the left sequenced to be spliced to the first character of the right sequence, inclusive."/>
- </when>
- </conditional>
- <param name="no_novel_juncs" type="select" label="Only look for supplied junctions">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- </when>
- <when value="No" />
- </conditional><!-- /own_junctions -->
-
+ <expand macro="own_junctionsConditional" /><!-- Closure search. --><conditional name="closure_search"><param name="use_search" type="select" label="Use Closure Search">
@@ -387,83 +333,40 @@
<outputs><data format="bed" name="insertions" label="${tool.name} on ${on_string}: insertions" from_work_dir="tophat_out/insertions.bed">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data><data format="bed" name="deletions" label="${tool.name} on ${on_string}: deletions" from_work_dir="tophat_out/deletions.bed">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data><data format="bed" name="junctions" label="${tool.name} on ${on_string}: splice junctions" from_work_dir="tophat_out/junctions.bed">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data><data format="bam" name="accepted_hits" label="${tool.name} on ${on_string}: accepted_hits" from_work_dir="tophat_out/accepted_hits.bam">
- <actions>
- <conditional name="refGenomeSource.genomeSource">
- <when value="indexed">
- <action type="metadata" name="dbkey">
- <option type="from_data_table" name="tophat_indexes" column="1" offset="0">
- <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
- <filter type="param_value" ref="refGenomeSource.index" column="0"/>
- </option>
- </action>
- </when>
- <when value="history">
- <action type="metadata" name="dbkey">
- <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
- </action>
- </when>
- </conditional>
- </actions>
+ <expand macro="dbKeyActions" /></data></outputs>
-
+ <macros>
+ <import>tophat_macros.xml</import>
+ <macro name="dbKeyActions">
+ <actions>
+ <conditional name="refGenomeSource.genomeSource">
+ <when value="indexed">
+ <action type="metadata" name="dbkey">
+ <option type="from_data_table" name="tophat_indexes" column="1" offset="0">
+ <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
+ <filter type="param_value" ref="refGenomeSource.index" column="0"/>
+ </option>
+ </action>
+ </when>
+ <when value="history">
+ <action type="metadata" name="dbkey">
+ <option type="from_param" name="refGenomeSource.ownFile" param_attribute="dbkey" />
+ </action>
+ </when>
+ </conditional>
+ </actions>
+ </macro>
+ </macros><tests><!-- Test base-space single-end reads with pre-built index and preset parameters --><test>
https://bitbucket.org/galaxy/galaxy-central/commits/22aaf90bc420/
changeset: 22aaf90bc420
user: jgoecks
date: 2013-02-27 21:21:30
summary: Merged in jmchilton/galaxy-central-multi-input-tool-fixes-2 (pull request #129)
Implement Macro Engine to Reduce Tool Config XML Duplication
affected #: 5 files
Diff not available.
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: inithello: Enhance twill automated repository installation framework to get a list of repositories from the tool shed API, install, run functional tests defined in the tools' XML, and report success or failure back to the tool shed.
by commits-noreply@bitbucket.org 27 Feb '13
by commits-noreply@bitbucket.org 27 Feb '13
27 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9d87d7c61912/
changeset: 9d87d7c61912
user: inithello
date: 2013-02-27 20:28:12
summary: Enhance twill automated repository installation framework to get a list of repositories from the tool shed API, install, run functional tests defined in the tools' XML, and report success or failure back to the tool shed.
affected #: 3 files
diff -r fabb0ae1edabf77f9aceb018fa5a988ce05500f9 -r 9d87d7c6191284aaf48ade4462256131c0345c8d test/install_and_test_tool_shed_repositories/base/twilltestcase.py
--- a/test/install_and_test_tool_shed_repositories/base/twilltestcase.py
+++ b/test/install_and_test_tool_shed_repositories/base/twilltestcase.py
@@ -55,7 +55,7 @@
name = repository_info_dict[ 'name' ]
owner = repository_info_dict[ 'owner' ]
changeset_revision = repository_info_dict[ 'changeset_revision' ]
- encoded_repository_id = repository_info_dict[ 'encoded_repository_id' ]
+ encoded_repository_id = repository_info_dict[ 'repository_id' ]
tool_shed_url = repository_info_dict[ 'tool_shed_url' ]
preview_params = urllib.urlencode( dict( repository_id=encoded_repository_id, changeset_revision=changeset_revision ) )
self.visit_url( '%s/repository/preview_tools_in_changeset?%s' % ( tool_shed_url, preview_params ) )
diff -r fabb0ae1edabf77f9aceb018fa5a988ce05500f9 -r 9d87d7c6191284aaf48ade4462256131c0345c8d test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py
--- a/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py
+++ b/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py
@@ -3,7 +3,7 @@
from install_and_test_tool_shed_repositories.base.twilltestcase import InstallTestRepository
log = logging.getLogger(__name__)
-class TestInstallRepositories( InstallTestRepository ):
+class InstallTestRepositories( InstallTestRepository ):
"""Abstract test case that installs and uninstalls a predefined list of repositories."""
def do_installation( self, repository_info_dict ):
self.logout()
@@ -35,11 +35,11 @@
G = globals()
# Eliminate all previous tests from G.
for key, val in G.items():
- if key.startswith( 'TestInstallRepository_' ) or key.startswith( 'TestUninstallRepository_' ):
+ if key.startswith( 'TestInstallRepository_' ) or key.startswith( 'TestUninstallRepository_' ) or key.startswith( 'TestForTool_' ):
del G[ key ]
# Create a new subclass with a method named install_repository_XXX that installs the repository specified by the provided dict.
name = "TestInstallRepository_" + repository_dict[ 'name' ]
- baseclasses = ( TestInstallRepositories, )
+ baseclasses = ( InstallTestRepositories, )
namespace = dict()
def make_install_method( repository_dict ):
def test_install_repository( self ):
@@ -61,11 +61,11 @@
G = globals()
# Eliminate all previous tests from G.
for key, val in G.items():
- if key.startswith( 'TestInstallRepository_' ) or key.startswith( 'TestUninstallRepository_' ):
+ if key.startswith( 'TestInstallRepository_' ) or key.startswith( 'TestUninstallRepository_' ) or key.startswith( 'TestForTool_' ):
del G[ key ]
# Create a new subclass with a method named install_repository_XXX that installs the repository specified by the provided dict.
name = "TestUninstallRepository_" + repository_dict[ 'name' ]
- baseclasses = ( TestInstallRepositories, )
+ baseclasses = ( InstallTestRepositories, )
namespace = dict()
def make_uninstall_method( repository_dict ):
def test_install_repository( self ):
diff -r fabb0ae1edabf77f9aceb018fa5a988ce05500f9 -r 9d87d7c6191284aaf48ade4462256131c0345c8d test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -4,7 +4,7 @@
# order to run functional tests on repository tools after installation. The install_and_test_tool_shed_repositories.sh
# will execute this script with the appropriate parameters.
-import os, sys, shutil, tempfile, re, string
+import os, sys, shutil, tempfile, re, string, urllib
# Assume we are run from the galaxy root directory, add lib to the python path
cwd = os.getcwd()
@@ -19,7 +19,7 @@
default_galaxy_locales = 'en'
default_galaxy_test_file_dir = "test-data"
os.environ[ 'GALAXY_INSTALL_TEST_TMP_DIR' ] = galaxy_test_tmp_dir
-new_path = [ os.path.join( cwd, "lib" ), os.path.join( cwd, 'test' ) ]
+new_path = [ os.path.join( cwd, "lib" ), os.path.join( cwd, 'test' ), os.path.join( cwd, 'scripts', 'api' ) ]
new_path.extend( sys.path )
sys.path = new_path
@@ -48,6 +48,7 @@
from galaxy.app import UniverseApplication
from galaxy.web import buildapp
from galaxy.util import parse_xml
+from galaxy.util.json import from_json_string, to_json_string
import nose.core
import nose.config
@@ -56,6 +57,8 @@
from base.util import parse_tool_panel_config
+from common import update
+
log = logging.getLogger( 'install_and_test_repositories' )
default_galaxy_test_port_min = 10000
@@ -95,7 +98,10 @@
'''
# Define a default location to find the list of repositories to check.
-galaxy_repository_list = os.environ.get( 'GALAXY_INSTALL_TEST_REPOSITORY_FILE', 'repository_list.json' )
+galaxy_repository_list = os.environ.get( 'GALAXY_INSTALL_TEST_REPOSITORY_LIST_LOCATIOM', 'repository_list.json' )
+galaxy_tool_shed_url = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_SHED_URL', 'http://toolshed.local:10001' )
+tool_shed_api_key = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_SHED_API_KEY', None )
+assert tool_shed_api_key is not None, 'Unable to proceed without API key.'
if 'GALAXY_INSTALL_TEST_SECRET' not in os.environ:
galaxy_encode_secret = 'changethisinproductiontoo'
@@ -103,7 +109,28 @@
else:
galaxy_encode_secret = os.environ[ 'GALAXY_INSTALL_TEST_SECRET' ]
-def get_repositories_to_install( format='json' ):
+def get_api_url( base, parts=[], params=None, key=None ):
+ if 'api' in parts and parts.index( 'api' ) != 0:
+ parts.pop( parts.index( 'api' ) )
+ parts.insert( 0, 'api' )
+ elif 'api' not in parts:
+ parts.insert( 0, 'api' )
+ url = '%s/%s' % ( base, '/'.join( parts ) )
+ if key:
+ url += '?%s' % urllib.urlencode( dict( key=key ) )
+ else:
+ url += '?%s' % urllib.urlencode( dict( key=tool_shed_api_key ) )
+ if params:
+ url += '&%s' % params
+ return url
+
+def get_repository_info_from_api( url, repository_info_dict ):
+ parts = [ 'api', 'repositories', repository_info_dict[ 'repository_id' ] ]
+ api_url = get_api_url( base=url, parts=parts )
+ extended_dict = json_from_url( api_url )
+ return extended_dict
+
+def get_repositories_to_install( location, source='file', format='json' ):
'''
Get a list of repository info dicts to install. This method expects a json list of dicts with the following structure:
[
@@ -118,11 +145,34 @@
]
NOTE: If the tool shed URL specified in any dict is not present in the tool_sheds_conf.xml, the installation will fail.
'''
+ if source == 'file':
+ listing = file( location, 'r' ).read()
+ elif source == 'url':
+ assert tool_shed_api_key is not None, 'Cannot proceed without tool shed API key.'
+ params = urllib.urlencode( dict( downloadable='true' ) )
+ api_url = get_api_url( base=location, parts=[ 'repository_revisions' ], params=params )
+ if format == 'json':
+ return json_from_url( api_url )
+ else:
+ raise AssertionError( 'Do not know how to handle source type %s.' % source )
if format == 'json':
- return simplejson.loads( file( galaxy_repository_list, 'r' ).read() )
+ return from_json_string( listing )
else:
raise AssertonError( 'Unknown format %s.' % format )
+def json_from_url( url ):
+ url_handle = urllib.urlopen( url )
+ url_contents = url_handle.read()
+ return from_json_string( url_contents )
+
+def register_test_failure( url, metadata_id, test_errors ):
+ params = dict( tools_functionally_correct='false', do_not_test='true', tool_test_errors=test_errors )
+ return update( tool_shed_api_key, '%s/api/%s' % ( galaxy_tool_shed_url, '/'.join( [ 'repository_revisions', metadata_id ] ) ), params )
+
+def register_test_success( url, metadata_id ):
+ params = dict( tools_functionally_correct='true', do_not_test='false' )
+ return update( tool_shed_api_key, '%s/api/%s' % ( galaxy_tool_shed_url, '/'.join( [ 'repository_revisions', metadata_id ] ) ), params )
+
def run_tests( test_config ):
loader = nose.loader.TestLoader( config=test_config )
plug_loader = test_config.plugins.prepareTestLoader( loader )
@@ -162,6 +212,7 @@
galaxy_migrated_tool_conf_file = os.environ.get( 'GALAXY_INSTALL_TEST_MIGRATED_TOOL_CONF', os.path.join( galaxy_test_tmp_dir, 'test_migrated_tool_conf.xml' ) )
galaxy_tool_sheds_conf_file = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_SHEDS_CONF', os.path.join( galaxy_test_tmp_dir, 'test_tool_sheds_conf.xml' ) )
galaxy_shed_tools_dict = os.environ.get( 'GALAXY_INSTALL_TEST_SHED_TOOL_DICT_FILE', os.path.join( galaxy_test_tmp_dir, 'shed_tool_dict' ) )
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( dict() ) )
if 'GALAXY_INSTALL_TEST_TOOL_DATA_PATH' in os.environ:
tool_data_path = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_DATA_PATH' )
else:
@@ -302,8 +353,13 @@
log.info( "Tests will be run against %s:%s" % ( galaxy_test_host, galaxy_test_port ) )
success = False
try:
+ repository_status = []
# Iterate through a list of repository info dicts.
- for repository_dict in get_repositories_to_install():
+ for repository_dict in get_repositories_to_install( galaxy_tool_shed_url, source='url' ):
+ metadata_revision_id = repository_dict[ 'id' ]
+ repository_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
+ repository_info = get_repository_info_from_api( galaxy_tool_shed_url, repository_dict )
+ repository_dict = dict( repository_info.items() + repository_dict.items() )
# Generate the method that will install this repository into the running Galaxy instance.
test_install_repositories.generate_install_method( repository_dict )
os.environ[ 'GALAXY_INSTALL_TEST_HOST' ] = galaxy_test_host
@@ -319,9 +375,12 @@
if success:
log.debug( 'Installation of %s succeeded, running any defined functional tests.' % repository_dict[ 'name' ] )
# Parse the tool panel config to get the test-data path for this repository.
- shed_tools_dict = parse_tool_panel_config( galaxy_shed_tool_conf_file, {} )
+ if not os.path.exists( galaxy_shed_tools_dict ):
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( dict() ) )
+ shed_tools_dict = parse_tool_panel_config( galaxy_shed_tool_conf_file, from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
+ log.debug( shed_tools_dict )
# Write this to a file, so the functional test framework can find it.
- file( galaxy_shed_tools_dict, 'w' ).write( simplejson.dumps( shed_tools_dict ) )
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
# Set up the environment so that test.functional.test_toolbox can find the Galaxy server we configured in this framework.
os.environ[ 'GALAXY_TOOL_SHED_TEST_FILE' ] = galaxy_shed_tools_dict
os.environ[ 'GALAXY_TEST_HOST' ] = galaxy_test_host
@@ -337,10 +396,52 @@
# Run the configured tests.
result = run_tests( test_config )
success = result.wasSuccessful()
+ repository_dict[ 'functional_tests_passed' ] = success
if success:
+ register_test_success( galaxy_tool_shed_url, metadata_revision_id )
log.debug( 'Repository %s installed and passed functional tests.' % repository_dict[ 'name' ] )
else:
+ # If the functional tests fail, log the output and submit it to the tool shed whence the repository was installed.
+ repository_dict[ 'tool_test_errors' ] = []
+ for failure in result.failures:
+ label = str( failure[0] )
+ log_output = failure[1].replace( '\\n', '\n' )
+ log_output = re.sub( r'control \d+:.+', r'', log_output )
+ log_output = re.sub( r'\n+', r'\n', log_output )
+ appending_to = 'output'
+ tmp_output = {}
+ output = {}
+ for line in log_output.split( '\n' ):
+ if line.startswith( 'Traceback' ):
+ appending_to = 'traceback'
+ elif 'request returned None from get_history' in line:
+ continue
+ elif '>> begin captured logging <<' in line:
+ appending_to = 'logging'
+ continue
+ elif '>> begin captured stdout <<' in line:
+ appending_to = 'stdout'
+ continue
+ elif '>> begin captured stderr <<' in line:
+ appending_to = 'stderr'
+ continue
+ if appending_to not in tmp_output:
+ tmp_output[ appending_to ] = []
+ tmp_output[ appending_to ].append( line )
+ for output_type in tmp_output:
+ output[ output_type ] = '\n'.join( tmp_output[ output_type ] )
+ repository_dict[ 'tool_test_errors' ].append( dict( test=label, output=output ) )
+ register_test_failure( galaxy_tool_shed_url, metadata_revision_id, repository_dict[ 'tool_test_errors' ] )
log.debug( 'Repository %s installed, but did not pass functional tests.' % repository_dict[ 'name' ] )
+ repository_status.append( repository_dict )
+ # Delete the completed tool functional tests from the test_toolbox.__dict__, otherwise nose will find them and try to re-run the
+ # tests after uninstalling the repository.
+ tests_to_delete = []
+ for key in test_toolbox.__dict__:
+ if key.startswith( 'TestForTool_' ):
+ tests_to_delete.append( key )
+ for key in tests_to_delete:
+ del test_toolbox.__dict__[ key ]
# Generate an uninstall method for this repository, so that the next repository has a clean environment for testing.
test_install_repositories.generate_uninstall_method( repository_dict )
# Set up nose to run the generated uninstall method as a functional test.
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: inithello: Remove some unneeded data from the repository metadata API collection view.
by commits-noreply@bitbucket.org 27 Feb '13
by commits-noreply@bitbucket.org 27 Feb '13
27 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fabb0ae1edab/
changeset: fabb0ae1edab
user: inithello
date: 2013-02-27 20:23:07
summary: Remove some unneeded data from the repository metadata API collection view.
affected #: 1 file
diff -r b9c7813848e989d1a228a53745bb57f958b05467 -r fabb0ae1edabf77f9aceb018fa5a988ce05500f9 lib/galaxy/webapps/community/model/__init__.py
--- a/lib/galaxy/webapps/community/model/__init__.py
+++ b/lib/galaxy/webapps/community/model/__init__.py
@@ -191,8 +191,7 @@
fp.close()
class RepositoryMetadata( object, APIItem ):
- api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'tools_functionally_correct',
- 'do_not_test', 'time_last_tested', 'tool_test_errors' )
+ api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable' )
api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'tools_functionally_correct',
'do_not_test', 'time_last_tested', 'tool_test_errors' )
def __init__( self, id=None, repository_id=None, changeset_revision=None, metadata=None, tool_versions=None, malicious=False, downloadable=False,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: inithello: Attempt to resolve issue with tool shed registry when running buildbot functional tests.
by commits-noreply@bitbucket.org 27 Feb '13
by commits-noreply@bitbucket.org 27 Feb '13
27 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b9c7813848e9/
changeset: b9c7813848e9
user: inithello
date: 2013-02-27 20:12:07
summary: Attempt to resolve issue with tool shed registry when running buildbot functional tests.
affected #: 1 file
diff -r 8bad40b5b8ab0aee26c09ef8d59ca15227e1fec3 -r b9c7813848e989d1a228a53745bb57f958b05467 scripts/functional_tests.py
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -314,6 +314,7 @@
log.info( "Functional tests will be run against %s:%s" % ( galaxy_test_host, galaxy_test_port ) )
success = False
try:
+ tool_configs = app.config.tool_configs
# What requires these? Handy for (eg) functional tests to save outputs?
if galaxy_test_save:
os.environ[ 'GALAXY_TEST_SAVE' ] = galaxy_test_save
@@ -337,7 +338,6 @@
# Eliminate the migrated_tool_panel_config from the app's tool_configs, append the list of installed_tool_panel_configs,
# and reload the app's toolbox.
relative_migrated_tool_panel_config = os.path.join( app.config.root, migrated_tool_panel_config )
- tool_configs = app.config.tool_configs
if relative_migrated_tool_panel_config in tool_configs:
tool_configs.remove( relative_migrated_tool_panel_config )
for installed_tool_panel_config in installed_tool_panel_configs:
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: inithello: Clean up remaining references to galaxy.util.shed_util_common.
by commits-noreply@bitbucket.org 27 Feb '13
by commits-noreply@bitbucket.org 27 Feb '13
27 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8bad40b5b8ab/
changeset: 8bad40b5b8ab
user: inithello
date: 2013-02-27 17:16:10
summary: Clean up remaining references to galaxy.util.shed_util_common.
affected #: 2 files
diff -r b985587c33926d8d38fa4456b51eecbc68953bb9 -r 8bad40b5b8ab0aee26c09ef8d59ca15227e1fec3 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -920,7 +920,7 @@
def tool_shed_repository( self ):
# If this tool is included in an installed tool shed repository, return it.
if self.tool_shed:
- return galaxy.util.shed_util_common.get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( self.app,
+ return tool_shed.util.shed_util_common.get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( self.app,
self.tool_shed,
self.repository_name,
self.repository_owner,
diff -r b985587c33926d8d38fa4456b51eecbc68953bb9 -r 8bad40b5b8ab0aee26c09ef8d59ca15227e1fec3 lib/tool_shed/galaxy_install/__init__.py
--- a/lib/tool_shed/galaxy_install/__init__.py
+++ b/lib/tool_shed/galaxy_install/__init__.py
@@ -28,7 +28,7 @@
ElementInclude.include( root )
tool_path = root.get( 'tool_path', None )
if tool_path:
- tool_shed = galaxy.util.shed_util_common.clean_tool_shed_url( tool_shed_repository.tool_shed )
+ tool_shed = tool_shed.util.shed_util_common.clean_tool_shed_url( tool_shed_repository.tool_shed )
relative_path = os.path.join( tool_path,
tool_shed,
'repos',
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 community template path to tool_shed.
by commits-noreply@bitbucket.org 26 Feb '13
by commits-noreply@bitbucket.org 26 Feb '13
26 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b985587c3392/
changeset: b985587c3392
user: greg
date: 2013-02-26 23:12:52
summary: Rename community template path to tool_shed.
affected #: 101 files
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/web/base/controllers/admin.py
--- a/lib/galaxy/web/base/controllers/admin.py
+++ b/lib/galaxy/web/base/controllers/admin.py
@@ -36,7 +36,7 @@
message=message,
status=status )
else:
- return trans.fill_template( '/webapps/community/admin/index.mako',
+ return trans.fill_template( '/webapps/tool_shed/admin/index.mako',
message=message,
status=status )
@web.expose
@@ -49,7 +49,7 @@
message=message,
status=status )
else:
- return trans.fill_template( '/webapps/community/admin/center.mako',
+ return trans.fill_template( '/webapps/tool_shed/admin/center.mako',
message=message,
status=status )
@web.expose
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/web/framework/helpers/grids.py
--- a/lib/galaxy/web/framework/helpers/grids.py
+++ b/lib/galaxy/web/framework/helpers/grids.py
@@ -454,7 +454,7 @@
""" Column that displays community ratings for an item. """
def get_value( self, trans, grid, item ):
ave_item_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, item, webapp_model=trans.model )
- return trans.fill_template( "community_rating.mako",
+ return trans.fill_template( "tool_shed_rating.mako",
ave_item_rating=ave_item_rating,
num_ratings=num_ratings,
item_id=trans.security.encode_id( item.id ) )
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/webapps/community/controllers/admin.py
--- a/lib/galaxy/webapps/community/controllers/admin.py
+++ b/lib/galaxy/webapps/community/controllers/admin.py
@@ -403,7 +403,7 @@
# Grid definition
title = "Repository Metadata"
model_class = model.RepositoryMetadata
- template='/webapps/community/repository/grid.mako'
+ template='/webapps/tool_shed/repository/grid.mako'
default_sort_key = "name"
columns = [
IdColumn( "Id",
@@ -567,7 +567,7 @@
action='manage_categories',
message=message,
status=status ) )
- return trans.fill_template( '/webapps/community/category/create_category.mako',
+ return trans.fill_template( '/webapps/tool_shed/category/create_category.mako',
name=name,
description=description,
message=message,
@@ -667,7 +667,7 @@
action='manage_categories',
message=message,
status=status ) )
- return trans.fill_template( '/webapps/community/category/edit_category.mako',
+ return trans.fill_template( '/webapps/tool_shed/category/edit_category.mako',
category=category,
message=message,
status=status )
@@ -677,7 +677,7 @@
if 'f-free-text-search' in kwd:
# Trick to enable searching repository name, description from the CategoryGrid.
# What we've done is rendered the search box for the RepositoryGrid on the grid.mako
- # template for the CategoryGrid. See ~/templates/webapps/community/category/grid.mako.
+ # template for the CategoryGrid. See ~/templates/webapps/tool_shed/category/grid.mako.
# Since we are searching repositories and not categories, redirect to browse_repositories().
return trans.response.send_redirect( web.url_for( controller='admin',
action='browse_repositories',
@@ -714,7 +714,7 @@
if 'regenerate_statistics_button' in kwd:
trans.app.shed_counter.generate_statistics()
message = "Successfully regenerated statistics"
- return trans.fill_template( '/webapps/community/admin/statistics.mako',
+ return trans.fill_template( '/webapps/tool_shed/admin/statistics.mako',
message=message,
status=status )
@web.expose
@@ -726,7 +726,7 @@
message = util.restore_text( kwd.get( 'message', '' ) )
status = kwd.get( 'status', 'done' )
repositories_select_field = suc.build_repository_ids_select_field( trans )
- return trans.fill_template( '/webapps/community/admin/reset_metadata_on_selected_repositories.mako',
+ return trans.fill_template( '/webapps/tool_shed/admin/reset_metadata_on_selected_repositories.mako',
repositories_select_field=repositories_select_field,
message=message,
status=status )
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -46,7 +46,7 @@
return 0
title = "Categories"
model_class = model.Category
- template='/webapps/community/category/grid.mako'
+ template='/webapps/tool_shed/category/grid.mako'
default_sort_key = "name"
columns = [
NameColumn( "Name",
@@ -82,7 +82,7 @@
return 0
title = "Categories of valid repositories"
model_class = model.Category
- template='/webapps/community/category/valid_grid.mako'
+ template='/webapps/tool_shed/category/valid_grid.mako'
default_sort_key = "name"
columns = [
CategoryGrid.NameColumn( "Name",
@@ -172,7 +172,7 @@
# Grid definition
title = "Repositories"
model_class = model.Repository
- template='/webapps/community/repository/grid.mako'
+ template='/webapps/tool_shed/repository/grid.mako'
default_sort_key = "name"
columns = [
NameColumn( "Name",
@@ -503,7 +503,7 @@
# Grid definition
title = "Matching repositories"
model_class = model.RepositoryMetadata
- template='/webapps/community/repository/grid.mako'
+ template='/webapps/tool_shed/repository/grid.mako'
default_sort_key = "Repository.name"
columns = [
NameColumn( "Repository name",
@@ -571,7 +571,7 @@
# The request came from the tool shed.
if 'f-free-text-search' in kwd:
# Trick to enable searching repository name, description from the CategoryGrid. What we've done is rendered the search box for the
- # RepositoryGrid on the grid.mako template for the CategoryGrid. See ~/templates/webapps/community/category/grid.mako. Since we
+ # RepositoryGrid on the grid.mako template for the CategoryGrid. See ~/templates/webapps/tool_shed/category/grid.mako. Since we
# are searching repositories and not categories, redirect to browse_repositories().
if 'id' in kwd and 'f-free-text-search' in kwd and kwd[ 'id' ] == kwd[ 'f-free-text-search' ]:
# The value of 'id' has been set to the search string, which is a repository name. We'll try to get the desired encoded repository
@@ -629,7 +629,7 @@
repository.name,
repository.user.username,
downloadable_revision.changeset_revision )
- return trans.fill_template( '/webapps/community/repository/browse_invalid_tools.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/browse_invalid_tools.mako',
cntrller=cntrller,
invalid_tools_dict=invalid_tools_dict,
message=message,
@@ -747,7 +747,7 @@
suc.update_repository( repo )
is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
- return trans.fill_template( '/webapps/community/repository/browse_repository.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/browse_repository.mako',
repository=repository,
metadata=metadata,
commit_message=commit_message,
@@ -937,7 +937,7 @@
repository = suc.get_repository_in_tool_shed( trans, id )
metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
if trans.user and trans.user.email:
- return trans.fill_template( "/webapps/community/repository/contact_owner.mako",
+ return trans.fill_template( "/webapps/tool_shed/repository/contact_owner.mako",
repository=repository,
metadata=metadata,
message=message,
@@ -1032,7 +1032,7 @@
action='view_repository',
message=message,
id=trans.security.encode_id( repository.id ) ) )
- return trans.fill_template( '/webapps/community/repository/create_repository.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/create_repository.mako',
name=name,
description=description,
long_description=long_description,
@@ -1073,7 +1073,7 @@
is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, repository_id, changeset_revision )
try:
- return trans.fill_template( "/webapps/community/repository/tool_form.mako",
+ return trans.fill_template( "/webapps/tool_shed/repository/tool_form.mako",
repository=repository,
metadata=metadata,
changeset_revision=changeset_revision,
@@ -1197,7 +1197,7 @@
message = "No search performed - each field must contain the same number of comma-separated items."
status = "error"
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
- return trans.fill_template( '/webapps/community/repository/find_tools.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/find_tools.mako',
tool_id=self.__stringify( tool_ids ),
tool_name=self.__stringify( tool_names ),
tool_version=self.__stringify( tool_versions ),
@@ -1286,7 +1286,7 @@
exact_matches_checked = False
workflow_names = []
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
- return trans.fill_template( '/webapps/community/repository/find_workflows.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/find_workflows.mako',
workflow_name=self.__stringify( workflow_names ),
exact_matches_check_box=exact_matches_check_box,
message=message,
@@ -1690,7 +1690,7 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
- return trans.fill_template( '/webapps/community/repository/help.mako', message=message, status=status, **kwd )
+ return trans.fill_template( '/webapps/tool_shed/repository/help.mako', message=message, status=status, **kwd )
def __in_tool_dict( self, tool_dict, exact_matches_checked, tool_id=None, tool_name=None, tool_version=None ):
found = False
if tool_id and not tool_name and not tool_version:
@@ -1762,7 +1762,7 @@
user_id = params.get( 'user_id', None )
repository_id = params.get( 'repository_id', None )
changeset_revision = params.get( 'changeset_revision', None )
- return trans.fill_template( '/webapps/community/index.mako',
+ return trans.fill_template( '/webapps/tool_shed/index.mako',
repository_metadata=repository_metadata,
has_reviewed_repositories=has_reviewed_repositories,
has_deprecated_repositories=has_deprecated_repositories,
@@ -1813,7 +1813,7 @@
elif error_message:
message = error_message
try:
- return trans.fill_template( "/webapps/community/repository/tool_form.mako",
+ return trans.fill_template( "/webapps/tool_shed/repository/tool_form.mako",
repository=repository,
changeset_revision=changeset_revision,
tool=tool,
@@ -1872,7 +1872,7 @@
.order_by( trans.model.Repository.table.c.name ):
if user.email in repository.email_alerts:
email_alert_repositories.append( repository )
- return trans.fill_template( "/webapps/community/user/manage_email_alerts.mako",
+ return trans.fill_template( "/webapps/tool_shed/user/manage_email_alerts.mako",
new_repo_alert_check_box=new_repo_alert_check_box,
email_alert_repositories=email_alert_repositories,
message=message,
@@ -2056,7 +2056,7 @@
review_id = None
can_browse_repository_reviews = suc.can_browse_repository_reviews( trans, repository )
containers_dict = suc.build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata )
- return trans.fill_template( '/webapps/community/repository/manage_repository.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/manage_repository.mako',
repo_name=repo_name,
description=description,
long_description=long_description,
@@ -2163,7 +2163,7 @@
add_id_to_name=False,
downloadable=False )
containers_dict = suc.build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata )
- return trans.fill_template( '/webapps/community/repository/preview_tools_in_changeset.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/preview_tools_in_changeset.mako',
repository=repository,
containers_dict=containers_dict,
repository_metadata_id=repository_metadata_id,
@@ -2230,7 +2230,7 @@
rra = self.get_user_item_rating( trans.sa_session, trans.user, repository, webapp_model=trans.model )
is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
- return trans.fill_template( '/webapps/community/repository/rate_repository.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/rate_repository.mako',
repository=repository,
metadata=metadata,
avg_rating=avg_rating,
@@ -2242,7 +2242,7 @@
status=status )
@web.expose
def reset_all_metadata( self, trans, id, **kwd ):
- # This method is called only from the ~/templates/webapps/community/repository/manage_repository.mako template.
+ # This method is called only from the ~/templates/webapps/tool_shed/repository/manage_repository.mako template.
# It resets all metadata on the complete changelog for a single repository in the tool shed.
invalid_file_tups, metadata_dict = suc.reset_all_metadata_on_repository_in_tool_shed( trans, id, **kwd )
if invalid_file_tups:
@@ -2405,7 +2405,7 @@
message = "Select at least 1 file to delete from the repository before clicking <b>Delete selected files</b>."
status = "error"
is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
- return trans.fill_template( '/webapps/community/repository/browse_repository.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/browse_repository.mako',
repo=repo,
repository=repository,
commit_message=commit_message,
@@ -2672,7 +2672,7 @@
changesets.insert( 0, change_dict )
is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
- return trans.fill_template( '/webapps/community/repository/view_changelog.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/view_changelog.mako',
repository=repository,
metadata=metadata,
changesets=changesets,
@@ -2703,7 +2703,7 @@
diffs.append( suc.to_safe_string( diff, to_html=True ) )
is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, ctx_str )
- return trans.fill_template( '/webapps/community/repository/view_changeset.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/view_changeset.mako',
repository=repository,
metadata=metadata,
ctx=ctx,
@@ -2810,7 +2810,7 @@
review_id = None
containers_dict = suc.build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata )
can_browse_repository_reviews = suc.can_browse_repository_reviews( trans, repository )
- return trans.fill_template( '/webapps/community/repository/view_repository.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/view_repository.mako',
repo=repo,
repository=repository,
repository_metadata_id=repository_metadata_id,
@@ -2893,7 +2893,7 @@
review_id = trans.security.encode_id( review.id )
else:
review_id = None
- return trans.fill_template( "/webapps/community/repository/view_tool_metadata.mako",
+ return trans.fill_template( "/webapps/tool_shed/repository/view_tool_metadata.mako",
repository=repository,
metadata=metadata,
tool=tool,
@@ -2919,7 +2919,7 @@
repository = suc.get_repository_in_tool_shed( trans, trans.security.encode_id( repository_metadata.repository_id ) )
changeset_revision = repository_metadata.changeset_revision
metadata = repository_metadata.metadata
- return trans.fill_template( "/webapps/community/repository/view_workflow.mako",
+ return trans.fill_template( "/webapps/tool_shed/repository/view_workflow.mako",
repository=repository,
changeset_revision=changeset_revision,
repository_metadata_id=repository_metadata_id,
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/webapps/community/controllers/repository_review.py
--- a/lib/galaxy/webapps/community/controllers/repository_review.py
+++ b/lib/galaxy/webapps/community/controllers/repository_review.py
@@ -27,7 +27,7 @@
return component.description
title = "Repository review components"
model_class = model.Component
- template='/webapps/community/repository_review/grid.mako'
+ template='/webapps/tool_shed/repository_review/grid.mako'
default_sort_key = "name"
columns = [
NameColumn( "Name",
@@ -89,7 +89,7 @@
return rval
title = "All reviewed repositories"
model_class = model.Repository
- template='/webapps/community/repository_review/grid.mako'
+ template='/webapps/tool_shed/repository_review/grid.mako'
default_sort_key = "Repository.name"
columns = [
RepositoryGrid.NameColumn( "Repository name",
@@ -196,7 +196,7 @@
return ''
title = "Reviews by user"
model_class = model.RepositoryReview
- template='/webapps/community/repository_review/grid.mako'
+ template='/webapps/tool_shed/repository_review/grid.mako'
default_sort_key = 'repository_id'
columns = [
RepositoryNameColumn( "Repository Name",
@@ -316,7 +316,7 @@
repository = review.repository
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, review.changeset_revision )
- return trans.fill_template( '/webapps/community/repository_review/browse_review.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository_review/browse_review.mako',
repository=repository,
changeset_revision_label=changeset_revision_label,
review=review,
@@ -361,7 +361,7 @@
action='manage_components',
message=message,
status=status ) )
- return trans.fill_template( '/webapps/community/repository_review/create_component.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository_review/create_component.mako',
name=name,
description=description,
message=message,
@@ -456,7 +456,7 @@
action='manage_components',
message=message,
status=status ) )
- return trans.fill_template( '/webapps/community/repository_review/edit_component.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository_review/edit_component.mako',
component=component,
message=message,
status=status )
@@ -576,7 +576,7 @@
selected_value=selected_value,
for_component=False )
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, review.changeset_revision )
- return trans.fill_template( '/webapps/community/repository_review/edit_review.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository_review/edit_review.mako',
repository=repository,
review=review,
changeset_revision_label=changeset_revision_label,
@@ -688,7 +688,7 @@
installable=installable,
can_add_review=can_add_review )
reviews_dict[ changeset_revision ] = revision_dict
- return trans.fill_template( '/webapps/community/repository_review/reviews_of_repository.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository_review/reviews_of_repository.mako',
repository=repository,
reviews_dict=reviews_dict,
mine=mine,
@@ -709,7 +709,7 @@
installable = changeset_revision in [ metadata_revision.changeset_revision for metadata_revision in repository.metadata_revisions ]
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, changeset_revision )
reviews = suc.get_reviews_by_repository_id_changeset_revision( trans, repository_id, changeset_revision )
- return trans.fill_template( '/webapps/community/repository_review/reviews_of_changeset_revision.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository_review/reviews_of_changeset_revision.mako',
repository=repository,
changeset_revision=changeset_revision,
changeset_revision_label=changeset_revision_label,
@@ -773,7 +773,7 @@
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
previous_reviews_dict = suc.get_previous_repository_reviews( trans, repository, changeset_revision )
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, changeset_revision )
- return trans.fill_template( '/webapps/community/repository_review/select_previous_review.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository_review/select_previous_review.mako',
repository=repository,
changeset_revision=changeset_revision,
changeset_revision_label=changeset_revision_label,
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/webapps/community/controllers/upload.py
--- a/lib/galaxy/webapps/community/controllers/upload.py
+++ b/lib/galaxy/webapps/community/controllers/upload.py
@@ -204,7 +204,7 @@
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
suc.reset_tool_data_tables( trans.app )
selected_categories = [ trans.security.decode_id( id ) for id in category_ids ]
- return trans.fill_template( '/webapps/community/repository/upload.mako',
+ return trans.fill_template( '/webapps/tool_shed/repository/upload.mako',
repository=repository,
url=url,
commit_message=commit_message,
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/webapps/galaxy/controllers/admin.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin.py
@@ -733,7 +733,7 @@
status = util.restore_text( kwd.get( 'status', 'done' ) )
migration_stages_dict = odict()
migration_modules = []
- migration_scripts_dir = os.path.abspath( os.path.join( trans.app.config.root, 'lib', 'galaxy', 'tool_shed', 'migrate', 'versions' ) )
+ migration_scripts_dir = os.path.abspath( os.path.join( trans.app.config.root, 'lib', 'tool_shed', 'galaxy_install', 'migrate', 'versions' ) )
migration_scripts_dir_contents = os.listdir( migration_scripts_dir )
for item in migration_scripts_dir_contents:
if os.path.isfile( os.path.join( migration_scripts_dir, item ) ) and item.endswith( '.py' ):
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -735,7 +735,7 @@
message=message,
status=status )
else:
- return trans.fill_template( '/webapps/community/user/manage_info.mako',
+ return trans.fill_template( '/webapps/tool_shed/user/manage_info.mako',
cntrller=cntrller,
user=user,
email=email,
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/admin/tool_shed_repository/common.mako
--- a/templates/admin/tool_shed_repository/common.mako
+++ b/templates/admin/tool_shed_repository/common.mako
@@ -1,4 +1,4 @@
-<%namespace file="/webapps/community/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" /><%def name="browse_files(title_text, directory_path)"><script type="text/javascript">
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/admin/tool_shed_repository/manage_repository.mako
--- a/templates/admin/tool_shed_repository/manage_repository.mako
+++ b/templates/admin/tool_shed_repository/manage_repository.mako
@@ -1,6 +1,6 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/community/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" /><%namespace file="/admin/tool_shed_repository/common.mako" import="*" /><%def name="stylesheets()">
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
--- a/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
+++ b/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
@@ -2,7 +2,7 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_dependencies_section" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_readme_section" />
-<%namespace file="/webapps/community/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" /><%def name="stylesheets()">
${parent.stylesheets()}
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/admin/tool_shed_repository/reset_metadata_on_selected_repositories.mako
--- a/templates/admin/tool_shed_repository/reset_metadata_on_selected_repositories.mako
+++ b/templates/admin/tool_shed_repository/reset_metadata_on_selected_repositories.mako
@@ -1,6 +1,6 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/community/common/common.mako" import="common_misc_javascripts" />
+<%namespace file="/webapps/tool_shed/common/common.mako" import="common_misc_javascripts" /><%def name="javascripts()">
${parent.javascripts()}
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/admin/tool_shed_repository/select_shed_tool_panel_config.mako
--- a/templates/admin/tool_shed_repository/select_shed_tool_panel_config.mako
+++ b/templates/admin/tool_shed_repository/select_shed_tool_panel_config.mako
@@ -2,7 +2,7 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_dependencies_section" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_readme_section" />
-<%namespace file="/webapps/community/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" /><%def name="stylesheets()">
${parent.stylesheets()}
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/admin/tool_shed_repository/select_tool_panel_section.mako
--- a/templates/admin/tool_shed_repository/select_tool_panel_section.mako
+++ b/templates/admin/tool_shed_repository/select_tool_panel_section.mako
@@ -2,7 +2,7 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_dependencies_section" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_readme_section" />
-<%namespace file="/webapps/community/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" /><%def name="stylesheets()">
${parent.stylesheets()}
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/admin/tool_shed_repository/view_workflow.mako
--- a/templates/admin/tool_shed_repository/view_workflow.mako
+++ b/templates/admin/tool_shed_repository/view_workflow.mako
@@ -1,7 +1,7 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/community/common/common.mako" import="*" />
-<%namespace file="/webapps/community/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" /><%
from galaxy.web.framework.helpers import time_ago
@@ -11,7 +11,7 @@
<%!
def inherit(context):
if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
+ return '/webapps/tool_shed/base_panels.mako'
else:
return '/base.mako'
%>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/community_rating.mako
--- a/templates/community_rating.mako
+++ /dev/null
@@ -1,33 +0,0 @@
-<%
- label = "ratings"
- if num_ratings == 1:
- label = "rating"
-%>
-<div>
- <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="1"
- %if ave_item_rating > 0 and ave_item_rating <= 1.5:
- checked="checked"
- %endif
-
- />
- <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="2"
- %if ave_item_rating > 1.5 and ave_item_rating <= 2.5:
- checked="checked"
- %endif
- />
- <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="3"
- %if ave_item_rating > 2.5 and ave_item_rating <= 3.5:
- checked="checked"
- %endif
- />
- <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="4"
- %if ave_item_rating > 3.5 and ave_item_rating <= 4.5:
- checked="checked"
- %endif
- />
- <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="5"
- %if ave_item_rating > 4.5:
- checked="checked"
- %endif
- />
-</div>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/tool_shed_rating.mako
--- /dev/null
+++ b/templates/tool_shed_rating.mako
@@ -0,0 +1,33 @@
+<%
+ label = "ratings"
+ if num_ratings == 1:
+ label = "rating"
+%>
+<div>
+ <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="1"
+ %if ave_item_rating > 0 and ave_item_rating <= 1.5:
+ checked="checked"
+ %endif
+
+ />
+ <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="2"
+ %if ave_item_rating > 1.5 and ave_item_rating <= 2.5:
+ checked="checked"
+ %endif
+ />
+ <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="3"
+ %if ave_item_rating > 2.5 and ave_item_rating <= 3.5:
+ checked="checked"
+ %endif
+ />
+ <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="4"
+ %if ave_item_rating > 3.5 and ave_item_rating <= 4.5:
+ checked="checked"
+ %endif
+ />
+ <input name="star1-${item_id}" type="radio" class="community_rating_star star" disabled="disabled" value="5"
+ %if ave_item_rating > 4.5:
+ checked="checked"
+ %endif
+ />
+</div>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/user/dbkeys.mako
--- a/templates/user/dbkeys.mako
+++ b/templates/user/dbkeys.mako
@@ -1,7 +1,7 @@
<%!
def inherit(context):
if context.get('use_panels'):
- return '/base_panels.mako'
+ return '/webapps/galaxy/base_panels.mako'
else:
return '/base.mako'
%>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/user/login.mako
--- a/templates/user/login.mako
+++ b/templates/user/login.mako
@@ -1,7 +1,7 @@
<%!
def inherit(context):
if context.get('use_panels'):
- return '/base_panels.mako'
+ return '/webapps/galaxy/base_panels.mako'
else:
return '/base.mako'
%>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/user/logout.mako
--- a/templates/user/logout.mako
+++ b/templates/user/logout.mako
@@ -1,4 +1,4 @@
-<%inherit file="/base_panels.mako"/>
+<%inherit file="/webapps/galaxy/base_panels.mako"/><%namespace file="/message.mako" import="render_msg" />
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/user/openid_associate.mako
--- a/templates/user/openid_associate.mako
+++ b/templates/user/openid_associate.mako
@@ -1,7 +1,7 @@
<%!
def inherit(context):
if context.get('use_panels'):
- return '/base_panels.mako'
+ return '/webapps/galaxy/base_panels.mako'
else:
return '/base.mako'
%>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/admin/center.mako
--- a/templates/webapps/community/admin/center.mako
+++ /dev/null
@@ -1,50 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-
-<%def name="title()">Galaxy Administration</%def>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<h2>Administration</h2>
-
-<p>The menu on the left provides the following features</p>
-<ul>
- <li>
- <strong>Categories</strong>
- <p/>
- <ul>
- <li>
- <strong>Manage categories</strong>
- </li>
- <p/>
- </ul>
- </li>
- <li>
- <strong>Security</strong>
- <p/>
- <ul>
- <li>
- <strong>Manage users</strong> - provides a view of the registered users and all groups and non-private roles associated
- with each user.
- </li>
- <p/>
- <li>
- <strong>Manage groups</strong> - provides a view of all groups along with the members of the group and the roles associated with
- each group (both private and non-private roles). The group names include a link to a page that allows you to manage the users and
- roles that are associated with the group.
- </li>
- <p/>
- <li>
- <strong>Manage roles</strong> - provides a view of all non-private roles along with the role type, and the users and groups that
- are associated with the role. The role names include a link to a page that allows you to manage the users and groups that are associated
- with the role. The page also includes a view of the data library datasets that are associated with the role and the permissions applied
- to each dataset.
- </li>
- </ul>
- </li>
- <p/>
-</ul>
-<br/>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/admin/index.mako
--- a/templates/webapps/community/admin/index.mako
+++ /dev/null
@@ -1,139 +0,0 @@
-<%inherit file="/webapps/community/base_panels.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<%def name="stylesheets()">
- ## Include "base.css" for styling tool menu and forms (details)
- ${h.css( "base", "autocomplete_tagging", "tool_menu" )}
-
- ## But make sure styles for the layout take precedence
- ${parent.stylesheets()}
-
- <style type="text/css">
- body { margin: 0; padding: 0; overflow: hidden; }
- #left {
- background: #C1C9E5 url(${h.url_for('/static/style/menu_bg.png')}) top repeat-x;
- }
- </style>
-</%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
-</%def>
-
-<%def name="init()">
- <%
- self.has_left_panel=True
- self.has_right_panel=False
- self.active_view="tools"
- %>
- %if trans.app.config.require_login and not trans.user:
- <script type="text/javascript">
- if ( window != top ) {
- top.location.href = location.href;
- }
- </script>
- %endif
-</%def>
-
-<%def name="left_panel()">
- <% can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user ) %>
- <div class="unified-panel-header" unselectable="on">
- <div class='unified-panel-header-inner'>Administration</div>
- </div>
- <div class="page-container" style="padding: 10px;">
- <div class="toolMenu">
- <div class="toolSectionList">
- <div class="toolSectionTitle">
- Repositories
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_categories' )}">Browse by category</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_repositories' )}">Browse all repositories</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='reset_metadata_on_selected_repositories_in_tool_shed' )}">Reset selected metadata</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_repository_metadata' )}">Browse metadata</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_invalid_tools', cntrller='admin' )}">Browse invalid tools</a>
- </div>
- </div>
- </div>
- %if can_review_repositories:
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Reviewing Repositories
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- %if trans.user.repository_reviews:
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_reviewed_by_me' )}">Repositories reviewed by me</a>
- </div>
- %endif
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_with_reviews' )}">All reviewed repositories</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_without_reviews' )}">Repositories with no reviews</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_components' )}">Manage review components</a>
- </div>
- </div>
- </div>
- %endif
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Categories
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='manage_categories' )}">Manage categories</a>
- </div>
- </div>
- </div>
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Security
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='users' )}">Manage users</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='groups' )}">Manage groups</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='roles' )}">Manage roles</a>
- </div>
- </div>
- </div>
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Statistics
- </div>
- <div class="toolSectionBody">
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='admin', action='regenerate_statistics' )}">View shed statistics</a>
- </div>
- </div>
- </div>
- </div>
- </div>
-</%def>
-
-<%def name="center_panel()">
- <%
- center_url = h.url_for(controller='admin', action='center' )
- %>
- <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe>
-</%def>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/admin/reset_metadata_on_selected_repositories.mako
--- a/templates/webapps/community/admin/reset_metadata_on_selected_repositories.mako
+++ /dev/null
@@ -1,40 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/community/common/common.mako" import="common_misc_javascripts" />
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${common_misc_javascripts()}
-</%def>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="warningmessage">
- Resetting metadata may take a while because this process clones each change set in each selected repository's change log to a temporary location on disk.
- Wait until this page redirects after clicking the <b>Reset metadata on selected repositories</b> button, as doing anything else will not be helpful. Watch
- the tool shed paster log to pass the time if necessary.
-</div>
-
-<div class="toolForm">
- <div class="toolFormTitle">Reset all metadata on each selected repository</div>
- <form name="reset_metadata_on_selected_repositories" id="reset_metadata_on_selected_repositories" action="${h.url_for( controller='admin', action='reset_metadata_on_selected_repositories_in_tool_shed' )}" method="post" >
- <div class="form-row">
- Check each repository for which you want to reset metadata. Repository names are followed by owners in parentheses.
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <input type="checkbox" id="checkAll" name="select_all_repositories_checkbox" value="true" onclick="checkAllFields('repository_ids');"/><input type="hidden" name="select_all_repositories_checkbox" value="true"/><b>Select/unselect all repositories</b>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- ${repositories_select_field.get_html()}
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <input type="submit" name="reset_metadata_on_selected_repositories_button" value="Reset metadata on selected repositories"/>
- </div>
- </form>
- </div>
-</div>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/admin/statistics.mako
--- a/templates/webapps/community/admin/statistics.mako
+++ /dev/null
@@ -1,56 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">Tool shed statistics generated on ${trans.app.shed_counter.generation_time}</div>
- <form name="regenerate_statistics" id="regenerate_statistics" action="${h.url_for( controller='admin', action='regenerate_statistics' )}" method="post" >
- <div class="form-row">
- <table class="grid">
- <tr>
- <th>Item</th>
- <th>Count</th>
- </tr>
- <tr>
- <td>Total repositories</td>
- <td>${trans.app.shed_counter.repositories | h}</td>
- </tr>
- ##<tr>
- ## <td>Empty repositories</td>
- ## <td>${trans.app.shed_counter.new_repositories | h}</td>
- ##</tr>
- <tr>
- <td>Deleted repositories</td>
- <td>${trans.app.shed_counter.deleted_repositories | h}</td>
- </tr>
- <tr>
- <td>Valid tools</td>
- <td>${trans.app.shed_counter.valid_tools | h}</td>
- </tr>
- <tr>
- <td>Invalid tools</td>
- <td>${trans.app.shed_counter.invalid_tools | h}</td>
- </tr>
- <tr>
- <td>Workflows</td>
- <td>${trans.app.shed_counter.workflows | h}</td>
- </tr>
- <tr>
- <td>Proprietary datatypes</td>
- <td>${trans.app.shed_counter.proprietary_datatypes | h}</td>
- </tr>
- <tr>
- <td>Total clones</td>
- <td>${trans.app.shed_counter.total_clones | h}</td>
- </tr>
- </table>
- </div>
- <div class="form-row">
- <input type="submit" name="regenerate_statistics_button" value="Regenerate statistics"/>
- </div>
- </form>
- </div>
-</div>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/base_panels.mako
--- a/templates/webapps/community/base_panels.mako
+++ /dev/null
@@ -1,133 +0,0 @@
-<%inherit file="/base/base_panels.mako"/>
-
-## Default title
-<%def name="title()">Galaxy Tool Shed</%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
-</%def>
-
-## Masthead
-<%def name="masthead()">
-
- ## Tab area, fills entire width
- <div style="position: relative; right: -50%; float: left;">
- <div style="display: block; position: relative; right: 50%;">
-
- <ul class="nav" border="0" cellspacing="0">
-
- <%def name="tab( id, display, href, target='_parent', visible=True, extra_class='', menu_options=None )">
- <%
- cls = ""
- a_cls = ""
- extra = ""
- if extra_class:
- cls += " " + extra_class
- if self.active_view == id:
- cls += " active"
- if menu_options:
- cls += " dropdown"
- a_cls += " dropdown-toggle"
- extra = "<b class='caret'></b>"
- style = ""
- if not visible:
- style = "display: none;"
- %>
- <li class="${cls}" style="${style}">
- %if href:
- <a class="${a_cls}" data-toggle="dropdown" target="${target}" href="${href}">${display}${extra}</a>
- %else:
- <a class="${a_cls}" data-toggle="dropdown">${display}${extra}</a>
- %endif
- %if menu_options:
- <ul class="dropdown-menu">
- %for menu_item in menu_options:
- %if not menu_item:
- <li class="divider"></li>
- %else:
- <li>
- %if len ( menu_item ) == 1:
- ${menu_item[0]}
- %elif len ( menu_item ) == 2:
- <% name, link = menu_item %>
- <a href="${link}">${name | h}</a>
- %else:
- <% name, link, target = menu_item %>
- <a target="${target}" href="${link}">${name | h}</a>
- %endif
- </li>
- %endif
- %endfor
- </ul>
- %endif
- </li>
- </%def>
-
- ## Repositories tab.
- ${tab( "repositories", "Repositories", h.url_for( controller='/repository', action='index' ) )}
-
- ## Admin tab.
- ${tab( "admin", "Admin", h.url_for( controller='/admin', action='index' ), extra_class="admin-only", visible=( trans.user and app.config.is_admin_user( trans.user ) ) )}
-
- ## Help tab.
- <%
- menu_options = []
- qa_url = app.config.get( "qa_url", None )
- if qa_url:
- menu_options = [ [_('Galaxy Q&A'), qa_url, "_blank" ] ]
- menu_options.extend( [
- [_('Support'), app.config.get( "support_url", "http://wiki.g2.bx.psu.edu/Support" ), "_blank" ],
- [_('Tool shed wiki'), app.config.get( "wiki_url", "http://wiki.g2.bx.psu.edu/Tool%20Shed" ), "_blank" ],
- [_('Galaxy wiki'), app.config.get( "wiki_url", "http://wiki.g2.bx.psu.edu/" ), "_blank" ],
- [_('Video tutorials (screencasts)'), app.config.get( "screencasts_url", "http://galaxycast.org" ), "_blank" ],
- [_('How to Cite Galaxy'), app.config.get( "citation_url", "http://wiki.g2.bx.psu.edu/Citing%20Galaxy" ), "_blank" ]
- ] )
- tab( "help", _("Help"), None, menu_options=menu_options )
- %>
-
- ## User tabs.
- <%
- # Menu for user who is not logged in.
- menu_options = [ [ _("Login"), h.url_for( controller='/user', action='login' ), "galaxy_main" ] ]
- if app.config.allow_user_creation:
- menu_options.append( [ _("Register"), h.url_for( controller='/user', action='create', cntrller='user' ), "galaxy_main" ] )
- extra_class = "loggedout-only"
- visible = ( trans.user == None )
- tab( "user", _("User"), None, visible=visible, menu_options=menu_options )
- # Menu for user who is logged in.
- if trans.user:
- email = trans.user.email
- else:
- email = ""
- menu_options = [ [ '<a>Logged in as <span id="user-email">%s</span></a>' % email ] ]
- if app.config.use_remote_user:
- if app.config.remote_user_logout_href:
- menu_options.append( [ _('Logout'), app.config.remote_user_logout_href, "_top" ] )
- else:
- menu_options.append( [ _('Preferences'), h.url_for( controller='/user', action='index', cntrller='user' ), "galaxy_main" ] )
- menu_options.append( [ _('API Keys'), h.url_for( controller='/user', action='api_keys', cntrller='user' ), "galaxy_main" ] )
- logout_url = h.url_for( controller='/user', action='logout' )
- menu_options.append( [ 'Logout', logout_url, "_top" ] )
- menu_options.append( None )
- if app.config.use_remote_user:
- menu_options.append( [ _('Public Name'), h.url_for( controller='/user', action='edit_username', cntrller='user' ), "galaxy_main" ] )
-
- extra_class = "loggedin-only"
- visible = ( trans.user != None )
- tab( "user", "User", None, visible=visible, menu_options=menu_options )
- %>
- </ul>
- </div>
- </div>
-
- ## Logo, layered over tabs to be clickable
- <div class="title">
- <a href="${h.url_for( app.config.get( 'logo_url', '/' ) )}">
- <img border="0" src="${h.url_for('/static/images/galaxyIcon_noText.png')}">
- Galaxy Tool Shed
- %if app.config.brand:
- <span>/ ${app.config.brand}</span>
- %endif
- </a>
- </div>
-</%def>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/category/create_category.mako
--- a/templates/webapps/community/category/create_category.mako
+++ /dev/null
@@ -1,34 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- <script type="text/javascript">
- $(function(){
- $("input:text:first").focus();
- })
- </script>
-</%def>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">Create Category</div>
- <div class="toolFormBody">
- <form name="create_category_form" id="create_category_form" action="${h.url_for(controller='admin', action='create_category' )}" method="post" >
- <div class="form-row">
- <label>Name:</label>
- <input name="name" type="textfield" value="${name | h}" size=40"/>
- </div>
- <div class="form-row">
- <label>Description:</label>
- <input name="description" type="textfield" value="${description | h}" size=40"/>
- </div>
- <div class="form-row">
- <input type="submit" name="create_category_button" value="Save"/>
- </div>
- </form>
- </div>
-</div>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/category/edit_category.mako
--- a/templates/webapps/community/category/edit_category.mako
+++ /dev/null
@@ -1,43 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">Change category name and description</div>
- <div class="toolFormBody">
- <form name="edit_category" action="${h.url_for( controller='admin', action='edit_category' )}" method="post" >
- <div class="form-row">
- <label>Name:</label>
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="text" name="name" value="${category.name | h}" size="40"/>
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Description:</label>
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input name="description" type="textfield" value="${category.description | h}" size=40"/>
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="hidden" name="rename" value="submitted"/>
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="hidden" name="id" value="${trans.security.encode_id( category.id )}"/>
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <input type="submit" name="edit_category_button" value="Save"/>
- </div>
- </form>
- </div>
-</div>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/category/grid.mako
--- a/templates/webapps/community/category/grid.mako
+++ /dev/null
@@ -1,64 +0,0 @@
-<%namespace file="/display_common.mako" import="render_message" />
-<%namespace file="/grid_base.mako" import="*" />
-<%namespace file="/grid_common.mako" import="*" />
-<%inherit file="/grid_base.mako" />
-
-## Render grid header.
-## TODO: This is very similar to this directory's valid_grid.mako, so see if we can re-use this code in a better way.
-<%def name="render_grid_header( grid, repo_grid, render_title=True)">
- <div class="grid-header">
- %if render_title:
- ${grid_title()}
- %endif
- %if grid.global_actions:
- <ul class="manage-table-actions">
- %if len( grid.global_actions ) < 4:
- %for action in grid.global_actions:
- <li><a class="action-button" href="${h.url_for( **action.url_args )}">${action.label | h}</a></li>
- %endfor
- %else:
- <li><a class="action-button" id="action-8675309-popup" class="menubutton">Actions</a></li>
- <div popupmenu="action-8675309-popup">
- %for action in grid.global_actions:
- <a class="action-button" href="${h.url_for( **action.url_args )}">${action.label | h}</a>
- %endfor
- </div>
- %endif
- </ul>
- %endif
- ${render_grid_filters( repo_grid, render_advanced_search=False )}
- </div>
-</%def>
-
-<%def name="make_grid( grid, repo_grid )">
- <div class="loading-elt-overlay"></div>
- <table>
- <tr>
- <td width="75%">${self.render_grid_header( grid, repo_grid )}</td>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td width="100%" id="grid-message" valign="top">${render_message( message, status )}</td>
- <td></td>
- <td></td>
- </tr>
- </table>
- ${render_grid_table( grid, show_item_checkboxes )}
-</%def>
-
-<%def name="grid_body( grid )">
- <%
- from galaxy.webapps.community.controllers.repository import RepositoryGrid
- repo_grid = RepositoryGrid()
- %>
- ${self.make_grid( grid, repo_grid )}
-</%def>
-
-<%def name="center_panel()">
- <div style="overflow: auto; height: 100%">
- <div class="page-container" style="padding: 10px;">
- ${self.grid_body( grid )}
- </div>
- </div>
-</%def>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/category/valid_grid.mako
--- a/templates/webapps/community/category/valid_grid.mako
+++ /dev/null
@@ -1,63 +0,0 @@
-<%namespace file="/display_common.mako" import="render_message" />
-<%namespace file="/grid_base.mako" import="*" />
-<%namespace file="/grid_common.mako" import="*" />
-<%inherit file="/grid_base.mako" />
-
-## Render grid header.
-<%def name="render_grid_header( grid, repo_grid, render_title=True)">
- <div class="grid-header">
- %if render_title:
- ${grid_title()}
- %endif
- %if grid.global_actions:
- <ul class="manage-table-actions">
- %if len( grid.global_actions ) < 4:
- %for action in grid.global_actions:
- <li><a class="action-button" href="${h.url_for( **action.url_args )}">${action.label | h}</a></li>
- %endfor
- %else:
- <li><a class="action-button" id="action-8675309-popup" class="menubutton">Actions</a></li>
- <div popupmenu="action-8675309-popup">
- %for action in grid.global_actions:
- <a class="action-button" href="${h.url_for( **action.url_args )}">${action.label | h}</a>
- %endfor
- </div>
- %endif
- </ul>
- %endif
- ${render_grid_filters( repo_grid, render_advanced_search=False )}
- </div>
-</%def>
-
-<%def name="make_grid( grid, repo_grid )">
- <div class="loading-elt-overlay"></div>
- <table>
- <tr>
- <td width="75%">${self.render_grid_header( grid, repo_grid )}</td>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td width="100%" id="grid-message" valign="top">${render_message( message, status )}</td>
- <td></td>
- <td></td>
- </tr>
- </table>
- ${render_grid_table( grid, show_item_checkboxes )}
-</%def>
-
-<%def name="grid_body( grid )">
- <%
- from galaxy.webapps.community.controllers.repository import ValidRepositoryGrid
- repo_grid = ValidRepositoryGrid()
- %>
- ${self.make_grid( grid, repo_grid )}
-</%def>
-
-<%def name="center_panel()">
- <div style="overflow: auto; height: 100%">
- <div class="page-container" style="padding: 10px;">
- ${self.grid_body( grid )}
- </div>
- </div>
-</%def>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/common/common.mako
--- a/templates/webapps/community/common/common.mako
+++ /dev/null
@@ -1,84 +0,0 @@
-<%def name="common_misc_javascripts()">
- <script type="text/javascript">
- function checkAllFields( name )
- {
- var chkAll = document.getElementById( 'checkAll' );
- var checks = document.getElementsByTagName( 'input' );
- var boxLength = checks.length;
- var allChecked = false;
- var totalChecked = 0;
- if ( chkAll.checked == true )
- {
- for ( i=0; i < boxLength; i++ )
- {
- if ( checks[i].name.indexOf( name ) != -1 )
- {
- checks[i].checked = true;
- }
- }
- }
- else
- {
- for ( i=0; i < boxLength; i++ )
- {
- if ( checks[i].name.indexOf( name ) != -1 )
- {
- checks[i].checked = false
- }
- }
- }
- }
- </script>
-</%def>
-
-<%def name="render_star_rating( name, rating, disabled=False )">
- <%
- if disabled:
- disabled_str = ' disabled="disabled"'
- else:
- disabled_str = ''
- html = ''
- for index in range( 1, 6 ):
- html += '<input name="%s" type="radio" class="star" value="%s" %s' % ( str( name ), str( index ), disabled_str )
- if rating > ( index - 0.5 ) and rating < ( index + 0.5 ):
- html += ' checked="checked"'
- html += '/>'
- %>
- ${html}
-</%def>
-
-<%def name="render_long_description( description_text )">
- <style type="text/css">
- #description_table{ table-layout:fixed;
- width:100%;
- overflow-wrap:normal;
- overflow:hidden;
- border:0px;
- word-break:keep-all;
- word-wrap:break-word;
- line-break:strict; }
- </style>
- <div class="form-row">
- <label>Detailed description:</label>
- <table id="description_table">
- <tr><td>${description_text}</td></tr>
- </table>
- <div style="clear: both"></div>
- </div>
-</%def>
-
-<%def name="render_review_comment( comment_text )">
- <style type="text/css">
- #reviews_table{ table-layout:fixed;
- width:100%;
- overflow-wrap:normal;
- overflow:hidden;
- border:0px;
- word-break:keep-all;
- word-wrap:break-word;
- line-break:strict; }
- </style>
- <table id="reviews_table">
- <tr><td>${comment_text}</td></tr>
- </table>
-</%def>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/index.mako
--- a/templates/webapps/community/index.mako
+++ /dev/null
@@ -1,165 +0,0 @@
-<%inherit file="/webapps/community/base_panels.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ## Include "base.css" for styling tool menu and forms (details)
- ${h.css( "base", "autocomplete_tagging", "tool_menu" )}
-
- ## But make sure styles for the layout take precedence
- ${parent.stylesheets()}
-
- <style type="text/css">
- body { margin: 0; padding: 0; overflow: hidden; }
- #left {
- background: #C1C9E5 url(${h.url_for('/static/style/menu_bg.png')}) top repeat-x;
- }
- </style>
-</%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
-</%def>
-
-<%def name="init()">
- <%
- self.has_left_panel=True
- self.has_right_panel=False
- self.active_view="tools"
- %>
- %if trans.app.config.require_login and not trans.user:
- <script type="text/javascript">
- if ( window != top ) {
- top.location.href = location.href;
- }
- </script>
- %endif
-</%def>
-
-<%def name="left_panel()">
- <% can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user ) %>
- <div class="unified-panel-header" unselectable="on">
- <div class='unified-panel-header-inner'>${trans.app.shed_counter.valid_tools | h} valid tools on ${trans.app.shed_counter.generation_time | h}</div>
- </div>
- <div class="page-container" style="padding: 10px;">
- <div class="toolMenu">
- <div class="toolSectionList">
- %if user_id or repository_id:
- ## The route in was a sharable url, and may have included a changeset_revision, although we don't check for it.
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- All Repositories
- </div>
- <div class="toolTitle">
- <a href="${h.url_for( controller='repository', action='index' )}">Browse by category</a>
- </div>
- %else:
- %if repository_metadata:
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Search
- </div>
- <div class="toolSectionBody">
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a>
- </div>
- </div>
- %endif
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- All Repositories
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_categories' )}">Browse by category</a>
- </div>
- %if trans.user:
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- My Repositories and Tools
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='repositories_i_own' )}">Repositories I own</a>
- </div>
- %if has_reviewed_repositories:
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='reviewed_repositories_i_own' )}">Reviewed repositories I own</a>
- </div>
- %endif
- %if has_deprecated_repositories:
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='deprecated_repositories_i_own' )}">Deprecated repositories I own</a>
- </div>
- %endif
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='my_writable_repositories' )}">My writable repositories</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_invalid_tools', cntrller='repository' )}">My invalid tools</a>
- </div>
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Available Actions
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='create_repository' )}">Create new repository</a>
- </div>
- %if can_review_repositories:
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Reviewing Repositories
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- %if trans.user.repository_reviews:
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_reviewed_by_me' )}">Repositories reviewed by me</a>
- </div>
- %endif
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_with_reviews' )}">All reviewed repositories</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_without_reviews' )}">Repositories with no reviews</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_components' )}">Manage review components</a>
- </div>
- </div>
- </div>
- %endif
- %else:
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Available Actions
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='/user', action='login' )}">Login to create a repository</a>
- </div>
- %endif
- %endif
- </div>
- </div>
- </div>
-</%def>
-
-<%def name="center_panel()">
- <%
- if trans.app.config.require_login and not trans.user:
- center_url = h.url_for( controller='user', action='login', message=message, status=status )
- elif repository_id and changeset_revision:
- # Route in was a sharable url: /view/{owner}/{name}/{changeset_revision}.
- center_url = h.url_for( controller='repository', action='view_repository', id=repository_id, changeset_revision=changeset_revision, message=message, status=status )
- elif repository_id:
- # Route in was a sharable url: /view/{owner}/{name}.
- center_url = h.url_for( controller='repository', action='view_repository', id=repository_id, message=message, status=status )
- elif user_id:
- # Route in was a sharable url: /view/{owner}.
- center_url = h.url_for( controller='repository', action='browse_repositories', operation="repositories_by_user", user_id=user_id, message=message, status=status )
- else:
- center_url = h.url_for( controller='repository', action='browse_categories', message=message, status=status )
- %>
- <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe>
-</%def>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/message.mako
--- a/templates/webapps/community/message.mako
+++ /dev/null
@@ -1,1 +0,0 @@
-<%inherit file="../../message.mako"/>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/repository/browse_invalid_tools.mako
--- a/templates/webapps/community/repository/browse_invalid_tools.mako
+++ /dev/null
@@ -1,44 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- %if invalid_tools_dict:
- <div class="toolFormTitle">Invalid tools<i> - click the tool config file name to see why the tool is invalid</i></div>
- <div class="form-row">
- <table class="grid">
- <tr>
- <th>Tool config</th>
- <th>Repository name</th>
- <th>Repository owner</th>
- <th>Changeset revision</th>
- </tr>
- %for invalid_tool_config, repository_tup in invalid_tools_dict.items():
- <% repository_id, repository_name, repository_owner, changeset_revision = repository_tup %>
- <tr>
- <td>
- <a class="view-info" href="${h.url_for( controller='repository', action='load_invalid_tool', repository_id=trans.security.encode_id( repository_id ), tool_config=invalid_tool_config, changeset_revision=changeset_revision )}">
- ${invalid_tool_config}
- </a>
- </td>
- <td>${repository_name | h}</td>
- <td>${repository_owner | h}</td>
- <td>${changeset_revision | h}</td>
- </tr>
- %endfor
- </table>
- </div>
- </div>
- %else:
- <div class="form-row">
- %if cntrller == 'admin' and trans.user_is_admin():
- No repositories in this tool shed contain invalid tools.
- %else:
- None of your repositories contain invalid tools.
- %endif
- </div>
- %endif
-</div>
diff -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 -r b985587c33926d8d38fa4456b51eecbc68953bb9 templates/webapps/community/repository/browse_repository.mako
--- a/templates/webapps/community/repository/browse_repository.mako
+++ /dev/null
@@ -1,156 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/community/common/common.mako" import="*" />
-<%namespace file="/webapps/community/repository/common.mako" import="*" />
-
-<%
- from galaxy.web.framework.helpers import time_ago
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_upload = can_push and ( not repository.deprecated )
- can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_rate = trans.user and repository.user != trans.user
- can_manage = is_admin or repository.user == trans.user
- can_view_change_log = not is_new
- has_readme = metadata and 'readme' in metadata
-%>
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "jquery.rating", "dynatree_skin/ui.dynatree" )}
- <style type="text/css">
- ul.fileBrowser,
- ul.toolFile {
- margin-left: 0;
- padding-left: 0;
- list-style: none;
- }
- ul.fileBrowser {
- margin-left: 20px;
- }
- .fileBrowser li,
- .toolFile li {
- padding-left: 20px;
- background-repeat: no-repeat;
- background-position: 0;
- min-height: 20px;
- }
- .toolFile li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} );
- }
- .fileBrowser li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} );
- }
- </style>
-</%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${h.js( "libs/jquery/jquery.rating", "libs/jquery/jquery-ui", "libs/jquery/jquery.cookie", "libs/jquery/jquery.dynatree" )}
- ${common_javascripts(repository)}
-</%def>
-
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-%if can_browse_contents:
- <div class="toolForm">
- <div class="toolFormTitle">Browse ${repository.name | h} revision ${repository.tip( trans.app ) | h} (repository tip)</div>
- %if can_download:
- <div class="form-row">
- <label>Clone this repository:</label>
- ${render_clone_str( repository )}
- </div>
- %endif
- %if can_push:
- <form name="select_files_to_delete" id="select_files_to_delete" action="${h.url_for( controller='repository', action='select_files_to_delete', id=trans.security.encode_id( repository.id ))}" method="post" >
- <div class="form-row" >
- <label>Contents:</label>
- <div id="tree" >
- Loading...
- </div>
- <div class="toolParamHelp" style="clear: both;">
- Click on a file to display it's contents below. You may delete files from the repository by clicking the check box next to each file and clicking the <b>Delete selected files</b> button.
- </div>
- <input id="selected_files_to_delete" name="selected_files_to_delete" type="hidden" value=""/>
- </div>
- <div class="form-row">
- <label>Message:</label>
- <div class="form-row-input">
- %if commit_message:
- <textarea name="commit_message" rows="3" cols="35">${commit_message | h}</textarea>
- %else:
- <textarea name="commit_message" rows="3" cols="35"></textarea>
- %endif
- </div>
- <div class="toolParamHelp" style="clear: both;">
- This is the commit message for the mercurial change set that will be created if you delete selected files.
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <input type="submit" name="select_files_to_delete_button" value="Delete selected files"/>
- </div>
- <div class="form-row">
- <div id="file_contents" class="toolParamHelp" style="clear: both;background-color:#FAFAFA;"></div>
- </div>
- </form>
- %else:
- <div class="toolFormBody">
- <div class="form-row" >
- <label>Contents:</label>
- <div id="tree" >
- Loading...
- </div>
- </div>
- <div class="form-row">
- <div id="file_contents" class="toolParamHelp" style="clear: both;background-color:#FAFAFA;"></div>
- </div>
- </div>
- %endif
- </div>
- <p/>
-%endif
This diff is so big that we needed to truncate the remainder.
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: inithello: Added name attribute to MigrateToolsApplication to generate a correct metadata dict for migrated tools.
by commits-noreply@bitbucket.org 26 Feb '13
by commits-noreply@bitbucket.org 26 Feb '13
26 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ddfdfd2fce3e/
changeset: ddfdfd2fce3e
user: inithello
date: 2013-02-26 22:59:17
summary: Added name attribute to MigrateToolsApplication to generate a correct metadata dict for migrated tools.
affected #: 1 file
diff -r b9a7f2ae70a830e7ad5ef2a4c7e24f43d4575fa1 -r ddfdfd2fce3ef42d50f4b7b5a02db1cad03c5663 lib/tool_shed/galaxy_install/migrate/common.py
--- a/lib/tool_shed/galaxy_install/migrate/common.py
+++ b/lib/tool_shed/galaxy_install/migrate/common.py
@@ -14,6 +14,7 @@
def __init__( self, tools_migration_config ):
install_dependencies = 'install_dependencies' in sys.argv
galaxy_config_file = 'universe_wsgi.ini'
+ self.name = 'galaxy'
if '-c' in sys.argv:
pos = sys.argv.index( '-c' )
sys.argv.pop( pos )
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
26 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b9a7f2ae70a8/
changeset: b9a7f2ae70a8
user: jgoecks
date: 2013-02-26 22:42:11
summary: Add missing import.
affected #: 1 file
diff -r 5d71d6193bbaf758ae901de19a601bce6c34aeca -r b9a7f2ae70a830e7ad5ef2a4c7e24f43d4575fa1 lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -6,6 +6,7 @@
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesVisualizationMixin
from galaxy.web.framework.helpers import time_ago, grids
from galaxy import util
+from galaxy.datatypes.interval import Bed
from galaxy.util.json import from_json_string
from galaxy.util.sanitize_html import sanitize_html
from galaxy.visualization.genomes import decode_dbkey
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: Force absolute imprts in Galaxy's app.
by commits-noreply@bitbucket.org 26 Feb '13
by commits-noreply@bitbucket.org 26 Feb '13
26 Feb '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5d71d6193bba/
changeset: 5d71d6193bba
user: greg
date: 2013-02-26 22:33:57
summary: Force absolute imprts in Galaxy's app.
affected #: 1 file
diff -r 6f0050c4e06ef6f5fdce3f7326280c07c63ef62e -r 5d71d6193bbaf758ae901de19a601bce6c34aeca lib/galaxy/app.py
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
import sys, os, atexit
from galaxy import config, jobs, util, tools, web
@@ -151,10 +152,10 @@
self.memdump = memdump.Memdump()
# Transfer manager client
if self.config.get_bool( 'enable_beta_job_managers', False ):
- from jobs import transfer_manager
+ from galaxy.jobs import transfer_manager
self.transfer_manager = transfer_manager.TransferManager( self )
# Start the job manager
- from jobs import manager
+ from galaxy.jobs import manager
self.job_manager = manager.JobManager( self )
# FIXME: These are exposed directly for backward compatibility
self.job_queue = self.job_manager.job_queue
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