galaxy-commits
Threads by month
- ----- 2026 -----
- October
- 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: dan: Add pipe (|) to the set of VALID_CHARS in shed_util_common.py. Fixes an issue with e.g. ReST display. TODO: Revisit this method and its usage throughout the toolshed and the toolshed interaction with Galaxy: e.g. is it still needed everywhere it is being used, and is it still doing what it is supposed to be doing?
by commits-noreply@bitbucket.org 28 Aug '13
by commits-noreply@bitbucket.org 28 Aug '13
28 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/29110e49c311/
Changeset: 29110e49c311
User: dan
Date: 2013-08-27 22:21:16
Summary: Add pipe (|) to the set of VALID_CHARS in shed_util_common.py. Fixes an issue with e.g. ReST display. TODO: Revisit this method and its usage throughout the toolshed and the toolshed interaction with Galaxy: e.g. is it still needed everywhere it is being used, and is it still doing what it is supposed to be doing?
Affected #: 1 file
diff -r f8b3dbe32435516af63e449cedb2e2fc9eb5bf26 -r 29110e49c311339c521525f0b0884ce8eb172129 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
@@ -37,7 +37,7 @@
INITIAL_CHANGELOG_HASH = '000000000000'
MAX_CONTENT_SIZE = 1048576
MAX_DISPLAY_SIZE = 32768
-VALID_CHARS = set( string.letters + string.digits + "'\"-=_.()/+*^,:?!#[]%\\$@;{}&<>" )
+VALID_CHARS = set( string.letters + string.digits + "'\"-=_.()/+*^,:?!#[]%\\$@;{}&<>|" )
DATATYPES_CONFIG_FILENAME = 'datatypes_conf.xml'
REPOSITORY_DATA_MANAGER_CONFIG_FILENAME = 'data_manager_conf.xml'
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Enhance the installed repositories container on the Manage repository page in Galaxy to properly display mising repositroy and tool dependencies for an installed repository.
by commits-noreply@bitbucket.org 28 Aug '13
by commits-noreply@bitbucket.org 28 Aug '13
28 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f8b3dbe32435/
Changeset: f8b3dbe32435
User: greg
Date: 2013-08-27 20:51:33
Summary: Enhance the installed repositories container on the Manage repository page in Galaxy to properly display mising repositroy and tool dependencies for an installed repository.
Affected #: 1 file
diff -r 6dfd50e1cfd1e2b9f356cb9e9319f85caf6a74f3 -r f8b3dbe32435516af63e449cedb2e2fc9eb5bf26 lib/tool_shed/util/container_util.py
--- a/lib/tool_shed/util/container_util.py
+++ b/lib/tool_shed/util/container_util.py
@@ -1265,6 +1265,35 @@
return get_folder( sub_folder, key )
return None
+def get_components_from_repository_dependency_for_installed_repository( trans, repository_dependency ):
+ """
+ Parse a repository dependency and return components necessary for proper display in Galaxy on the Manage repository page.
+ """
+ if len( repository_dependency ) == 6:
+ # Metadata should have been reset on this installed repository, but it wasn't.
+ tool_shed_repository_id = repository_dependency[ 4 ]
+ installation_status = repository_dependency[ 5 ]
+ tool_shed, name, owner, changeset_revision = repository_dependency[ 0:4 ]
+ # Default prior_installation_required to False.
+ prior_installation_required = False
+ repository_dependency = [ tool_shed, name, owner, changeset_revision, prior_installation_required ]
+ elif len( repository_dependency ) == 7:
+ # We have a repository dependency tuple that includes a prior_installation_required value.
+ tool_shed_repository_id = repository_dependency[ 5 ]
+ installation_status = repository_dependency[ 6 ]
+ repository_dependency = repository_dependency[ 0:5 ]
+ else:
+ tool_shed_repository_id = None
+ installation_status = 'unknown'
+ if tool_shed_repository_id:
+ tool_shed_repository = suc.get_tool_shed_repository_by_id( trans, trans.security.encode_id( tool_shed_repository_id ) )
+ if tool_shed_repository:
+ if tool_shed_repository.missing_repository_dependencies:
+ installation_status = '%s, missing repository dependencies' % installation_status
+ elif tool_shed_repository.missing_tool_dependencies:
+ installation_status = '%s, missing tool dependencies' % installation_status
+ return tool_shed_repository_id, installation_status, repository_dependency
+
def get_components_from_key( key ):
# FIXME: assumes tool shed is current tool shed since repository dependencies across tool sheds is not yet supported.
items = key.split( STRSEP )
@@ -1315,22 +1344,8 @@
sub_folder.repository_dependencies.append( repository_dependency )
for repository_dependency in rd_value:
if trans.webapp.name == 'galaxy':
- if len( repository_dependency ) == 6:
- # Metadata should have been reset on this installed repository, but it wasn't.
- tool_shed_repository_id = repository_dependency[ 4 ]
- installation_status = repository_dependency[ 5 ]
- tool_shed, name, owner, changeset_revision = repository_dependency[ 0:4 ]
- # Default prior_installation_required to False.
- prior_installation_required = False
- repository_dependency = [ tool_shed, name, owner, changeset_revision, prior_installation_required ]
- elif len( repository_dependency ) == 7:
- # We have a repository dependency tuple that includes a prior_installation_required value.
- tool_shed_repository_id = repository_dependency[ 5 ]
- installation_status = repository_dependency[ 6 ]
- repository_dependency = repository_dependency[ 0:5 ]
- else:
- tool_shed_repository_id = None
- installation_status = 'unknown'
+ tool_shed_repository_id, installation_status, repository_dependency = \
+ get_components_from_repository_dependency_for_installed_repository( trans, repository_dependency )
else:
tool_shed_repository_id = None
installation_status = None
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Correctly handle the case where a repository installs correctly, but it depends on a repository with a tool dependency that is in an error state.
by commits-noreply@bitbucket.org 27 Aug '13
by commits-noreply@bitbucket.org 27 Aug '13
27 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6dfd50e1cfd1/
Changeset: 6dfd50e1cfd1
User: Dave Bouvier
Date: 2013-08-27 19:50:30
Summary: Correctly handle the case where a repository installs correctly, but it depends on a repository with a tool dependency that is in an error state.
Affected #: 1 file
diff -r 6439459c265ea7748ff9a16706fa5af5cc224269 -r 6dfd50e1cfd1e2b9f356cb9e9319f85caf6a74f3 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
@@ -269,6 +269,14 @@
url += '&%s' % params
return url
+def get_failed_tool_dependencies( repository ):
+ missing_dependencies = repository.missing_tool_dependencies
+ for repository_dependency in repository.repository_dependencies:
+ if not repository_dependency.includes_tool_dependencies:
+ continue
+ missing_dependencies.extend( get_failed_tool_dependencies( repository_dependency ) )
+ return missing_dependencies
+
def get_latest_downloadable_changeset_revision( url, name, owner ):
api_url_parts = [ 'api', 'repositories', 'get_ordered_installable_revisions' ]
params = urllib.urlencode( dict( name=name, owner=owner ) )
@@ -459,7 +467,7 @@
Update the repository metadata tool_test_results and appropriate flags using the API.
'''
params[ 'tool_test_results' ] = test_results_dict
- if '-info_only' in sys.argv:
+ if '-info_only' in sys.argv or 'GALAXY_INSTALL_TEST_INFO_ONLY' in os.environ:
return {}
else:
return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
@@ -914,7 +922,7 @@
# "reason": "The Galaxy development team has determined that this repository should not be installed and tested by the automated framework."
# }
# }
- failed_tool_dependencies = repository.includes_tool_dependencies and repository.tool_dependencies_with_installation_errors
+ failed_tool_dependencies = get_failed_tool_dependencies( repository )
failed_repository_dependencies = repository.repository_dependencies_with_installation_errors
if 'missing_test_components' not in repository_status:
repository_status[ 'missing_test_components' ] = []
@@ -958,7 +966,7 @@
log.error( 'One or more tool dependencies of this repository are marked as missing.' )
log.error( 'Updating repository and skipping functional tests.' )
# In keeping with the standard display layout, add the error message to the dict for each tool individually.
- for dependency in repository.tool_dependencies_with_installation_errors:
+ for dependency in failed_tool_dependencies:
test_result = dict( type=dependency.type,
name=dependency.name,
version=dependency.version,
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: Send changeset_revision to method that renders the Repository Actions pop-up menu in the tool shed to ensure the desired repository revision is used when choosing actions.
by commits-noreply@bitbucket.org 27 Aug '13
by commits-noreply@bitbucket.org 27 Aug '13
27 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6439459c265e/
Changeset: 6439459c265e
User: greg
Date: 2013-08-27 19:24:37
Summary: Send changeset_revision to method that renders the Repository Actions pop-up menu in the tool shed to ensure the desired repository revision is used when choosing actions.
Affected #: 5 files
diff -r d7ea2536e8e370cd202f735351c37264270ddbaf -r 6439459c265ea7748ff9a16706fa5af5cc224269 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
@@ -664,10 +664,12 @@
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
# Update repository files for browsing.
suc.update_repository( repo )
- metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
+ changeset_revision = repository.tip( trans.app )
+ metadata = self.get_metadata( trans, id, changeset_revision )
repository_type_select_field = rt_util.build_repository_type_select_field( trans, repository=repository )
return trans.fill_template( '/webapps/tool_shed/repository/browse_repository.mako',
repository=repository,
+ changeset_revision=changeset_revision,
metadata=metadata,
commit_message=commit_message,
repository_type_select_field=repository_type_select_field,
@@ -1102,6 +1104,7 @@
repositories_archive_filename = os.path.basename( repositories_archive.name )
if error_message:
message = error_message
+ status = 'error'
else:
trans.response.set_content_type( 'application/x-gzip' )
trans.response.headers[ "Content-Disposition" ] = 'attachment; filename="%s"' % ( repositories_archive_filename )
@@ -1109,9 +1112,7 @@
# Make sure the file is removed from disk after the contents have been downloaded.
os.unlink( repositories_archive.name )
return opened_archive
- repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
- trans.security.encode_id( repository.id ),
- changeset_revision )
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
metadata = repository_metadata.metadata
# Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
repository_dependencies = \
@@ -1822,6 +1823,10 @@
return trans.fill_template( '/webapps/tool_shed/repository/help.mako', message=message, status=status, **kwd )
@web.expose
+ def import_capsule( self, trans, **kwd ):
+ pass
+
+ @web.expose
def index( self, trans, **kwd ):
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
@@ -2449,9 +2454,11 @@
message = "Select at least 1 file to delete from the repository before clicking <b>Delete selected files</b>."
status = "error"
repository_type_select_field = rt_util.build_repository_type_select_field( trans, repository=repository )
+ changeset_revision = repository.tip( trans.app )
return trans.fill_template( '/webapps/tool_shed/repository/browse_repository.mako',
repo=repo,
repository=repository,
+ changeset_revision=changeset_revision,
commit_message=commit_message,
repository_type_select_field=repository_type_select_field,
message=message,
diff -r d7ea2536e8e370cd202f735351c37264270ddbaf -r 6439459c265ea7748ff9a16706fa5af5cc224269 lib/galaxy/webapps/tool_shed/controllers/upload.py
--- a/lib/galaxy/webapps/tool_shed/controllers/upload.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py
@@ -241,6 +241,7 @@
selected_categories = [ trans.security.decode_id( id ) for id in category_ids ]
return trans.fill_template( '/webapps/tool_shed/repository/upload.mako',
repository=repository,
+ changeset_revision=tip,
url=url,
commit_message=commit_message,
uncompress_file=uncompress_file,
diff -r d7ea2536e8e370cd202f735351c37264270ddbaf -r 6439459c265ea7748ff9a16706fa5af5cc224269 templates/webapps/tool_shed/index.mako
--- a/templates/webapps/tool_shed/index.mako
+++ b/templates/webapps/tool_shed/index.mako
@@ -147,6 +147,9 @@
<div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='create_repository' )}">Create new repository</a></div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='import_capsule' )}">Import repository capsule</a>
+ </div>
%if can_review_repositories:
<div class="toolSectionPad"></div><div class="toolSectionTitle">
diff -r d7ea2536e8e370cd202f735351c37264270ddbaf -r 6439459c265ea7748ff9a16706fa5af5cc224269 templates/webapps/tool_shed/repository/browse_repository.mako
--- a/templates/webapps/tool_shed/repository/browse_repository.mako
+++ b/templates/webapps/tool_shed/repository/browse_repository.mako
@@ -31,7 +31,7 @@
can_browse_contents = not is_new
%>
-${render_tool_shed_repository_actions( repository )}
+${render_tool_shed_repository_actions( repository, changeset_revision=changeset_revision )}
%if message:
${render_msg( message, status )}
diff -r d7ea2536e8e370cd202f735351c37264270ddbaf -r 6439459c265ea7748ff9a16706fa5af5cc224269 templates/webapps/tool_shed/repository/rate_repository.mako
--- a/templates/webapps/tool_shed/repository/rate_repository.mako
+++ b/templates/webapps/tool_shed/repository/rate_repository.mako
@@ -33,7 +33,7 @@
${render_msg( message, status )}
%endif
-${render_tool_shed_repository_actions( repository, repo=None, metadata=None, changeset_revision=None )}
+${render_tool_shed_repository_actions( repository, metadata=None, changeset_revision=None )}
%if repository.user != trans.user:
<div class="toolForm">
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/19c4ec5b8faf/
Changeset: 19c4ec5b8faf
User: jgoecks
Date: 2013-08-26 23:36:50
Summary: Use Galaxy root to dynamically load CSS files.
Affected #: 3 files
diff -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f -r 19c4ec5b8fafbf9095b102d4c59c6a59f125a8a1 static/scripts/galaxy.frame.js
--- a/static/scripts/galaxy.frame.js
+++ b/static/scripts/galaxy.frame.js
@@ -74,7 +74,7 @@
initialize : function(options)
{
// load required css files
- css.load_file(options.root + "static/style/galaxy.frame.css");
+ css.load_file("static/style/galaxy.frame.css");
// read in defaults
if (options)
diff -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f -r 19c4ec5b8fafbf9095b102d4c59c6a59f125a8a1 static/scripts/utils/galaxy.css.js
--- a/static/scripts/utils/galaxy.css.js
+++ b/static/scripts/utils/galaxy.css.js
@@ -29,7 +29,7 @@
{
// check if css is already available
if (!$('link[href^="' + url + '"]').length)
- $('<link href="' + url + '" rel="stylesheet">').appendTo('head');
+ $('<link href="' + galaxy_config.root + url + '" rel="stylesheet">').appendTo('head');
};
// return
diff -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f -r 19c4ec5b8fafbf9095b102d4c59c6a59f125a8a1 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -21,12 +21,12 @@
], function(css)
{
// load css
- css.load_file("/static/style/jquery.rating.css");
- css.load_file("/static/style/history.css");
- css.load_file("/static/style/autocomplete_tagging.css");
- css.load_file("/static/style/jquery-ui/smoothness/jquery-ui.css");
- css.load_file("/static/style/library.css");
- css.load_file("/static/style/trackster.css");
+ css.load_file("static/style/jquery.rating.css");
+ css.load_file("static/style/history.css");
+ css.load_file("static/style/autocomplete_tagging.css");
+ css.load_file("static/style/jquery-ui/smoothness/jquery-ui.css");
+ css.load_file("static/style/library.css");
+ css.load_file("static/style/trackster.css");
});
// trackster viewer
https://bitbucket.org/galaxy/galaxy-central/commits/d7ea2536e8e3/
Changeset: d7ea2536e8e3
User: jgoecks
Date: 2013-08-26 23:38:00
Summary: Pack scripts.
Affected #: 3 files
diff -r 19c4ec5b8fafbf9095b102d4c59c6a59f125a8a1 -r d7ea2536e8e370cd202f735351c37264270ddbaf static/scripts/packed/galaxy.frame.js
--- a/static/scripts/packed/galaxy.frame.js
+++ b/static/scripts/packed/galaxy.frame.js
@@ -1,1 +1,1 @@
-define(["utils/galaxy.css","libs/backbone/backbone-relational"],function(b){var a=Backbone.View.extend({el:"#everything",el_header:"#masthead",options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:10},cols:0,top:0,top_max:0,frame_counter:0,frame_counter_id:0,frame_list:[],galaxy_frame_shadow:null,visible:false,active:false,initialize:function(d){b.load_file(d.root+"static/style/galaxy.frame.css");if(d){this.options=_.defaults(d,this.options)}this.top=this.top_max=this.options.top_min;$(this.el).append(this.frame_template_background());$(this.el).append(this.frame_template_menu());$(this.el_header).append(this.frame_template_header());var e="#galaxy-frame-shadow";$(this.el).append(this.frame_template_shadow(e.substring(1)));this.galaxy_frame_shadow={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this.frame_resize(this.galaxy_frame_shadow,{width:0,height:0});this.frame_list[e]=this.galaxy_frame_shadow;this.panel_refresh();this.event_initialize();$(".galaxy-frame-active").tooltip({title:"Enable/Disable Scratchbook"});$(".galaxy-frame-load").tooltip({title:"Show/Hide Scratchbook"});var c=this;$(window).resize(function(){c.panel_refresh()});window.onbeforeunload=function(){if(c.frame_counter>0){return"You opened "+c.frame_counter+" frame(s) which will be lost."}}},is_mobile:function(){return navigator.userAgent.match(/mobile|(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i)},event:{type:null,target:null,xy:null},event_initialize:function(){this.events={mousemove:"event_frame_mouse_move",mouseup:"event_frame_mouse_up",mouseleave:"event_frame_mouse_up",mousewheel:"event_panel_scroll",DOMMouseScroll:"event_panel_scroll","mousedown .galaxy-frame":"event_frame_mouse_down","mousedown .galaxy-frame-active":"event_panel_active","mousedown .galaxy-frame-load":"event_panel_load","mousedown .galaxy-frame-background":"event_panel_load","mousedown .galaxy-frame-scroll-up":"event_panel_scroll_up","mousedown .galaxy-frame-scroll-down":"event_panel_scroll_down","mousedown .f-close":"event_frame_close","mousedown .f-pin":"event_frame_lock"};this.delegateEvents(this.events)},event_frame_mouse_down:function(c){if(this.event.type!==null){return}if($(c.target).hasClass("f-header")||$(c.target).hasClass("f-title")){this.event.type="drag"}if($(c.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}c.preventDefault();this.event.target=this.event_get_frame(c.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:c.originalEvent.pageX,y:c.originalEvent.pageY};this.frame_drag_start(this.event.target)},event_frame_mouse_move:function(i){if(this.event.type!="drag"&&this.event.type!="resize"){return}var g={x:i.originalEvent.pageX,y:i.originalEvent.pageY};var d={x:g.x-this.event.xy.x,y:g.y-this.event.xy.y};this.event.xy=g;var h=this.frame_screen(this.event.target);if(this.event.type=="resize"){h.width+=d.x;h.height+=d.y;var f=this.options.cell-this.options.margin-1;h.width=Math.max(h.width,f);h.height=Math.max(h.height,f);this.frame_resize(this.event.target,h);h.width=this.to_grid_coord("width",h.width)+1;h.height=this.to_grid_coord("height",h.height)+1;h.width=this.to_pixel_coord("width",h.width);h.height=this.to_pixel_coord("height",h.height);this.frame_resize(this.galaxy_frame_shadow,h);this.frame_insert(this.galaxy_frame_shadow,{top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)})}if(this.event.type=="drag"){h.left+=d.x;h.top+=d.y;this.frame_offset(this.event.target,h);var c={top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)};if(c.left!==0){c.left++}this.frame_insert(this.galaxy_frame_shadow,c)}},event_frame_mouse_up:function(c){if(this.event.type!="drag"&&this.event.type!="resize"){return}this.frame_drag_stop(this.event.target);this.event.type=null},event_frame_close:function(d){if(this.event.type!==null){return}d.preventDefault();var f=this.event_get_frame(d.target);var c=this;$(f.id).fadeOut("fast",function(){$(f.id).remove();delete c.frame_list[f.id];c.frame_counter--;c.panel_refresh(true);c.panel_animation_complete();if(c.visible&&c.frame_counter==0){c.panel_show_hide()}})},event_frame_lock:function(c){if(this.event.type!==null){return}c.preventDefault();var d=this.event_get_frame(c.target);if(d.grid_lock){d.grid_lock=false;$(d.id).find(".f-pin").removeClass("f-toggle");$(d.id).find(".f-header").removeClass("f-not-allowed");$(d.id).find(".f-title").removeClass("f-not-allowed");$(d.id).find(".f-resize").show();$(d.id).find(".f-close").show()}else{d.grid_lock=true;$(d.id).find(".f-pin").addClass("f-toggle");$(d.id).find(".f-header").addClass("f-not-allowed");$(d.id).find(".f-title").addClass("f-not-allowed");$(d.id).find(".f-resize").hide();$(d.id).find(".f-close").hide()}},event_panel_load:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_show_hide()},event_panel_active:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_active_disable()},event_panel_scroll:function(c){if(this.event.type!==null||!this.visible){return}c.preventDefault();var d=c.originalEvent.detail?c.originalEvent.detail:c.originalEvent.wheelDelta/-3;this.panel_scroll(d)},event_panel_scroll_up:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(-this.options.scroll)},event_panel_scroll_down:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(this.options.scroll)},event_get_frame:function(c){return this.frame_list["#"+$(c).closest(".galaxy-frame").attr("id")]},frame_drag_start:function(d){this.frame_focus(d,true);var c=this.frame_screen(d);this.frame_resize(this.galaxy_frame_shadow,c);this.frame_grid(this.galaxy_frame_shadow,d.grid_location);d.grid_location=null;$(this.galaxy_frame_shadow.id).show();$(".f-cover").show()},frame_drag_stop:function(d){this.frame_focus(d,false);var c=this.frame_screen(this.galaxy_frame_shadow);this.frame_resize(d,c);this.frame_grid(d,this.galaxy_frame_shadow.grid_location,true);this.galaxy_frame_shadow.grid_location=null;$(this.galaxy_frame_shadow.id).hide();$(".f-cover").hide();this.panel_animation_complete()},to_grid_coord:function(e,d){var c=(e=="width"||e=="height")?1:-1;if(e=="top"){d-=this.top}return parseInt((d+c*this.options.margin)/this.options.cell,10)},to_pixel_coord:function(e,f){var c=(e=="width"||e=="height")?1:-1;var d=(f*this.options.cell)-c*this.options.margin;if(e=="top"){d+=this.top}return d},to_grid:function(c){return{top:this.to_grid_coord("top",c.top),left:this.to_grid_coord("left",c.left),width:this.to_grid_coord("width",c.width),height:this.to_grid_coord("height",c.height)}},to_pixel:function(c){return{top:this.to_pixel_coord("top",c.top),left:this.to_pixel_coord("left",c.left),width:this.to_pixel_coord("width",c.width),height:this.to_pixel_coord("height",c.height)}},is_collision:function(e){function c(h,g){return !(h.left>g.left+g.width-1||h.left+h.width-1<g.left||h.top>g.top+g.height-1||h.top+h.height-1<g.top)}for(var d in this.frame_list){var f=this.frame_list[d];if(f.grid_location===null){continue}if(c(e,f.grid_location)){return true}}return false},location_rank:function(c){return(c.top*this.cols)+c.left},menu_refresh:function(){$(".galaxy-frame-load .number").text(this.frame_counter);if(this.frame_counter==0){$(".galaxy-frame-load").hide()}else{$(".galaxy-frame-load").show()}if(this.top==this.options.top_min){$(".galaxy-frame-scroll-up").hide()}else{$(".galaxy-frame-scroll-up").show()}if(this.top==this.top_max){$(".galaxy-frame-scroll-down").hide()}else{$(".galaxy-frame-scroll-down").show()}},panel_animation_complete:function(){var c=this;$(".galaxy-frame").promise().done(function(){c.panel_scroll(0,true)})},panel_refresh:function(c){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this.frame_insert(null,null,c)},panel_scroll:function(h,c){var e=this.top-this.options.scroll*h;e=Math.max(e,this.top_max);e=Math.min(e,this.options.top_min);if(this.top!=e){for(var d in this.frame_list){var g=this.frame_list[d];if(g.grid_location!==null){var f={top:g.screen_location.top-(this.top-e),left:g.screen_location.left};this.frame_offset(g,f,c)}}this.top=e}this.menu_refresh()},panel_show_hide:function(){if(this.visible){this.visible=false;$(".galaxy-frame").fadeOut("fast");$(".galaxy-frame-load .icon").addClass("fa-icon-eye-close");$(".galaxy-frame-load .icon").removeClass("fa-icon-eye-open");$(".galaxy-frame-background").hide();$(".galaxy-frame-menu").hide()}else{this.visible=true;$(".galaxy-frame").fadeIn("fast");$(".galaxy-frame-load .icon").addClass("fa-icon-eye-open");$(".galaxy-frame-load .icon").removeClass("fa-icon-eye-close");$(this.galaxy_frame_shadow.id).hide();$(".galaxy-frame-background").show();this.menu_refresh()}},panel_active_disable:function(){if(this.active){this.active=false;$(".galaxy-frame-active .icon").removeClass("f-toggle");if(this.visible){this.panel_show_hide()}}else{this.active=true;$(".galaxy-frame-active .icon").addClass("f-toggle")}},frame_new:function(d){if(!this.active){if(d.location=="center"){var c=$(window.parent.document).find("iframe#galaxy_main");c.attr("src",d.content)}else{window.location=d.content}return}if(this.frame_counter>this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var e="#galaxy-frame-"+(this.frame_counter_id++);if($(e).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;$(this.el).append(this.frame_template(e.substring(1),d.title,d.type,d.content));var f={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};d.width=this.to_pixel_coord("width",this.options.frame.cols);d.height=this.to_pixel_coord("height",this.options.frame.rows);this.frame_list[e]=f;this.frame_counter++;this.frame_resize(f,{width:d.width,height:d.height});this.frame_insert(f,{top:0,left:0},true);if(!this.visible){this.panel_show_hide()}},frame_insert:function(j,c,e){var d=[];if(j){j.grid_location=null;d.push([j,this.location_rank(c)])}var g=null;for(g in this.frame_list){var h=this.frame_list[g];if(h.grid_location!==null&&!h.grid_lock){h.grid_location=null;d.push([h,h.grid_rank])}}d.sort(function(k,f){var m=k[1];var l=f[1];return m<l?-1:(m>l?1:0)});for(g=0;g<d.length;g++){this.frame_place(d[g][0],e)}this.top_max=0;for(var g in this.frame_list){var j=this.frame_list[g];if(j.grid_location!==null){this.top_max=Math.max(this.top_max,j.grid_location.top+j.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this.menu_refresh()},frame_place:function(k,d){k.grid_location=null;var h=this.to_grid(this.frame_screen(k));var c=false;for(var f=0;f<this.options.rows;f++){for(var e=0;e<Math.max(1,this.cols-h.width);e++){h.top=f;h.left=e;if(!this.is_collision(h)){c=true;break}}if(c){break}}if(c){this.frame_grid(k,h,d)}else{console.log("Grid dimensions exceeded.")}},frame_focus:function(e,c){var d=parseInt(b.get_attribute("galaxy-frame","z-index"))+(c?1:0);$(e.id).css("z-index",d)},frame_offset:function(f,e,d){f.screen_location.left=e.left;f.screen_location.top=e.top;if(d){this.frame_focus(f,true);var c=this;$(f.id).animate({top:e.top,left:e.left},"fast",function(){c.frame_focus(f,false)})}else{$(f.id).css({top:e.top,left:e.left})}},frame_resize:function(d,c){$(d.id).css({width:c.width,height:c.height});d.screen_location.width=c.width;d.screen_location.height=c.height},frame_grid:function(e,c,d){e.grid_location=c;this.frame_offset(e,this.to_pixel(c),d);e.grid_rank=this.location_rank(c)},frame_screen:function(d){var c=d.screen_location;return{top:c.top,left:c.left,width:c.width,height:c.height}},frame_template:function(f,e,c,d){if(!e){e=""}if(c=="url"){d='<iframe scrolling="auto" class="f-iframe" src="'+d+'"></iframe>'}return'<div id="'+f+'" class="galaxy-frame f-corner"><div class="f-header f-corner"><span class="f-title">'+e+'</span><span class="f-icon f-pin fa-icon-pushpin"></span><span class="f-icon f-close fa-icon-trash"></span></div><div class="f-content f-corner">'+d+'<div class="f-cover"></div></div><span class="f-resize f-icon f-corner fa-icon-resize-full"></span></div>'},frame_template_shadow:function(c){return'<div id="'+c+'" class="galaxy-frame-shadow f-corner"></div>'},frame_template_background:function(){return'<div class="galaxy-frame-background"></div>'},frame_template_header:function(){return'<div class="galaxy-frame-load f-corner"><div class="number f-corner">0</div><div class="icon fa-icon-2x"></div></div><div class="galaxy-frame-active f-corner" style="position: absolute; top: 8px;"><div class="icon fa-icon-2x fa-icon-th"></div></div>'},frame_template_menu:function(){return'<div class="galaxy-frame-scroll-up galaxy-frame-menu fa-icon-chevron-up fa-icon-2x"></div><div class="galaxy-frame-scroll-down galaxy-frame-menu fa-icon-chevron-down fa-icon-2x"></div>'}});return{GalaxyFrameManager:a}});
\ No newline at end of file
+define(["utils/galaxy.css","libs/backbone/backbone-relational"],function(b){var a=Backbone.View.extend({el:"#everything",el_header:"#masthead",options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:10},cols:0,top:0,top_max:0,frame_counter:0,frame_counter_id:0,frame_list:[],galaxy_frame_shadow:null,visible:false,active:false,initialize:function(d){b.load_file("static/style/galaxy.frame.css");if(d){this.options=_.defaults(d,this.options)}this.top=this.top_max=this.options.top_min;$(this.el).append(this.frame_template_background());$(this.el).append(this.frame_template_menu());$(this.el_header).append(this.frame_template_header());var e="#galaxy-frame-shadow";$(this.el).append(this.frame_template_shadow(e.substring(1)));this.galaxy_frame_shadow={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this.frame_resize(this.galaxy_frame_shadow,{width:0,height:0});this.frame_list[e]=this.galaxy_frame_shadow;this.panel_refresh();this.event_initialize();$(".galaxy-frame-active").tooltip({title:"Enable/Disable Scratchbook"});$(".galaxy-frame-load").tooltip({title:"Show/Hide Scratchbook"});var c=this;$(window).resize(function(){c.panel_refresh()});window.onbeforeunload=function(){if(c.frame_counter>0){return"You opened "+c.frame_counter+" frame(s) which will be lost."}}},is_mobile:function(){return navigator.userAgent.match(/mobile|(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i)},event:{type:null,target:null,xy:null},event_initialize:function(){this.events={mousemove:"event_frame_mouse_move",mouseup:"event_frame_mouse_up",mouseleave:"event_frame_mouse_up",mousewheel:"event_panel_scroll",DOMMouseScroll:"event_panel_scroll","mousedown .galaxy-frame":"event_frame_mouse_down","mousedown .galaxy-frame-active":"event_panel_active","mousedown .galaxy-frame-load":"event_panel_load","mousedown .galaxy-frame-background":"event_panel_load","mousedown .galaxy-frame-scroll-up":"event_panel_scroll_up","mousedown .galaxy-frame-scroll-down":"event_panel_scroll_down","mousedown .f-close":"event_frame_close","mousedown .f-pin":"event_frame_lock"};this.delegateEvents(this.events)},event_frame_mouse_down:function(c){if(this.event.type!==null){return}if($(c.target).hasClass("f-header")||$(c.target).hasClass("f-title")){this.event.type="drag"}if($(c.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}c.preventDefault();this.event.target=this.event_get_frame(c.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:c.originalEvent.pageX,y:c.originalEvent.pageY};this.frame_drag_start(this.event.target)},event_frame_mouse_move:function(i){if(this.event.type!="drag"&&this.event.type!="resize"){return}var g={x:i.originalEvent.pageX,y:i.originalEvent.pageY};var d={x:g.x-this.event.xy.x,y:g.y-this.event.xy.y};this.event.xy=g;var h=this.frame_screen(this.event.target);if(this.event.type=="resize"){h.width+=d.x;h.height+=d.y;var f=this.options.cell-this.options.margin-1;h.width=Math.max(h.width,f);h.height=Math.max(h.height,f);this.frame_resize(this.event.target,h);h.width=this.to_grid_coord("width",h.width)+1;h.height=this.to_grid_coord("height",h.height)+1;h.width=this.to_pixel_coord("width",h.width);h.height=this.to_pixel_coord("height",h.height);this.frame_resize(this.galaxy_frame_shadow,h);this.frame_insert(this.galaxy_frame_shadow,{top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)})}if(this.event.type=="drag"){h.left+=d.x;h.top+=d.y;this.frame_offset(this.event.target,h);var c={top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)};if(c.left!==0){c.left++}this.frame_insert(this.galaxy_frame_shadow,c)}},event_frame_mouse_up:function(c){if(this.event.type!="drag"&&this.event.type!="resize"){return}this.frame_drag_stop(this.event.target);this.event.type=null},event_frame_close:function(d){if(this.event.type!==null){return}d.preventDefault();var f=this.event_get_frame(d.target);var c=this;$(f.id).fadeOut("fast",function(){$(f.id).remove();delete c.frame_list[f.id];c.frame_counter--;c.panel_refresh(true);c.panel_animation_complete();if(c.visible&&c.frame_counter==0){c.panel_show_hide()}})},event_frame_lock:function(c){if(this.event.type!==null){return}c.preventDefault();var d=this.event_get_frame(c.target);if(d.grid_lock){d.grid_lock=false;$(d.id).find(".f-pin").removeClass("f-toggle");$(d.id).find(".f-header").removeClass("f-not-allowed");$(d.id).find(".f-title").removeClass("f-not-allowed");$(d.id).find(".f-resize").show();$(d.id).find(".f-close").show()}else{d.grid_lock=true;$(d.id).find(".f-pin").addClass("f-toggle");$(d.id).find(".f-header").addClass("f-not-allowed");$(d.id).find(".f-title").addClass("f-not-allowed");$(d.id).find(".f-resize").hide();$(d.id).find(".f-close").hide()}},event_panel_load:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_show_hide()},event_panel_active:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_active_disable()},event_panel_scroll:function(c){if(this.event.type!==null||!this.visible){return}c.preventDefault();var d=c.originalEvent.detail?c.originalEvent.detail:c.originalEvent.wheelDelta/-3;this.panel_scroll(d)},event_panel_scroll_up:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(-this.options.scroll)},event_panel_scroll_down:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(this.options.scroll)},event_get_frame:function(c){return this.frame_list["#"+$(c).closest(".galaxy-frame").attr("id")]},frame_drag_start:function(d){this.frame_focus(d,true);var c=this.frame_screen(d);this.frame_resize(this.galaxy_frame_shadow,c);this.frame_grid(this.galaxy_frame_shadow,d.grid_location);d.grid_location=null;$(this.galaxy_frame_shadow.id).show();$(".f-cover").show()},frame_drag_stop:function(d){this.frame_focus(d,false);var c=this.frame_screen(this.galaxy_frame_shadow);this.frame_resize(d,c);this.frame_grid(d,this.galaxy_frame_shadow.grid_location,true);this.galaxy_frame_shadow.grid_location=null;$(this.galaxy_frame_shadow.id).hide();$(".f-cover").hide();this.panel_animation_complete()},to_grid_coord:function(e,d){var c=(e=="width"||e=="height")?1:-1;if(e=="top"){d-=this.top}return parseInt((d+c*this.options.margin)/this.options.cell,10)},to_pixel_coord:function(e,f){var c=(e=="width"||e=="height")?1:-1;var d=(f*this.options.cell)-c*this.options.margin;if(e=="top"){d+=this.top}return d},to_grid:function(c){return{top:this.to_grid_coord("top",c.top),left:this.to_grid_coord("left",c.left),width:this.to_grid_coord("width",c.width),height:this.to_grid_coord("height",c.height)}},to_pixel:function(c){return{top:this.to_pixel_coord("top",c.top),left:this.to_pixel_coord("left",c.left),width:this.to_pixel_coord("width",c.width),height:this.to_pixel_coord("height",c.height)}},is_collision:function(e){function c(h,g){return !(h.left>g.left+g.width-1||h.left+h.width-1<g.left||h.top>g.top+g.height-1||h.top+h.height-1<g.top)}for(var d in this.frame_list){var f=this.frame_list[d];if(f.grid_location===null){continue}if(c(e,f.grid_location)){return true}}return false},location_rank:function(c){return(c.top*this.cols)+c.left},menu_refresh:function(){$(".galaxy-frame-load .number").text(this.frame_counter);if(this.frame_counter==0){$(".galaxy-frame-load").hide()}else{$(".galaxy-frame-load").show()}if(this.top==this.options.top_min){$(".galaxy-frame-scroll-up").hide()}else{$(".galaxy-frame-scroll-up").show()}if(this.top==this.top_max){$(".galaxy-frame-scroll-down").hide()}else{$(".galaxy-frame-scroll-down").show()}},panel_animation_complete:function(){var c=this;$(".galaxy-frame").promise().done(function(){c.panel_scroll(0,true)})},panel_refresh:function(c){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this.frame_insert(null,null,c)},panel_scroll:function(h,c){var e=this.top-this.options.scroll*h;e=Math.max(e,this.top_max);e=Math.min(e,this.options.top_min);if(this.top!=e){for(var d in this.frame_list){var g=this.frame_list[d];if(g.grid_location!==null){var f={top:g.screen_location.top-(this.top-e),left:g.screen_location.left};this.frame_offset(g,f,c)}}this.top=e}this.menu_refresh()},panel_show_hide:function(){if(this.visible){this.visible=false;$(".galaxy-frame").fadeOut("fast");$(".galaxy-frame-load .icon").addClass("fa-icon-eye-close");$(".galaxy-frame-load .icon").removeClass("fa-icon-eye-open");$(".galaxy-frame-background").hide();$(".galaxy-frame-menu").hide()}else{this.visible=true;$(".galaxy-frame").fadeIn("fast");$(".galaxy-frame-load .icon").addClass("fa-icon-eye-open");$(".galaxy-frame-load .icon").removeClass("fa-icon-eye-close");$(this.galaxy_frame_shadow.id).hide();$(".galaxy-frame-background").show();this.menu_refresh()}},panel_active_disable:function(){if(this.active){this.active=false;$(".galaxy-frame-active .icon").removeClass("f-toggle");if(this.visible){this.panel_show_hide()}}else{this.active=true;$(".galaxy-frame-active .icon").addClass("f-toggle")}},frame_new:function(d){if(!this.active){if(d.location=="center"){var c=$(window.parent.document).find("iframe#galaxy_main");c.attr("src",d.content)}else{window.location=d.content}return}if(this.frame_counter>this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var e="#galaxy-frame-"+(this.frame_counter_id++);if($(e).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;$(this.el).append(this.frame_template(e.substring(1),d.title,d.type,d.content));var f={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};d.width=this.to_pixel_coord("width",this.options.frame.cols);d.height=this.to_pixel_coord("height",this.options.frame.rows);this.frame_list[e]=f;this.frame_counter++;this.frame_resize(f,{width:d.width,height:d.height});this.frame_insert(f,{top:0,left:0},true);if(!this.visible){this.panel_show_hide()}},frame_insert:function(j,c,e){var d=[];if(j){j.grid_location=null;d.push([j,this.location_rank(c)])}var g=null;for(g in this.frame_list){var h=this.frame_list[g];if(h.grid_location!==null&&!h.grid_lock){h.grid_location=null;d.push([h,h.grid_rank])}}d.sort(function(k,f){var m=k[1];var l=f[1];return m<l?-1:(m>l?1:0)});for(g=0;g<d.length;g++){this.frame_place(d[g][0],e)}this.top_max=0;for(var g in this.frame_list){var j=this.frame_list[g];if(j.grid_location!==null){this.top_max=Math.max(this.top_max,j.grid_location.top+j.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this.menu_refresh()},frame_place:function(k,d){k.grid_location=null;var h=this.to_grid(this.frame_screen(k));var c=false;for(var f=0;f<this.options.rows;f++){for(var e=0;e<Math.max(1,this.cols-h.width);e++){h.top=f;h.left=e;if(!this.is_collision(h)){c=true;break}}if(c){break}}if(c){this.frame_grid(k,h,d)}else{console.log("Grid dimensions exceeded.")}},frame_focus:function(e,c){var d=parseInt(b.get_attribute("galaxy-frame","z-index"))+(c?1:0);$(e.id).css("z-index",d)},frame_offset:function(f,e,d){f.screen_location.left=e.left;f.screen_location.top=e.top;if(d){this.frame_focus(f,true);var c=this;$(f.id).animate({top:e.top,left:e.left},"fast",function(){c.frame_focus(f,false)})}else{$(f.id).css({top:e.top,left:e.left})}},frame_resize:function(d,c){$(d.id).css({width:c.width,height:c.height});d.screen_location.width=c.width;d.screen_location.height=c.height},frame_grid:function(e,c,d){e.grid_location=c;this.frame_offset(e,this.to_pixel(c),d);e.grid_rank=this.location_rank(c)},frame_screen:function(d){var c=d.screen_location;return{top:c.top,left:c.left,width:c.width,height:c.height}},frame_template:function(f,e,c,d){if(!e){e=""}if(c=="url"){d='<iframe scrolling="auto" class="f-iframe" src="'+d+'"></iframe>'}return'<div id="'+f+'" class="galaxy-frame f-corner"><div class="f-header f-corner"><span class="f-title">'+e+'</span><span class="f-icon f-pin fa-icon-pushpin"></span><span class="f-icon f-close fa-icon-trash"></span></div><div class="f-content f-corner">'+d+'<div class="f-cover"></div></div><span class="f-resize f-icon f-corner fa-icon-resize-full"></span></div>'},frame_template_shadow:function(c){return'<div id="'+c+'" class="galaxy-frame-shadow f-corner"></div>'},frame_template_background:function(){return'<div class="galaxy-frame-background"></div>'},frame_template_header:function(){return'<div class="galaxy-frame-load f-corner"><div class="number f-corner">0</div><div class="icon fa-icon-2x"></div></div><div class="galaxy-frame-active f-corner" style="position: absolute; top: 8px;"><div class="icon fa-icon-2x fa-icon-th"></div></div>'},frame_template_menu:function(){return'<div class="galaxy-frame-scroll-up galaxy-frame-menu fa-icon-chevron-up fa-icon-2x"></div><div class="galaxy-frame-scroll-down galaxy-frame-menu fa-icon-chevron-down fa-icon-2x"></div>'}});return{GalaxyFrameManager:a}});
\ No newline at end of file
diff -r 19c4ec5b8fafbf9095b102d4c59c6a59f125a8a1 -r d7ea2536e8e370cd202f735351c37264270ddbaf static/scripts/packed/utils/galaxy.css.js
--- a/static/scripts/packed/utils/galaxy.css.js
+++ b/static/scripts/packed/utils/galaxy.css.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(a){function b(g,d){var e=$('<div class="'+g+'"></div>');e.appendTo(":eq(0)");var f=e.css(d);e.remove();return f}function c(d){if(!$('link[href^="'+d+'"]').length){$('<link href="'+d+'" rel="stylesheet">').appendTo("head")}}return{load_file:c,get_attribute:b}});
\ No newline at end of file
+define(["libs/underscore"],function(a){function b(g,d){var e=$('<div class="'+g+'"></div>');e.appendTo(":eq(0)");var f=e.css(d);e.remove();return f}function c(d){if(!$('link[href^="'+d+'"]').length){$('<link href="'+galaxy_config.root+d+'" rel="stylesheet">').appendTo("head")}}return{load_file:c,get_attribute:b}});
\ No newline at end of file
diff -r 19c4ec5b8fafbf9095b102d4c59c6a59f125a8a1 -r d7ea2536e8e370cd202f735351c37264270ddbaf static/scripts/packed/viz/trackster.js
--- a/static/scripts/packed/viz/trackster.js
+++ b/static/scripts/packed/viz/trackster.js
@@ -1,1 +1,1 @@
-var ui=null;var view=null;var browser_router=null;require(["utils/galaxy.css","libs/jquery/jstorage","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/jquery-ui-combobox","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating","mvc/ui"],function(a){a.load_file("/static/style/jquery.rating.css");a.load_file("/static/style/history.css");a.load_file("/static/style/autocomplete_tagging.css");a.load_file("/static/style/jquery-ui/smoothness/jquery-ui.css");a.load_file("/static/style/library.css");a.load_file("/static/style/trackster.css")});define(["libs/backbone/backbone-relational","viz/visualization","viz/trackster_ui"],function(c,a,b){var d=Backbone.View.extend({initialize:function(){ui=new b.TracksterUI(galaxy_config.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right .unified-panel-title").append("Bookmarks");$("#right .unified-panel-icons").append("<a id='add-bookmark-button' class='icon-button menu-button plus-button' href='javascript:void(0);' title='Add bookmark'></a>");$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(galaxy_config.app.id){this.view_existing()}else{this.view_new()}},set_up_router:function(e){browser_router=new a.TrackBrowserRouter(e);Backbone.history.start()},view_existing:function(){var e=galaxy_config.app.viz_config;view=ui.create_visualization({container:$("#center .unified-panel-body"),name:e.title,vis_id:e.vis_id,dbkey:e.dbkey},e.viewport,e.tracks,e.bookmarks,true);this.init_editor()},view_new:function(){var e=this;$.ajax({url:galaxy_config.root+"api/genomes?chrom_info=True",data:{},error:function(){alert("Couldn't create new browser.")},success:function(f){show_modal("New Visualization",e.template_view_new(f),{Cancel:function(){window.location=galaxy_config.root+"visualization/list"},Create:function(){e.create_browser($("#new-title").val(),$("#new-dbkey").val())}});if(galaxy_config.app.default_dbkey){$("#new-dbkey option[value='"+galaxy_config.app.default_dbkey+"']").attr("selected",true)}$("#new-title").focus();$("select[name='dbkey']").combobox({appendTo:$("#overlay"),size:40});$("#overlay").css("overflow","auto")}})},template_view_new:function(e){var g='<form id="new-browser-form" action="javascript:void(0);" method="post" onsubmit="return false;"><div class="form-row"><label for="new-title">Browser name:</label><div class="form-row-input"><input type="text" name="title" id="new-title" value="Unnamed"></input></div><div style="clear: both;"></div></div><div class="form-row"><label for="new-dbkey">Reference genome build (dbkey): </label><div class="form-row-input"><select name="dbkey" id="new-dbkey">';for(var f in e){g+='<option value="'+e[f][1]+'">'+e[f][0]+"</option>"}g+='</select></div><div style="clear: both;"></div></div><div class="form-row">Is the build not listed here? <a href="'+galaxy_config.root+'user/dbkeys?use_panels=True">Add a Custom Build</a></div></form>';return g},create_browser:function(f,e){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#center .unified-panel-body"),name:f,dbkey:e},galaxy_config.app.gene_region);this.init_editor();view.editor=true;hide_modal()},init_editor:function(){$("#center .unified-panel-title").text(view.name+" ("+view.dbkey+")");if(galaxy_config.app.add_dataset){$.ajax({url:galaxy_config.root+"api/datasets/"+galaxy_config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(e){view.add_drawable(b.object_from_template(e,view,view))}})}$("#add-bookmark-button").click(function(){var f=view.chrom+":"+view.low+"-"+view.high,e="Bookmark description";return ui.add_bookmark(f,e,true)});ui.init_keyboard_nav(view);this.set_up_router({view:view})}});return{GalaxyApp:d}});
\ No newline at end of file
+var ui=null;var view=null;var browser_router=null;require(["utils/galaxy.css","libs/jquery/jstorage","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/jquery-ui-combobox","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating","mvc/ui"],function(a){a.load_file("static/style/jquery.rating.css");a.load_file("static/style/history.css");a.load_file("static/style/autocomplete_tagging.css");a.load_file("static/style/jquery-ui/smoothness/jquery-ui.css");a.load_file("static/style/library.css");a.load_file("static/style/trackster.css")});define(["libs/backbone/backbone-relational","viz/visualization","viz/trackster_ui"],function(c,a,b){var d=Backbone.View.extend({initialize:function(){ui=new b.TracksterUI(galaxy_config.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right .unified-panel-title").append("Bookmarks");$("#right .unified-panel-icons").append("<a id='add-bookmark-button' class='icon-button menu-button plus-button' href='javascript:void(0);' title='Add bookmark'></a>");$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(galaxy_config.app.id){this.view_existing()}else{this.view_new()}},set_up_router:function(e){browser_router=new a.TrackBrowserRouter(e);Backbone.history.start()},view_existing:function(){var e=galaxy_config.app.viz_config;view=ui.create_visualization({container:$("#center .unified-panel-body"),name:e.title,vis_id:e.vis_id,dbkey:e.dbkey},e.viewport,e.tracks,e.bookmarks,true);this.init_editor()},view_new:function(){var e=this;$.ajax({url:galaxy_config.root+"api/genomes?chrom_info=True",data:{},error:function(){alert("Couldn't create new browser.")},success:function(f){show_modal("New Visualization",e.template_view_new(f),{Cancel:function(){window.location=galaxy_config.root+"visualization/list"},Create:function(){e.create_browser($("#new-title").val(),$("#new-dbkey").val())}});if(galaxy_config.app.default_dbkey){$("#new-dbkey option[value='"+galaxy_config.app.default_dbkey+"']").attr("selected",true)}$("#new-title").focus();$("select[name='dbkey']").combobox({appendTo:$("#overlay"),size:40});$("#overlay").css("overflow","auto")}})},template_view_new:function(e){var g='<form id="new-browser-form" action="javascript:void(0);" method="post" onsubmit="return false;"><div class="form-row"><label for="new-title">Browser name:</label><div class="form-row-input"><input type="text" name="title" id="new-title" value="Unnamed"></input></div><div style="clear: both;"></div></div><div class="form-row"><label for="new-dbkey">Reference genome build (dbkey): </label><div class="form-row-input"><select name="dbkey" id="new-dbkey">';for(var f in e){g+='<option value="'+e[f][1]+'">'+e[f][0]+"</option>"}g+='</select></div><div style="clear: both;"></div></div><div class="form-row">Is the build not listed here? <a href="'+galaxy_config.root+'user/dbkeys?use_panels=True">Add a Custom Build</a></div></form>';return g},create_browser:function(f,e){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#center .unified-panel-body"),name:f,dbkey:e},galaxy_config.app.gene_region);this.init_editor();view.editor=true;hide_modal()},init_editor:function(){$("#center .unified-panel-title").text(view.name+" ("+view.dbkey+")");if(galaxy_config.app.add_dataset){$.ajax({url:galaxy_config.root+"api/datasets/"+galaxy_config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(e){view.add_drawable(b.object_from_template(e,view,view))}})}$("#add-bookmark-button").click(function(){var f=view.chrom+":"+view.low+"-"+view.high,e="Bookmark description";return ui.add_bookmark(f,e,true)});ui.init_keyboard_nav(view);this.set_up_router({view:view})}});return{GalaxyApp:d}});
\ 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: Rename ~/lib/galaxy/webapps/tool_shed/util/common_util.py to be ratings_util.
by commits-noreply@bitbucket.org 27 Aug '13
by commits-noreply@bitbucket.org 27 Aug '13
27 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/dd8329aa8d9e/
Changeset: dd8329aa8d9e
User: greg
Date: 2013-08-26 20:37:28
Summary: Rename ~/lib/galaxy/webapps/tool_shed/util/common_util.py to be ratings_util.
Affected #: 5 files
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -17,7 +17,7 @@
from galaxy.util import json
from galaxy.model.orm import and_
import tool_shed.util.shed_util_common as suc
-from tool_shed.util import common_util as scu
+from tool_shed.util import common_util
from tool_shed.util import container_util
from tool_shed.util import encoding_util
from tool_shed.util import export_util
@@ -31,7 +31,7 @@
from tool_shed.util import tool_util
from tool_shed.util import workflow_util
from tool_shed.galaxy_install import repository_util
-from galaxy.webapps.tool_shed.util import common_util
+from galaxy.webapps.tool_shed.util import ratings_util
import galaxy.tools
import tool_shed.grids.repository_grids as repository_grids
import tool_shed.grids.util as grids_util
@@ -51,7 +51,7 @@
malicious_error_can_push = " Correct this changeset as soon as possible, it potentially produces malicious behavior or contains inappropriate content."
-class RepositoryController( BaseUIController, common_util.ItemRatings ):
+class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
category_grid = repository_grids.CategoryGrid()
datatypes_grid = repository_grids.DatatypesGrid()
@@ -1233,7 +1233,7 @@
return self.install_matched_repository_grid( trans, **kwd )
else:
kwd[ 'message' ] = "tool id: <b>%s</b><br/>tool name: <b>%s</b><br/>tool version: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
- ( common_util.stringify( tool_ids ), common_util.stringify( tool_names ), common_util.stringify( tool_versions ), str( exact_matches_checked ) )
+ ( suc.stringify( tool_ids ), suc.stringify( tool_names ), suc.stringify( tool_versions ), str( exact_matches_checked ) )
self.matched_repository_grid.title = "Repositories with matching tools"
return self.matched_repository_grid( trans, **kwd )
else:
@@ -1241,9 +1241,9 @@
status = "error"
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
return trans.fill_template( '/webapps/tool_shed/repository/find_tools.mako',
- tool_id=common_util.stringify( tool_ids ),
- tool_name=common_util.stringify( tool_names ),
- tool_version=common_util.stringify( tool_versions ),
+ tool_id=suc.stringify( tool_ids ),
+ tool_name=suc.stringify( tool_names ),
+ tool_version=suc.stringify( tool_versions ),
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
@@ -1317,7 +1317,7 @@
return self.install_matched_repository_grid( trans, **kwd )
else:
kwd[ 'message' ] = "workflow name: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
- ( common_util.stringify( workflow_names ), str( exact_matches_checked ) )
+ ( suc.stringify( workflow_names ), str( exact_matches_checked ) )
self.matched_repository_grid.title = "Repositories with matching workflows"
return self.matched_repository_grid( trans, **kwd )
else:
@@ -1328,7 +1328,7 @@
workflow_names = []
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
return trans.fill_template( '/webapps/tool_shed/repository/find_workflows.mako',
- workflow_name=common_util.stringify( workflow_names ),
+ workflow_name=suc.stringify( workflow_names ),
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
@@ -1645,7 +1645,8 @@
encoded_repository_ids = []
changeset_revisions = []
for required_repository_tup in decoded_required_repository_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = scu.parse_repository_dependency_tuple( required_repository_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = \
+ common_util.parse_repository_dependency_tuple( required_repository_tup )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
encoded_repository_ids.append( trans.security.encode_id( repository.id ) )
changeset_revisions.append( changeset_revision )
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/controllers/repository_review.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
@@ -4,7 +4,7 @@
from galaxy.web.form_builder import SelectField, CheckboxField
from sqlalchemy.sql.expression import func
from galaxy.model.orm import and_
-from galaxy.webapps.tool_shed.util import common_util
+from galaxy.webapps.tool_shed.util import ratings_util
from tool_shed.util.container_util import STRSEP
import tool_shed.util.shed_util_common as suc
from tool_shed.util import review_util
@@ -19,7 +19,7 @@
log = logging.getLogger( __name__ )
-class RepositoryReviewController( BaseUIController, common_util.ItemRatings ):
+class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
component_grid = repository_review_grids.ComponentGrid()
repositories_ready_for_review_grid = repository_review_grids.RepositoriesReadyForReviewGrid()
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/util/common_util.py
--- a/lib/galaxy/webapps/tool_shed/util/common_util.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import logging
-from galaxy.model.item_attrs import UsesItemRatings
-
-log = logging.getLogger( __name__ )
-
-class ItemRatings( UsesItemRatings ):
- """Overrides rate_item method since we also allow for comments"""
- def rate_item( self, trans, user, item, rating, comment='' ):
- """ Rate an item. Return type is <item_class>RatingAssociation. """
- item_rating = self.get_user_item_rating( trans.sa_session, user, item, webapp_model=trans.model )
- if not item_rating:
- # User has not yet rated item; create rating.
- item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=trans.model )
- item_rating = item_rating_assoc_class()
- item_rating.user = trans.user
- item_rating.set_item( item )
- item_rating.rating = rating
- item_rating.comment = comment
- trans.sa_session.add( item_rating )
- trans.sa_session.flush()
- elif item_rating.rating != rating or item_rating.comment != comment:
- # User has previously rated item; update rating.
- item_rating.rating = rating
- item_rating.comment = comment
- trans.sa_session.add( item_rating )
- trans.sa_session.flush()
- return item_rating
-
-def stringify( list ):
- if list:
- return ','.join( list )
- return ''
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/galaxy/webapps/tool_shed/util/ratings_util.py
--- /dev/null
+++ b/lib/galaxy/webapps/tool_shed/util/ratings_util.py
@@ -0,0 +1,27 @@
+import logging
+from galaxy.model.item_attrs import UsesItemRatings
+
+log = logging.getLogger( __name__ )
+
+class ItemRatings( UsesItemRatings ):
+ """Overrides rate_item method since we also allow for comments"""
+ def rate_item( self, trans, user, item, rating, comment='' ):
+ """ Rate an item. Return type is <item_class>RatingAssociation. """
+ item_rating = self.get_user_item_rating( trans.sa_session, user, item, webapp_model=trans.model )
+ if not item_rating:
+ # User has not yet rated item; create rating.
+ item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=trans.model )
+ item_rating = item_rating_assoc_class()
+ item_rating.user = trans.user
+ item_rating.set_item( item )
+ item_rating.rating = rating
+ item_rating.comment = comment
+ trans.sa_session.add( item_rating )
+ trans.sa_session.flush()
+ elif item_rating.rating != rating or item_rating.comment != comment:
+ # User has previously rated item; update rating.
+ item_rating.rating = rating
+ item_rating.comment = comment
+ trans.sa_session.add( item_rating )
+ trans.sa_session.flush()
+ return item_rating
diff -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 -r dd8329aa8d9e84397fd226adb9e54589bd1aea2f lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -1401,7 +1401,12 @@
# Return the boolean value of prior_installation_required, which defaults to False.
return required_rd_tup[ 4 ]
return False
-
+
+def stringify( list ):
+ if list:
+ return ','.join( list )
+ return ''
+
def strip_path( fpath ):
"""Attempt to strip the path from a file name."""
if not fpath:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix imports in the tool shed's metadata_util.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a8baee5722c3/
Changeset: a8baee5722c3
User: greg
Date: 2013-08-26 20:12:43
Summary: Fix imports in the tool shed's metadata_util.
Affected #: 1 file
diff -r f5791b418b4e1d0be9d94895f0642083f795e61f -r a8baee5722c3d6df9d71bfdd5ed40c7890b2a473 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -19,7 +19,7 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import xml_util
-import tool_shed.galaxy_install.tool_dependencies.common_util as cu
+from tool_shed.galaxy_install.tool_dependencies import td_common_util
import pkg_resources
@@ -1124,7 +1124,7 @@
if not toolshed:
# Default to the current tool shed.
toolshed = str( url_for( '/', qualified=True ) ).rstrip( '/' )
- cleaned_toolshed = cu.clean_tool_shed_url( toolshed )
+ cleaned_toolshed = td_common_util.clean_tool_shed_url( toolshed )
name = repository_elem.get( 'name' )
owner = repository_elem.get( 'owner' )
changeset_revision = repository_elem.get( 'changeset_revision' )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Rename ~/tool_shed/galaxy_install/tool_dependencies/common_util.py to be td_common_util.py
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f5791b418b4e/
Changeset: f5791b418b4e
User: greg
Date: 2013-08-26 20:09:11
Summary: Rename ~/tool_shed/galaxy_install/tool_dependencies/common_util.py to be td_common_util.py
Affected #: 4 files
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
+++ /dev/null
@@ -1,314 +0,0 @@
-import logging
-import os
-import shutil
-import sys
-import tarfile
-import traceback
-import urllib2
-import zipfile
-import tool_shed.util.shed_util_common as suc
-from galaxy.datatypes import checkers
-from urllib2 import HTTPError
-
-log = logging.getLogger( __name__ )
-
-def clean_tool_shed_url( base_url ):
- if base_url:
- protocol, base = base_url.split( '://' )
- return base.rstrip( '/' )
- return base_url
-
-def create_env_var_dict( elem, tool_dependency_install_dir=None, tool_shed_repository_install_dir=None ):
- env_var_name = elem.get( 'name', 'PATH' )
- env_var_action = elem.get( 'action', 'prepend_to' )
- env_var_text = None
- if elem.text and elem.text.find( 'REPOSITORY_INSTALL_DIR' ) >= 0:
- if tool_shed_repository_install_dir and elem.text.find( '$REPOSITORY_INSTALL_DIR' ) != -1:
- env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_shed_repository_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- else:
- env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_dependency_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- if elem.text and elem.text.find( 'INSTALL_DIR' ) >= 0:
- if tool_dependency_install_dir:
- env_var_text = elem.text.replace( '$INSTALL_DIR', tool_dependency_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- else:
- env_var_text = elem.text.replace( '$INSTALL_DIR', tool_shed_repository_install_dir )
- return dict( name=env_var_name, action=env_var_action, value=env_var_text )
- if elem.text:
- # Allow for environment variables that contain neither REPOSITORY_INSTALL_DIR nor INSTALL_DIR since there may be command line
- # parameters that are tuned for a Galaxy instance. Allowing them to be set in one location rather than being hard coded into
- # each tool config is the best approach. For example:
- # <environment_variable name="GATK2_SITE_OPTIONS" action="set_to">
- # "--num_threads 4 --num_cpu_threads_per_data_thread 3 --phone_home STANDARD"
- # </environment_variable>
- return dict( name=env_var_name, action=env_var_action, value=elem.text)
- return None
-
-def create_or_update_env_shell_file( install_dir, env_var_dict ):
- env_var_name = env_var_dict[ 'name' ]
- env_var_action = env_var_dict[ 'action' ]
- env_var_value = env_var_dict[ 'value' ]
- if env_var_action == 'prepend_to':
- changed_value = '%s:$%s' % ( env_var_value, env_var_name )
- elif env_var_action == 'set_to':
- changed_value = '%s' % env_var_value
- elif env_var_action == 'append_to':
- changed_value = '$%s:%s' % ( env_var_name, env_var_value )
- line = "%s=%s; export %s" % (env_var_name, changed_value, env_var_name)
- return create_or_update_env_shell_file_with_command(install_dir, line)
-
-
-def create_or_update_env_shell_file_with_command( install_dir, command ):
- """
- Return a shell expression which when executed will create or update
- a Galaxy env.sh dependency file in the specified install_dir containing
- the supplied command.
- """
- env_shell_file_path = '%s/env.sh' % install_dir
- if os.path.exists( env_shell_file_path ):
- write_action = '>>'
- else:
- write_action = '>'
- cmd = "echo %s %s %s;chmod +x %s" % ( __shellquote(command),
- write_action,
- __shellquote(env_shell_file_path),
- __shellquote(env_shell_file_path))
- return cmd
-
-def download_binary( url, work_dir ):
- '''
- Download a pre-compiled binary from the specified URL.
- '''
- downloaded_filename = os.path.split( url )[ -1 ]
- dir = url_download( work_dir, downloaded_filename, url, extract=False )
- return downloaded_filename
-
-def extract_tar( file_name, file_path ):
- if isgzip( file_name ) or isbz2( file_name ):
- # Open for reading with transparent compression.
- tar = tarfile.open( file_name, 'r:*', errorlevel=0 )
- else:
- tar = tarfile.open( file_name, errorlevel=0 )
- tar.extractall( path=file_path )
- tar.close()
-
-def extract_zip( archive_path, extraction_path ):
- # TODO: change this method to use zipfile.Zipfile.extractall() when we stop supporting Python 2.5.
- if not zipfile_ok( archive_path ):
- return False
- zip_archive = zipfile.ZipFile( archive_path, 'r' )
- for name in zip_archive.namelist():
- uncompressed_path = os.path.join( extraction_path, name )
- if uncompressed_path.endswith( '/' ):
- if not os.path.isdir( uncompressed_path ):
- os.makedirs( uncompressed_path )
- else:
- file( uncompressed_path, 'wb' ).write( zip_archive.read( name ) )
- zip_archive.close()
- return True
-
-def format_traceback():
- ex_type, ex, tb = sys.exc_info()
- return ''.join( traceback.format_tb( tb ) )
-
-def get_env_shell_file_path( installation_directory ):
- env_shell_file_name = 'env.sh'
- default_location = os.path.abspath( os.path.join( installation_directory, env_shell_file_name ) )
- if os.path.exists( default_location ):
- return default_location
- for root, dirs, files in os.walk( installation_directory ):
- for name in files:
- if name == env_shell_file_name:
- return os.path.abspath( os.path.join( root, name ) )
- return None
-
-def get_env_shell_file_paths( app, elem ):
- # Currently only the following tag set is supported.
- # <repository toolshed="http://localhost:9009/" name="package_numpy_1_7" owner="test" changeset_revision="c84c6a8be056">
- # <package name="numpy" version="1.7.1" />
- # </repository>
- env_shell_file_paths = []
- toolshed = elem.get( 'toolshed', None )
- repository_name = elem.get( 'name', None )
- repository_owner = elem.get( 'owner', None )
- changeset_revision = elem.get( 'changeset_revision', None )
- if toolshed and repository_name and repository_owner and changeset_revision:
- toolshed = clean_tool_shed_url( toolshed )
- repository = suc.get_repository_for_dependency_relationship( app, toolshed, repository_name, repository_owner, changeset_revision )
- if repository:
- for sub_elem in elem:
- tool_dependency_type = sub_elem.tag
- tool_dependency_name = sub_elem.get( 'name' )
- tool_dependency_version = sub_elem.get( 'version' )
- if tool_dependency_type and tool_dependency_name and tool_dependency_version:
- # Get the tool_dependency so we can get it's installation directory.
- tool_dependency = None
- for tool_dependency in repository.tool_dependencies:
- if tool_dependency.type == tool_dependency_type and tool_dependency.name == tool_dependency_name and tool_dependency.version == tool_dependency_version:
- break
- if tool_dependency:
- tool_dependency_key = '%s/%s' % ( tool_dependency_name, tool_dependency_version )
- installation_directory = tool_dependency.installation_directory( app )
- env_shell_file_path = get_env_shell_file_path( installation_directory )
- if env_shell_file_path:
- env_shell_file_paths.append( env_shell_file_path )
- else:
- error_message = "Skipping tool dependency definition because unable to locate env.sh file for tool dependency "
- error_message += "type %s, name %s, version %s for repository %s" % \
- ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
- log.debug( error_message )
- continue
- else:
- error_message = "Skipping tool dependency definition because unable to locate tool dependency "
- error_message += "type %s, name %s, version %s for repository %s" % \
- ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
- log.debug( error_message )
- continue
- else:
- error_message = "Skipping invalid tool dependency definition: type %s, name %s, version %s." % \
- ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ) )
- log.debug( error_message )
- continue
- else:
- error_message = "Skipping set_environment_for_install definition because unable to locate required installed tool shed repository: "
- error_message += "toolshed %s, name %s, owner %s, changeset_revision %s." % \
- ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
- log.debug( error_message )
- else:
- error_message = "Skipping invalid set_environment_for_install definition: toolshed %s, name %s, owner %s, changeset_revision %s." % \
- ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
- log.debug( error_message )
- return env_shell_file_paths
-
-def get_env_var_values( install_dir ):
- env_var_dict = {}
- env_var_dict[ 'INSTALL_DIR' ] = install_dir
- env_var_dict[ 'system_install' ] = install_dir
- # If the Python interpreter is 64bit then we can safely assume that the underlying system is also 64bit.
- env_var_dict[ '__is64bit__' ] = sys.maxsize > 2**32
- return env_var_dict
-
-def isbz2( file_path ):
- return checkers.is_bz2( file_path )
-
-def isgzip( file_path ):
- return checkers.is_gzip( file_path )
-
-def isjar( file_path ):
- return iszip( file_path ) and file_path.endswith( '.jar' )
-
-def istar( file_path ):
- return tarfile.is_tarfile( file_path )
-
-def iszip( file_path ):
- return checkers.check_zip( file_path )
-
-def is_compressed( file_path ):
- if isjar( file_path ):
- return False
- else:
- return iszip( file_path ) or isgzip( file_path ) or istar( file_path ) or isbz2( file_path )
-
-def make_directory( full_path ):
- if not os.path.exists( full_path ):
- os.makedirs( full_path )
-
-def move_directory_files( current_dir, source_dir, destination_dir ):
- source_directory = os.path.abspath( os.path.join( current_dir, source_dir ) )
- destination_directory = os.path.join( destination_dir )
- if not os.path.isdir( destination_directory ):
- os.makedirs( destination_directory )
- for file_name in os.listdir( source_directory ):
- source_file = os.path.join( source_directory, file_name )
- destination_file = os.path.join( destination_directory, file_name )
- shutil.move( source_file, destination_file )
-
-def move_file( current_dir, source, destination_dir ):
- source_file = os.path.abspath( os.path.join( current_dir, source ) )
- destination_directory = os.path.join( destination_dir )
- if not os.path.isdir( destination_directory ):
- os.makedirs( destination_directory )
- shutil.move( source_file, destination_directory )
-
-def tar_extraction_directory( file_path, file_name ):
- """Try to return the correct extraction directory."""
- file_name = file_name.strip()
- extensions = [ '.tar.gz', '.tgz', '.tar.bz2', '.tar', '.zip' ]
- for extension in extensions:
- if file_name.find( extension ) > 0:
- dir_name = file_name[ :-len( extension ) ]
- if os.path.exists( os.path.abspath( os.path.join( file_path, dir_name ) ) ):
- return dir_name
- if os.path.exists( os.path.abspath( os.path.join( file_path, file_name ) ) ):
- return os.path.abspath( file_path )
- raise ValueError( 'Could not find path to file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
-
-def url_download( install_dir, downloaded_file_name, download_url, extract=True ):
- file_path = os.path.join( install_dir, downloaded_file_name )
- src = None
- dst = None
- try:
- src = urllib2.urlopen( download_url )
- dst = open( file_path, 'wb' )
- while True:
- chunk = src.read( suc.CHUNK_SIZE )
- if chunk:
- dst.write( chunk )
- else:
- break
- except:
- raise
- finally:
- if src:
- src.close()
- if dst:
- dst.close()
- if extract:
- if istar( file_path ):
- # <action type="download_by_url">http://sourceforge.net/projects/samtools/files/samtools/0.1.18/samtools-0.1…</action>
- extract_tar( file_path, install_dir )
- dir = tar_extraction_directory( install_dir, downloaded_file_name )
- elif isjar( file_path ):
- dir = os.path.curdir
- elif iszip( file_path ):
- # <action type="download_by_url">http://downloads.sourceforge.net/project/picard/picard-tools/1.56/picard-to…</action>
- zip_archive_extracted = extract_zip( file_path, install_dir )
- dir = zip_extraction_directory( install_dir, downloaded_file_name )
- else:
- dir = os.path.abspath( install_dir )
- else:
- dir = os.path.abspath( install_dir )
- return dir
-
-def zip_extraction_directory( file_path, file_name ):
- """Try to return the correct extraction directory."""
- files = [ filename for filename in os.listdir( file_path ) if not filename.endswith( '.zip' ) ]
- if len( files ) > 1:
- return os.path.abspath( file_path )
- elif len( files ) == 1:
- # If there is only on file it should be a directory.
- if os.path.isdir( os.path.join( file_path, files[ 0 ] ) ):
- return os.path.abspath( os.path.join( file_path, files[ 0 ] ) )
- raise ValueError( 'Could not find directory for the extracted file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
-
-def zipfile_ok( path_to_archive ):
- """
- This function is a bit pedantic and not functionally necessary. It checks whether there is no file pointing outside of the extraction,
- because ZipFile.extractall() has some potential security holes. See python zipfile documentation for more details.
- """
- basename = os.path.realpath( os.path.dirname( path_to_archive ) )
- zip_archive = zipfile.ZipFile( path_to_archive )
- for member in zip_archive.namelist():
- member_path = os.path.realpath( os.path.join( basename, member ) )
- if not member_path.startswith( basename ):
- return False
- return True
-
-
-def __shellquote(s):
- """
- Quote and escape the supplied string for use in shell expressions.
- """
- return "'" + s.replace("'", "'\\''") + "'"
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -1,12 +1,12 @@
# For Python 2.5
from __future__ import with_statement
-import common_util
import logging
import os
import shutil
import tempfile
import shutil
+import td_common_util
from contextlib import contextmanager
from galaxy.util.template import fill_template
from galaxy import eggs
@@ -155,10 +155,10 @@
if not os.path.exists( venv_dir ):
with make_tmp_dir() as work_dir:
downloaded_filename = VIRTUALENV_URL.rsplit('/', 1)[-1]
- downloaded_file_path = common_util.url_download( work_dir, downloaded_filename, VIRTUALENV_URL )
- if common_util.istar( downloaded_file_path ):
- common_util.extract_tar( downloaded_file_path, work_dir )
- dir = common_util.tar_extraction_directory( work_dir, downloaded_filename )
+ downloaded_file_path = td_common_util.url_download( work_dir, downloaded_filename, VIRTUALENV_URL )
+ if td_common_util.istar( downloaded_file_path ):
+ td_common_util.extract_tar( downloaded_file_path, work_dir )
+ dir = td_common_util.tar_extraction_directory( work_dir, downloaded_filename )
else:
log.error( "Failed to download virtualenv: Downloaded file '%s' is not a tar file", downloaded_filename )
return False
@@ -188,7 +188,7 @@
log.debug( 'Attempting to download from %s to %s', url, str( target_directory ) )
downloaded_filename = None
try:
- downloaded_filename = common_util.download_binary( url, work_dir )
+ downloaded_filename = td_common_util.download_binary( url, work_dir )
# Filter out any actions that are not download_binary, chmod, or set_environment.
filtered_actions = filter_actions_after_binary_installation( actions[ 1: ] )
# Set actions to the same, so that the current download_binary doesn't get re-run in the filtered actions below.
@@ -210,9 +210,9 @@
full_path_to_dir = os.path.abspath( install_dir )
else:
full_path_to_dir = os.path.abspath( install_dir )
- common_util.move_file( current_dir=work_dir,
- source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ td_common_util.move_file( current_dir=work_dir,
+ source=downloaded_filename,
+ destination_dir=full_path_to_dir )
if action_type == 'download_by_url':
# Eliminate the download_by_url action so remaining actions can be processed correctly.
filtered_actions = actions[ 1: ]
@@ -223,7 +223,7 @@
downloaded_filename = action_dict[ 'target_filename' ]
else:
downloaded_filename = os.path.split( url )[ -1 ]
- dir = common_util.url_download( work_dir, downloaded_filename, url, extract=True )
+ dir = td_common_util.url_download( work_dir, downloaded_filename, url, extract=True )
elif action_type == 'shell_command':
# <action type="shell_command">git clone --recursive git://github.com/ekg/freebayes.git</action>
# Eliminate the shell_command clone action so remaining actions can be processed correctly.
@@ -243,7 +243,7 @@
filename = action_dict[ 'target_filename' ]
else:
filename = url.split( '/' )[ -1 ]
- common_util.url_download( work_dir, filename, url )
+ td_common_util.url_download( work_dir, filename, url )
dir = os.path.curdir
else:
# We're handling a complex repository dependency where we only have a set_environment tag set.
@@ -263,17 +263,17 @@
with lcd( current_dir ):
action_type, action_dict = action_tup
if action_type == 'make_directory':
- common_util.make_directory( full_path=action_dict[ 'full_path' ] )
+ td_common_util.make_directory( full_path=action_dict[ 'full_path' ] )
elif action_type == 'move_directory_files':
- common_util.move_directory_files( current_dir=current_dir,
- source_dir=os.path.join( action_dict[ 'source_directory' ] ),
- destination_dir=os.path.join( action_dict[ 'destination_directory' ] ) )
+ td_common_util.move_directory_files( current_dir=current_dir,
+ source_dir=os.path.join( action_dict[ 'source_directory' ] ),
+ destination_dir=os.path.join( action_dict[ 'destination_directory' ] ) )
elif action_type == 'move_file':
# TODO: Remove this hack that resets current_dir so that the pre-compiled bwa binary can be found.
# current_dir = '/Users/gvk/workspaces_2008/bwa/bwa-0.5.9'
- common_util.move_file( current_dir=current_dir,
- source=os.path.join( action_dict[ 'source' ] ),
- destination_dir=os.path.join( action_dict[ 'destination' ] ) )
+ td_common_util.move_file( current_dir=current_dir,
+ source=os.path.join( action_dict[ 'source' ] ),
+ destination_dir=os.path.join( action_dict[ 'destination' ] ) )
elif action_type == 'set_environment':
# Currently the only action supported in this category is "environment_variable".
# Build a command line from the prior_installation_required, in case an environment variable is referenced
@@ -289,7 +289,7 @@
for env_var_dict in env_var_dicts:
# Check for the presence of the $ENV[] key string and populate it if possible.
env_var_dict = handle_environment_variables( app, tool_dependency, install_dir, env_var_dict, cmds )
- env_command = common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
+ env_command = td_common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
return_code = handle_command( app, tool_dependency, install_dir, env_command )
if return_code:
return
@@ -331,11 +331,13 @@
if not os.path.exists( output.stdout ):
log.error( "virtualenv's site-packages directory '%s' does not exist", output.stdout )
return
- modify_env_command = common_util.create_or_update_env_shell_file( install_dir, dict( name="PYTHONPATH", action="prepend_to", value=output.stdout ) )
+ modify_env_command_dict = dict( name="PYTHONPATH", action="prepend_to", value=output.stdout )
+ modify_env_command = td_common_util.create_or_update_env_shell_file( install_dir, modify_env_command_dict )
return_code = handle_command( app, tool_dependency, install_dir, modify_env_command )
if return_code:
return
- modify_env_command = common_util.create_or_update_env_shell_file( install_dir, dict( name="PATH", action="prepend_to", value=os.path.join( venv_directory, "bin" ) ) )
+ modify_env_command_dict = dict( name="PATH", action="prepend_to", value=os.path.join( venv_directory, "bin" ) )
+ modify_env_command = td_common_util.create_or_update_env_shell_file( install_dir, modify_env_command_dict )
return_code = handle_command( app, tool_dependency, install_dir, modify_env_command )
if return_code:
return
@@ -362,7 +364,7 @@
env_vars[ env_name ] = env_path
else:
log.debug( 'Invalid file %s specified, ignoring template_command action.', env_shell_file_path )
- env_vars.update( common_util.get_env_var_values( install_dir ) )
+ env_vars.update( td_common_util.get_env_var_values( install_dir ) )
language = action_dict[ 'language' ]
with settings( warn_only=True, **env_vars ):
if language == 'cheetah':
@@ -379,7 +381,7 @@
else:
filename = url.split( '/' )[ -1 ]
extract = action_dict.get( 'extract', False )
- common_util.url_download( current_dir, filename, url, extract=extract )
+ td_common_util.url_download( current_dir, filename, url, extract=extract )
elif action_type == 'change_directory':
target_directory = os.path.realpath( os.path.normpath( os.path.join( current_dir, action_dict[ 'directory' ] ) ) )
if target_directory.startswith( os.path.realpath( current_dir ) ) and os.path.exists( target_directory ):
@@ -398,7 +400,7 @@
url = action_dict[ 'url' ]
target_directory = action_dict.get( 'target_directory', None )
try:
- downloaded_filename = common_util.download_binary( url, work_dir )
+ downloaded_filename = td_common_util.download_binary( url, work_dir )
except Exception, e:
log.exception( str( e ) )
# If the downloaded file exists, move it to $INSTALL_DIR. Put this outside the try/catch above so that
@@ -413,9 +415,9 @@
full_path_to_dir = os.path.abspath( install_dir )
else:
full_path_to_dir = os.path.abspath( install_dir )
- common_util.move_file( current_dir=work_dir,
- source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ td_common_util.move_file( current_dir=work_dir,
+ source=downloaded_filename,
+ destination_dir=full_path_to_dir )
def log_results( command, fabric_AttributeString, file_path ):
"""
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -5,10 +5,10 @@
import subprocess
import tempfile
from string import Template
-import common_util
import fabric_util
+import td_common_util
import tool_shed.util.shed_util_common as suc
-import tool_shed.util.common_util as cu
+from tool_shed.util import common_util
from tool_shed.util import encoding_util
from tool_shed.util import tool_dependency_util
from tool_shed.util import xml_util
@@ -22,7 +22,7 @@
"""Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
url = url_join( tool_shed_url,
'repository/get_tool_dependencies_config_contents?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
- text = cu.tool_shed_get( app, tool_shed_url, url )
+ text = common_util.tool_shed_get( app, tool_shed_url, url )
if text:
# Write the contents to a temporary file on disk so it can be reloaded and parsed.
fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-cttdc" )
@@ -51,7 +51,7 @@
def get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app, tool_shed_url, name, owner, changeset_revision ):
sa_session = app.model.context.current
- tool_shed = common_util.clean_tool_shed_url( tool_shed_url )
+ tool_shed = td_common_util.clean_tool_shed_url( tool_shed_url )
tool_shed_repository = sa_session.query( app.model.ToolShedRepository ) \
.filter( and_( app.model.ToolShedRepository.table.c.tool_shed == tool_shed,
app.model.ToolShedRepository.table.c.name == name,
@@ -103,7 +103,7 @@
"""
url = suc.url_join( tool_shed_url,
'repository/updated_changeset_revisions?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
- text = cu.tool_shed_get( app, tool_shed_url, url )
+ text = common_util.tool_shed_get( app, tool_shed_url, url )
return text
def handle_set_environment_entry_for_package( app, install_dir, tool_shed_repository, package_name, package_version, elem, required_repository ):
@@ -139,7 +139,7 @@
# </action>
for env_elem in action_elem:
if env_elem.tag == 'environment_variable':
- env_var_dict = common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
+ env_var_dict = td_common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
if env_var_dict:
if env_var_dict not in env_var_dicts:
env_var_dicts.append( env_var_dict )
@@ -203,7 +203,7 @@
except Exception, e:
log.exception( 'Error installing tool dependency %s version %s.', str( tool_dependency.name ), str( tool_dependency.version ) )
tool_dependency.status = app.model.ToolDependency.installation_status.ERROR
- tool_dependency.error_message = '%s\n%s' % ( common_util.format_traceback(), str( e ) )
+ tool_dependency.error_message = '%s\n%s' % ( td_common_util.format_traceback(), str( e ) )
sa_session.add( tool_dependency )
sa_session.flush()
if tool_dependency.status != app.model.ToolDependency.installation_status.ERROR:
@@ -362,7 +362,7 @@
def evaluate_template( text ):
""" Substitute variables defined in XML blocks from dependencies file."""
- return Template( text ).safe_substitute( common_util.get_env_var_values( install_dir ) )
+ return Template( text ).safe_substitute( td_common_util.get_env_var_values( install_dir ) )
if not os.path.exists( install_dir ):
os.makedirs( install_dir )
@@ -469,7 +469,7 @@
# </action>
for env_elem in action_elem:
if env_elem.tag == 'environment_variable':
- env_var_dict = common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
+ env_var_dict = td_common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
if env_var_dict:
env_var_dicts.append( env_var_dict )
if env_var_dicts:
@@ -489,7 +489,7 @@
# tool dependency package. See the package_matplotlib_1_2 repository in the test tool shed for a real-world example.
for env_elem in action_elem:
if env_elem.tag == 'repository':
- env_shell_file_paths = common_util.get_env_shell_file_paths( app, env_elem )
+ env_shell_file_paths = td_common_util.get_env_shell_file_paths( app, env_elem )
if env_shell_file_paths:
all_env_shell_file_paths.extend( env_shell_file_paths )
if all_env_shell_file_paths:
@@ -705,7 +705,7 @@
tool_dependency_name=env_var_name,
tool_dependency_version=None )
tool_shed_repository_install_dir = get_tool_shed_repository_install_dir( app, tool_shed_repository )
- env_var_dict = common_util.create_env_var_dict( env_var_elem, tool_shed_repository_install_dir=tool_shed_repository_install_dir )
+ env_var_dict = td_common_util.create_env_var_dict( env_var_elem, tool_shed_repository_install_dir=tool_shed_repository_install_dir )
if env_var_dict:
if not os.path.exists( install_dir ):
os.makedirs( install_dir )
@@ -716,7 +716,7 @@
type='set_environment',
status=app.model.ToolDependency.installation_status.INSTALLING,
set_status=True )
- cmd = common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
+ cmd = td_common_util.create_or_update_env_shell_file( install_dir, env_var_dict )
if env_var_version == '1.0':
# Handle setting environment variables using a fabric method.
fabric_util.handle_command( app, tool_dependency, install_dir, cmd )
diff -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 -r f5791b418b4e1d0be9d94895f0642083f795e61f lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
@@ -0,0 +1,311 @@
+import logging
+import os
+import shutil
+import sys
+import tarfile
+import traceback
+import urllib2
+import zipfile
+import tool_shed.util.shed_util_common as suc
+from galaxy.datatypes import checkers
+from urllib2 import HTTPError
+
+log = logging.getLogger( __name__ )
+
+def clean_tool_shed_url( base_url ):
+ if base_url:
+ protocol, base = base_url.split( '://' )
+ return base.rstrip( '/' )
+ return base_url
+
+def create_env_var_dict( elem, tool_dependency_install_dir=None, tool_shed_repository_install_dir=None ):
+ env_var_name = elem.get( 'name', 'PATH' )
+ env_var_action = elem.get( 'action', 'prepend_to' )
+ env_var_text = None
+ if elem.text and elem.text.find( 'REPOSITORY_INSTALL_DIR' ) >= 0:
+ if tool_shed_repository_install_dir and elem.text.find( '$REPOSITORY_INSTALL_DIR' ) != -1:
+ env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_shed_repository_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ else:
+ env_var_text = elem.text.replace( '$REPOSITORY_INSTALL_DIR', tool_dependency_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ if elem.text and elem.text.find( 'INSTALL_DIR' ) >= 0:
+ if tool_dependency_install_dir:
+ env_var_text = elem.text.replace( '$INSTALL_DIR', tool_dependency_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ else:
+ env_var_text = elem.text.replace( '$INSTALL_DIR', tool_shed_repository_install_dir )
+ return dict( name=env_var_name, action=env_var_action, value=env_var_text )
+ if elem.text:
+ # Allow for environment variables that contain neither REPOSITORY_INSTALL_DIR nor INSTALL_DIR since there may be command line
+ # parameters that are tuned for a Galaxy instance. Allowing them to be set in one location rather than being hard coded into
+ # each tool config is the best approach. For example:
+ # <environment_variable name="GATK2_SITE_OPTIONS" action="set_to">
+ # "--num_threads 4 --num_cpu_threads_per_data_thread 3 --phone_home STANDARD"
+ # </environment_variable>
+ return dict( name=env_var_name, action=env_var_action, value=elem.text)
+ return None
+
+def create_or_update_env_shell_file( install_dir, env_var_dict ):
+ env_var_name = env_var_dict[ 'name' ]
+ env_var_action = env_var_dict[ 'action' ]
+ env_var_value = env_var_dict[ 'value' ]
+ if env_var_action == 'prepend_to':
+ changed_value = '%s:$%s' % ( env_var_value, env_var_name )
+ elif env_var_action == 'set_to':
+ changed_value = '%s' % env_var_value
+ elif env_var_action == 'append_to':
+ changed_value = '$%s:%s' % ( env_var_name, env_var_value )
+ line = "%s=%s; export %s" % (env_var_name, changed_value, env_var_name)
+ return create_or_update_env_shell_file_with_command(install_dir, line)
+
+
+def create_or_update_env_shell_file_with_command( install_dir, command ):
+ """
+ Return a shell expression which when executed will create or update
+ a Galaxy env.sh dependency file in the specified install_dir containing
+ the supplied command.
+ """
+ env_shell_file_path = '%s/env.sh' % install_dir
+ if os.path.exists( env_shell_file_path ):
+ write_action = '>>'
+ else:
+ write_action = '>'
+ cmd = "echo %s %s %s;chmod +x %s" % ( __shellquote(command),
+ write_action,
+ __shellquote(env_shell_file_path),
+ __shellquote(env_shell_file_path))
+ return cmd
+
+def download_binary( url, work_dir ):
+ '''
+ Download a pre-compiled binary from the specified URL.
+ '''
+ downloaded_filename = os.path.split( url )[ -1 ]
+ dir = url_download( work_dir, downloaded_filename, url, extract=False )
+ return downloaded_filename
+
+def extract_tar( file_name, file_path ):
+ if isgzip( file_name ) or isbz2( file_name ):
+ # Open for reading with transparent compression.
+ tar = tarfile.open( file_name, 'r:*', errorlevel=0 )
+ else:
+ tar = tarfile.open( file_name, errorlevel=0 )
+ tar.extractall( path=file_path )
+ tar.close()
+
+def extract_zip( archive_path, extraction_path ):
+ # TODO: change this method to use zipfile.Zipfile.extractall() when we stop supporting Python 2.5.
+ if not zipfile_ok( archive_path ):
+ return False
+ zip_archive = zipfile.ZipFile( archive_path, 'r' )
+ for name in zip_archive.namelist():
+ uncompressed_path = os.path.join( extraction_path, name )
+ if uncompressed_path.endswith( '/' ):
+ if not os.path.isdir( uncompressed_path ):
+ os.makedirs( uncompressed_path )
+ else:
+ file( uncompressed_path, 'wb' ).write( zip_archive.read( name ) )
+ zip_archive.close()
+ return True
+
+def format_traceback():
+ ex_type, ex, tb = sys.exc_info()
+ return ''.join( traceback.format_tb( tb ) )
+
+def get_env_shell_file_path( installation_directory ):
+ env_shell_file_name = 'env.sh'
+ default_location = os.path.abspath( os.path.join( installation_directory, env_shell_file_name ) )
+ if os.path.exists( default_location ):
+ return default_location
+ for root, dirs, files in os.walk( installation_directory ):
+ for name in files:
+ if name == env_shell_file_name:
+ return os.path.abspath( os.path.join( root, name ) )
+ return None
+
+def get_env_shell_file_paths( app, elem ):
+ # Currently only the following tag set is supported.
+ # <repository toolshed="http://localhost:9009/" name="package_numpy_1_7" owner="test" changeset_revision="c84c6a8be056">
+ # <package name="numpy" version="1.7.1" />
+ # </repository>
+ env_shell_file_paths = []
+ toolshed = elem.get( 'toolshed', None )
+ repository_name = elem.get( 'name', None )
+ repository_owner = elem.get( 'owner', None )
+ changeset_revision = elem.get( 'changeset_revision', None )
+ if toolshed and repository_name and repository_owner and changeset_revision:
+ toolshed = clean_tool_shed_url( toolshed )
+ repository = suc.get_repository_for_dependency_relationship( app, toolshed, repository_name, repository_owner, changeset_revision )
+ if repository:
+ for sub_elem in elem:
+ tool_dependency_type = sub_elem.tag
+ tool_dependency_name = sub_elem.get( 'name' )
+ tool_dependency_version = sub_elem.get( 'version' )
+ if tool_dependency_type and tool_dependency_name and tool_dependency_version:
+ # Get the tool_dependency so we can get it's installation directory.
+ tool_dependency = None
+ for tool_dependency in repository.tool_dependencies:
+ if tool_dependency.type == tool_dependency_type and tool_dependency.name == tool_dependency_name and tool_dependency.version == tool_dependency_version:
+ break
+ if tool_dependency:
+ tool_dependency_key = '%s/%s' % ( tool_dependency_name, tool_dependency_version )
+ installation_directory = tool_dependency.installation_directory( app )
+ env_shell_file_path = get_env_shell_file_path( installation_directory )
+ if env_shell_file_path:
+ env_shell_file_paths.append( env_shell_file_path )
+ else:
+ error_message = "Skipping tool dependency definition because unable to locate env.sh file for tool dependency "
+ error_message += "type %s, name %s, version %s for repository %s" % \
+ ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
+ log.debug( error_message )
+ continue
+ else:
+ error_message = "Skipping tool dependency definition because unable to locate tool dependency "
+ error_message += "type %s, name %s, version %s for repository %s" % \
+ ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ), str( repository.name ) )
+ log.debug( error_message )
+ continue
+ else:
+ error_message = "Skipping invalid tool dependency definition: type %s, name %s, version %s." % \
+ ( str( tool_dependency_type ), str( tool_dependency_name ), str( tool_dependency_version ) )
+ log.debug( error_message )
+ continue
+ else:
+ error_message = "Skipping set_environment_for_install definition because unable to locate required installed tool shed repository: "
+ error_message += "toolshed %s, name %s, owner %s, changeset_revision %s." % \
+ ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ log.debug( error_message )
+ else:
+ error_message = "Skipping invalid set_environment_for_install definition: toolshed %s, name %s, owner %s, changeset_revision %s." % \
+ ( str( toolshed ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ log.debug( error_message )
+ return env_shell_file_paths
+
+def get_env_var_values( install_dir ):
+ env_var_dict = {}
+ env_var_dict[ 'INSTALL_DIR' ] = install_dir
+ env_var_dict[ 'system_install' ] = install_dir
+ # If the Python interpreter is 64bit then we can safely assume that the underlying system is also 64bit.
+ env_var_dict[ '__is64bit__' ] = sys.maxsize > 2**32
+ return env_var_dict
+
+def isbz2( file_path ):
+ return checkers.is_bz2( file_path )
+
+def isgzip( file_path ):
+ return checkers.is_gzip( file_path )
+
+def isjar( file_path ):
+ return iszip( file_path ) and file_path.endswith( '.jar' )
+
+def istar( file_path ):
+ return tarfile.is_tarfile( file_path )
+
+def iszip( file_path ):
+ return checkers.check_zip( file_path )
+
+def is_compressed( file_path ):
+ if isjar( file_path ):
+ return False
+ else:
+ return iszip( file_path ) or isgzip( file_path ) or istar( file_path ) or isbz2( file_path )
+
+def make_directory( full_path ):
+ if not os.path.exists( full_path ):
+ os.makedirs( full_path )
+
+def move_directory_files( current_dir, source_dir, destination_dir ):
+ source_directory = os.path.abspath( os.path.join( current_dir, source_dir ) )
+ destination_directory = os.path.join( destination_dir )
+ if not os.path.isdir( destination_directory ):
+ os.makedirs( destination_directory )
+ for file_name in os.listdir( source_directory ):
+ source_file = os.path.join( source_directory, file_name )
+ destination_file = os.path.join( destination_directory, file_name )
+ shutil.move( source_file, destination_file )
+
+def move_file( current_dir, source, destination_dir ):
+ source_file = os.path.abspath( os.path.join( current_dir, source ) )
+ destination_directory = os.path.join( destination_dir )
+ if not os.path.isdir( destination_directory ):
+ os.makedirs( destination_directory )
+ shutil.move( source_file, destination_directory )
+
+def tar_extraction_directory( file_path, file_name ):
+ """Try to return the correct extraction directory."""
+ file_name = file_name.strip()
+ extensions = [ '.tar.gz', '.tgz', '.tar.bz2', '.tar', '.zip' ]
+ for extension in extensions:
+ if file_name.find( extension ) > 0:
+ dir_name = file_name[ :-len( extension ) ]
+ if os.path.exists( os.path.abspath( os.path.join( file_path, dir_name ) ) ):
+ return dir_name
+ if os.path.exists( os.path.abspath( os.path.join( file_path, file_name ) ) ):
+ return os.path.abspath( file_path )
+ raise ValueError( 'Could not find path to file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
+
+def url_download( install_dir, downloaded_file_name, download_url, extract=True ):
+ file_path = os.path.join( install_dir, downloaded_file_name )
+ src = None
+ dst = None
+ try:
+ src = urllib2.urlopen( download_url )
+ dst = open( file_path, 'wb' )
+ while True:
+ chunk = src.read( suc.CHUNK_SIZE )
+ if chunk:
+ dst.write( chunk )
+ else:
+ break
+ except:
+ raise
+ finally:
+ if src:
+ src.close()
+ if dst:
+ dst.close()
+ if extract:
+ if istar( file_path ):
+ # <action type="download_by_url">http://sourceforge.net/projects/samtools/files/samtools/0.1.18/samtools-0.1…</action>
+ extract_tar( file_path, install_dir )
+ dir = tar_extraction_directory( install_dir, downloaded_file_name )
+ elif isjar( file_path ):
+ dir = os.path.curdir
+ elif iszip( file_path ):
+ # <action type="download_by_url">http://downloads.sourceforge.net/project/picard/picard-tools/1.56/picard-to…</action>
+ zip_archive_extracted = extract_zip( file_path, install_dir )
+ dir = zip_extraction_directory( install_dir, downloaded_file_name )
+ else:
+ dir = os.path.abspath( install_dir )
+ else:
+ dir = os.path.abspath( install_dir )
+ return dir
+
+def zip_extraction_directory( file_path, file_name ):
+ """Try to return the correct extraction directory."""
+ files = [ filename for filename in os.listdir( file_path ) if not filename.endswith( '.zip' ) ]
+ if len( files ) > 1:
+ return os.path.abspath( file_path )
+ elif len( files ) == 1:
+ # If there is only on file it should be a directory.
+ if os.path.isdir( os.path.join( file_path, files[ 0 ] ) ):
+ return os.path.abspath( os.path.join( file_path, files[ 0 ] ) )
+ raise ValueError( 'Could not find directory for the extracted file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
+
+def zipfile_ok( path_to_archive ):
+ """
+ This function is a bit pedantic and not functionally necessary. It checks whether there is no file pointing outside of the extraction,
+ because ZipFile.extractall() has some potential security holes. See python zipfile documentation for more details.
+ """
+ basename = os.path.realpath( os.path.dirname( path_to_archive ) )
+ zip_archive = zipfile.ZipFile( path_to_archive )
+ for member in zip_archive.namelist():
+ member_path = os.path.realpath( os.path.join( basename, member ) )
+ if not member_path.startswith( basename ):
+ return False
+ return True
+
+def __shellquote(s):
+ """Quote and escape the supplied string for use in shell expressions."""
+ return "'" + s.replace( "'", "'\\''" ) + "'"
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Update tool migration process to handle orphan tool dependencies.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1520189c271f/
Changeset: 1520189c271f
User: Dave Bouvier
Date: 2013-08-26 17:42:35
Summary: Update tool migration process to handle orphan tool dependencies.
Affected #: 3 files
diff -r d51946b4a19f41ebb77e79774c01b89357aa007f -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -108,7 +108,11 @@
repository_dependencies_dict )
for tool_shed_repository in ordered_tool_shed_repositories:
- self.install_repository( repository_elem, tool_shed_repository, install_dependencies )
+ is_repository_dependency = self.__is_repository_dependency( name, changeset_revision, tool_shed_repository )
+ self.install_repository( repository_elem,
+ tool_shed_repository,
+ install_dependencies,
+ is_repository_dependency=is_repository_dependency )
else:
message = "\nNo tools associated with migration stage %s are defined in your " % str( latest_migration_script_number )
message += "file%s named %s,\nso no repositories will be installed on disk.\n" % ( plural, file_names )
@@ -320,7 +324,7 @@
tool_panel_elems.append( elem )
return tool_panel_elems
- def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies ):
+ def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies, is_repository_dependency=False ):
"""
Generate the metadata for the installed tool shed repository, among other things. If the installed tool_shed_repository contains tools
that are loaded into the Galaxy tool panel, this method will automatically eliminate all entries for each of the tools defined in the
@@ -333,37 +337,38 @@
repo_install_dir = os.path.join( self.tool_path, relative_install_dir )
else:
repo_install_dir = relative_install_dir
- for tool_elem in repository_elem:
- # The tool_elem looks something like this: <tool id="EMBOSS: antigenic1" version="5.0.0" file="emboss_antigenic.xml" />
- tool_config = tool_elem.get( 'file' )
- guid = self.get_guid( repository_clone_url, relative_install_dir, tool_config )
- # See if tool_config is defined inside of a section in self.proprietary_tool_panel_elems.
- is_displayed, tool_sections = self.get_containing_tool_sections( tool_config )
- if is_displayed:
- tool_panel_dict_for_tool_config = tool_util.generate_tool_panel_dict_for_tool_config( guid, tool_config, tool_sections=tool_sections )
- # The tool-panel_dict has the following structure.
- # {<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>}]}
- for k, v in tool_panel_dict_for_tool_config.items():
- tool_panel_dict_for_display[ k ] = v
- for tool_panel_dict in v:
- # Keep track of tool config file names associated with entries that have been made to the migrated_tools_conf.xml file so
- # they can be eliminated from all non-shed-related tool panel configs.
- tool_config_file = tool_panel_dict.get( 'tool_config', None )
- if tool_config_file:
- if tool_config_file not in tool_configs_to_filter:
- tool_configs_to_filter.append( tool_config_file )
- else:
- print 'The tool "%s" (%s) has not been enabled because it is not defined in a proprietary tool config (%s).' \
- % ( guid, tool_config, ", ".join( self.proprietary_tool_confs or [] ) )
- if tool_configs_to_filter:
- lock = threading.Lock()
- lock.acquire( True )
- try:
- self.filter_and_persist_proprietary_tool_panel_configs( tool_configs_to_filter )
- except Exception, e:
- log.exception( "Exception attempting to filter and persist non-shed-related tool panel configs:\n%s" % str( e ) )
- finally:
- lock.release()
+ if not is_repository_dependency:
+ for tool_elem in repository_elem:
+ # The tool_elem looks something like this: <tool id="EMBOSS: antigenic1" version="5.0.0" file="emboss_antigenic.xml" />
+ tool_config = tool_elem.get( 'file' )
+ guid = self.get_guid( repository_clone_url, relative_install_dir, tool_config )
+ # See if tool_config is defined inside of a section in self.proprietary_tool_panel_elems.
+ is_displayed, tool_sections = self.get_containing_tool_sections( tool_config )
+ if is_displayed:
+ tool_panel_dict_for_tool_config = tool_util.generate_tool_panel_dict_for_tool_config( guid, tool_config, tool_sections=tool_sections )
+ # The tool-panel_dict has the following structure.
+ # {<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>}]}
+ for k, v in tool_panel_dict_for_tool_config.items():
+ tool_panel_dict_for_display[ k ] = v
+ for tool_panel_dict in v:
+ # Keep track of tool config file names associated with entries that have been made to the migrated_tools_conf.xml file so
+ # they can be eliminated from all non-shed-related tool panel configs.
+ tool_config_file = tool_panel_dict.get( 'tool_config', None )
+ if tool_config_file:
+ if tool_config_file not in tool_configs_to_filter:
+ tool_configs_to_filter.append( tool_config_file )
+ else:
+ print 'The tool "%s" (%s) has not been enabled because it is not defined in a proprietary tool config (%s).' \
+ % ( guid, tool_config, ", ".join( self.proprietary_tool_confs or [] ) )
+ if tool_configs_to_filter:
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ self.filter_and_persist_proprietary_tool_panel_configs( tool_configs_to_filter )
+ except Exception, e:
+ log.exception( "Exception attempting to filter and persist non-shed-related tool panel configs:\n%s" % str( e ) )
+ finally:
+ lock.release()
metadata_dict, invalid_file_tups = metadata_util.generate_metadata_for_changeset_revision( app=self.app,
repository=tool_shed_repository,
changeset_revision=tool_shed_repository.changeset_revision,
@@ -377,7 +382,8 @@
tool_shed_repository.metadata = metadata_dict
self.app.sa_session.add( tool_shed_repository )
self.app.sa_session.flush()
- if 'tool_dependencies' in metadata_dict:
+ has_tool_dependencies = self.__has_tool_dependencies( metadata_dict )
+ if has_tool_dependencies:
# All tool_dependency objects must be created before the tools are processed even if no tool dependencies will be installed.
tool_dependencies = tool_dependency_util.create_tool_dependency_objects( self.app, tool_shed_repository, relative_install_dir, set_status=True )
else:
@@ -400,30 +406,31 @@
sample_files_copied )
# Copy remaining sample files included in the repository to the ~/tool-data directory of the local Galaxy instance.
tool_util.copy_sample_files( self.app, sample_files, tool_path=self.tool_path, sample_files_copied=sample_files_copied )
- if install_dependencies and tool_dependencies and 'tool_dependencies' in metadata_dict:
- # Install tool dependencies.
- suc.update_tool_shed_repository_status( self.app,
- tool_shed_repository,
- self.app.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
- # Get the tool_dependencies.xml file from disk.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repo_install_dir )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=self.app,
- tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_dependencies )
- for installed_tool_dependency in installed_tool_dependencies:
- if installed_tool_dependency.status == self.app.model.ToolDependency.installation_status.ERROR:
- print '\nThe following error occurred from the InstallManager while installing tool dependency ', installed_tool_dependency.name, ':'
- print installed_tool_dependency.error_message, '\n\n'
- tool_util.add_to_tool_panel( self.app,
- tool_shed_repository.name,
- repository_clone_url,
- tool_shed_repository.installed_changeset_revision,
- repository_tools_tups,
- self.repository_owner,
- self.migrated_tools_config,
- tool_panel_dict=tool_panel_dict_for_display,
- new_install=True )
+ if not is_repository_dependency:
+ tool_util.add_to_tool_panel( self.app,
+ tool_shed_repository.name,
+ repository_clone_url,
+ tool_shed_repository.installed_changeset_revision,
+ repository_tools_tups,
+ self.repository_owner,
+ self.migrated_tools_config,
+ tool_panel_dict=tool_panel_dict_for_display,
+ new_install=True )
+ if install_dependencies and tool_dependencies and has_tool_dependencies:
+ # Install tool dependencies.
+ suc.update_tool_shed_repository_status( self.app,
+ tool_shed_repository,
+ self.app.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
+ # Get the tool_dependencies.xml file from disk.
+ tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repo_install_dir )
+ installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=self.app,
+ tool_shed_repository=tool_shed_repository,
+ tool_dependencies_config=tool_dependencies_config,
+ tool_dependencies=tool_dependencies )
+ for installed_tool_dependency in installed_tool_dependencies:
+ if installed_tool_dependency.status == self.app.model.ToolDependency.installation_status.ERROR:
+ print '\nThe following error occurred from the InstallManager while installing tool dependency ', installed_tool_dependency.name, ':'
+ print installed_tool_dependency.error_message, '\n\n'
if 'datatypes' in metadata_dict:
tool_shed_repository.status = self.app.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES
if not tool_shed_repository.includes_datatypes:
@@ -455,7 +462,7 @@
except:
pass
- def install_repository( self, repository_elem, tool_shed_repository, install_dependencies ):
+ def install_repository( self, repository_elem, tool_shed_repository, install_dependencies, is_repository_dependency=False ):
"""Install a single repository, loading contained tools into the tool panel."""
# Install path is of the form: <tool path>/<tool shed>/repos/<repository owner>/<repository name>/<installed changeset revision>
relative_clone_dir = os.path.join( tool_shed_repository.tool_shed,
@@ -482,7 +489,8 @@
repository_clone_url=repository_clone_url,
relative_install_dir=relative_install_dir,
repository_elem=repository_elem,
- install_dependencies=install_dependencies )
+ install_dependencies=install_dependencies,
+ is_repository_dependency=is_repository_dependency )
self.app.sa_session.refresh( tool_shed_repository )
metadata_dict = tool_shed_repository.metadata
if 'tools' in metadata_dict:
@@ -526,6 +534,12 @@
self.app.sa_session.add( tool_version_association )
self.app.sa_session.flush()
suc.update_tool_shed_repository_status( self.app, tool_shed_repository, self.app.model.ToolShedRepository.installation_status.INSTALLED )
+ else:
+ print 'Error attempting to clone repository %s: %s' % ( str( tool_shed_repository.name ), str( error_message ) )
+ suc.update_tool_shed_repository_status( self.app,
+ tool_shed_repository,
+ self.app.model.ToolShedRepository.installation_status.ERROR,
+ error_message=error_message )
@property
def non_shed_tool_panel_configs( self ):
@@ -565,6 +579,12 @@
break
return ordered_tool_shed_repositories
+ def __has_tool_dependencies( self, metadata_dict ):
+ '''Determine if the provided metadata_dict specifies tool dependencies.'''
+ if 'tool_dependencies' in metadata_dict or 'orphan_tool_dependencies' in metadata_dict:
+ return True
+ return False
+
def __isinstalled( self, clone_dir ):
full_path = os.path.abspath( clone_dir )
if os.path.exists( full_path ):
@@ -574,6 +594,14 @@
return True
return False
+ def __is_repository_dependency( self, name, changeset_revision, tool_shed_repository ):
+ '''Determine if the provided tool shed repository is a repository dependency.'''
+ if str( tool_shed_repository.name ) != str( name ) or \
+ str( tool_shed_repository.owner ) != str( self.repository_owner ) or \
+ str( tool_shed_repository.changeset_revision ) != str( changeset_revision ):
+ return True
+ return False
+
def __is_valid_repository_tag( self, elem ):
# <repository name="emboss_datatypes" description="Datatypes for Emboss tools" changeset_revision="a89163f31369" />
if elem.tag != 'repository':
diff -r d51946b4a19f41ebb77e79774c01b89357aa007f -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -1521,10 +1521,12 @@
# purging is not supported by the mercurial API.
commands.update( get_configured_ui(), repo, rev=ctx_rev )
-def update_tool_shed_repository_status( app, tool_shed_repository, status ):
+def update_tool_shed_repository_status( app, tool_shed_repository, status, error_message=None ):
"""Update the status of a tool shed repository in the process of being installed into Galaxy."""
sa_session = app.model.context.current
tool_shed_repository.status = status
+ if error_message:
+ tool_shed_repository.error_message = str( error_message )
sa_session.add( tool_shed_repository )
sa_session.flush()
diff -r d51946b4a19f41ebb77e79774c01b89357aa007f -r 1520189c271f3a09a11f28b13548d7f0fce92fa1 lib/tool_shed/util/tool_dependency_util.py
--- a/lib/tool_shed/util/tool_dependency_util.py
+++ b/lib/tool_shed/util/tool_dependency_util.py
@@ -39,37 +39,6 @@
tool_dependencies[ dependency_key ] = requirements_dict
return tool_dependencies
-def get_download_url_for_platform( url_templates, platform_info_dict ):
- '''
- Compare the dict returned by get_platform_info() with the values specified in the base_url element. Return
- true if and only if all defined attributes match the corresponding dict entries. If an entry is not
- defined in the base_url element, it is assumed to be irrelevant at this stage. For example,
- <base_url os="darwin">http://hgdownload.cse.ucsc.edu/admin/exe/macOSX.${architecture}/faToTwoBit</base_url>
- where the OS must be 'darwin', but the architecture is filled in later using string.Template.
- '''
- os_ok = False
- architecture_ok = False
- for url_template in url_templates:
- os_name = url_template.get( 'os', None )
- architecture = url_template.get( 'architecture', None )
- if os_name:
- if os_name.lower() == platform_info_dict[ 'os' ]:
- os_ok = True
- else:
- os_ok = False
- else:
- os_ok = True
- if architecture:
- if architecture.lower() == platform_info_dict[ 'architecture' ]:
- architecture_ok = True
- else:
- architecture_ok = False
- else:
- architecture_ok = True
- if os_ok and architecture_ok:
- return url_template
- return None
-
def create_or_update_tool_dependency( app, tool_shed_repository, name, version, type, status, set_status=True ):
# Called from Galaxy (never the tool shed) when a new repository is being installed or when an uninstalled repository is being reinstalled.
sa_session = app.model.context.current
@@ -189,6 +158,37 @@
message += "This repository contains no tools, so it's defined tool dependencies are considered orphans within this repository.<br/>"
return message
+def get_download_url_for_platform( url_templates, platform_info_dict ):
+ '''
+ Compare the dict returned by get_platform_info() with the values specified in the base_url element. Return
+ true if and only if all defined attributes match the corresponding dict entries. If an entry is not
+ defined in the base_url element, it is assumed to be irrelevant at this stage. For example,
+ <base_url os="darwin">http://hgdownload.cse.ucsc.edu/admin/exe/macOSX.${architecture}/faToTwoBit</base_url>
+ where the OS must be 'darwin', but the architecture is filled in later using string.Template.
+ '''
+ os_ok = False
+ architecture_ok = False
+ for url_template in url_templates:
+ os_name = url_template.get( 'os', None )
+ architecture = url_template.get( 'architecture', None )
+ if os_name:
+ if os_name.lower() == platform_info_dict[ 'os' ]:
+ os_ok = True
+ else:
+ os_ok = False
+ else:
+ os_ok = True
+ if architecture:
+ if architecture.lower() == platform_info_dict[ 'architecture' ]:
+ architecture_ok = True
+ else:
+ architecture_ok = False
+ else:
+ architecture_ok = True
+ if os_ok and architecture_ok:
+ return url_template
+ return None
+
def get_installed_and_missing_tool_dependencies( trans, repository, all_tool_dependencies ):
if all_tool_dependencies:
tool_dependencies = {}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Move workflows JavaScript code to its own file for modularity and bundling purposes. Pack scripts.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d51946b4a19f/
Changeset: d51946b4a19f
User: jgoecks
Date: 2013-08-26 16:32:07
Summary: Move workflows JavaScript code to its own file for modularity and bundling purposes. Pack scripts.
Affected #: 6 files
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/galaxy.workflows.js
--- /dev/null
+++ b/static/scripts/galaxy.workflows.js
@@ -0,0 +1,617 @@
+$( function() {
+
+ if ( window.lt_ie_7 ) {
+ show_modal(
+ "Browser not supported",
+ "Sorry, the workflow editor is not supported for IE6 and below."
+ );
+ return;
+ }
+
+ // Init searching.
+ $("#tool-search-query").click( function (){
+ $(this).focus();
+ $(this).select();
+ })
+ .keyup( function () {
+ // Remove italics.
+ $(this).css("font-style", "normal");
+ // Don't update if same value as last time
+ if ( this.value.length < 3 ) {
+ reset_tool_search(false);
+ } else if ( this.value != this.lastValue ) {
+ // Add class to denote that searching is active.
+ $(this).addClass("search_active");
+ // input.addClass(config.loadingClass);
+ // Add '*' to facilitate partial matching.
+ var q = this.value + '*';
+ // Stop previous ajax-request
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ // Start a new ajax-request in X ms
+ $("#search-spinner").show();
+ this.timer = setTimeout(function () {
+ $.get(tool_search_url, { query: q }, function (data) {
+ // input.removeClass(config.loadingClass);
+ // Show live-search if results and search-term aren't empty
+ $("#search-no-results").hide();
+ // Hide all tool sections.
+ $(".toolSectionWrapper").hide();
+ // This hides all tools but not workflows link (which is in a .toolTitle div).
+ $(".toolSectionWrapper").find(".toolTitle").hide();
+ if ( data.length != 0 ) {
+ // Map tool ids to element ids and join them.
+ var s = $.map( data, function( n, i ) { return "link-" + n; } );
+ // First pass to show matching tools and their parents.
+ $(s).each( function(index,id) {
+ // Add class to denote match.
+ $("[id='"+id+"']").parent().addClass("search_match");
+ $("[id='"+id+"']").parent().show().parent().parent().show().parent().show();
+ });
+ // Hide labels that have no visible children.
+ $(".toolPanelLabel").each( function() {
+ var this_label = $(this);
+ var next = this_label.next();
+ var no_visible_tools = true;
+ // Look through tools following label and, if none are visible, hide label.
+ while (next.length !== 0 && next.hasClass("toolTitle")) {
+ if (next.is(":visible")) {
+ no_visible_tools = false;
+ break;
+ } else {
+ next = next.next();
+ }
+ }
+ if (no_visible_tools) {
+ this_label.hide();
+ }
+ });
+ } else {
+ $("#search-no-results").show();
+ }
+ $("#search-spinner").hide();
+ }, "json" );
+ }, 200 );
+ }
+ this.lastValue = this.value;
+ });
+
+ // Canvas overview management
+ canvas_manager = new CanvasManager( $("#canvas-viewport"), $("#overview") );
+
+ // Initialize workflow state
+ reset();
+ // Load the datatype info
+ $.ajax( {
+ url: get_datatypes_url,
+ dataType: "json",
+ cache: false,
+ success: function( data ) {
+ populate_datatype_info( data );
+ // Load workflow definition
+ $.ajax( {
+ url: load_workflow_url,
+ data: { id: workflow_id, "_": "true" },
+ dataType: 'json',
+ cache: false,
+ success: function( data ) {
+ reset();
+ workflow.from_simple( data );
+ workflow.has_changes = false;
+ workflow.fit_canvas_to_nodes();
+ scroll_to_nodes();
+ canvas_manager.draw_overview();
+ // Determine if any parameters were 'upgraded' and provide message
+ upgrade_message = "";
+ $.each( data.upgrade_messages, function( k, v ) {
+ upgrade_message += ( "<li>Step " + ( parseInt(k, 10) + 1 ) + ": " + workflow.nodes[k].name + "<ul>");
+ $.each( v, function( i, vv ) {
+ upgrade_message += "<li>" + vv +"</li>";
+ });
+ upgrade_message += "</ul></li>";
+ });
+ if ( upgrade_message ) {
+ show_modal( "Workflow loaded with changes",
+ "Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>" + upgrade_message + "</ul>",
+ { "Continue" : hide_modal } );
+ } else {
+ hide_modal();
+ }
+ show_workflow_parameters();
+ },
+ beforeSubmit: function( data ) {
+ show_message( "Loading workflow", "progress" );
+ }
+ });
+ }
+ });
+
+ // For autosave purposes
+ $(document).ajaxStart( function() {
+ active_ajax_call = true;
+ $(document).bind( "ajaxStop.global", function() {
+ active_ajax_call = false;
+ });
+ });
+
+ $(document).ajaxError( function ( e, x ) {
+ // console.log( e, x );
+ var message = x.responseText || x.statusText || "Could not connect to server";
+ show_modal( "Server error", message, { "Ignore error" : hide_modal } );
+ return false;
+ });
+
+ make_popupmenu( $("#workflow-options-button"), {
+ "Save" : save_current_workflow,
+ "Run": function() {
+ window.location = run_workflow_url;
+ },
+ //"Create New" : create_new_workflow_dialog,
+ "Edit Attributes" : edit_workflow_attributes,
+ //"Edit Workflow Outputs": edit_workflow_outputs,
+ "Auto Re-layout": layout_editor,
+ //"Load a Workflow" : load_workflow,
+ "Close": close_editor
+ });
+
+ function edit_workflow_outputs(){
+ workflow.clear_active_node();
+ $('.right-content').hide();
+ var new_content = "";
+ for (var node_key in workflow.nodes){
+ var node = workflow.nodes[node_key];
+ if(node.type == 'tool'){
+ new_content += "<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step " + node.id + " - " + node.name + "</div>";
+ for (var ot_key in node.output_terminals){
+ var output = node.output_terminals[ot_key];
+ // if (node.workflow_outputs[node.id + "|" + output.name]){
+ if ($.inArray(output.name, node.workflow_outputs) != -1){
+ new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' checked /></p>";
+ }
+ else{
+ new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' /></p>";
+ }
+ }
+ new_content += "</div>";
+ }
+ }
+ $("#output-fill-area").html(new_content);
+ $("#output-fill-area input").bind('click', function(){
+ var node_id = this.name.split('|')[0];
+ var output_name = this.name.split('|')[1];
+ if (this.checked){
+ if($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) == -1){
+ workflow.nodes[node_id].workflow_outputs.push(output_name);
+ }//else it's already in the array. Shouldn't happen, but forget it.
+ }else{
+ while ($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) != -1){
+ var ia = $.inArray(output_name, workflow.nodes[node_id].workflow_outputs);
+ workflow.nodes[node_id].workflow_outputs = workflow.nodes[node_id].workflow_outputs.slice(0,ia).concat( workflow.nodes[node_id].workflow_outputs.slice(ia+1) );
+ }
+ }
+ workflow.has_changes = true;
+ });
+ $('#workflow-output-area').show();
+ }
+
+ function layout_editor() {
+ workflow.layout();
+ workflow.fit_canvas_to_nodes();
+ scroll_to_nodes();
+ canvas_manager.draw_overview();
+ }
+
+ function edit_workflow_attributes() {
+ workflow.clear_active_node();
+ $('.right-content').hide();
+ $('#edit-attributes').show();
+
+ }
+
+ // On load, set the size to the pref stored in local storage if it exists
+ overview_size = $.jStorage.get("overview-size");
+ if (overview_size !== undefined) {
+ $("#overview-border").css( {
+ width: overview_size,
+ height: overview_size
+ });
+ }
+
+ // Show viewport on load unless pref says it's off
+ if ($.jStorage.get("overview-off")) {
+ hide_overview();
+ } else {
+ show_overview();
+ }
+
+ // Stores the size of the overview into local storage when it's resized
+ $("#overview-border").bind( "dragend", function( e, d ) {
+ var op = $(this).offsetParent();
+ var opo = op.offset();
+ var new_size = Math.max( op.width() - ( d.offsetX - opo.left ),
+ op.height() - ( d.offsetY - opo.top ) );
+ $.jStorage.set("overview-size", new_size + "px");
+ });
+
+ function show_overview() {
+ $.jStorage.set("overview-off", false);
+ $("#overview-border").css("right", "0px");
+ $("#close-viewport").css("background-position", "0px 0px");
+ }
+
+ function hide_overview() {
+ $.jStorage.set("overview-off", true);
+ $("#overview-border").css("right", "20000px");
+ $("#close-viewport").css("background-position", "12px 0px");
+ }
+
+ // Lets the overview be toggled visible and invisible, adjusting the arrows accordingly
+ $("#close-viewport").click( function() {
+ if ( $("#overview-border").css("right") === "0px" ) {
+ hide_overview();
+ } else {
+ show_overview();
+ }
+ });
+
+ // Unload handler
+ window.onbeforeunload = function() {
+ if ( workflow && workflow.has_changes ) {
+ return "There are unsaved changes to your workflow which will be lost.";
+ }
+ };
+
+ // Tool menu
+ $( "div.toolSectionBody" ).hide();
+ $( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" );
+ var last_expanded = null;
+ $( "div.toolSectionTitle" ).each( function() {
+ var body = $(this).next( "div.toolSectionBody" );
+ $(this).click( function() {
+ if ( body.is( ":hidden" ) ) {
+ if ( last_expanded ) last_expanded.slideUp( "fast" );
+ last_expanded = body;
+ body.slideDown( "fast" );
+ }
+ else {
+ body.slideUp( "fast" );
+ last_expanded = null;
+ }
+ });
+ });
+
+ // Rename async.
+ async_save_text("workflow-name", "workflow-name", rename_async_url, "new_name");
+
+ // Tag async. Simply have the workflow edit element generate a click on the tag element to activate tagging.
+ $('#workflow-tag').click( function() {
+ $('.tag-area').click();
+ return false;
+ });
+ // Annotate async.
+ async_save_text("workflow-annotation", "workflow-annotation", annotate_async_url, "new_annotation", 25, true, 4);
+});
+
+// Global state for the whole workflow
+function reset() {
+ if ( workflow ) {
+ workflow.remove_all();
+ }
+ workflow = new Workflow( $("#canvas-container") );
+}
+
+function scroll_to_nodes() {
+ var cv = $("#canvas-viewport");
+ var cc = $("#canvas-container");
+ var top, left;
+ if ( cc.width() < cv.width() ) {
+ left = ( cv.width() - cc.width() ) / 2;
+ } else {
+ left = 0;
+ }
+ if ( cc.height() < cv.height() ) {
+ top = ( cv.height() - cc.height() ) / 2;
+ } else {
+ top = 0;
+ }
+ cc.css( { left: left, top: top } );
+}
+
+// Add a new step to the workflow by tool id
+function add_node_for_tool( id, title ) {
+ var node = prebuild_node( 'tool', title, id );
+ workflow.add_node( node );
+ workflow.fit_canvas_to_nodes();
+ canvas_manager.draw_overview();
+ workflow.activate_node( node );
+ $.ajax( {
+ url: get_new_module_info_url,
+ data: { type: "tool", tool_id: id, "_": "true" },
+ global: false,
+ dataType: "json",
+ success: function( data ) {
+ node.init_field_data( data );
+ },
+ error: function( x, e ) {
+ var m = "error loading field data";
+ if ( x.status === 0 ) {
+ m += ", server unavailable";
+ }
+ node.error( m );
+ }
+ });
+}
+
+function add_node_for_module( type, title ) {
+ node = prebuild_node( type, title );
+ workflow.add_node( node );
+ workflow.fit_canvas_to_nodes();
+ canvas_manager.draw_overview();
+ workflow.activate_node( node );
+ $.ajax( {
+ url: get_new_module_info_url,
+ data: { type: type, "_": "true" },
+ dataType: "json",
+ success: function( data ) {
+ node.init_field_data( data );
+ },
+ error: function( x, e ) {
+ var m = "error loading field data"
+ if ( x.status == 0 ) {
+ m += ", server unavailable"
+ }
+ node.error( m );
+ }
+ });
+}
+
+// This function preloads how to display known pja's.
+function display_pja(pja, node) {
+ // DBTODO SANITIZE INPUTS.
+ $("#pja_container").append( get_pja_form(pja) );
+ $("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function (){
+ action_to_rem = $(this).closest(".toolForm", ".action_tag").children(".action_tag:first").text();
+ $(this).closest(".toolForm").remove();
+ delete workflow.active_node.post_job_actions[action_to_rem];
+ workflow.active_form_has_changes = true;
+ });
+}
+
+function display_pja_list(){
+ return pja_list;
+}
+
+function display_file_list(node){
+ addlist = "<select id='node_data_list' name='node_data_list'>";
+ for (var out_terminal in node.output_terminals){
+ addlist += "<option value='" + out_terminal + "'>"+ out_terminal +"</option>";
+ }
+ addlist += "</select>";
+ return addlist;
+}
+
+function new_pja(action_type, target, node){
+ if (node.post_job_actions === undefined){
+ //New tool node, set up dict.
+ node.post_job_actions = {};
+ }
+ if (node.post_job_actions[action_type+target] === undefined){
+ var new_pja = {};
+ new_pja.action_type = action_type;
+ new_pja.output_name = target;
+ node.post_job_actions[action_type+target] = null;
+ node.post_job_actions[action_type+target] = new_pja;
+ display_pja(new_pja, node);
+ workflow.active_form_has_changes = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function show_workflow_parameters(){
+ var parameter_re = /\$\{.+?\}/g;
+ var workflow_parameters = [];
+ var wf_parm_container = $("#workflow-parameters-container");
+ var wf_parm_box = $("#workflow-parameters-box");
+ var new_parameter_content = "";
+ var matches = [];
+ $.each(workflow.nodes, function (k, node){
+ var form_matches = node.form_html.match(parameter_re);
+ if (form_matches){
+ matches = matches.concat(form_matches);
+ }
+ if (node.post_job_actions){
+ $.each(node.post_job_actions, function(k, pja){
+ if (pja.action_arguments){
+ $.each(pja.action_arguments, function(k, action_argument){
+ var arg_matches = action_argument.match(parameter_re);
+ if (arg_matches){
+ matches = matches.concat(arg_matches);
+ }
+ });
+ }
+ });
+ if (matches){
+ $.each(matches, function(k, element){
+ if ($.inArray(element, workflow_parameters) === -1){
+ workflow_parameters.push(element);
+ }
+ });
+ }
+ }
+ });
+ if (workflow_parameters && workflow_parameters.length !== 0){
+ $.each(workflow_parameters, function(k, element){
+ new_parameter_content += "<div>" + element.substring(2, element.length -1) + "</div>";
+ });
+ wf_parm_container.html(new_parameter_content);
+ wf_parm_box.show();
+ }else{
+ wf_parm_container.html(new_parameter_content);
+ wf_parm_box.hide();
+ }
+}
+
+function show_form_for_tool( text, node ) {
+ $('.right-content').hide();
+ $("#right-content").show().html( text );
+ // Add metadata form to tool.
+ if (node) {
+ $("#right-content").find(".toolForm:first").after( "<p><div class='metadataForm'> \
+ <div class='metadataFormTitle'>Edit Step Attributes</div> \
+ <div class='form-row'> \
+ <label>Annotation / Notes:</label> \
+ <div style='margin-right: 10px;'> \
+ <textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \
+ <div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \
+ </div> \
+ </div> \
+ </div>" );
+ }
+ // Add step actions.
+ if (node && node.type=='tool'){
+ pjastr = "<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> \
+ " + display_pja_list() + " <br/> "+ display_file_list(node) + " <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div>\
+ </div><div class='form-row'>\
+ <div style='margin-right: 10px;'><span id='pja_container'></span>";
+ pjastr += "<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";
+ $("#right-content").find(".toolForm").after( pjastr );
+ for (var key in node.post_job_actions){
+ if (key != "undefined"){ //To make sure we haven't just deleted it.
+ display_pja(node.post_job_actions[key], node);
+ }
+ }
+ $("#add_pja").click(function (){
+ new_pja($("#new_pja_list").val(),$("#node_data_list").val(), node);
+ });
+ }
+ $("#right-content").find( "form" ).ajaxForm( {
+ type: 'POST',
+ dataType: 'json',
+ success: function( data ) {
+ workflow.active_form_has_changes = false;
+ node.update_field_data( data );
+ show_workflow_parameters();
+ },
+ beforeSubmit: function( data ) {
+ data.push( { name: 'tool_state', value: node.tool_state } );
+ data.push( { name: '_', value: "true" } );
+ }
+ }).each( function() {
+ var form = this;
+ $(this).find( "select[refresh_on_change='true']").change( function() {
+ $(form).submit();
+ });
+ $(this).find( ".popupmenu" ).each( function() {
+ var id = $(this).parents( "div.form-row" ).attr( 'id' );
+ var b = $('<a class="popup-arrow" id="popup-arrow-for-' + id + '">▼</a>');
+ var options = {};
+ $(this).find( "button" ).each( function() {
+ var name = $(this).attr( 'name' );
+ var value = $(this).attr( 'value' );
+ options[ $(this).text() ] = function() {
+ $(form).append( "<input type='hidden' name='"+name+"' value='"+value+"' />" ).submit();
+ };
+ });
+ b.insertAfter( this );
+ $(this).remove();
+ make_popupmenu( b, options );
+ });
+ // Implements auto-saving based on whether the inputs change. We consider
+ // "changed" to be when a field is accessed and not necessarily modified
+ // because of an issue where "onchange" is not triggered when activating
+ // another node, or saving the workflow.
+ $(this).find("input,textarea,select").each( function() {
+ $(this).bind("focus click", function() {
+ workflow.active_form_has_changes = true;
+ });
+ });
+ });
+}
+
+var close_editor = function() {
+ workflow.check_changes_in_active_form();
+ if ( workflow && workflow.has_changes ) {
+ do_close = function() {
+ window.onbeforeunload = undefined;
+ window.document.location = workflow_index_url;
+ };
+ show_modal( "Close workflow editor",
+ "There are unsaved changes to your workflow which will be lost.",
+ {
+ "Cancel" : hide_modal,
+ "Save Changes" : function() {
+ save_current_workflow( null, do_close );
+ }
+ }, {
+ "Don't Save": do_close
+ } );
+ } else {
+ window.document.location = workflow_index_url;
+ }
+};
+
+var save_current_workflow = function ( eventObj, success_callback ) {
+ show_message( "Saving workflow", "progress" );
+ workflow.check_changes_in_active_form();
+ if (!workflow.has_changes) {
+ hide_modal();
+ if ( success_callback ) {
+ success_callback();
+ }
+ return;
+ }
+ workflow.rectify_workflow_outputs();
+ var savefn = function(callback) {
+ $.ajax( {
+ url: save_workflow_url,
+ type: "POST",
+ data: {
+ id: workflow_id,
+ workflow_data: function() { return JSON.stringify( workflow.to_simple() ); },
+ "_": "true"
+ },
+ dataType: 'json',
+ success: function( data ) {
+ var body = $("<div></div>").text( data.message );
+ if ( data.errors ) {
+ body.addClass( "warningmark" );
+ var errlist = $( "<ul/>" );
+ $.each( data.errors, function( i, v ) {
+ $("<li></li>").text( v ).appendTo( errlist );
+ });
+ body.append( errlist );
+ } else {
+ body.addClass( "donemark" );
+ }
+ workflow.name = data.name;
+ workflow.has_changes = false;
+ workflow.stored = true;
+ show_workflow_parameters();
+ if ( data.errors ) {
+ show_modal( "Saving workflow", body, { "Ok" : hide_modal } );
+ } else {
+ if (callback) {
+ callback();
+ }
+ hide_modal();
+ }
+ }
+ });
+ };
+
+ // We bind to ajaxStop because of auto-saving, since the form submission ajax
+ // call needs to be completed so that the new data is saved
+ if (active_ajax_call) {
+ $(document).bind('ajaxStop.save_workflow', function() {
+ $(document).unbind('ajaxStop.save_workflow');
+ savefn();
+ $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here
+ active_ajax_call = false;
+ });
+ } else {
+ savefn(success_callback);
+ }
+};
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/galaxy.workflows.js
--- /dev/null
+++ b/static/scripts/packed/galaxy.workflows.js
@@ -0,0 +1,1 @@
+$(function(){if(window.lt_ie_7){show_modal("Browser not supported","Sorry, the workflow editor is not supported for IE6 and below.");return}$("#tool-search-query").click(function(){$(this).focus();$(this).select()}).keyup(function(){$(this).css("font-style","normal");if(this.value.length<3){reset_tool_search(false)}else{if(this.value!=this.lastValue){$(this).addClass("search_active");var g=this.value+"*";if(this.timer){clearTimeout(this.timer)}$("#search-spinner").show();this.timer=setTimeout(function(){$.get(tool_search_url,{query:g},function(i){$("#search-no-results").hide();$(".toolSectionWrapper").hide();$(".toolSectionWrapper").find(".toolTitle").hide();if(i.length!=0){var h=$.map(i,function(k,j){return"link-"+k});$(h).each(function(j,k){$("[id='"+k+"']").parent().addClass("search_match");$("[id='"+k+"']").parent().show().parent().parent().show().parent().show()});$(".toolPanelLabel").each(function(){var l=$(this);var k=l.next();var j=true;while(k.length!==0&&k.hasClass("toolTitle")){if(k.is(":visible")){j=false;break}else{k=k.next()}}if(j){l.hide()}})}else{$("#search-no-results").show()}$("#search-spinner").hide()},"json")},200)}}this.lastValue=this.value});canvas_manager=new CanvasManager($("#canvas-viewport"),$("#overview"));reset();$.ajax({url:get_datatypes_url,dataType:"json",cache:false,success:function(g){populate_datatype_info(g);$.ajax({url:load_workflow_url,data:{id:workflow_id,_:"true"},dataType:"json",cache:false,success:function(h){reset();workflow.from_simple(h);workflow.has_changes=false;workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview();upgrade_message="";$.each(h.upgrade_messages,function(j,i){upgrade_message+=("<li>Step "+(parseInt(j,10)+1)+": "+workflow.nodes[j].name+"<ul>");$.each(i,function(k,l){upgrade_message+="<li>"+l+"</li>"});upgrade_message+="</ul></li>"});if(upgrade_message){show_modal("Workflow loaded with changes","Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>"+upgrade_message+"</ul>",{Continue:hide_modal})}else{hide_modal()}show_workflow_parameters()},beforeSubmit:function(h){show_message("Loading workflow","progress")}})}});$(document).ajaxStart(function(){active_ajax_call=true;$(document).bind("ajaxStop.global",function(){active_ajax_call=false})});$(document).ajaxError(function(i,g){var h=g.responseText||g.statusText||"Could not connect to server";show_modal("Server error",h,{"Ignore error":hide_modal});return false});make_popupmenu($("#workflow-options-button"),{Save:save_current_workflow,Run:function(){window.location=run_workflow_url},"Edit Attributes":c,"Auto Re-layout":f,Close:close_editor});function b(){workflow.clear_active_node();$(".right-content").hide();var j="";for(var h in workflow.nodes){var i=workflow.nodes[h];if(i.type=="tool"){j+="<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step "+i.id+" - "+i.name+"</div>";for(var k in i.output_terminals){var g=i.output_terminals[k];if($.inArray(g.name,i.workflow_outputs)!=-1){j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' checked /></p>"}else{j+="<p>"+g.name+"<input type='checkbox' name='"+i.id+"|"+g.name+"' /></p>"}}j+="</div>"}}$("#output-fill-area").html(j);$("#output-fill-area input").bind("click",function(){var n=this.name.split("|")[0];var l=this.name.split("|")[1];if(this.checked){if($.inArray(l,workflow.nodes[n].workflow_outputs)==-1){workflow.nodes[n].workflow_outputs.push(l)}}else{while($.inArray(l,workflow.nodes[n].workflow_outputs)!=-1){var m=$.inArray(l,workflow.nodes[n].workflow_outputs);workflow.nodes[n].workflow_outputs=workflow.nodes[n].workflow_outputs.slice(0,m).concat(workflow.nodes[n].workflow_outputs.slice(m+1))}}workflow.has_changes=true});$("#workflow-output-area").show()}function f(){workflow.layout();workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview()}function c(){workflow.clear_active_node();$(".right-content").hide();$("#edit-attributes").show()}overview_size=$.jStorage.get("overview-size");if(overview_size!==undefined){$("#overview-border").css({width:overview_size,height:overview_size})}if($.jStorage.get("overview-off")){d()}else{e()}$("#overview-border").bind("dragend",function(h,j){var k=$(this).offsetParent();var i=k.offset();var g=Math.max(k.width()-(j.offsetX-i.left),k.height()-(j.offsetY-i.top));$.jStorage.set("overview-size",g+"px")});function e(){$.jStorage.set("overview-off",false);$("#overview-border").css("right","0px");$("#close-viewport").css("background-position","0px 0px")}function d(){$.jStorage.set("overview-off",true);$("#overview-border").css("right","20000px");$("#close-viewport").css("background-position","12px 0px")}$("#close-viewport").click(function(){if($("#overview-border").css("right")==="0px"){d()}else{e()}});window.onbeforeunload=function(){if(workflow&&workflow.has_changes){return"There are unsaved changes to your workflow which will be lost."}};$("div.toolSectionBody").hide();$("div.toolSectionTitle > span").wrap("<a href='#'></a>");var a=null;$("div.toolSectionTitle").each(function(){var g=$(this).next("div.toolSectionBody");$(this).click(function(){if(g.is(":hidden")){if(a){a.slideUp("fast")}a=g;g.slideDown("fast")}else{g.slideUp("fast");a=null}})});async_save_text("workflow-name","workflow-name",rename_async_url,"new_name");$("#workflow-tag").click(function(){$(".tag-area").click();return false});async_save_text("workflow-annotation","workflow-annotation",annotate_async_url,"new_annotation",25,true,4)});function reset(){if(workflow){workflow.remove_all()}workflow=new Workflow($("#canvas-container"))}function scroll_to_nodes(){var a=$("#canvas-viewport");var d=$("#canvas-container");var c,b;if(d.width()<a.width()){b=(a.width()-d.width())/2}else{b=0}if(d.height()<a.height()){c=(a.height()-d.height())/2}else{c=0}d.css({left:b,top:c})}function add_node_for_tool(c,b){var a=prebuild_node("tool",b,c);workflow.add_node(a);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(a);$.ajax({url:get_new_module_info_url,data:{type:"tool",tool_id:c,_:"true"},global:false,dataType:"json",success:function(d){a.init_field_data(d)},error:function(f,g){var d="error loading field data";if(f.status===0){d+=", server unavailable"}a.error(d)}})}function add_node_for_module(a,b){node=prebuild_node(a,b);workflow.add_node(node);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(node);$.ajax({url:get_new_module_info_url,data:{type:a,_:"true"},dataType:"json",success:function(c){node.init_field_data(c)},error:function(d,f){var c="error loading field data";if(d.status==0){c+=", server unavailable"}node.error(c)}})}function display_pja(b,a){$("#pja_container").append(get_pja_form(b));$("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function(){action_to_rem=$(this).closest(".toolForm",".action_tag").children(".action_tag:first").text();$(this).closest(".toolForm").remove();delete workflow.active_node.post_job_actions[action_to_rem];workflow.active_form_has_changes=true})}function display_pja_list(){return pja_list}function display_file_list(b){addlist="<select id='node_data_list' name='node_data_list'>";for(var a in b.output_terminals){addlist+="<option value='"+a+"'>"+a+"</option>"}addlist+="</select>";return addlist}function new_pja(d,b,a){if(a.post_job_actions===undefined){a.post_job_actions={}}if(a.post_job_actions[d+b]===undefined){var c={};c.action_type=d;c.output_name=b;a.post_job_actions[d+b]=null;a.post_job_actions[d+b]=c;display_pja(c,a);workflow.active_form_has_changes=true;return true}else{return false}}function show_workflow_parameters(){var c=/\$\{.+?\}/g;var b=[];var f=$("#workflow-parameters-container");var e=$("#workflow-parameters-box");var a="";var d=[];$.each(workflow.nodes,function(g,h){var i=h.form_html.match(c);if(i){d=d.concat(i)}if(h.post_job_actions){$.each(h.post_job_actions,function(j,l){if(l.action_arguments){$.each(l.action_arguments,function(m,n){var o=n.match(c);if(o){d=d.concat(o)}})}});if(d){$.each(d,function(j,l){if($.inArray(l,b)===-1){b.push(l)}})}}});if(b&&b.length!==0){$.each(b,function(g,h){a+="<div>"+h.substring(2,h.length-1)+"</div>"});f.html(a);e.show()}else{f.html(a);e.hide()}}function show_form_for_tool(c,b){$(".right-content").hide();$("#right-content").show().html(c);if(b){$("#right-content").find(".toolForm:first").after("<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Attributes</div><div class='form-row'><label>Annotation / Notes:</label><div style='margin-right: 10px;'><textarea name='annotation' rows='3' style='width: 100%'>"+b.annotation+"</textarea><div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div></div></div></div>")}if(b&&b.type=="tool"){pjastr="<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> "+display_pja_list()+" <br/> "+display_file_list(b)+" <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div></div><div class='form-row'><div style='margin-right: 10px;'><span id='pja_container'></span>";pjastr+="<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";$("#right-content").find(".toolForm").after(pjastr);for(var a in b.post_job_actions){if(a!="undefined"){display_pja(b.post_job_actions[a],b)}}$("#add_pja").click(function(){new_pja($("#new_pja_list").val(),$("#node_data_list").val(),b)})}$("#right-content").find("form").ajaxForm({type:"POST",dataType:"json",success:function(d){workflow.active_form_has_changes=false;b.update_field_data(d);show_workflow_parameters()},beforeSubmit:function(d){d.push({name:"tool_state",value:b.tool_state});d.push({name:"_",value:"true"})}}).each(function(){var d=this;$(this).find("select[refresh_on_change='true']").change(function(){$(d).submit()});$(this).find(".popupmenu").each(function(){var g=$(this).parents("div.form-row").attr("id");var e=$('<a class="popup-arrow" id="popup-arrow-for-'+g+'">▼</a>');var f={};$(this).find("button").each(function(){var h=$(this).attr("name");var i=$(this).attr("value");f[$(this).text()]=function(){$(d).append("<input type='hidden' name='"+h+"' value='"+i+"' />").submit()}});e.insertAfter(this);$(this).remove();make_popupmenu(e,f)});$(this).find("input,textarea,select").each(function(){$(this).bind("focus click",function(){workflow.active_form_has_changes=true})})})}var close_editor=function(){workflow.check_changes_in_active_form();if(workflow&&workflow.has_changes){do_close=function(){window.onbeforeunload=undefined;window.document.location=workflow_index_url};show_modal("Close workflow editor","There are unsaved changes to your workflow which will be lost.",{Cancel:hide_modal,"Save Changes":function(){save_current_workflow(null,do_close)}},{"Don't Save":do_close})}else{window.document.location=workflow_index_url}};var save_current_workflow=function(b,c){show_message("Saving workflow","progress");workflow.check_changes_in_active_form();if(!workflow.has_changes){hide_modal();if(c){c()}return}workflow.rectify_workflow_outputs();var a=function(d){$.ajax({url:save_workflow_url,type:"POST",data:{id:workflow_id,workflow_data:function(){return JSON.stringify(workflow.to_simple())},_:"true"},dataType:"json",success:function(g){var e=$("<div></div>").text(g.message);if(g.errors){e.addClass("warningmark");var f=$("<ul/>");$.each(g.errors,function(j,h){$("<li></li>").text(h).appendTo(f)});e.append(f)}else{e.addClass("donemark")}workflow.name=g.name;workflow.has_changes=false;workflow.stored=true;show_workflow_parameters();if(g.errors){show_modal("Saving workflow",e,{Ok:hide_modal})}else{if(d){d()}hide_modal()}}})};if(active_ajax_call){$(document).bind("ajaxStop.save_workflow",function(){$(document).unbind("ajaxStop.save_workflow");a();$(document).unbind("ajaxStop.save_workflow");active_ajax_call=false})}else{a(c)}};
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/mvc/tools.js
--- a/static/scripts/packed/mvc/tools.js
+++ b/static/scripts/packed/mvc/tools.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/backbone-relational"],function(t,a,u){var f={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},get_samples:function(){var w=this.get("type"),v=null;if(w==="number"){v=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(w==="select"){v=t.map(this.get("options"),function(x){return x[0]})}}return v},set_value:function(v){this.set("value",v||"")}},{TYPE_DICT:{number:d},create:function(v){var w=e.TYPE_DICT[v.type]||e;return new w(v)}});var d=e.extend({defaults:t.extend({},e.prototype.defaults,{min:null,max:null}),initialize:function(){e.prototype.initialize.call(this);if(this.attributes.min){this.attributes.min=parseInt(this.attributes.min,10)}if(this.attributes.max){this.attributes.max=parseInt(this.attributes.max,10)}},set_value:function(v){this.set("value",parseInt(v,10))}});var h=Backbone.RelationalModel.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[]},initialize:function(v){this.attributes.inputs=new Backbone.Collection(t.map(v.inputs,function(w){return e.create(w)}))},urlRoot:galaxy_config.root+"api/tools",copy:function(w){var x=new h(this.toJSON());if(w){var v=new Backbone.Collection();x.get("inputs").each(function(y){if(y.get_samples()){v.push(y)}});x.set("inputs",v)}return x},apply_search_results:function(v){(t.indexOf(v,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(v,w){this.get("inputs").find(function(x){return x.get("name")===v}).set("value",w)},set_input_values:function(w){var v=this;t.each(t.keys(w),function(x){v.set_input_value(x,w[x])})},run:function(){return this._run()},rerun:function(w,v){return this._run({action:"rerun",target_dataset_id:w.id,regions:v})},get_inputs_dict:function(){var v={};this.get("inputs").each(function(w){v[w.get("name")]=w.get("value")});return v},_run:function(x){var y=t.extend({tool_id:this.id,inputs:this.get_inputs_dict()},x);var w=$.Deferred(),v=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(y),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(z){return z!=="pending"}});$.when(v.go()).then(function(z){w.resolve(new u.DatasetCollection().reset(z))});return w}});t.extend(h.prototype,f);var n=Backbone.View.extend({});var k=Backbone.Collection.extend({model:h});var r=Backbone.Model.extend(f);var i=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){t.each(this.attributes.elems,function(v){v.show()});this.show();this.set("open",false)},apply_search_results:function(w){var x=true,v;t.each(this.attributes.elems,function(y){if(y instanceof r){v=y;v.hide()}else{if(y instanceof h){if(y.apply_search_results(w)){x=false;if(v){v.show()}}}}});if(x){this.hide()}else{this.show();this.set("open",true)}}});t.extend(i.prototype,f);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var x=this.attributes.query;if(x.length<this.attributes.min_chars_for_search){this.set("results",null);return}var w=x+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var v=this;this.timer=setTimeout(function(){$.get(v.attributes.search_url,{query:w},function(y){v.set("results",y);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});t.extend(c.prototype,f);var l=Backbone.Model.extend({initialize:function(v){this.attributes.tool_search=v.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=v.tools;this.attributes.layout=new Backbone.Collection(this.parse(v.layout))},parse:function(w){var v=this,x=function(A){var z=A.model_class;if(z.indexOf("Tool")===z.length-4){return v.attributes.tools.get(A.id)}else{if(z==="ToolSection"){var y=t.map(A.elems,x);A.elems=y;return new i(A)}else{if(z==="ToolSectionLabel"){return new r(A)}}}};return t.map(w,x)},clear_search_results:function(){this.get("layout").each(function(v){if(v instanceof i){v.clear_search_results()}else{v.show()}})},apply_search_results:function(){var w=this.get("tool_search").get("results");if(w===null){this.clear_search_results();return}var v=null;this.get("layout").each(function(x){if(x instanceof r){v=x;v.hide()}else{if(x instanceof h){if(x.apply_search_results(w)){if(v){v.show()}}}else{v=null;x.apply_search_results(w)}}})}});var p=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var j=p.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var b=p.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var o=p.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){p.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var v=this.$el.find(".toolSectionBody");t.each(this.model.attributes.elems,function(w){if(w instanceof h){var x=new j({model:w,className:"toolTitle"});x.render();v.append(x.$el)}else{if(w instanceof r){var y=new b({model:w});y.render();v.append(y.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var m=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(v){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===v.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var s=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var v=this;var w=new m({model:this.model.get("tool_search")});w.render();v.$el.append(w.$el);this.model.get("layout").each(function(y){if(y instanceof i){var x=new o({model:y});x.render();v.$el.append(x.$el)}else{if(y instanceof h){var z=new j({model:y,className:"toolTitleNoSection"});z.render();v.$el.append(z.$el)}else{if(y instanceof r){var A=new b({model:y});A.render();v.$el.append(A.$el)}}}});v.$el.find("a.tool-link").click(function(z){var y=$(this).attr("class").split(/\s+/)[0],x=v.model.get("tools").get(y);v.trigger("tool_link_click",z,x)});return this},handle_search_results:function(){var v=this.model.get("tool_search").get("results");if(v&&v.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var q=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var g=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new s({collection:this.collection});this.tool_form_view=new q()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var v=this;this.tool_panel_view.on("tool_link_click",function(x,w){x.preventDefault();v.show_tool(w)})},show_tool:function(w){var v=this;w.fetch().done(function(){v.tool_form_view.model=w;v.tool_form_view.render();v.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,Tool:h,ToolCollection:k,ToolSearch:c,ToolPanel:l,ToolPanelView:s,ToolFormView:q}});
\ No newline at end of file
+define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/backbone-relational"],function(x,a,y){var g={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},subModelTypes:{integer:"IntegerToolParameter","float":"FloatToolParameter",data:"DataToolParameter",select:"SelectToolParameter"},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},set_value:function(z){this.set("value",z||"")}});var o={};Backbone.Relational.store.addModelScope(o);var j=o.DataToolParameter=e.extend({});var d=o.IntegerToolParameter=e.extend({set_value:function(z){this.set("value",parseInt(z,10))},get_samples:function(){return d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}});var f=o.FloatToolParameter=d.extend({set_value:function(z){this.set("value",parseFloat(z))}});var t=o.SelectToolParameter=e.extend({get_samples:function(){return x.map(this.get("options"),function(z){return z[0]})}});var i=Backbone.RelationalModel.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[],outputs:[]},relations:[{type:Backbone.HasMany,key:"inputs",relatedModel:e}],urlRoot:galaxy_config.root+"api/tools",remove_inputs:function(A){var z=this,B=z.get("inputs").filter(function(C){return(A.indexOf(C.get("type"))!==-1)});z.get("inputs").remove(B)},copy:function(A){var B=new i(this.toJSON());if(A){var z=new Backbone.Collection();B.get("inputs").each(function(C){if(C.get_samples()){z.push(C)}});B.set("inputs",z)}return B},apply_search_results:function(z){(x.indexOf(z,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(z,A){this.get("inputs").find(function(B){return B.get("name")===z}).set("value",A)},set_input_values:function(A){var z=this;x.each(x.keys(A),function(B){z.set_input_value(B,A[B])})},run:function(){return this._run()},rerun:function(A,z){return this._run({action:"rerun",target_dataset_id:A.id,regions:z})},get_inputs_dict:function(){var z={};this.get("inputs").each(function(A){z[A.get("name")]=A.get("value")});return z},_run:function(B){var C=x.extend({tool_id:this.id,inputs:this.get_inputs_dict()},B);var A=$.Deferred(),z=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(C),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(D){return D!=="pending"}});$.when(z.go()).then(function(D){A.resolve(new y.DatasetCollection().reset(D))});return A}});x.extend(i.prototype,g);var q=Backbone.View.extend({});var m=Backbone.Collection.extend({model:i});var v=Backbone.Model.extend(g);var k=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){x.each(this.attributes.elems,function(z){z.show()});this.show();this.set("open",false)},apply_search_results:function(A){var B=true,z;x.each(this.attributes.elems,function(C){if(C instanceof v){z=C;z.hide()}else{if(C instanceof i){if(C.apply_search_results(A)){B=false;if(z){z.show()}}}}});if(B){this.hide()}else{this.show();this.set("open",true)}}});x.extend(k.prototype,g);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var B=this.attributes.query;if(B.length<this.attributes.min_chars_for_search){this.set("results",null);return}var A=B+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var z=this;this.timer=setTimeout(function(){$.get(z.attributes.search_url,{query:A},function(C){z.set("results",C);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});x.extend(c.prototype,g);var n=Backbone.Model.extend({initialize:function(z){this.attributes.tool_search=z.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=z.tools;this.attributes.layout=new Backbone.Collection(this.parse(z.layout))},parse:function(A){var z=this,B=function(E){var D=E.model_class;if(D.indexOf("Tool")===D.length-4){return z.attributes.tools.get(E.id)}else{if(D==="ToolSection"){var C=x.map(E.elems,B);E.elems=C;return new k(E)}else{if(D==="ToolSectionLabel"){return new v(E)}}}};return x.map(A,B)},clear_search_results:function(){this.get("layout").each(function(z){if(z instanceof k){z.clear_search_results()}else{z.show()}})},apply_search_results:function(){var A=this.get("tool_search").get("results");if(A===null){this.clear_search_results();return}var z=null;this.get("layout").each(function(B){if(B instanceof v){z=B;z.hide()}else{if(B instanceof i){if(B.apply_search_results(A)){if(z){z.show()}}}else{z=null;B.apply_search_results(A)}}})}});var s=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var l=s.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var b=s.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var r=s.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){s.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var z=this.$el.find(".toolSectionBody");x.each(this.model.attributes.elems,function(A){if(A instanceof i){var B=new l({model:A,className:"toolTitle"});B.render();z.append(B.$el)}else{if(A instanceof v){var C=new b({model:A});C.render();z.append(C.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var p=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(z){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===z.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var w=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var z=this;var A=new p({model:this.model.get("tool_search")});A.render();z.$el.append(A.$el);this.model.get("layout").each(function(C){if(C instanceof k){var B=new r({model:C});B.render();z.$el.append(B.$el)}else{if(C instanceof i){var D=new l({model:C,className:"toolTitleNoSection"});D.render();z.$el.append(D.$el)}else{if(C instanceof v){var E=new b({model:C});E.render();z.$el.append(E.$el)}}}});z.$el.find("a.tool-link").click(function(D){var C=$(this).attr("class").split(/\s+/)[0],B=z.model.get("tools").get(C);z.trigger("tool_link_click",D,B)});return this},handle_search_results:function(){var z=this.model.get("tool_search").get("results");if(z&&z.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var u=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var h=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new w({collection:this.collection});this.tool_form_view=new u()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var z=this;this.tool_panel_view.on("tool_link_click",function(B,A){B.preventDefault();z.show_tool(A)})},show_tool:function(A){var z=this;A.fetch().done(function(){z.tool_form_view.model=A;z.tool_form_view.render();z.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,SelectToolParameter:t,Tool:i,ToolCollection:m,ToolSearch:c,ToolPanel:n,ToolPanelView:w,ToolFormView:u}});
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/viz/sweepster.js
--- a/static/scripts/packed/viz/sweepster.js
+++ b/static/scripts/packed/viz/sweepster.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","libs/d3","viz/trackster/util","viz/visualization","viz/trackster/tracks","mvc/tools","mvc/data"],function(m,q,f,o,h,g,d){var n=Backbone.Model.extend({defaults:{inputs:null,values:null}});var p=Backbone.RelationalModel.extend({defaults:{tool:null,tree_data:null},initialize:function(s){var r=this;this.get("tool").get("inputs").each(function(t){if(!t.get_samples()){return}t.on("change:min change:max change:num_samples",function(u){if(u.get("in_ptree")){r.set_tree_data()}},r);t.on("change:in_ptree",function(u){if(u.get("in_ptree")){r.add_param(u)}else{r.remove_param(u)}r.set_tree_data()},r)});if(s.config){m.each(s.config,function(u){var t=r.get("tool").get("inputs").find(function(v){return v.get("name")===u.name});r.add_param(t);t.set(u)})}},add_param:function(r){if(r.get("ptree_index")){return}r.set("in_ptree",true);r.set("ptree_index",this.get_tree_params().length)},remove_param:function(r){r.set("in_ptree",false);r.set("ptree_index",null);m(this.get_tree_params()).each(function(s,t){s.set("ptree_index",t+1)})},set_tree_data:function(){var s=m.map(this.get_tree_params(),function(u){return{param:u,samples:u.get_samples()}});var r=0,t=function(x,u){var z=x[u],y=z.param,w=y.get("label"),v=z.samples;if(x.length-1===u){return m.map(v,function(A){return{id:r++,name:A,param:y,value:A}})}return m.map(v,function(A){return{id:r++,name:A,param:y,value:A,children:t(x,u+1)}})};this.set("tree_data",{name:"Root",id:r++,children:(s.length!==0?t(s,0):null)})},get_tree_params:function(){return m(this.get("tool").get("inputs").where({in_ptree:true})).sortBy(function(r){return r.get("ptree_index")})},get_num_leaves:function(){return this.get_tree_params().reduce(function(r,s){return r*s.get_samples().length},1)},get_node_settings:function(v){var t=this.get("tool").get_inputs_dict();var w=v.parent;if(w){while(w.depth!==0){t[w.param.get("name")]=w.value;w=w.parent}}var r=this,s=function(y,x){if(y.param){x[y.param.get("name")]=y.value}if(!y.children){return new n({inputs:r.get("tool").get("inputs"),values:x})}else{return m.flatten(m.map(y.children,function(z){return s(z,m.clone(x))}))}},u=s(v,t);if(!m.isArray(u)){u=[u]}return u},get_connected_nodes:function(t){var u=function(v){if(!v.children){return v}else{return m.flatten([v,m.map(v.children,function(w){return u(w)})])}};var s=[],r=t.parent;while(r){s.push(r);r=r.parent}return m.flatten([s,u(t)])},get_leaf:function(s){var t=this.get("tree_data"),r=function(u){return m.find(u,function(v){return s[v.param.get("name")]===v.value})};while(t.children){t=r(t.children)}return t},toJSON:function(){return this.get_tree_params().map(function(r){return{name:r.get("name"),min:r.get("min"),max:r.get("max"),num_samples:r.get("num_samples")}})}});var c=Backbone.RelationalModel.extend({defaults:{track:null,mode:"Pack",settings:null,regions:null},relations:[{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion}],initialize:function(r){if(r.track){var s=m.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},r.track);this.set("track",h.object_from_template(s,{},null))}},same_settings:function(r){var s=this.get("settings"),t=r.get("settings");for(var u in s){if(!t[u]||s[u]!==t[u]){return false}}return true},toJSON:function(){return{track:this.get("track").to_dict(),settings:this.get("settings"),regions:this.get("regions")}}});var a=Backbone.Collection.extend({model:c});var i=o.Visualization.extend({defaults:m.extend({},o.Visualization.prototype.defaults,{dataset:null,tool:null,parameter_tree:null,regions:null,tracks:null,default_mode:"Pack"}),relations:[{type:Backbone.HasOne,key:"dataset",relatedModel:d.Dataset},{type:Backbone.HasOne,key:"tool",relatedModel:g.Tool},{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion},{type:Backbone.HasMany,key:"tracks",relatedModel:c}],initialize:function(r){var s=this.get("tool").copy(true);this.set("tool_with_samplable_inputs",s);this.set("parameter_tree",new p({tool:s,config:r.tree_config}))},add_track:function(r){this.get("tracks").add(r)},toJSON:function(){return{id:this.get("id"),title:"Parameter exploration for dataset '"+this.get("dataset").get("name")+"'",type:"sweepster",dataset_id:this.get("dataset").id,tool_id:this.get("tool").id,regions:this.get("regions").toJSON(),tree_config:this.get("parameter_tree").toJSON(),tracks:this.get("tracks").toJSON()}}});var l=Backbone.View.extend({tagName:"tr",TILE_LEN:250,initialize:function(r){this.canvas_manager=r.canvas_manager;this.render();this.model.on("change:track change:mode",this.draw_tiles,this)},render:function(){var w=this.model.get("settings"),s=w.get("values"),u=$("<td/>").addClass("settings").appendTo(this.$el),t=$("<div/>").addClass("track-info").hide().appendTo(u);t.append($("<div/>").css("font-weight","bold").text("Track Settings"));w.get("inputs").each(function(y){t.append(y.get("label")+": "+s[y.get("name")]+"<br/>")});var r=this,x=$("<button/>").appendTo(t).text("Run on complete dataset").click(function(){t.toggle();r.trigger("run_on_dataset",w)});var v=create_icon_buttons_menu([{title:"Settings",icon_class:"gear track-settings",on_click:function(){t.toggle()}},{title:"Remove",icon_class:"cross-circle",on_click:function(){r.$el.remove();$(".bs-tooltip").remove()}}]);u.prepend(v.$el);this.model.get("regions").each(function(){r.$el.append($("<td/>").addClass("tile").html($("<img/>").attr("src",galaxy_paths.get("image_path")+"/loading_large_white_bg.gif")))});if(this.model.get("track")){this.draw_tiles()}},draw_tiles:function(){var s=this,r=this.model.get("track"),u=this.model.get("regions"),t=this.$el.find("td.tile");if(!r){return}$.when(r.data_manager.data_is_ready()).then(function(v){u.each(function(y,x){var w=y.length()/s.TILE_LEN,A=1/w,z=s.model.get("mode");$.when(r.data_manager.get_data(y,z,w,{})).then(function(C){var B=s.canvas_manager.new_canvas();B.width=s.TILE_LEN;B.height=r.get_canvas_height(C,z,A,B.width);r.draw_tile(C,B.getContext("2d"),z,w,y,A);$(t[x]).empty().append(B)})})})}});var b=Backbone.View.extend({number_input_template:'<div class="form-row-input sweep"><input class="min" type="text" size="6" value="<%= min %>"> - <input class="max" type="text" size="6" value="<%= max %>"> samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>"></div>',select_input_template:'<div class="form-row-input sweep"><%= options %></div>',initialize:function(r){this.$el=r.tool_row;this.render()},render:function(){var s=this.model,w=s.get("type"),y=this.$el.find(".form-row-input"),u=null;y.find(":input").change(function(){s.set("value",$(this).val())});if(w==="number"){u=$(m.template(this.number_input_template,this.model.toJSON()))}else{if(w==="select"){var t=m.map(this.$el.find("select option"),function(z){return $(z).val()}),v=t.join(", ");u=$(m.template(this.select_input_template,{options:v}))}}u.insertAfter(y);var r=this,x=create_icon_buttons_menu([{title:"Add parameter to tree",icon_class:"plus-button",on_click:function(){s.set("in_ptree",true);y.hide();u.show();$(this).hide();r.$el.find(".icon-button.toggle").show()}},{title:"Remove parameter from tree",icon_class:"toggle",on_click:function(){s.set("in_ptree",false);u.hide();y.show();$(this).hide();r.$el.find(".icon-button.plus-button").show()}}],{});this.$el.prepend(x.$el);if(s.get("in_ptree")){y.hide();r.$el.find(".icon-button.plus-button").hide()}else{r.$el.find(".icon-button.toggle").hide();u.hide()}m.each(["min","max","num_samples"],function(z){u.find("."+z).change(function(){s.set(z,parseFloat($(this).val()))})})}});var k=Backbone.View.extend({className:"tree-design",initialize:function(r){this.render()},render:function(){var t=new g.ToolFormView({model:this.model.get("tool")});t.render();this.$el.append(t.$el);var s=this,r=s.model.get("tool").get("inputs");this.$el.find(".form-row").not(".form-actions").each(function(u){var v=new b({model:r.at(u),tool_row:$(this)})})}});var j=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(r){this.model.on("change:tree_data",this.render,this)},render:function(){this.$el.children().remove();var z=this.model.get_tree_params();if(!z.length){return}this.width=100*(2+z.length);this.height=15*this.model.get_num_leaves();var y=this;var x=q.layout.cluster().size([this.height,this.width-160]);var t=q.svg.diagonal().projection(function(A){return[A.y,A.x]});var r=x.nodes(this.model.get("tree_data"));var u=m.uniq(m.pluck(r,"y"));m.each(z,function(C,B){var A=u[B+1],D=$("#center").position().left;y.$el.append($("<div>").addClass("label").text(C.get("label")).css("left",A+D))});var s=q.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height+30).append("g").attr("transform","translate(40, 20)");var w=s.selectAll("path.link").data(x.links(r)).enter().append("path").attr("class","link").attr("d",t);var v=s.selectAll("g.node").data(r).enter().append("g").attr("class","node").attr("transform",function(A){return"translate("+A.y+","+A.x+")"}).on("mouseover",function(B){var A=m.pluck(y.model.get_connected_nodes(B),"id");v.filter(function(C){return m.find(A,function(D){return D===C.id})!==undefined}).style("fill","#f00")}).on("mouseout",function(){v.style("fill","#000")});v.append("circle").attr("r",9);v.append("text").attr("dx",function(A){return A.children?-12:12}).attr("dy",3).attr("text-anchor",function(A){return A.children?"end":"start"}).text(function(A){return A.name})}});var e=Backbone.View.extend({className:"Sweepster",helpText:"<div><h4>Getting Started</h4><ol><li>Create a parameter tree by using the icons next to the tool's parameter names to add or remove parameters.<li>Adjust the tree by using parameter inputs to select min, max, and number of samples<li>Run the tool with different settings by clicking on tree nodes</ol></div>",initialize:function(s){this.canvas_manager=new o.CanvasManager(this.$el.parents("body"));this.tool_param_tree_view=new j({model:this.model.get("parameter_tree")});this.track_collection_container=$("<table/>").addClass("tracks");this.model.get("parameter_tree").on("change:tree_data",this.handle_node_clicks,this);var r=this;this.model.get("tracks").each(function(t){t.get("track").view=r});this.block_color=f.get_random_color();this.reverse_strand_color=f.get_random_color([this.block_color,"#ffffff"])},render:function(){var x=new k({model:this.model.get("parameter_tree")});$("#left").append(x.$el);var A=this,u=A.model.get("regions"),y=$("<tr/>").appendTo(this.track_collection_container);u.each(function(B){y.append($("<th>").text(B.toString()))});y.children().first().attr("colspan",2);var v=$("<div>").addClass("tiles");$("#right").append(v.append(this.track_collection_container));A.model.get("tracks").each(function(B){A.add_track(B)});var z=$(this.helpText).addClass("help"),w=create_icon_buttons_menu([{title:"Close",icon_class:"cross-circle",on_click:function(){$(".bs-tooltip").remove();z.remove()}}]);z.prepend(w.$el.css("float","right"));$("#center").append(z);this.tool_param_tree_view.render();$("#center").append(this.tool_param_tree_view.$el);this.handle_node_clicks();var t=create_icon_buttons_menu([{icon_class:"chevron-expand",title:"Set display mode"},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location="${h.url_for( controller='visualization', action='list' )}"}}],{tooltip_config:{placement:"bottom"}});var s=["Squish","Pack"],r={};m.each(s,function(B){r[B]=function(){A.model.set("default_mode",B);A.model.get("tracks").each(function(C){C.set("mode",B)})}});make_popupmenu(t.$el.find(".chevron-expand"),r);t.$el.attr("style","float: right");$("#right .unified-panel-header-inner").append(t.$el)},run_tool_on_dataset:function(s){var r=this.model.get("tool"),u=r.get("name"),t=this.model.get("dataset");r.set_input_values(s.get("values"));$.when(r.rerun(t)).then(function(v){});show_modal("Running "+u+" on complete dataset",u+" is running on dataset '"+t.get("name")+"'. Outputs are in the dataset's history.",{Ok:function(){hide_modal()}})},add_track:function(u){var s=this,t=this.model.get("parameter_tree");s.model.add_track(u);var r=new l({model:u,canvas_manager:s.canvas_manager});r.on("run_on_dataset",s.run_tool_on_dataset,s);s.track_collection_container.append(r.$el);r.$el.hover(function(){var w=t.get_leaf(u.get("settings").get("values"));var v=m.pluck(t.get_connected_nodes(w),"id");q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").filter(function(x){return m.find(v,function(y){return y===x.id})!==undefined}).style("fill","#f00")},function(){q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").style("fill","#000")});return u},handle_node_clicks:function(){var r=this,s=this.model.get("parameter_tree"),u=this.model.get("regions"),t=q.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");t.on("click",function(A,x){var w=r.model.get("tool"),z=r.model.get("dataset"),y=s.get_node_settings(A),v=$.Deferred();if(y.length>=10){show_modal("Whoa there cowboy!","You clicked on a node to try "+r.model.get("tool").get("name")+" with "+y.length+" different combinations of settings. You can only run 10 jobs at a time.",{Ok:function(){hide_modal();v.resolve(false)}})}else{v.resolve(true)}$.when(v).then(function(B){if(!B){return}var C=m.map(y,function(D){var E=new c({settings:D,regions:u,mode:r.model.get("default_mode")});r.add_track(E);return E});m.each(C,function(E,D){setTimeout(function(){w.set_input_values(E.get("settings").get("values"));$.when(w.rerun(z,u)).then(function(G){var H=m.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},G.first().get("track_config")),F=h.object_from_template(H,r,null);F.data_manager.set("data_type","raw_data");F.prefs.block_color=r.block_color;F.prefs.reverse_strand_color=r.reverse_strand_color;E.set("track",F)})},D*10000)})})})}});return{SweepsterVisualization:i,SweepsterVisualizationView:e}});
\ No newline at end of file
+define(["libs/underscore","libs/d3","viz/trackster/util","viz/visualization","viz/trackster/tracks","mvc/tools","mvc/data"],function(m,q,f,o,h,g,d){var n=Backbone.Model.extend({defaults:{inputs:null,values:null}});var p=Backbone.RelationalModel.extend({defaults:{tool:null,tree_data:null},initialize:function(s){var r=this;this.get("tool").get("inputs").each(function(t){t.on("change:min change:max change:num_samples",function(u){if(u.get("in_ptree")){r.set_tree_data()}},r);t.on("change:in_ptree",function(u){if(u.get("in_ptree")){r.add_param(u)}else{r.remove_param(u)}r.set_tree_data()},r)});if(s.config){m.each(s.config,function(u){var t=r.get("tool").get("inputs").find(function(v){return v.get("name")===u.name});r.add_param(t);t.set(u)})}},add_param:function(r){if(r.get("ptree_index")){return}r.set("in_ptree",true);r.set("ptree_index",this.get_tree_params().length)},remove_param:function(r){r.set("in_ptree",false);r.set("ptree_index",null);m(this.get_tree_params()).each(function(s,t){s.set("ptree_index",t+1)})},set_tree_data:function(){var s=m.map(this.get_tree_params(),function(u){return{param:u,samples:u.get_samples()}});var r=0,t=function(x,u){var z=x[u],y=z.param,w=y.get("label"),v=z.samples;if(x.length-1===u){return m.map(v,function(A){return{id:r++,name:A,param:y,value:A}})}return m.map(v,function(A){return{id:r++,name:A,param:y,value:A,children:t(x,u+1)}})};this.set("tree_data",{name:"Root",id:r++,children:(s.length!==0?t(s,0):null)})},get_tree_params:function(){return m(this.get("tool").get("inputs").where({in_ptree:true})).sortBy(function(r){return r.get("ptree_index")})},get_num_leaves:function(){return this.get_tree_params().reduce(function(r,s){return r*s.get_samples().length},1)},get_node_settings:function(v){var t=this.get("tool").get_inputs_dict();var w=v.parent;if(w){while(w.depth!==0){t[w.param.get("name")]=w.value;w=w.parent}}var r=this,s=function(y,x){if(y.param){x[y.param.get("name")]=y.value}if(!y.children){return new n({inputs:r.get("tool").get("inputs"),values:x})}else{return m.flatten(m.map(y.children,function(z){return s(z,m.clone(x))}))}},u=s(v,t);if(!m.isArray(u)){u=[u]}return u},get_connected_nodes:function(t){var u=function(v){if(!v.children){return v}else{return m.flatten([v,m.map(v.children,function(w){return u(w)})])}};var s=[],r=t.parent;while(r){s.push(r);r=r.parent}return m.flatten([s,u(t)])},get_leaf:function(s){var t=this.get("tree_data"),r=function(u){return m.find(u,function(v){return s[v.param.get("name")]===v.value})};while(t.children){t=r(t.children)}return t},toJSON:function(){return this.get_tree_params().map(function(r){return{name:r.get("name"),min:r.get("min"),max:r.get("max"),num_samples:r.get("num_samples")}})}});var c=Backbone.RelationalModel.extend({defaults:{track:null,mode:"Pack",settings:null,regions:null},relations:[{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion}],initialize:function(r){if(r.track){var s=m.extend({data_url:galaxy_config.root+"dummy1",converted_datasets_state_url:galaxy_config.root+"dummy2"},r.track);this.set("track",h.object_from_template(s,{},null))}},same_settings:function(r){var s=this.get("settings"),t=r.get("settings");for(var u in s){if(!t[u]||s[u]!==t[u]){return false}}return true},toJSON:function(){return{track:this.get("track").to_dict(),settings:this.get("settings"),regions:this.get("regions")}}});var a=Backbone.Collection.extend({model:c});var i=o.Visualization.extend({defaults:m.extend({},o.Visualization.prototype.defaults,{dataset:null,tool:null,parameter_tree:null,regions:null,tracks:null,default_mode:"Pack"}),relations:[{type:Backbone.HasOne,key:"dataset",relatedModel:d.Dataset},{type:Backbone.HasOne,key:"tool",relatedModel:g.Tool},{type:Backbone.HasMany,key:"regions",relatedModel:o.GenomeRegion},{type:Backbone.HasMany,key:"tracks",relatedModel:c}],initialize:function(r){var s=this.get("tool");this.set("tool_with_samplable_inputs",s);s.remove_inputs(["data","hidden_data","conditional"]);this.set("parameter_tree",new p({tool:s,config:r.tree_config}))},add_track:function(r){this.get("tracks").add(r)},toJSON:function(){return{id:this.get("id"),title:"Parameter exploration for dataset '"+this.get("dataset").get("name")+"'",type:"sweepster",dataset_id:this.get("dataset").id,tool_id:this.get("tool").id,regions:this.get("regions").toJSON(),tree_config:this.get("parameter_tree").toJSON(),tracks:this.get("tracks").toJSON()}}});var l=Backbone.View.extend({tagName:"tr",TILE_LEN:250,initialize:function(r){this.canvas_manager=r.canvas_manager;this.render();this.model.on("change:track change:mode",this.draw_tiles,this)},render:function(){var w=this.model.get("settings"),s=w.get("values"),u=$("<td/>").addClass("settings").appendTo(this.$el),t=$("<div/>").addClass("track-info").hide().appendTo(u);t.append($("<div/>").css("font-weight","bold").text("Track Settings"));w.get("inputs").each(function(y){t.append(y.get("label")+": "+s[y.get("name")]+"<br/>")});var r=this,x=$("<button/>").appendTo(t).text("Run on complete dataset").click(function(){t.toggle();r.trigger("run_on_dataset",w)});var v=create_icon_buttons_menu([{title:"Settings",icon_class:"gear track-settings",on_click:function(){t.toggle()}},{title:"Remove",icon_class:"cross-circle",on_click:function(){r.$el.remove();$(".bs-tooltip").remove()}}]);u.prepend(v.$el);this.model.get("regions").each(function(){r.$el.append($("<td/>").addClass("tile").html($("<img/>").attr("src",galaxy_config.root+"images/loading_large_white_bg.gif")))});if(this.model.get("track")){this.draw_tiles()}},draw_tiles:function(){var s=this,r=this.model.get("track"),u=this.model.get("regions"),t=this.$el.find("td.tile");if(!r){return}$.when(r.data_manager.data_is_ready()).then(function(v){u.each(function(y,x){var w=y.length()/s.TILE_LEN,A=1/w,z=s.model.get("mode");$.when(r.data_manager.get_data(y,z,w,{})).then(function(C){var B=s.canvas_manager.new_canvas();B.width=s.TILE_LEN;B.height=r.get_canvas_height(C,z,A,B.width);r.draw_tile(C,B.getContext("2d"),z,w,y,A);$(t[x]).empty().append(B)})})})}});var b=Backbone.View.extend({number_input_template:'<div class="form-row-input sweep"><input class="min" type="text" size="6" value="<%= min %>"> - <input class="max" type="text" size="6" value="<%= max %>"> samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>"></div>',select_input_template:'<div class="form-row-input sweep"><%= options %></div>',initialize:function(r){this.$el=r.tool_row;this.render()},render:function(){var s=this.model,w=s.get("type"),y=this.$el.find(".form-row-input"),u=null;y.find(":input").change(function(){s.set("value",$(this).val())});if(s instanceof g.IntegerToolParameter){u=$(m.template(this.number_input_template,this.model.toJSON()))}else{if(s instanceof g.SelectToolParameter){var t=m.map(this.$el.find("select option"),function(z){return $(z).val()}),v=t.join(", ");u=$(m.template(this.select_input_template,{options:v}))}}u.insertAfter(y);var r=this,x=create_icon_buttons_menu([{title:"Add parameter to tree",icon_class:"plus-button",on_click:function(){s.set("in_ptree",true);y.hide();u.show();$(this).hide();r.$el.find(".icon-button.toggle").show()}},{title:"Remove parameter from tree",icon_class:"toggle",on_click:function(){s.set("in_ptree",false);u.hide();y.show();$(this).hide();r.$el.find(".icon-button.plus-button").show()}}],{});this.$el.prepend(x.$el);if(s.get("in_ptree")){y.hide();r.$el.find(".icon-button.plus-button").hide()}else{r.$el.find(".icon-button.toggle").hide();u.hide()}m.each(["min","max","num_samples"],function(z){u.find("."+z).change(function(){s.set(z,parseFloat($(this).val()))})})}});var k=Backbone.View.extend({className:"tree-design",initialize:function(r){this.render()},render:function(){var t=new g.ToolFormView({model:this.model.get("tool")});t.render();this.$el.append(t.$el);var s=this,r=s.model.get("tool").get("inputs");this.$el.find(".form-row").not(".form-actions").each(function(u){var v=new b({model:r.at(u),tool_row:$(this)})})}});var j=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(r){this.model.on("change:tree_data",this.render,this)},render:function(){this.$el.children().remove();var z=this.model.get_tree_params();if(!z.length){return}this.width=100*(2+z.length);this.height=15*this.model.get_num_leaves();var y=this;var x=q.layout.cluster().size([this.height,this.width-160]);var t=q.svg.diagonal().projection(function(A){return[A.y,A.x]});var r=x.nodes(this.model.get("tree_data"));var u=m.uniq(m.pluck(r,"y"));m.each(z,function(C,B){var A=u[B+1],D=$("#center").position().left;y.$el.append($("<div>").addClass("label").text(C.get("label")).css("left",A+D))});var s=q.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height+30).append("g").attr("transform","translate(40, 20)");var w=s.selectAll("path.link").data(x.links(r)).enter().append("path").attr("class","link").attr("d",t);var v=s.selectAll("g.node").data(r).enter().append("g").attr("class","node").attr("transform",function(A){return"translate("+A.y+","+A.x+")"}).on("mouseover",function(B){var A=m.pluck(y.model.get_connected_nodes(B),"id");v.filter(function(C){return m.find(A,function(D){return D===C.id})!==undefined}).style("fill","#f00")}).on("mouseout",function(){v.style("fill","#000")});v.append("circle").attr("r",9);v.append("text").attr("dx",function(A){return A.children?-12:12}).attr("dy",3).attr("text-anchor",function(A){return A.children?"end":"start"}).text(function(A){return A.name})}});var e=Backbone.View.extend({className:"Sweepster",helpText:"<div><h4>Getting Started</h4><ol><li>Create a parameter tree by using the icons next to the tool's parameter names to add or remove parameters.<li>Adjust the tree by using parameter inputs to select min, max, and number of samples<li>Run the tool with different settings by clicking on tree nodes</ol></div>",initialize:function(s){this.canvas_manager=new o.CanvasManager(this.$el.parents("body"));this.tool_param_tree_view=new j({model:this.model.get("parameter_tree")});this.track_collection_container=$("<table/>").addClass("tracks");this.model.get("parameter_tree").on("change:tree_data",this.handle_node_clicks,this);var r=this;this.model.get("tracks").each(function(t){t.get("track").view=r});this.block_color=f.get_random_color();this.reverse_strand_color=f.get_random_color([this.block_color,"#ffffff"])},render:function(){var x=new k({model:this.model.get("parameter_tree")});$("#left").append(x.$el);var A=this,u=A.model.get("regions"),y=$("<tr/>").appendTo(this.track_collection_container);u.each(function(B){y.append($("<th>").text(B.toString()))});y.children().first().attr("colspan",2);var v=$("<div>").addClass("tiles");$("#right").append(v.append(this.track_collection_container));A.model.get("tracks").each(function(B){A.add_track(B)});var z=$(this.helpText).addClass("help"),w=create_icon_buttons_menu([{title:"Close",icon_class:"cross-circle",on_click:function(){$(".bs-tooltip").remove();z.remove()}}]);z.prepend(w.$el.css("float","right"));$("#center").append(z);this.tool_param_tree_view.render();$("#center").append(this.tool_param_tree_view.$el);this.handle_node_clicks();var t=create_icon_buttons_menu([{icon_class:"chevron-expand",title:"Set display mode"},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location="${h.url_for( controller='visualization', action='list' )}"}}],{tooltip_config:{placement:"bottom"}});var s=["Squish","Pack"],r={};m.each(s,function(B){r[B]=function(){A.model.set("default_mode",B);A.model.get("tracks").each(function(C){C.set("mode",B)})}});make_popupmenu(t.$el.find(".chevron-expand"),r);t.$el.attr("style","float: right");$("#right .unified-panel-header-inner").append(t.$el)},run_tool_on_dataset:function(s){var r=this.model.get("tool"),u=r.get("name"),t=this.model.get("dataset");r.set_input_values(s.get("values"));$.when(r.rerun(t)).then(function(v){});show_modal("Running "+u+" on complete dataset",u+" is running on dataset '"+t.get("name")+"'. Outputs are in the dataset's history.",{Ok:function(){hide_modal()}})},add_track:function(u){var s=this,t=this.model.get("parameter_tree");s.model.add_track(u);var r=new l({model:u,canvas_manager:s.canvas_manager});r.on("run_on_dataset",s.run_tool_on_dataset,s);s.track_collection_container.append(r.$el);r.$el.hover(function(){var w=t.get_leaf(u.get("settings").get("values"));var v=m.pluck(t.get_connected_nodes(w),"id");q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").filter(function(x){return m.find(v,function(y){return y===x.id})!==undefined}).style("fill","#f00")},function(){q.select(s.tool_param_tree_view.$el[0]).selectAll("g.node").style("fill","#000")});return u},handle_node_clicks:function(){var r=this,s=this.model.get("parameter_tree"),u=this.model.get("regions"),t=q.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");t.on("click",function(A,x){var w=r.model.get("tool"),z=r.model.get("dataset"),y=s.get_node_settings(A),v=$.Deferred();if(y.length>=10){show_modal("Whoa there cowboy!","You clicked on a node to try "+r.model.get("tool").get("name")+" with "+y.length+" different combinations of settings. You can only run 10 jobs at a time.",{Ok:function(){hide_modal();v.resolve(false)}})}else{v.resolve(true)}$.when(v).then(function(B){if(!B){return}var C=m.map(y,function(D){var E=new c({settings:D,regions:u,mode:r.model.get("default_mode")});r.add_track(E);return E});m.each(C,function(E,D){setTimeout(function(){w.set_input_values(E.get("settings").get("values"));$.when(w.rerun(z,u)).then(function(G){var H=G.first(),I=H.get("track_config");I.dataset=H;I.tool=null;var F=h.object_from_template(I,r,null);F.init_for_tool_data();F.prefs.block_color=r.block_color;F.prefs.reverse_strand_color=r.reverse_strand_color;E.set("track",F)})},D*10000)})})})}});return{SweepsterVisualization:i,SweepsterVisualizationView:e}});
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f static/scripts/packed/viz/trackster/tracks.js
--- a/static/scripts/packed/viz/trackster/tracks.js
+++ b/static/scripts/packed/viz/trackster/tracks.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","viz/trackster/filters","mvc/data","mvc/tools"],function(ac,w,j,s,L,h,X,R){var o=ac.extend;var l={};var i=function(ad,ae){l[ad.attr("id")]=ae};var k=function(ad,af,ah,ag){ah=".group";var ae={};l[ad.attr("id")]=ag;ad.bind("drag",{handle:"."+af,relative:true},function(ap,aq){var ao=$(this),au=$(this).parent(),al=au.children(),an=l[$(this).attr("id")],ak,aj,ar,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ar=aj.position().top;ai=ar+aj.outerHeight();if(aq.offsetY<ar){$(this).insertBefore(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable_before(an,at);return}else{if(aq.offsetY>ai){$(this).insertAfter(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable(an);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ar=ak.position().top;ai=ar+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&aq.offsetY>=ar&&aq.offsetY<=ai){if(aq.offsetY-ar<ai-aq.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}if(an.container){an.container.remove_drawable(an)}l[ak.attr("id")].add_drawable(an);return}}for(am=0;am<al.length;am++){ak=$(al.get(am));if(aq.offsetY<ak.position().top&&!(ak.hasClass("reference-track")||ak.hasClass("intro"))){break}}if(am===al.length){if(this!==al.get(am-1)){au.append(this);l[au.attr("id")].move_drawable(an,am)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am));l[au.attr("id")].move_drawable(an,(aq.deltaY>0?am-1:am))}}}).bind("dragstart",function(){ae["border-top"]=ad.css("border-top");ae["border-bottom"]=ad.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ae)})};var aa=16,G=9,D=20,z=100,I=12000,S=400,K=5000,v=100,m="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",u="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",x="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20,A=["Histogram","Line","Filled","Intensity"];function V(ae,ad){if(!ad){ad=0}var af=Math.pow(10,ad);return Math.round(ae*af)/af}var p=function(ae,ad,ag){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ag.name;this.view=ae;this.container=ad;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ag.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ah){ah.stopPropagation()});var af=this;this.container_div.hover(function(){af.icons_div.show()},function(){af.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ad){if(ad.content_visible){ad.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ad.hide_contents();ad.content_visible=false}else{ad.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ad.content_visible=true;ad.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ae){var ag=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){ae.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},af=function(ah){if((ah.keyCode||ah.which)===27){ag()}else{if((ah.keyCode||ah.which)===13){ad()}}};$(window).bind("keypress.check_enter_esc",af);show_modal("Configure",ae.config.build_form(),{Cancel:ag,OK:ad})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.remove()}}];o(p.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(ad){},to_dict:function(){},set_name:function(ad){this.old_name=this.name;this.name=ad;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ad=this.view;this.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ae,aj,ai,ah,ad,ag){var af=this;this.action_icons[ae]=$("<a/>").attr("href","javascript:void(0);").attr("title",aj).addClass("icon-button").addClass(ai).tooltip().click(function(){ah(af)}).appendTo(this.icons_div);if(ag){this.action_icons[ae].hide()}},build_action_icons:function(ad){var af;for(var ae=0;ae<ad.length;ae++){af=ad[ae];this.add_action_icon(af.name,af.title,af.css_class,af.on_click_fn,af.prepend,af.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var y=function(ae,ad,af){p.call(this,ae,ad,af);this.obj_type=af.obj_type;this.drawables=[]};o(y.prototype,p.prototype,{unpack_drawables:function(af){this.drawables=[];var ae;for(var ad=0;ad<af.length;ad++){ae=n(af[ad],this.view,this);this.add_drawable(ae)}},init:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].init()}},_draw:function(ad){for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae]._draw(ad)}},to_dict:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ae}},add_drawable:function(ad){this.drawables.push(ad);ad.container=this;this.changed()},add_drawable_before:function(af,ad){this.changed();var ae=this.drawables.indexOf(ad);if(ae!==-1){this.drawables.splice(ae,0,af);return true}return false},replace_drawable:function(af,ad,ae){var ag=this.drawables.indexOf(af);if(ag!==-1){this.drawables[ag]=ad;if(ae){af.container_div.replaceWith(ad.container_div)}this.changed()}return ag},remove_drawable:function(ae){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);ae.container=null;this.changed();return true}return false},move_drawable:function(ae,af){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);this.drawables.splice(af,0,ae);this.changed();return true}return false},get_drawables:function(){return this.drawables},get_tracks:function(ag){var ad=this.drawables.slice(0),ae=[],af;while(ad.length!==0){af=ad.shift();if(af instanceof ag){ae.push(af)}else{if(af.drawables){ad=ad.concat(af.drawables)}}}return ae}});var P=function(ae,ad,ag){o(ag,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});y.call(this,ae,ad,ag);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);i(this.container_div,this);i(this.content_div,this);k(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new h.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ag){this.unpack_drawables(ag.drawables)}if("filters" in ag){var af=this.filters_manager;this.filters_manager=new h.FiltersManager(this,ag.filters);af.parent_div.replaceWith(this.filters_manager.parent_div);if(ag.filters.visible){this.setup_multitrack_filtering()}}};o(P.prototype,p.prototype,y.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters();ad._restore_filter_managers()}else{ad.setup_multitrack_filtering();ad.request_draw({clear_tile_cache:true})}ad.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var ad=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ad)}return ad},build_header_div:function(){var ad=$("<div/>").addClass("track-header");ad.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ad);return ad},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var af=this.drawables.length;if(af===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(af===1){if(this.drawables[0] instanceof e){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var am,al,aj,ap=true,ah=this.drawables[0].get_type(),ad=0;for(am=0;am<af;am++){aj=this.drawables[am];if(aj.get_type()!==ah){can_composite=false;break}if(aj instanceof c){ad++}}if(ap||ad===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ad>1&&ad===this.drawables.length){var aq={},ae;aj=this.drawables[0];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];aq[ae.name]=[ae]}for(am=1;am<this.drawables.length;am++){aj=this.drawables[am];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];if(ae.name in aq){aq[ae.name].push(ae)}}}this.filters_manager.remove_all();var ag,ai,ak,an;for(var ao in aq){ag=aq[ao];if(ag.length===ad){ai=new h.NumberFilter({name:ag[0].name,index:ag[0].index});this.filters_manager.add_filter(ai)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].filters_manager=this.saved_filters_managers[ad]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ad=0;ad<this.drawables.length;ad++){drawable=this.drawables[ad];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ae=new e(this.view,this.view,{name:this.name,drawables:this.drawables});var ad=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);this.update_icons()},remove_drawable:function(ad){y.prototype.remove_drawable.call(this,ad);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ad=o(y.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ad},request_draw:function(ad){ac.each(this.drawables,function(ae){ae.request_draw(ad)})}});var Y=Backbone.View.extend({initialize:function(ad){o(ad,{obj_type:"View"});y.call(this,"View",ad.container,ad);this.chrom=null;this.vis_id=ad.vis_id;this.dbkey=ad.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new w.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ad.prefs,onchange:function(){track.request_redraw({clear_tile_cache:true})}})},render:function(){this.requested_redraw=false;var af=this.container,ad=this;this.top_container=$("<div/>").addClass("top-container").appendTo(af);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(af);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(af);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;i(this.viewport_container,ad);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ag=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){w.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":ad.dbkey},function(ah){ac.each(ah,function(ai){ad.add_drawable(n(ai,ad,ad))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ae=function(ah){if(ah.type==="focusout"||(ah.keyCode||ah.which)===13||(ah.keyCode||ah.which)===27){if((ah.keyCode||ah.which)!==27){ad.go_to($(this).val())}$(this).hide();$(this).val("");ad.location_span.show();ad.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ae).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ad.location_span.hide();ad.chrom_select.hide();ad.nav_input.val(ad.chrom+":"+ad.low+"-"+ad.high);ad.nav_input.css("display","inline-block");ad.nav_input.select();ad.nav_input.focus();ad.nav_input.autocomplete({source:function(aj,ah){var ak=[],ai=$.map(ad.get_tracks(c),function(al){return al.data_manager.search_features(aj.term).success(function(am){ak=ak.concat(am)})});$.when.apply($,ai).done(function(){ah($.map(ak,function(al){return{label:al[0],value:al[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ad.zoom_out();ad.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ad.zoom_in();ad.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ad.change_chrom(ad.chrom_select.val())});this.browser_content_div.click(function(ah){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ah){ad.zoom_in(ah.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ah,ai){this.current_x=ai.offsetX}).bind("drag",function(ah,aj){var ak=aj.offsetX-this.current_x;this.current_x=aj.offsetX;var ai=Math.round(ak/ad.viewport_container.width()*(ad.max_high-ad.max_low));ad.move_delta(-ai)});this.overview_close.click(function(){ad.reset_overview()});this.viewport_container.bind("draginit",function(ah,ai){if(ah.clientX>ad.viewport_container.width()-16){return false}}).bind("dragstart",function(ah,ai){ai.original_low=ad.low;ai.current_height=ah.clientY;ai.current_x=ai.offsetX}).bind("drag",function(aj,al){var ah=$(this);var am=al.offsetX-al.current_x;var ai=ah.scrollTop()-(aj.clientY-al.current_height);ah.scrollTop(ai);al.current_height=aj.clientY;al.current_x=al.offsetX;var ak=Math.round(am/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}).bind("mousewheel",function(aj,al,ai,ah){if(ai){ai*=50;var ak=Math.round(-ai/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}});this.top_labeltrack.bind("dragstart",function(ah,ai){return $("<div />").css({height:ad.browser_content_div.height()+ad.top_labeltrack.height()+ad.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(al,am){$(am.proxy).css({left:Math.min(al.pageX,am.startX)-ad.container.offset().left,width:Math.abs(al.pageX-am.startX)});var ai=Math.min(al.pageX,am.startX)-ad.container.offset().left,ah=Math.max(al.pageX,am.startX)-ad.container.offset().left,ak=(ad.high-ad.low),aj=ad.viewport_container.width();ad.update_location(Math.round(ai/aj*ak)+ad.low,Math.round(ah/aj*ak)+ad.low)}).bind("dragend",function(am,an){var ai=Math.min(am.pageX,an.startX),ah=Math.max(am.pageX,an.startX),ak=(ad.high-ad.low),aj=ad.viewport_container.width(),al=ad.low;ad.low=Math.round(ai/aj*ak)+al;ad.high=Math.round(ah/aj*ak)+al;$(an.proxy).remove();ad.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ad.resize_window()},500)});$(document).bind("redraw",function(){ad.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ad){return this.config.values[ad.toLowerCase()+"_color"]||this.config.values.n_color}});o(Y.prototype,y.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ae,ag,ad,ah){if(this.timer){clearTimeout(this.timer)}if(ah){var af=this;this.timer=setTimeout(function(){af.trigger("navigate",ae+":"+ag+"-"+ad)},500)}else{view.trigger("navigate",ae+":"+ag+"-"+ad)}},update_location:function(ad,af){this.location_span.text(commatize(ad)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ad)+"-"+commatize(af));var ae=view.chrom_select.val();if(ae!==""){this.trigger_navigate(ae,view.low,view.high,true)}},load_chroms:function(af){af.num=v;var ad=this,ae=$.Deferred();$.ajax({url:galaxy_config.root+"api/genomes/"+this.dbkey,data:af,dataType:"json",success:function(ah){if(ah.chrom_info.length===0){return}if(ah.reference){ad.add_label_track(new B(ad))}ad.chrom_data=ah.chrom_info;var ak='<option value="">Select Chrom/Contig</option>';for(var aj=0,ag=ad.chrom_data.length;aj<ag;aj++){var ai=ad.chrom_data[aj].chrom;ak+='<option value="'+ai+'">'+ai+"</option>"}if(ah.prev_chroms){ak+='<option value="previous">Previous '+v+"</option>"}if(ah.next_chroms){ak+='<option value="next">Next '+v+"</option>"}ad.chrom_select.html(ak);ad.chrom_start_index=ah.start_index;ae.resolve(ah.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ad.dbkey)}});return ae},change_chrom:function(ai,ae,ak){var af=this;if(!af.chrom_data){af.load_chroms_deferred.then(function(){af.change_chrom(ai,ae,ak)});return}if(!ai||ai==="None"){return}if(ai==="previous"){af.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){af.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(af.chrom_data,function(al,am){return al.chrom===ai})[0];if(aj===undefined){af.load_chroms({chrom:ai},function(){af.change_chrom(ai,ae,ak)});return}else{if(ai!==af.chrom){af.chrom=ai;af.chrom_select.val(af.chrom);af.max_high=aj.len-1;af.reset();for(var ah=0,ad=af.drawables.length;ah<ad;ah++){var ag=af.drawables[ah];if(ag.init){ag.init()}}if(af.reference_track){af.reference_track.init()}}if(ae&&ak){af.low=Math.max(ae,0);af.high=Math.min(ak,af.max_high)}else{af.low=0;af.high=af.max_high}af.reset_overview();af.request_redraw()}},go_to:function(ah){ah=ah.replace(/,/g,"");ah=ah.replace(/:|\-/g," ");var ae=ah.split(/\s+/),ag=ae[0],af=(ae[1]?parseInt(ae[1],10):null),ad=(ae[2]?parseInt(ae[2],10):null);if(!ad){af=af-15;ad=af+15}this.change_chrom(ag,af,ad)},move_fraction:function(af){var ad=this;var ae=ad.high-ad.low;this.move_delta(af*ae)},move_delta:function(ag){var ad=this;var af=ad.high-ad.low;if(ad.low-ag<ad.max_low){ad.low=ad.max_low;ad.high=ad.max_low+af}else{if(ad.high-ag>ad.max_high){ad.high=ad.max_high;ad.low=ad.max_high-af}else{ad.high-=ag;ad.low-=ag}}ad.request_redraw({data_fetch:false});if(this.redraw_on_move_fn){clearTimeout(this.redraw_on_move_fn)}this.redraw_on_move_fn=setTimeout(function(){ad.request_redraw()},200);var ae=ad.chrom_select.val();this.trigger_navigate(ae,ad.low,ad.high,true)},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);ad.init();this.changed();this.update_intro_div()},add_label_track:function(ad){ad.view=this;ad.init();this.label_tracks.push(ad)},remove_drawable:function(af,ae){y.prototype.remove_drawable.call(this,af);if(ae){var ad=this;af.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ae,af){var ad=this,ag=(af?[af]:ad.drawables);ac.each(ag,function(ah){var ai=ac.find(ad.tracks_to_be_redrawn,function(aj){return aj[0]===ah});if(ai){ai[1]=ae}else{ad.tracks_to_be_redrawn.push([ah,ae])}});if(!this.requested_redraw){requestAnimationFrame(function(){ad._redraw()});this.requested_redraw=true}},_redraw:function(){this.requested_redraw=false;var ad=this.low,ah=this.high;if(ad<this.max_low){ad=this.max_low}if(ah>this.max_high){ah=this.max_high}var ae=this.high-this.low;if(this.high!==0&&ae<this.min_separation){ah=ad+this.min_separation}this.low=Math.floor(ad);this.high=Math.ceil(ah);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ag=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var af=13;this.overview_box.css({left:ag,width:Math.max(af,ai)}).show();if(ai<af){this.overview_box.css("left",ag-(af-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ag,width:ai})}ac.each(this.tracks_to_be_redrawn,function(al){var aj=al[0],ak=al[1];if(aj){aj._draw(ak)}});this.tracks_to_be_redrawn=[];ac.each(this.label_tracks,function(aj){aj._draw()})},zoom_in:function(ae,af){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ag=this.high-this.low,ah=ag/2+this.low,ad=(ag/this.zoom_factor)/2;if(ae){ah=ae/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ah-ad);this.high=Math.round(ah+ad);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ae=this.high-this.low,af=ae/2+this.low,ad=(ae*this.zoom_factor)/2;this.low=Math.round(af-ad);this.high=Math.round(af+ad);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(af){if(this.overview_drawable){if(this.overview_drawable.dataset.id===af.dataset.id){return}this.overview_viewport.find(".track").remove()}var ae=af.copy({content_div:this.overview_viewport}),ad=this;ae.header_div.hide();ae.is_overview=true;ad.overview_drawable=ae;this.overview_drawable.postdraw_actions=function(){ad.overview_highlight.show().height(ad.overview_drawable.content_div.height());ad.overview_viewport.height(ad.overview_drawable.content_div.height()+ad.overview_box.outerHeight());ad.overview_close.show();ad.resize_window()};ad.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();view.overview_drawable=null}});var q=Backbone.RelationalModel.extend({defaults:{track:null,tool:null,},relations:[{type:Backbone.HasOne,key:"tool",relatedModel:R.Tool}],initialize:function(ae){var ad=this.get("tool"),af=ad.get("inputs").filter(function(ag){return(["data","hidden_data","group"].indexOf(ag.get("type"))!==-1)});ad.get("inputs").remove(af)}});var t=Backbone.View.extend({events:{"change input":"update_value"},render:function(){var af=this.$el.addClass("param-row"),ag=this.model;var ad=$("<div>").addClass("param-label").text(ag.get("label")).appendTo(af);var ae=$("<div/>").addClass("param-input").html(ag.get("html")).appendTo(af);ae.find(":input").val(ag.get("value"));$("<div style='clear: both;'/>").appendTo(af)},update_value:function(ad){this.model.set_value($(ad.target).val())}});var ab=Backbone.View.extend({render:function(){var ae=this;tool=this.model.get("tool"),parent_div=this.$el.addClass("dynamic-tool").hide();parent_div.bind("drag",function(ai){ai.stopPropagation()}).click(function(ai){ai.stopPropagation()}).bind("dblclick",function(ai){ai.stopPropagation()}).keydown(function(ai){ai.stopPropagation()});var af=$("<div class='tool-name'>").appendTo(parent_div).text(tool.get("name"));tool.get("inputs").each(function(aj){var ai=new t({model:aj});ai.render();parent_div.append(ai.$el)});parent_div.find("input").click(function(){$(this).select()});var ag=$("<div>").addClass("param-row").appendTo(parent_div);var ah=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ag);var ad=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ag);ad.click(function(){ae.run_on_region()});ah.click(function(){ae.run_on_dataset()})},update_params:function(){for(var ad=0;ad<this.params.length;ad++){this.params[ad].update_value()}},state_dict:function(){var ad=this.model.get("tool").get_param_values_dict();ad.visible=this.parent_div.is(":visible");return ad},run_on_dataset:function(){var ad=this.model.get("tool");this.run({target_dataset_id:this.model.get("track").dataset.id,action:"rerun",tool_id:ad.id},null,function(ae){show_modal(ad.get("name")+" is Running",ad.get("name")+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae=this.model.get("track"),ah=this.model.get("tool"),aj=new w.GenomeRegion({chrom:ae.view.chrom,start:ae.view.low,end:ae.view.high}),ak={target_dataset_id:ae.dataset.id,action:"rerun",tool_id:ah.id,regions:[aj.toJSON()]},ai=ae,am=ak.tool_id+ai.tool_region_and_parameters_str(aj),ad;if(ai.container===view){var al=new P(view,view,{name:this.name});var ag=ai.container.replace_drawable(ai,al,false);al.container_div.insertBefore(ai.view.content_div.children()[ag]);al.add_drawable(ai);ai.container_div.appendTo(al.content_div);ad=al}else{ad=ai.container}var af=new ai.constructor(view,ad,{name:am,hda_ldda:"hda"});af.init_for_tool_data();af.change_mode(ai.mode);af.set_filters_manager(ai.filters_manager.copy(af));af.update_icons();ad.add_drawable(af);af.tiles_div.text("Starting job.");this.run(ak,af,function(an){af.set_dataset(new X.Dataset(an));af.tiles_div.text("Running job.");af.init()})},run:function(ad,af,ag){ad.inputs=this.model.get("tool").get_inputs_dict();var ae=new j.ServerStateDeferred({ajax_settings:{url:galaxy_config.root+"api/tools",data:JSON.stringify(ad),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ah){return ah!=="pending"}});$.when(ae.go()).then(function(ah){if(ah==="no converter"){af.container_div.addClass("error");af.content_div.text(J)}else{if(ah.error){af.container_div.addClass("error");af.content_div.text(x+ah.message)}else{ag(ah)}}})}});var C=function(ad,ae){L.Scaler.call(this,ae);this.filter=ad};C.prototype.gen_val=function(ad){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ad[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ad){this.track=ad.track;this.params=ad.params;this.values={};this.restore_values((ad.saved_values?ad.saved_values:{}));this.onchange=ad.onchange};o(F.prototype,{set_param_default_value:function(ae,ad){var af=ac.find(this.params,function(ag){return ag.key===ae});if(af){af.default_value=ad}},set_param_value:function(ad,ae){var af=ac.find(this.params,function(ag){return ag.key===ad});if(af){if(typeof ae==="string"||ae instanceof String){if(ae.trim()===""){ae=af.default_value}else{if(af.type==="float"){ae=parseFloat(ae)}else{if(af.type==="int"){ae=parseInt(ae,10)}}}}}if(this.values[ad]!==ae){this.values[ad]=ae;return true}else{return false}},restore_values:function(ad){var ae=this;$.each(this.params,function(af,ag){if(ad[ag.key]!==undefined){ae.values[ag.key]=ad[ag.key]}else{ae.values[ag.key]=ag.default_value}})},build_form:function(){var ag=this;var ad=$("<div />");var af;function ae(al,ah){for(var ap=0;ap<al.length;ap++){af=al[ap];if(af.hidden){continue}var aj="param_"+ap;var au=ag.values[af.key];var aw=$("<div class='form-row' />").appendTo(ah);aw.append($("<label />").attr("for",aj).text(af.label+":"));if(af.type==="bool"){aw.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",au))}else{if(af.type==="text"){aw.append($('<input type="text"/>').attr("id",aj).val(au).click(function(){$(this).select()}))}else{if(af.type==="select"){var ar=$("<select />").attr("id",aj);for(var an=0;an<af.options.length;an++){$("<option/>").text(af.options[an].label).attr("value",af.options[an].value).appendTo(ar)}ar.val(au);aw.append(ar)}else{if(af.type==="color"){var av=$("<div/>").appendTo(aw),aq=$("<input />").attr("id",aj).attr("name",aj).val(au).css("float","left").appendTo(av).click(function(ay){$(".bs-tooltip").removeClass("in");var ax=$(this).siblings(".bs-tooltip").addClass("in");ax.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ax).height()/2)+($(this).height()/2)}).show();ax.click(function(az){az.stopPropagation()});$(document).bind("click.color-picker",function(){ax.hide();$(document).unbind("click.color-picker")});ay.stopPropagation()}),ao=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(av).attr("title","Set new random color").tooltip(),at=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(av).hide(),ak=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(at),ai=$("<div class='tooltip-arrow'></div>").appendTo(at),am=$.farbtastic(ak,{width:100,height:100,callback:aq,color:au});av.append($("<div/>").css("clear","both"));(function(ax){ao.click(function(){ax.setColor(j.get_random_color())})})(am)}else{aw.append($("<input />").attr("id",aj).attr("name",aj).val(au))}}}}if(af.help){aw.append($("<div class='help'/>").text(af.help))}}}ae(this.params,ad);return ad},update_from_form:function(ad){var af=this;var ae=false;$.each(this.params,function(ag,ai){if(!ai.hidden){var aj="param_"+ag;var ah=ad.find("#"+aj).val();if(ai.type==="bool"){ah=ad.find("#"+aj).is(":checked")}ae=af.set_param_value(ai.key,ah)||ae}});if(ae){this.onchange();this.track.changed()}}});var b=function(ad,ah,af,ae,ag){this.track=ad;this.region=ah;this.low=ah.get("start");this.high=ah.get("end");this.resolution=af;this.html_elt=$("<div class='track-tile'/>").append(ae).height($(ae).attr("height"));this.data=ag;this.stale=false};b.prototype.predisplay_actions=function(){};var M=function(ad,ah,af,ae,ag){b.call(this,ad,ah,af,ae,ag)};M.prototype.predisplay_actions=function(){};var O=function(ag,ao,ah,af,aj,aq,ak,ar,ae,an){b.call(this,ag,ao,ah,af,aj);this.mode=ak;this.all_slotted=ae;this.feature_mapper=an;this.has_icons=false;if(ar){this.has_icons=true;var al=this;af=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:af.width}).prependTo(this.html_elt);var am=new w.GenomeRegion({chrom:ag.view.chrom,start:this.low,end:this.high}),ap=aj.length,ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ad=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ai.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()});ad.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()})}};o(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ae=this,ad={};if(ae.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ap){if(!this.hovered){return}var ak=$(this).offset(),ao=ap.pageX-ak.left,an=ap.pageY-ak.top,au=ae.feature_mapper.get_feature_data(ao,an),al=(au?au[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!al||$(this).attr("id")!==al.toString()){$(this).remove()}});if(au){var ag=ad[al];if(!ag){var al=au[0],aq={name:au[3],start:au[1],end:au[2],strand:au[4]},aj=ae.track.filters_manager.filters,ai;for(var am=0;am<aj.length;am++){ai=aj[am];aq[ai.name]=au[ai.index]}var ag=$("<div/>").attr("id",al).addClass("feature-popup"),av=$("<table/>"),at,ar,aw;for(at in aq){ar=aq[at];aw=$("<tr/>").appendTo(av);$("<th/>").appendTo(aw).text(at);$("<td/>").attr("align","left").appendTo(aw).text(typeof(ar)==="number"?V(ar,2):ar)}ag.append($("<div class='feature-popup-inner'>").append(av));ad[al]=ag}ag.appendTo($(this).parents(".track-content").children(".overlay"));var ah=ao+parseInt(ae.html_elt.css("left"))-ag.width()/2,af=an+parseInt(ae.html_elt.css("top"))+7;ag.css("left",ah+"px").css("top",af+"px")}else{if(!ap.isPropagationStopped()){ap.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ap)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var f=function(ae,ad,af){o(af,{drag_handle_class:"draghandle"});p.call(this,ae,ad,af);this.dataset=(af.dataset?new X.Dataset(af.dataset):null);this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in af?af.data_query_wait:K);this.data_manager=("data_manager" in af?af.data_manager:new w.GenomeDataManager({dataset:this.dataset,genome:new w.Genome({key:ae.dbkey,chroms_info:{chrom_info:ae.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in af)||af.resize){this.add_resize_handle()}}};o(f.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ad){ad.view.set_overview(ad)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters()}else{ad.filters_manager.init_filters()}ad.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ad){ad.dynamic_tool_div.toggle();if(ad.dynamic_tool_div.is(":visible")){ad.set_name(ad.name+ad.tool_region_and_parameters_str())}else{ad.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ad){var ag='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',af=ac.template(ag,{track:ad});var ai=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(){var ak=$('select[name="regions"] option:selected').val(),am,aj=new w.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),al=ac.map($(".bookmark"),function(an){return new w.GenomeRegion({from_str:$(an).children(".position").text()})});if(ak==="cur"){am=[aj]}else{if(ak==="bookmarks"){am=al}else{am=[aj].concat(al)}}hide_modal();window.location.href=galaxy_config.root+"visualization/sweepster?"+$.param({dataset_id:ad.dataset.id,hda_ldda:ad.dataset.get("hda_ldda"),regions:JSON.stringify(new Backbone.Collection(am).toJSON())})},ah=function(aj){if((aj.keyCode||aj.which)===27){ai()}else{if((aj.keyCode||aj.which)===13){ae()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",af,{No:ai,Yes:ae})}},p.prototype.action_icons_def[2]],can_draw:function(){return this.dataset&&p.prototype.can_draw.call(this)},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ad=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ad)}this.name_div=$("<div/>").addClass("track-name").appendTo(ad).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ad},set_dataset:function(ad){this.dataset=ad;this.data_manager.set("dataset",ad)},on_resize:function(){this.request_draw({clear_tile_cache:true})},add_resize_handle:function(){var ad=this;var ag=false;var af=false;var ae=$("<div class='track-resize'>");$(ad.container_div).hover(function(){if(ad.content_visible){ag=true;ae.show()}},function(){ag=false;if(!af){ae.hide()}});ae.hide().bind("dragstart",function(ah,ai){af=true;ai.original_height=$(ad.content_div).height()}).bind("drag",function(ai,aj){var ah=Math.min(Math.max(aj.original_height+aj.deltaY,ad.min_height_px),ad.max_height_px);$(ad.tiles_div).css("height",ah);ad.visible_height_px=(ad.max_height_px===ah?0:ah);ad.on_resize()}).bind("dragend",function(ah,ai){ad.tile_cache.clear();af=false;if(!ag){ae.hide()}ad.config.values.height=ad.visible_height_px;ad.changed()}).appendTo(ad.container_div)},set_display_modes:function(ag,aj){this.display_modes=ag;this.mode=(aj?aj:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ae=this,ah={};for(var af=0,ad=ae.display_modes.length;af<ad;af++){var ai=ae.display_modes[af];ah[ai]=function(ak){return function(){ae.change_mode(ak);ae.icons_div.show();ae.container_div.mouseleave(function(){ae.icons_div.hide()})}}(ai)}make_popupmenu(this.action_icons.mode_icon,ah)},build_action_icons:function(){p.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof g){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof e){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(af){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.tiles_div.css("height","auto");ae.tiles_div.text("").children().remove();ae.container_div.removeClass("nodata error pending");if(!ae.dataset.id){return}var ad=$.Deferred(),ag={hda_ldda:ae.dataset.get("hda_ldda"),data_type:this.dataset_check_type,chrom:ae.view.chrom,retry:af};$.getJSON(this.dataset.url(),ag,function(ah){if(!ah||ah==="error"||ah.kind==="error"){ae.container_div.addClass("error");ae.tiles_div.text(m);if(ah.message){ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ah.message+"</pre>",{Close:hide_modal})}));ae.tiles_div.append($("<span/>").text(" "));ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ae.init(true)}))}}else{if(ah==="no converter"){ae.container_div.addClass("error");ae.tiles_div.text(J)}else{if(ah==="no data"||(ah.data!==undefined&&(ah.data===null||ah.data.length===0))){ae.container_div.addClass("nodata");ae.tiles_div.text(E)}else{if(ah==="pending"){ae.container_div.addClass("pending");ae.tiles_div.html(u);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(ah==="data"||ah.status==="data"){if(ah.valid_chroms){ae.valid_chroms=ah.valid_chroms;ae.update_icons()}ae.tiles_div.text(U);if(ae.view.chrom){ae.tiles_div.text("");ae.tiles_div.css("height",ae.visible_height_px+"px");ae.enabled=true;$.when.apply($,ae.predraw_init()).done(function(){ad.resolve();ae.container_div.removeClass("nodata error pending");ae.request_draw()})}else{ad.resolve()}}}}}}});this.update_icons();return ad},predraw_init:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){ad.container_div.addClass("line-track");var ag=ae.data;if(ag&&ag.min&&ag.max){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.config.set_param_default_value("min_value",af);ad.config.set_param_default_value("max_value",ah);ad.prefs.min_value=af;ad.prefs.max_value=ah}})},get_drawables:function(){return this}});var N=function(af,ae,ah){f.call(this,af,ae,ah);var ad=this;k(ad.container_div,ad.drag_handle_class,".group",ad);this.filters_manager=new h.FiltersManager(this,("filters" in ah?ah.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=(ah.tool?new q({track:this,tool:ah.tool,tool_state:ah.tool_state}):null);this.tile_cache=new w.Cache(Q);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){var ag=new ab({model:this.tool});ag.render();this.dynamic_tool_div=ag.$el;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(ah.mode){this.change_mode(ah.mode)}};o(N.prototype,p.prototype,f.prototype,{action_icons_def:f.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.slotters[ad.view.resolution_px_b].max_rows*=2;ad.request_draw({clear_tile_cache:true})},hide:true}]),copy:function(ad){var ae=this.to_dict();o(ae,{data_manager:this.data_manager});var af=new this.constructor(this.view,ad,ae);af.change_mode(this.mode);af.enabled=this.enabled;return af},set_filters_manager:function(ad){this.filters_manager=ad;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,dataset:{id:this.dataset.id,hda_ldda:this.dataset.get("hda_ldda")},prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},set_min_max:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){var ag=ae.data;if(isNaN(parseFloat(ad.prefs.min_value))||isNaN(parseFloat(ad.prefs.max_value))){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.prefs.min_value=af;ad.prefs.max_value=ah}})},change_mode:function(ae){var ad=this;ad.mode=ae;ad.config.values.mode=ae;if(ae==="Auto"){this.data_manager.clear()}ad.request_draw({clear_tile_cache:true});this.action_icons.mode_icon.attr("title","Set display mode (now: "+ad.mode+")");return ad},update_icons:function(){var ad=this;if(ad.filters_available){ad.action_icons.filters_icon.show()}else{ad.action_icons.filters_icon.hide()}if(ad.tool){ad.action_icons.tools_icon.show();ad.action_icons.param_space_viz_icon.show()}else{ad.action_icons.tools_icon.hide();ad.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ae,ad){return ae+"_"+ad},request_draw:function(ad){if(ad&&ad.clear_tile_cache){this.tile_cache.clear()}this.view.request_redraw(ad,this)},before_draw:function(){this.max_height_px=0},_draw:function(aq){if(!this.can_draw()){return}var an=aq&&aq.clear_after,al=this.view.low,ah=this.view.high,ak=ah-al,ae=this.view.container.width(),ap=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;ap=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ad=Math.floor(al/(ag*S)),am,ai,aj=[],ao=[];while((ad*S*ag)<ah){am=this._get_tile_bounds(ad,ag);ai=this.draw_helper(am,ag,ap,aq);aj.push(ai);$.when(ai).then(function(ar){ao.push(ar)});ad+=1}if(!an){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;$.when.apply($,aj).then(function(){af.tiles_div.children(".remove").remove();ao=ac.filter(ao,function(ar){return ar!==null});if(ao.length!==0){af.postdraw_actions(ao,ae,ap,an)}})},_add_yaxis_label:function(ag,ai){var ae=this,ah=(ag==="max"?"top":"bottom"),aj=(ag==="max"?"max":"min"),ad=(ag==="max"?"max_value":"min_value"),ai=ai||function(){ae.request_draw({clear_tile_cache:true})},af=this.container_div.find(".yaxislabel."+ah);if(af.length!==0){af.text(ae.prefs[ad])}else{af=$("<div/>").text(ae.prefs[ad]).make_text_editable({num_cols:12,on_finish:function(ak){$(".bs-tooltip").remove();ae.config.set_param_value(ad,ak);ai()},help_text:"Set "+aj+" value"}).addClass("yaxislabel "+ah).css("color",this.prefs.label_color);this.container_div.prepend(af)}},postdraw_actions:function(ag,ah,aj,ad){var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length>0){this.max_height_px=0;var ae=this;ac.each(ag,function(ak){if(!(ak instanceof M)){ak.html_elt.remove();ae.draw_helper(ak.region,ak.resolution,aj,{force:true,mode:"Coverage"})}});ae._add_yaxis_label("max")}else{this.container_div.find(".yaxislabel").remove();var ai=ac.find(ag,function(ak){return ak.has_icons});if(ai){ac.each(ag,function(ak){if(!ak.has_icons){ak.html_elt.css("padding-top",D)}})}}},get_mode:function(ad){return this.mode},update_auto_mode:function(ad){},_get_drawables:function(){return[this]},draw_helper:function(am,ag,ap,aq){if(!aq){aq={}}var ae=aq.force,ao=!(aq.data_fetch===false),aj=aq.mode||this.mode,af=this,ah=this._get_drawables(),an=this._gen_tile_cache_key(ap,am),ai=function(ar){return(ar&&"track" in ar)};var ak=(ae?undefined:af.tile_cache.get_elt(an));if(ak){if(ai(ak)){af.show_tile(ak,ap)}return ak}if(!ao){return null}var al=function(){var ar=(ac.find(A,function(au){return au===aj})?"Coverage":aj);var at=ac.map(ah,function(au){return au.data_manager.get_data(am,ar,ag,af.data_url_extra_params)});if(view.reference_track){at.push(view.reference_track.data_manager.get_data(am,aj,ag,view.reference_track.data_url_extra_params))}return at};var ad=$.Deferred();af.tile_cache.set_elt(an,ad);$.when.apply($,al()).then(function(){var ar=al(),ax=ar,aD;if(view.reference_track){aD=view.reference_track.data_manager.subset_entry(ar.pop(),am)}var ay=[],av=[];ac.each(ah,function(aI,aF){var aH=aI.mode,aG=ax[aF];if(aH==="Auto"){aH=aI.get_mode(aG);aI.update_auto_mode(aH)}ay.push(aH);av.push(aI.get_canvas_height(aG,aH,ap,at))});var aw=af.view.canvas_manager.new_canvas(),az=am.get("start"),aE=am.get("end"),au=0,at=Math.ceil((aE-az)*ap)+af.left_offset,aB=ac.max(av),aA;aw.width=at;aw.height=(aq.height||aB);var aC=aw.getContext("2d");aC.translate(af.left_offset,0);if(ah.length>1){aC.globalAlpha=0.5;aC.globalCompositeOperation="source-over"}ac.each(ah,function(aG,aF){aA=aG.draw_tile(ax[aF],aC,ay[aF],ag,am,ap,aD)});if(aA!==undefined){af.tile_cache.set_elt(an,aA);af.show_tile(aA,ap)}ad.resolve(aA)});return ad},get_canvas_height:function(ad,af,ag,ae){return this.visible_height_px},_draw_line_track_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.LinePainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new M(this,ai,ah,ag,ad.data)},draw_tile:function(ad,ae,ai,ag,ah,aj,af){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(af,ai){var ae=this,ad=af.html_elt;af.predisplay_actions();var ah=(af.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ah-=this.left_offset}ad.css({position:"absolute",top:0,left:ah});if(ad.hasClass("remove")){ad.removeClass("remove")}else{this.tiles_div.append(ad)}af.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,af.html_elt.height());af.html_elt.parent().children().css("height",this.max_height_px+"px");var ag=this.max_height_px;if(this.visible_height_px!==0){ag=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",ag+"px")},_get_tile_bounds:function(ad,ae){var ag=Math.floor(ad*S*ae),ah=Math.ceil(S*ae),af=(ag+ah<=this.view.max_high?ag+ah:this.view.max_high);return new w.GenomeRegion({chrom:this.view.chrom,start:ag,end:af})},tool_region_and_parameters_str:function(ag){var ad=this,af=(ag!==undefined?ag.toString():"all"),ae=ac.values(ad.tool.get("tool").get_inputs_dict()).join(", ");return" - region=["+af+"], parameters=["+ae+"]"},data_and_mode_compatible:function(ad,ae){if(ae==="Auto"){return true}else{if(ae==="Coverage"){return ad.dataset_type==="bigwig"}else{if(ad.extra_info==="no_detail"){return false}else{return true}}}},can_subset:function(ad){if(ad.dataset_type==="bigwig"||ad.message||ad.extra_info==="no_detail"){return false}return true},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(af,ag,ai,ad){var ae=this;ae.normal_postdraw_actions(af,ag,ai,ad);ae.dataset_check_type="converted_datasets_state";ae.data_query_wait=K;var ah=new j.ServerStateDeferred({url:ae.dataset_state_url,url_params:{dataset_id:ae.dataset.id,hda_ldda:ae.dataset.get("hda_ldda")},interval:ae.data_query_wait,success_fn:function(aj){return aj!=="pending"}});$.when(ah.go()).then(function(){ae.data_manager.set("data_type","data")});ae.postdraw_actions=ae.normal_postdraw_actions}}});var W=function(ae,ad){var af={resize:false};f.call(this,ae,ad,af);this.container_div.addClass("label-track")};o(W.prototype,f.prototype,{build_header_div:function(){},init:function(){this.enabled=true},predraw_init:function(){},_draw:function(ah){var af=this.view,ag=af.high-af.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ag)/Math.log(10)))),ad=Math.floor(af.low/ak)*ak,ai=this.view.container.width(),ae=$("<div style='position: relative; height: 1.3em;'></div>");while(ad<af.high){var aj=(ad-af.low)/ag*ai;ae.append($("<div class='label'>"+commatize(ad)+"</div>").css({position:"absolute",left:aj-1}));ad+=ak}this.content_div.children(":first").remove();this.content_div.append(ae)}});var e=function(ae,ad,ah){this.display_modes=A;N.call(this,ae,ad,ah);this.drawables=[];if("drawables" in ah){var ag;for(var af=0;af<ah.drawables.length;af++){ag=ah.drawables[af];this.drawables[af]=n(ag,ae,null);if(ag.left_offset>this.left_offset){this.left_offset=ag.left_offset}}this.enabled=true}ac.each(this.drawables,function(ai){if(ai instanceof c||ai instanceof T){ai.change_mode("Coverage")}});this.update_icons();this.obj_type="CompositeTrack"};o(e.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_group()}}].concat(N.prototype.action_icons_def),to_dict:y.prototype.to_dict,add_drawable:y.prototype.add_drawable,unpack_drawables:y.prototype.unpack_drawables,change_mode:function(ad){N.prototype.change_mode.call(this,ad);for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae].change_mode(ad)}},init:function(){var af=[];for(var ae=0;ae<this.drawables.length;ae++){af.push(this.drawables[ae].init())}var ad=this;$.when.apply($,af).then(function(){ad.enabled=true;ad.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:p.prototype.can_draw,_get_drawables:function(){return this.drawables},show_group:function(){var ag=new P(this.view,this.container,{name:this.name}),ad;for(var af=0;af<this.drawables.length;af++){ad=this.drawables[af];ad.update_icons();ag.add_drawable(ad);ad.container=ag;ag.content_div.append(ad.container_div)}var ae=this.container.replace_drawable(this,ag,true);ag.request_draw({clear_tile_cache:true})},before_draw:function(){N.prototype.before_draw.call(this);var ae=ac.min(ac.map(this.drawables,function(af){return af.prefs.min_value})),ad=ac.max(ac.map(this.drawables,function(af){return af.prefs.max_value}));this.prefs.min_value=ae;this.prefs.max_value=ad;ac.each(this.drawables,function(af){af.prefs.min_value=ae;af.prefs.max_value=ad})},update_all_min_max:function(){var ad=this;ac.each(this.drawables,function(ae){ae.prefs.min_value=ad.prefs.min_value;ae.prefs.max_value=ad.prefs.max_value});this.request_draw({clear_tile_cache:true})},postdraw_actions:function(aj,ad,am,ai){N.prototype.postdraw_actions.call(this,aj,ad,am,ai);var ah=-1;for(var af=0;af<aj.length;af++){var ak=aj[af].html_elt.find("canvas").height();if(ak>ah){ah=ak}}for(var af=0;af<aj.length;af++){var ag=aj[af];if(ag.html_elt.find("canvas").height()!==ah){this.draw_helper(ag.region,ag.resolution,am,{force:true,height:ah});ag.html_elt.remove()}}var ae=this,al=function(){ae.update_all_min_max()};this._add_yaxis_label("min",al);this._add_yaxis_label("max",al)}});var B=function(ad){N.call(this,ad,{content_div:ad.top_labeltrack},{resize:false});ad.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=galaxy_config.root+"api/genomes//"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new w.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};o(B.prototype,p.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},predraw_init:function(){},can_draw:p.prototype.can_draw,draw_helper:function(af,ae,ag,ad){if(ag>this.view.canvas_manager.char_width_px){this.tiles_div.show();return N.prototype.draw_helper.call(this,af,ae,ag,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ad){return true},draw_tile:function(ag,am,ah,ae,aj,an){var af=this.data_manager.subset_entry(ag,aj),al=af.data;var ad=am.canvas;am.font=am.canvas.manager.default_font;am.textAlign="center";for(var ai=0,ak=al.length;ai<ak;ai++){am.fillStyle=this.view.get_base_color(al[ai]);am.fillText(al[ai],Math.floor(ai*an),10)}return new b(this,aj,ae,ad,af)}});var g=function(af,ae,ag){var ad=this;this.display_modes=A;this.mode="Histogram";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:j.get_random_color()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(g.prototype,p.prototype,N.prototype,{before_draw:function(){},draw_tile:function(ad,ae,ah,af,ag,ai){return this._draw_line_track_tile(ad,ae,ah,af,ag,ai)},can_subset:function(ad){return(ad.data[1][0]-ad.data[0][0]===1)},postdraw_actions:function(ae,af,ag,ad){this._add_yaxis_label("max");this._add_yaxis_label("min")}});var r=function(af,ae,ag){var ad=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);this.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(r.prototype,p.prototype,N.prototype,{draw_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.DiagonalHeatmapPainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new b(this,ai,ah,ag,ad.data)}});var c=function(ag,af,ai){var ae=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ag,af,ai);var ah=j.get_random_color(),ad=j.get_random_color([ah,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ah},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ai.prefs,onchange:function(){ae.set_name(ae.prefs.name);ae.set_painter_from_config();ae.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};o(c.prototype,p.prototype,N.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},postdraw_actions:function(an,af,ao,am){N.prototype.postdraw_actions.call(this,an,af,ao,am);var ah=this,ai;if(ah.filters_manager){var ag=ah.filters_manager.filters;for(var ak=0;ak<ag.length;ak++){ag[ak].update_ui_elt()}var aj=false,al,ae;for(ai=0;ai<an.length;ai++){if(an[ai].data.length){al=an[ai].data[0];for(var ak=0;ak<ag.length;ak++){ae=ag[ak];if(ae.applies_to(al)&&ae.min!==ae.max){aj=true;break}}}}if(ah.filters_available!==aj){ah.filters_available=aj;if(!ah.filters_available){ah.filters_manager.hide()}ah.update_icons()}}if(an[0] instanceof O){var ad=true;for(ai=0;ai<an.length;ai++){if(!an[ai].all_slotted){ad=false;break}}if(!ad){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ad){var ad;if(this.mode==="Auto"){if(ad==="no_detail"){ad="feature spans"}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ad+")")}},incremental_slots:function(ah,ad,ag){var ae=this.view.canvas_manager.dummy_context,af=this.slotters[ah];if(!af||(af.mode!==ag)){af=new (s.FeatureSlotter)(ah,ag,z,function(ai){return ae.measureText(ai)});this.slotters[ah]=af}return af.slot_features(ad)},get_mode:function(ad){if(ad.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}return mode},get_canvas_height:function(ad,ah,ai,ae){if(ah==="Coverage"||ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=this.incremental_slots(ai,ad.data,ah);var af=new (this.painter)(null,null,null,this.prefs,ah);return Math.max(aa,af.get_required_height(ag,ae))}},draw_tile:function(an,ar,ap,at,ag,ak,af){var aq=this,ae=ar.canvas,az=ag.get("start"),ad=ag.get("end"),ah=this.left_offset;if(an.dataset_type==="bigwig"){return this._draw_line_track_tile(an,ar,ap,at,ag,ak)}var aj=[],ao=this.slotters[ak].slots;all_slotted=true;if(an.data){var al=this.filters_manager.filters;for(var au=0,aw=an.data.length;au<aw;au++){var ai=an.data[au];var av=false;var am;for(var ay=0,aD=al.length;ay<aD;ay++){am=al[ay];am.update_attrs(ai);if(!am.keep(ai)){av=true;break}}if(!av){aj.push(ai);if(!(ai[0] in ao)){all_slotted=false}}}}var aC=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),aA=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aB=new (this.painter)(aj,az,ad,this.prefs,ap,aC,aA,af,function(aE){return aq.view.get_base_color(aE)});var ax=null;ar.fillStyle=this.prefs.block_color;ar.font=ar.canvas.manager.default_font;ar.textAlign="right";if(an.data){ax=aB.draw(ar,ae.width,ae.height,ak,ao);ax.translation=-ah}return new O(aq,ag,at,ae,an.data,ak,ap,an.message,all_slotted,ax)}});var Z=function(ae,ad,af){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Histogram color",type:"color",default_value:j.get_random_color()},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};o(Z.prototype,p.prototype,N.prototype,{draw_tile:function(ad,ag,aj,ah,ai,ak){if(ad.dataset_type==="bigwig"){return this._draw_line_track_tile(ad,ag,"Histogram",ah,ai,ak)}else{var af=this.view,ae=new (this.painter)(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj,function(al){return af.get_base_color(al)});ae.draw(ag,ag.canvas.width,ag.canvas.height,ak);return new b(this,ai,ah,ag.canvas,ad.data)}},get_canvas_height:function(ad,ah,ai,af){if(ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=new (this.painter)(null,null,null,this.prefs,ah);var ae=(this.dataset.get_metadata("sample_names")?this.dataset.get_metadata("sample_names").length:0);if(ae===0&&ad.data.length!==0){ae=ad.data[0][7].match(/,/g);if(ae===null){ae=1}else{ae=ae.length+1}}return ag.get_required_height(ae)}},predraw_init:function(){var ad=[f.prototype.predraw_init.call(this)];if(!this.dataset.get_metadata("sample_names")){ad.push(this.dataset.fetch())}return ad},postdraw_actions:function(ag,ah,aj,ae){N.prototype.postdraw_actions.call(this,ag,ah,aj,ae);var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length===0&&this.prefs.show_labels){var ad;if(this.container_div.find(".yaxislabel.variant").length===0){ad=this.prefs.summary_height/2;this.tiles_div.prepend($("<div/>").text("Summary").addClass("yaxislabel variant top").css({"font-size":ad+"px",top:(this.prefs.summary_height-ad)/2+"px"}));if(this.prefs.show_sample_data){var ai=this.dataset.get("metadata").get("sample_names").join("<br/>");this.tiles_div.prepend($("<div/>").html(ai).addClass("yaxislabel variant top sample").css({top:this.prefs.summary_height+2,}))}}ad=(this.mode==="Squish"?5:10)+"px";$(this.tiles_div).find(".sample").css({"font-size":ad,"line-height":ad});$(this.tiles_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel.variant").remove()}}});var T=function(af,ae,ah){c.call(this,af,ae,ah);var ag=j.get_random_color(),ad=j.get_random_color([ag,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"}],saved_values:ah.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=(af.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};o(T.prototype,p.prototype,N.prototype,c.prototype);var d={CompositeTrack:e,DrawableGroup:P,DiagonalHeatmapTrack:r,FeatureTrack:c,LineTrack:g,ReadTrack:T,VariantTrack:Z,VcfTrack:Z};var n=function(af,ae,ad){if("copy" in af){return af.copy(ad)}else{var ag=af.obj_type;if(!ag){ag=af.track_type}return new d[ag](ae,ad,af)}};return{TracksterView:Y,DrawableGroup:P,LineTrack:g,FeatureTrack:c,DiagonalHeatmapTrack:r,ReadTrack:T,VariantTrack:Z,CompositeTrack:e,object_from_template:n}});
\ No newline at end of file
+define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","viz/trackster/filters","mvc/data","mvc/tools"],function(ac,w,j,s,L,h,X,R){var o=ac.extend;var l={};var i=function(ad,ae){l[ad.attr("id")]=ae};var k=function(ad,af,ah,ag){ah=".group";var ae={};l[ad.attr("id")]=ag;ad.bind("drag",{handle:"."+af,relative:true},function(ap,aq){var ao=$(this),au=$(this).parent(),al=au.children(),an=l[$(this).attr("id")],ak,aj,ar,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ar=aj.position().top;ai=ar+aj.outerHeight();if(aq.offsetY<ar){$(this).insertBefore(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable_before(an,at);return}else{if(aq.offsetY>ai){$(this).insertAfter(aj);var at=l[aj.attr("id")];at.remove_drawable(an);at.container.add_drawable(an);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ar=ak.position().top;ai=ar+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&aq.offsetY>=ar&&aq.offsetY<=ai){if(aq.offsetY-ar<ai-aq.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}if(an.container){an.container.remove_drawable(an)}l[ak.attr("id")].add_drawable(an);return}}for(am=0;am<al.length;am++){ak=$(al.get(am));if(aq.offsetY<ak.position().top&&!(ak.hasClass("reference-track")||ak.hasClass("intro"))){break}}if(am===al.length){if(this!==al.get(am-1)){au.append(this);l[au.attr("id")].move_drawable(an,am)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am));l[au.attr("id")].move_drawable(an,(aq.deltaY>0?am-1:am))}}}).bind("dragstart",function(){ae["border-top"]=ad.css("border-top");ae["border-bottom"]=ad.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ae)})};var aa=16,G=9,D=20,z=100,I=12000,S=400,K=5000,v=100,m="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",u="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",x="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20,A=["Histogram","Line","Filled","Intensity"];function V(ae,ad){if(!ad){ad=0}var af=Math.pow(10,ad);return Math.round(ae*af)/af}var p=function(ae,ad,ag){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ag.name;this.view=ae;this.container=ad;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ag.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ah){ah.stopPropagation()});var af=this;this.container_div.hover(function(){af.icons_div.show()},function(){af.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ad){if(ad.content_visible){ad.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ad.hide_contents();ad.content_visible=false}else{ad.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ad.content_visible=true;ad.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ae){var ag=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){ae.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},af=function(ah){if((ah.keyCode||ah.which)===27){ag()}else{if((ah.keyCode||ah.which)===13){ad()}}};$(window).bind("keypress.check_enter_esc",af);show_modal("Configure",ae.config.build_form(),{Cancel:ag,OK:ad})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.remove()}}];o(p.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(ad){},to_dict:function(){},set_name:function(ad){this.old_name=this.name;this.name=ad;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ad=this.view;this.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ae,aj,ai,ah,ad,ag){var af=this;this.action_icons[ae]=$("<a/>").attr("href","javascript:void(0);").attr("title",aj).addClass("icon-button").addClass(ai).tooltip().click(function(){ah(af)}).appendTo(this.icons_div);if(ag){this.action_icons[ae].hide()}},build_action_icons:function(ad){var af;for(var ae=0;ae<ad.length;ae++){af=ad[ae];this.add_action_icon(af.name,af.title,af.css_class,af.on_click_fn,af.prepend,af.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var y=function(ae,ad,af){p.call(this,ae,ad,af);this.obj_type=af.obj_type;this.drawables=[]};o(y.prototype,p.prototype,{unpack_drawables:function(af){this.drawables=[];var ae;for(var ad=0;ad<af.length;ad++){ae=n(af[ad],this.view,this);this.add_drawable(ae)}},init:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].init()}},_draw:function(ad){for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae]._draw(ad)}},to_dict:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ae}},add_drawable:function(ad){this.drawables.push(ad);ad.container=this;this.changed()},add_drawable_before:function(af,ad){this.changed();var ae=this.drawables.indexOf(ad);if(ae!==-1){this.drawables.splice(ae,0,af);return true}return false},replace_drawable:function(af,ad,ae){var ag=this.drawables.indexOf(af);if(ag!==-1){this.drawables[ag]=ad;if(ae){af.container_div.replaceWith(ad.container_div)}this.changed()}return ag},remove_drawable:function(ae){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);ae.container=null;this.changed();return true}return false},move_drawable:function(ae,af){var ad=this.drawables.indexOf(ae);if(ad!==-1){this.drawables.splice(ad,1);this.drawables.splice(af,0,ae);this.changed();return true}return false},get_drawables:function(){return this.drawables},get_tracks:function(ag){var ad=this.drawables.slice(0),ae=[],af;while(ad.length!==0){af=ad.shift();if(af instanceof ag){ae.push(af)}else{if(af.drawables){ad=ad.concat(af.drawables)}}}return ae}});var P=function(ae,ad,ag){o(ag,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});y.call(this,ae,ad,ag);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);i(this.container_div,this);i(this.content_div,this);k(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new h.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ag){this.unpack_drawables(ag.drawables)}if("filters" in ag){var af=this.filters_manager;this.filters_manager=new h.FiltersManager(this,ag.filters);af.parent_div.replaceWith(this.filters_manager.parent_div);if(ag.filters.visible){this.setup_multitrack_filtering()}}};o(P.prototype,p.prototype,y.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters();ad._restore_filter_managers()}else{ad.setup_multitrack_filtering();ad.request_draw({clear_tile_cache:true})}ad.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var ad=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ad)}return ad},build_header_div:function(){var ad=$("<div/>").addClass("track-header");ad.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ad);return ad},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var af=this.drawables.length;if(af===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(af===1){if(this.drawables[0] instanceof e){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var am,al,aj,ap=true,ah=this.drawables[0].get_type(),ad=0;for(am=0;am<af;am++){aj=this.drawables[am];if(aj.get_type()!==ah){can_composite=false;break}if(aj instanceof c){ad++}}if(ap||ad===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ad>1&&ad===this.drawables.length){var aq={},ae;aj=this.drawables[0];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];aq[ae.name]=[ae]}for(am=1;am<this.drawables.length;am++){aj=this.drawables[am];for(al=0;al<aj.filters_manager.filters.length;al++){ae=aj.filters_manager.filters[al];if(ae.name in aq){aq[ae.name].push(ae)}}}this.filters_manager.remove_all();var ag,ai,ak,an;for(var ao in aq){ag=aq[ao];if(ag.length===ad){ai=new h.NumberFilter({name:ag[0].name,index:ag[0].index});this.filters_manager.add_filter(ai)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].filters_manager=this.saved_filters_managers[ad]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ad=0;ad<this.drawables.length;ad++){drawable=this.drawables[ad];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ae=new e(this.view,this.view,{name:this.name,drawables:this.drawables});var ad=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);this.update_icons()},remove_drawable:function(ad){y.prototype.remove_drawable.call(this,ad);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ad=o(y.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ad},request_draw:function(ad){ac.each(this.drawables,function(ae){ae.request_draw(ad)})}});var Y=Backbone.View.extend({initialize:function(ad){o(ad,{obj_type:"View"});y.call(this,"View",ad.container,ad);this.chrom=null;this.vis_id=ad.vis_id;this.dbkey=ad.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new w.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"}],saved_values:ad.prefs,onchange:function(){track.request_redraw({clear_tile_cache:true})}})},render:function(){this.requested_redraw=false;var af=this.container,ad=this;this.top_container=$("<div/>").addClass("top-container").appendTo(af);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(af);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(af);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;i(this.viewport_container,ad);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ag=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){w.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",{"f-dbkey":ad.dbkey},function(ah){ac.each(ah,function(ai){ad.add_drawable(n(ai,ad,ad))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ae=function(ah){if(ah.type==="focusout"||(ah.keyCode||ah.which)===13||(ah.keyCode||ah.which)===27){if((ah.keyCode||ah.which)!==27){ad.go_to($(this).val())}$(this).hide();$(this).val("");ad.location_span.show();ad.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ae).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ad.location_span.hide();ad.chrom_select.hide();ad.nav_input.val(ad.chrom+":"+ad.low+"-"+ad.high);ad.nav_input.css("display","inline-block");ad.nav_input.select();ad.nav_input.focus();ad.nav_input.autocomplete({source:function(aj,ah){var ak=[],ai=$.map(ad.get_tracks(c),function(al){return al.data_manager.search_features(aj.term).success(function(am){ak=ak.concat(am)})});$.when.apply($,ai).done(function(){ah($.map(ak,function(al){return{label:al[0],value:al[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ad.zoom_out();ad.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ad.zoom_in();ad.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ad.change_chrom(ad.chrom_select.val())});this.browser_content_div.click(function(ah){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ah){ad.zoom_in(ah.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ah,ai){this.current_x=ai.offsetX}).bind("drag",function(ah,aj){var ak=aj.offsetX-this.current_x;this.current_x=aj.offsetX;var ai=Math.round(ak/ad.viewport_container.width()*(ad.max_high-ad.max_low));ad.move_delta(-ai)});this.overview_close.click(function(){ad.reset_overview()});this.viewport_container.bind("draginit",function(ah,ai){if(ah.clientX>ad.viewport_container.width()-16){return false}}).bind("dragstart",function(ah,ai){ai.original_low=ad.low;ai.current_height=ah.clientY;ai.current_x=ai.offsetX}).bind("drag",function(aj,al){var ah=$(this);var am=al.offsetX-al.current_x;var ai=ah.scrollTop()-(aj.clientY-al.current_height);ah.scrollTop(ai);al.current_height=aj.clientY;al.current_x=al.offsetX;var ak=Math.round(am/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}).bind("mousewheel",function(aj,al,ai,ah){if(ai){ai*=50;var ak=Math.round(-ai/ad.viewport_container.width()*(ad.high-ad.low));ad.move_delta(ak)}});this.top_labeltrack.bind("dragstart",function(ah,ai){return $("<div />").css({height:ad.browser_content_div.height()+ad.top_labeltrack.height()+ad.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(al,am){$(am.proxy).css({left:Math.min(al.pageX,am.startX)-ad.container.offset().left,width:Math.abs(al.pageX-am.startX)});var ai=Math.min(al.pageX,am.startX)-ad.container.offset().left,ah=Math.max(al.pageX,am.startX)-ad.container.offset().left,ak=(ad.high-ad.low),aj=ad.viewport_container.width();ad.update_location(Math.round(ai/aj*ak)+ad.low,Math.round(ah/aj*ak)+ad.low)}).bind("dragend",function(am,an){var ai=Math.min(am.pageX,an.startX),ah=Math.max(am.pageX,an.startX),ak=(ad.high-ad.low),aj=ad.viewport_container.width(),al=ad.low;ad.low=Math.round(ai/aj*ak)+al;ad.high=Math.round(ah/aj*ak)+al;$(an.proxy).remove();ad.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ad.resize_window()},500)});$(document).bind("redraw",function(){ad.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ad){return this.config.values[ad.toLowerCase()+"_color"]||this.config.values.n_color}});o(Y.prototype,y.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ae,ag,ad,ah){if(this.timer){clearTimeout(this.timer)}if(ah){var af=this;this.timer=setTimeout(function(){af.trigger("navigate",ae+":"+ag+"-"+ad)},500)}else{view.trigger("navigate",ae+":"+ag+"-"+ad)}},update_location:function(ad,af){this.location_span.text(commatize(ad)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ad)+"-"+commatize(af));var ae=view.chrom_select.val();if(ae!==""){this.trigger_navigate(ae,view.low,view.high,true)}},load_chroms:function(af){af.num=v;var ad=this,ae=$.Deferred();$.ajax({url:galaxy_config.root+"api/genomes/"+this.dbkey,data:af,dataType:"json",success:function(ah){if(ah.chrom_info.length===0){return}if(ah.reference){ad.add_label_track(new B(ad))}ad.chrom_data=ah.chrom_info;var ak='<option value="">Select Chrom/Contig</option>';for(var aj=0,ag=ad.chrom_data.length;aj<ag;aj++){var ai=ad.chrom_data[aj].chrom;ak+='<option value="'+ai+'">'+ai+"</option>"}if(ah.prev_chroms){ak+='<option value="previous">Previous '+v+"</option>"}if(ah.next_chroms){ak+='<option value="next">Next '+v+"</option>"}ad.chrom_select.html(ak);ad.chrom_start_index=ah.start_index;ae.resolve(ah.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ad.dbkey)}});return ae},change_chrom:function(ai,ae,ak){var af=this;if(!af.chrom_data){af.load_chroms_deferred.then(function(){af.change_chrom(ai,ae,ak)});return}if(!ai||ai==="None"){return}if(ai==="previous"){af.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){af.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(af.chrom_data,function(al,am){return al.chrom===ai})[0];if(aj===undefined){af.load_chroms({chrom:ai},function(){af.change_chrom(ai,ae,ak)});return}else{if(ai!==af.chrom){af.chrom=ai;af.chrom_select.val(af.chrom);af.max_high=aj.len-1;af.reset();for(var ah=0,ad=af.drawables.length;ah<ad;ah++){var ag=af.drawables[ah];if(ag.init){ag.init()}}if(af.reference_track){af.reference_track.init()}}if(ae&&ak){af.low=Math.max(ae,0);af.high=Math.min(ak,af.max_high)}else{af.low=0;af.high=af.max_high}af.reset_overview();af.request_redraw()}},go_to:function(ah){ah=ah.replace(/,/g,"");ah=ah.replace(/:|\-/g," ");var ae=ah.split(/\s+/),ag=ae[0],af=(ae[1]?parseInt(ae[1],10):null),ad=(ae[2]?parseInt(ae[2],10):null);if(!ad){af=af-15;ad=af+15}this.change_chrom(ag,af,ad)},move_fraction:function(af){var ad=this;var ae=ad.high-ad.low;this.move_delta(af*ae)},move_delta:function(ag){var ad=this;var af=ad.high-ad.low;if(ad.low-ag<ad.max_low){ad.low=ad.max_low;ad.high=ad.max_low+af}else{if(ad.high-ag>ad.max_high){ad.high=ad.max_high;ad.low=ad.max_high-af}else{ad.high-=ag;ad.low-=ag}}ad.request_redraw({data_fetch:false});if(this.redraw_on_move_fn){clearTimeout(this.redraw_on_move_fn)}this.redraw_on_move_fn=setTimeout(function(){ad.request_redraw()},200);var ae=ad.chrom_select.val();this.trigger_navigate(ae,ad.low,ad.high,true)},add_drawable:function(ad){y.prototype.add_drawable.call(this,ad);ad.init();this.changed();this.update_intro_div()},add_label_track:function(ad){ad.view=this;ad.init();this.label_tracks.push(ad)},remove_drawable:function(af,ae){y.prototype.remove_drawable.call(this,af);if(ae){var ad=this;af.container_div.hide(0,function(){$(this).remove();ad.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ae,af){var ad=this,ag=(af?[af]:ad.drawables);ac.each(ag,function(ah){var ai=ac.find(ad.tracks_to_be_redrawn,function(aj){return aj[0]===ah});if(ai){ai[1]=ae}else{ad.tracks_to_be_redrawn.push([ah,ae])}});if(!this.requested_redraw){requestAnimationFrame(function(){ad._redraw()});this.requested_redraw=true}},_redraw:function(){this.requested_redraw=false;var ad=this.low,ah=this.high;if(ad<this.max_low){ad=this.max_low}if(ah>this.max_high){ah=this.max_high}var ae=this.high-this.low;if(this.high!==0&&ae<this.min_separation){ah=ad+this.min_separation}this.low=Math.floor(ad);this.high=Math.ceil(ah);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ag=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var af=13;this.overview_box.css({left:ag,width:Math.max(af,ai)}).show();if(ai<af){this.overview_box.css("left",ag-(af-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ag,width:ai})}ac.each(this.tracks_to_be_redrawn,function(al){var aj=al[0],ak=al[1];if(aj){aj._draw(ak)}});this.tracks_to_be_redrawn=[];ac.each(this.label_tracks,function(aj){aj._draw()})},zoom_in:function(ae,af){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ag=this.high-this.low,ah=ag/2+this.low,ad=(ag/this.zoom_factor)/2;if(ae){ah=ae/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ah-ad);this.high=Math.round(ah+ad);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ae=this.high-this.low,af=ae/2+this.low,ad=(ae*this.zoom_factor)/2;this.low=Math.round(af-ad);this.high=Math.round(af+ad);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(af){if(this.overview_drawable){if(this.overview_drawable.dataset.id===af.dataset.id){return}this.overview_viewport.find(".track").remove()}var ae=af.copy({content_div:this.overview_viewport}),ad=this;ae.header_div.hide();ae.is_overview=true;ad.overview_drawable=ae;this.overview_drawable.postdraw_actions=function(){ad.overview_highlight.show().height(ad.overview_drawable.content_div.height());ad.overview_viewport.height(ad.overview_drawable.content_div.height()+ad.overview_box.outerHeight());ad.overview_close.show();ad.resize_window()};ad.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();view.overview_drawable=null}});var q=Backbone.RelationalModel.extend({defaults:{track:null,tool:null,},relations:[{type:Backbone.HasOne,key:"tool",relatedModel:R.Tool}],initialize:function(ad){this.get("tool").remove_inputs(["data","hidden_data","conditional"])}});var t=Backbone.View.extend({events:{"change input":"update_value"},render:function(){var af=this.$el.addClass("param-row"),ag=this.model;var ad=$("<div>").addClass("param-label").text(ag.get("label")).appendTo(af);var ae=$("<div/>").addClass("param-input").html(ag.get("html")).appendTo(af);ae.find(":input").val(ag.get("value"));$("<div style='clear: both;'/>").appendTo(af)},update_value:function(ad){this.model.set_value($(ad.target).val())}});var ab=Backbone.View.extend({render:function(){var ae=this;tool=this.model.get("tool"),parent_div=this.$el.addClass("dynamic-tool").hide();parent_div.bind("drag",function(ai){ai.stopPropagation()}).click(function(ai){ai.stopPropagation()}).bind("dblclick",function(ai){ai.stopPropagation()}).keydown(function(ai){ai.stopPropagation()});var af=$("<div class='tool-name'>").appendTo(parent_div).text(tool.get("name"));tool.get("inputs").each(function(aj){var ai=new t({model:aj});ai.render();parent_div.append(ai.$el)});parent_div.find("input").click(function(){$(this).select()});var ag=$("<div>").addClass("param-row").appendTo(parent_div);var ah=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ag);var ad=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ag);ad.click(function(){ae.run_on_region()});ah.click(function(){ae.run_on_dataset()})},update_params:function(){for(var ad=0;ad<this.params.length;ad++){this.params[ad].update_value()}},state_dict:function(){var ad=this.model.get("tool").get_param_values_dict();ad.visible=this.parent_div.is(":visible");return ad},run_on_dataset:function(){var ad=this.model.get("tool");this.run({target_dataset_id:this.model.get("track").dataset.id,action:"rerun",tool_id:ad.id},null,function(ae){show_modal(ad.get("name")+" is Running",ad.get("name")+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae=this.model.get("track"),ah=this.model.get("tool"),aj=new w.GenomeRegion({chrom:ae.view.chrom,start:ae.view.low,end:ae.view.high}),ak={target_dataset_id:ae.dataset.id,action:"rerun",tool_id:ah.id,regions:[aj.toJSON()]},ai=ae,am=ak.tool_id+ai.tool_region_and_parameters_str(aj),ad;if(ai.container===view){var al=new P(view,view,{name:this.name});var ag=ai.container.replace_drawable(ai,al,false);al.container_div.insertBefore(ai.view.content_div.children()[ag]);al.add_drawable(ai);ai.container_div.appendTo(al.content_div);ad=al}else{ad=ai.container}var af=new ai.constructor(view,ad,{name:am,hda_ldda:"hda"});af.init_for_tool_data();af.change_mode(ai.mode);af.set_filters_manager(ai.filters_manager.copy(af));af.update_icons();ad.add_drawable(af);af.tiles_div.text("Starting job.");this.run(ak,af,function(an){af.set_dataset(new X.Dataset(an));af.tiles_div.text("Running job.");af.init()})},run:function(ad,af,ag){ad.inputs=this.model.get("tool").get_inputs_dict();var ae=new j.ServerStateDeferred({ajax_settings:{url:galaxy_config.root+"api/tools",data:JSON.stringify(ad),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ah){return ah!=="pending"}});$.when(ae.go()).then(function(ah){if(ah==="no converter"){af.container_div.addClass("error");af.content_div.text(J)}else{if(ah.error){af.container_div.addClass("error");af.content_div.text(x+ah.message)}else{ag(ah)}}})}});var C=function(ad,ae){L.Scaler.call(this,ae);this.filter=ad};C.prototype.gen_val=function(ad){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ad[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ad){this.track=ad.track;this.params=ad.params;this.values={};this.restore_values((ad.saved_values?ad.saved_values:{}));this.onchange=ad.onchange};o(F.prototype,{set_param_default_value:function(ae,ad){var af=ac.find(this.params,function(ag){return ag.key===ae});if(af){af.default_value=ad}},set_param_value:function(ad,ae){var af=ac.find(this.params,function(ag){return ag.key===ad});if(af){if(typeof ae==="string"||ae instanceof String){if(ae.trim()===""){ae=af.default_value}else{if(af.type==="float"){ae=parseFloat(ae)}else{if(af.type==="int"){ae=parseInt(ae,10)}}}}}if(this.values[ad]!==ae){this.values[ad]=ae;return true}else{return false}},restore_values:function(ad){var ae=this;$.each(this.params,function(af,ag){if(ad[ag.key]!==undefined){ae.values[ag.key]=ad[ag.key]}else{ae.values[ag.key]=ag.default_value}})},build_form:function(){var ag=this;var ad=$("<div />");var af;function ae(al,ah){for(var ap=0;ap<al.length;ap++){af=al[ap];if(af.hidden){continue}var aj="param_"+ap;var au=ag.values[af.key];var aw=$("<div class='form-row' />").appendTo(ah);aw.append($("<label />").attr("for",aj).text(af.label+":"));if(af.type==="bool"){aw.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",au))}else{if(af.type==="text"){aw.append($('<input type="text"/>').attr("id",aj).val(au).click(function(){$(this).select()}))}else{if(af.type==="select"){var ar=$("<select />").attr("id",aj);for(var an=0;an<af.options.length;an++){$("<option/>").text(af.options[an].label).attr("value",af.options[an].value).appendTo(ar)}ar.val(au);aw.append(ar)}else{if(af.type==="color"){var av=$("<div/>").appendTo(aw),aq=$("<input />").attr("id",aj).attr("name",aj).val(au).css("float","left").appendTo(av).click(function(ay){$(".bs-tooltip").removeClass("in");var ax=$(this).siblings(".bs-tooltip").addClass("in");ax.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ax).height()/2)+($(this).height()/2)}).show();ax.click(function(az){az.stopPropagation()});$(document).bind("click.color-picker",function(){ax.hide();$(document).unbind("click.color-picker")});ay.stopPropagation()}),ao=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(av).attr("title","Set new random color").tooltip(),at=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(av).hide(),ak=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(at),ai=$("<div class='tooltip-arrow'></div>").appendTo(at),am=$.farbtastic(ak,{width:100,height:100,callback:aq,color:au});av.append($("<div/>").css("clear","both"));(function(ax){ao.click(function(){ax.setColor(j.get_random_color())})})(am)}else{aw.append($("<input />").attr("id",aj).attr("name",aj).val(au))}}}}if(af.help){aw.append($("<div class='help'/>").text(af.help))}}}ae(this.params,ad);return ad},update_from_form:function(ad){var af=this;var ae=false;$.each(this.params,function(ag,ai){if(!ai.hidden){var aj="param_"+ag;var ah=ad.find("#"+aj).val();if(ai.type==="bool"){ah=ad.find("#"+aj).is(":checked")}ae=af.set_param_value(ai.key,ah)||ae}});if(ae){this.onchange();this.track.changed()}}});var b=function(ad,ah,af,ae,ag){this.track=ad;this.region=ah;this.low=ah.get("start");this.high=ah.get("end");this.resolution=af;this.html_elt=$("<div class='track-tile'/>").append(ae).height($(ae).attr("height"));this.data=ag;this.stale=false};b.prototype.predisplay_actions=function(){};var M=function(ad,ah,af,ae,ag){b.call(this,ad,ah,af,ae,ag)};M.prototype.predisplay_actions=function(){};var O=function(ag,ao,ah,af,aj,aq,ak,ar,ae,an){b.call(this,ag,ao,ah,af,aj);this.mode=ak;this.all_slotted=ae;this.feature_mapper=an;this.has_icons=false;if(ar){this.has_icons=true;var al=this;af=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:af.width}).prependTo(this.html_elt);var am=new w.GenomeRegion({chrom:ag.view.chrom,start:this.low,end:this.high}),ap=aj.length,ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ad=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ap+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ai.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()});ad.click(function(){al.stale=true;ag.data_manager.get_more_data(am,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();ag.request_draw()}).dblclick(function(at){at.stopPropagation()})}};o(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ae=this,ad={};if(ae.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ap){if(!this.hovered){return}var ak=$(this).offset(),ao=ap.pageX-ak.left,an=ap.pageY-ak.top,au=ae.feature_mapper.get_feature_data(ao,an),al=(au?au[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!al||$(this).attr("id")!==al.toString()){$(this).remove()}});if(au){var ag=ad[al];if(!ag){var al=au[0],aq={name:au[3],start:au[1],end:au[2],strand:au[4]},aj=ae.track.filters_manager.filters,ai;for(var am=0;am<aj.length;am++){ai=aj[am];aq[ai.name]=au[ai.index]}var ag=$("<div/>").attr("id",al).addClass("feature-popup"),av=$("<table/>"),at,ar,aw;for(at in aq){ar=aq[at];aw=$("<tr/>").appendTo(av);$("<th/>").appendTo(aw).text(at);$("<td/>").attr("align","left").appendTo(aw).text(typeof(ar)==="number"?V(ar,2):ar)}ag.append($("<div class='feature-popup-inner'>").append(av));ad[al]=ag}ag.appendTo($(this).parents(".track-content").children(".overlay"));var ah=ao+parseInt(ae.html_elt.css("left"))-ag.width()/2,af=an+parseInt(ae.html_elt.css("top"))+7;ag.css("left",ah+"px").css("top",af+"px")}else{if(!ap.isPropagationStopped()){ap.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ap)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var f=function(ae,ad,af){o(af,{drag_handle_class:"draghandle"});p.call(this,ae,ad,af);this.dataset=null;if(af.dataset){this.dataset=(af.dataset instanceof Backbone.Model?af.dataset:new X.Dataset(af.dataset))}this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in af?af.data_query_wait:K);this.data_manager=("data_manager" in af?af.data_manager:new w.GenomeDataManager({dataset:this.dataset,genome:new w.Genome({key:ae.dbkey,chroms_info:{chrom_info:ae.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in af)||af.resize){this.add_resize_handle()}}};o(f.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ad){ad.view.set_overview(ad)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ad){if(ad.filters_manager.visible()){ad.filters_manager.clear_filters()}else{ad.filters_manager.init_filters()}ad.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ad){ad.dynamic_tool_div.toggle();if(ad.dynamic_tool_div.is(":visible")){ad.set_name(ad.name+ad.tool_region_and_parameters_str())}else{ad.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ad){var ag='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',af=ac.template(ag,{track:ad});var ai=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(){var ak=$('select[name="regions"] option:selected').val(),am,aj=new w.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),al=ac.map($(".bookmark"),function(an){return new w.GenomeRegion({from_str:$(an).children(".position").text()})});if(ak==="cur"){am=[aj]}else{if(ak==="bookmarks"){am=al}else{am=[aj].concat(al)}}hide_modal();window.location.href=galaxy_config.root+"visualization/sweepster?"+$.param({dataset_id:ad.dataset.id,hda_ldda:ad.dataset.get("hda_ldda"),regions:JSON.stringify(new Backbone.Collection(am).toJSON())})},ah=function(aj){if((aj.keyCode||aj.which)===27){ai()}else{if((aj.keyCode||aj.which)===13){ae()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",af,{No:ai,Yes:ae})}},p.prototype.action_icons_def[2]],can_draw:function(){return this.dataset&&p.prototype.can_draw.call(this)},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ad=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ad)}this.name_div=$("<div/>").addClass("track-name").appendTo(ad).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ad},set_dataset:function(ad){this.dataset=ad;this.data_manager.set("dataset",ad)},on_resize:function(){this.request_draw({clear_tile_cache:true})},add_resize_handle:function(){var ad=this;var ag=false;var af=false;var ae=$("<div class='track-resize'>");$(ad.container_div).hover(function(){if(ad.content_visible){ag=true;ae.show()}},function(){ag=false;if(!af){ae.hide()}});ae.hide().bind("dragstart",function(ah,ai){af=true;ai.original_height=$(ad.content_div).height()}).bind("drag",function(ai,aj){var ah=Math.min(Math.max(aj.original_height+aj.deltaY,ad.min_height_px),ad.max_height_px);$(ad.tiles_div).css("height",ah);ad.visible_height_px=(ad.max_height_px===ah?0:ah);ad.on_resize()}).bind("dragend",function(ah,ai){ad.tile_cache.clear();af=false;if(!ag){ae.hide()}ad.config.values.height=ad.visible_height_px;ad.changed()}).appendTo(ad.container_div)},set_display_modes:function(ag,aj){this.display_modes=ag;this.mode=(aj?aj:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ae=this,ah={};for(var af=0,ad=ae.display_modes.length;af<ad;af++){var ai=ae.display_modes[af];ah[ai]=function(ak){return function(){ae.change_mode(ak);ae.icons_div.show();ae.container_div.mouseleave(function(){ae.icons_div.hide()})}}(ai)}make_popupmenu(this.action_icons.mode_icon,ah)},build_action_icons:function(){p.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof g){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof e){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(af){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.tiles_div.css("height","auto");ae.tiles_div.text("").children().remove();ae.container_div.removeClass("nodata error pending");if(!ae.dataset.id){return}var ad=$.Deferred(),ag={hda_ldda:ae.dataset.get("hda_ldda"),data_type:this.dataset_check_type,chrom:ae.view.chrom,retry:af};$.getJSON(this.dataset.url(),ag,function(ah){if(!ah||ah==="error"||ah.kind==="error"){ae.container_div.addClass("error");ae.tiles_div.text(m);if(ah.message){ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ah.message+"</pre>",{Close:hide_modal})}));ae.tiles_div.append($("<span/>").text(" "));ae.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ae.init(true)}))}}else{if(ah==="no converter"){ae.container_div.addClass("error");ae.tiles_div.text(J)}else{if(ah==="no data"||(ah.data!==undefined&&(ah.data===null||ah.data.length===0))){ae.container_div.addClass("nodata");ae.tiles_div.text(E)}else{if(ah==="pending"){ae.container_div.addClass("pending");ae.tiles_div.html(u);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(ah==="data"||ah.status==="data"){if(ah.valid_chroms){ae.valid_chroms=ah.valid_chroms;ae.update_icons()}ae.tiles_div.text(U);if(ae.view.chrom){ae.tiles_div.text("");ae.tiles_div.css("height",ae.visible_height_px+"px");ae.enabled=true;$.when.apply($,ae.predraw_init()).done(function(){ad.resolve();ae.container_div.removeClass("nodata error pending");ae.request_draw()})}else{ad.resolve()}}}}}}});this.update_icons();return ad},predraw_init:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){ad.container_div.addClass("line-track");var ag=ae.data;if(ag&&ag.min&&ag.max){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.config.set_param_default_value("min_value",af);ad.config.set_param_default_value("max_value",ah);ad.prefs.min_value=af;ad.prefs.max_value=ah}})},get_drawables:function(){return this}});var N=function(af,ae,ah){f.call(this,af,ae,ah);var ad=this;k(ad.container_div,ad.drag_handle_class,".group",ad);this.filters_manager=new h.FiltersManager(this,("filters" in ah?ah.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=(ah.tool?new q({track:this,tool:ah.tool,tool_state:ah.tool_state}):null);this.tile_cache=new w.Cache(Q);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){var ag=new ab({model:this.tool});ag.render();this.dynamic_tool_div=ag.$el;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(ah.mode){this.change_mode(ah.mode)}};o(N.prototype,p.prototype,f.prototype,{action_icons_def:f.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.slotters[ad.view.resolution_px_b].max_rows*=2;ad.request_draw({clear_tile_cache:true})},hide:true}]),copy:function(ad){var ae=this.to_dict();o(ae,{data_manager:this.data_manager});var af=new this.constructor(this.view,ad,ae);af.change_mode(this.mode);af.enabled=this.enabled;return af},set_filters_manager:function(ad){this.filters_manager=ad;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,dataset:{id:this.dataset.id,hda_ldda:this.dataset.get("hda_ldda")},prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},set_min_max:function(){var ad=this;return $.getJSON(ad.dataset.url(),{data_type:"data",stats:true,chrom:ad.view.chrom,low:0,high:ad.view.max_high,hda_ldda:ad.dataset.get("hda_ldda")},function(ae){var ag=ae.data;if(isNaN(parseFloat(ad.prefs.min_value))||isNaN(parseFloat(ad.prefs.max_value))){var af=ag.min,ah=ag.max;af=Math.floor(Math.min(0,Math.max(af,ag.mean-2*ag.sd)));ah=Math.ceil(Math.max(0,Math.min(ah,ag.mean+2*ag.sd)));ad.prefs.min_value=af;ad.prefs.max_value=ah}})},change_mode:function(ae){var ad=this;ad.mode=ae;ad.config.values.mode=ae;if(ae==="Auto"){this.data_manager.clear()}ad.request_draw({clear_tile_cache:true});this.action_icons.mode_icon.attr("title","Set display mode (now: "+ad.mode+")");return ad},update_icons:function(){var ad=this;if(ad.filters_available){ad.action_icons.filters_icon.show()}else{ad.action_icons.filters_icon.hide()}if(ad.tool){ad.action_icons.tools_icon.show();ad.action_icons.param_space_viz_icon.show()}else{ad.action_icons.tools_icon.hide();ad.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ae,ad){return ae+"_"+ad},request_draw:function(ad){if(ad&&ad.clear_tile_cache){this.tile_cache.clear()}this.view.request_redraw(ad,this)},before_draw:function(){this.max_height_px=0},_draw:function(aq){if(!this.can_draw()){return}var an=aq&&aq.clear_after,al=this.view.low,ah=this.view.high,ak=ah-al,ae=this.view.container.width(),ap=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;ap=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ad=Math.floor(al/(ag*S)),am,ai,aj=[],ao=[];while((ad*S*ag)<ah){am=this._get_tile_bounds(ad,ag);ai=this.draw_helper(am,ag,ap,aq);aj.push(ai);$.when(ai).then(function(ar){ao.push(ar)});ad+=1}if(!an){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;$.when.apply($,aj).then(function(){af.tiles_div.children(".remove").remove();ao=ac.filter(ao,function(ar){return ar!==null});if(ao.length!==0){af.postdraw_actions(ao,ae,ap,an)}})},_add_yaxis_label:function(ag,ai){var ae=this,ah=(ag==="max"?"top":"bottom"),aj=(ag==="max"?"max":"min"),ad=(ag==="max"?"max_value":"min_value"),ai=ai||function(){ae.request_draw({clear_tile_cache:true})},af=this.container_div.find(".yaxislabel."+ah);if(af.length!==0){af.text(ae.prefs[ad])}else{af=$("<div/>").text(ae.prefs[ad]).make_text_editable({num_cols:12,on_finish:function(ak){$(".bs-tooltip").remove();ae.config.set_param_value(ad,ak);ai()},help_text:"Set "+aj+" value"}).addClass("yaxislabel "+ah).css("color",this.prefs.label_color);this.container_div.prepend(af)}},postdraw_actions:function(ag,ah,aj,ad){var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length>0){this.max_height_px=0;var ae=this;ac.each(ag,function(ak){if(!(ak instanceof M)){ak.html_elt.remove();ae.draw_helper(ak.region,ak.resolution,aj,{force:true,mode:"Coverage"})}});ae._add_yaxis_label("max")}else{this.container_div.find(".yaxislabel").remove();var ai=ac.find(ag,function(ak){return ak.has_icons});if(ai){ac.each(ag,function(ak){if(!ak.has_icons){ak.html_elt.css("padding-top",D)}})}}},get_mode:function(ad){return this.mode},update_auto_mode:function(ad){},_get_drawables:function(){return[this]},draw_helper:function(am,ag,ap,aq){if(!aq){aq={}}var ae=aq.force,ao=!(aq.data_fetch===false),aj=aq.mode||this.mode,af=this,ah=this._get_drawables(),an=this._gen_tile_cache_key(ap,am),ai=function(ar){return(ar&&"track" in ar)};var ak=(ae?undefined:af.tile_cache.get_elt(an));if(ak){if(ai(ak)){af.show_tile(ak,ap)}return ak}if(!ao){return null}var al=function(){var ar=(ac.find(A,function(au){return au===aj})?"Coverage":aj);var at=ac.map(ah,function(au){return au.data_manager.get_data(am,ar,ag,af.data_url_extra_params)});if(view.reference_track){at.push(view.reference_track.data_manager.get_data(am,aj,ag,view.reference_track.data_url_extra_params))}return at};var ad=$.Deferred();af.tile_cache.set_elt(an,ad);$.when.apply($,al()).then(function(){var ar=al(),ax=ar,aD;if(view.reference_track){aD=view.reference_track.data_manager.subset_entry(ar.pop(),am)}var ay=[],av=[];ac.each(ah,function(aI,aF){var aH=aI.mode,aG=ax[aF];if(aH==="Auto"){aH=aI.get_mode(aG);aI.update_auto_mode(aH)}ay.push(aH);av.push(aI.get_canvas_height(aG,aH,ap,at))});var aw=af.view.canvas_manager.new_canvas(),az=am.get("start"),aE=am.get("end"),au=0,at=Math.ceil((aE-az)*ap)+af.left_offset,aB=ac.max(av),aA;aw.width=at;aw.height=(aq.height||aB);var aC=aw.getContext("2d");aC.translate(af.left_offset,0);if(ah.length>1){aC.globalAlpha=0.5;aC.globalCompositeOperation="source-over"}ac.each(ah,function(aG,aF){aA=aG.draw_tile(ax[aF],aC,ay[aF],ag,am,ap,aD)});if(aA!==undefined){af.tile_cache.set_elt(an,aA);af.show_tile(aA,ap)}ad.resolve(aA)});return ad},get_canvas_height:function(ad,af,ag,ae){return this.visible_height_px},_draw_line_track_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.LinePainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new M(this,ai,ah,ag,ad.data)},draw_tile:function(ad,ae,ai,ag,ah,aj,af){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(af,ai){var ae=this,ad=af.html_elt;af.predisplay_actions();var ah=(af.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ah-=this.left_offset}ad.css({position:"absolute",top:0,left:ah});if(ad.hasClass("remove")){ad.removeClass("remove")}else{this.tiles_div.append(ad)}af.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,af.html_elt.height());af.html_elt.parent().children().css("height",this.max_height_px+"px");var ag=this.max_height_px;if(this.visible_height_px!==0){ag=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",ag+"px")},_get_tile_bounds:function(ad,ae){var ag=Math.floor(ad*S*ae),ah=Math.ceil(S*ae),af=(ag+ah<=this.view.max_high?ag+ah:this.view.max_high);return new w.GenomeRegion({chrom:this.view.chrom,start:ag,end:af})},tool_region_and_parameters_str:function(ag){var ad=this,af=(ag!==undefined?ag.toString():"all"),ae=ac.values(ad.tool.get("tool").get_inputs_dict()).join(", ");return" - region=["+af+"], parameters=["+ae+"]"},data_and_mode_compatible:function(ad,ae){if(ae==="Auto"){return true}else{if(ae==="Coverage"){return ad.dataset_type==="bigwig"}else{if(ad.extra_info==="no_detail"){return false}else{return true}}}},can_subset:function(ad){if(ad.dataset_type==="bigwig"||ad.message||ad.extra_info==="no_detail"){return false}return true},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state"}});var W=function(ae,ad){var af={resize:false};f.call(this,ae,ad,af);this.container_div.addClass("label-track")};o(W.prototype,f.prototype,{build_header_div:function(){},init:function(){this.enabled=true},predraw_init:function(){},_draw:function(ah){var af=this.view,ag=af.high-af.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ag)/Math.log(10)))),ad=Math.floor(af.low/ak)*ak,ai=this.view.container.width(),ae=$("<div style='position: relative; height: 1.3em;'></div>");while(ad<af.high){var aj=(ad-af.low)/ag*ai;ae.append($("<div class='label'>"+commatize(ad)+"</div>").css({position:"absolute",left:aj-1}));ad+=ak}this.content_div.children(":first").remove();this.content_div.append(ae)}});var e=function(ae,ad,ah){this.display_modes=A;N.call(this,ae,ad,ah);this.drawables=[];if("drawables" in ah){var ag;for(var af=0;af<ah.drawables.length;af++){ag=ah.drawables[af];this.drawables[af]=n(ag,ae,null);if(ag.left_offset>this.left_offset){this.left_offset=ag.left_offset}}this.enabled=true}ac.each(this.drawables,function(ai){if(ai instanceof c||ai instanceof T){ai.change_mode("Coverage")}});this.update_icons();this.obj_type="CompositeTrack"};o(e.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ad){$(".bs-tooltip").remove();ad.show_group()}}].concat(N.prototype.action_icons_def),to_dict:y.prototype.to_dict,add_drawable:y.prototype.add_drawable,unpack_drawables:y.prototype.unpack_drawables,change_mode:function(ad){N.prototype.change_mode.call(this,ad);for(var ae=0;ae<this.drawables.length;ae++){this.drawables[ae].change_mode(ad)}},init:function(){var af=[];for(var ae=0;ae<this.drawables.length;ae++){af.push(this.drawables[ae].init())}var ad=this;$.when.apply($,af).then(function(){ad.enabled=true;ad.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:p.prototype.can_draw,_get_drawables:function(){return this.drawables},show_group:function(){var ag=new P(this.view,this.container,{name:this.name}),ad;for(var af=0;af<this.drawables.length;af++){ad=this.drawables[af];ad.update_icons();ag.add_drawable(ad);ad.container=ag;ag.content_div.append(ad.container_div)}var ae=this.container.replace_drawable(this,ag,true);ag.request_draw({clear_tile_cache:true})},before_draw:function(){N.prototype.before_draw.call(this);var ae=ac.min(ac.map(this.drawables,function(af){return af.prefs.min_value})),ad=ac.max(ac.map(this.drawables,function(af){return af.prefs.max_value}));this.prefs.min_value=ae;this.prefs.max_value=ad;ac.each(this.drawables,function(af){af.prefs.min_value=ae;af.prefs.max_value=ad})},update_all_min_max:function(){var ad=this;ac.each(this.drawables,function(ae){ae.prefs.min_value=ad.prefs.min_value;ae.prefs.max_value=ad.prefs.max_value});this.request_draw({clear_tile_cache:true})},postdraw_actions:function(aj,ad,am,ai){N.prototype.postdraw_actions.call(this,aj,ad,am,ai);var ah=-1;for(var af=0;af<aj.length;af++){var ak=aj[af].html_elt.find("canvas").height();if(ak>ah){ah=ak}}for(var af=0;af<aj.length;af++){var ag=aj[af];if(ag.html_elt.find("canvas").height()!==ah){this.draw_helper(ag.region,ag.resolution,am,{force:true,height:ah});ag.html_elt.remove()}}var ae=this,al=function(){ae.update_all_min_max()};this._add_yaxis_label("min",al);this._add_yaxis_label("max",al)}});var B=function(ad){N.call(this,ad,{content_div:ad.top_labeltrack},{resize:false});ad.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=galaxy_config.root+"api/genomes//"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new w.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};o(B.prototype,p.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},predraw_init:function(){},can_draw:p.prototype.can_draw,draw_helper:function(af,ae,ag,ad){if(ag>this.view.canvas_manager.char_width_px){this.tiles_div.show();return N.prototype.draw_helper.call(this,af,ae,ag,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ad){return true},draw_tile:function(ag,am,ah,ae,aj,an){var af=this.data_manager.subset_entry(ag,aj),al=af.data;var ad=am.canvas;am.font=am.canvas.manager.default_font;am.textAlign="center";for(var ai=0,ak=al.length;ai<ak;ai++){am.fillStyle=this.view.get_base_color(al[ai]);am.fillText(al[ai],Math.floor(ai*an),10)}return new b(this,aj,ae,ad,af)}});var g=function(af,ae,ag){var ad=this;this.display_modes=A;this.mode="Histogram";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:j.get_random_color()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(g.prototype,p.prototype,N.prototype,{before_draw:function(){},draw_tile:function(ad,ae,ah,af,ag,ai){return this._draw_line_track_tile(ad,ae,ah,af,ag,ai)},can_subset:function(ad){return(ad.data[1][0]-ad.data[0][0]===1)},postdraw_actions:function(ae,af,ag,ad){this._add_yaxis_label("max");this._add_yaxis_label("min")}});var r=function(af,ae,ag){var ad=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,af,ae,ag);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:ag.prefs,onchange:function(){ad.set_name(ad.prefs.name);this.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};o(r.prototype,p.prototype,N.prototype,{draw_tile:function(ad,af,aj,ah,ai,ak){var ag=af.canvas,ae=new L.DiagonalHeatmapPainter(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj);ae.draw(af,ag.width,ag.height,ak);return new b(this,ai,ah,ag,ad.data)}});var c=function(ag,af,ai){var ae=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ag,af,ai);var ah=j.get_random_color(),ad=j.get_random_color([ah,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ah},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ai.prefs,onchange:function(){ae.set_name(ae.prefs.name);ae.set_painter_from_config();ae.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};o(c.prototype,p.prototype,N.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},postdraw_actions:function(an,af,ao,am){N.prototype.postdraw_actions.call(this,an,af,ao,am);var ah=this,ai;if(ah.filters_manager){var ag=ah.filters_manager.filters;for(var ak=0;ak<ag.length;ak++){ag[ak].update_ui_elt()}var aj=false,al,ae;for(ai=0;ai<an.length;ai++){if(an[ai].data.length){al=an[ai].data[0];for(var ak=0;ak<ag.length;ak++){ae=ag[ak];if(ae.applies_to(al)&&ae.min!==ae.max){aj=true;break}}}}if(ah.filters_available!==aj){ah.filters_available=aj;if(!ah.filters_available){ah.filters_manager.hide()}ah.update_icons()}}if(an[0] instanceof O){var ad=true;for(ai=0;ai<an.length;ai++){if(!an[ai].all_slotted){ad=false;break}}if(!ad){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ad){var ad;if(this.mode==="Auto"){if(ad==="no_detail"){ad="feature spans"}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ad+")")}},incremental_slots:function(ah,ad,ag){var ae=this.view.canvas_manager.dummy_context,af=this.slotters[ah];if(!af||(af.mode!==ag)){af=new (s.FeatureSlotter)(ah,ag,z,function(ai){return ae.measureText(ai)});this.slotters[ah]=af}return af.slot_features(ad)},get_mode:function(ad){if(ad.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}return mode},get_canvas_height:function(ad,ah,ai,ae){if(ah==="Coverage"||ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=this.incremental_slots(ai,ad.data,ah);var af=new (this.painter)(null,null,null,this.prefs,ah);return Math.max(aa,af.get_required_height(ag,ae))}},draw_tile:function(an,ar,ap,at,ag,ak,af){var aq=this,ae=ar.canvas,az=ag.get("start"),ad=ag.get("end"),ah=this.left_offset;if(an.dataset_type==="bigwig"){return this._draw_line_track_tile(an,ar,ap,at,ag,ak)}var aj=[],ao=this.slotters[ak].slots;all_slotted=true;if(an.data){var al=this.filters_manager.filters;for(var au=0,aw=an.data.length;au<aw;au++){var ai=an.data[au];var av=false;var am;for(var ay=0,aD=al.length;ay<aD;ay++){am=al[ay];am.update_attrs(ai);if(!am.keep(ai)){av=true;break}}if(!av){aj.push(ai);if(!(ai[0] in ao)){all_slotted=false}}}}var aC=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),aA=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aB=new (this.painter)(aj,az,ad,this.prefs,ap,aC,aA,af,function(aE){return aq.view.get_base_color(aE)});var ax=null;ar.fillStyle=this.prefs.block_color;ar.font=ar.canvas.manager.default_font;ar.textAlign="right";if(an.data){ax=aB.draw(ar,ae.width,ae.height,ak,ao);ax.translation=-ah}return new O(aq,ag,at,ae,an.data,ak,ap,an.message,all_slotted,ax)}});var Z=function(ae,ad,af){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Histogram color",type:"color",default_value:j.get_random_color()},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};o(Z.prototype,p.prototype,N.prototype,{draw_tile:function(ad,ag,aj,ah,ai,ak){if(ad.dataset_type==="bigwig"){return this._draw_line_track_tile(ad,ag,"Histogram",ah,ai,ak)}else{var af=this.view,ae=new (this.painter)(ad.data,ai.get("start"),ai.get("end"),this.prefs,aj,function(al){return af.get_base_color(al)});ae.draw(ag,ag.canvas.width,ag.canvas.height,ak);return new b(this,ai,ah,ag.canvas,ad.data)}},get_canvas_height:function(ad,ah,ai,af){if(ad.dataset_type==="bigwig"){return this.summary_draw_height}else{var ag=new (this.painter)(null,null,null,this.prefs,ah);var ae=(this.dataset.get_metadata("sample_names")?this.dataset.get_metadata("sample_names").length:0);if(ae===0&&ad.data.length!==0){ae=ad.data[0][7].match(/,/g);if(ae===null){ae=1}else{ae=ae.length+1}}return ag.get_required_height(ae)}},predraw_init:function(){var ad=[f.prototype.predraw_init.call(this)];if(!this.dataset.get_metadata("sample_names")){ad.push(this.dataset.fetch())}return ad},postdraw_actions:function(ag,ah,aj,ae){N.prototype.postdraw_actions.call(this,ag,ah,aj,ae);var af=ac.filter(ag,function(ak){return(ak instanceof M)});if(af.length===0&&this.prefs.show_labels){var ad;if(this.container_div.find(".yaxislabel.variant").length===0){ad=this.prefs.summary_height/2;this.tiles_div.prepend($("<div/>").text("Summary").addClass("yaxislabel variant top").css({"font-size":ad+"px",top:(this.prefs.summary_height-ad)/2+"px"}));if(this.prefs.show_sample_data){var ai=this.dataset.get("metadata").get("sample_names").join("<br/>");this.tiles_div.prepend($("<div/>").html(ai).addClass("yaxislabel variant top sample").css({top:this.prefs.summary_height+2,}))}}ad=(this.mode==="Squish"?5:10)+"px";$(this.tiles_div).find(".sample").css({"font-size":ad,"line-height":ad});$(this.tiles_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel.variant").remove()}}});var T=function(af,ae,ah){c.call(this,af,ae,ah);var ag=j.get_random_color(),ad=j.get_random_color([ag,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ad},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"}],saved_values:ah.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=(af.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};o(T.prototype,p.prototype,N.prototype,c.prototype);var d={CompositeTrack:e,DrawableGroup:P,DiagonalHeatmapTrack:r,FeatureTrack:c,LineTrack:g,ReadTrack:T,VariantTrack:Z,VcfTrack:Z};var n=function(af,ae,ad){if("copy" in af){return af.copy(ad)}else{var ag=af.obj_type;if(!ag){ag=af.track_type}return new d[ag](ae,ad,af)}};return{TracksterView:Y,DrawableGroup:P,LineTrack:g,FeatureTrack:c,DiagonalHeatmapTrack:r,ReadTrack:T,VariantTrack:Z,CompositeTrack:e,object_from_template:n}});
\ No newline at end of file
diff -r 89813e684db6ba8582aabc7cd045894d2021c872 -r d51946b4a19f41ebb77e79774c01b89357aa007f templates/webapps/galaxy/workflow/editor.mako
--- a/templates/webapps/galaxy/workflow/editor.mako
+++ b/templates/webapps/galaxy/workflow/editor.mako
@@ -32,7 +32,8 @@
"libs/jquery/jstorage",
"galaxy.workflow_editor.canvas",
"libs/jquery/jquery.autocomplete",
- "galaxy.autocom_tagging")}
+ "galaxy.autocom_tagging",
+ "galaxy.workflows" )}
<!--[if lt IE 7]><script type='text/javascript'>
@@ -41,639 +42,37 @@
<![endif]--><script type='text/javascript'>
- // Globals
- workflow = null;
- canvas_manager = null;
- active_ajax_call = false;
- var galaxy_async = new GalaxyAsync();
- galaxy_async.set_func_url(galaxy_async.set_user_pref, "${h.url_for( controller='user', action='set_user_pref_async' )}");
+ // Globals
+ workflow = null;
+ canvas_manager = null;
+ active_ajax_call = false;
- // jQuery onReady
- $( function() {
+ var workflow_id = "${trans.security.encode_id( stored.id ) }";
- if ( window.lt_ie_7 ) {
- show_modal(
- "Browser not supported",
- "Sorry, the workflow editor is not supported for IE6 and below."
- );
- return;
- }
+ // URLs used by galaxy.workflows.js
+ var tool_search_url = "${h.url_for( controller='root', action='tool_search' )}",
+ get_datatypes_url = "${h.url_for( controller='workflow', action='get_datatypes' )}",
+ load_workflow_url = "${h.url_for( controller='workflow', action='load_workflow' )}",
+ run_workflow_url = "${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id(stored.id))}",
+ rename_async_url = "${h.url_for( controller='workflow', action='rename_async', id=trans.security.encode_id(stored.id) )}",
+ annotate_async_url = "${h.url_for( controller='workflow', action='annotate_async', id=trans.security.encode_id(stored.id) )}",
+ get_new_module_info_url = "${h.url_for(controller='workflow', action='get_new_module_info' )}",
+ workflow_index_url = "${h.url_for( controller='workflow', action='index' )}",
+ save_workflow_url = "${h.url_for(controller='workflow', action='save_workflow' )}";
- // Init searching.
- $("#tool-search-query").click( function (){
- $(this).focus();
- $(this).select();
- })
- .keyup( function () {
- // Remove italics.
- $(this).css("font-style", "normal");
- // Don't update if same value as last time
- if ( this.value.length < 3 ) {
- reset_tool_search(false);
- } else if ( this.value != this.lastValue ) {
- // Add class to denote that searching is active.
- $(this).addClass("search_active");
- // input.addClass(config.loadingClass);
- // Add '*' to facilitate partial matching.
- var q = this.value + '*';
- // Stop previous ajax-request
- if (this.timer) {
- clearTimeout(this.timer);
- }
- // Start a new ajax-request in X ms
- $("#search-spinner").show();
- this.timer = setTimeout(function () {
- $.get("${h.url_for( controller='root', action='tool_search' )}", { query: q }, function (data) {
- // input.removeClass(config.loadingClass);
- // Show live-search if results and search-term aren't empty
- $("#search-no-results").hide();
- // Hide all tool sections.
- $(".toolSectionWrapper").hide();
- // This hides all tools but not workflows link (which is in a .toolTitle div).
- $(".toolSectionWrapper").find(".toolTitle").hide();
- if ( data.length != 0 ) {
- // Map tool ids to element ids and join them.
- var s = $.map( data, function( n, i ) { return "link-" + n; } );
- // First pass to show matching tools and their parents.
- $(s).each( function(index,id) {
- // Add class to denote match.
- $("[id='"+id+"']").parent().addClass("search_match");
- $("[id='"+id+"']").parent().show().parent().parent().show().parent().show();
- });
- // Hide labels that have no visible children.
- $(".toolPanelLabel").each( function() {
- var this_label = $(this);
- var next = this_label.next();
- var no_visible_tools = true;
- // Look through tools following label and, if none are visible, hide label.
- while (next.length !== 0 && next.hasClass("toolTitle")) {
- if (next.is(":visible")) {
- no_visible_tools = false;
- break;
- } else {
- next = next.next();
- }
- }
- if (no_visible_tools) {
- this_label.hide();
- }
- });
- } else {
- $("#search-no-results").show();
- }
- $("#search-spinner").hide();
- }, "json" );
- }, 200 );
- }
- this.lastValue = this.value;
- });
+ <%
+ from galaxy.jobs.actions.post import ActionBox
+ %>
+ // Post-job action vars.
+ var pja_list = "${ActionBox.get_add_list()}",
+ get_pja_form = function(pja) {
+ var p_str = '';
+ // FIXME: this writes JS code; this logic should be codified in galaxy.workflows.js
+ ${ActionBox.get_forms(trans)}
+ return p_str;
+ };
- // Canvas overview management
- canvas_manager = new CanvasManager( $("#canvas-viewport"), $("#overview") );
-
- // Initialize workflow state
- reset();
- // Load the datatype info
- $.ajax( {
- url: "${h.url_for( controller='workflow', action='get_datatypes' )}",
- dataType: "json",
- cache: false,
- success: function( data ) {
- populate_datatype_info( data );
- // Load workflow definition
- $.ajax( {
- url: "${h.url_for( controller='workflow', action='load_workflow' )}",
- data: { id: "${trans.security.encode_id( stored.id )}", "_": "true" },
- dataType: 'json',
- cache: false,
- success: function( data ) {
- reset();
- workflow.from_simple( data );
- workflow.has_changes = false;
- workflow.fit_canvas_to_nodes();
- scroll_to_nodes();
- canvas_manager.draw_overview();
- // Determine if any parameters were 'upgraded' and provide message
- upgrade_message = "";
- $.each( data.upgrade_messages, function( k, v ) {
- upgrade_message += ( "<li>Step " + ( parseInt(k, 10) + 1 ) + ": " + workflow.nodes[k].name + "<ul>");
- $.each( v, function( i, vv ) {
- upgrade_message += "<li>" + vv +"</li>";
- });
- upgrade_message += "</ul></li>";
- });
- if ( upgrade_message ) {
- show_modal( "Workflow loaded with changes",
- "Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>" + upgrade_message + "</ul>",
- { "Continue" : hide_modal } );
- } else {
- hide_modal();
- }
- show_workflow_parameters();
- },
- beforeSubmit: function( data ) {
- show_message( "Loading workflow", "progress" );
- }
- });
- }
- });
-
- // For autosave purposes
- $(document).ajaxStart( function() {
- active_ajax_call = true;
- $(document).bind( "ajaxStop.global", function() {
- active_ajax_call = false;
- });
- });
-
- $(document).ajaxError( function ( e, x ) {
- // console.log( e, x );
- var message = x.responseText || x.statusText || "Could not connect to server";
- show_modal( "Server error", message, { "Ignore error" : hide_modal } );
- return false;
- });
-
- make_popupmenu( $("#workflow-options-button"), {
- "Save" : save_current_workflow,
- "Run": function() {
- window.location = "${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id(stored.id))}";
- },
- ##"Create New" : create_new_workflow_dialog,
- "Edit Attributes" : edit_workflow_attributes,
- ##"Edit Workflow Outputs": edit_workflow_outputs,
- "Auto Re-layout": layout_editor,
- ##"Load a Workflow" : load_workflow,
- "Close": close_editor
- });
-
- function edit_workflow_outputs(){
- workflow.clear_active_node();
- $('.right-content').hide();
- var new_content = "";
- for (var node_key in workflow.nodes){
- var node = workflow.nodes[node_key];
- if(node.type == 'tool'){
- new_content += "<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step " + node.id + " - " + node.name + "</div>";
- for (var ot_key in node.output_terminals){
- var output = node.output_terminals[ot_key];
- // if (node.workflow_outputs[node.id + "|" + output.name]){
- if ($.inArray(output.name, node.workflow_outputs) != -1){
- new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' checked /></p>";
- }
- else{
- new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' /></p>";
- }
- }
- new_content += "</div>";
- }
- }
- $("#output-fill-area").html(new_content);
- $("#output-fill-area input").bind('click', function(){
- var node_id = this.name.split('|')[0];
- var output_name = this.name.split('|')[1];
- if (this.checked){
- if($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) == -1){
- workflow.nodes[node_id].workflow_outputs.push(output_name);
- }//else it's already in the array. Shouldn't happen, but forget it.
- }else{
- while ($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) != -1){
- var ia = $.inArray(output_name, workflow.nodes[node_id].workflow_outputs);
- workflow.nodes[node_id].workflow_outputs = workflow.nodes[node_id].workflow_outputs.slice(0,ia).concat( workflow.nodes[node_id].workflow_outputs.slice(ia+1) );
- }
- }
- workflow.has_changes = true;
- });
- $('#workflow-output-area').show();
- }
-
- function layout_editor() {
- workflow.layout();
- workflow.fit_canvas_to_nodes();
- scroll_to_nodes();
- canvas_manager.draw_overview();
- }
-
- function edit_workflow_attributes() {
- workflow.clear_active_node();
- $('.right-content').hide();
- $('#edit-attributes').show();
-
- }
-
- // On load, set the size to the pref stored in local storage if it exists
- overview_size = $.jStorage.get("overview-size");
- if (overview_size !== undefined) {
- $("#overview-border").css( {
- width: overview_size,
- height: overview_size
- });
- }
-
- // Show viewport on load unless pref says it's off
- if ($.jStorage.get("overview-off")) {
- hide_overview();
- } else {
- show_overview();
- }
-
- // Stores the size of the overview into local storage when it's resized
- $("#overview-border").bind( "dragend", function( e, d ) {
- var op = $(this).offsetParent();
- var opo = op.offset();
- var new_size = Math.max( op.width() - ( d.offsetX - opo.left ),
- op.height() - ( d.offsetY - opo.top ) );
- $.jStorage.set("overview-size", new_size + "px");
- });
-
- function show_overview() {
- $.jStorage.set("overview-off", false);
- $("#overview-border").css("right", "0px");
- $("#close-viewport").css("background-position", "0px 0px");
- }
-
- function hide_overview() {
- $.jStorage.set("overview-off", true);
- $("#overview-border").css("right", "20000px");
- $("#close-viewport").css("background-position", "12px 0px");
- }
-
- // Lets the overview be toggled visible and invisible, adjusting the arrows accordingly
- $("#close-viewport").click( function() {
- if ( $("#overview-border").css("right") === "0px" ) {
- hide_overview();
- } else {
- show_overview();
- }
- });
-
- // Unload handler
- window.onbeforeunload = function() {
- if ( workflow && workflow.has_changes ) {
- return "There are unsaved changes to your workflow which will be lost.";
- }
- };
-
- // Tool menu
- $( "div.toolSectionBody" ).hide();
- $( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" );
- var last_expanded = null;
- $( "div.toolSectionTitle" ).each( function() {
- var body = $(this).next( "div.toolSectionBody" );
- $(this).click( function() {
- if ( body.is( ":hidden" ) ) {
- if ( last_expanded ) last_expanded.slideUp( "fast" );
- last_expanded = body;
- body.slideDown( "fast" );
- }
- else {
- body.slideUp( "fast" );
- last_expanded = null;
- }
- });
- });
-
- // Rename async.
- async_save_text("workflow-name", "workflow-name", "${h.url_for( controller='workflow', action='rename_async', id=trans.security.encode_id(stored.id) )}", "new_name");
-
- // Tag async. Simply have the workflow edit element generate a click on the tag element to activate tagging.
- $('#workflow-tag').click( function() {
- $('.tag-area').click();
- return false;
- });
- // Annotate async.
- async_save_text("workflow-annotation", "workflow-annotation", "${h.url_for( controller='workflow', action='annotate_async', id=trans.security.encode_id(stored.id) )}", "new_annotation", 25, true, 4);
- });
-
- // Global state for the whole workflow
- function reset() {
- if ( workflow ) {
- workflow.remove_all();
- }
- workflow = new Workflow( $("#canvas-container") );
- }
-
- function scroll_to_nodes() {
- var cv = $("#canvas-viewport");
- var cc = $("#canvas-container");
- var top, left;
- if ( cc.width() < cv.width() ) {
- left = ( cv.width() - cc.width() ) / 2;
- } else {
- left = 0;
- }
- if ( cc.height() < cv.height() ) {
- top = ( cv.height() - cc.height() ) / 2;
- } else {
- top = 0;
- }
- cc.css( { left: left, top: top } );
- }
-
- // Add a new step to the workflow by tool id
- function add_node_for_tool( id, title ) {
- var node = prebuild_node( 'tool', title, id );
- workflow.add_node( node );
- workflow.fit_canvas_to_nodes();
- canvas_manager.draw_overview();
- workflow.activate_node( node );
- $.ajax( {
- url: "${h.url_for(controller='workflow', action='get_new_module_info' )}",
- data: { type: "tool", tool_id: id, "_": "true" },
- global: false,
- dataType: "json",
- success: function( data ) {
- node.init_field_data( data );
- },
- error: function( x, e ) {
- var m = "error loading field data";
- if ( x.status === 0 ) {
- m += ", server unavailable";
- }
- node.error( m );
- }
- });
- }
-
- function add_node_for_module( type, title ) {
- node = prebuild_node( type, title );
- workflow.add_node( node );
- workflow.fit_canvas_to_nodes();
- canvas_manager.draw_overview();
- workflow.activate_node( node );
- $.ajax( {
- url: "${h.url_for(controller='workflow', action='get_new_module_info' )}",
- data: { type: type, "_": "true" },
- dataType: "json",
- success: function( data ) {
- node.init_field_data( data );
- },
- error: function( x, e ) {
- var m = "error loading field data"
- if ( x.status == 0 ) {
- m += ", server unavailable"
- }
- node.error( m );
- }
- });
- }
-
-<%
- from galaxy.jobs.actions.post import ActionBox
-%>
-
- // This function preloads how to display known pja's.
- function display_pja(pja, node){
- // DBTODO SANITIZE INPUTS.
- p_str = '';
- ${ActionBox.get_forms(trans)}
- $("#pja_container").append(p_str);
- $("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function (){
- action_to_rem = $(this).closest(".toolForm", ".action_tag").children(".action_tag:first").text();
- $(this).closest(".toolForm").remove();
- delete workflow.active_node.post_job_actions[action_to_rem];
- workflow.active_form_has_changes = true;
- });
- }
-
- function display_pja_list(){
- return "${ActionBox.get_add_list()}";
- }
-
- function display_file_list(node){
- addlist = "<select id='node_data_list' name='node_data_list'>";
- for (var out_terminal in node.output_terminals){
- addlist += "<option value='" + out_terminal + "'>"+ out_terminal +"</option>";
- }
- addlist += "</select>";
- return addlist;
- }
-
- function new_pja(action_type, target, node){
- if (node.post_job_actions === undefined){
- //New tool node, set up dict.
- node.post_job_actions = {};
- }
- if (node.post_job_actions[action_type+target] === undefined){
- var new_pja = {};
- new_pja.action_type = action_type;
- new_pja.output_name = target;
- node.post_job_actions[action_type+target] = null;
- node.post_job_actions[action_type+target] = new_pja;
- display_pja(new_pja, node);
- workflow.active_form_has_changes = true;
- return true;
- } else {
- return false;
- }
- }
-
- function show_workflow_parameters(){
- var parameter_re = /\$\{.+?\}/g;
- var workflow_parameters = [];
- var wf_parm_container = $("#workflow-parameters-container");
- var wf_parm_box = $("#workflow-parameters-box");
- var new_parameter_content = "";
- var matches = [];
- $.each(workflow.nodes, function (k, node){
- var form_matches = node.form_html.match(parameter_re);
- if (form_matches){
- matches = matches.concat(form_matches);
- }
- if (node.post_job_actions){
- $.each(node.post_job_actions, function(k, pja){
- if (pja.action_arguments){
- $.each(pja.action_arguments, function(k, action_argument){
- var arg_matches = action_argument.match(parameter_re);
- if (arg_matches){
- matches = matches.concat(arg_matches);
- }
- });
- }
- });
- if (matches){
- $.each(matches, function(k, element){
- if ($.inArray(element, workflow_parameters) === -1){
- workflow_parameters.push(element);
- }
- });
- }
- }
- });
- if (workflow_parameters && workflow_parameters.length !== 0){
- $.each(workflow_parameters, function(k, element){
- new_parameter_content += "<div>" + element.substring(2, element.length -1) + "</div>";
- });
- wf_parm_container.html(new_parameter_content);
- wf_parm_box.show();
- }else{
- wf_parm_container.html(new_parameter_content);
- wf_parm_box.hide();
- }
- }
-
- function show_form_for_tool( text, node ) {
- $('.right-content').hide();
- $("#right-content").show().html( text );
- // Add metadata form to tool.
- if (node) {
- $("#right-content").find(".toolForm:first").after( "<p><div class='metadataForm'> \
- <div class='metadataFormTitle'>Edit Step Attributes</div> \
- <div class='form-row'> \
- <label>Annotation / Notes:</label> \
- <div style='margin-right: 10px;'> \
- <textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \
- <div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \
- </div> \
- </div> \
- </div>" );
- }
- // Add step actions.
- if (node && node.type=='tool'){
- pjastr = "<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> \
- " + display_pja_list() + " <br/> "+ display_file_list(node) + " <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div>\
- </div><div class='form-row'>\
- <div style='margin-right: 10px;'><span id='pja_container'></span>";
- pjastr += "<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";
- $("#right-content").find(".toolForm").after( pjastr );
- for (var key in node.post_job_actions){
- if (key != "undefined"){ //To make sure we haven't just deleted it.
- display_pja(node.post_job_actions[key], node);
- }
- }
- $("#add_pja").click(function (){
- new_pja($("#new_pja_list").val(),$("#node_data_list").val(), node);
- });
- }
- $("#right-content").find( "form" ).ajaxForm( {
- type: 'POST',
- dataType: 'json',
- success: function( data ) {
- workflow.active_form_has_changes = false;
- node.update_field_data( data );
- show_workflow_parameters();
- },
- beforeSubmit: function( data ) {
- data.push( { name: 'tool_state', value: node.tool_state } );
- data.push( { name: '_', value: "true" } );
- }
- }).each( function() {
- var form = this;
- $(this).find( "select[refresh_on_change='true']").change( function() {
- $(form).submit();
- });
- $(this).find( ".popupmenu" ).each( function() {
- var id = $(this).parents( "div.form-row" ).attr( 'id' );
- var b = $('<a class="popup-arrow" id="popup-arrow-for-' + id + '">▼</a>');
- var options = {};
- $(this).find( "button" ).each( function() {
- var name = $(this).attr( 'name' );
- var value = $(this).attr( 'value' );
- options[ $(this).text() ] = function() {
- $(form).append( "<input type='hidden' name='"+name+"' value='"+value+"' />" ).submit();
- };
- });
- b.insertAfter( this );
- $(this).remove();
- make_popupmenu( b, options );
- });
- // Implements auto-saving based on whether the inputs change. We consider
- // "changed" to be when a field is accessed and not necessarily modified
- // because of an issue where "onchange" is not triggered when activating
- // another node, or saving the workflow.
- $(this).find("input,textarea,select").each( function() {
- $(this).bind("focus click", function() {
- workflow.active_form_has_changes = true;
- });
- });
- });
- }
-
- var close_editor = function() {
- <% next_url = h.url_for( controller='workflow', action='index' ) %>
- workflow.check_changes_in_active_form();
- if ( workflow && workflow.has_changes ) {
- do_close = function() {
- window.onbeforeunload = undefined;
- window.document.location = "${next_url}"
- };
- show_modal( "Close workflow editor",
- "There are unsaved changes to your workflow which will be lost.",
- {
- "Cancel" : hide_modal,
- "Save Changes" : function() {
- save_current_workflow( null, do_close );
- }
- }, {
- "Don't Save": do_close
- } );
- } else {
- window.document.location = "${next_url}";
- }
- };
-
- var save_current_workflow = function ( eventObj, success_callback ) {
- show_message( "Saving workflow", "progress" );
- workflow.check_changes_in_active_form();
- if (!workflow.has_changes) {
- hide_modal();
- if ( success_callback ) {
- success_callback();
- }
- return;
- }
- workflow.rectify_workflow_outputs();
- var savefn = function(callback) {
- $.ajax( {
- url: "${h.url_for(controller='workflow', action='save_workflow' )}",
- type: "POST",
- data: {
- id: "${trans.security.encode_id( stored.id )}",
- workflow_data: function() { return JSON.stringify( workflow.to_simple() ); },
- "_": "true"
- },
- dataType: 'json',
- success: function( data ) {
- var body = $("<div></div>").text( data.message );
- if ( data.errors ) {
- body.addClass( "warningmark" );
- var errlist = $( "<ul/>" );
- $.each( data.errors, function( i, v ) {
- $("<li></li>").text( v ).appendTo( errlist );
- });
- body.append( errlist );
- } else {
- body.addClass( "donemark" );
- }
- workflow.name = data.name;
- workflow.has_changes = false;
- workflow.stored = true;
- show_workflow_parameters();
- if ( data.errors ) {
- show_modal( "Saving workflow", body, { "Ok" : hide_modal } );
- } else {
- if (callback) {
- callback();
- }
- hide_modal();
- }
- }
- });
- };
-
- // We bind to ajaxStop because of auto-saving, since the form submission ajax
- // call needs to be completed so that the new data is saved
- if (active_ajax_call) {
- $(document).bind('ajaxStop.save_workflow', function() {
- $(document).unbind('ajaxStop.save_workflow');
- savefn();
- $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here
- active_ajax_call = false;
- });
- } else {
- savefn(success_callback);
- }
- };
-
+ // NOTE: code to initialize and edit workflows is in galaxy.workflows.js
</script></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Enhance the Galaxy tool migration framework to support restricted repository dependency definitions. Repository dependency definitions contained in repositories that contain tools migrated from the Galaxy code base cannot define a dependency to a repository that contains a tool at any level of the dependency hierarchy.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/89813e684db6/
Changeset: 89813e684db6
User: greg
Date: 2013-08-26 15:57:18
Summary: Enhance the Galaxy tool migration framework to support restricted repository dependency definitions. Repository dependency definitions contained in repositories that contain tools migrated from the Galaxy code base cannot define a dependency to a repository that contains a tool at any level of the dependency hierarchy.
Affected #: 9 files
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -17,6 +17,7 @@
from galaxy.util import json
from galaxy.model.orm import and_
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import common_util as scu
from tool_shed.util import container_util
from tool_shed.util import encoding_util
from tool_shed.util import export_util
@@ -1579,6 +1580,8 @@
changeset_revision = kwd.get( 'changeset_revision', None )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
repository_id = trans.security.encode_id( repository.id )
+ # We aren't concerned with repository's of type tool_dependency_definition here if a repository_metadata record is not returned
+ # because repositories of this type will never have repository dependencies.
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
@@ -1642,7 +1645,7 @@
encoded_repository_ids = []
changeset_revisions = []
for required_repository_tup in decoded_required_repository_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( required_repository_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = scu.parse_repository_dependency_tuple( required_repository_tup )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
encoded_repository_ids.append( trans.security.encode_id( repository.id ) )
changeset_revisions.append( changeset_revision )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -54,7 +54,8 @@
print error_message
else:
root = tree.getroot()
- self.tool_shed = suc.clean_tool_shed_url( root.get( 'name' ) )
+ self.tool_shed_url = suc.get_url_from_tool_shed( self.app, root.get( 'name' ) )
+ self.tool_shed = suc.clean_tool_shed_url( self.tool_shed_url )
self.repository_owner = common_util.REPOSITORY_OWNER
index, self.shed_config_dict = suc.get_shed_tool_conf_dict( app, self.migrated_tools_config )
# Since tool migration scripts can be executed any number of times, we need to make sure the appropriate tools are defined in
@@ -85,7 +86,29 @@
for repository_elem in root:
# Make sure we have a valid repository tag.
if self.__is_valid_repository_tag( repository_elem ):
- self.install_repository( repository_elem, install_dependencies )
+ # Get all repository dependencies for the repository defined by the current repository_elem. Repository dependency
+ # definitions contained in tool shed repositories with migrated tools must never define a relationship to a repository
+ # dependency that contains a tool. The repository dependency can only contain items that are not loaded into the Galaxy
+ # tool panel (e.g., tool dependency definitions, custom datatypes, etc). This restriction must be followed down the
+ # entire dependency hierarchy.
+ name = repository_elem.get( 'name' )
+ changeset_revision = repository_elem.get( 'changeset_revision' )
+ tool_shed_accessible, repository_dependencies_dict = \
+ common_util.get_repository_dependencies( app, self.tool_shed_url, name, self.repository_owner, changeset_revision )
+ # Make sure all repository dependency records exist (as tool_shed_repository table rows) in the Galaxy database.
+ created_tool_shed_repositories = self.create_or_update_tool_shed_repository_records( name,
+ changeset_revision,
+ repository_dependencies_dict )
+ # Order the repositories for proper installation. This process is similar to the process used when installing tool
+ # shed repositories (i.e., the order_components_for_installation() method in ~/lib/tool_shed/galaxy_install/
+ # repository_util), but does not handle managing tool panel sections and other components since repository dependency
+ # definitions contained in tool shed repositories with migrated tools must never define a relationship to a repository
+ # dependency that contains a tool.
+ ordered_tool_shed_repositories = self.order_repositories_for_installation( created_tool_shed_repositories,
+ repository_dependencies_dict )
+
+ for tool_shed_repository in ordered_tool_shed_repositories:
+ self.install_repository( repository_elem, tool_shed_repository, install_dependencies )
else:
message = "\nNo tools associated with migration stage %s are defined in your " % str( latest_migration_script_number )
message += "file%s named %s,\nso no repositories will be installed on disk.\n" % ( plural, file_names )
@@ -95,6 +118,52 @@
message += "Try again later.\n"
print message
+ def create_or_update_tool_shed_repository_record( self, name, owner, changeset_revision, description=None ):
+
+ # Install path is of the form: <tool path>/<tool shed>/repos/<repository owner>/<repository name>/<installed changeset revision>
+ relative_clone_dir = os.path.join( self.tool_shed, 'repos', owner, name, changeset_revision )
+ clone_dir = os.path.join( self.tool_path, relative_clone_dir )
+ if not self.__isinstalled( clone_dir ):
+ repository_clone_url = os.path.join( self.tool_shed_url, 'repos', owner, name )
+ relative_install_dir = os.path.join( relative_clone_dir, name )
+ install_dir = os.path.join( clone_dir, name )
+ ctx_rev = suc.get_ctx_rev( self.app, self.tool_shed_url, name, owner, changeset_revision )
+ tool_shed_repository = suc.create_or_update_tool_shed_repository( app=self.app,
+ name=name,
+ description=description,
+ installed_changeset_revision=changeset_revision,
+ ctx_rev=ctx_rev,
+ repository_clone_url=repository_clone_url,
+ metadata_dict={},
+ status=self.app.model.ToolShedRepository.installation_status.NEW,
+ current_changeset_revision=None,
+ owner=self.repository_owner,
+ dist_to_shed=True )
+ return tool_shed_repository
+ return None
+
+ def create_or_update_tool_shed_repository_records( self, name, changeset_revision, repository_dependencies_dict ):
+ """
+ Make sure the repository defined by name and changeset_revision and all of it's repository dependencies have associated tool_shed_repository
+ table rows in the Galaxy database.
+ """
+ created_tool_shed_repositories = []
+ description = repository_dependencies_dict.get( 'description', None )
+ tool_shed_repository = self.create_or_update_tool_shed_repository_record( name, self.repository_owner, changeset_revision, description=description )
+ if tool_shed_repository:
+ created_tool_shed_repositories.append( tool_shed_repository )
+ for rd_key, rd_tups in repository_dependencies_dict.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ rd_tool_shed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = \
+ common_util.parse_repository_dependency_tuple( rd_tup )
+ # TODO: Make sure the repository description is applied to the new repository record during installation.
+ tool_shed_repository = self.create_or_update_tool_shed_repository_record( rd_name, rd_owner, rd_changeset_revision, description=None )
+ if tool_shed_repository:
+ created_tool_shed_repositories.append( tool_shed_repository )
+ return created_tool_shed_repositories
+
def filter_and_persist_proprietary_tool_panel_configs( self, tool_configs_to_filter ):
"""Eliminate all entries in all non-shed-related tool panel configs for all tool config file names in the received tool_configs_to_filter."""
for proprietary_tool_conf in self.proprietary_tool_confs:
@@ -131,7 +200,38 @@
fh.close()
shutil.move( tmp_filename, os.path.abspath( proprietary_tool_conf ) )
os.chmod( proprietary_tool_conf, 0644 )
-
+
+ def get_containing_tool_sections( self, tool_config ):
+ """
+ If tool_config is defined somewhere in self.proprietary_tool_panel_elems, return True and a list of ToolSections in which the
+ tool is displayed. If the tool is displayed outside of any sections, None is appended to the list.
+ """
+ tool_sections = []
+ is_displayed = False
+ for proprietary_tool_panel_elem in self.proprietary_tool_panel_elems:
+ if proprietary_tool_panel_elem.tag == 'tool':
+ # The proprietary_tool_panel_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
+ proprietary_tool_config = proprietary_tool_panel_elem.get( 'file' )
+ proprietary_name = suc.strip_path( proprietary_tool_config )
+ if tool_config == proprietary_name:
+ # The tool is loaded outside of any sections.
+ tool_sections.append( None )
+ if not is_displayed:
+ is_displayed = True
+ if proprietary_tool_panel_elem.tag == 'section':
+ # The proprietary_tool_panel_elem looks something like <section name="EMBOSS" id="EMBOSSLite">.
+ for section_elem in proprietary_tool_panel_elem:
+ if section_elem.tag == 'tool':
+ # The section_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
+ proprietary_tool_config = section_elem.get( 'file' )
+ proprietary_name = suc.strip_path( proprietary_tool_config )
+ if tool_config == proprietary_name:
+ # The tool is loaded inside of the section_elem.
+ tool_sections.append( ToolSection( proprietary_tool_panel_elem ) )
+ if not is_displayed:
+ is_displayed = True
+ return is_displayed, tool_sections
+
def get_guid( self, repository_clone_url, relative_install_dir, tool_config ):
if self.shed_config_dict.get( 'tool_path' ):
relative_install_dir = os.path.join( self.shed_config_dict['tool_path'], relative_install_dir )
@@ -150,6 +250,30 @@
tool = self.toolbox.load_tool( full_path )
return suc.generate_tool_guid( repository_clone_url, tool )
+ def get_prior_install_required_dict( self, tool_shed_repositories, repository_dependencies_dict ):
+ """
+ Return a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained in the received
+ list of tsr_ids and whose associated repository must be installed prior to the repository associated with the tsr_id key.
+ """
+ # Initialize the dictionary.
+ prior_install_required_dict = {}
+ tsr_ids = [ tool_shed_repository.id for tool_shed_repository in tool_shed_repositories ]
+ for tsr_id in tsr_ids:
+ prior_install_required_dict[ tsr_id ] = []
+ # Inspect the repository dependencies about to be installed and populate the dictionary.
+ for rd_key, rd_tups in repository_dependencies_dict.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ prior_install_ids = []
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
+ if util.asbool( prior_installation_required ):
+ for tsr in tool_shed_repositories:
+ if tsr.name == name and tsr.owner == owner and tsr.changeset_revision == changeset_revision:
+ prior_install_ids.append( tsr.id )
+ prior_install_required_dict[ tsr.id ] = prior_install_ids
+ return prior_install_required_dict
+
def get_proprietary_tool_panel_elems( self, latest_tool_migration_script_number ):
"""
Parse each config in self.proprietary_tool_confs (the default is tool_conf.xml) and generate a list of Elements that are
@@ -196,37 +320,6 @@
tool_panel_elems.append( elem )
return tool_panel_elems
- def get_containing_tool_sections( self, tool_config ):
- """
- If tool_config is defined somewhere in self.proprietary_tool_panel_elems, return True and a list of ToolSections in which the
- tool is displayed. If the tool is displayed outside of any sections, None is appended to the list.
- """
- tool_sections = []
- is_displayed = False
- for proprietary_tool_panel_elem in self.proprietary_tool_panel_elems:
- if proprietary_tool_panel_elem.tag == 'tool':
- # The proprietary_tool_panel_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
- proprietary_tool_config = proprietary_tool_panel_elem.get( 'file' )
- proprietary_name = suc.strip_path( proprietary_tool_config )
- if tool_config == proprietary_name:
- # The tool is loaded outside of any sections.
- tool_sections.append( None )
- if not is_displayed:
- is_displayed = True
- if proprietary_tool_panel_elem.tag == 'section':
- # The proprietary_tool_panel_elem looks something like <section name="EMBOSS" id="EMBOSSLite">.
- for section_elem in proprietary_tool_panel_elem:
- if section_elem.tag == 'tool':
- # The section_elem looks something like <tool file="emboss_5/emboss_antigenic.xml" />.
- proprietary_tool_config = section_elem.get( 'file' )
- proprietary_name = suc.strip_path( proprietary_tool_config )
- if tool_config == proprietary_name:
- # The tool is loaded inside of the section_elem.
- tool_sections.append( ToolSection( proprietary_tool_panel_elem ) )
- if not is_displayed:
- is_displayed = True
- return is_displayed, tool_sections
-
def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies ):
"""
Generate the metadata for the installed tool shed repository, among other things. If the installed tool_shed_repository contains tools
@@ -362,33 +455,26 @@
except:
pass
- def install_repository( self, repository_elem, install_dependencies ):
- # Install a single repository, loading contained tools into the tool panel.
- name = repository_elem.get( 'name' )
- description = repository_elem.get( 'description' )
- installed_changeset_revision = repository_elem.get( 'changeset_revision' )
+ def install_repository( self, repository_elem, tool_shed_repository, install_dependencies ):
+ """Install a single repository, loading contained tools into the tool panel."""
# Install path is of the form: <tool path>/<tool shed>/repos/<repository owner>/<repository name>/<installed changeset revision>
- relative_clone_dir = os.path.join( self.tool_shed, 'repos', self.repository_owner, name, installed_changeset_revision )
+ relative_clone_dir = os.path.join( tool_shed_repository.tool_shed,
+ 'repos',
+ tool_shed_repository.owner,
+ tool_shed_repository.name,
+ tool_shed_repository.installed_changeset_revision )
clone_dir = os.path.join( self.tool_path, relative_clone_dir )
if self.__isinstalled( clone_dir ):
- print "Skipping automatic install of repository '", name, "' because it has already been installed in location ", clone_dir
+ print "Skipping automatic install of repository '", tool_shed_repository.name, "' because it has already been installed in location ", clone_dir
else:
- tool_shed_url = suc.get_url_from_tool_shed( self.app, self.tool_shed )
- repository_clone_url = os.path.join( tool_shed_url, 'repos', self.repository_owner, name )
- relative_install_dir = os.path.join( relative_clone_dir, name )
- install_dir = os.path.join( clone_dir, name )
- ctx_rev = suc.get_ctx_rev( self.app, tool_shed_url, name, self.repository_owner, installed_changeset_revision )
- tool_shed_repository = suc.create_or_update_tool_shed_repository( app=self.app,
- name=name,
- description=description,
- installed_changeset_revision=installed_changeset_revision,
- ctx_rev=ctx_rev,
- repository_clone_url=repository_clone_url,
- metadata_dict={},
- status=self.app.model.ToolShedRepository.installation_status.NEW,
- current_changeset_revision=None,
- owner=self.repository_owner,
- dist_to_shed=True )
+ repository_clone_url = os.path.join( self.tool_shed_url, 'repos', tool_shed_repository.owner, tool_shed_repository.name )
+ relative_install_dir = os.path.join( relative_clone_dir, tool_shed_repository.name )
+ install_dir = os.path.join( clone_dir, tool_shed_repository.name )
+ ctx_rev = suc.get_ctx_rev( self.app,
+ self.tool_shed_url,
+ tool_shed_repository.name,
+ tool_shed_repository.owner,
+ tool_shed_repository.installed_changeset_revision )
suc.update_tool_shed_repository_status( self.app, tool_shed_repository, self.app.model.ToolShedRepository.installation_status.CLONING )
cloned_ok, error_message = suc.clone_repository( repository_clone_url, os.path.abspath( install_dir ), ctx_rev )
if cloned_ok:
@@ -405,8 +491,8 @@
self.app.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS )
# Get the tool_versions from the tool shed for each tool in the installed change set.
url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s' % \
- ( tool_shed_url, tool_shed_repository.name, self.repository_owner, installed_changeset_revision )
- text = common_util.tool_shed_get( self.app, tool_shed_url, url )
+ ( self.tool_shed_url, tool_shed_repository.name, self.repository_owner, tool_shed_repository.installed_changeset_revision )
+ text = common_util.tool_shed_get( self.app, self.tool_shed_url, url )
if text:
tool_version_dicts = from_json_string( text )
tool_util.handle_tool_versions( self.app, tool_version_dicts, tool_shed_repository )
@@ -445,6 +531,40 @@
def non_shed_tool_panel_configs( self ):
return common_util.get_non_shed_tool_panel_configs( self.app )
+ def order_repositories_for_installation( self, tool_shed_repositories, repository_dependencies_dict ):
+ """
+ Some repositories may have repository dependencies that are required to be installed before the dependent repository. This method will
+ inspect the list of repositories about to be installed and make sure to order them appropriately. For each repository about to be installed,
+ if required repositories are not contained in the list of repositories about to be installed, then they are not considered. Repository
+ dependency definitions that contain circular dependencies should not result in an infinite loop, but obviously prior installation will not be
+ handled for one or more of the repositories that require prior installation. This process is similar to the process used when installing tool
+ shed repositories (i.e., the order_components_for_installation() method in ~/lib/tool_shed/galaxy_install/repository_util), but does not handle
+ managing tool panel sections and other components since repository dependency definitions contained in tool shed repositories with migrated
+ tools must never define a relationship to a repository dependency that contains a tool.
+ """
+ ordered_tool_shed_repositories = []
+ ordered_tsr_ids = []
+ processed_tsr_ids = []
+ prior_install_required_dict = self.get_prior_install_required_dict( tool_shed_repositories, repository_dependencies_dict )
+ tsr_ids = [ tool_shed_repository.id for tool_shed_repository in tool_shed_repositories ]
+ while len( processed_tsr_ids ) != len( prior_install_required_dict.keys() ):
+ tsr_id = suc.get_next_prior_import_or_install_required_dict_entry( prior_install_required_dict, processed_tsr_ids )
+ processed_tsr_ids.append( tsr_id )
+ # Create the ordered_tsr_ids, the ordered_repo_info_dicts and the ordered_tool_panel_section_keys lists.
+ if tsr_id not in ordered_tsr_ids:
+ prior_install_required_ids = prior_install_required_dict[ tsr_id ]
+ for prior_install_required_id in prior_install_required_ids:
+ if prior_install_required_id not in ordered_tsr_ids:
+ # Install the associated repository dependency first.
+ ordered_tsr_ids.append( prior_install_required_id )
+ ordered_tsr_ids.append( tsr_id )
+ for ordered_tsr_id in ordered_tsr_ids:
+ for tool_shed_repository in tool_shed_repositories:
+ if tool_shed_repository.id == ordered_tsr_id:
+ ordered_tool_shed_repositories.append( tool_shed_repository )
+ break
+ return ordered_tool_shed_repositories
+
def __isinstalled( self, clone_dir ):
full_path = os.path.abspath( clone_dir )
if os.path.exists( full_path ):
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -211,7 +211,7 @@
if key in [ 'description', 'root_key' ]:
continue
for rd_tup in rd_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
# Updates to installed repository revisions may have occurred, so make sure to locate the appropriate repository revision if one exists.
# We need to create a temporary repo_info_tuple that includes the correct repository owner which we get from the current rd_tup. The current
# tuple looks like: ( description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, installed_td )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/common_util.py
--- a/lib/tool_shed/util/common_util.py
+++ b/lib/tool_shed/util/common_util.py
@@ -1,11 +1,20 @@
import os
import urllib2
+from galaxy.util import json
from galaxy.util.odict import odict
from tool_shed.util import encoding_util
from tool_shed.util import xml_util
REPOSITORY_OWNER = 'devteam'
+def accumulate_tool_dependencies( tool_shed_accessible, tool_dependencies, all_tool_dependencies ):
+ if tool_shed_accessible:
+ if tool_dependencies:
+ for tool_dependency in tool_dependencies:
+ if tool_dependency not in all_tool_dependencies:
+ all_tool_dependencies.append( tool_dependency )
+ return all_tool_dependencies
+
def check_for_missing_tools( app, tool_panel_configs, latest_tool_migration_script_number ):
# Get the 000x_tools.xml file associated with the current migrate_tools version number.
tools_xml_file_path = os.path.abspath( os.path.join( 'scripts', 'migrate_tools', '%04d_tools.xml' % latest_tool_migration_script_number ) )
@@ -23,30 +32,38 @@
if tool_shed_url:
for elem in root:
if elem.tag == 'repository':
- tool_dependencies = []
- tool_dependencies_dict = {}
+ repository_dependencies = []
+ all_tool_dependencies = []
repository_name = elem.get( 'name' )
changeset_revision = elem.get( 'changeset_revision' )
- url = '%s/repository/get_tool_dependencies?name=%s&owner=%s&changeset_revision=%s&from_install_manager=True' % \
- ( tool_shed_url, repository_name, REPOSITORY_OWNER, changeset_revision )
- try:
- text = tool_shed_get( app, tool_shed_url, url )
- tool_shed_accessible = True
- except Exception, e:
- # Tool shed may be unavailable - we have to set tool_shed_accessible since we're looping.
- tool_shed_accessible = False
- print "The URL\n%s\nraised the exception:\n%s\n" % ( url, str( e ) )
- if tool_shed_accessible:
- if text:
- tool_dependencies_dict = encoding_util.tool_shed_decode( text )
- for dependency_key, requirements_dict in tool_dependencies_dict.items():
- tool_dependency_name = requirements_dict[ 'name' ]
- tool_dependency_version = requirements_dict[ 'version' ]
- tool_dependency_type = requirements_dict[ 'type' ]
- tool_dependency_readme = requirements_dict.get( 'readme', '' )
- tool_dependencies.append( ( tool_dependency_name, tool_dependency_version, tool_dependency_type, tool_dependency_readme ) )
- for tool_elem in elem.findall( 'tool' ):
- migrated_tool_configs_dict[ tool_elem.get( 'file' ) ] = tool_dependencies
+ tool_shed_accessible, repository_dependencies_dict = get_repository_dependencies( app,
+ tool_shed_url,
+ repository_name,
+ REPOSITORY_OWNER,
+ changeset_revision )
+ # Accumulate all tool dependencies defined for repository dependencies for display to the user.
+ for rd_key, rd_tups in repository_dependencies_dict.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ tool_shed, name, owner, changeset_revision, prior_installation_required = parse_repository_dependency_tuple( rd_tup )
+ tool_shed_accessible, tool_dependencies = get_tool_dependencies( app,
+ tool_shed,
+ name,
+ owner,
+ changeset_revision )
+ all_tool_dependencies = accumulate_tool_dependencies( tool_shed_accessible, tool_dependencies, all_tool_dependencies )
+ tool_shed_accessible, tool_dependencies = get_tool_dependencies( app, tool_shed_url, repository_name, REPOSITORY_OWNER, changeset_revision )
+ all_tool_dependencies = accumulate_tool_dependencies( tool_shed_accessible, tool_dependencies, all_tool_dependencies )
+ for tool_elem in elem.findall( 'tool' ):
+ tool_config_file_name = tool_elem.get( 'file' )
+ if tool_config_file_name:
+ # We currently do nothing with repository dependencies except install them (we do not display repositories that will be
+ # installed to the user). However, we'll store them in the following dictionary in case we choose to display them in the
+ # future.
+ dependencies_dict = dict( tool_dependencies=all_tool_dependencies,
+ repository_dependencies=repository_dependencies )
+ migrated_tool_configs_dict[ tool_config_file_name ] = dependencies_dict
if tool_shed_accessible:
# Parse the proprietary tool_panel_configs (the default is tool_conf.xml) and generate the list of missing tool config file names.
for tool_panel_config in tool_panel_configs:
@@ -90,6 +107,44 @@
config_filenames.append( config_filename )
return config_filenames
+def get_repository_dependencies( app, tool_shed_url, repository_name, repository_owner, changeset_revision ):
+ repository_dependencies_dict = {}
+ tool_shed_accessible = True
+ url = '%s/repository/get_repository_dependencies?name=%s&owner=%s&changeset_revision=%s' % \
+ ( tool_shed_url, repository_name, repository_owner, changeset_revision )
+ try:
+ raw_text = tool_shed_get( app, tool_shed_url, url )
+ tool_shed_accessible = True
+ except Exception, e:
+ tool_shed_accessible = False
+ print "The URL\n%s\nraised the exception:\n%s\n" % ( url, str( e ) )
+ if tool_shed_accessible:
+ if len( raw_text ) > 2:
+ encoded_text = json.from_json_string( raw_text )
+ repository_dependencies_dict = encoding_util.tool_shed_decode( encoded_text )
+ return tool_shed_accessible, repository_dependencies_dict
+
+def get_tool_dependencies( app, tool_shed_url, repository_name, repository_owner, changeset_revision ):
+ tool_dependencies = []
+ tool_shed_accessible = True
+ url = '%s/repository/get_tool_dependencies?name=%s&owner=%s&changeset_revision=%s&from_install_manager=True' % \
+ ( tool_shed_url, repository_name, repository_owner, changeset_revision )
+ try:
+ text = tool_shed_get( app, tool_shed_url, url )
+ tool_shed_accessible = True
+ except Exception, e:
+ tool_shed_accessible = False
+ print "The URL\n%s\nraised the exception:\n%s\n" % ( url, str( e ) )
+ if tool_shed_accessible:
+ if text:
+ tool_dependencies_dict = encoding_util.tool_shed_decode( text )
+ for dependency_key, requirements_dict in tool_dependencies_dict.items():
+ tool_dependency_name = requirements_dict[ 'name' ]
+ tool_dependency_version = requirements_dict[ 'version' ]
+ tool_dependency_type = requirements_dict[ 'type' ]
+ tool_dependencies.append( ( tool_dependency_name, tool_dependency_version, tool_dependency_type ) )
+ return tool_shed_accessible, tool_dependencies
+
def get_tool_shed_url_from_tools_xml_file_path( app, tool_shed ):
search_str = '://%s' % tool_shed
for shed_name, shed_url in app.tool_shed_registry.tool_sheds.items():
@@ -98,7 +153,29 @@
shed_url = shed_url.rstrip( '/' )
return shed_url
return None
-
+
+def parse_repository_dependency_tuple( repository_dependency_tuple, contains_error=False ):
+ if contains_error:
+ if len( repository_dependency_tuple ) == 5:
+ # Metadata should have been reset on the repository containing this repository_dependency definition.
+ tool_shed, name, owner, changeset_revision, error = repository_dependency_tuple
+ # Default prior_installation_required to False.
+ prior_installation_required = False
+ elif len( repository_dependency_tuple ) == 6:
+ toolshed, name, owner, changeset_revision, prior_installation_required, error = repository_dependency_tuple
+ prior_installation_required = str( prior_installation_required )
+ return toolshed, name, owner, changeset_revision, prior_installation_required, error
+ else:
+ if len( repository_dependency_tuple ) == 4:
+ # Metadata should have been reset on the repository containing this repository_dependency definition.
+ tool_shed, name, owner, changeset_revision = repository_dependency_tuple
+ # Default prior_installation_required to False.
+ prior_installation_required = False
+ elif len( repository_dependency_tuple ) == 5:
+ tool_shed, name, owner, changeset_revision, prior_installation_required = repository_dependency_tuple
+ prior_installation_required = str( prior_installation_required )
+ return tool_shed, name, owner, changeset_revision, prior_installation_required
+
def tool_shed_get( app, tool_shed_url, uri ):
"""Make contact with the tool shed via the uri provided."""
registry = app.tool_shed_registry
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/container_util.py
--- a/lib/tool_shed/util/container_util.py
+++ b/lib/tool_shed/util/container_util.py
@@ -3,6 +3,7 @@
import threading
from galaxy.util import asbool
from galaxy.web.framework.helpers import time_ago
+from tool_shed.util import common_util
from tool_shed.util import readme_util
import tool_shed.util.shed_util_common as suc
@@ -63,7 +64,7 @@
self.repository_dependencies.remove( contained_repository_dependency )
def to_repository_dependency( self, repository_dependency_id ):
- toolshed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( self.key.split( STRSEP ) )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( self.key.split( STRSEP ) )
return RepositoryDependency( id=repository_dependency_id,
toolshed=toolshed,
repository_name=name,
@@ -463,7 +464,7 @@
folder_id += 1
invalid_repository_dependency_id += 1
toolshed, name, owner, changeset_revision, prior_installation_required, error = \
- suc.parse_repository_dependency_tuple( invalid_repository_dependency, contains_error=True )
+ common_util.parse_repository_dependency_tuple( invalid_repository_dependency, contains_error=True )
key = generate_repository_dependencies_key_for_repository( toolshed, name, owner, changeset_revision, prior_installation_required )
label = "Repository <b>%s</b> revision <b>%s</b> owned by <b>%s</b>" % ( name, changeset_revision, owner )
folder = Folder( id=folder_id,
@@ -1336,7 +1337,7 @@
can_create_dependency = not is_subfolder_of( sub_folder, repository_dependency )
if can_create_dependency:
toolshed, repository_name, repository_owner, changeset_revision, prior_installation_required = \
- suc.parse_repository_dependency_tuple( repository_dependency )
+ common_util.parse_repository_dependency_tuple( repository_dependency )
repository_dependency_id += 1
repository_dependency = RepositoryDependency( id=repository_dependency_id,
toolshed=toolshed,
@@ -1352,7 +1353,7 @@
def is_subfolder_of( folder, repository_dependency ):
toolshed, repository_name, repository_owner, changeset_revision, prior_installation_required = \
- suc.parse_repository_dependency_tuple( repository_dependency )
+ common_util.parse_repository_dependency_tuple( repository_dependency )
key = generate_repository_dependencies_key_for_repository( toolshed, repository_name, repository_owner, changeset_revision, asbool( prior_installation_required ) )
for sub_folder in folder.folders:
if key == sub_folder.key:
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/encoding_util.py
--- a/lib/tool_shed/util/encoding_util.py
+++ b/lib/tool_shed/util/encoding_util.py
@@ -44,4 +44,4 @@
value = val
a = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
b = binascii.hexlify( value )
- return "%s:%s" % ( a, b )
\ No newline at end of file
+ return "%s:%s" % ( a, b )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -354,9 +354,9 @@
Determine if the only difference between rd_tup and a dependency definition in the list of repository_dependencies is the changeset_revision value.
"""
new_metadata_required = False
- rd_tool_shed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
+ rd_tool_shed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
for repository_dependency in repository_dependencies:
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
if rd_tool_shed == tool_shed and rd_name == name and rd_owner == owner:
# Determine if the repository represented by the dependency tuple is an instance of the repository type TipOnly.
required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -54,7 +54,7 @@
for repository_dependency_components_list in val:
required_repository = None
rd_toolshed, rd_name, rd_owner, rd_changeset_revision, prior_installation_required = \
- suc.parse_repository_dependency_tuple( repository_dependency_components_list )
+ common_util.parse_repository_dependency_tuple( repository_dependency_components_list )
# Get the the tool_shed_repository defined by rd_name, rd_owner and rd_changeset_revision. This is the repository that will be
# required by the current dependent_repository.
# TODO: Check tool_shed_repository.tool_shed as well when repository dependencies across tool sheds is supported.
@@ -254,7 +254,7 @@
invalid_repository_dependencies = invalid_repository_dependencies_dict.get( 'invalid_repository_dependencies', [] )
for repository_dependency_tup in invalid_repository_dependencies:
toolshed, name, owner, changeset_revision, prior_installation_required, error = \
- suc.parse_repository_dependency_tuple( repository_dependency_tup, contains_error=True )
+ common_util.parse_repository_dependency_tuple( repository_dependency_tup, contains_error=True )
if error:
message = '%s ' % str( error )
return message
@@ -279,7 +279,7 @@
if rd_key in [ 'root_key', 'description' ]:
continue
for rd_tup in rd_tups:
- rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
if rd_toolshed == toolshed_base_url and \
rd_name == repository.name and \
rd_owner == repository.user.username and \
@@ -370,7 +370,8 @@
for key_rd_dict in key_rd_dicts:
key = key_rd_dict.keys()[ 0 ]
repository_dependency = key_rd_dict[ key ]
- rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = \
+ common_util.parse_repository_dependency_tuple( repository_dependency )
if suc.tool_shed_is_this_tool_shed( rd_toolshed ):
repository = suc.get_repository_by_name_and_owner( trans.app, rd_name, rd_owner )
if repository:
@@ -457,7 +458,7 @@
def handle_key_rd_dicts_for_repository( trans, current_repository_key, repository_key_rd_dicts, key_rd_dicts_to_be_processed, handled_key_rd_dicts, circular_repository_dependencies ):
key_rd_dict = repository_key_rd_dicts.pop( 0 )
repository_dependency = key_rd_dict[ current_repository_key ]
- toolshed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
if suc.tool_shed_is_this_tool_shed( toolshed ):
required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
required_repository_metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
@@ -686,11 +687,11 @@
clean_key_rd_dicts = []
key = key_rd_dicts[ 0 ].keys()[ 0 ]
repository_tup = key.split( container_util.STRSEP )
- rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( repository_tup )
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = common_util.parse_repository_dependency_tuple( repository_tup )
for key_rd_dict in key_rd_dicts:
k = key_rd_dict.keys()[ 0 ]
repository_dependency = key_rd_dict[ k ]
- toolshed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
if rd_toolshed == toolshed and rd_name == name and rd_owner == owner:
log.debug( "Removing repository dependency for repository %s owned by %s since it refers to a revision within itself." % ( name, owner ) )
else:
@@ -700,7 +701,7 @@
return clean_key_rd_dicts
def get_repository_dependency_as_key( repository_dependency ):
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( repository_dependency )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repository_dependency )
return container_util.generate_repository_dependencies_key_for_repository( tool_shed, name, owner, changeset_revision, str( prior_installation_required ) )
def get_repository_dependency_by_repository_id( trans, decoded_repository_id ):
diff -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 -r 89813e684db6ba8582aabc7cd045894d2021c872 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -237,8 +237,8 @@
def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url, metadata_dict,
status, current_changeset_revision=None, owner='', dist_to_shed=False ):
"""
- Update a tool shed repository record in the Galaxy database with the new information received. If a record defined by the received tool shed, repository name
- and owner does not exists, create a new record with the received information.
+ Update a tool shed repository record in the Galaxy database with the new information received. If a record defined by the received tool shed,
+ repository name and owner does not exist, create a new record with the received information.
"""
# The received value for dist_to_shed will be True if the InstallManager is installing a repository that contains tools or datatypes that used
# to be in the Galaxy distribution, but have been moved to the main Galaxy tool shed.
@@ -312,7 +312,7 @@
def generate_clone_url_from_repo_info_tup( repo_info_tup ):
"""Generate teh URL for cloning a repositoyr given a tuple of toolshed, name, owner, changeset_revision."""
# Example tuple: ['http://localhost:9009', 'blast_datatypes', 'test', '461a4216e8ab', False]
- toolshed, name, owner, changeset_revision, prior_installation_required = parse_repository_dependency_tuple( repo_info_tup )
+ toolshed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( repo_info_tup )
# Don't include the changeset_revision in clone urls.
return url_join( toolshed, 'repos', owner, name )
@@ -947,7 +947,7 @@
This method is used in the Tool Shed when exporting a repository and it's dependencies, and in Galaxy when a repository and it's dependencies
are being installed. Inspect the received repository_dependencies and determine if the encoded id of each required repository is in the received
tsr_ids. If so, then determine whether that required repository should be imported / installed prior to it's dependent repository. Return a list
- of encoded repository ids, each of which is contained in the received list of tsr_ids, and whose associated repositories must be impoerted / installed
+ of encoded repository ids, each of which is contained in the received list of tsr_ids, and whose associated repositories must be imported / installed
prior to the dependent repository associated with the received repository_dependencies.
"""
prior_tsr_ids = []
@@ -956,7 +956,7 @@
if key in [ 'description', 'root_key' ]:
continue
for rd_tup in rd_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = parse_repository_dependency_tuple( rd_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
if asbool( prior_installation_required ):
if trans.webapp.name == 'galaxy':
repository = get_repository_for_dependency_relationship( trans.app, tool_shed, name, owner, changeset_revision )
@@ -983,7 +983,7 @@
.order_by( trans.model.RepositoryMetadata.table.c.update_time.desc() ) \
.all()
if len( all_metadata_records ) > 1:
- # Delete all recrds older than the last one updated.
+ # Delete all records older than the last one updated.
for repository_metadata in all_metadata_records[ 1: ]:
trans.sa_session.delete( repository_metadata )
trans.sa_session.flush()
@@ -1308,28 +1308,6 @@
folder_contents.append( node )
return folder_contents
-def parse_repository_dependency_tuple( repository_dependency_tuple, contains_error=False ):
- if contains_error:
- if len( repository_dependency_tuple ) == 5:
- # Metadata should have been reset on the repository containing this repository_dependency definition.
- tool_shed, name, owner, changeset_revision, error = repository_dependency_tuple
- # Default prior_installation_required to False.
- prior_installation_required = False
- elif len( repository_dependency_tuple ) == 6:
- toolshed, name, owner, changeset_revision, prior_installation_required, error = repository_dependency_tuple
- prior_installation_required = str( prior_installation_required )
- return toolshed, name, owner, changeset_revision, prior_installation_required, error
- else:
- if len( repository_dependency_tuple ) == 4:
- # Metadata should have been reset on the repository containing this repository_dependency definition.
- tool_shed, name, owner, changeset_revision = repository_dependency_tuple
- # Default prior_installation_required to False.
- prior_installation_required = False
- elif len( repository_dependency_tuple ) == 5:
- tool_shed, name, owner, changeset_revision, prior_installation_required = repository_dependency_tuple
- prior_installation_required = str( prior_installation_required )
- return tool_shed, name, owner, changeset_revision, prior_installation_required
-
def pretty_print( dict=None ):
if dict:
return json.to_json_string( dict, sort_keys=True, indent=4 * ' ' )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Another instance of the API referencing the wrong attribute.
by commits-noreply@bitbucket.org 26 Aug '13
by commits-noreply@bitbucket.org 26 Aug '13
26 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e97f613a4948/
Changeset: e97f613a4948
User: Dave Bouvier
Date: 2013-08-26 15:07:54
Summary: Another instance of the API referencing the wrong attribute.
Affected #: 1 file
diff -r a86290c120d3aafb321f73d5ff57e777e8946a41 -r e97f613a4948dd641e66019e0c5eb72a8660f2e2 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -3440,7 +3440,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Fix Sweepster bug that prevented changing parameter tree after running sweeps.
by commits-noreply@bitbucket.org 24 Aug '13
by commits-noreply@bitbucket.org 24 Aug '13
24 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a86290c120d3/
Changeset: a86290c120d3
User: jgoecks
Date: 2013-08-24 16:31:23
Summary: Fix Sweepster bug that prevented changing parameter tree after running sweeps.
Affected #: 1 file
diff -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c -r a86290c120d3aafb321f73d5ff57e777e8946a41 static/scripts/viz/sweepster.js
--- a/static/scripts/viz/sweepster.js
+++ b/static/scripts/viz/sweepster.js
@@ -920,11 +920,16 @@
// Set inputs and run tool.
tool.set_input_values(pm_track.get('settings').get('values'));
$.when(tool.rerun(dataset, regions)).then(function(output) {
- // HACK: output is an HDA with track config attribute. To create a track, rearrange
- // track config to point to HDA.
+ // HACKish: output is an HDA with track config attribute. To create a track
+ // that works correctly with Backbone relational, it is necessary to
+ // use a modified version of the track config.
var dataset = output.first(),
track_config = dataset.get('track_config');
+ // Set dataset to be the tool's output.
track_config.dataset = dataset;
+ // Set tool to null so that it is not unpacked; unpacking it messes with
+ // the tool parameters and parameter tree.
+ track_config.tool = null;
// Create and add track for output dataset.
var track_obj = tracks.object_from_template(track_config, self, null);
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Tools and visual analytics: (a) add tool parameter types to client-side code and automatically unpack tools; (b) update Sweepster to work with recent tool parameter enhancements; and (c) fix additional warts.
by commits-noreply@bitbucket.org 24 Aug '13
by commits-noreply@bitbucket.org 24 Aug '13
24 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5b4c4cf9bc96/
Changeset: 5b4c4cf9bc96
User: jgoecks
Date: 2013-08-23 22:09:22
Summary: Tools and visual analytics: (a) add tool parameter types to client-side code and automatically unpack tools; (b) update Sweepster to work with recent tool parameter enhancements; and (c) fix additional warts.
Affected #: 6 files
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -236,7 +236,7 @@
ValueError: An integer is required
"""
- dict_colletion_visible_keys = ToolParameter.dict_collection_visible_keys + ( 'min', 'max' )
+ dict_collection_visible_keys = ToolParameter.dict_collection_visible_keys + ( 'min', 'max' )
def __init__( self, tool, elem ):
TextToolParameter.__init__( self, tool, elem )
@@ -251,12 +251,12 @@
self.max = elem.get( 'max' )
if self.min:
try:
- int( self.min )
+ self.min = int( self.min )
except:
raise ValueError( "An integer is required" )
if self.max:
try:
- int( self.max )
+ self.max = int( self.max )
except:
raise ValueError( "An integer is required" )
if self.min and self.max:
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -37,7 +37,7 @@
from galaxy.datatypes.interval import ChromatinInteractions
from galaxy.datatypes.data import Text
-from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation,HistoryDatasetAssociation
+from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation
from galaxy.datatypes.display_applications import util as da_util
from galaxy.datatypes.metadata import FileParameter
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -873,8 +873,8 @@
# Add tool, dataset attributes to config based on id.
tool = trans.app.toolbox.get_tool( viz_config[ 'tool_id' ] )
- viz_config[ 'tool' ] = tool.dictify( trans, for_display=True )
- viz_config[ 'dataset' ] = dataset.dictify()
+ viz_config[ 'tool' ] = tool.dictify( trans, io_details=True )
+ viz_config[ 'dataset' ] = trans.security.encode_dict_ids( dataset.dictify() )
return trans.fill_template_mako( "visualization/sweepster.mako", config=viz_config )
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c static/scripts/mvc/tools.js
--- a/static/scripts/mvc/tools.js
+++ b/static/scripts/mvc/tools.js
@@ -1,16 +1,12 @@
/**
* Model, view, and controller objects for Galaxy tools and tool panel.
- *
- * Models have no references to views, instead using events to indicate state
- * changes; this is advantageous because multiple views can use the same object
- * and models can be used without views.
*/
define( ["libs/underscore", "viz/trackster/util", "mvc/data", "libs/backbone/backbone-relational" ],
function(_, util, data) {
/**
- * Mixin to enable model to track visibility.
+ * Mixin for tracking model visibility.
*/
var VisibilityMixin = {
hidden: false,
@@ -41,6 +37,13 @@
html: null,
num_samples: 5
},
+
+ subModelTypes: {
+ 'integer': 'IntegerToolParameter',
+ 'float': 'FloatToolParameter',
+ 'data': 'DataToolParameter',
+ 'select': 'SelectToolParameter'
+ },
initialize: function() {
this.attributes.html = unescape(this.attributes.html);
@@ -49,69 +52,57 @@
copy: function() {
return new ToolParameter(this.toJSON());
},
-
+
+ set_value: function(value) {
+ this.set('value', value || '');
+ }
+});
+
+// In order to resolve subModelTypes for tool parameters, use a custom scope here rather
+// than polluting the global scope.
+var tools_scope = {};
+Backbone.Relational.store.addModelScope(tools_scope);
+
+/**
+ * A data tool parameter.
+ */
+var DataToolParameter = tools_scope.DataToolParameter = ToolParameter.extend({});
+
+/**
+ * An integer tool parameter.
+ */
+var IntegerToolParameter = tools_scope.IntegerToolParameter = ToolParameter.extend({
+ set_value: function(value) {
+ this.set('value', parseInt(value, 10));
+ },
+
/**
* Returns samples from a tool input.
*/
get_samples: function() {
- var type = this.get('type'),
- samples = null;
- if (type === 'number') {
- samples = d3.scale.linear()
+ return d3.scale.linear()
.domain([this.get('min'), this.get('max')])
.ticks(this.get('num_samples'));
- }
- else if (type === 'select') {
- samples = _.map(this.get('options'), function(option) {
- return option[0];
- });
- }
-
- return samples;
- },
-
- set_value: function(value) {
- this.set('value', value || '');
- }
-},
-{
- /**
- * Dictionary mapping parameter type strings to parameter classes.
- */
- TYPE_DICT: {
- 'number': IntegerToolParameter
- },
-
- /**
- * Create new parameter from a dictionary.
- */
- create: function(options) {
- var param_class = ToolParameter.TYPE_DICT[options.type] || ToolParameter;
- return new param_class(options);
}
});
-/**
- * A number tool parameter.
+var FloatToolParameter = tools_scope.FloatToolParameter = IntegerToolParameter.extend({
+ set_value: function(value) {
+ this.set('value', parseFloat(value));
+ }
+});
+
+/**
+ * A select tool parameter.
*/
-var IntegerToolParameter = ToolParameter.extend({
- defaults: _.extend({}, ToolParameter.prototype.defaults, {
- min: null,
- max: null
- }),
-
- initialize: function() {
- ToolParameter.prototype.initialize.call(this);
- if (this.attributes.min) {
- this.attributes.min = parseInt(this.attributes.min, 10);
- }
- if (this.attributes.max) {
- this.attributes.max = parseInt(this.attributes.max, 10);
- }
- },
-
- set_value: function(value) {
- this.set('value', parseInt(value, 10))
+var SelectToolParameter = tools_scope.SelectToolParameter = ToolParameter.extend({
+ /**
+ * Returns tool options.
+ */
+ get_samples: function() {
+ return _.map(this.get('options'), function(option) {
+ return option[0];
+ });
}
});
@@ -125,21 +116,32 @@
name: null,
description: null,
target: null,
- inputs: []
+ inputs: [],
+ outputs: []
},
- initialize: function(options) {
- // Unpack parameters manually so that different parameter types can be created.
- this.attributes.inputs = new Backbone.Collection( _.map(options.inputs, function(param_dict) {
- // FIXME: it is still useful to be able to save/restore tool state?
- // Update parameter value from tool state dict.
- //param_dict.value = tool_state_dict[ param_dict[name] ] || param_dict.value;
- return ToolParameter.create(param_dict);
- }));
+ relations: [
+ {
+ type: Backbone.HasMany,
+ key: 'inputs',
+ relatedModel: ToolParameter
+ }
+ ],
+
+ urlRoot: galaxy_config.root + 'api/tools',
+
+ /**
+ * Removes inputs of a particular type; this is useful because not all inputs can be handled by
+ * client and server yet.
+ */
+ remove_inputs: function(types) {
+ var tool = this,
+ incompatible_inputs = tool.get('inputs').filter( function(input) {
+ return ( types.indexOf( input.get('type') ) !== -1);
+ });
+ tool.get('inputs').remove(incompatible_inputs);
},
- urlRoot: galaxy_config.root + 'api/tools',
-
/**
* Returns object copy, optionally including only inputs that can be sampled.
*/
@@ -735,6 +737,7 @@
return {
ToolParameter: ToolParameter,
IntegerToolParameter: IntegerToolParameter,
+ SelectToolParameter: SelectToolParameter,
Tool: Tool,
ToolCollection: ToolCollection,
ToolSearch: ToolSearch,
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c static/scripts/viz/sweepster.js
--- a/static/scripts/viz/sweepster.js
+++ b/static/scripts/viz/sweepster.js
@@ -30,8 +30,6 @@
// Set up tool parameters to work with tree.
var self = this;
this.get('tool').get('inputs').each(function(input) {
- if (!input.get_samples()) { return; }
-
// Listen for changes to input's attributes.
input.on('change:min change:max change:num_samples', function(input) {
if (input.get('in_ptree')) {
@@ -270,8 +268,8 @@
if (options.track) {
// FIXME: find a better way to deal with needed URLs:
var track_config = _.extend({
- data_url: galaxy_paths.get('raw_data_url'),
- converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
+ data_url: galaxy_config.root + 'dummy1',
+ converted_datasets_state_url: galaxy_config.root + 'dummy2'
}, options.track);
this.set('track', tracks.object_from_template(track_config, {}, null));
}
@@ -340,8 +338,10 @@
],
initialize: function(options) {
- var tool_with_samplable_inputs = this.get('tool').copy(true);
+ var tool_with_samplable_inputs = this.get('tool');
this.set('tool_with_samplable_inputs', tool_with_samplable_inputs);
+ // Remove complex parameters for now.
+ tool_with_samplable_inputs.remove_inputs( [ 'data', 'hidden_data', 'conditional' ] );
this.set('parameter_tree', new ToolParameterTree({
tool: tool_with_samplable_inputs,
@@ -425,7 +425,7 @@
// Render tile placeholders.
this.model.get('regions').each(function() {
self.$el.append($('<td/>').addClass('tile').html(
- $('<img/>').attr('src', galaxy_paths.get('image_path') + '/loading_large_white_bg.gif')
+ $('<img/>').attr('src', galaxy_config.root + 'images/loading_large_white_bg.gif')
));
});
@@ -497,10 +497,10 @@
});
// Add row for parameter sweep inputs.
- if (type === 'number') {
+ if (input instanceof tools.IntegerToolParameter) {
sweep_inputs_row = $(_.template(this.number_input_template, this.model.toJSON()));
}
- else if (type === 'select') {
+ else if (input instanceof tools.SelectToolParameter) {
var options = _.map(this.$el.find('select option'), function(option) {
return $(option).val();
}),
@@ -918,19 +918,18 @@
_.each(new_tracks, function(pm_track, index) {
setTimeout(function() {
// Set inputs and run tool.
- // console.log('running with settings', pm_track.get('settings'));
tool.set_input_values(pm_track.get('settings').get('values'));
$.when(tool.rerun(dataset, regions)).then(function(output) {
+ // HACK: output is an HDA with track config attribute. To create a track, rearrange
+ // track config to point to HDA.
+ var dataset = output.first(),
+ track_config = dataset.get('track_config');
+ track_config.dataset = dataset;
+
// Create and add track for output dataset.
- var track_config = _.extend({
- data_url: galaxy_paths.get('raw_data_url'),
- converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
- }, output.first().get('track_config')),
- track_obj = tracks.object_from_template(track_config, self, null);
-
- // Track uses raw data.
- track_obj.data_manager.set('data_type', 'raw_data');
-
+ var track_obj = tracks.object_from_template(track_config, self, null);
+ track_obj.init_for_tool_data();
+
// Set track block colors.
track_obj.prefs.block_color = self.block_color;
track_obj.prefs.reverse_strand_color = self.reverse_strand_color;
diff -r ab74f2d8017306fb909778aafcd51b78b24e3e56 -r 5b4c4cf9bc9619d51d7f2471d64896dcdd93707c static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -919,7 +919,7 @@
{ key: 'c_color', label: 'C Color', type: 'color', default_value: "#00FF00" },
{ key: 'g_color', label: 'G Color', type: 'color', default_value: "#0000FF" },
{ key: 't_color', label: 'T Color', type: 'color', default_value: "#FF00FF" },
- { key: 'n_color', label: 'N Color', type: 'color', default_value: "#AAAAAA" },
+ { key: 'n_color', label: 'N Color', type: 'color', default_value: "#AAAAAA" }
],
saved_values: obj_dict.prefs,
onchange: function() {
@@ -1393,7 +1393,7 @@
//
// Redraw without requesting more data immediately.
- view.request_redraw({ data_fetch: false })
+ view.request_redraw({ data_fetch: false });
// Set up timeout to redraw with more data when moving stops.
if (this.redraw_on_move_fn) {
@@ -1637,15 +1637,11 @@
],
initialize: function(options) {
- // HACK: remove data and group tool inputs because Trackster
- // does not work with them right now.
- var tool = this.get('tool'),
- incompatible_inputs = tool.get('inputs').filter( function(input) {
- return ( [ 'data', 'hidden_data', 'group'].indexOf( input.get('type') ) !== -1);
- });
- tool.get('inputs').remove(incompatible_inputs);
+ // HACK: remove some inputs because Trackster does yet not work with them.
+ this.get('tool').remove_inputs( [ 'data', 'hidden_data', 'conditional' ] );
+
+ // FIXME: need to restore tool values/visibility.
}
-
});
/**
@@ -2320,8 +2316,12 @@
// Attribute init.
//
- // Only create dataset if it is defined.
- this.dataset = (obj_dict.dataset ? new data.Dataset(obj_dict.dataset) : null);
+ // Set or create dataset.
+ this.dataset = null;
+ if (obj_dict.dataset) {
+ // Dataset can be a Backbone model or a dict that can be used to create a model.
+ this.dataset = (obj_dict.dataset instanceof Backbone.Model ? obj_dict.dataset : new data.Dataset(obj_dict.dataset) );
+ }
this.dataset_check_type = 'converted_datasets_state';
this.data_url_extra_params = {};
this.data_query_wait = ('data_query_wait' in obj_dict ? obj_dict.data_query_wait : DEFAULT_DATA_QUERY_WAIT);
@@ -3452,9 +3452,13 @@
this.data_query_wait = 1000;
this.dataset_check_type = 'state';
+ // FIXME: this is optional and is disabled for now because it creates
+ // additional converter jobs without a clear benefit because indexing
+ // such a small dataset provides little benefit.
//
// Set up one-time, post-draw to clear tool execution settings.
//
+ /*
this.normal_postdraw_actions = this.postdraw_actions;
this.postdraw_actions = function(tiles, width, w_scale, clear_after) {
var self = this;
@@ -3484,6 +3488,7 @@
// Reset post-draw actions function.
self.postdraw_actions = self.normal_postdraw_actions;
};
+ */
}
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Update tool shed API dictify methods to reference the correct attribute.
by commits-noreply@bitbucket.org 24 Aug '13
by commits-noreply@bitbucket.org 24 Aug '13
24 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ab74f2d80173/
Changeset: ab74f2d80173
User: Dave Bouvier
Date: 2013-08-23 20:55:56
Summary: Update tool shed API dictify methods to reference the correct attribute.
Affected #: 1 file
diff -r e2bca7e8fe7e0f3022c1e1afb4a6eed54dec2bcf -r ab74f2d8017306fb909778aafcd51b78b24e3e56 lib/galaxy/webapps/tool_shed/model/__init__.py
--- a/lib/galaxy/webapps/tool_shed/model/__init__.py
+++ b/lib/galaxy/webapps/tool_shed/model/__init__.py
@@ -180,7 +180,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
@@ -291,7 +291,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
@@ -322,7 +322,7 @@
value_mapper = {}
rval = {}
try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
for key in visible_keys:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Add version command information to Cuff* tools.
by commits-noreply@bitbucket.org 23 Aug '13
by commits-noreply@bitbucket.org 23 Aug '13
23 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e2bca7e8fe7e/
Changeset: e2bca7e8fe7e
User: jgoecks
Date: 2013-08-23 16:49:06
Summary: Add version command information to Cuff* tools.
Affected #: 3 files
diff -r fa8c4978733072137f708190e65d46c6cb616b0b -r e2bca7e8fe7e0f3022c1e1afb4a6eed54dec2bcf tools/ngs_rna/cuffcompare_wrapper.xml
--- a/tools/ngs_rna/cuffcompare_wrapper.xml
+++ b/tools/ngs_rna/cuffcompare_wrapper.xml
@@ -4,6 +4,7 @@
<requirements><requirement type="package">cufflinks</requirement></requirements>
+ <version_command>cuffcompare 2>&1 | head -n 1</version_command><command interpreter="python">
cuffcompare_wrapper.py
diff -r fa8c4978733072137f708190e65d46c6cb616b0b -r e2bca7e8fe7e0f3022c1e1afb4a6eed54dec2bcf tools/ngs_rna/cuffdiff_wrapper.xml
--- a/tools/ngs_rna/cuffdiff_wrapper.xml
+++ b/tools/ngs_rna/cuffdiff_wrapper.xml
@@ -4,6 +4,7 @@
<requirements><requirement type="package">cufflinks</requirement></requirements>
+ <version_command>cuffdiff 2>&1 | head -n 1</version_command><command>
cuffdiff
--FDR=$fdr
diff -r fa8c4978733072137f708190e65d46c6cb616b0b -r e2bca7e8fe7e0f3022c1e1afb4a6eed54dec2bcf tools/ngs_rna/cufflinks_wrapper.xml
--- a/tools/ngs_rna/cufflinks_wrapper.xml
+++ b/tools/ngs_rna/cufflinks_wrapper.xml
@@ -4,6 +4,7 @@
<requirements><requirement type="package">cufflinks</requirement></requirements>
+ <version_command>cufflinks 2>&1 | head -n 1</version_command><command interpreter="python">
cufflinks_wrapper.py
--input=$input
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/fa8c49787330/
Changeset: fa8c49787330
User: dan
Date: 2013-08-23 15:07:28
Summary: Fix for ToolParameterValueWrapper.get_display_text() due to inconsistent behavior between Python2.7 and lower for empty strings.
expected quoted empty string:
$ python2.7
Python 2.7.5 (default, Aug 1 2013, 00:59:24)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pipes
>>> print pipes.quote('')
''
>>> repr( pipes.quote('') )
'"\'\'"'
>>>
python < 2.7:
$ python2.6
Python 2.6.1 (r261:67515, Aug 2 2010, 20:10:18)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pipes
>>> print pipes.quote('')
>>> repr( pipes.quote('') )
"''"
>>>
Affected #: 1 file
diff -r c0073a8c820c43b419dfdcc8d88ba157e214f610 -r fa8c4978733072137f708190e65d46c6cb616b0b lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -3284,7 +3284,14 @@
def __nonzero__( self ):
return bool( self.value )
def get_display_text( self, quote=True ):
- return pipes.quote( self.input.value_to_display_text( self.value, self.input.tool.app ) )
+ """
+ Returns a string containing the value that would be displayed to the user in the tool interface.
+ When quote is True (default), the string is escaped for e.g. command-line usage.
+ """
+ rval = self.input.value_to_display_text( self.value, self.input.tool.app ) or ''
+ if quote:
+ return pipes.quote( rval ) or "''" #pipes.quote in Python < 2.7 returns an empty string instead of the expected quoted empty string
+ return rval
class RawObjectWrapper( ToolParameterValueWrapper ):
"""
https://bitbucket.org/galaxy/galaxy-central/commits/de04c251c6ca/
Changeset: de04c251c6ca
Branch: stable
User: dan
Date: 2013-08-23 15:07:28
Summary: Fix for ToolParameterValueWrapper.get_display_text() due to inconsistent behavior between Python2.7 and lower for empty strings.
expected quoted empty string:
$ python2.7
Python 2.7.5 (default, Aug 1 2013, 00:59:24)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pipes
>>> print pipes.quote('')
''
>>> repr( pipes.quote('') )
'"\'\'"'
>>>
python < 2.7:
$ python2.6
Python 2.6.1 (r261:67515, Aug 2 2010, 20:10:18)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pipes
>>> print pipes.quote('')
>>> repr( pipes.quote('') )
"''"
>>>
Affected #: 1 file
diff -r 29ab5a6d75a778cd4989adf881c47916607b9acb -r de04c251c6cae5760fd13c83030a6aab78ae0c4e lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -3258,7 +3258,14 @@
def __nonzero__( self ):
return bool( self.value )
def get_display_text( self, quote=True ):
- return pipes.quote( self.input.value_to_display_text( self.value, self.input.tool.app ) )
+ """
+ Returns a string containing the value that would be displayed to the user in the tool interface.
+ When quote is True (default), the string is escaped for e.g. command-line usage.
+ """
+ rval = self.input.value_to_display_text( self.value, self.input.tool.app ) or ''
+ if quote:
+ return pipes.quote( rval ) or "''" #pipes.quote in Python < 2.7 returns an empty string instead of the expected quoted empty string
+ return rval
class RawObjectWrapper( ToolParameterValueWrapper ):
"""
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: Fixes for 8ed926e: (1) enable labels to be displayed outside of sections in tool panel and(b) revert class for label divs. Pack script.
by commits-noreply@bitbucket.org 23 Aug '13
by commits-noreply@bitbucket.org 23 Aug '13
23 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c0073a8c820c/
Changeset: c0073a8c820c
User: jgoecks
Date: 2013-08-23 00:13:57
Summary: Fixes for 8ed926e: (1) enable labels to be displayed outside of sections in tool panel and(b) revert class for label divs. Pack script.
Affected #: 3 files
diff -r 24f4f507fdecf214e9090f215fe309249a29252d -r c0073a8c820c43b419dfdcc8d88ba157e214f610 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -93,6 +93,15 @@
class ToolNotFoundException( Exception ):
pass
+def dictify_helper( obj, kwargs ):
+ """ Helper function that provides the appropriate kwargs to dictify an object. """
+
+ # Label.dictify cannot have kwargs.
+ if isinstance( obj, ToolSectionLabel ):
+ kwargs = {}
+
+ return obj.dictify( **kwargs )
+
class ToolBox( object, DictifiableMixin ):
"""Container for a collection of tools"""
@@ -722,8 +731,12 @@
# Produce panel.
rval = []
+ kwargs = dict(
+ trans = trans,
+ link_details = True
+ )
for elt in panel_elts:
- rval.append( elt.dictify( trans, link_details=True ) )
+ rval.append( dictify_helper( elt, kwargs ) )
else:
tools = []
for id, tool in self.tools_by_id.items():
@@ -816,11 +829,12 @@
section_dict = super( ToolSection, self ).dictify()
section_elts = []
- for key, val in self.elems.items():
- if isinstance( val, ToolSectionLabel ):
- section_elts.append( val.dictify() )
- else:
- section_elts.append( val.dictify( trans, link_details=link_details ) )
+ kwargs = dict(
+ trans = trans,
+ link_details = link_details
+ )
+ for elt in self.elems.values():
+ section_elts.append( dictify_helper( elt, kwargs ) )
section_dict[ 'elems' ] = section_elts
return section_dict
diff -r 24f4f507fdecf214e9090f215fe309249a29252d -r c0073a8c820c43b419dfdcc8d88ba157e214f610 static/scripts/mvc/tools.js
--- a/static/scripts/mvc/tools.js
+++ b/static/scripts/mvc/tools.js
@@ -499,7 +499,7 @@
*/
var ToolSectionLabelView = BaseView.extend({
tagName: 'div',
- className: 'ToolSectionLabel',
+ className: 'toolPanelLabel',
render: function() {
this.$el.append( $("<span/>").text(this.model.attributes.text) );
diff -r 24f4f507fdecf214e9090f215fe309249a29252d -r c0073a8c820c43b419dfdcc8d88ba157e214f610 static/scripts/packed/mvc/tools.js
--- a/static/scripts/packed/mvc/tools.js
+++ b/static/scripts/packed/mvc/tools.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/backbone-relational"],function(t,a,u){var f={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},get_samples:function(){var w=this.get("type"),v=null;if(w==="number"){v=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(w==="select"){v=t.map(this.get("options"),function(x){return x[0]})}}return v},set_value:function(v){this.set("value",v||"")}},{TYPE_DICT:{number:d},create:function(v){var w=e.TYPE_DICT[v.type]||e;return new w(v)}});var d=e.extend({defaults:t.extend({},e.prototype.defaults,{min:null,max:null}),initialize:function(){e.prototype.initialize.call(this);if(this.attributes.min){this.attributes.min=parseInt(this.attributes.min,10)}if(this.attributes.max){this.attributes.max=parseInt(this.attributes.max,10)}},set_value:function(v){this.set("value",parseInt(v,10))}});var h=Backbone.RelationalModel.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[]},initialize:function(v){this.attributes.inputs=new Backbone.Collection(t.map(v.inputs,function(w){return e.create(w)}))},urlRoot:galaxy_config.root+"api/tools",copy:function(w){var x=new h(this.toJSON());if(w){var v=new Backbone.Collection();x.get("inputs").each(function(y){if(y.get_samples()){v.push(y)}});x.set("inputs",v)}return x},apply_search_results:function(v){(t.indexOf(v,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(v,w){this.get("inputs").find(function(x){return x.get("name")===v}).set("value",w)},set_input_values:function(w){var v=this;t.each(t.keys(w),function(x){v.set_input_value(x,w[x])})},run:function(){return this._run()},rerun:function(w,v){return this._run({action:"rerun",target_dataset_id:w.id,regions:v})},get_inputs_dict:function(){var v={};this.get("inputs").each(function(w){v[w.get("name")]=w.get("value")});return v},_run:function(x){var y=t.extend({tool_id:this.id,inputs:this.get_inputs_dict()},x);var w=$.Deferred(),v=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(y),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(z){return z!=="pending"}});$.when(v.go()).then(function(z){w.resolve(new u.DatasetCollection().reset(z))});return w}});t.extend(h.prototype,f);var n=Backbone.View.extend({});var k=Backbone.Collection.extend({model:h});var r=Backbone.Model.extend(f);var i=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){t.each(this.attributes.elems,function(v){v.show()});this.show();this.set("open",false)},apply_search_results:function(w){var x=true,v;t.each(this.attributes.elems,function(y){if(y instanceof r){v=y;v.hide()}else{if(y instanceof h){if(y.apply_search_results(w)){x=false;if(v){v.show()}}}}});if(x){this.hide()}else{this.show();this.set("open",true)}}});t.extend(i.prototype,f);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var x=this.attributes.query;if(x.length<this.attributes.min_chars_for_search){this.set("results",null);return}var w=x+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var v=this;this.timer=setTimeout(function(){$.get(v.attributes.search_url,{query:w},function(y){v.set("results",y);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});t.extend(c.prototype,f);var l=Backbone.Model.extend({initialize:function(v){this.attributes.tool_search=v.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=v.tools;this.attributes.layout=new Backbone.Collection(this.parse(v.layout))},parse:function(w){var v=this,x=function(A){var z=A.model_class;if(z.indexOf("Tool")===z.length-4){return v.attributes.tools.get(A.id)}else{if(z==="ToolSection"){var y=t.map(A.elems,x);A.elems=y;return new i(A)}else{if(z==="ToolSectionLabel"){return new r(A)}}}};return t.map(w,x)},clear_search_results:function(){this.get("layout").each(function(v){if(v instanceof i){v.clear_search_results()}else{v.show()}})},apply_search_results:function(){var w=this.get("tool_search").get("results");if(w===null){this.clear_search_results();return}var v=null;this.get("layout").each(function(x){if(x instanceof r){v=x;v.hide()}else{if(x instanceof h){if(x.apply_search_results(w)){if(v){v.show()}}}else{v=null;x.apply_search_results(w)}}})}});var p=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var j=p.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var b=p.extend({tagName:"div",className:"ToolSectionLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var o=p.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){p.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var v=this.$el.find(".toolSectionBody");t.each(this.model.attributes.elems,function(w){if(w instanceof h){var x=new j({model:w,className:"toolTitle"});x.render();v.append(x.$el)}else{if(w instanceof r){var y=new b({model:w});y.render();v.append(y.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var m=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(v){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===v.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var s=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var v=this;var w=new m({model:this.model.get("tool_search")});w.render();v.$el.append(w.$el);this.model.get("layout").each(function(y){if(y instanceof i){var x=new o({model:y});x.render();v.$el.append(x.$el)}else{if(y instanceof h){var z=new j({model:y,className:"toolTitleNoSection"});z.render();v.$el.append(z.$el)}else{if(y instanceof r){var A=new b({model:y});A.render();v.$el.append(A.$el)}}}});v.$el.find("a.tool-link").click(function(z){var y=$(this).attr("class").split(/\s+/)[0],x=v.model.get("tools").get(y);v.trigger("tool_link_click",z,x)});return this},handle_search_results:function(){var v=this.model.get("tool_search").get("results");if(v&&v.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var q=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var g=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new s({collection:this.collection});this.tool_form_view=new q()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var v=this;this.tool_panel_view.on("tool_link_click",function(x,w){x.preventDefault();v.show_tool(w)})},show_tool:function(w){var v=this;w.fetch().done(function(){v.tool_form_view.model=w;v.tool_form_view.render();v.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,Tool:h,ToolCollection:k,ToolSearch:c,ToolPanel:l,ToolPanelView:s,ToolFormView:q}});
\ No newline at end of file
+define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/backbone-relational"],function(t,a,u){var f={hidden:false,show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}};var e=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new e(this.toJSON())},get_samples:function(){var w=this.get("type"),v=null;if(w==="number"){v=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(w==="select"){v=t.map(this.get("options"),function(x){return x[0]})}}return v},set_value:function(v){this.set("value",v||"")}},{TYPE_DICT:{number:d},create:function(v){var w=e.TYPE_DICT[v.type]||e;return new w(v)}});var d=e.extend({defaults:t.extend({},e.prototype.defaults,{min:null,max:null}),initialize:function(){e.prototype.initialize.call(this);if(this.attributes.min){this.attributes.min=parseInt(this.attributes.min,10)}if(this.attributes.max){this.attributes.max=parseInt(this.attributes.max,10)}},set_value:function(v){this.set("value",parseInt(v,10))}});var h=Backbone.RelationalModel.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[]},initialize:function(v){this.attributes.inputs=new Backbone.Collection(t.map(v.inputs,function(w){return e.create(w)}))},urlRoot:galaxy_config.root+"api/tools",copy:function(w){var x=new h(this.toJSON());if(w){var v=new Backbone.Collection();x.get("inputs").each(function(y){if(y.get_samples()){v.push(y)}});x.set("inputs",v)}return x},apply_search_results:function(v){(t.indexOf(v,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(v,w){this.get("inputs").find(function(x){return x.get("name")===v}).set("value",w)},set_input_values:function(w){var v=this;t.each(t.keys(w),function(x){v.set_input_value(x,w[x])})},run:function(){return this._run()},rerun:function(w,v){return this._run({action:"rerun",target_dataset_id:w.id,regions:v})},get_inputs_dict:function(){var v={};this.get("inputs").each(function(w){v[w.get("name")]=w.get("value")});return v},_run:function(x){var y=t.extend({tool_id:this.id,inputs:this.get_inputs_dict()},x);var w=$.Deferred(),v=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(y),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(z){return z!=="pending"}});$.when(v.go()).then(function(z){w.resolve(new u.DatasetCollection().reset(z))});return w}});t.extend(h.prototype,f);var n=Backbone.View.extend({});var k=Backbone.Collection.extend({model:h});var r=Backbone.Model.extend(f);var i=Backbone.Model.extend({defaults:{elems:[],open:false},clear_search_results:function(){t.each(this.attributes.elems,function(v){v.show()});this.show();this.set("open",false)},apply_search_results:function(w){var x=true,v;t.each(this.attributes.elems,function(y){if(y instanceof r){v=y;v.hide()}else{if(y instanceof h){if(y.apply_search_results(w)){x=false;if(v){v.show()}}}}});if(x){this.hide()}else{this.show();this.set("open",true)}}});t.extend(i.prototype,f);var c=Backbone.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var x=this.attributes.query;if(x.length<this.attributes.min_chars_for_search){this.set("results",null);return}var w=x+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var v=this;this.timer=setTimeout(function(){$.get(v.attributes.search_url,{query:w},function(y){v.set("results",y);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});t.extend(c.prototype,f);var l=Backbone.Model.extend({initialize:function(v){this.attributes.tool_search=v.tool_search;this.attributes.tool_search.on("change:results",this.apply_search_results,this);this.attributes.tools=v.tools;this.attributes.layout=new Backbone.Collection(this.parse(v.layout))},parse:function(w){var v=this,x=function(A){var z=A.model_class;if(z.indexOf("Tool")===z.length-4){return v.attributes.tools.get(A.id)}else{if(z==="ToolSection"){var y=t.map(A.elems,x);A.elems=y;return new i(A)}else{if(z==="ToolSectionLabel"){return new r(A)}}}};return t.map(w,x)},clear_search_results:function(){this.get("layout").each(function(v){if(v instanceof i){v.clear_search_results()}else{v.show()}})},apply_search_results:function(){var w=this.get("tool_search").get("results");if(w===null){this.clear_search_results();return}var v=null;this.get("layout").each(function(x){if(x instanceof r){v=x;v.hide()}else{if(x instanceof h){if(x.apply_search_results(w)){if(v){v.show()}}}else{v=null;x.apply_search_results(w)}}})}});var p=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var j=p.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var b=p.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.text));return this}});var o=p.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){p.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var v=this.$el.find(".toolSectionBody");t.each(this.model.attributes.elems,function(w){if(w instanceof h){var x=new j({model:w,className:"toolTitle"});x.render();v.append(x.$el)}else{if(w instanceof r){var y=new b({model:w});y.render();v.append(y.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var m=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(v){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===v.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var s=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var v=this;var w=new m({model:this.model.get("tool_search")});w.render();v.$el.append(w.$el);this.model.get("layout").each(function(y){if(y instanceof i){var x=new o({model:y});x.render();v.$el.append(x.$el)}else{if(y instanceof h){var z=new j({model:y,className:"toolTitleNoSection"});z.render();v.$el.append(z.$el)}else{if(y instanceof r){var A=new b({model:y});A.render();v.$el.append(A.$el)}}}});v.$el.find("a.tool-link").click(function(z){var y=$(this).attr("class").split(/\s+/)[0],x=v.model.get("tools").get(y);v.trigger("tool_link_click",z,x)});return this},handle_search_results:function(){var v=this.model.get("tool_search").get("results");if(v&&v.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var q=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var g=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new s({collection:this.collection});this.tool_form_view=new q()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var v=this;this.tool_panel_view.on("tool_link_click",function(x,w){x.preventDefault();v.show_tool(w)})},show_tool:function(w){var v=this;w.fetch().done(function(){v.tool_form_view.model=w;v.tool_form_view.render();v.tool_form_view.$el.show();$("#left").width("650px")})}});return{ToolParameter:e,IntegerToolParameter:d,Tool:h,ToolCollection:k,ToolSearch:c,ToolPanel:l,ToolPanelView:s,ToolFormView:q}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Fix for running a tool migration script that specifies one or more repositories with complex tool dependencies.
by commits-noreply@bitbucket.org 23 Aug '13
by commits-noreply@bitbucket.org 23 Aug '13
23 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/24f4f507fdec/
Changeset: 24f4f507fdec
User: Dave Bouvier
Date: 2013-08-22 20:44:56
Summary: Fix for running a tool migration script that specifies one or more repositories with complex tool dependencies.
Affected #: 2 files
diff -r 185232cef732d9b79aad686ca0aa556bb7c63614 -r 24f4f507fdecf214e9090f215fe309249a29252d lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -19,6 +19,7 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import xml_util
+import tool_shed.galaxy_install.tool_dependencies.common_util as cu
import pkg_resources
@@ -1123,6 +1124,7 @@
if not toolshed:
# Default to the current tool shed.
toolshed = str( url_for( '/', qualified=True ) ).rstrip( '/' )
+ cleaned_toolshed = cu.clean_tool_shed_url( toolshed )
name = repository_elem.get( 'name' )
owner = repository_elem.get( 'owner' )
changeset_revision = repository_elem.get( 'changeset_revision' )
@@ -1135,7 +1137,7 @@
# generating metadata for an installed repository. See if we can locate the installed repository via the changeset_revision defined in the
# repository_elem (it may be outdated). If we're successful in locating an installed repository with the attributes defined in the
# repository_elem, we know it is valid.
- repository = suc.get_repository_for_dependency_relationship( app, toolshed, name, owner, changeset_revision )
+ repository = suc.get_repository_for_dependency_relationship( app, cleaned_toolshed, name, owner, changeset_revision )
if repository:
return repository_dependency_tup, is_valid, error_message
else:
@@ -1144,7 +1146,7 @@
if text:
updated_changeset_revisions = util.listify( text )
for updated_changeset_revision in updated_changeset_revisions:
- repository = suc.get_repository_for_dependency_relationship( app, toolshed, name, owner, updated_changeset_revision )
+ repository = suc.get_repository_for_dependency_relationship( app, cleaned_toolshed, name, owner, updated_changeset_revision )
if repository:
return repository_dependency_tup, is_valid, error_message
# We'll currently default to setting the repository dependency definition as invalid if an installed repository cannot be found.
diff -r 185232cef732d9b79aad686ca0aa556bb7c63614 -r 24f4f507fdecf214e9090f215fe309249a29252d 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
@@ -872,8 +872,8 @@
# tool shed that is associated with repository_metadata.
tool_shed_url = get_url_from_tool_shed( app, tool_shed )
url = url_join( tool_shed_url,
- 'repository/next_installable_changeset_revision?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s' % \
- ( url_for( '/', qualified=True ), name, owner, changeset_revision ) )
+ 'repository/next_installable_changeset_revision?name=%s&owner=%s&changeset_revision=%s' % \
+ ( name, owner, changeset_revision ) )
text = common_util.tool_shed_get( app, tool_shed_url, url )
if text:
repository = get_tool_shed_repository_by_shed_name_owner_changeset_revision( app=app,
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: Automatically eliminate tool entries from non-shed-related tool panel configs for tools contained in tool shed repositories that were migrated out of the Galaxy distribution.
by commits-noreply@bitbucket.org 22 Aug '13
by commits-noreply@bitbucket.org 22 Aug '13
22 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/185232cef732/
Changeset: 185232cef732
User: greg
Date: 2013-08-22 16:12:08
Summary: Automatically eliminate tool entries from non-shed-related tool panel configs for tools contained in tool shed repositories that were migrated out of the Galaxy distribution.
Affected #: 5 files
diff -r 097abeb6969e93265135a8d6f3e566b5e913ca8f -r 185232cef732d9b79aad686ca0aa556bb7c63614 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -3,7 +3,9 @@
All of the tools were at some point included in the Galaxy distribution, but are now hosted in the main Galaxy tool shed.
"""
import os
+import shutil
import tempfile
+import threading
from galaxy import util
from galaxy.tools import ToolSection
from galaxy.util.json import from_json_string
@@ -63,7 +65,9 @@
if tool_panel_configs:
# The missing_tool_configs_dict contents are something like:
# {'emboss_antigenic.xml': [('emboss', '5.0.0', 'package', '\nreadme blah blah blah\n')]}
- tool_shed_accessible, missing_tool_configs_dict = common_util.check_for_missing_tools( app, tool_panel_configs, latest_migration_script_number )
+ tool_shed_accessible, missing_tool_configs_dict = common_util.check_for_missing_tools( app,
+ tool_panel_configs,
+ latest_migration_script_number )
else:
# It doesn't matter if the tool shed is accessible since there are no migrated tools defined in the local Galaxy instance, but
# we have to set the value of tool_shed_accessible to True so that the value of migrate_tools.version can be correctly set in
@@ -79,7 +83,9 @@
file_names = ', '.join( self.proprietary_tool_confs )
if missing_tool_configs_dict:
for repository_elem in root:
- self.install_repository( repository_elem, install_dependencies )
+ # Make sure we have a valid repository tag.
+ if self.__is_valid_repository_tag( repository_elem ):
+ self.install_repository( repository_elem, install_dependencies )
else:
message = "\nNo tools associated with migration stage %s are defined in your " % str( latest_migration_script_number )
message += "file%s named %s,\nso no repositories will be installed on disk.\n" % ( plural, file_names )
@@ -89,6 +95,43 @@
message += "Try again later.\n"
print message
+ def filter_and_persist_proprietary_tool_panel_configs( self, tool_configs_to_filter ):
+ """Eliminate all entries in all non-shed-related tool panel configs for all tool config file names in the received tool_configs_to_filter."""
+ for proprietary_tool_conf in self.proprietary_tool_confs:
+ persist_required = False
+ tree, error_message = xml_util.parse_xml( proprietary_tool_conf )
+ if tree:
+ root = tree.getroot()
+ for elem in root:
+ if elem.tag == 'tool':
+ # Tools outside of sections.
+ file_path = elem.get( 'file', None )
+ if file_path:
+ file_name = suc.strip_path( file_path )
+ if file_name in tool_configs_to_filter:
+ root.remove( elem )
+ persist_required = True
+ elif elem.tag == 'section':
+ # Tools contained in a section.
+ for section_elem in elem:
+ if section_elem.tag == 'tool':
+ file_path = section_elem.get( 'file', None )
+ if file_path:
+ file_name = suc.strip_path( file_path )
+
+ if file_name in tool_configs_to_filter:
+ elem.remove( section_elem )
+ persist_required = True
+ if persist_required:
+ fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-fapptpc" )
+ tmp_filename = fh.name
+ fh.close()
+ fh = open( tmp_filename, 'wb' )
+ tree.write( tmp_filename )
+ fh.close()
+ shutil.move( tmp_filename, os.path.abspath( proprietary_tool_conf ) )
+ os.chmod( proprietary_tool_conf, 0644 )
+
def get_guid( self, repository_clone_url, relative_install_dir, tool_config ):
if self.shed_config_dict.get( 'tool_path' ):
relative_install_dir = os.path.join( self.shed_config_dict['tool_path'], relative_install_dir )
@@ -108,9 +151,11 @@
return suc.generate_tool_guid( repository_clone_url, tool )
def get_proprietary_tool_panel_elems( self, latest_tool_migration_script_number ):
- # Parse each config in self.proprietary_tool_confs (the default is tool_conf.xml) and generate a list of Elements that are
- # either ToolSection elements or Tool elements. These will be used to generate new entries in the migrated_tools_conf.xml
- # file for the installed tools.
+ """
+ Parse each config in self.proprietary_tool_confs (the default is tool_conf.xml) and generate a list of Elements that are
+ either ToolSection elements or Tool elements. These will be used to generate new entries in the migrated_tools_conf.xml
+ file for the installed tools.
+ """
tools_xml_file_path = os.path.abspath( os.path.join( 'scripts', 'migrate_tools', '%04d_tools.xml' % latest_tool_migration_script_number ) )
# Parse the XML and load the file attributes for later checking against the integrated elements from self.proprietary_tool_confs.
migrated_tool_configs = []
@@ -183,7 +228,13 @@
return is_displayed, tool_sections
def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies ):
- """Generate the metadata for the installed tool shed repository, among other things."""
+ """
+ Generate the metadata for the installed tool shed repository, among other things. If the installed tool_shed_repository contains tools
+ that are loaded into the Galaxy tool panel, this method will automatically eliminate all entries for each of the tools defined in the
+ received repository_elem from all non-shed-related tool panel configuration files since the entries are automatically added to the reserved
+ migrated_tools_conf.xml file as part of the migration process.
+ """
+ tool_configs_to_filter = []
tool_panel_dict_for_display = odict()
if self.tool_path:
repo_install_dir = os.path.join( self.tool_path, relative_install_dir )
@@ -197,11 +248,29 @@
is_displayed, tool_sections = self.get_containing_tool_sections( tool_config )
if is_displayed:
tool_panel_dict_for_tool_config = tool_util.generate_tool_panel_dict_for_tool_config( guid, tool_config, tool_sections=tool_sections )
+ # The tool-panel_dict has the following structure.
+ # {<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>}]}
for k, v in tool_panel_dict_for_tool_config.items():
tool_panel_dict_for_display[ k ] = v
+ for tool_panel_dict in v:
+ # Keep track of tool config file names associated with entries that have been made to the migrated_tools_conf.xml file so
+ # they can be eliminated from all non-shed-related tool panel configs.
+ tool_config_file = tool_panel_dict.get( 'tool_config', None )
+ if tool_config_file:
+ if tool_config_file not in tool_configs_to_filter:
+ tool_configs_to_filter.append( tool_config_file )
else:
print 'The tool "%s" (%s) has not been enabled because it is not defined in a proprietary tool config (%s).' \
% ( guid, tool_config, ", ".join( self.proprietary_tool_confs or [] ) )
+ if tool_configs_to_filter:
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ self.filter_and_persist_proprietary_tool_panel_configs( tool_configs_to_filter )
+ except Exception, e:
+ log.exception( "Exception attempting to filter and persist non-shed-related tool panel configs:\n%s" % str( e ) )
+ finally:
+ lock.release()
metadata_dict, invalid_file_tups = metadata_util.generate_metadata_for_changeset_revision( app=self.app,
repository=tool_shed_repository,
changeset_revision=tool_shed_repository.changeset_revision,
@@ -384,3 +453,13 @@
# Assume that the repository has been installed if we find a .hg directory.
return True
return False
+
+ def __is_valid_repository_tag( self, elem ):
+ # <repository name="emboss_datatypes" description="Datatypes for Emboss tools" changeset_revision="a89163f31369" />
+ if elem.tag != 'repository':
+ return False
+ if not elem.get( 'name' ):
+ return False
+ if not elem.get( 'changeset_revision' ):
+ return False
+ return True
diff -r 097abeb6969e93265135a8d6f3e566b5e913ca8f -r 185232cef732d9b79aad686ca0aa556bb7c63614 lib/tool_shed/galaxy_install/migrate/check.py
--- a/lib/tool_shed/galaxy_install/migrate/check.py
+++ b/lib/tool_shed/galaxy_install/migrate/check.py
@@ -1,13 +1,17 @@
-import sys, os, logging, subprocess
+import logging
+import os
+import subprocess
+import sys
from galaxy import eggs
-import pkg_resources
-pkg_resources.require( "SQLAlchemy" )
-pkg_resources.require( "decorator" )
-pkg_resources.require( "Tempita " )
-pkg_resources.require( "sqlalchemy-migrate" )
-
-from migrate.versioning import repository, schema
-from sqlalchemy import *
+eggs.require( "decorator" )
+eggs.require( "Tempita" )
+eggs.require( "SQLAlchemy" )
+eggs.require( "sqlalchemy_migrate" )
+from migrate.versioning import repository
+from migrate.versioning import schema
+from sqlalchemy import create_engine
+from sqlalchemy import MetaData
+from sqlalchemy import Table
from galaxy.util.odict import odict
from galaxy.model.orm import dialect_to_egg
from tool_shed.util import common_util
@@ -52,7 +56,9 @@
if tool_panel_configs:
# The missing_tool_configs_dict contents are something like:
# {'emboss_antigenic.xml': [('emboss', '5.0.0', 'package', '\nreadme blah blah blah\n')]}
- tool_shed_accessible, missing_tool_configs_dict = common_util.check_for_missing_tools( app, tool_panel_configs, latest_tool_migration_script_number )
+ tool_shed_accessible, missing_tool_configs_dict = common_util.check_for_missing_tools( app,
+ tool_panel_configs,
+ latest_tool_migration_script_number )
else:
# It doesn't matter if the tool shed is accessible since there are no migrated tools defined in the local Galaxy instance, but
# we have to set the value of tool_shed_accessible to True so that the value of migrate_tools.version can be correctly set in
@@ -136,8 +142,8 @@
msg += "Tool dependencies can be installed after the repositories have been installed as well.\n\n"
msg += "After the installation process finishes, you can start your Galaxy server. As part of this installation process,\n"
msg += "entries for each of the following tool config files will be added to the file named ./migrated_tool_conf.xml, so these\n"
- msg += "tools will continue to be loaded into your tool panel. Because of this, existing entries for these files should be\n"
- msg += "removed from your file%s named %s, but only after the installation process finishes.\n\n" % ( plural, tool_panel_config_file_names )
+ msg += "tools will continue to be loaded into your tool panel. Because of this, existing entries for these tools have been\n"
+ msg += "removed from your file%s named %s.\n\n" % ( plural, tool_panel_config_file_names )
for missing_tool_config, tool_dependencies in missing_tool_configs_dict.items():
msg += "%s\n" % missing_tool_config
msg += "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
diff -r 097abeb6969e93265135a8d6f3e566b5e913ca8f -r 185232cef732d9b79aad686ca0aa556bb7c63614 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
@@ -1,8 +1,10 @@
-import sys, os, ConfigParser
+import ConfigParser
+import os
+import sys
import galaxy.config
import galaxy.datatypes.registry
from galaxy import tools
-from galaxy.tools.data import *
+from galaxy.tools.data import ToolDataTableManager
from galaxy.web import security
import galaxy.model.mapping
import galaxy.tools.search
@@ -10,8 +12,10 @@
import tool_shed.tool_shed_registry
from tool_shed.galaxy_install import install_manager
+
class MigrateToolsApplication( object ):
"""Encapsulates the state of a basic Galaxy Universe application in order to initiate the Install Manager"""
+
def __init__( self, tools_migration_config ):
install_dependencies = 'install_dependencies' in sys.argv
galaxy_config_file = 'universe_wsgi.ini'
@@ -23,7 +27,7 @@
if not os.path.exists( galaxy_config_file ):
print "Galaxy config file does not exist (hint: use '-c config.ini' for non-standard locations): %s" % galaxy_config_file
sys.exit( 1 )
- config_parser = ConfigParser.ConfigParser( { 'here':os.getcwd() } )
+ config_parser = ConfigParser.ConfigParser( { 'here' : os.getcwd() } )
config_parser.read( galaxy_config_file )
galaxy_config_dict = {}
for key, value in config_parser.items( "app:main" ):
@@ -77,8 +81,10 @@
tools_migration_config ),
migrated_tools_config=self.config.migrated_tools_config,
install_dependencies=install_dependencies )
+
@property
def sa_session( self ):
return self.model.context.current
+
def shutdown( self ):
self.object_store.shutdown()
diff -r 097abeb6969e93265135a8d6f3e566b5e913ca8f -r 185232cef732d9b79aad686ca0aa556bb7c63614 lib/tool_shed/util/common_util.py
--- a/lib/tool_shed/util/common_util.py
+++ b/lib/tool_shed/util/common_util.py
@@ -76,7 +76,7 @@
return missing_tool_configs_dict
def get_non_shed_tool_panel_configs( app ):
- # Get the non-shed related tool panel configs - there can be more than one, and the default is tool_conf.xml.
+ """Get the non-shed related tool panel configs - there can be more than one, and the default is tool_conf.xml."""
config_filenames = []
for config_filename in app.config.tool_configs:
# Any config file that includes a tool_path attribute in the root tag set like the following is shed-related.
@@ -98,13 +98,13 @@
shed_url = shed_url.rstrip( '/' )
return shed_url
return None
-
+
def tool_shed_get( app, tool_shed_url, uri ):
"""Make contact with the tool shed via the uri provided."""
registry = app.tool_shed_registry
urlopener = urllib2.build_opener()
password_mgr = registry.password_manager_for_url( tool_shed_url )
- if ( password_mgr is not None ):
+ if password_mgr is not None:
auth_handler = urllib2.HTTPBasicAuthHandler( password_mgr )
urlopener.add_handler( auth_handler )
response = urlopener.open( uri )
diff -r 097abeb6969e93265135a8d6f3e566b5e913ca8f -r 185232cef732d9b79aad686ca0aa556bb7c63614 scripts/migrate_tools/migrate_tools.py
--- a/scripts/migrate_tools/migrate_tools.py
+++ b/scripts/migrate_tools/migrate_tools.py
@@ -1,4 +1,3 @@
-
"""
This script will start up its own web application which includes an InstallManager (~/lib/galaxy/tool_shed/install_manager.py).
For each tool discovered missing, the tool shed repository that contains it will be installed on disk and a new entry will be
@@ -8,11 +7,12 @@
layout of the local tool_conf.xml file. Entries will not be created in migrated_tools_conf.xml for tools included in the tool
shed repository but not defined in tool_conf.xml.
"""
-import sys, os
+import os
+import sys
new_path = [ os.path.join( os.getcwd(), "lib" ) ]
# Remove scripts/ from the path.
-new_path.extend( sys.path[1:] )
+new_path.extend( sys.path[ 1: ] )
sys.path = new_path
from galaxy import eggs
@@ -26,8 +26,8 @@
else:
plural = 's'
file_names = ', '.join( non_shed_tool_confs )
-msg = "\nThe installation process is finished. If any tools associated with this migration were defined in your file%s named\n" % plural
-msg += "%s, then you should remove entries for them and start your Galaxy server.\n" % file_names
+msg = "\nThe installation process is finished. All tools associated with this migration that were defined in your file%s named\n" % plural
+msg += "%s, have been removed. You may now start your Galaxy server.\n" % file_names
print msg
app.shutdown()
sys.exit( 0 )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Workflow from_dict was creating duplicate PostJobActions -- this already happens in module.save_to_step
by commits-noreply@bitbucket.org 22 Aug '13
by commits-noreply@bitbucket.org 22 Aug '13
22 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/097abeb6969e/
Changeset: 097abeb6969e
User: dannon
Date: 2013-08-22 16:05:09
Summary: Workflow from_dict was creating duplicate PostJobActions -- this already happens in module.save_to_step
Affected #: 2 files
diff -r 1859b9f04a6e665e90ed42441302e8486cbd6941 -r 097abeb6969e93265135a8d6f3e566b5e913ca8f lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -1803,12 +1803,6 @@
if annotation:
annotation = sanitize_html( annotation, 'utf-8', 'text/html' )
self.add_item_annotation( trans.sa_session, trans.get_user(), step, annotation )
- # Unpack and add post-job actions.
- post_job_actions = step_dict.get( 'post_job_actions', {} )
- for name, pja_dict in post_job_actions.items():
- model.PostJobAction( pja_dict[ 'action_type' ],
- step, pja_dict[ 'output_name' ],
- pja_dict[ 'action_arguments' ] )
# Second pass to deal with connections between steps
for step in steps:
# Input connections
diff -r 1859b9f04a6e665e90ed42441302e8486cbd6941 -r 097abeb6969e93265135a8d6f3e566b5e913ca8f lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -250,7 +250,6 @@
module.version_changes.append("%s: using version '%s' instead of version '%s' indicated in this workflow." % (tool_id, module.tool.version, step.tool_version))
module.state.inputs = module.tool.params_from_strings( step.tool_inputs, trans.app, ignore_errors=True )
module.errors = step.tool_errors
- # module.post_job_actions = step.post_job_actions
module.workflow_outputs = step.workflow_outputs
pjadict = {}
for pja in step.post_job_actions:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Update functional tests to check for the correct string on the 'Monitor installing tool shed repositories' page.
by commits-noreply@bitbucket.org 22 Aug '13
by commits-noreply@bitbucket.org 22 Aug '13
22 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1859b9f04a6e/
Changeset: 1859b9f04a6e
User: Dave Bouvier
Date: 2013-08-22 15:49:25
Summary: Update functional tests to check for the correct string on the 'Monitor installing tool shed repositories' page.
Affected #: 6 files
diff -r e9ced769e4f3d348875d014a16c82b32ec748517 -r 1859b9f04a6e665e90ed42441302e8486cbd6941 test/tool_shed/functional/test_1100_install_repository_with_complex_dependencies.py
--- a/test/tool_shed/functional/test_1100_install_repository_with_complex_dependencies.py
+++ b/test/tool_shed/functional/test_1100_install_repository_with_complex_dependencies.py
@@ -232,7 +232,7 @@
category_name,
install_tool_dependencies=True,
preview_strings_displayed=preview_strings_displayed,
- post_submit_strings_displayed=[ base_repository.name, tool_repository.name, 'new' ],
+ post_submit_strings_displayed=[ base_repository.name, tool_repository.name, 'New' ],
includes_tools_for_display_in_tool_panel=True )
def test_0050_verify_installed_repositories( self ):
diff -r e9ced769e4f3d348875d014a16c82b32ec748517 -r 1859b9f04a6e665e90ed42441302e8486cbd6941 test/tool_shed/functional/test_1110_install_repository_with_invalid_repository_dependency.py
--- a/test/tool_shed/functional/test_1110_install_repository_with_invalid_repository_dependency.py
+++ b/test/tool_shed/functional/test_1110_install_repository_with_invalid_repository_dependency.py
@@ -176,7 +176,7 @@
install_tool_dependencies=False,
install_repository_dependencies=True,
preview_strings_displayed=preview_strings_displayed,
- post_submit_strings_displayed=[ repository.name, repository.name, 'new' ],
+ post_submit_strings_displayed=[ repository.name, repository.name, 'New' ],
includes_tools_for_display_in_tool_panel=True )
repository = test_db_util.get_installed_repository_by_name_owner( emboss_repository_name, common.test_user_1_name )
self.display_installed_repository_manage_page( repository, strings_not_displayed=[ 'Repository dependencies' ] )
diff -r e9ced769e4f3d348875d014a16c82b32ec748517 -r 1859b9f04a6e665e90ed42441302e8486cbd6941 test/tool_shed/functional/test_1130_datatype_converters.py
--- a/test/tool_shed/functional/test_1130_datatype_converters.py
+++ b/test/tool_shed/functional/test_1130_datatype_converters.py
@@ -79,7 +79,7 @@
preview_strings_displayed=preview_strings_displayed,
strings_displayed=strings_displayed,
strings_not_displayed=strings_not_displayed,
- post_submit_strings_displayed=[ repository.name, 'new' ],
+ post_submit_strings_displayed=[ repository.name, 'New' ],
includes_tools_for_display_in_tool_panel=False )
def test_0015_uninstall_and_verify_tool_panel_section( self ):
diff -r e9ced769e4f3d348875d014a16c82b32ec748517 -r 1859b9f04a6e665e90ed42441302e8486cbd6941 test/tool_shed/functional/test_1150_prior_installation_required.py
--- a/test/tool_shed/functional/test_1150_prior_installation_required.py
+++ b/test/tool_shed/functional/test_1150_prior_installation_required.py
@@ -138,7 +138,7 @@
preview_strings_displayed=preview_strings_displayed,
strings_displayed=strings_displayed,
strings_not_displayed=[],
- post_submit_strings_displayed=[ 'column_maker_0150', 'new' ],
+ post_submit_strings_displayed=[ 'column_maker_0150', 'New' ],
includes_tools_for_display_in_tool_panel=True )
def test_0030_verify_installation_order( self ):
diff -r e9ced769e4f3d348875d014a16c82b32ec748517 -r 1859b9f04a6e665e90ed42441302e8486cbd6941 test/tool_shed/functional/test_1160_circular_prior_installation_required.py
--- a/test/tool_shed/functional/test_1160_circular_prior_installation_required.py
+++ b/test/tool_shed/functional/test_1160_circular_prior_installation_required.py
@@ -207,7 +207,7 @@
preview_strings_displayed=preview_strings_displayed,
strings_displayed=strings_displayed,
strings_not_displayed=[],
- post_submit_strings_displayed=[ 'filtering_0160', 'new' ],
+ post_submit_strings_displayed=[ 'filtering_0160', 'New' ],
includes_tools_for_display_in_tool_panel=True )
def test_0035_verify_installation_order( self ):
diff -r e9ced769e4f3d348875d014a16c82b32ec748517 -r 1859b9f04a6e665e90ed42441302e8486cbd6941 test/tool_shed/functional/test_1170_complex_prior_installation_required.py
--- a/test/tool_shed/functional/test_1170_complex_prior_installation_required.py
+++ b/test/tool_shed/functional/test_1170_complex_prior_installation_required.py
@@ -163,7 +163,7 @@
preview_strings_displayed=preview_strings_displayed,
strings_displayed=[],
strings_not_displayed=[],
- post_submit_strings_displayed=[ 'package_matplotlib_1_2_0170', 'new' ],
+ post_submit_strings_displayed=[ 'package_matplotlib_1_2_0170', 'New' ],
includes_tools_for_display_in_tool_panel=False )
def test_0030_verify_installation_order( 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: dannon: Update hide action to reflect what output is being hidden.
by commits-noreply@bitbucket.org 22 Aug '13
by commits-noreply@bitbucket.org 22 Aug '13
22 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e9ced769e4f3/
Changeset: e9ced769e4f3
User: dannon
Date: 2013-08-22 15:05:41
Summary: Update hide action to reflect what output is being hidden.
Affected #: 1 file
diff -r 315ee3999082396e751e7478f0ac2a4247ba5e70 -r e9ced769e4f3d348875d014a16c82b32ec748517 lib/galaxy/jobs/actions/post.py
--- a/lib/galaxy/jobs/actions/post.py
+++ b/lib/galaxy/jobs/actions/post.py
@@ -242,8 +242,8 @@
}
"""
@classmethod
- def get_short_str(cls, trans):
- return "Hide this dataset."
+ def get_short_str(cls, pja):
+ return "Hide output '%s'." % pja.output_name
class DeleteDatasetAction(DefaultJobAction):
# This is disabled for right now. Deleting a dataset in the middle of a workflow causes errors (obviously) for the subsequent steps using the data.
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/2f655d7df4de/
Changeset: 2f655d7df4de
User: jmchilton
Date: 2013-08-13 21:38:00
Summary: Add some overly simple baseline unit tests for visualizations plugin behavior.
Affected #: 1 file
diff -r 009088d5e76fb00794da78dc0ee3cdaa8524b7d8 -r 2f655d7df4de9731adf45ec1487a9e85c5671aaf test/unit/test_plugins.py
--- /dev/null
+++ b/test/unit/test_plugins.py
@@ -0,0 +1,14 @@
+from os.path import join, dirname, basename
+from galaxy.visualization.registry import VisualizationsRegistry
+
+
+def test_visualization_loading():
+ galaxy_root = join(dirname(__file__), '..', '..')
+ visualizations = join(galaxy_root, 'config', 'plugins', 'visualizations')
+ registry = VisualizationsRegistry(visualizations, 'foo')
+ assert "VisualizationsRegistry" in str(registry)
+ assert visualizations in str(registry)
+ assert registry.name == "visualizations"
+ assert 'scatterplot' in \
+ [basename(path) for path in registry.get_plugin_directories()]
+ assert registry._get_template_paths() == [visualizations]
https://bitbucket.org/galaxy/galaxy-central/commits/83139f9fed93/
Changeset: 83139f9fed93
User: jmchilton
Date: 2013-08-13 21:38:00
Summary: Planning on refactoring out self.plugin_directory, is this simplified logic sufficient or was it the way it was for a good reason?
Affected #: 1 file
diff -r 2f655d7df4de9731adf45ec1487a9e85c5671aaf -r 83139f9fed93f4a3759ed1b5c2019c24fb8037c5 lib/galaxy/web/base/pluginframework.py
--- a/lib/galaxy/web/base/pluginframework.py
+++ b/lib/galaxy/web/base/pluginframework.py
@@ -220,8 +220,7 @@
this version of `fill_template` allows `bler.mako` to call `import my_script`.
"""
try:
- plugin_base_path = os.path.split( os.path.dirname( template_filename ) )[0]
- plugin_path = os.path.join( self.plugin_directory, plugin_base_path )
+ plugin_path = os.path.dirname( os.path.dirname( template_filename ) )
sys.path.append( plugin_path )
filled_template = self.fill_template( trans, template_filename, **kwargs )
https://bitbucket.org/galaxy/galaxy-central/commits/82b20714be81/
Changeset: 82b20714be81
User: jmchilton
Date: 2013-08-13 21:38:00
Summary: Refactor plugin framework to allow multiple plugin directories (like tools framework allows multiple tool roots).
Idea here is to allow some plugins to be managed by Galaxy team inside root and some plugins to be managed outside of Galaxy root by deployers, etc.... This will help keep merges unnecessary or as minimal as possible and should ease efforts like Debian packaging of Galaxy.
The need to actually modify the Galaxy code base is an unfortunate aspect of the way dynamic job destinations and dynamic toolbox filters have been implemented. Bringing these under a generic plugin framework and allowing them to be tweaked outside of the Galaxy code base would be wins.
Affected #: 2 files
diff -r 83139f9fed93f4a3759ed1b5c2019c24fb8037c5 -r 82b20714be81946be9d6fa8ff0848fc6bd02b567 lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -61,9 +61,6 @@
#: directories under plugin_directory that aren't plugins
non_plugin_directories = []
- def __str__( self ):
- return 'VisualizationsRegistry(%s)' %( self.plugin_directory )
-
def __init__( self, registry_filepath, template_cache_dir ):
super( VisualizationsRegistry, self ).__init__( registry_filepath, 'visualizations', template_cache_dir )
@@ -84,7 +81,7 @@
self.listings = VisualizationsConfigParser.parse( self.get_plugin_directories() )
except Exception, exc:
- log.exception( 'Error parsing visualizations plugins %s', self.plugin_directory )
+ log.exception( 'Error parsing visualizations plugins %s', self.plugin_directories )
raise
def get_visualization( self, trans, visualization_name, target_object ):
diff -r 83139f9fed93f4a3759ed1b5c2019c24fb8037c5 -r 82b20714be81946be9d6fa8ff0848fc6bd02b567 lib/galaxy/web/base/pluginframework.py
--- a/lib/galaxy/web/base/pluginframework.py
+++ b/lib/galaxy/web/base/pluginframework.py
@@ -14,6 +14,8 @@
pkg_resources.require( 'Mako' )
import mako
+from galaxy.util import listify
+
import logging
log = logging.getLogger( __name__ )
@@ -94,24 +96,29 @@
return None
def __str__( self ):
- return '%s(%s)' %( self.__class__.__name__, self.plugin_directory )
+ return '%s(%s)' %( self.__class__.__name__, self.plugin_directories )
- def __init__( self, plugin_directory, name=None, template_cache_dir=None, debug=False ):
+ def __init__( self, plugin_directories, name=None, template_cache_dir=None, debug=False, assert_exists=True ):
"""
- :type plugin_directory: string
- :param plugin_directory: the base directory where plugin code is kept
- :type name: (optional) string (default: None)
- :param name: the name of this plugin
+ :type plugin_directories: string or list
+ :param plugin_directories: the base directory where plugin code is kept
+ :type name: (optional) string (default: None)
+ :param name: the name of this plugin
(that will appear in url pathing, etc.)
- :type template_cache_dir: (optional) string (default: None)
- :param template_cache_dir: the cache directory to store compiled mako
+ :type template_cache_dir: (optional) string (default: None)
+ :param template_cache_dir: the cache directory to store compiled mako
+ :type assert_exists: (optional) bool (default: False)
+ :param assert_exists: If True, each configured plugin directory must exist.
"""
- if not os.path.isdir( plugin_directory ):
- raise PluginFrameworkException( 'Framework plugin directory not found: %s, %s'
- %( self.__class__.__name__, plugin_directory ) )
- self.plugin_directory = plugin_directory
+ self.plugin_directories = listify( plugin_directories )
+ if assert_exists:
+ for plugin_directory in self.plugin_directories:
+ if not os.path.isdir( plugin_directory ):
+ raise PluginFrameworkException( 'Framework plugin directory not found: %s, %s'
+ % ( self.__class__.__name__, plugin_directory ) )
+
#TODO: or pass in from config
- self.name = name or os.path.basename( self.plugin_directory )
+ self.name = name or os.path.basename( self.plugin_directories[0] )
if self.has_config:
self.load_configuration()
@@ -127,14 +134,15 @@
themselves and whose ``basename`` is not in ``plugin_directory``.
"""
# could instead explicitly list on/off in master config file
- for plugin_path in glob.glob( os.path.join( self.plugin_directory, '*' ) ):
- if not os.path.isdir( plugin_path ):
- continue
+ for plugin_directory in self.plugin_directories:
+ for plugin_path in glob.glob( os.path.join( plugin_directory, '*' ) ):
+ if not os.path.isdir( plugin_path ):
+ continue
- if os.path.basename( plugin_path ) in self.non_plugin_directories:
- continue
+ if os.path.basename( plugin_path ) in self.non_plugin_directories:
+ continue
- yield plugin_path
+ yield plugin_path
# ------------------------------------------------------------------------- config
def load_configuration( self ):
@@ -185,7 +193,7 @@
"""
Get the paths that will be searched for templates.
"""
- return [ self.plugin_directory ]
+ return self.plugin_directories
def _create_mako_template_lookup( self, cache_dir, paths, collection_size=500, output_encoding='utf-8' ):
"""
https://bitbucket.org/galaxy/galaxy-central/commits/b5f765e074f8/
Changeset: b5f765e074f8
User: jmchilton
Date: 2013-08-13 21:38:00
Summary: Add some test cases for plugins configured from multiple directories.
Affected #: 1 file
diff -r 82b20714be81946be9d6fa8ff0848fc6bd02b567 -r b5f765e074f8ff5ba02dad1d841b92c15b3fb224 test/unit/test_plugins.py
--- a/test/unit/test_plugins.py
+++ b/test/unit/test_plugins.py
@@ -1,14 +1,42 @@
+from os import makedirs
from os.path import join, dirname, basename
+from tempfile import mkdtemp
+from shutil import rmtree
+
from galaxy.visualization.registry import VisualizationsRegistry
def test_visualization_loading():
- galaxy_root = join(dirname(__file__), '..', '..')
- visualizations = join(galaxy_root, 'config', 'plugins', 'visualizations')
+ visualizations = __default_viz_root()
registry = VisualizationsRegistry(visualizations, 'foo')
assert "VisualizationsRegistry" in str(registry)
assert visualizations in str(registry)
assert registry.name == "visualizations"
+ __assert_scatterplot_registered(registry)
+ assert registry._get_template_paths() == [visualizations]
+
+
+def test_multiple_visualization_roots():
+ temp_dir = mkdtemp()
+ try:
+ makedirs(join(temp_dir, "coolplugin5"))
+ visualization_dirs = "%s,%s" % (__default_viz_root(), temp_dir)
+ registry = VisualizationsRegistry(visualization_dirs, 'foo')
+ __assert_scatterplot_registered(registry)
+ assert "coolplugin5" in \
+ [basename(path) for path in registry.get_plugin_directories()]
+ assert registry._get_template_paths() == \
+ [__default_viz_root(), temp_dir]
+ finally:
+ rmtree(temp_dir)
+
+
+def __assert_scatterplot_registered(registry):
assert 'scatterplot' in \
[basename(path) for path in registry.get_plugin_directories()]
- assert registry._get_template_paths() == [visualizations]
+
+
+def __default_viz_root():
+ galaxy_root = join(dirname(__file__), '..', '..')
+ visualizations = join(galaxy_root, 'config', 'plugins', 'visualizations')
+ return visualizations
https://bitbucket.org/galaxy/galaxy-central/commits/315ee3999082/
Changeset: 315ee3999082
User: carlfeberhard
Date: 2013-08-22 00:24:53
Summary: Merge John Chilton's pull request #204
Affected #: 3 files
diff -r ee60297266b09d81a7906c32a7ec03199e50a0c7 -r 315ee3999082396e751e7478f0ac2a4247ba5e70 lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -61,9 +61,6 @@
#: directories under plugin_directory that aren't plugins
non_plugin_directories = []
- def __str__( self ):
- return 'VisualizationsRegistry(%s)' %( self.plugin_directory )
-
def __init__( self, registry_filepath, template_cache_dir ):
super( VisualizationsRegistry, self ).__init__( registry_filepath, 'visualizations', template_cache_dir )
@@ -84,7 +81,7 @@
self.listings = VisualizationsConfigParser.parse( self.get_plugin_directories() )
except Exception, exc:
- log.exception( 'Error parsing visualizations plugins %s', self.plugin_directory )
+ log.exception( 'Error parsing visualizations plugins %s', self.plugin_directories )
raise
def get_visualization( self, trans, visualization_name, target_object ):
diff -r ee60297266b09d81a7906c32a7ec03199e50a0c7 -r 315ee3999082396e751e7478f0ac2a4247ba5e70 lib/galaxy/web/base/pluginframework.py
--- a/lib/galaxy/web/base/pluginframework.py
+++ b/lib/galaxy/web/base/pluginframework.py
@@ -14,6 +14,8 @@
pkg_resources.require( 'Mako' )
import mako
+from galaxy.util import listify
+
import logging
log = logging.getLogger( __name__ )
@@ -94,24 +96,29 @@
return None
def __str__( self ):
- return '%s(%s)' %( self.__class__.__name__, self.plugin_directory )
+ return '%s(%s)' %( self.__class__.__name__, self.plugin_directories )
- def __init__( self, plugin_directory, name=None, template_cache_dir=None, debug=False ):
+ def __init__( self, plugin_directories, name=None, template_cache_dir=None, debug=False, assert_exists=True ):
"""
- :type plugin_directory: string
- :param plugin_directory: the base directory where plugin code is kept
- :type name: (optional) string (default: None)
- :param name: the name of this plugin
+ :type plugin_directories: string or list
+ :param plugin_directories: the base directory where plugin code is kept
+ :type name: (optional) string (default: None)
+ :param name: the name of this plugin
(that will appear in url pathing, etc.)
- :type template_cache_dir: (optional) string (default: None)
- :param template_cache_dir: the cache directory to store compiled mako
+ :type template_cache_dir: (optional) string (default: None)
+ :param template_cache_dir: the cache directory to store compiled mako
+ :type assert_exists: (optional) bool (default: False)
+ :param assert_exists: If True, each configured plugin directory must exist.
"""
- if not os.path.isdir( plugin_directory ):
- raise PluginFrameworkException( 'Framework plugin directory not found: %s, %s'
- %( self.__class__.__name__, plugin_directory ) )
- self.plugin_directory = plugin_directory
+ self.plugin_directories = listify( plugin_directories )
+ if assert_exists:
+ for plugin_directory in self.plugin_directories:
+ if not os.path.isdir( plugin_directory ):
+ raise PluginFrameworkException( 'Framework plugin directory not found: %s, %s'
+ % ( self.__class__.__name__, plugin_directory ) )
+
#TODO: or pass in from config
- self.name = name or os.path.basename( self.plugin_directory )
+ self.name = name or os.path.basename( self.plugin_directories[0] )
if self.has_config:
self.load_configuration()
@@ -127,14 +134,15 @@
themselves and whose ``basename`` is not in ``plugin_directory``.
"""
# could instead explicitly list on/off in master config file
- for plugin_path in glob.glob( os.path.join( self.plugin_directory, '*' ) ):
- if not os.path.isdir( plugin_path ):
- continue
+ for plugin_directory in self.plugin_directories:
+ for plugin_path in glob.glob( os.path.join( plugin_directory, '*' ) ):
+ if not os.path.isdir( plugin_path ):
+ continue
- if os.path.basename( plugin_path ) in self.non_plugin_directories:
- continue
+ if os.path.basename( plugin_path ) in self.non_plugin_directories:
+ continue
- yield plugin_path
+ yield plugin_path
# ------------------------------------------------------------------------- config
def load_configuration( self ):
@@ -185,7 +193,7 @@
"""
Get the paths that will be searched for templates.
"""
- return [ self.plugin_directory ]
+ return self.plugin_directories
def _create_mako_template_lookup( self, cache_dir, paths, collection_size=500, output_encoding='utf-8' ):
"""
@@ -220,8 +228,7 @@
this version of `fill_template` allows `bler.mako` to call `import my_script`.
"""
try:
- plugin_base_path = os.path.split( os.path.dirname( template_filename ) )[0]
- plugin_path = os.path.join( self.plugin_directory, plugin_base_path )
+ plugin_path = os.path.dirname( os.path.dirname( template_filename ) )
sys.path.append( plugin_path )
filled_template = self.fill_template( trans, template_filename, **kwargs )
diff -r ee60297266b09d81a7906c32a7ec03199e50a0c7 -r 315ee3999082396e751e7478f0ac2a4247ba5e70 test/unit/test_plugins.py
--- /dev/null
+++ b/test/unit/test_plugins.py
@@ -0,0 +1,42 @@
+from os import makedirs
+from os.path import join, dirname, basename
+from tempfile import mkdtemp
+from shutil import rmtree
+
+from galaxy.visualization.registry import VisualizationsRegistry
+
+
+def test_visualization_loading():
+ visualizations = __default_viz_root()
+ registry = VisualizationsRegistry(visualizations, 'foo')
+ assert "VisualizationsRegistry" in str(registry)
+ assert visualizations in str(registry)
+ assert registry.name == "visualizations"
+ __assert_scatterplot_registered(registry)
+ assert registry._get_template_paths() == [visualizations]
+
+
+def test_multiple_visualization_roots():
+ temp_dir = mkdtemp()
+ try:
+ makedirs(join(temp_dir, "coolplugin5"))
+ visualization_dirs = "%s,%s" % (__default_viz_root(), temp_dir)
+ registry = VisualizationsRegistry(visualization_dirs, 'foo')
+ __assert_scatterplot_registered(registry)
+ assert "coolplugin5" in \
+ [basename(path) for path in registry.get_plugin_directories()]
+ assert registry._get_template_paths() == \
+ [__default_viz_root(), temp_dir]
+ finally:
+ rmtree(temp_dir)
+
+
+def __assert_scatterplot_registered(registry):
+ assert 'scatterplot' in \
+ [basename(path) for path in registry.get_plugin_directories()]
+
+
+def __default_viz_root():
+ galaxy_root = join(dirname(__file__), '..', '..')
+ visualizations = join(galaxy_root, 'config', 'plugins', 'visualizations')
+ return visualizations
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: Remove spurious type setting in Group object.
by commits-noreply@bitbucket.org 22 Aug '13
by commits-noreply@bitbucket.org 22 Aug '13
22 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ee60297266b0/
Changeset: ee60297266b0
User: jgoecks
Date: 2013-08-21 21:24:04
Summary: Remove spurious type setting in Group object.
Affected #: 1 file
diff -r 8ed926ee0b523bb16a90e218f1d8bd5ee082ffe8 -r ee60297266b09d81a7906c32a7ec03199e50a0c7 lib/galaxy/tools/parameters/grouping.py
--- a/lib/galaxy/tools/parameters/grouping.py
+++ b/lib/galaxy/tools/parameters/grouping.py
@@ -23,8 +23,7 @@
def __init__( self ):
self.name = None
- self.type = 'group'
-
+
@property
def visible( self ):
return 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