commit/galaxy-central: jgoecks: Fix problems with computing indices for GFF/GTF datasets.
by Bitbucket
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.
11 years, 4 months
commit/galaxy-central: natefoo: Fix for a minor bug in e28ebc25b2e7
by Bitbucket
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.
11 years, 4 months
commit/galaxy-central: jgoecks: Trackster: fixes for adding a dataset to a new visualization.
by Bitbucket
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.
11 years, 4 months
commit/galaxy-central: greg: Two minor fixes.
by Bitbucket
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.
11 years, 4 months
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
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.
11 years, 4 months
commit/galaxy-central: jgoecks: 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.
by Bitbucket
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.
11 years, 4 months
commit/galaxy-central: natefoo: Don't include purged histories in usage calculation.
by Bitbucket
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.
11 years, 4 months
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
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.
11 years, 4 months
commit/galaxy-central: natefoo: Fix for the mime type when a dataset instance's extension is None.
by Bitbucket
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.
11 years, 4 months