galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
September 2011
- 1 participants
- 91 discussions
commit/galaxy-central: jgoecks: Fix problems with computing indices for GFF/GTF datasets.
by Bitbucket 30 Sep '11
by Bitbucket 30 Sep '11
30 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c265358e1062/
changeset: c265358e1062
user: jgoecks
date: 2011-10-01 00:38:30
summary: Fix problems with computing indices for GFF/GTF datasets.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/datatypes/util/gff_util.py Fri Sep 30 15:07:11 2011 -0400
+++ b/lib/galaxy/datatypes/util/gff_util.py Fri Sep 30 18:38:30 2011 -0400
@@ -133,6 +133,7 @@
self.last_line = None
self.cur_offset = 0
self.seed_interval = None
+ self.seed_interval_line_len = 0
def parse_row( self, line ):
interval = GFFInterval( self, line.split( "\t" ), self.chrom_col, self.feature_col, \
@@ -160,12 +161,12 @@
# For debugging, uncomment this to propogate parsing exceptions up.
# I.e. the underlying reason for an unexpected StopIteration exception
# can be found by uncommenting this.
- #raise e
+ # raise e
#
# Get next GFFFeature
#
- raw_size = 0
+ raw_size = self.seed_interval_line_len
# If there is no seed interval, set one. Also, if there are no more
# intervals to read, this is where iterator dies.
@@ -184,8 +185,9 @@
return_val = self.seed_interval
return_val.raw_size = len( self.current_line )
self.seed_interval = None
+ self.seed_interval_line_len = 0
return return_val
-
+
# Initialize feature identifier from seed.
feature_group = self.seed_interval.attributes.get( 'group', None ) # For GFF
# For GFF3
@@ -220,21 +222,28 @@
if isinstance( interval, Comment ):
continue
- # If interval not associated with feature, break.
+ # Determine if interval is part of feature.
+ part_of = True
group = interval.attributes.get( 'group', None )
# GFF test:
if group and feature_group != group:
- break
+ part_of = False
# GFF3 test:
parent_id = interval.attributes.get( 'Parent', None )
cur_id = interval.attributes.get( 'ID', None )
if ( cur_id and cur_id != feature_id ) or ( parent_id and parent_id != feature_id ):
- break
+ part_of = False
# GTF test:
gene_id = interval.attributes.get( 'gene_id', None )
transcript_id = interval.attributes.get( 'transcript_id', None )
if ( transcript_id and transcript_id != feature_transcript_id ) or \
( gene_id and gene_id != feature_gene_id ):
+ part_of = False
+
+ # If interval is not part of feature, clean up and break.
+ if not part_of:
+ # Adjust raw size because current line is not part of feature.
+ raw_size -= len( self.current_line )
break
# Interval associated with feature.
@@ -242,6 +251,7 @@
# Last interval read is the seed for the next interval.
self.seed_interval = interval
+ self.seed_interval_line_len = len( self.current_line )
# Return feature.
feature = GFFFeature( self, self.chrom_col, self.feature_col, self.start_col, \
@@ -255,7 +265,6 @@
return feature
-
def convert_bed_coords_to_gff( interval ):
"""
Converts an interval object's coordinates from BED format to GFF format.
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
30 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c32929b315bd/
changeset: c32929b315bd
user: natefoo
date: 2011-09-30 21:07:11
summary: Fix for a minor bug in e28ebc25b2e7
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/web/controllers/dataset.py Fri Sep 30 14:21:51 2011 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Fri Sep 30 15:07:11 2011 -0400
@@ -690,7 +690,7 @@
# If data is binary or an image, stream without template; otherwise, use display template.
# TODO: figure out a way to display images in display template.
if isinstance(dataset.datatype, datatypes.binary.Binary) or isinstance(dataset.datatype, datatypes.images.Image) or isinstance(dataset.datatype, datatypes.images.Html):
- trans.response.set_content_type( data.get_mime() )
+ trans.response.set_content_type( dataset.get_mime() )
return open( dataset.file_name )
else:
# Get rating 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
commit/galaxy-central: jgoecks: Trackster: fixes for adding a dataset to a new visualization.
by Bitbucket 30 Sep '11
by Bitbucket 30 Sep '11
30 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/1478b77001bd/
changeset: 1478b77001bd
user: jgoecks
date: 2011-09-30 20:21:51
summary: Trackster: fixes for adding a dataset to a new visualization.
affected #: 3 files (-1 bytes)
--- a/static/scripts/packed/trackster_ui.js Fri Sep 30 14:03:58 2011 -0400
+++ b/static/scripts/packed/trackster_ui.js Fri Sep 30 14:21:51 2011 -0400
@@ -1,1 +1,1 @@
-var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(c,b){var a=new addable_objects[c.track_type](c.name,view,b,c.hda_ldda,c.dataset_id,c.prefs,c.filters,c.tool);if(c.mode){a.change_mode(c.mode)}return a};var drawable_collection_from_dict=function(f,a){var e=new addable_objects[f.obj_type](f.name,view,a,f.prefs,view.viewport_container,view);for(var d=0;d<f.drawables.length;d++){var b=f.drawables[d],c;if(b.track_type){c=track_from_dict(b,e)}else{c=drawable_collection_from_dict(b)}e.add_drawable(c);e.content_div.append(c.container_div)}return e};var drawable_from_dict=function(b,a){return(b.track_type?track_from_dict(b,a):drawable_collection_from_dict(b,a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o,view))}}var n;for(var j=0;j<view.tracks.length;j++){if(view.tracks[j].name==m){view.set_overview(view.tracks[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
+var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(c,b){var a=new addable_objects[c.track_type](c.name,view,b,c.hda_ldda,c.dataset_id,c.prefs,c.filters,c.tool);if(c.mode){a.change_mode(c.mode)}return a};var drawable_collection_from_dict=function(f,a){var e=new addable_objects[f.obj_type](f.name,view,a,f.prefs,view.viewport_container,view);for(var d=0;d<f.drawables.length;d++){var b=f.drawables[d],c;if(b.track_type){c=track_from_dict(b,e)}else{c=drawable_collection_from_dict(b)}e.add_drawable(c);e.content_div.append(c.container_div)}return e};var drawable_from_dict=function(b,a){return(b.track_type?track_from_dict(b,a):drawable_collection_from_dict(b,a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(a){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o,view))}}var n;for(var j=0;j<view.tracks.length;j++){if(view.tracks[j].name==m){view.set_overview(view.tracks[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
--- a/static/scripts/trackster_ui.js Fri Sep 30 14:03:58 2011 -0400
+++ b/static/scripts/trackster_ui.js Fri Sep 30 14:21:51 2011 -0400
@@ -89,15 +89,17 @@
view = new View(parent_elt, title, id, dbkey);
view.editor = true;
$.when( view.load_chroms_deferred ).then(function() {
- // Viewport config.
- var
- chrom = viewport_config.chrom,
- start = viewport_config.start,
- end = viewport_config.end,
- overview_track_name = viewport_config.overview;
+ // Viewport config.
+ if (viewport_config) {
+ var
+ chrom = viewport_config.chrom,
+ start = viewport_config.start,
+ end = viewport_config.end,
+ overview_track_name = viewport_config.overview;
- if (chrom && (start !== undefined) && end) {
- view.change_chrom(chrom, start, end);
+ if (chrom && (start !== undefined) && end) {
+ view.change_chrom(chrom, start, end);
+ }
}
// Add drawables to view.
--- a/templates/tracks/browser.mako Fri Sep 30 14:03:58 2011 -0400
+++ b/templates/tracks/browser.mako Fri Sep 30 14:21:51 2011 -0400
@@ -166,7 +166,7 @@
url: "${h.url_for( action='add_track_async' )}",
data: { hda_id: "${add_dataset}" },
dataType: "json",
- success: function(track_data) { view.add_drawable( track_from_dict(track_data) ) }
+ success: function(track_data) { view.add_drawable( track_from_dict(track_data, view) ) }
});
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/be9f3aa6c324/
changeset: be9f3aa6c324
user: greg
date: 2011-09-30 20:03:58
summary: Two minor fixes.
affected #: 2 files (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Fri Sep 30 10:50:02 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 30 14:03:58 2011 -0400
@@ -1305,7 +1305,7 @@
if webapp == 'galaxy':
cloned_repositories = trans.sa_session.query( trans.model.ToolShedRepository ) \
.filter( trans.model.ToolShedRepository.deleted == False ) \
- .all()
+ .first()
return trans.fill_template( '/webapps/galaxy/admin/index.mako',
webapp=webapp,
cloned_repositories=cloned_repositories,
--- a/templates/webapps/galaxy/admin/index.mako Fri Sep 30 10:50:02 2011 -0400
+++ b/templates/webapps/galaxy/admin/index.mako Fri Sep 30 14:03:58 2011 -0400
@@ -63,7 +63,7 @@
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='memdump' )}" target="galaxy_main">Profile memory usage</a></div><div class="toolTitle"><a href="${h.url_for( controller='admin', action='jobs' )}" target="galaxy_main">Manage jobs</a></div>
%if cloned_repositories:
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_repositories' )}" target="galaxy_main">Manage cloned tool shed repositories</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_repositories' )}" target="galaxy_main">Manage installed tool shed repositories</a></div>
%endif
</div></div>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix for retrieving the list of cloned tool shed repositories from a local Galaxy instance.
by Bitbucket 30 Sep '11
by Bitbucket 30 Sep '11
30 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/418f75a6041a/
changeset: 418f75a6041a
user: greg
date: 2011-09-30 16:50:02
summary: Fix for retrieving the list of cloned tool shed repositories from a local Galaxy instance.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Fri Sep 30 09:48:56 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 30 10:50:02 2011 -0400
@@ -1304,7 +1304,8 @@
status = params.get( 'status', 'done' )
if webapp == 'galaxy':
cloned_repositories = trans.sa_session.query( trans.model.ToolShedRepository ) \
- .filter( trans.model.ToolShedRepository.deleted == False )
+ .filter( trans.model.ToolShedRepository.deleted == False ) \
+ .all()
return trans.fill_template( '/webapps/galaxy/admin/index.mako',
webapp=webapp,
cloned_repositories=cloned_repositories,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Add the ability for a Galaxy admin to get updates from the tool shed for cloned tool shed repositories installed on their local Galaxy instance.
by Bitbucket 30 Sep '11
by Bitbucket 30 Sep '11
30 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/8dce400655d6/
changeset: 8dce400655d6
user: greg
date: 2011-09-30 15:48:56
summary: Add the ability for a Galaxy admin to get updates from the tool shed for cloned tool shed repositories installed on their local Galaxy instance.
affected #: 10 files (-1 bytes)
--- a/lib/galaxy/model/__init__.py Fri Sep 30 09:26:22 2011 -0400
+++ b/lib/galaxy/model/__init__.py Fri Sep 30 09:48:56 2011 -0400
@@ -2630,6 +2630,17 @@
class APIKeys( object ):
pass
+class ToolShedRepository( object ):
+ def __init__( self, id=None, create_time=None, tool_shed=None, name=None, description=None, owner=None, changeset_revision=None, deleted=False ):
+ self.id = id
+ self.create_time = create_time
+ self.tool_shed = tool_shed
+ self.name = name
+ self.description = description
+ self.owner = owner
+ self.changeset_revision = changeset_revision
+ self.deleted = deleted
+
## ---- Utility methods -------------------------------------------------------
def directory_hash_id( id ):
--- a/lib/galaxy/model/mapping.py Fri Sep 30 09:26:22 2011 -0400
+++ b/lib/galaxy/model/mapping.py Fri Sep 30 09:48:56 2011 -0400
@@ -363,6 +363,17 @@
Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
Column( "deleted", Boolean, index=True, default=False ) )
+ToolShedRepository.table = Table( "tool_shed_repository", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_shed", TrimmedString( 255 ), index=True ),
+ Column( "name", TrimmedString( 255 ), index=True ),
+ Column( "description" , TEXT ),
+ Column( "owner", TrimmedString( 255 ), index=True ),
+ Column( "changeset_revision", TrimmedString( 255 ), index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
Job.table = Table( "job", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
@@ -1583,7 +1594,9 @@
annotations=relation( PageAnnotationAssociation, order_by=PageAnnotationAssociation.table.c.id, backref="pages" ),
ratings=relation( PageRatingAssociation, order_by=PageRatingAssociation.table.c.id, backref="pages" )
) )
-
+
+assign_mapper( context, ToolShedRepository, ToolShedRepository.table )
+
# Set up proxy so that
# Page.users_shared_with
# returns a list of users that page is shared with.
--- a/lib/galaxy/web/base/controller.py Fri Sep 30 09:26:22 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 30 09:48:56 2011 -0400
@@ -1293,6 +1293,7 @@
role_list_grid = None
group_list_grid = None
quota_list_grid = None
+ repository_list_grid = None
@web.expose
@web.require_admin
@@ -1302,8 +1303,11 @@
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
if webapp == 'galaxy':
+ cloned_repositories = trans.sa_session.query( trans.model.ToolShedRepository ) \
+ .filter( trans.model.ToolShedRepository.deleted == False )
return trans.fill_template( '/webapps/galaxy/admin/index.mako',
webapp=webapp,
+ cloned_repositories=cloned_repositories,
message=message,
status=status )
else:
@@ -2382,362 +2386,9 @@
msg = msg,
status = status,
job_lock = trans.app.job_manager.job_queue.job_lock )
- @web.expose
- @web.require_admin
- def browse_tool_shed( self, trans, **kwd ):
- tool_shed_url = kwd[ 'tool_shed_url' ]
- galaxy_url = trans.request.host
- url = '%s/repository/browse_downloadable_repositories?galaxy_url=%s&webapp=community' % ( tool_shed_url, galaxy_url )
- return trans.response.send_redirect( url )
- @web.expose
- @web.require_admin
- def install_tool_shed_repository( self, trans, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- tool_shed_url = kwd[ 'tool_shed_url' ]
- repository_name = kwd[ 'repository_name' ]
- changeset_revision = kwd[ 'changeset_revision' ]
- repository_clone_url = kwd[ 'repository_clone_url' ]
- if kwd.get( 'select_tool_panel_section_button', False ):
- shed_tool_conf = kwd[ 'shed_tool_conf' ]
- # Get the tool path.
- for k, tool_path in trans.app.toolbox.shed_tool_confs.items():
- if k == shed_tool_conf:
- break
- if 'tool_panel_section' in kwd:
- section_key = 'section_%s' % kwd[ 'tool_panel_section' ]
- tool_section = trans.app.toolbox.tool_panel[ section_key ]
- # Clone the repository to the configured location.
- current_working_dir = os.getcwd()
- clone_dir = os.path.join( tool_path, self.__generate_tool_path( repository_clone_url, changeset_revision ) )
- if os.path.exists( clone_dir ):
- # Repository and revision has already been cloned.
- # TODO: implement the ability to re-install or revert an existing repository.
- message = 'Revision <b>%s</b> of repository <b>%s</b> has already been installed. Updating an existing repository is not yet supported.' % \
- ( changeset_revision, repository_name )
- status = 'error'
- else:
- os.makedirs( clone_dir )
- log.debug( 'Cloning %s...' % repository_clone_url )
- cmd = 'hg clone %s' % repository_clone_url
- tmp_name = tempfile.NamedTemporaryFile().name
- tmp_stderr = open( tmp_name, 'wb' )
- os.chdir( clone_dir )
- proc = subprocess.Popen( args=cmd, shell=True, stderr=tmp_stderr.fileno() )
- returncode = proc.wait()
- os.chdir( current_working_dir )
- tmp_stderr.close()
- if returncode == 0:
- repo_files_dir = os.path.join( clone_dir, repository_name )
- log.debug( 'Updating cloned repository to revision "%s"...' % changeset_revision )
- cmd = 'hg update -r %s' % changeset_revision
- tmp_name = tempfile.NamedTemporaryFile().name
- tmp_stderr = open( tmp_name, 'wb' )
- os.chdir( repo_files_dir )
- proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
- returncode = proc.wait()
- os.chdir( current_working_dir )
- tmp_stderr.close()
- if returncode == 0:
- sample_files, repository_tools_tups = self.__get_repository_tools_and_sample_files( trans, tool_path, repo_files_dir )
- if repository_tools_tups:
- # Handle missing data table entries for tool parameters that are dynamically generated select lists.
- repository_tools_tups = self.__handle_missing_data_table_entry( trans, tool_path, sample_files, repository_tools_tups )
- # Handle missing index files for tool parameters that are dynamically generated select lists.
- repository_tools_tups = self.__handle_missing_index_file( trans, tool_path, sample_files, repository_tools_tups )
- # Handle tools that use fabric scripts to install dependencies.
- self.__handle_tool_dependencies( current_working_dir, repo_files_dir, repository_tools_tups )
- # Generate an in-memory tool conf section that includes the new tools.
- new_tool_section = self.__generate_tool_panel_section( repository_name,
- repository_clone_url,
- changeset_revision,
- tool_section,
- repository_tools_tups )
- # Create a temporary file to persist the in-memory tool section
- # TODO: Figure out how to do this in-memory using xml.etree.
- tmp_name = tempfile.NamedTemporaryFile().name
- persisted_new_tool_section = open( tmp_name, 'wb' )
- persisted_new_tool_section.write( new_tool_section )
- persisted_new_tool_section.close()
- # Parse the persisted tool panel section
- tree = ElementTree.parse( tmp_name )
- root = tree.getroot()
- ElementInclude.include( root )
- # Load the tools in the section into the tool panel.
- trans.app.toolbox.load_section_tag_set( root, trans.app.toolbox.tool_panel, tool_path )
- # Remove the temporary file
- try:
- os.unlink( tmp_name )
- except:
- pass
- # Append the new section to the shed_tool_config file.
- self.__add_shed_tool_conf_entry( trans, shed_tool_conf, new_tool_section )
- message = 'Revision <b>%s</b> of repository <b>%s</b> has been installed in tool panel section <b>%s</b>.' % \
- ( changeset_revision, repository_name, tool_section.name )
- return trans.show_ok_message( message )
- else:
- tmp_stderr = open( tmp_name, 'rb' )
- message = tmp_stderr.read()
- tmp_stderr.close()
- status = 'error'
- else:
- tmp_stderr = open( tmp_name, 'rb' )
- message = tmp_stderr.read()
- tmp_stderr.close()
- status = 'error'
- else:
- message = 'Choose the section in your tool panel to contain the installed tools.'
- status = 'error'
- if len( trans.app.toolbox.shed_tool_confs.keys() ) > 1:
- shed_tool_conf_select_field = build_shed_tool_conf_select_field( trans )
- shed_tool_conf = None
- else:
- shed_tool_conf = trans.app.toolbox.shed_tool_confs.keys()[0].lstrip( './' )
- shed_tool_conf_select_field = None
- tool_panel_section_select_field = build_tool_panel_section_select_field( trans )
- return trans.fill_template( '/admin/select_tool_panel_section.mako',
- tool_shed_url=tool_shed_url,
- repository_name=repository_name,
- changeset_revision=changeset_revision,
- repository_clone_url=repository_clone_url,
- shed_tool_conf=shed_tool_conf,
- shed_tool_conf_select_field=shed_tool_conf_select_field,
- tool_panel_section_select_field=tool_panel_section_select_field,
- message=message,
- status=status )
- def __handle_missing_data_table_entry( self, trans, tool_path, sample_files, repository_tools_tups ):
- # Inspect each tool to see if any have input parameters that are dynamically
- # generated select lists that require entries in the tool_data_table_conf.xml file.
- missing_data_table_entry = False
- for index, repository_tools_tup in enumerate( repository_tools_tups ):
- tup_path, repository_tool = repository_tools_tup
- if repository_tool.params_with_missing_data_table_entry:
- missing_data_table_entry = True
- break
- if missing_data_table_entry:
- # The repository must contain a tool_data_table_conf.xml.sample file that includes
- # all required entries for all tools in the repository.
- for sample_file in sample_files:
- head, tail = os.path.split( sample_file )
- if tail == 'tool_data_table_conf.xml.sample':
- break
- error, correction_msg = handle_sample_tool_data_table_conf_file( trans, sample_file )
- if error:
- # TODO: Do more here than logging an exception.
- log.debug( exception_msg )
- # Reload the tool into the local list of repository_tools_tups.
- repository_tool = trans.app.toolbox.load_tool( os.path.join( tool_path, tup_path ) )
- repository_tools_tups[ index ] = ( tup_path, repository_tool )
- return repository_tools_tups
- def __handle_missing_index_file( self, trans, tool_path, sample_files, repository_tools_tups ):
- # Inspect each tool to see if it has any input parameters that
- # are dynamically generated select lists that depend on a .loc file.
- missing_files_handled = []
- for index, repository_tools_tup in enumerate( repository_tools_tups ):
- tup_path, repository_tool = repository_tools_tup
- params_with_missing_index_file = repository_tool.params_with_missing_index_file
- for param in params_with_missing_index_file:
- options = param.options
- missing_head, missing_tail = os.path.split( options.missing_index_file )
- if missing_tail not in missing_files_handled:
- # The repository must contain the required xxx.loc.sample file.
- for sample_file in sample_files:
- sample_head, sample_tail = os.path.split( sample_file )
- if sample_tail == '%s.sample' % missing_tail:
- copy_sample_loc_file( trans, sample_file )
- if options.tool_data_table and options.tool_data_table.missing_index_file:
- options.tool_data_table.handle_found_index_file( options.missing_index_file )
- missing_files_handled.append( missing_tail )
- break
- # Reload the tool into the local list of repository_tools_tups.
- repository_tool = trans.app.toolbox.load_tool( os.path.join( tool_path, tup_path ) )
- repository_tools_tups[ index ] = ( tup_path, repository_tool )
- return repository_tools_tups
- def __handle_tool_dependencies( self, current_working_dir, repo_files_dir, repository_tools_tups ):
- # Inspect each tool to see if it includes a "requirement" that refers to a fabric
- # script. For those that do, execute the fabric script to install tool dependencies.
- for index, repository_tools_tup in enumerate( repository_tools_tups ):
- tup_path, repository_tool = repository_tools_tup
- for requirement in repository_tool.requirements:
- if requirement.type == 'fabfile':
- log.debug( 'Executing fabric script to install dependencies for tool "%s"...' % repository_tool.name )
- fabfile = requirement.fabfile
- method = requirement.method
- # Find the relative path to the fabfile.
- relative_fabfile_path = None
- for root, dirs, files in os.walk( repo_files_dir ):
- for name in files:
- if name == fabfile:
- relative_fabfile_path = os.path.join( root, name )
- break
- if relative_fabfile_path:
- # cmd will look something like: fab -f fabfile.py install_bowtie
- cmd = 'fab -f %s %s' % ( relative_fabfile_path, method )
- tmp_name = tempfile.NamedTemporaryFile().name
- tmp_stderr = open( tmp_name, 'wb' )
- os.chdir( repo_files_dir )
- proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
- returncode = proc.wait()
- os.chdir( current_working_dir )
- tmp_stderr.close()
- if returncode != 0:
- # TODO: do something more here than logging the problem.
- tmp_stderr = open( tmp_name, 'rb' )
- error = tmp_stderr.read()
- tmp_stderr.close()
- log.debug( 'Problem installing dependencies for tool "%s"\n%s' % ( repository_tool.name, error ) )
- def __get_repository_tools_and_sample_files( self, trans, tool_path, repo_files_dir ):
- # The sample_files list contains all files whose name ends in .sample
- sample_files = []
- # The repository_tools_tups list contains tuples of ( relative_path_to_tool_config, tool ) pairs
- repository_tools_tups = []
- for root, dirs, files in os.walk( repo_files_dir ):
- if not root.find( '.hg' ) >= 0 and not root.find( 'hgrc' ) >= 0:
- if '.hg' in dirs:
- # Don't visit .hg directories - should be impossible since we don't
- # allow uploaded archives that contain .hg dirs, but just in case...
- dirs.remove( '.hg' )
- if 'hgrc' in files:
- # Don't include hgrc files in commit.
- files.remove( 'hgrc' )
- # Find all special .sample files first.
- for name in files:
- if name.endswith( '.sample' ):
- sample_files.append( os.path.abspath( os.path.join( root, name ) ) )
- for name in files:
- # Find all tool configs.
- if name.endswith( '.xml' ):
- relative_path = os.path.join( root, name )
- full_path = os.path.abspath( os.path.join( root, name ) )
- try:
- repository_tool = trans.app.toolbox.load_tool( full_path )
- if repository_tool:
- # At this point, we need to lstrip tool_path from relative_path.
- tup_path = relative_path.replace( tool_path, '' ).lstrip( '/' )
- repository_tools_tups.append( ( tup_path, repository_tool ) )
- except Exception, e:
- # We have an invalid .xml file, so not a tool config.
- log.debug( "Ignoring invalid tool config (%s). Error: %s" % ( str( relative_path ), str( e ) ) )
- return sample_files, repository_tools_tups
- def __add_shed_tool_conf_entry( self, trans, shed_tool_conf, new_tool_section ):
- # Add an entry in the shed_tool_conf file. An entry looks something like:
- # <section name="Filter and Sort" id="filter">
- # <tool file="filter/filtering.xml" guid="toolshed.g2.bx.psu.edu/repos/test/filter/1.0.2"/>
- # </section>
- # Make a backup of the hgweb.config file since we're going to be changing it.
- if not os.path.exists( shed_tool_conf ):
- output = open( shed_tool_conf, 'w' )
- output.write( '<?xml version="1.0"?>\n' )
- output.write( '<toolbox tool_path="%s">\n' % tool_path )
- output.write( '</toolbox>\n' )
- output.close()
- self.__make_shed_tool_conf_copy( trans, shed_tool_conf )
- tmp_fd, tmp_fname = tempfile.mkstemp()
- new_shed_tool_conf = open( tmp_fname, 'wb' )
- for i, line in enumerate( open( shed_tool_conf ) ):
- if line.startswith( '</toolbox>' ):
- # We're at the end of the original config file, so add our entry.
- new_shed_tool_conf.write( new_tool_section )
- new_shed_tool_conf.write( line )
- else:
- new_shed_tool_conf.write( line )
- new_shed_tool_conf.close()
- shutil.move( tmp_fname, os.path.abspath( shed_tool_conf ) )
- def __make_shed_tool_conf_copy( self, trans, shed_tool_conf ):
- # Make a backup of the shed_tool_conf file.
- today = date.today()
- backup_date = today.strftime( "%Y_%m_%d" )
- shed_tool_conf_copy = '%s/%s_%s_backup' % ( trans.app.config.root, shed_tool_conf, backup_date )
- shutil.copy( os.path.abspath( shed_tool_conf ), os.path.abspath( shed_tool_conf_copy ) )
- def __clean_tool_shed_url( self, tool_shed_url ):
- if tool_shed_url.find( ':' ) > 0:
- # Eliminate the port, if any, since it will result in an invalid directory name.
- return tool_shed_url.split( ':' )[ 0 ]
- return tool_shed_url.rstrip( '/' )
- def __clean_repository_clone_url( self, repository_clone_url ):
- if repository_clone_url.find( '@' ) > 0:
- # We have an url that includes an authenticated user, something like:
- # http://test@bx.psu.edu:9009/repos/some_username/column
- items = repository_clone_url.split( '@' )
- tmp_url = items[ 1 ]
- elif repository_clone_url.find( '\/\/' ) > 0:
- # We have an url that includes only a protocol, something like:
- # http://bx.psu.edu:9009/repos/some_username/column
- items = repository_clone_url.split( '\/\/' )
- tmp_url = items[ 1 ]
- else:
- tmp_url = repository_clone_url
- return tmp_url
- def __get_repository_owner( self, cleaned_repository_url ):
- items = cleaned_repository_url.split( 'repos' )
- repo_path = items[ 1 ]
- return repo_path.lstrip( '/' ).split( '/' )[ 0 ]
- def __generate_tool_path( self, repository_clone_url, changeset_revision ):
- """
- Generate a tool path that guarantees repositories with the same name will always be installed
- in different directories. The tool path will be of the form:
- <tool shed url>/repos/<repository owner>/<repository name>/<changeset revision>
- http://test@bx.psu.edu:9009/repos/test/filter
- """
- tmp_url = self.__clean_repository_clone_url( repository_clone_url )
- # Now tmp_url is something like: bx.psu.edu:9009/repos/some_username/column
- items = tmp_url.split( 'repos' )
- tool_shed_url = items[ 0 ]
- repo_path = items[ 1 ]
- tool_shed_url = self.__clean_tool_shed_url( tool_shed_url )
- return '%s/repos%s/%s' % ( tool_shed_url, repo_path, changeset_revision )
- def __generate_tool_guid( self, repository_clone_url, tool ):
- """
- Generate a guid for the installed tool. It is critical that this guid matches the guid for
- the tool in the Galaxy tool shed from which it is being installed. The form of the guid is
- <tool shed host>/repos/<repository owner>/<repository name>/<tool id>/<tool version>
- """
- tmp_url = self.__clean_repository_clone_url( repository_clone_url )
- return '%s/%s/%s' % ( tmp_url, tool.id, tool.version )
- def __generate_tool_panel_section( self, repository_name, repository_clone_url, changeset_revision, tool_section, repository_tools_tups ):
- """
- Write an in-memory tool panel section so we can load it into the tool panel and then
- append it to the appropriate shed tool config.
- TODO: re-write using ElementTree.
- """
- tmp_url = self.__clean_repository_clone_url( repository_clone_url )
- section_str = ''
- section_str += ' <section name="%s" id="%s">\n' % ( tool_section.name, tool_section.id )
- for repository_tool_tup in repository_tools_tups:
- tool_file_path, tool = repository_tool_tup
- guid = self.__generate_tool_guid( repository_clone_url, tool )
- section_str += ' <tool file="%s" guid="%s">\n' % ( tool_file_path, guid )
- section_str += ' <tool_shed>%s</tool_shed>\n' % tmp_url.split( 'repos' )[ 0 ].rstrip( '/' )
- section_str += ' <repository_name>%s</repository_name>\n' % repository_name
- section_str += ' <repository_owner>%s</repository_owner>\n' % self.__get_repository_owner( tmp_url )
- section_str += ' <changeset_revision>%s</changeset_revision>\n' % changeset_revision
- section_str += ' <id>%s</id>\n' % tool.id
- section_str += ' <version>%s</version>\n' % tool.version
- section_str += ' </tool>\n'
- section_str += ' </section>\n'
- return section_str
## ---- Utility methods -------------------------------------------------------
-def build_shed_tool_conf_select_field( trans ):
- """Build a SelectField whose options are the keys in trans.app.toolbox.shed_tool_confs."""
- options = []
- for shed_tool_conf_filename, tool_path in trans.app.toolbox.shed_tool_confs.items():
- options.append( ( shed_tool_conf_filename.lstrip( './' ), shed_tool_conf_filename ) )
- select_field = SelectField( name='shed_tool_conf' )
- for option_tup in options:
- select_field.add_option( option_tup[0], option_tup[1] )
- return select_field
-def build_tool_panel_section_select_field( trans ):
- """Build a SelectField whose options are the sections of the current in-memory toolbox."""
- options = []
- for k, tool_section in trans.app.toolbox.tool_panel.items():
- options.append( ( tool_section.name, tool_section.id ) )
- select_field = SelectField( name='tool_panel_section', display='radio' )
- for option_tup in options:
- select_field.add_option( option_tup[0], option_tup[1] )
- return select_field
def copy_sample_loc_file( trans, filename ):
"""Copy xxx.loc.sample to ~/tool-data/xxx.loc.sample and ~/tool-data/xxx.loc"""
head, sample_loc_file = os.path.split( filename )
@@ -2757,6 +2408,12 @@
if not user:
return trans.show_error_message( "User not found for id (%s)" % str( id ) )
return user
+def get_user_by_username( trans, username ):
+ """Get a user from the database by username"""
+ # TODO: Add exception handling here.
+ return trans.sa_session.query( trans.model.User ) \
+ .filter( trans.model.User.table.c.username == username ) \
+ .one()
def get_role( trans, id ):
"""Get a Role from the database by id."""
# Load user from database
--- a/lib/galaxy/web/controllers/admin.py Fri Sep 30 09:26:22 2011 -0400
+++ b/lib/galaxy/web/controllers/admin.py Fri Sep 30 09:48:56 2011 -0400
@@ -384,14 +384,66 @@
preserve_state = False
use_paging = True
+class RepositoryListGrid( grids.Grid ):
+ class NameColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.name
+ class DescriptionColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.description
+ class OwnerColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.owner
+ class RevisionColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.changeset_revision
+ class ToolShedColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.tool_shed
+ # Grid definition
+ title = "Tool shed repositories"
+ model_class = model.ToolShedRepository
+ template='/admin/tool_shed_repository/grid.mako'
+ default_sort_key = "name"
+ columns = [
+ NameColumn( "Name",
+ key="name",
+ attach_popup=True ),
+ DescriptionColumn( "Description" ),
+ OwnerColumn( "Owner" ),
+ RevisionColumn( "Revision" ),
+ ToolShedColumn( "Tool shed" ),
+ # Columns that are valid for filtering but are not visible.
+ grids.DeletedColumn( "Deleted",
+ key="deleted",
+ visible=False,
+ filterable="advanced" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name",
+ cols_to_filter=[ columns[0] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ operations = [ grids.GridOperation( "Get updates",
+ allow_multiple=False,
+ condition=( lambda item: not item.deleted ),
+ async_compatible=False ) ]
+ standard_filters = []
+ default_filter = dict( deleted="False" )
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = True
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( self.model_class )
+
class AdminGalaxy( BaseUIController, Admin, AdminActions, UsesQuota, QuotaParamParser ):
user_list_grid = UserListGrid()
role_list_grid = RoleListGrid()
group_list_grid = GroupListGrid()
quota_list_grid = QuotaListGrid()
+ repository_list_grid = RepositoryListGrid()
- # Galaxy Quota Stuff
@web.expose
@web.require_admin
def quotas( self, trans, **kwargs ):
@@ -417,7 +469,6 @@
return self.edit_quota( trans, **kwargs )
# Render the list view
return self.quota_list_grid( trans, **kwargs )
-
@web.expose
@web.require_admin
def create_quota( self, trans, **kwd ):
@@ -464,7 +515,6 @@
out_groups=params.out_groups,
message=params.message,
status=params.status )
-
@web.expose
@web.require_admin
def rename_quota( self, trans, **kwd ):
@@ -478,7 +528,6 @@
webapp=params.webapp,
message=params.message,
status=params.status )
-
@web.expose
@web.require_admin
def manage_users_and_groups_for_quota( self, trans, **kwd ):
@@ -513,7 +562,6 @@
webapp=params.webapp,
message=params.message,
status=params.status )
-
@web.expose
@web.require_admin
def edit_quota( self, trans, **kwd ):
@@ -527,7 +575,6 @@
webapp=params.webapp,
message=params.message,
status=params.status )
-
@web.expose
@web.require_admin
def set_quota_default( self, trans, **kwd ):
@@ -546,7 +593,6 @@
webapp=params.webapp,
message=params.message,
status=params.status )
-
@web.expose
@web.require_admin
def unset_quota_default( self, trans, **kwd ):
@@ -558,8 +604,6 @@
webapp=params.webapp,
message=util.sanitize_text( params.message ),
status='error' ) )
-
-
@web.expose
@web.require_admin
def mark_quota_deleted( self, trans, **kwd ):
@@ -571,7 +615,6 @@
webapp=params.webapp,
message=util.sanitize_text( params.message ),
status='error' ) )
-
@web.expose
@web.require_admin
def undelete_quota( self, trans, **kwd ):
@@ -583,7 +626,6 @@
webapp=params.webapp,
message=util.sanitize_text( params.message ),
status='error' ) )
-
@web.expose
@web.require_admin
def purge_quota( self, trans, **kwd ):
@@ -595,7 +637,6 @@
webapp=params.webapp,
message=util.sanitize_text( params.message ),
status='error' ) )
-
def _quota_op( self, trans, do_op, op_method, kwd, listify=False ):
params = self.get_quota_params( kwd )
if listify:
@@ -633,3 +674,488 @@
params.message = e.err_msg
params.status = e.type
return quota, params
+ @web.expose
+ @web.require_admin
+ def browse_repositories( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd.pop('operation').lower()
+ if operation == "get updates":
+ return self.check_for_updates( trans, **kwd )
+ # Render the list view
+ return self.repository_list_grid( trans, **kwd )
+ @web.expose
+ @web.require_admin
+ def browse_tool_shed( self, trans, **kwd ):
+ tool_shed_url = kwd[ 'tool_shed_url' ]
+ galaxy_url = trans.request.host
+ url = '%s/repository/browse_downloadable_repositories?galaxy_url=%s&webapp=community' % ( tool_shed_url, galaxy_url )
+ return trans.response.send_redirect( url )
+ @web.expose
+ @web.require_admin
+ def install_tool_shed_repository( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ tool_shed_url = kwd[ 'tool_shed_url' ]
+ name = kwd[ 'name' ]
+ description = kwd[ 'description' ]
+ changeset_revision = kwd[ 'changeset_revision' ]
+ repository_clone_url = kwd[ 'repository_clone_url' ]
+ if kwd.get( 'select_tool_panel_section_button', False ):
+ shed_tool_conf = kwd[ 'shed_tool_conf' ]
+ # Get the tool path.
+ for k, tool_path in trans.app.toolbox.shed_tool_confs.items():
+ if k == shed_tool_conf:
+ break
+ if 'tool_panel_section' in kwd:
+ section_key = 'section_%s' % kwd[ 'tool_panel_section' ]
+ tool_section = trans.app.toolbox.tool_panel[ section_key ]
+ # Clone the repository to the configured location.
+ current_working_dir = os.getcwd()
+ clone_dir = os.path.join( tool_path, self.__generate_tool_path( repository_clone_url, changeset_revision ) )
+ if os.path.exists( clone_dir ):
+ # Repository and revision has already been cloned.
+ # TODO: implement the ability to re-install or revert an existing repository.
+ message = 'Revision <b>%s</b> of repository <b>%s</b> has already been installed. Updating an existing repository is not yet supported.' % \
+ ( changeset_revision, name )
+ status = 'error'
+ else:
+ os.makedirs( clone_dir )
+ log.debug( 'Cloning %s...' % repository_clone_url )
+ cmd = 'hg clone %s' % repository_clone_url
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( clone_dir )
+ proc = subprocess.Popen( args=cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode == 0:
+ # Add a new record to the tool_shed_repository table.
+ tool_shed_repository = self.__create_tool_shed_repository( trans,
+ name,
+ description,
+ changeset_revision,
+ repository_clone_url )
+ # Update the cloned repository to changeset_revision.
+ repo_files_dir = os.path.join( clone_dir, name )
+ log.debug( 'Updating cloned repository to revision "%s"...' % changeset_revision )
+ cmd = 'hg update -r %s' % changeset_revision
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( repo_files_dir )
+ proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode == 0:
+ sample_files, repository_tools_tups = self.__get_repository_tools_and_sample_files( trans, tool_path, repo_files_dir )
+ if repository_tools_tups:
+ # Handle missing data table entries for tool parameters that are dynamically generated select lists.
+ repository_tools_tups = self.__handle_missing_data_table_entry( trans, tool_path, sample_files, repository_tools_tups )
+ # Handle missing index files for tool parameters that are dynamically generated select lists.
+ repository_tools_tups = self.__handle_missing_index_file( trans, tool_path, sample_files, repository_tools_tups )
+ # Handle tools that use fabric scripts to install dependencies.
+ self.__handle_tool_dependencies( current_working_dir, repo_files_dir, repository_tools_tups )
+ # Generate an in-memory tool conf section that includes the new tools.
+ new_tool_section = self.__generate_tool_panel_section( name,
+ repository_clone_url,
+ changeset_revision,
+ tool_section,
+ repository_tools_tups )
+ # Create a temporary file to persist the in-memory tool section
+ # TODO: Figure out how to do this in-memory using xml.etree.
+ tmp_name = tempfile.NamedTemporaryFile().name
+ persisted_new_tool_section = open( tmp_name, 'wb' )
+ persisted_new_tool_section.write( new_tool_section )
+ persisted_new_tool_section.close()
+ # Parse the persisted tool panel section
+ tree = ElementTree.parse( tmp_name )
+ root = tree.getroot()
+ ElementInclude.include( root )
+ # Load the tools in the section into the tool panel.
+ trans.app.toolbox.load_section_tag_set( root, trans.app.toolbox.tool_panel, tool_path )
+ # Remove the temporary file
+ try:
+ os.unlink( tmp_name )
+ except:
+ pass
+ # Append the new section to the shed_tool_config file.
+ self.__add_shed_tool_conf_entry( trans, shed_tool_conf, new_tool_section )
+ message = 'Revision <b>%s</b> of repository <b>%s</b> has been installed in tool panel section <b>%s</b>.' % \
+ ( changeset_revision, name, tool_section.name )
+ return trans.show_ok_message( message )
+ else:
+ tmp_stderr = open( tmp_name, 'rb' )
+ message = tmp_stderr.read()
+ tmp_stderr.close()
+ status = 'error'
+ else:
+ tmp_stderr = open( tmp_name, 'rb' )
+ message = tmp_stderr.read()
+ tmp_stderr.close()
+ status = 'error'
+ else:
+ message = 'Choose the section in your tool panel to contain the installed tools.'
+ status = 'error'
+ if len( trans.app.toolbox.shed_tool_confs.keys() ) > 1:
+ shed_tool_conf_select_field = build_shed_tool_conf_select_field( trans )
+ shed_tool_conf = None
+ else:
+ shed_tool_conf = trans.app.toolbox.shed_tool_confs.keys()[0].lstrip( './' )
+ shed_tool_conf_select_field = None
+ tool_panel_section_select_field = build_tool_panel_section_select_field( trans )
+ return trans.fill_template( '/admin/select_tool_panel_section.mako',
+ tool_shed_url=tool_shed_url,
+ name=name,
+ description=description,
+ changeset_revision=changeset_revision,
+ repository_clone_url=repository_clone_url,
+ shed_tool_conf=shed_tool_conf,
+ shed_tool_conf_select_field=shed_tool_conf_select_field,
+ tool_panel_section_select_field=tool_panel_section_select_field,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_admin
+ def check_for_updates( self, trans, **kwd ):
+ params = util.Params( kwd )
+ repository_id = params.get( 'id', None )
+ repository = get_repository( trans, repository_id )
+ galaxy_url = trans.request.host
+ # Send a request to the relevant tool shed to see if there are any updates.
+ # TODO: support https in the following url.
+ url = 'http://%s/repository/check_for_updates?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s&webapp=community' % \
+ ( repository.tool_shed, galaxy_url, repository.name, repository.owner, repository.changeset_revision )
+ return trans.response.send_redirect( url )
+ @web.expose
+ @web.require_admin
+ def update_to_changeset_revision( self, trans, **kwd ):
+ """Update a cloned repository to the latest revision possible."""
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ tool_shed_url = kwd[ 'tool_shed_url' ]
+ name = params.get( 'name', None )
+ owner = params.get( 'owner', None )
+ changeset_revision = params.get( 'changeset_revision', None )
+ latest_changeset_revision = params.get( 'latest_changeset_revision', None )
+ if changeset_revision and latest_changeset_revision:
+ if changeset_revision == latest_changeset_revision:
+ message = "The cloned tool shed repository named '%s' is current (there are no updates available)." % name
+ else:
+ repository = get_repository_by_name_owner_changeset_revision( trans, name, owner, changeset_revision )
+ current_working_dir = os.getcwd()
+ # Get the directory where the repository is cloned.
+ cleaned_tool_shed_url = self.__clean_tool_shed_url( tool_shed_url )
+ partial_cloned_dir = '%s/repos/%s/%s/%s' % ( cleaned_tool_shed_url, owner, name, changeset_revision )
+ # Get the relative tool installation paths from each of the shed tool configs.
+ shed_tool_confs = trans.app.toolbox.shed_tool_confs
+ relative_cloned_dir = None
+ # The shed_tool_confs dictionary contains shed_conf_filename : tool_path pairs.
+ for shed_conf_filename, tool_path in shed_tool_confs.items():
+ relative_cloned_dir = os.path.join( tool_path, partial_cloned_dir )
+ if os.path.isdir( relative_cloned_dir ):
+ break
+ if relative_cloned_dir:
+ # Update the cloned repository to changeset_revision.
+ repo_files_dir = os.path.join( relative_cloned_dir, name )
+ log.debug( "Updating cloned repository named '%s' from revision '%s' to revision '%s'..." % \
+ ( name, changeset_revision, latest_changeset_revision ) )
+ cmd = 'hg pull'
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( repo_files_dir )
+ proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode == 0:
+ cmd = 'hg update -r %s' % latest_changeset_revision
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( repo_files_dir )
+ proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode == 0:
+ # Update the repository changeset_revision in the database.
+ repository.changeset_revision = latest_changeset_revision
+ trans.sa_session.add( repository )
+ trans.sa_session.flush()
+ message = "The cloned repository named '%s' has been updated to change set revision '%s'." % \
+ ( name, latest_changeset_revision )
+ else:
+ tmp_stderr = open( tmp_name, 'rb' )
+ message = tmp_stderr.read()
+ tmp_stderr.close()
+ status = 'error'
+ else:
+ tmp_stderr = open( tmp_name, 'rb' )
+ message = tmp_stderr.read()
+ tmp_stderr.close()
+ status = 'error'
+ else:
+ message = "The directory containing the cloned repository named '%s' cannot be found." % name
+ status = 'error'
+ else:
+ message = "The latest changeset revision could not be retrieved for the repository named '%s'." % name
+ status = 'error'
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='browse_repositories',
+ message=message,
+ status=status ) )
+ def __handle_missing_data_table_entry( self, trans, tool_path, sample_files, repository_tools_tups ):
+ # Inspect each tool to see if any have input parameters that are dynamically
+ # generated select lists that require entries in the tool_data_table_conf.xml file.
+ missing_data_table_entry = False
+ for index, repository_tools_tup in enumerate( repository_tools_tups ):
+ tup_path, repository_tool = repository_tools_tup
+ if repository_tool.params_with_missing_data_table_entry:
+ missing_data_table_entry = True
+ break
+ if missing_data_table_entry:
+ # The repository must contain a tool_data_table_conf.xml.sample file that includes
+ # all required entries for all tools in the repository.
+ for sample_file in sample_files:
+ head, tail = os.path.split( sample_file )
+ if tail == 'tool_data_table_conf.xml.sample':
+ break
+ error, correction_msg = handle_sample_tool_data_table_conf_file( trans, sample_file )
+ if error:
+ # TODO: Do more here than logging an exception.
+ log.debug( exception_msg )
+ # Reload the tool into the local list of repository_tools_tups.
+ repository_tool = trans.app.toolbox.load_tool( os.path.join( tool_path, tup_path ) )
+ repository_tools_tups[ index ] = ( tup_path, repository_tool )
+ return repository_tools_tups
+ def __handle_missing_index_file( self, trans, tool_path, sample_files, repository_tools_tups ):
+ # Inspect each tool to see if it has any input parameters that
+ # are dynamically generated select lists that depend on a .loc file.
+ missing_files_handled = []
+ for index, repository_tools_tup in enumerate( repository_tools_tups ):
+ tup_path, repository_tool = repository_tools_tup
+ params_with_missing_index_file = repository_tool.params_with_missing_index_file
+ for param in params_with_missing_index_file:
+ options = param.options
+ missing_head, missing_tail = os.path.split( options.missing_index_file )
+ if missing_tail not in missing_files_handled:
+ # The repository must contain the required xxx.loc.sample file.
+ for sample_file in sample_files:
+ sample_head, sample_tail = os.path.split( sample_file )
+ if sample_tail == '%s.sample' % missing_tail:
+ copy_sample_loc_file( trans, sample_file )
+ if options.tool_data_table and options.tool_data_table.missing_index_file:
+ options.tool_data_table.handle_found_index_file( options.missing_index_file )
+ missing_files_handled.append( missing_tail )
+ break
+ # Reload the tool into the local list of repository_tools_tups.
+ repository_tool = trans.app.toolbox.load_tool( os.path.join( tool_path, tup_path ) )
+ repository_tools_tups[ index ] = ( tup_path, repository_tool )
+ return repository_tools_tups
+ def __handle_tool_dependencies( self, current_working_dir, repo_files_dir, repository_tools_tups ):
+ # Inspect each tool to see if it includes a "requirement" that refers to a fabric
+ # script. For those that do, execute the fabric script to install tool dependencies.
+ for index, repository_tools_tup in enumerate( repository_tools_tups ):
+ tup_path, repository_tool = repository_tools_tup
+ for requirement in repository_tool.requirements:
+ if requirement.type == 'fabfile':
+ log.debug( 'Executing fabric script to install dependencies for tool "%s"...' % repository_tool.name )
+ fabfile = requirement.fabfile
+ method = requirement.method
+ # Find the relative path to the fabfile.
+ relative_fabfile_path = None
+ for root, dirs, files in os.walk( repo_files_dir ):
+ for name in files:
+ if name == fabfile:
+ relative_fabfile_path = os.path.join( root, name )
+ break
+ if relative_fabfile_path:
+ # cmd will look something like: fab -f fabfile.py install_bowtie
+ cmd = 'fab -f %s %s' % ( relative_fabfile_path, method )
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( repo_files_dir )
+ proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode != 0:
+ # TODO: do something more here than logging the problem.
+ tmp_stderr = open( tmp_name, 'rb' )
+ error = tmp_stderr.read()
+ tmp_stderr.close()
+ log.debug( 'Problem installing dependencies for tool "%s"\n%s' % ( repository_tool.name, error ) )
+ def __get_repository_tools_and_sample_files( self, trans, tool_path, repo_files_dir ):
+ # The sample_files list contains all files whose name ends in .sample
+ sample_files = []
+ # The repository_tools_tups list contains tuples of ( relative_path_to_tool_config, tool ) pairs
+ repository_tools_tups = []
+ for root, dirs, files in os.walk( repo_files_dir ):
+ if not root.find( '.hg' ) >= 0 and not root.find( 'hgrc' ) >= 0:
+ if '.hg' in dirs:
+ # Don't visit .hg directories - should be impossible since we don't
+ # allow uploaded archives that contain .hg dirs, but just in case...
+ dirs.remove( '.hg' )
+ if 'hgrc' in files:
+ # Don't include hgrc files in commit.
+ files.remove( 'hgrc' )
+ # Find all special .sample files first.
+ for name in files:
+ if name.endswith( '.sample' ):
+ sample_files.append( os.path.abspath( os.path.join( root, name ) ) )
+ for name in files:
+ # Find all tool configs.
+ if name.endswith( '.xml' ):
+ relative_path = os.path.join( root, name )
+ full_path = os.path.abspath( os.path.join( root, name ) )
+ try:
+ repository_tool = trans.app.toolbox.load_tool( full_path )
+ if repository_tool:
+ # At this point, we need to lstrip tool_path from relative_path.
+ tup_path = relative_path.replace( tool_path, '' ).lstrip( '/' )
+ repository_tools_tups.append( ( tup_path, repository_tool ) )
+ except Exception, e:
+ # We have an invalid .xml file, so not a tool config.
+ log.debug( "Ignoring invalid tool config (%s). Error: %s" % ( str( relative_path ), str( e ) ) )
+ return sample_files, repository_tools_tups
+ def __create_tool_shed_repository( self, trans, name, description, changeset_revision, repository_clone_url ):
+ tmp_url = self.__clean_repository_clone_url( repository_clone_url )
+ tool_shed = tmp_url.split( 'repos' )[ 0 ].rstrip( '/' )
+ owner = self.__get_repository_owner( tmp_url )
+ tool_shed_repository = trans.model.ToolShedRepository( tool_shed=tool_shed,
+ name=name,
+ description=description,
+ owner=owner,
+ changeset_revision=changeset_revision )
+ trans.sa_session.add( tool_shed_repository )
+ trans.sa_session.flush()
+ def __add_shed_tool_conf_entry( self, trans, shed_tool_conf, new_tool_section ):
+ # Add an entry in the shed_tool_conf file. An entry looks something like:
+ # <section name="Filter and Sort" id="filter">
+ # <tool file="filter/filtering.xml" guid="toolshed.g2.bx.psu.edu/repos/test/filter/1.0.2"/>
+ # </section>
+ # Make a backup of the hgweb.config file since we're going to be changing it.
+ if not os.path.exists( shed_tool_conf ):
+ output = open( shed_tool_conf, 'w' )
+ output.write( '<?xml version="1.0"?>\n' )
+ output.write( '<toolbox tool_path="%s">\n' % tool_path )
+ output.write( '</toolbox>\n' )
+ output.close()
+ self.__make_shed_tool_conf_copy( trans, shed_tool_conf )
+ tmp_fd, tmp_fname = tempfile.mkstemp()
+ new_shed_tool_conf = open( tmp_fname, 'wb' )
+ for i, line in enumerate( open( shed_tool_conf ) ):
+ if line.startswith( '</toolbox>' ):
+ # We're at the end of the original config file, so add our entry.
+ new_shed_tool_conf.write( new_tool_section )
+ new_shed_tool_conf.write( line )
+ else:
+ new_shed_tool_conf.write( line )
+ new_shed_tool_conf.close()
+ shutil.move( tmp_fname, os.path.abspath( shed_tool_conf ) )
+ def __make_shed_tool_conf_copy( self, trans, shed_tool_conf ):
+ # Make a backup of the shed_tool_conf file.
+ today = date.today()
+ backup_date = today.strftime( "%Y_%m_%d" )
+ shed_tool_conf_copy = '%s/%s_%s_backup' % ( trans.app.config.root, shed_tool_conf, backup_date )
+ shutil.copy( os.path.abspath( shed_tool_conf ), os.path.abspath( shed_tool_conf_copy ) )
+ def __clean_tool_shed_url( self, tool_shed_url ):
+ if tool_shed_url.find( ':' ) > 0:
+ # Eliminate the port, if any, since it will result in an invalid directory name.
+ return tool_shed_url.split( ':' )[ 0 ]
+ return tool_shed_url.rstrip( '/' )
+ def __clean_repository_clone_url( self, repository_clone_url ):
+ if repository_clone_url.find( '@' ) > 0:
+ # We have an url that includes an authenticated user, something like:
+ # http://test@bx.psu.edu:9009/repos/some_username/column
+ items = repository_clone_url.split( '@' )
+ tmp_url = items[ 1 ]
+ elif repository_clone_url.find( '\/\/' ) > 0:
+ # We have an url that includes only a protocol, something like:
+ # http://bx.psu.edu:9009/repos/some_username/column
+ items = repository_clone_url.split( '\/\/' )
+ tmp_url = items[ 1 ]
+ else:
+ tmp_url = repository_clone_url
+ return tmp_url
+ def __get_repository_owner( self, cleaned_repository_url ):
+ items = cleaned_repository_url.split( 'repos' )
+ repo_path = items[ 1 ]
+ return repo_path.lstrip( '/' ).split( '/' )[ 0 ]
+ def __generate_tool_path( self, repository_clone_url, changeset_revision ):
+ """
+ Generate a tool path that guarantees repositories with the same name will always be installed
+ in different directories. The tool path will be of the form:
+ <tool shed url>/repos/<repository owner>/<repository name>/<changeset revision>
+ http://test@bx.psu.edu:9009/repos/test/filter
+ """
+ tmp_url = self.__clean_repository_clone_url( repository_clone_url )
+ # Now tmp_url is something like: bx.psu.edu:9009/repos/some_username/column
+ items = tmp_url.split( 'repos' )
+ tool_shed_url = items[ 0 ]
+ repo_path = items[ 1 ]
+ tool_shed_url = self.__clean_tool_shed_url( tool_shed_url )
+ return '%s/repos%s/%s' % ( tool_shed_url, repo_path, changeset_revision )
+ def __generate_tool_guid( self, repository_clone_url, tool ):
+ """
+ Generate a guid for the installed tool. It is critical that this guid matches the guid for
+ the tool in the Galaxy tool shed from which it is being installed. The form of the guid is
+ <tool shed host>/repos/<repository owner>/<repository name>/<tool id>/<tool version>
+ """
+ tmp_url = self.__clean_repository_clone_url( repository_clone_url )
+ return '%s/%s/%s' % ( tmp_url, tool.id, tool.version )
+ def __generate_tool_panel_section( self, repository_name, repository_clone_url, changeset_revision, tool_section, repository_tools_tups ):
+ """
+ Write an in-memory tool panel section so we can load it into the tool panel and then
+ append it to the appropriate shed tool config.
+ TODO: re-write using ElementTree.
+ """
+ tmp_url = self.__clean_repository_clone_url( repository_clone_url )
+ section_str = ''
+ section_str += ' <section name="%s" id="%s">\n' % ( tool_section.name, tool_section.id )
+ for repository_tool_tup in repository_tools_tups:
+ tool_file_path, tool = repository_tool_tup
+ guid = self.__generate_tool_guid( repository_clone_url, tool )
+ section_str += ' <tool file="%s" guid="%s">\n' % ( tool_file_path, guid )
+ section_str += ' <tool_shed>%s</tool_shed>\n' % tmp_url.split( 'repos' )[ 0 ].rstrip( '/' )
+ section_str += ' <repository_name>%s</repository_name>\n' % repository_name
+ section_str += ' <repository_owner>%s</repository_owner>\n' % self.__get_repository_owner( tmp_url )
+ section_str += ' <changeset_revision>%s</changeset_revision>\n' % changeset_revision
+ section_str += ' <id>%s</id>\n' % tool.id
+ section_str += ' <version>%s</version>\n' % tool.version
+ section_str += ' </tool>\n'
+ section_str += ' </section>\n'
+ return section_str
+
+## ---- Utility methods -------------------------------------------------------
+
+def build_shed_tool_conf_select_field( trans ):
+ """Build a SelectField whose options are the keys in trans.app.toolbox.shed_tool_confs."""
+ options = []
+ for shed_tool_conf_filename, tool_path in trans.app.toolbox.shed_tool_confs.items():
+ options.append( ( shed_tool_conf_filename.lstrip( './' ), shed_tool_conf_filename ) )
+ select_field = SelectField( name='shed_tool_conf' )
+ for option_tup in options:
+ select_field.add_option( option_tup[0], option_tup[1] )
+ return select_field
+def build_tool_panel_section_select_field( trans ):
+ """Build a SelectField whose options are the sections of the current in-memory toolbox."""
+ options = []
+ for k, tool_section in trans.app.toolbox.tool_panel.items():
+ options.append( ( tool_section.name, tool_section.id ) )
+ select_field = SelectField( name='tool_panel_section', display='radio' )
+ for option_tup in options:
+ select_field.add_option( option_tup[0], option_tup[1] )
+ return select_field
+def get_repository( trans, id ):
+ """Get a tool_shed_repository from the database via id"""
+ return trans.sa_session.query( trans.model.ToolShedRepository ).get( trans.security.decode_id( id ) )
+def get_repository_by_name_owner_changeset_revision( trans, name, owner, changeset_revision ):
+ """Get a repository from the database via name owner and changeset_revision"""
+ return trans.sa_session.query( trans.model.ToolShedRepository ) \
+ .filter( and_( trans.model.ToolShedRepository.table.c.name == name,
+ trans.model.ToolShedRepository.table.c.owner == owner,
+ trans.model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
+ .first()
--- a/lib/galaxy/webapps/community/controllers/common.py Fri Sep 30 09:26:22 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/common.py Fri Sep 30 09:48:56 2011 -0400
@@ -86,6 +86,13 @@
def get_repository( trans, id ):
"""Get a repository from the database via id"""
return trans.sa_session.query( trans.model.Repository ).get( trans.security.decode_id( id ) )
+def get_repository_by_name_and_owner( trans, name, owner ):
+ """Get a repository from the database via name and owner"""
+ user = get_user_by_username( trans, owner )
+ return trans.sa_session.query( trans.model.Repository ) \
+ .filter( and_( trans.model.Repository.table.c.name == name,
+ trans.model.Repository.table.c.user_id == user.id ) ) \
+ .first()
def get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ):
"""Get metadata for a specified repository change set from the database"""
return trans.sa_session.query( trans.model.RepositoryMetadata ) \
@@ -95,6 +102,10 @@
def get_repository_metadata_by_id( trans, id ):
"""Get repository metadata from the database"""
return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) )
+def get_repository_metadata_by_repository_id( trans, id ):
+ """Get all metadata records for a specified repository."""
+ return trans.sa_session.query( trans.model.RepositoryMetadata ) \
+ .filter( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ) )
def get_revision_label( trans, repository, changeset_revision ):
"""
Return a string consisting of the human read-able
@@ -469,7 +480,7 @@
_ui.setconfig( 'ui', 'quiet', True )
return _ui
def get_user( trans, id ):
- """Get a user from the database"""
+ """Get a user from the database by id"""
return trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( id ) )
def handle_email_alerts( trans, repository ):
repo_dir = repository.repo_path
--- a/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 30 09:26:22 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 30 09:48:56 2011 -0400
@@ -341,8 +341,100 @@
tool_shed_url = trans.request.host
repository_clone_url = generate_clone_url( trans, repository_id )
# TODO: support https in the following url.
- url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&repository_name=%s&repository_clone_url=%s&changeset_revision=%s' % \
- ( galaxy_url, tool_shed_url, repository.name, repository_clone_url, changeset_revision )
+ url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&name=%s&description=%s&repository_clone_url=%s&changeset_revision=%s' % \
+ ( galaxy_url, tool_shed_url, repository.name, repository.description, repository_clone_url, changeset_revision )
+ return trans.response.send_redirect( url )
+ @web.expose
+ def check_for_updates( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ # The sender didn't store galaxy_url in a cookie since
+ # this method immediately redirects back to the caller.
+ galaxy_url = kwd[ 'galaxy_url' ]
+ name = params.get( 'name', None )
+ owner = params.get( 'owner', None )
+ changeset_revision = params.get( 'changeset_revision', None )
+ webapp = params.get( 'webapp', None )
+ tool_shed_url = trans.request.host
+ # Start building up the url to redirect back to the calling Galaxy instance.
+ # TODO: support https in the following url.
+ url = 'http://%s/admin/update_to_changeset_revision?tool_shed_url=%s' % ( galaxy_url, tool_shed_url )
+ repository = get_repository_by_name_and_owner( trans, name, owner )
+ #if error:
+ # url += '&message=%s&status=error' % message
+ #else:
+ url += '&name=%s&owner=%s&changeset_revision=%s&latest_changeset_revision=' % \
+ ( repository.name, repository.user.username, changeset_revision )
+ if changeset_revision == repository.tip:
+ # If changeset_revision is the repository tip, then
+ # we know there are no additional updates for the tools.
+ url += repository.tip
+ else:
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans,
+ trans.security.encode_id( repository.id ),
+ changeset_revision )
+ if repository_metadata:
+ # If changeset_revision is in the repository_metadata table for this
+ # repository, then we know there are no additional updates for the tools.
+ url += changeset_revision
+ else:
+ # The changeset_revision column in the repository_metadata table has been
+ # updated with a new changeset_revision value since the repository was cloned.
+ repo_dir = repository.repo_path
+ repo = hg.repository( get_configured_ui(), repo_dir )
+ # Load each tool in the repository's changeset_revision to generate a list of
+ # tool guids, since guids differentiate tools by id and version.
+ ctx = get_changectx_for_changeset( trans, repo, changeset_revision )
+ if ctx is not None:
+ tool_guids = []
+ for filename in ctx:
+ # Find all tool configs in this repository changeset_revision.
+ if filename.endswith( '.xml' ):
+ fctx = ctx[ filename ]
+ # Write the contents of the old tool config to a temporary file.
+ fh = tempfile.NamedTemporaryFile( 'w' )
+ tmp_filename = fh.name
+ fh.close()
+ fh = open( tmp_filename, 'w' )
+ fh.write( fctx.data() )
+ fh.close()
+ try:
+ tool = load_tool( trans, tmp_filename )
+ if tool is not None:
+ tool_guids.append( generate_tool_guid( trans, repository, tool ) )
+ except:
+ # File must not be a valid tool config even though it has a .xml extension.
+ pass
+ try:
+ os.unlink( tmp_filename )
+ except:
+ pass
+ tool_guids.sort()
+ if tool_guids:
+ # Compare our list of tool guids against those in each repository_metadata record
+ # for the repository to find the repository_metadata record with the changeset_revision
+ # value we want to pass back to the caller.
+ found = False
+ for repository_metadata in get_repository_metadata_by_repository_id( trans, trans.security.encode_id( repository.id ) ):
+ metadata = repository_metadata.metadata
+ metadata_tool_guids = []
+ for tool_dict in metadata[ 'tools' ]:
+ metadata_tool_guids.append( tool_dict[ 'guid' ] )
+ metadata_tool_guids.sort()
+ if tool_guids == metadata_tool_guids:
+ # We've found the repository_metadata record whose changeset_revision
+ # value has been updated.
+ url += repository_metadata.changeset_revision
+ found = True
+ break
+ if not found:
+ # There must be a problem in the data, so we'll just send back the received changeset_revision.
+ log.debug( "Possible data corruption - updated repository_metadata cannot be found for repository id %d." % repository.id )
+ url += changeset_revision
+ else:
+ # There are not tools in the changeset_revision, so no tool updates are possible.
+ url += changeset_revision
return trans.response.send_redirect( url )
@web.expose
def browse_repositories( self, trans, **kwd ):
--- a/templates/admin/select_tool_panel_section.mako Fri Sep 30 09:26:22 2011 -0400
+++ b/templates/admin/select_tool_panel_section.mako Fri Sep 30 09:48:56 2011 -0400
@@ -23,9 +23,9 @@
<br/><div class="toolForm">
- <div class="toolFormTitle">Install tools from repository '${repository_name}'</div>
+ <div class="toolFormTitle">Install tools from repository '${name}'</div><div class="toolFormBody">
- <form name="select_tool_panel_section" id="select_tool_panel_section" action="${h.url_for( controller='admin', action='install_tool_shed_repository', tool_shed_url=tool_shed_url, repository_name=repository_name, changeset_revision=changeset_revision, repository_clone_url=repository_clone_url )}" method="post" >
+ <form name="select_tool_panel_section" id="select_tool_panel_section" action="${h.url_for( controller='admin', action='install_tool_shed_repository', tool_shed_url=tool_shed_url, name=name, description=description, changeset_revision=changeset_revision, repository_clone_url=repository_clone_url )}" method="post" >
%if shed_tool_conf_select_field:
<div class="form-row"><label>Shed tool configuration file:</label>
--- a/templates/webapps/galaxy/admin/index.mako Fri Sep 30 09:26:22 2011 -0400
+++ b/templates/webapps/galaxy/admin/index.mako Fri Sep 30 09:48:56 2011 -0400
@@ -62,6 +62,9 @@
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='reload_tool' )}" target="galaxy_main">Reload a tool's configuration</a></div><div class="toolTitle"><a href="${h.url_for( controller='admin', action='memdump' )}" target="galaxy_main">Profile memory usage</a></div><div class="toolTitle"><a href="${h.url_for( controller='admin', action='jobs' )}" target="galaxy_main">Manage jobs</a></div>
+ %if cloned_repositories:
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_repositories' )}" target="galaxy_main">Manage cloned tool shed repositories</a></div>
+ %endif
</div></div>
%if trans.app.tool_shed_registry and trans.app.tool_shed_registry.tool_sheds:
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
30 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/3541bcdb236c/
changeset: 3541bcdb236c
user: jgoecks
date: 2011-09-30 15:26:22
summary: Trackster improvements: (a) groups now have menus and can be renamed and deleted; (b) mode is again saved and restored; (c) tracks can be added directly to groups rather than only the view; running a tool inside trackster creates its own group and places new tracks in group.
affected #: 7 files (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Thu Sep 29 16:45:19 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 30 09:26:22 2011 -0400
@@ -337,6 +337,7 @@
"hda_ldda": track_dict.get("hda_ldda", "hda"),
"dataset_id": trans.security.encode_id( dataset.id ),
"prefs": prefs,
+ "mode": track_dict.get( 'mode', 'Auto' ),
"filters": track_data_provider.get_filters(),
"tool": get_tool_def( trans, dataset )
}
--- a/lib/galaxy/web/controllers/tracks.py Thu Sep 29 16:45:19 2011 -0400
+++ b/lib/galaxy/web/controllers/tracks.py Fri Sep 30 09:26:22 2011 -0400
@@ -623,7 +623,8 @@
"hda_ldda": track_json.get('hda_ldda', "hda"),
"name": track_json['name'],
"track_type": track_json['track_type'],
- "prefs": track_json['prefs']
+ "prefs": track_json['prefs'],
+ "mode": track_json['mode']
}
def unpack_collection( collection_json ):
--- a/static/scripts/packed/trackster.js Thu Sep 29 16:45:19 2011 -0400
+++ b/static/scripts/packed/trackster.js Fri Sep 30 09:26:22 2011 -0400
@@ -1,1 +1,1 @@
-var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,aa){var q=f("class").extend,t=f("slotting"),N=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}if(ar.container){ar.container.remove_drawable(ar)}o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};aa.moveable=n;var af=16,I=9,F=20,V=I+2,B=100,K=12000,T=200,E=5,w=10,M=5000,x=100,p="There was an error in indexing this dataset. ",L="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",z="Tool cannot be rerun: ",a="Loading data...",ab="Ready for display",d=10,v=5,D=5;function y(ah){return Math.round(ah*1000)/1000}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var U=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(U.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var J=function(ai,ah,aj){U.call(this,ai,ah,aj)};q(J.prototype,U.prototype,c.prototype,{load_data:function(aj,ah,al,am,ai,ak){if(ai>1){return}return U.prototype.load_data.call(this,aj,ah,al,am,ai,ak)}});var r=function(ak,ai,aj,am,al,ah){this.name=ak;this.view=ai;this.parent_element=am;this.drag_handle_class=al;this.container=ah;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak}],saved_values:aj,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values};q(r.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},make_name_popup_menu:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var A=function(al,ak,ai,aj,an,am,ah){r.call(this,ak,ai,aj,an,am,ah);this.obj_type=al;this.drawables=[]};q(A.prototype,r.prototype,{init:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah].init()}},_draw:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah]._draw()}},to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){ai.push(this.drawables[ah].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ai}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var S=function(ak,ai,aj,am,ah){A.call(this,"DrawableGroup",ak,ai,aj,am,"group-handle",ah);if(!S.id_counter){S.id_counter=0}var al=S.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+al).appendTo(this.parent_element);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+al+"_content_div").appendTo(this.container_div);m(this.container_div,this);m(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.make_name_popup_menu()};q(S.prototype,r.prototype,A.prototype,{make_name_popup_menu:function(){var ai=this;var ah={};ah["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Group",ai.config.build_form(),{Cancel:al,OK:aj})};ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)}});var ae=function(ah,ak,aj,ai){A.call(this,"View");this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;this.tracks=this.drawables;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.init();this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,A.prototype,{init:function(){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.content_div);m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ai=function(al){if(al.type==="focusout"||(al.keyCode||al.which)===13||(al.keyCode||al.which)===27){if((al.keyCode||al.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.content_div.click(function(al){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(al){ah.zoom_in(al.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(al,am){this.current_x=am.offsetX}).bind("drag",function(al,an){var ao=an.offsetX-this.current_x;this.current_x=an.offsetX;var am=Math.round(ao/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-am)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(al,am){if(al.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(al,am){am.original_low=ah.low;am.current_height=al.clientY;am.current_x=am.offsetX}).bind("drag",function(an,ap){var al=$(this);var aq=ap.offsetX-ap.current_x;var am=al.scrollTop()-(an.clientY-ap.current_height);al.scrollTop(am);ap.current_height=an.clientY;ap.current_x=ap.offsetX;var ao=Math.round(aq/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}).bind("mousewheel",function(an,ap,am,al){if(am){var ao=Math.round(-am/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}});this.top_labeltrack.bind("dragstart",function(al,am){return $("<div />").css({height:ah.content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ap,aq){$(aq.proxy).css({left:Math.min(ap.pageX,aq.startX),width:Math.abs(ap.pageX-aq.startX)});var am=Math.min(ap.pageX,aq.startX)-ah.container.offset().left,al=Math.max(ap.pageX,aq.startX)-ah.container.offset().left,ao=(ah.high-ah.low),an=ah.viewport_container.width();ah.update_location(Math.round(am/an*ao)+ah.low,Math.round(al/an*ao)+ah.low)}).bind("dragend",function(aq,ar){var am=Math.min(aq.pageX,ar.startX),al=Math.max(aq.pageX,ar.startX),ao=(ah.high-ah.low),an=ah.viewport_container.width(),ap=ah.low;ah.low=Math.round(am/an*ao)+ap;ah.high=Math.round(al/an*ao)+ap;$(ar.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,this.top_labeltrack));this.add_label_track(new ad(this,this.nav_labeltrack));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(aj){aj.num=x;$.extend(aj,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this,ai=$.Deferred();$.ajax({url:chrom_url,data:aj,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+aj.chrom);return}if(al.reference){ah.add_label_track(new C(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);ah.chrom_start_index=al.start_index;ai.resolve(al)},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}});return ai},change_chrom:function(al,ai,an){if(!al||al==="None"){return}var ak=this;if(al==="previous"){ak.load_chroms({low:this.chrom_start_index-x});return}if(al==="next"){ak.load_chroms({low:this.chrom_start_index+x});return}var am=$.grep(ak.chrom_data,function(ap,aq){return ap.chrom===al})[0];if(am===undefined){ak.load_chroms({chrom:al},function(){ak.change_chrom(al,ai,an)});return}else{if(al!==ak.chrom){ak.chrom=al;ak.chrom_select.val(ak.chrom);ak.max_high=am.len-1;ak.reset();ak.request_redraw(true);for(var ao=0,ah=ak.tracks.length;ao<ah;ao++){var aj=ak.tracks[ao];if(aj.init){aj.init()}}}if(ai!==undefined&&an!==undefined){ak.low=Math.max(ai,0);ak.high=Math.min(an,ak.max_high)}ak.reset_overview();ak.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_drawable:function(ah){A.prototype.add_drawable.call(this,ah);if(ah.init){ah.init()}this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;this.label_tracks.push(ah)},remove_drawable:function(aj,ai){A.prototype.remove_drawable.call(this,aj);if(ai){var ah=this;aj.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.tracks),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(E,Math.ceil(Math.log((this.high-this.low)/T)/Math.log(E)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ah){$.when(ah.get_overview_tile()).then(function(ai){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(ai.canvas);view.overview_highlight.show().height(ai.canvas.height());view.overview_viewport.height(ai.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ah;ah.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var s=function(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new P(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){var ay=this.track.parent_element;ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ah={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},aj=this.track,ai=ah.tool_id+aj.tool_region_and_parameters_str(ah.chrom,ah.low,ah.high),ak;if(aj instanceof e){ak=new X(ai,view,aj.hda_ldda,undefined,{},{},aj);ak.change_mode(aj.mode)}this.track.view.add_drawable(ak);ak.content_div.text("Starting job.");this.run(ah,ak,function(al){ak.dataset_id=al.dataset_id;ak.content_div.text("Running job.");ak.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(L)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(z+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var P=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){P.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var Y=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};q(Y.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=parseFloat(ah[this.index]);return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(ar,ay){this.track=ar;this.filters=[];for(var at=0;at<ay.length;at++){var au=ay[at],az=au.name,ah=au.type,ak=au.index,ax=au.tool_id,aw=au.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[at]=new Y(az,ak,ax,aw)}else{console.log("ERROR: unsupported filter: ",az,ah)}}var al=function(aA,aB,aC){aA.click(function(){var aD=aB.text();max=parseFloat(aC.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aC.slider("option","values")){input_size=2*input_size+1;multi_value=true}aB.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aD).appendTo(aB).focus().select().click(function(aE){aE.stopPropagation()}).blur(function(){$(this).remove();aB.text(aD)}).keyup(function(aI){if(aI.keyCode===27){$(this).trigger("blur")}else{if(aI.keyCode===13){var aG=aC.slider("option","min"),aE=aC.slider("option","max"),aH=function(aJ){return(isNaN(aJ)||aJ>aE||aJ<aG)},aF=$(this).val();if(!multi_value){aF=parseFloat(aF);if(aH(aF)){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}else{aF=aF.split("-");aF=[parseFloat(aF[0]),parseFloat(aF[1])];if(aH(aF[0])||aH(aF[1])){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}aC.slider((multi_value?"values":"value"),aF)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aA){aA.stopPropagation()}).click(function(aA){aA.stopPropagation()}).bind("dblclick",function(aA){aA.stopPropagation()}).bind("keydown",function(aA){aA.stopPropagation()});var av=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aD,aF){aF.container=$("<div/>").addClass("slider-row").appendTo(av);var aE=$("<div/>").addClass("elt-label").appendTo(aF.container);var aC=$("<span/>").addClass("slider-name").text(aF.name+" ").appendTo(aE);var aB=$("<span/>");var aH=$("<span/>").addClass("slider-value").appendTo(aE).append("[").append(aB).append("]");var aA=$("<div/>").addClass("slider").appendTo(aF.container);aF.control_element=$("<div/>").attr("id",aF.name+"-filter-control").appendTo(aA);var aG=[0,0];aF.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aJ,aK){var aI=aK.values;aB.text(aI[0]+"-"+aI[1]);aF.low=aI[0];aF.high=aI[1];ap.track.request_draw(true,true)},change:function(aI,aJ){aF.control_element.slider("option","slide").call(aF.control_element,aI,aJ)}});aF.slider=aF.control_element;aF.slider_label=aB;al(aH,aB,aF.control_element);$("<div style='clear: both;'/>").appendTo(aF.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(av);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var aj=this;ao.click(function(){aj.run_on_dataset()})}var aq=$("<div/>").addClass("display-controls").appendTo(this.parent_div),an=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(aq),ai=$("<select/>").attr("name","alpha_dropdown").appendTo(aq);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(ai);for(var at=0;at<this.filters.length;at++){$("<option/>").attr("value",at).text(this.filters[at].name).appendTo(ai)}ai.change(function(){$(this).children("option:selected").each(function(){var aA=parseInt($(this).val());ap.alpha_filter=(aA>=0?ap.filters[aA]:null);ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var Q=function(ai,ah){N.AlphaGenerator.call(this,ah);this.filter=ai};Q.prototype.gen_alpha=function(ah){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var H=function(ah){this.track=ah.track;this.params=ah.params;this.values={};if(ah.saved_values){this.restore_values(ah.saved_values)}this.onchange=ah.onchange};q(H.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(aj,ai,ah,ak){this.index=aj;this.low=aj*T*ai;this.high=(aj+1)*T*ai;this.resolution=ai;this.canvas=$("<div class='track-tile'/>").append(ah);this.data=ak;this.stale=false};var l=function(aj,ai,ah,ak,al){b.call(this,aj,ai,ah,ak);this.max_val=al};var R=function(aj,ai,ah,al,ak){b.call(this,aj,ai,ah,al);this.message=ak};var j=function(aj,ah,ai,am,ak,al){r.call(this,aj,ah,{},am,"draghandle",ah);this.data_url=(ak?ak:default_data_url);this.data_url_extra_params={};this.data_query_wait=(al?al:M);this.dataset_check_url=converted_datasets_state_url;if(!j.id_counter){j.id_counter=0}this.container_div=$("<div />").addClass("track").attr("id","track_"+j.id_counter++).css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};q(j.prototype,r.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof C){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Z){return"ReadTrack"}else{if(this instanceof X){return"ToolDataFeatureTrack"}else{if(this instanceof W){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var ak=ah.view.tracks.indexOf(ah);var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(L)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.make_name_popup_menu()}ah.content_div.text(ab);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}})},predraw_init:function(){},});var O=function(ao,am,ap){var ai=this,aq=ai.view;n(ai.container_div,ai.drag_handle_class,".group",ai);this.filters_manager=(ao!==undefined?new ac(this,ao):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(am!==undefined&&obj_length(am)>0?new s(this,am):undefined);this.is_overview=false;if(ai.hidden){return}if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(ai.display_modes!==undefined){if(ai.mode_div===undefined){ai.mode_div=$("<div class='right-float menubutton popup' />").appendTo(ai.header_div);var aj=(ai.config&&ai.config.values.mode?ai.config.values.mode:ai.display_modes[0]);ai.mode=aj;ai.mode_div.text(aj);var ah={};for(var ak=0,an=ai.display_modes.length;ak<an;ak++){var al=ai.display_modes[ak];ah[al]=function(ar){return function(){ai.change_mode(ar)}}(al)}make_popupmenu(ai.mode_div,ah)}else{ai.mode_div.hide()}}this.make_name_popup_menu()};q(O.prototype,r.prototype,j.prototype,{to_json:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.config.values.mode=ai;ah.tile_cache.clear();ah.request_draw()},make_name_popup_menu:function(){var ai=this;var ah={};ah[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(ai.is_overview){ai.view.reset_overview()}else{ai.view.set_overview(ai)}};ah["Edit configuration"]=function(){var am=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},al=function(an){if((an.keyCode||an.which)===27){am()}else{if((an.keyCode||an.which)===13){ak()}}};$(window).bind("keypress.check_enter_esc",al);show_modal("Configure Track",ai.config.build_form(),{Cancel:am,OK:ak})};if(ai.filters_available>0){var aj=(ai.filters_div.is(":visible")?"Hide filters":"Show filters");ah[aj]=function(){ai.filters_visible=(ai.filters_div.is(":visible"));if(ai.filters_visible){ai.filters_manager.reset_filters()}ai.filters_div.toggle();ai.make_name_popup_menu()}}if(ai.tool){var aj=(ai.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ah[aj]=function(){if(!ai.dynamic_tool_div.is(":visible")){ai.set_name(ai.name+ai.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";ai.revert_name()}ai.dynamic_tool_div.toggle();ai.make_name_popup_menu()}}ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)},set_is_overview:function(ah){this.is_overview=ah;this.make_name_popup_menu()},get_overview_tile:function(){var ah=this;view=ah.view,resolution=Math.pow(E,Math.ceil(Math.log((view.max_high-view.max_low)/T)/Math.log(E))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ah.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ah.data_url_extra_params)).then(function(ai){var ak=ah._gen_tile_cache_key(view_width,w_scale,0),am=ah.tile_cache.get(ak);if(!am){am=ah.draw_tile(ai,"Auto",resolution,0,w_scale);ah.tile_cache.set(ak,am)}var ap=$(am.canvas.find("canvas")),al=ap.clone(),ao=ap.get(0).getContext("2d"),aj=al.get(0).getContext("2d"),an=ao.getImageData(0,0,ao.canvas.width,ao.canvas.height);aj.putImageData(an,-ah.left_offset,(am.data.dataset_type==="summary_tree"?V:0));new_tile=new b(-1,resolution,al);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!this.enabled){return}if(!(this instanceof C)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/T);var ap=true;var at=[];var ah=0;while((ai*T*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*T*an,ax=ap+T*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);al.tile_cache.set(at,aq);if(aq!==undefined){al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw()});return null},show_tile:function(ao,aq,ar){var aj=this,ai=ao.canvas,an=ai;if(ao.message){var at=$("<div/>"),ap=$("<div/>").addClass("tile-message").text(ao.message).css({height:F-1,width:ao.canvas.width}).appendTo(at),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ap),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ap);at.append(ai);an=at;al.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()});ah.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()})}var am=this.view.high-this.view.low,ak=(ao.low-this.view.low)*ar;if(this.left_offset){ak-=this.left_offset}an.css({position:"absolute",top:0,left:ak,height:""});aq.append(an);aj.max_height=Math.max(aj.max_height,an.height());aj.content_div.css("height",aj.max_height+"px");aq.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*T*ai,al=T*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ah,ai){this.hidden=true;j.call(this,"label",ah,{},ai);this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var C=function(ah){this.hidden=true;j.call(this,null,ah,{},ah.top_labeltrack);O.call(this);ah.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ah.dbkey};this.data_manager=new J(D,this,false);this.tile_cache=new c(v)};q(C.prototype,r.prototype,O.prototype,{draw_tile:function(ar,an,am,ai,at){var al=this,aj=T*am;if(at>this.view.canvas_manager.char_width_px){if(ar===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(al,aj,am,ah,ak){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,al,aj,ak,aj.viewport_container);O.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=am;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new U(D,this);this.tile_cache=new c(v);this.left_offset=0;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:ak,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.track_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.track_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};q(k.prototype,r.prototype,O.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this,ai=ah.view.tracks.indexOf(ah);ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(aj){ah.container_div.addClass("line-track");var al=aj.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=al.min;ah.prefs.max_value=al.max;$("#track_"+ai+"_minval").val(ah.prefs.min_value);$("#track_"+ai+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=al.total_frequency;ah.container_div.find(".yaxislabel").remove();var am=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_minval").text(y(ah.prefs.min_value));var ak=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_maxval").text(y(ah.prefs.max_value));ak.css({position:"absolute",top:"24px",left:"10px"});ak.prependTo(ah.container_div);am.css({position:"absolute",bottom:"2px",left:"10px"});am.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new N.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(aj,al,ak,au.data)}});var e=function(ah,am,al,ap,ao,aj,ak,an){var ai=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];j.call(this,ah,am,ao,am.viewport_container);O.call(this,aj,ak,an);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){ai.set_name(ai.prefs.name);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=al;this.dataset_id=ap;this.original_dataset_id=ap;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new U(20,this);this.left_offset=200;this.painter=N.LinkedFeaturePainter};q(e.prototype,r.prototype,O.prototype,{postdraw_actions:function(ax,ah,ay,aw){O.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.make_name_popup_menu()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",B,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aE,aI,ar,ak){var aB=this,am=aB._get_tile_bounds(aI,aE),aK=am[0],ai=am[1],ay=ai-aK,aC=Math.ceil(ay*ar),aO=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"){az="no_detail"}else{var aN=aw.data;if(this.view.high-this.view.low>K){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an+V;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aK,ai,200);if(aw.max){at.max=aw.max}aw=at}var aL=new N.SummaryTreePainter(aw,aK,ai,this.prefs);var aD=aj.getContext("2d");aD.translate(al,V);aL.draw(aD,aC,an);return new l(aI,aE,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aF=0,aH=aw.data.length;aF<aH;aF++){var ao=aw.data[aF];var aG=false;var av;for(var aJ=0,aM=au.length;aJ<aM;aJ++){av=au[aJ];av.update_attrs(ao);if(!av.keep(ao)){aG=true;break}}if(!aG){aq.push(ao)}}}var aA=(this.filters_manager.alpha_filter?new Q(this.filters_manager.alpha_filter):null);var aL=new (this.painter)(aq,aK,ai,this.prefs,az,aA,ak);var an=Math.max(af,aL.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an;var aD=aj.getContext("2d");aD.fillStyle=this.prefs.block_color;aD.font=aD.canvas.manager.default_font;aD.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aD.translate(al,0);aL.draw(aD,aC,an,ax)}return new R(aI,aE,aj,aw.data,aw.message)}});var W=function(ak,ai,am,ah,aj,al){e.call(this,ak,ai,am,ah,aj,al);this.painter=N.VariantPainter};q(W.prototype,r.prototype,O.prototype,e.prototype);var Z=function(ak,ai,am,ah,aj,al){e.call(this,ak,ai,am,ah,aj,al);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:aj,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=N.ReadPainter;this.make_name_popup_menu()};q(Z.prototype,r.prototype,O.prototype,e.prototype);var X=function(al,aj,an,ah,ak,am,ai){e.call(this,al,aj,an,ah,ak,am,{},ai);this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(X.prototype,r.prototype,O.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=M;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});aa.View=ae;aa.DrawableGroup=S;aa.LineTrack=k;aa.FeatureTrack=e;aa.ReadTrack=Z};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,aa){var q=f("class").extend,t=f("slotting"),N=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}if(ar.container){ar.container.remove_drawable(ar)}o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};aa.moveable=n;var af=16,I=9,F=20,V=I+2,B=100,K=12000,T=200,E=5,w=10,M=5000,x=100,p="There was an error in indexing this dataset. ",L="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",z="Tool cannot be rerun: ",a="Loading data...",ab="Ready for display",d=10,v=5,D=5;function y(ah){return Math.round(ah*1000)/1000}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var U=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(U.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var J=function(ai,ah,aj){U.call(this,ai,ah,aj)};q(J.prototype,U.prototype,c.prototype,{load_data:function(aj,ah,al,am,ai,ak){if(ai>1){return}return U.prototype.load_data.call(this,aj,ah,al,am,ai,ak)}});var r=function(ak,ai,ah,aj,al){this.name=ak;this.view=ai;this.container=ah;this.drag_handle_class=al;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak}],saved_values:aj,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values};q(r.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},make_name_popup_menu:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var A=function(al,ak,ai,ah,aj,am){r.call(this,ak,ai,ah,aj,am);this.obj_type=al;this.drawables=[]};q(A.prototype,r.prototype,{init:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah].init()}},_draw:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah]._draw()}},to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){ai.push(this.drawables[ah].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ai}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var S=function(ak,ai,ah,aj){A.call(this,"DrawableGroup",ak,ai,ah,aj,"group-handle");if(!S.id_counter){S.id_counter=0}var al=S.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+al).appendTo(this.container.content_div);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+al+"_content_div").appendTo(this.container_div);m(this.container_div,this);m(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.make_name_popup_menu()};q(S.prototype,r.prototype,A.prototype,{make_name_popup_menu:function(){var ai=this;var ah={};ah["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Group",ai.config.build_form(),{Cancel:al,OK:aj})};ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)}});var ae=function(ah,ak,aj,ai){A.call(this,"View");this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;this.tracks=this.drawables;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.init();this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,A.prototype,{init:function(){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ai=function(al){if(al.type==="focusout"||(al.keyCode||al.which)===13||(al.keyCode||al.which)===27){if((al.keyCode||al.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.browser_content_div.click(function(al){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(al){ah.zoom_in(al.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(al,am){this.current_x=am.offsetX}).bind("drag",function(al,an){var ao=an.offsetX-this.current_x;this.current_x=an.offsetX;var am=Math.round(ao/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-am)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(al,am){if(al.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(al,am){am.original_low=ah.low;am.current_height=al.clientY;am.current_x=am.offsetX}).bind("drag",function(an,ap){var al=$(this);var aq=ap.offsetX-ap.current_x;var am=al.scrollTop()-(an.clientY-ap.current_height);al.scrollTop(am);ap.current_height=an.clientY;ap.current_x=ap.offsetX;var ao=Math.round(aq/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}).bind("mousewheel",function(an,ap,am,al){if(am){var ao=Math.round(-am/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}});this.top_labeltrack.bind("dragstart",function(al,am){return $("<div />").css({height:ah.browser_content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ap,aq){$(aq.proxy).css({left:Math.min(ap.pageX,aq.startX),width:Math.abs(ap.pageX-aq.startX)});var am=Math.min(ap.pageX,aq.startX)-ah.container.offset().left,al=Math.max(ap.pageX,aq.startX)-ah.container.offset().left,ao=(ah.high-ah.low),an=ah.viewport_container.width();ah.update_location(Math.round(am/an*ao)+ah.low,Math.round(al/an*ao)+ah.low)}).bind("dragend",function(aq,ar){var am=Math.min(aq.pageX,ar.startX),al=Math.max(aq.pageX,ar.startX),ao=(ah.high-ah.low),an=ah.viewport_container.width(),ap=ah.low;ah.low=Math.round(am/an*ao)+ap;ah.high=Math.round(al/an*ao)+ap;$(ar.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,{content_div:this.top_labeltrack}));this.add_label_track(new ad(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(aj){aj.num=x;$.extend(aj,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this,ai=$.Deferred();$.ajax({url:chrom_url,data:aj,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+aj.chrom);return}if(al.reference){ah.add_label_track(new C(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);ah.chrom_start_index=al.start_index;ai.resolve(al)},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}});return ai},change_chrom:function(al,ai,an){if(!al||al==="None"){return}var ak=this;if(al==="previous"){ak.load_chroms({low:this.chrom_start_index-x});return}if(al==="next"){ak.load_chroms({low:this.chrom_start_index+x});return}var am=$.grep(ak.chrom_data,function(ap,aq){return ap.chrom===al})[0];if(am===undefined){ak.load_chroms({chrom:al},function(){ak.change_chrom(al,ai,an)});return}else{if(al!==ak.chrom){ak.chrom=al;ak.chrom_select.val(ak.chrom);ak.max_high=am.len-1;ak.reset();ak.request_redraw(true);for(var ao=0,ah=ak.tracks.length;ao<ah;ao++){var aj=ak.tracks[ao];if(aj.init){aj.init()}}}if(ai!==undefined&&an!==undefined){ak.low=Math.max(ai,0);ak.high=Math.min(an,ak.max_high)}ak.reset_overview();ak.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_drawable:function(ah){A.prototype.add_drawable.call(this,ah);if(ah.init){ah.init()}this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;this.label_tracks.push(ah)},remove_drawable:function(aj,ai){A.prototype.remove_drawable.call(this,aj);if(ai){var ah=this;aj.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.tracks),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(E,Math.ceil(Math.log((this.high-this.low)/T)/Math.log(E)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ah){$.when(ah.get_overview_tile()).then(function(ai){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(ai.canvas);view.overview_highlight.show().height(ai.canvas.height());view.overview_viewport.height(ai.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ah;ah.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var s=function(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new P(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},al=this.track,aj=ai.tool_id+al.tool_region_and_parameters_str(ai.chrom,ai.low,ai.high),ah,am;if(al.container===view){var ak=new S(this.name,this.track.view,this.track.container);al.container.add_drawable(ak);al.container.remove_drawable(al);ak.add_drawable(al);al.container_div.appendTo(ak.content_div);ah=ak}else{ah=al.container}if(al instanceof e){am=new X(aj,view,ah,"hda");am.change_mode(al.mode);ah.add_drawable(am)}am.content_div.text("Starting job.");this.run(ai,am,function(an){am.dataset_id=an.dataset_id;am.content_div.text("Running job.");am.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(L)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(z+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var P=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){P.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var Y=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};q(Y.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=parseFloat(ah[this.index]);return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(ar,ay){this.track=ar;this.filters=[];for(var at=0;at<ay.length;at++){var au=ay[at],az=au.name,ah=au.type,ak=au.index,ax=au.tool_id,aw=au.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[at]=new Y(az,ak,ax,aw)}else{console.log("ERROR: unsupported filter: ",az,ah)}}var al=function(aA,aB,aC){aA.click(function(){var aD=aB.text();max=parseFloat(aC.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aC.slider("option","values")){input_size=2*input_size+1;multi_value=true}aB.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aD).appendTo(aB).focus().select().click(function(aE){aE.stopPropagation()}).blur(function(){$(this).remove();aB.text(aD)}).keyup(function(aI){if(aI.keyCode===27){$(this).trigger("blur")}else{if(aI.keyCode===13){var aG=aC.slider("option","min"),aE=aC.slider("option","max"),aH=function(aJ){return(isNaN(aJ)||aJ>aE||aJ<aG)},aF=$(this).val();if(!multi_value){aF=parseFloat(aF);if(aH(aF)){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}else{aF=aF.split("-");aF=[parseFloat(aF[0]),parseFloat(aF[1])];if(aH(aF[0])||aH(aF[1])){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}aC.slider((multi_value?"values":"value"),aF)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aA){aA.stopPropagation()}).click(function(aA){aA.stopPropagation()}).bind("dblclick",function(aA){aA.stopPropagation()}).bind("keydown",function(aA){aA.stopPropagation()});var av=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aD,aF){aF.container=$("<div/>").addClass("slider-row").appendTo(av);var aE=$("<div/>").addClass("elt-label").appendTo(aF.container);var aC=$("<span/>").addClass("slider-name").text(aF.name+" ").appendTo(aE);var aB=$("<span/>");var aH=$("<span/>").addClass("slider-value").appendTo(aE).append("[").append(aB).append("]");var aA=$("<div/>").addClass("slider").appendTo(aF.container);aF.control_element=$("<div/>").attr("id",aF.name+"-filter-control").appendTo(aA);var aG=[0,0];aF.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aJ,aK){var aI=aK.values;aB.text(aI[0]+"-"+aI[1]);aF.low=aI[0];aF.high=aI[1];ap.track.request_draw(true,true)},change:function(aI,aJ){aF.control_element.slider("option","slide").call(aF.control_element,aI,aJ)}});aF.slider=aF.control_element;aF.slider_label=aB;al(aH,aB,aF.control_element);$("<div style='clear: both;'/>").appendTo(aF.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(av);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var aj=this;ao.click(function(){aj.run_on_dataset()})}var aq=$("<div/>").addClass("display-controls").appendTo(this.parent_div),an=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(aq),ai=$("<select/>").attr("name","alpha_dropdown").appendTo(aq);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(ai);for(var at=0;at<this.filters.length;at++){$("<option/>").attr("value",at).text(this.filters[at].name).appendTo(ai)}ai.change(function(){$(this).children("option:selected").each(function(){var aA=parseInt($(this).val());ap.alpha_filter=(aA>=0?ap.filters[aA]:null);ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var Q=function(ai,ah){N.AlphaGenerator.call(this,ah);this.filter=ai};Q.prototype.gen_alpha=function(ah){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var H=function(ah){this.track=ah.track;this.params=ah.params;this.values={};this.restore_values((ah.saved_values?ah.saved_values:{}));this.onchange=ah.onchange};q(H.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(aj,ai,ah,ak){this.index=aj;this.low=aj*T*ai;this.high=(aj+1)*T*ai;this.resolution=ai;this.canvas=$("<div class='track-tile'/>").append(ah);this.data=ak;this.stale=false};var l=function(aj,ai,ah,ak,al){b.call(this,aj,ai,ah,ak);this.max_val=al};var R=function(aj,ai,ah,al,ak){b.call(this,aj,ai,ah,al);this.message=ak};var j=function(ak,ai,ah,aj,al,am){r.call(this,ak,ai,ah,{},"draghandle");this.data_url=(al?al:default_data_url);this.data_url_extra_params={};this.data_query_wait=(am?am:M);this.dataset_check_url=converted_datasets_state_url;if(!j.id_counter){j.id_counter=0}this.container_div=$("<div />").addClass("track").attr("id","track_"+j.id_counter++).css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.container.content_div.append(this.container_div)};q(j.prototype,r.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof C){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Z){return"ReadTrack"}else{if(this instanceof X){return"ToolDataFeatureTrack"}else{if(this instanceof W){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var ak=ah.view.tracks.indexOf(ah);var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(L)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.make_name_popup_menu()}ah.content_div.text(ab);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}})},predraw_init:function(){},});var O=function(ao,am){var ai=this,ap=ai.view;n(ai.container_div,ai.drag_handle_class,".group",ai);this.filters_manager=new ac(this,(ao!==undefined?ao:{}));this.filters_available=false;this.filters_visible=false;this.tool=(am!==undefined&&obj_length(am)>0?new s(this,am):undefined);this.is_overview=false;if(ai.hidden){return}if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(ai.display_modes!==undefined){if(ai.mode_div===undefined){ai.mode_div=$("<div class='right-float menubutton popup' />").appendTo(ai.header_div);var aj=(ai.config&&ai.config.values.mode?ai.config.values.mode:ai.display_modes[0]);ai.mode=aj;ai.mode_div.text(aj);var ah={};for(var ak=0,an=ai.display_modes.length;ak<an;ak++){var al=ai.display_modes[ak];ah[al]=function(aq){return function(){ai.change_mode(aq)}}(al)}make_popupmenu(ai.mode_div,ah)}else{ai.mode_div.hide()}}this.make_name_popup_menu()};q(O.prototype,r.prototype,j.prototype,{to_json:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.config.values.mode=ai;ah.tile_cache.clear();ah.request_draw();return ah},make_name_popup_menu:function(){var ai=this;var ah={};ah[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(ai.is_overview){ai.view.reset_overview()}else{ai.view.set_overview(ai)}};ah["Edit configuration"]=function(){var am=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},al=function(an){if((an.keyCode||an.which)===27){am()}else{if((an.keyCode||an.which)===13){ak()}}};$(window).bind("keypress.check_enter_esc",al);show_modal("Configure Track",ai.config.build_form(),{Cancel:am,OK:ak})};if(ai.filters_available>0){var aj=(ai.filters_div.is(":visible")?"Hide filters":"Show filters");ah[aj]=function(){ai.filters_visible=(ai.filters_div.is(":visible"));if(ai.filters_visible){ai.filters_manager.reset_filters()}ai.filters_div.toggle();ai.make_name_popup_menu()}}if(ai.tool){var aj=(ai.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ah[aj]=function(){if(!ai.dynamic_tool_div.is(":visible")){ai.set_name(ai.name+ai.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";ai.revert_name()}ai.dynamic_tool_div.toggle();ai.make_name_popup_menu()}}ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)},set_is_overview:function(ah){this.is_overview=ah;this.make_name_popup_menu()},get_overview_tile:function(){var ah=this;view=ah.view,resolution=Math.pow(E,Math.ceil(Math.log((view.max_high-view.max_low)/T)/Math.log(E))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ah.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ah.data_url_extra_params)).then(function(ai){var ak=ah._gen_tile_cache_key(view_width,w_scale,0),am=ah.tile_cache.get(ak);if(!am){am=ah.draw_tile(ai,"Auto",resolution,0,w_scale);ah.tile_cache.set(ak,am)}var ap=$(am.canvas.find("canvas")),al=ap.clone(),ao=ap.get(0).getContext("2d"),aj=al.get(0).getContext("2d"),an=ao.getImageData(0,0,ao.canvas.width,ao.canvas.height);aj.putImageData(an,-ah.left_offset,(am.data.dataset_type==="summary_tree"?V:0));new_tile=new b(-1,resolution,al);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!this.enabled){return}if(!(this instanceof C)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/T);var ap=true;var at=[];var ah=0;while((ai*T*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*T*an,ax=ap+T*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);al.tile_cache.set(at,aq);if(aq!==undefined){al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw()});return null},show_tile:function(ao,aq,ar){var aj=this,ai=ao.canvas,an=ai;if(ao.message){var at=$("<div/>"),ap=$("<div/>").addClass("tile-message").text(ao.message).css({height:F-1,width:ao.canvas.width}).appendTo(at),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ap),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ap);at.append(ai);an=at;al.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()});ah.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()})}var am=this.view.high-this.view.low,ak=(ao.low-this.view.low)*ar;if(this.left_offset){ak-=this.left_offset}an.css({position:"absolute",top:0,left:ak,height:""});aq.append(an);aj.max_height=Math.max(aj.max_height,an.height());aj.content_div.css("height",aj.max_height+"px");aq.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*T*ai,al=T*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ai,ah){this.hidden=true;j.call(this,"label",ai,ah,{});this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var C=function(ah){this.hidden=true;j.call(this,"reference",ah,{content_div:ah.top_labeltrack},{});O.call(this);ah.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ah.dbkey};this.data_manager=new J(D,this,false);this.tile_cache=new c(v)};q(C.prototype,r.prototype,O.prototype,{draw_tile:function(ar,an,am,ai,at){var al=this,aj=T*am;if(at>this.view.canvas_manager.char_width_px){if(ar===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(am,ak,aj,an,ah,al){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,am,ak,aj,al);O.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=an;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new U(D,this);this.tile_cache=new c(v);this.left_offset=0;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:am},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:al,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.track_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.track_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};q(k.prototype,r.prototype,O.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this,ai=ah.view.tracks.indexOf(ah);ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(aj){ah.container_div.addClass("line-track");var al=aj.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=al.min;ah.prefs.max_value=al.max;$("#track_"+ai+"_minval").val(ah.prefs.min_value);$("#track_"+ai+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=al.total_frequency;ah.container_div.find(".yaxislabel").remove();var am=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_minval").text(y(ah.prefs.min_value));var ak=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_maxval").text(y(ah.prefs.max_value));ak.css({position:"absolute",top:"24px",left:"10px"});ak.prependTo(ah.container_div);am.css({position:"absolute",bottom:"2px",left:"10px"});am.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new N.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(aj,al,ak,au.data)}});var e=function(ah,an,ai,am,ap,ao,ak,al){var aj=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];j.call(this,ah,an,ai,ao);O.call(this,ak,al);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){aj.set_name(aj.prefs.name);aj.tile_cache.clear();aj.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=am;this.dataset_id=ap;this.original_dataset_id=ap;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new U(20,this);this.left_offset=200;this.painter=N.LinkedFeaturePainter};q(e.prototype,r.prototype,O.prototype,{postdraw_actions:function(ax,ah,ay,aw){O.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.make_name_popup_menu()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",B,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aE,aI,ar,ak){var aB=this,am=aB._get_tile_bounds(aI,aE),aK=am[0],ai=am[1],ay=ai-aK,aC=Math.ceil(ay*ar),aO=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"){az="no_detail"}else{var aN=aw.data;if(this.view.high-this.view.low>K){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an+V;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aK,ai,200);if(aw.max){at.max=aw.max}aw=at}var aL=new N.SummaryTreePainter(aw,aK,ai,this.prefs);var aD=aj.getContext("2d");aD.translate(al,V);aL.draw(aD,aC,an);return new l(aI,aE,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aF=0,aH=aw.data.length;aF<aH;aF++){var ao=aw.data[aF];var aG=false;var av;for(var aJ=0,aM=au.length;aJ<aM;aJ++){av=au[aJ];av.update_attrs(ao);if(!av.keep(ao)){aG=true;break}}if(!aG){aq.push(ao)}}}var aA=(this.filters_manager.alpha_filter?new Q(this.filters_manager.alpha_filter):null);var aL=new (this.painter)(aq,aK,ai,this.prefs,az,aA,ak);var an=Math.max(af,aL.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an;var aD=aj.getContext("2d");aD.fillStyle=this.prefs.block_color;aD.font=aD.canvas.manager.default_font;aD.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aD.translate(al,0);aL.draw(aD,aC,an,ax)}return new R(aI,aE,aj,aw.data,aw.message)}});var W=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.painter=N.VariantPainter};q(W.prototype,r.prototype,O.prototype,e.prototype);var Z=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ak,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=N.ReadPainter;this.make_name_popup_menu()};q(Z.prototype,r.prototype,O.prototype,e.prototype);var X=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am,{});this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(X.prototype,r.prototype,O.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=M;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});aa.View=ae;aa.DrawableGroup=S;aa.LineTrack=k;aa.FeatureTrack=e;aa.ReadTrack=Z};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
--- a/static/scripts/packed/trackster_ui.js Thu Sep 29 16:45:19 2011 -0400
+++ b/static/scripts/packed/trackster_ui.js Fri Sep 30 09:26:22 2011 -0400
@@ -1,1 +1,1 @@
-var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(a){return new addable_objects[a.track_type](a.name,view,a.hda_ldda,a.dataset_id,a.prefs,a.filters,a.tool)};var drawable_collection_from_dict=function(e){var d=new addable_objects[e.obj_type](e.name,view,e.prefs,view.viewport_container,view);for(var c=0;c<e.drawables.length;c++){var a=e.drawables[c],b;if(a.track_type){b=track_from_dict(a)}else{b=drawable_collection_from_dict(a)}d.add_drawable(b);d.content_div.append(b.container_div)}return d};var drawable_from_dict=function(a){return(a.track_type?track_from_dict(a):drawable_collection_from_dict(a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o))}}var n;for(var j=0;j<view.tracks.length;j++){if(view.tracks[j].name==m){view.set_overview(view.tracks[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
+var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(c,b){var a=new addable_objects[c.track_type](c.name,view,b,c.hda_ldda,c.dataset_id,c.prefs,c.filters,c.tool);if(c.mode){a.change_mode(c.mode)}return a};var drawable_collection_from_dict=function(f,a){var e=new addable_objects[f.obj_type](f.name,view,a,f.prefs,view.viewport_container,view);for(var d=0;d<f.drawables.length;d++){var b=f.drawables[d],c;if(b.track_type){c=track_from_dict(b,e)}else{c=drawable_collection_from_dict(b)}e.add_drawable(c);e.content_div.append(c.container_div)}return e};var drawable_from_dict=function(b,a){return(b.track_type?track_from_dict(b,a):drawable_collection_from_dict(b,a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o,view))}}var n;for(var j=0;j<view.tracks.length;j++){if(view.tracks[j].name==m){view.set_overview(view.tracks[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
--- a/static/scripts/trackster.js Thu Sep 29 16:45:19 2011 -0400
+++ b/static/scripts/trackster.js Fri Sep 30 09:26:22 2011 -0400
@@ -573,14 +573,14 @@
*/
/**
- * Base interface for all drawable objects.
+ * Base interface for all drawable objects. Drawable objects have a name and are
+ * associated with a view and container. They optionally have a drag handle class.
*/
-var Drawable = function(name, view, prefs, parent_element, drag_handle_class, container) {
+var Drawable = function(name, view, container, prefs, drag_handle_class) {
this.name = name;
this.view = view;
- this.parent_element = parent_element;
+ this.container = container;
this.drag_handle_class = drag_handle_class;
- this.container = container;
this.config = new DrawableConfig({
track: this,
params: [
@@ -633,8 +633,8 @@
/**
* A collection of drawable objects.
*/
-var DrawableCollection = function(obj_type, name, view, prefs, parent_element, drag_handle_class, container) {
- Drawable.call(this, name, view, prefs, parent_element, drag_handle_class, container);
+var DrawableCollection = function(obj_type, name, view, container, prefs, drag_handle_class) {
+ Drawable.call(this, name, view, container, prefs, drag_handle_class);
// Attribute init.
this.obj_type = obj_type;
@@ -722,20 +722,21 @@
/**
* A group of drawables that are moveable, visible.
*/
-var DrawableGroup = function(name, view, prefs, parent_element, container) {
- DrawableCollection.call(this, "DrawableGroup", name, view, prefs, parent_element, "group-handle", container);
+var DrawableGroup = function(name, view, container, prefs) {
+ DrawableCollection.call(this, "DrawableGroup", name, view, container, prefs, "group-handle");
// HTML elements.
if (!DrawableGroup.id_counter) { DrawableGroup.id_counter = 0; }
var group_id = DrawableGroup.id_counter++
- this.container_div = $("<div/>").addClass("group").attr("id", "group_" + group_id).appendTo(this.parent_element);
+ this.container_div = $("<div/>").addClass("group").attr("id", "group_" + group_id).appendTo(this.container.content_div);
this.header_div = $("<div/>").addClass("track-header").appendTo(this.container_div);
this.header_div.append($("<div/>").addClass(this.drag_handle_class));
this.name_div = $("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);
this.content_div = $("<div/>").addClass("content-div").attr("id", "group_" + group_id + "_content_div").appendTo(this.container_div);
- // Set up containers/moving for group: register both container and content div as container
- // because both are used as containers. Group can be moved.
+ // Set up containers/moving for group: register both container_div and content div as container
+ // because both are used as containers (container div to recognize container, content_div to
+ // store elements). Group can be moved.
is_container(this.container_div, this);
is_container(this.content_div, this);
moveable(this.container_div, this.drag_handle_class, ".group", this);
@@ -820,14 +821,16 @@
view = this;
// Top container for things that are fixed at the top
this.top_container = $("<div/>").addClass("top-container").appendTo(parent_element);
- // Content container, primary tracks are contained in here
- this.content_div = $("<div/>").addClass("content").css("position", "relative").appendTo(parent_element);
+ // Browser content, primary tracks are contained in here
+ this.browser_content_div = $("<div/>").addClass("content").css("position", "relative").appendTo(parent_element);
// Bottom container for things that are fixed at the bottom
this.bottom_container = $("<div/>").addClass("bottom-container").appendTo(parent_element);
// Label track fixed at top
this.top_labeltrack = $("<div/>").addClass("top-labeltrack").appendTo(this.top_container);
// Viewport for dragging tracks in center
- this.viewport_container = $("<div/>").addClass("viewport-container").attr("id", "viewport-container").appendTo(this.content_div);
+ this.viewport_container = $("<div/>").addClass("viewport-container").attr("id", "viewport-container").appendTo(this.browser_content_div);
+ // Alias viewport_container as content_div so that it matches function of DrawableCollection/Group content_div.
+ this.content_div = this.viewport_container;
is_container(this.viewport_container, view);
// Introduction div shown when there are no tracks.
this.intro_div = $("<div/>").addClass("intro");
@@ -884,7 +887,7 @@
});
/*
- this.content_div.bind("mousewheel", function( e, delta ) {
+ this.browser_content_div.bind("mousewheel", function( e, delta ) {
if (Math.abs(delta) < 0.5) {
return;
}
@@ -898,12 +901,12 @@
*/
// Blur tool/filter inputs when user clicks on content div.
- this.content_div.click(function( e ) {
+ this.browser_content_div.click(function( e ) {
$(this).find("input").trigger("blur");
});
// Double clicking zooms in
- this.content_div.bind("dblclick", function( e ) {
+ this.browser_content_div.bind("dblclick", function( e ) {
view.zoom_in(e.pageX, this.viewport_container);
});
@@ -954,7 +957,7 @@
// to zoom in
this.top_labeltrack.bind( "dragstart", function( e, d ) {
return $("<div />").css( {
- "height": view.content_div.height() + view.top_labeltrack.height()
+ "height": view.browser_content_div.height() + view.top_labeltrack.height()
+ view.nav_labeltrack.height() + 1,
"top": "0px",
"position": "absolute",
@@ -982,8 +985,8 @@
view.request_redraw();
});
- this.add_label_track( new LabelTrack( this, this.top_labeltrack ) );
- this.add_label_track( new LabelTrack( this, this.nav_labeltrack ) );
+ this.add_label_track( new LabelTrack( this, { content_div: this.top_labeltrack } ) );
+ this.add_label_track( new LabelTrack( this, { content_div: this.nav_labeltrack } ) );
$(window).bind("resize", function() { view.resize_window(); });
$(document).bind("redraw", function() { view.redraw(); });
@@ -1414,13 +1417,6 @@
var run_on_region_button = $("<input type='submit'>").attr("value", "Run on visible region").css("margin-left", "3em").appendTo(run_tool_row);
var tool = this;
run_on_region_button.click( function() {
- // Create group for track + new tracks and put track in group.
- var
- parent_elt = this.track.parent_element;
- //new_group = new DrawableCollection("New Group", parent_elt);
- //this.track.view.add_drawable(new_group);
-
-
// Run tool to create new track.
tool.run_on_region();
});
@@ -1497,15 +1493,29 @@
// Set name of track to include tool name, parameters, and region used.
track_name = url_params.tool_id +
current_track.tool_region_and_parameters_str(url_params.chrom, url_params.low, url_params.high),
+ container,
new_track;
- // Create and add track.
- // TODO: add support for other kinds of tool data tracks.
+ // If track not in a group, create a group for it and add new track to group. If track
+ // already in group, add track to group.
+ if (current_track.container === view) {
+ var group = new DrawableGroup(this.name, this.track.view, this.track.container);
+ current_track.container.add_drawable(group);
+ // TODO: this is ugly way to move track from one container to another -- make this easier via
+ // a Drawable or DrawableCollection function.
+ current_track.container.remove_drawable(current_track);
+ group.add_drawable(current_track);
+ current_track.container_div.appendTo(group.content_div);
+ container = group;
+ }
+ else {
+ container = current_track.container;
+ }
if (current_track instanceof FeatureTrack) {
- new_track = new ToolDataFeatureTrack(track_name, view, current_track.hda_ldda, undefined, {}, {}, current_track);
+ new_track = new ToolDataFeatureTrack(track_name, view, container, "hda");
new_track.change_mode(current_track.mode);
+ container.add_drawable(new_track);
}
- this.track.view.add_drawable(new_track);
new_track.content_div.text("Starting job.");
// Run tool.
@@ -1985,9 +1995,7 @@
this.track = options.track;
this.params = options.params;
this.values = {}
- if ( options.saved_values ) {
- this.restore_values( options.saved_values );
- }
+ this.restore_values( (options.saved_values ? options.saved_values : {}) );
this.onchange = options.onchange
};
@@ -2111,9 +2119,9 @@
* -------> ToolDataFeatureTrack
* -------> VcfTrack
*/
-var Track = function(name, view, prefs, parent_element, data_url, data_query_wait) {
+var Track = function(name, view, container, prefs, data_url, data_query_wait) {
// For now, track's container is always view.
- Drawable.call(this, name, view, {}, parent_element, "draghandle", view);
+ Drawable.call(this, name, view, container, {}, "draghandle");
//
// Attribute init.
@@ -2140,7 +2148,7 @@
// Create content div, which is where track is displayed.
//
this.content_div = $("<div class='track-content'>").appendTo(this.container_div);
- this.parent_element.append(this.container_div);
+ this.container.content_div.append(this.container_div);
};
extend(Track.prototype, Drawable.prototype, {
/** Returns track type. */
@@ -2230,7 +2238,7 @@
// predraw_init may be asynchronous, wait for it and then draw
$.when(track.predraw_init()).done(function() {
track.container_div.removeClass("nodata error pending");
- track.request_draw()
+ track.request_draw();
});
}
}
@@ -2242,7 +2250,7 @@
predraw_init: function() {},
});
-var TiledTrack = function(filters_list, tool_dict, parent_track) {
+var TiledTrack = function(filters_list, tool_dict) {
var track = this,
view = track.view;
@@ -2250,7 +2258,7 @@
moveable(track.container_div, track.drag_handle_class, ".group", track);
// Attribute init.
- this.filters_manager = (filters_list !== undefined ? new FiltersManager(this, filters_list) : undefined);
+ this.filters_manager = new FiltersManager( this, (filters_list !== undefined ? filters_list : {}) );
// filters_available is determined by data, filters_visible is set by user.
this.filters_available = false;
this.filters_visible = false;
@@ -2311,7 +2319,8 @@
"name": this.name,
"hda_ldda": this.hda_ldda,
"dataset_id": this.dataset_id,
- "prefs": this.prefs
+ "prefs": this.prefs,
+ "mode": this.mode,
};
},
/**
@@ -2325,6 +2334,7 @@
track.config.values['mode'] = name;
track.tile_cache.clear();
track.request_draw();
+ return track;
},
/**
* Make popup menu for track name.
@@ -2712,9 +2722,9 @@
}
});
-var LabelTrack = function (view, parent_element) {
+var LabelTrack = function (view, container) {
this.hidden = true;
- Track.call(this, "label", view, {}, parent_element );
+ Track.call(this, "label", view, container, {} );
this.container_div.addClass( "label-track" );
};
extend(LabelTrack.prototype, Track.prototype, {
@@ -2741,7 +2751,7 @@
var ReferenceTrack = function (view) {
this.hidden = true;
- Track.call(this, null, view, {}, view.top_labeltrack);
+ Track.call(this, "reference", view, { content_div: view.top_labeltrack }, {});
TiledTrack.call(this);
view.reference_track = this;
@@ -2786,11 +2796,11 @@
}
});
-var LineTrack = function (name, view, hda_ldda, dataset_id, prefs) {
+var LineTrack = function (name, view, container, hda_ldda, dataset_id, prefs) {
var track = this;
this.display_modes = ["Histogram", "Line", "Filled", "Intensity"];
this.mode = "Histogram";
- Track.call( this, name, view, prefs, view.viewport_container );
+ Track.call( this, name, view, container, prefs );
TiledTrack.call( this );
this.min_height_px = 16;
@@ -2927,7 +2937,7 @@
}
});
-var FeatureTrack = function(name, view, hda_ldda, dataset_id, prefs, filters, tool, parent_track) {
+var FeatureTrack = function(name, view, container, hda_ldda, dataset_id, prefs, filters, tool) {
//
// Preinitialization: do things that need to be done before calling Track and TiledTrack
// initialization code.
@@ -2938,8 +2948,10 @@
//
// Initialization.
//
- Track.call(this, name, view, prefs, view.viewport_container);
- TiledTrack.call(this, filters, tool, parent_track);
+
+ // FIXME: cleaner init needed; should just be able to call TiledTrack()
+ Track.call(this, name, view, container, prefs);
+ TiledTrack.call(this, filters, tool);
// Define and restore track configuration.
this.config = new DrawableConfig( {
@@ -3315,16 +3327,16 @@
}
});
-var VcfTrack = function(name, view, hda_ldda, dataset_id, prefs, filters) {
- FeatureTrack.call(this, name, view, hda_ldda, dataset_id, prefs, filters);
+var VcfTrack = function(name, view, container, hda_ldda, dataset_id, prefs, filters) {
+ FeatureTrack.call(this, name, view, container, hda_ldda, dataset_id, prefs, filters);
this.painter = painters.VariantPainter;
};
extend(VcfTrack.prototype, Drawable.prototype, TiledTrack.prototype, FeatureTrack.prototype);
-var ReadTrack = function (name, view, hda_ldda, dataset_id, prefs, filters) {
- FeatureTrack.call(this, name, view, hda_ldda, dataset_id, prefs, filters);
+var ReadTrack = function (name, view, container, hda_ldda, dataset_id, prefs, filters) {
+ FeatureTrack.call(this, name, view, container, hda_ldda, dataset_id, prefs, filters);
this.config = new DrawableConfig( {
track: this,
@@ -3354,8 +3366,8 @@
/**
* Feature track that displays data generated from tool.
*/
-var ToolDataFeatureTrack = function(name, view, hda_ldda, dataset_id, prefs, filters, parent_track) {
- FeatureTrack.call(this, name, view, hda_ldda, dataset_id, prefs, filters, {}, parent_track);
+var ToolDataFeatureTrack = function(name, view, container, hda_ldda, dataset_id, prefs, filters) {
+ FeatureTrack.call(this, name, view, container, hda_ldda, dataset_id, prefs, filters, {});
// Set up track to fetch initial data from raw data URL when the dataset--not the converted datasets--
// is ready.
--- a/static/scripts/trackster_ui.js Thu Sep 29 16:45:19 2011 -0400
+++ b/static/scripts/trackster_ui.js Fri Sep 30 09:26:22 2011 -0400
@@ -36,23 +36,27 @@
/**
* Decode a track from a dictionary.
*/
-var track_from_dict = function(track_dict) {
- return new addable_objects[track_dict.track_type](
- track_dict.name, view, track_dict.hda_ldda, track_dict.dataset_id,
+var track_from_dict = function(track_dict, container) {
+ var track = new addable_objects[track_dict.track_type](
+ track_dict.name, view, container, track_dict.hda_ldda, track_dict.dataset_id,
track_dict.prefs, track_dict.filters, track_dict.tool);
+ if (track_dict.mode) {
+ track.change_mode(track_dict.mode);
+ }
+ return track;
};
/**
* Decode a drawable collection from a dictionary.
*/
-var drawable_collection_from_dict = function(collection_dict) {
- var collection = new addable_objects[collection_dict.obj_type](collection_dict.name, view, collection_dict.prefs, view.viewport_container, view);
+var drawable_collection_from_dict = function(collection_dict, container) {
+ var collection = new addable_objects[collection_dict.obj_type](collection_dict.name, view, container, collection_dict.prefs, view.viewport_container, view);
for (var i = 0; i < collection_dict.drawables.length; i++) {
var
drawable_dict = collection_dict.drawables[i],
drawable;
if (drawable_dict['track_type']) {
- drawable = track_from_dict(drawable_dict);
+ drawable = track_from_dict(drawable_dict, collection);
}
else {
drawable = drawable_collection_from_dict(drawable_dict);
@@ -70,10 +74,10 @@
/**
* Decode a drawable from a dict.
*/
-var drawable_from_dict = function(drawable_dict) {
+var drawable_from_dict = function(drawable_dict, container) {
return (drawable_dict['track_type'] ?
- track_from_dict(drawable_dict) :
- drawable_collection_from_dict(drawable_dict));
+ track_from_dict(drawable_dict, container) :
+ drawable_collection_from_dict(drawable_dict, container));
};
/**
@@ -101,7 +105,7 @@
var track_config;
for (var i = 0; i < tracks_config.length; i++) {
track_config = tracks_config[i];
- view.add_drawable( drawable_from_dict(track_config) );
+ view.add_drawable( drawable_from_dict(track_config, view) );
}
}
--- a/templates/tracks/browser.mako Thu Sep 29 16:45:19 2011 -0400
+++ b/templates/tracks/browser.mako Fri Sep 30 09:26:22 2011 -0400
@@ -101,7 +101,7 @@
[ arguments[0] ]
);
for (var i= 0; i < track_defs.length; i++) {
- view.add_drawable( track_from_dict(track_defs[i]) );
+ view.add_drawable( track_from_dict(track_defs[i], view) );
}
});
hide_modal();
@@ -178,7 +178,7 @@
make_popupmenu( $("#viz-actions-button"), {
"Add Tracks": add_tracks,
"Add Group": function() {
- var group = new DrawableGroup("New Group", view, {}, view.viewport_container, view);
+ var group = new DrawableGroup("New Group", view, view);
view.add_drawable(group);
},
"Save": function() {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Don't include purged histories in usage calculation.
by Bitbucket 29 Sep '11
by Bitbucket 29 Sep '11
29 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/338ead4737ba/
changeset: 338ead4737ba
user: natefoo
date: 2011-09-29 22:45:19
summary: Don't include purged histories in usage calculation.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/model/__init__.py Wed Sep 28 15:41:21 2011 -0400
+++ b/lib/galaxy/model/__init__.py Thu Sep 29 16:45:19 2011 -0400
@@ -90,7 +90,7 @@
total = 0
# this can be a huge number and can run out of memory, so we avoid the mappers
db_session = object_session( self )
- for history in db_session.query( History ).enable_eagerloads( False ).filter_by( user_id=self.id ).yield_per( 1000 ):
+ for history in db_session.query( History ).enable_eagerloads( False ).filter_by( user_id=self.id, purged=False ).yield_per( 1000 ):
for hda in db_session.query( HistoryDatasetAssociation ).enable_eagerloads( False ).filter_by( history_id=history.id, purged=False ).yield_per( 1000 ):
if not hda.dataset.id in dataset_ids and not hda.dataset.purged and not hda.dataset.library_associations:
dataset_ids.append( hda.dataset.id )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Fix openid_associate upon logging in with an unassociated account, drop Flickr from OpenID since it no longer works (you have to use your photostream URL now).
by Bitbucket 28 Sep '11
by Bitbucket 28 Sep '11
28 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ec5c9d242d9f/
changeset: ec5c9d242d9f
user: natefoo
date: 2011-09-28 21:41:21
summary: Fix openid_associate upon logging in with an unassociated account, drop Flickr from OpenID since it no longer works (you have to use your photostream URL now).
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/web/controllers/user.py Wed Sep 28 10:56:30 2011 -0400
+++ b/lib/galaxy/web/controllers/user.py Wed Sep 28 15:41:21 2011 -0400
@@ -28,7 +28,6 @@
OPENID_PROVIDERS = { 'Google' : 'https://www.google.com/accounts/o8/id',
'Yahoo!' : 'http://yahoo.com',
'AOL/AIM' : 'http://openid.aol.com',
- 'Flickr' : 'http://flickr.com',
'Launchpad' : 'http://login.launchpad.net',
}
@@ -195,7 +194,7 @@
message=message,
status=status ) )
@web.expose
- def openid_associate( self, trans, cntrller, webapp='galaxy', **kwd ):
+ def openid_associate( self, trans, cntrller='user', webapp='galaxy', **kwd ):
if not trans.app.config.enable_openid:
return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
@@ -266,7 +265,7 @@
if user_type_fd_id == 'none' and user_type_form_definition is not None:
user_type_fd_id = trans.security.encode_id( user_type_form_definition.id )
user_type_fd_id_select_field = self.__build_user_type_fd_id_select_field( trans, selected_value=user_type_fd_id )
- widgets = self.__get_widgets( self, trans, user_type_form_definition, user=user, **kwd )
+ widgets = self.__get_widgets( trans, user_type_form_definition, user=user, **kwd )
else:
user_type_fd_id_select_field = None
user_type_form_definition = 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: natefoo: Fix for the mime type when a dataset instance's extension is None.
by Bitbucket 28 Sep '11
by Bitbucket 28 Sep '11
28 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/e28ebc25b2e7/
changeset: e28ebc25b2e7
user: natefoo
date: 2011-09-28 16:56:30
summary: Fix for the mime type when a dataset instance's extension is None.
affected #: 4 files (-1 bytes)
--- a/lib/galaxy/model/__init__.py Wed Sep 28 10:47:54 2011 -0400
+++ b/lib/galaxy/model/__init__.py Wed Sep 28 10:56:30 2011 -0400
@@ -862,7 +862,11 @@
self.datatype.set_raw_data(self, data)
def get_mime( self ):
"""Returns the mime type of the data"""
- return datatypes_registry.get_mimetype_by_extension( self.extension.lower() )
+ try:
+ return datatypes_registry.get_mimetype_by_extension( self.extension.lower() )
+ except AttributeError:
+ # extension is None
+ return 'data'
def is_multi_byte( self ):
"""Data consists of multi-byte characters"""
return self.dataset.is_multi_byte()
--- a/lib/galaxy/web/controllers/dataset.py Wed Sep 28 10:47:54 2011 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Wed Sep 28 10:56:30 2011 -0400
@@ -358,8 +358,7 @@
else:
return trans.show_error_message( "Could not find '%s' on the extra files path %s." % ( filename, file_path ) )
- mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
- trans.response.set_content_type(mime)
+ trans.response.set_content_type(data.get_mime())
trans.log_event( "Display dataset id: %s" % str( dataset_id ) )
if to_ext or isinstance(data.datatype, datatypes.binary.Binary): # Saving the file, or binary file
@@ -691,8 +690,7 @@
# If data is binary or an image, stream without template; otherwise, use display template.
# TODO: figure out a way to display images in display template.
if isinstance(dataset.datatype, datatypes.binary.Binary) or isinstance(dataset.datatype, datatypes.images.Image) or isinstance(dataset.datatype, datatypes.images.Html):
- mime = trans.app.datatypes_registry.get_mimetype_by_extension( dataset.extension.lower() )
- trans.response.set_content_type( mime )
+ trans.response.set_content_type( data.get_mime() )
return open( dataset.file_name )
else:
# Get rating data.
--- a/lib/galaxy/web/controllers/library_common.py Wed Sep 28 10:47:54 2011 -0400
+++ b/lib/galaxy/web/controllers/library_common.py Wed Sep 28 10:56:30 2011 -0400
@@ -1404,8 +1404,7 @@
kwd['do_action'] = 'zip'
return self.act_on_multiple_datasets( trans, cntrller, library_id, ldda_ids=[id,], **kwd )
else:
- mime = trans.app.datatypes_registry.get_mimetype_by_extension( ldda.extension.lower() )
- trans.response.set_content_type( mime )
+ trans.response.set_content_type( ldda.get_mime() )
fStat = os.stat( ldda.file_name )
trans.response.headers[ 'Content-Length' ] = int( fStat.st_size )
valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
--- a/lib/galaxy/web/controllers/root.py Wed Sep 28 10:47:54 2011 -0400
+++ b/lib/galaxy/web/controllers/root.py Wed Sep 28 10:56:30 2011 -0400
@@ -241,8 +241,7 @@
if data:
current_user_roles = trans.get_current_user_roles()
if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ):
- mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
- trans.response.set_content_type(mime)
+ trans.response.set_content_type(data.get_mime())
if tofile:
fStat = os.stat(data.file_name)
trans.response.headers['Content-Length'] = int(fStat.st_size)
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