galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
April 2011
- 1 participants
- 112 discussions
commit/galaxy-central: greg: Fixes for transferring files from external services using the http protocol. Automatic file transfers from Pac Bio SMRT Portal are functional for version 1.1.0.
by Bitbucket 14 Apr '11
by Bitbucket 14 Apr '11
14 Apr '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/5affe61170f7/
changeset: r5391:5affe61170f7
user: greg
date: 2011-04-14 22:42:12
summary: Fixes for transferring files from external services using the http protocol. Automatic file transfers from Pac Bio SMRT Portal are functional for version 1.1.0.
affected #: 8 files (2.5 KB)
--- a/external_service_types/pacific_biosciences_smrt_portal.xml Thu Apr 14 14:34:39 2011 -0400
+++ b/external_service_types/pacific_biosciences_smrt_portal.xml Thu Apr 14 16:42:12 2011 -0400
@@ -2,9 +2,6 @@
<description></description><version>1</version><data_transfer_settings>
- <!--
- <data_transfer protocol='scp' automatic_transfer='True' host='host' user_name='user_name' password='password' data_location='data_location' />
- --><data_transfer protocol='http' automatic_transfer='True' /></data_transfer_settings><run_details>
--- a/lib/galaxy/jobs/deferred/data_transfer.py Thu Apr 14 14:34:39 2011 -0400
+++ b/lib/galaxy/jobs/deferred/data_transfer.py Thu Apr 14 16:42:12 2011 -0400
@@ -4,8 +4,6 @@
import logging, urllib2, re, shutil
from galaxy import eggs
-from galaxy.util import json
-from string import Template
from sqlalchemy import and_
from galaxy.util.odict import odict
@@ -19,6 +17,8 @@
log = logging.getLogger( __name__ )
+__all__ = [ 'DataTransfer' ]
+
class DataTransfer( object ):
check_interval = 15
dataset_name_re = re.compile( '(dataset\d+)_(name)' )
@@ -36,7 +36,10 @@
if job.params[ 'protocol' ] in [ 'http', 'https' ]:
results = []
for result in job.params[ 'results' ].values():
- result[ 'transfer_job' ] = self.app.transfer_manager.new( protocol=job.params[ 'protocol' ], url=result[ 'url' ] )
+ result[ 'transfer_job' ] = self.app.transfer_manager.new( protocol=job.params[ 'protocol' ],
+ name=result[ 'name' ],
+ datatype=result[ 'datatype' ],
+ url=result[ 'url' ] )
results.append( result )
elif job.params[ 'protocol' ] == 'scp':
results = []
@@ -83,9 +86,9 @@
# Update the state of the relevant SampleDataset
new_status = self.app.model.SampleDataset.transfer_status.ADD_TO_LIBRARY
if protocol in [ 'http', 'https' ]:
- result_dict = job.params[ 'results' ]
- library_dataset_name = job.params[ 'result' ][ 'name' ]
- extension = job.params[ 'result' ][ 'datatype' ]
+ result_dict = job.params[ 'result' ]
+ library_dataset_name = result_dict[ 'name' ]
+ extension = result_dict[ 'datatype' ]
elif protocol in [ 'scp' ]:
# In this case, job.params will be a dictionary that contains a key named 'result'. The value
# of the result key is a dictionary that looks something like:
--- a/lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py Thu Apr 14 14:34:39 2011 -0400
+++ b/lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py Thu Apr 14 16:42:12 2011 -0400
@@ -3,6 +3,9 @@
produced by SMRT Portal.
"""
import logging, urllib2, re, shutil
+from string import Template
+from galaxy.util import json
+
from data_transfer import *
log = logging.getLogger( __name__ )
@@ -18,9 +21,16 @@
sample = kwd[ 'sample' ]
smrt_job_id = kwd[ 'secondary_analysis_job_id' ]
external_service = sample.request.type.get_external_service( 'pacific_biosciences_smrt_portal' )
+ external_service.load_data_transfer_settings( trans )
+ http_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.HTTP ]
+ if not http_configs[ 'automatic_transfer' ]:
+ raise Exception( "Manual data transfer using http is not yet supported." )
smrt_host = external_service.form_values.content[ 'host' ]
- external_service_type_id = external_service.external_service_type_id
- external_service_type = self.app.external_service_types.all_external_service_types[ external_service_type_id ]
+ external_service_type = external_service.get_external_service_type( trans )
+ # TODO: is there a better way to store the protocol?
+ # external_service_type.data_transfer looks somethng like
+ # {'http': <galaxy.sample_tracking.data_transfer.HttpDataTransferFactory object at 0x1064239d0>}
+ protocol = external_service_type.data_transfer.keys()[0]
results = {}
for k, v in external_service.form_values.content.items():
match = self.dataset_name_re.match( k ) or self.dataset_datatype_re.match( k )
@@ -42,6 +52,7 @@
self.sa_session.add(sample)
self.sa_session.flush()
params = { 'type' : 'init_transfer',
+ 'protocol' : protocol,
'sample_id' : sample.id,
'results' : results,
'smrt_host' : smrt_host,
@@ -50,6 +61,7 @@
self._associate_untransferred_datasets_with_sample( sample, external_service, results )
elif 'transfer_job_id' in kwd:
params = { 'type' : 'finish_transfer',
+ 'protocol' : kwd[ 'result' ][ 'protocol' ],
'sample_id' : kwd[ 'sample_id' ],
'result' : kwd[ 'result' ],
'transfer_job_id' : kwd[ 'transfer_job_id' ] }
--- a/lib/galaxy/jobs/transfer_manager.py Thu Apr 14 14:34:39 2011 -0400
+++ b/lib/galaxy/jobs/transfer_manager.py Thu Apr 14 16:42:12 2011 -0400
@@ -30,14 +30,13 @@
if protocol in [ 'http', 'https' ]:
if 'url' not in kwd:
raise Exception( 'Missing required parameter "url".' )
- transfer_job = self.app.model.TransferJob( state=self.app.model.TransferJob.states.NEW, params=kwd )
elif protocol == 'scp':
# TODO: add more checks here?
if 'sample_dataset_id' not in kwd:
raise Exception( 'Missing required parameter "sample_dataset_id".' )
if 'file_path' not in kwd:
raise Exception( 'Missing required parameter "file_path".' )
- transfer_job = self.app.model.TransferJob( state=self.app.model.TransferJob.states.NEW, params=kwd )
+ transfer_job = self.app.model.TransferJob( state=self.app.model.TransferJob.states.NEW, params=kwd )
self.sa_session.add( transfer_job )
self.sa_session.flush()
return transfer_job
--- a/lib/galaxy/model/__init__.py Thu Apr 14 14:34:39 2011 -0400
+++ b/lib/galaxy/model/__init__.py Thu Apr 14 16:42:12 2011 -0400
@@ -1825,6 +1825,11 @@
scp_configs[ 'data_location' ] = self.form_values.content.get( data_transfer_obj.config.get( 'data_location', '' ), '' )
scp_configs[ 'rename_dataset' ] = self.form_values.content.get( data_transfer_obj.config.get( 'rename_dataset', '' ), '' )
self.data_transfer[ self.data_transfer_protocol.SCP ] = scp_configs
+ if data_transfer_protocol == self.data_transfer_protocol.HTTP:
+ http_configs = {}
+ automatic_transfer = data_transfer_obj.config.get( 'automatic_transfer', 'false' )
+ http_configs[ 'automatic_transfer' ] = util.string_as_bool( automatic_transfer )
+ self.data_transfer[ self.data_transfer_protocol.HTTP ] = http_configs
def populate_actions( self, trans, item, param_dict=None ):
return self.get_external_service_type( trans ).actions.populate( self, item, param_dict=param_dict )
--- a/lib/galaxy/sample_tracking/data_transfer.py Thu Apr 14 14:34:39 2011 -0400
+++ b/lib/galaxy/sample_tracking/data_transfer.py Thu Apr 14 16:42:12 2011 -0400
@@ -27,12 +27,23 @@
# Validate
for name, value in self.config.items():
assert value, "'%s' attribute missing in 'data_transfer' element of type 'scp' in external_service_type xml config file: '%s'." % ( name, config_file )
-
+
+class HttpDataTransferFactory( DataTransferFactory ):
+ type = 'http'
+ def __init__( self ):
+ pass
+ def parse( self, config_file, elem ):
+ self.config = {}
+ self.config[ 'automatic_transfer' ] = elem.get( 'automatic_transfer' )
+ # Validate
+ for name, value in self.config.items():
+ assert value, "'%s' attribute missing in 'data_transfer' element of type 'http' in external_service_type xml config file: '%s'." % ( name, config_file )
+
class FtpDataTransferFactory( DataTransferFactory ):
type = 'ftp'
def __init__( self ):
pass
def parse( self, elem ):
pass
-
-data_transfer_factories = dict( [ ( data_transfer.type, data_transfer() ) for data_transfer in [ ScpDataTransferFactory, FtpDataTransferFactory ] ] )
+
+data_transfer_factories = dict( [ ( data_transfer.type, data_transfer() ) for data_transfer in [ ScpDataTransferFactory, HttpDataTransferFactory, FtpDataTransferFactory ] ] )
--- a/lib/galaxy/sample_tracking/external_service_types.py Thu Apr 14 14:34:39 2011 -0400
+++ b/lib/galaxy/sample_tracking/external_service_types.py Thu Apr 14 16:42:12 2011 -0400
@@ -84,12 +84,16 @@
def parse_data_transfer_settings( self, root ):
self.data_transfer = {}
data_transfer_settings_elem = root.find( 'data_transfer_settings' )
- # Currently only data transfer using scp is supported.
+ # Currently only data transfer using scp or http is supported.
for data_transfer_elem in data_transfer_settings_elem.findall( "data_transfer" ):
if data_transfer_elem.get( 'protocol' ) == model.ExternalService.data_transfer_protocol.SCP:
scp_data_transfer = data_transfer_factories[ model.ExternalService.data_transfer_protocol.SCP ]
scp_data_transfer.parse( self.config_file, data_transfer_elem )
self.data_transfer[ model.ExternalService.data_transfer_protocol.SCP ] = scp_data_transfer
+ if data_transfer_elem.get( 'protocol' ) == model.ExternalService.data_transfer_protocol.HTTP:
+ http_data_transfer = data_transfer_factories[ model.ExternalService.data_transfer_protocol.HTTP ]
+ http_data_transfer.parse( self.config_file, data_transfer_elem )
+ self.data_transfer[ model.ExternalService.data_transfer_protocol.HTTP ] = http_data_transfer
def parse_run_details( self, root ):
self.run_details = {}
run_details_elem = root.find( 'run_details' )
--- a/lib/galaxy/web/controllers/requests_admin.py Thu Apr 14 14:34:39 2011 -0400
+++ b/lib/galaxy/web/controllers/requests_admin.py Thu Apr 14 16:42:12 2011 -0400
@@ -671,7 +671,7 @@
if not scp_configs[ 'automatic_transfer' ]:
deferred_plugin = 'ManualDataTransferPlugin'
else:
- raise Exception( "Automatic data transfer using scp is not yet suppored." )
+ raise Exception( "Automatic data transfer using scp is not yet supported." )
trans.app.job_manager.deferred_job_queue.plugins[ deferred_plugin ].create_job( trans,
sample=sample,
sample_datasets=sample_datasets,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Create and use ReferenceTrackDataManager to fetch ReferenceTrack data.
by Bitbucket 14 Apr '11
by Bitbucket 14 Apr '11
14 Apr '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b20ed3ccbba2/
changeset: r5390:b20ed3ccbba2
user: jgoecks
date: 2011-04-14 20:34:39
summary: Create and use ReferenceTrackDataManager to fetch ReferenceTrack data.
affected #: 1 file (383 bytes)
--- a/static/scripts/trackster.js Thu Apr 14 14:29:32 2011 -0400
+++ b/static/scripts/trackster.js Thu Apr 14 14:34:39 2011 -0400
@@ -244,11 +244,6 @@
* Load data from server; returns AJAX object so that use of Deferred is possible.
*/
load_data: function(chrom, low, high, mode, resolution, extra_params) {
- if (this.track.track_type == "ReferenceTrack" && resolution > 1) {
- // Now that data is pre-fetched before draw, we don't load reference tracks
- // unless it's at the bottom level
- return;
- }
// Setup data request params.
var params = {"chrom": chrom, "low": low, "high": high, "mode": mode,
"resolution": resolution, "dataset_id" : this.track.dataset_id,
@@ -346,6 +341,20 @@
}
});
+var ReferenceTrackDataManager = function(num_elements, track, subset) {
+ DataManager.call(this, num_elements, track, subset);
+};
+extend(ReferenceTrackDataManager.prototype, DataManager.prototype, Cache.prototype, {
+ load_data: function(chrom, low, high, mode, resolution, extra_params) {
+ if (resolution > 1) {
+ // Now that data is pre-fetched before draw, we don't load reference tracks
+ // unless it's at the bottom level
+ return;
+ }
+ return DataManager.prototype.load_data.call(this, chrom, low, high, mode, resolution, extra_params);
+ }
+});
+
/**
* View object manages complete viz view, including tracks and user interactions.
*/
@@ -1979,7 +1988,7 @@
this.content_div.css("border", "none");
this.data_url = reference_url;
this.data_url_extra_params = {dbkey: view.dbkey};
- this.data_cache = new DataManager(CACHED_DATA, this, false);
+ this.data_cache = new ReferenceTrackDataManager(CACHED_DATA, this, false);
this.tile_cache = new Cache(CACHED_TILES_LINE);
};
extend(ReferenceTrack.prototype, TiledTrack.prototype, {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
14 Apr '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/49e97cc2ac1f/
changeset: r5389:49e97cc2ac1f
user: jgoecks
date: 2011-04-14 20:29:32
summary: Trackster: (a) fix bug in acee660871cd that prevented line tracks from displaying properly and (b) set track height in show_tile rather than draw_tile, which obviates the need for parent_element to be passed to draw_tile.
affected #: 2 files (1.8 KB)
--- a/static/scripts/packed/trackster.js Thu Apr 14 10:37:42 2011 -0400
+++ b/static/scripts/packed/trackster.js Thu Apr 14 14:29:32 2011 -0400
@@ -1,1 +1,1 @@
-var extend=function(){var c=arguments[0];for(var b=1;b<arguments.length;b++){var a=arguments[b];for(key in a){c[key]=a[key]}}return c};var trackster_module=function(f,P){var o=f("slotting"),F=f("painters");var V=function(W,X){this.document=W;this.default_font=X!==undefined?X:"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")};extend(V.prototype,{load_pattern:function(W,aa){var X=this.patterns,Y=this.dummy_context,Z=new Image();Z.src=image_path+aa;Z.onload=function(){X[W]=Y.createPattern(Z,"repeat")}},get_pattern:function(W){return this.patterns[W]},new_canvas:function(){var W=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(W)}W.manager=this;return W}});var A=function(W,X){W.bind("drag",{handle:X,relative:true},function(ab,ac){var aa=$(this).parent();var Z=aa.children();var Y;for(Y=0;Y<Z.length;Y++){if(ac.offsetY<$(Z.get(Y)).position().top){break}}if(Y===Z.length){if(this!==Z.get(Y-1)){aa.append(this)}}else{if(this!==Z.get(Y)){$(this).insertBefore(Z.get(Y))}}})};var h=function(Y,W){var X=W-Y;return(X<=2?0.01:(X<=100?1:(X<=1000?5:10)))};var B=9,y=10,K=B+2,v=100,C=12000,I=200,r=10,E=5000,s=100,m="There was an error in indexing this dataset. ",D="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",z="No data for this chrom/contig.",p="Currently indexing... please wait",u="Tool cannot be rerun: ",a="Loading data...",Q="Ready for display",d=10,q=5,x=5;function t(W){return Math.round(W*1000)/1000}var c=function(W){this.num_elements=W;this.clear()};extend(c.prototype,{get:function(X){var W=this.key_ary.indexOf(X);if(W!==-1){this.move_key_to_end(X,W)}return this.obj_cache[X]},set:function(X,Y){if(!this.obj_cache[X]){if(this.key_ary.length>=this.num_elements){var W=this.key_ary.shift();delete this.obj_cache[W]}this.key_ary.push(X)}this.obj_cache[X]=Y;return Y},move_key_to_end:function(X,W){this.key_ary.splice(W,1);this.key_ary.push(X)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var J=function(X,W,Y){c.call(this,X);this.track=W;this.subset=(Y!==undefined?Y:true)};extend(J.prototype,c.prototype,{load_data:function(ae,af,aa,ad,X,ac){var Z={chrom:ae,low:af,high:aa,mode:ad,resolution:X,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(Z,ac);if(this.track.filters_manager){var ag=[];var W=this.track.filters_manager.filters;for(var ab=0;ab<W.length;ab++){ag[ag.length]=W[ab].name}Z.filter_cols=JSON.stringify(ag)}var Y=this;return $.getJSON(this.track.data_url,Z,function(ah){Y.set_data(af,aa,ad,ah)})},get_data:function(Y,W,ab,ac,X,aa){var Z=this.get(this.gen_key(W,ab,ac));if(Z){return Z}Z=this.load_data(Y,W,ab,ac,X,aa);this.set_data(W,ab,ac,Z);return Z},set_data:function(X,Y,Z,W){return this.set(this.gen_key(X,Y,Z),W)},gen_key:function(W,Y,Z){var X=W+"_"+Y+"_"+Z;return X},split_key:function(W){return W.split("_")}});var U=function(W,Z,Y,X,aa){this.container=W;this.chrom=null;this.vis_id=Y;this.dbkey=X;this.title=Z;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(aa);this.canvas_manager=new V(W.get(0).ownerDocument);this.reset()};extend(U.prototype,{init:function(Z){var Y=this.container,W=this;this.top_container=$("<div/>").addClass("top-container").appendTo(Y);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(Y);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(Y);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();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 X=function(aa){if(aa.type==="focusout"||(aa.keyCode||aa.which)===13||(aa.keyCode||aa.which)===27){if((aa.keyCode||aa.which)!==27){W.go_to($(this).val())}$(this).hide();$(this).val("");W.location_span.show();W.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",X).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.bind("click",function(){W.location_span.hide();W.chrom_select.hide();W.nav_input.val(W.chrom+":"+W.low+"-"+W.high);W.nav_input.css("display","inline-block");W.nav_input.select();W.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(){W.zoom_out();W.redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){W.zoom_in();W.redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},Z);this.chrom_select.bind("change",function(){W.change_chrom(W.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(aa){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(aa){W.zoom_in(aa.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aa,ab){this.current_x=ab.offsetX}).bind("drag",function(aa,ac){var ad=ac.offsetX-this.current_x;this.current_x=ac.offsetX;var ab=Math.round(ad/W.viewport_container.width()*(W.max_high-W.max_low));W.move_delta(-ab)});this.overview_close.bind("click",function(){for(var ab=0,aa=W.tracks.length;ab<aa;ab++){W.tracks[ab].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",W.overview_box.height());W.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(aa,ab){if(aa.clientX>W.viewport_container.width()-16){return false}}).bind("dragstart",function(aa,ab){ab.original_low=W.low;ab.current_height=aa.clientY;ab.current_x=ab.offsetX}).bind("drag",function(ac,ae){var aa=$(this);var af=ae.offsetX-ae.current_x;var ab=aa.scrollTop()-(ac.clientY-ae.current_height);aa.scrollTop(ab);ae.current_height=ac.clientY;ae.current_x=ae.offsetX;var ad=Math.round(af/W.viewport_container.width()*(W.high-W.low));W.move_delta(ad)}).bind("mousewheel",function(ac,ae,ab,aa){if(ab){var ad=Math.round(-ab/W.viewport_container.width()*(W.high-W.low));W.move_delta(ad)}});this.top_labeltrack.bind("dragstart",function(aa,ab){return $("<div />").css({height:W.content_div.height()+W.top_labeltrack.height()+W.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ae,af){$(af.proxy).css({left:Math.min(ae.pageX,af.startX),width:Math.abs(ae.pageX-af.startX)});var ab=Math.min(ae.pageX,af.startX)-W.container.offset().left,aa=Math.max(ae.pageX,af.startX)-W.container.offset().left,ad=(W.high-W.low),ac=W.viewport_container.width();W.update_location(Math.round(ab/ac*ad)+W.low,Math.round(aa/ac*ad)+W.low)}).bind("dragend",function(af,ag){var ab=Math.min(af.pageX,ag.startX),aa=Math.max(af.pageX,ag.startX),ad=(W.high-W.low),ac=W.viewport_container.width(),ae=W.low;W.low=Math.round(ab/ac*ad)+ae;W.high=Math.round(aa/ac*ad)+ae;$(ag.proxy).remove();W.redraw()});this.add_label_track(new T(this,this.top_labeltrack));this.add_label_track(new T(this,this.nav_labeltrack));$(window).bind("resize",function(){W.resize_window()});$(document).bind("redraw",function(){W.redraw()});this.reset();$(window).trigger("resize")},update_location:function(W,X){this.location_span.text(commatize(W)+" - "+commatize(X));this.nav_input.val(this.chrom+":"+commatize(W)+"-"+commatize(X))},load_chroms:function(X,Y){X.num=s;$.extend(X,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var W=this;$.ajax({url:chrom_url,data:X,dataType:"json",success:function(aa){if(aa.chrom_info.length===0){alert("Invalid chromosome: "+X.chrom);return}if(aa.reference){W.add_label_track(new w(W))}W.chrom_data=aa.chrom_info;var ad='<option value="">Select Chrom/Contig</option>';for(var ac=0,Z=W.chrom_data.length;ac<Z;ac++){var ab=W.chrom_data[ac].chrom;ad+='<option value="'+ab+'">'+ab+"</option>"}if(aa.prev_chroms){ad+='<option value="previous">Previous '+s+"</option>"}if(aa.next_chroms){ad+='<option value="next">Next '+s+"</option>"}W.chrom_select.html(ad);if(Y){Y()}W.chrom_start_index=aa.start_index},error:function(){alert("Could not load chroms for this dbkey:",W.dbkey)}})},change_chrom:function(aa,X,ac){if(!aa||aa==="None"){return}var Z=this;if(aa==="previous"){Z.load_chroms({low:this.chrom_start_index-s});return}if(aa==="next"){Z.load_chroms({low:this.chrom_start_index+s});return}var ab=$.grep(Z.chrom_data,function(ae,af){return ae.chrom===aa})[0];if(ab===undefined){Z.load_chroms({chrom:aa},function(){Z.change_chrom(aa,X,ac)});return}else{if(aa!==Z.chrom){Z.chrom=aa;if(!Z.chrom){Z.intro_div.show()}else{Z.intro_div.hide()}Z.chrom_select.val(Z.chrom);Z.max_high=ab.len-1;Z.reset();Z.redraw(true);for(var ad=0,W=Z.tracks.length;ad<W;ad++){var Y=Z.tracks[ad];if(Y.init){Y.init()}}}if(X!==undefined&&ac!==undefined){Z.low=Math.max(X,0);Z.high=Math.min(ac,Z.max_high)}Z.reset_overview();Z.redraw()}},go_to:function(aa){var ae=this,W,Z,X=aa.split(":"),ac=X[0],ad=X[1];if(ad!==undefined){try{var ab=ad.split("-");W=parseInt(ab[0].replace(/,/g,""),10);Z=parseInt(ab[1].replace(/,/g,""),10)}catch(Y){return false}}ae.change_chrom(ac,W,Z)},move_fraction:function(Y){var W=this;var X=W.high-W.low;this.move_delta(Y*X)},move_delta:function(Y){var W=this;var X=W.high-W.low;if(W.low-Y<W.max_low){W.low=W.max_low;W.high=W.max_low+X}else{if(W.high-Y>W.max_high){W.high=W.max_high;W.low=W.max_high-X}else{W.high-=Y;W.low-=Y}}W.redraw()},add_track:function(W){W.view=this;W.track_id=this.track_id_counter;this.tracks.push(W);if(W.init){W.init()}W.container_div.attr("id","track_"+W.track_id);A(W.container_div,".draghandle");this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(W){W.view=this;this.label_tracks.push(W)},remove_track:function(W){this.has_changes=true;W.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(W)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(ad){var ac=this.high-this.low,ab=this.low,X=this.high;if(ab<this.max_low){ab=this.max_low}if(X>this.max_high){X=this.max_high}if(this.high!==0&&ac<this.min_separation){X=ab+this.min_separation}this.low=Math.floor(ab);this.high=Math.ceil(X);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(r,Math.max(0,Math.ceil(Math.log(this.resolution,r)/Math.log(r))));var W=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var aa=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ae=13;this.overview_box.css({left:W,width:Math.max(ae,aa)}).show();if(aa<ae){this.overview_box.css("left",W-(ae-aa)/2)}if(this.overview_highlight){this.overview_highlight.css({left:W,width:aa})}this.update_location(this.low,this.high);if(!ad){for(var Y=0,Z=this.tracks.length;Y<Z;Y++){if(this.tracks[Y]&&this.tracks[Y].enabled){this.tracks[Y].draw()}}for(Y=0,Z=this.label_tracks.length;Y<Z;Y++){this.label_tracks[Y].draw()}}},zoom_in:function(X,Y){if(this.max_high===0||this.high-this.low<this.min_separation){return}var Z=this.high-this.low,aa=Z/2+this.low,W=(Z/this.zoom_factor)/2;if(X){aa=X/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(aa-W);this.high=Math.round(aa+W);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var X=this.high-this.low,Y=X/2+this.low,W=(X*this.zoom_factor)/2;this.low=Math.round(Y-W);this.high=Math.round(Y+W);this.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.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").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()}});var n=function(X,aa){this.track=X;this.name=aa.name;this.params=[];var ai=aa.params;for(var Y=0;Y<ai.length;Y++){var ad=ai[Y],W=ad.name,ah=ad.label,Z=unescape(ad.html),af=ad.type;if(af==="number"){this.params[this.params.length]=new g(W,ah,Z,ad.min,ad.max)}else{if(af=="select"){this.params[this.params.length]=new H(W,ah,Z)}else{console.log("WARNING: unrecognized tool parameter type:",W,af)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ak){ak.stopPropagation()}).bind("click",function(ak){ak.stopPropagation()}).bind("dblclick",function(ak){ak.stopPropagation()});var ag=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ae=this.params;var ab=this;$.each(this.params,function(al,ao){var an=$("<div>").addClass("param-row").appendTo(ab.parent_div);var ak=$("<div>").addClass("param-label").text(ao.label).appendTo(an);var am=$("<div/>").addClass("slider").html(ao.html).appendTo(an);$("<div style='clear: both;'/>").appendTo(an)});this.parent_div.find("input").click(function(){$(this).select()});var aj=$("<div>").addClass("slider-row").appendTo(this.parent_div);var ac=$("<input type='submit'>").attr("value","Run").appendTo(aj);var ab=this;ac.click(function(){ab.run()})};extend(n.prototype,{get_param_values_dict:function(){var W={};this.parent_div.find(":input").each(function(){var X=$(this).attr("name"),Y=$(this).val();W[X]=JSON.stringify(Y)});return W},get_param_values:function(){var X=[];var W={};this.parent_div.find(":input").each(function(){var Y=$(this).attr("name"),Z=$(this).val();if(Y){X[X.length]=Z}});return X},run:function(){var X={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};$.extend(X,this.get_param_values_dict());var Z=this.track,Y=X.tool_id+Z.tool_region_and_parameters_str(X.chrom,X.low,X.high),aa;if(Z.track_type==="FeatureTrack"){aa=new M(Y,view,Z.hda_ldda,undefined,{},{},Z)}this.track.add_track(aa);aa.content_div.text("Starting job.");var W=function(){$.getJSON(run_tool_url,X,function(ab){if(ab==="no converter"){aa.container_div.addClass("error");aa.content_div.text(D)}else{if(ab.error){aa.container_div.addClass("error");aa.content_div.text(u+ab.message)}else{if(ab==="pending"){aa.container_div.addClass("pending");aa.content_div.text("Converting input data so that it can be easily reused.");setTimeout(W,2000)}else{aa.dataset_id=ab.dataset_id;aa.content_div.text("Running job.");aa.init()}}}})};W()}});var H=function(X,W,Y){this.name=X;this.label=W;this.html=Y};var g=function(Y,X,aa,Z,W){H.call(this,Y,X,aa);this.min=Z;this.max=W};var j=function(X,W,Y){this.name=X;this.index=W;this.value=Y};var N=function(X,W){this.name=X;this.index=W;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};extend(N.prototype,{applies_to:function(W){if(W.length>this.index){return true}return false},keep:function(W){if(!this.applies_to(W)){return true}return(W[this.index]>=this.low&&W[this.index]<=this.high)},update_attrs:function(X){var W=false;if(!this.applies_to(X)){return W}if(X[this.index]<this.min){this.min=Math.floor(X[this.index]);W=true}if(X[this.index]>this.max){this.max=Math.ceil(X[this.index]);W=true}return W},update_ui_elt:function(){var X=this.slider.slider("option","min"),W=this.slider.slider("option","max");if(this.min<X||this.max>W){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",h(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var S=function(Y,ae){this.track=Y;this.filters=[];for(var aa=0;aa<ae.length;aa++){var W=ae[aa];var X=W.name,ad=W.type,ab=W.index;if(ad==="int"||ad==="float"){this.filters[aa]=new N(X,ab)}else{this.filters[aa]=new j(X,ab,ad)}}var ac=function(af,ag,ah){af.click(function(){var ai=ag.text();max=parseFloat(ah.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(ah.slider("option","values")){input_size=2*input_size+1;multi_value=true}ag.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",ai).appendTo(ag).focus().select().click(function(aj){aj.stopPropagation()}).blur(function(){$(this).remove();ag.text(ai)}).keyup(function(an){if(an.keyCode===27){$(this).trigger("blur")}else{if(an.keyCode===13){var al=ah.slider("option","min"),aj=ah.slider("option","max"),am=function(ao){return(isNaN(ao)||ao>aj||ao<al)},ak=$(this).val();if(!multi_value){ak=parseFloat(ak);if(am(ak)){alert("Parameter value must be in the range ["+al+"-"+aj+"]");return $(this)}}else{ak=ak.split("-");ak=[parseFloat(ak[0]),parseFloat(ak[1])];if(am(ak[0])||am(ak[1])){alert("Parameter value must be in the range ["+al+"-"+aj+"]");return $(this)}}ah.slider((multi_value?"values":"value"),ak)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(af){af.stopPropagation()}).bind("click",function(af){af.stopPropagation()}).bind("dblclick",function(af){af.stopPropagation()});var Z=this;$.each(this.filters,function(al,ag){var ai=$("<div/>").addClass("slider-row").appendTo(Z.parent_div);var af=$("<div/>").addClass("slider-label").appendTo(ai);var an=$("<span/>").addClass("slider-name").text(ag.name+" ").appendTo(af);var ah=$("<span/>");var aj=$("<span/>").addClass("slider-value").appendTo(af).append("[").append(ah).append("]");var am=$("<div/>").addClass("slider").appendTo(ai);ag.control_element=$("<div/>").attr("id",ag.name+"-filter-control").appendTo(am);var ak=[0,0];ag.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(ao,ap){ak=ap.values;ah.text(ap.values[0]+"-"+ap.values[1]);setTimeout(function(){if(ap.values[0]==ak[0]&&ap.values[1]==ak[1]){var aq=ap.values;ah.text(aq[0]+"-"+aq[1]);ag.low=aq[0];ag.high=aq[1];Z.track.draw(true,true)}},50)},change:function(ao,ap){ag.control_element.slider("option","slide").call(ag.control_element,ao,ap)}});ag.slider=ag.control_element;ag.slider_label=ah;ac(aj,ah,ag.control_element);$("<div style='clear: both;'/>").appendTo(ai)})};var R=function(W){this.track=W.track;this.params=W.params;this.values={};if(W.saved_values){this.restore_values(W.saved_values)}this.onchange=W.onchange};extend(R.prototype,{restore_values:function(W){var X=this;$.each(this.params,function(Y,Z){if(W[Z.key]!==undefined){X.values[Z.key]=W[Z.key]}else{X.values[Z.key]=Z.default_value}})},build_form:function(){var X=this;var W=$("<div />");$.each(this.params,function(ab,Z){if(!Z.hidden){var Y="param_"+ab;var ag=$("<div class='form-row' />").appendTo(W);ag.append($("<label />").attr("for",Y).text(Z.label+":"));if(Z.type==="bool"){ag.append($('<input type="checkbox" />').attr("id",Y).attr("name",Y).attr("checked",X.values[Z.key]))}else{if(Z.type==="color"){var ad=X.values[Z.key];var ac=$("<input />").attr("id",Y).attr("name",Y).val(ad);var ae=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var aa=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ae);var af=$("<div/>").appendTo(aa).farbtastic({width:100,height:100,callback:ac,color:ad});$("<div />").append(ac).append(ae).appendTo(ag).bind("click",function(ah){ae.css({left:$(this).position().left+($(ac).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ae.hide();$(document).unbind("click.color-picker")});ah.stopPropagation()})}else{ag.append($("<input />").attr("id",Y).attr("name",Y).val(X.values[Z.key]))}}}});return W},update_from_form:function(W){var Y=this;var X=false;$.each(this.params,function(Z,ab){if(!ab.hidden){var ac="param_"+Z;var aa=W.find("#"+ac).val();if(ab.type==="float"){aa=parseFloat(aa)}else{if(ab.type==="int"){aa=parseInt(aa)}else{if(ab.type==="bool"){aa=W.find("#"+ac).is(":checked")}}}if(aa!==Y.values[ab.key]){Y.values[ab.key]=aa;X=true}}});if(X){this.onchange()}}});var b=function(W,X){this.track=W;this.canvas=X};var k=function(X,W,aa,Y,Z){this.name=X;this.view=W;this.parent_element=aa;this.data_url=(Y?Y:default_data_url);this.data_url_extra_params={};this.data_query_wait=(Z?Z:E);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").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 class='draghandle' />").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)};extend(k.prototype,{init:function(){var W=this;W.enabled=false;W.tile_cache.clear();W.data_cache.clear();W.initial_canvas=undefined;W.content_div.css("height","auto");W.container_div.removeClass("nodata error pending");if(!W.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:W.hda_ldda,dataset_id:W.dataset_id,chrom:W.view.chrom},function(X){if(!X||X==="error"||X.kind==="error"){W.container_div.addClass("error");W.content_div.text(m);if(X.message){var Z=W.view.tracks.indexOf(W);var Y=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+X.message+"</pre>",{Close:hide_modal})});W.content_div.append(Y)}}else{if(X==="no converter"){W.container_div.addClass("error");W.content_div.text(D)}else{if(X==="no data"||(X.data!==undefined&&(X.data===null||X.data.length===0))){W.container_div.addClass("nodata");W.content_div.text(z)}else{if(X==="pending"){W.container_div.addClass("pending");W.content_div.text(p);setTimeout(function(){W.init()},W.data_query_wait)}else{if(X.status==="data"){if(X.valid_chroms){W.valid_chroms=X.valid_chroms;W.make_name_popup_menu()}W.content_div.text(Q);if(W.view.chrom){W.content_div.text("");W.content_div.css("height",W.height_px+"px");W.enabled=true;$.when(W.predraw_init()).done(function(){W.container_div.removeClass("nodata error pending");W.draw()})}}}}}}})},predraw_init:function(){},update_name:function(W){this.old_name=this.name;this.name=W;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var G=function(ae,ac,af){var X=this,ag=X.view;this.filters_manager=(ae!==undefined?new S(this,ae):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(ac!==undefined&&obj_length(ac)>0?new n(this,ac):undefined);this.parent_track=af;this.child_tracks=[];if(X.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}X.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();X.container_div.append(X.child_tracks_container);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(X.display_modes!==undefined){if(X.mode_div===undefined){X.mode_div=$("<div class='right-float menubutton popup' />").appendTo(X.header_div);var Z=(X.track_config&&X.track_config.values.mode?X.track_config.values.mode:X.display_modes[0]);X.mode=Z;X.mode_div.text(Z);var Y=function(ah){X.mode_div.text(ah);X.mode=ah;X.track_config.values.mode=ah;X.tile_cache.clear();X.draw()};var W={};for(var aa=0,ad=X.display_modes.length;aa<ad;aa++){var ab=X.display_modes[aa];W[ab]=function(ah){return function(){Y(ah)}}(ab)}make_popupmenu(X.mode_div,W)}else{X.mode_div.hide()}}this.make_name_popup_menu()};extend(G.prototype,k.prototype,{make_name_popup_menu:function(){var X=this;var W={};W["Edit configuration"]=function(){var ad=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ab=function(){X.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(ae){if((ae.keyCode||ae.which)===27){ad()}else{if((ae.keyCode||ae.which)===13){ab()}}};$(window).bind("keypress.check_enter_esc",ac);show_modal("Configure Track",X.track_config.build_form(),{Cancel:ad,OK:ab})};if(X.filters_available>0){var aa=(X.filters_div.is(":visible")?"Hide filters":"Show filters");W[aa]=function(){X.filters_visible=(X.filters_div.is(":visible"));X.filters_div.toggle();X.make_name_popup_menu()}}if(X.tool){var aa=(X.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");W[aa]=function(){if(!X.dynamic_tool_div.is(":visible")){X.update_name(X.name+X.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";X.revert_name()}X.dynamic_tool_div.toggle();X.make_name_popup_menu()}}if(X.valid_chroms){W["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+X.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var Y=view;var Z=function(){$("#no-tracks").show()};if(this.parent_track){Y=this.parent_track;Z=function(){}}W.Remove=function(){Y.remove_track(X);if(Y.num_tracks===0){Z()}};make_popupmenu(X.name_div,W)},draw:function(W,Z){var an=this.view.low,ac=this.view.high,ae=ac-an,ag=this.view.container.width(),ab=ag/ae,ah=this.view.resolution,aa=$("<div style='position: relative;'></div>");if(!Z){this.content_div.children().remove()}this.content_div.append(aa);this.max_height=0;var aj=Math.floor(an/ah/I);var Y={};while((aj*I*ah)<ac){var am=ag+"_"+ab+"_"+aj;var ad=this.tile_cache.get(am);var ak=aj*I*this.view.resolution;var X=ak+I*this.view.resolution;if(!W&&ad){this.show_tile(ad,aa,ak,ab)}else{this.delayed_draw(W,am,ak,X,aj,ah,aa,ab,Y)}aj+=1}var af=this;var al=setInterval(function(){if(obj_length(Y)===0){clearInterval(al);if(Z){var aq=af.content_div.children();var ap=false;for(var ar=aq.length-1,ao=0;ar>=ao;ar--){var aw=$(aq[ar]);if(ap){aw.remove()}else{if(aw.children().length!==0){ap=true}}}}if(af.filters_manager){var au=af.filters_manager.filters;for(var av=0;av<au.length;av++){au[av].update_ui_elt()}var at=false;if(af.example_feature){for(var av=0;av<au.length;av++){if(au[av].applies_to(af.example_feature)){at=true;break}}}if(af.filters_available!==at){af.filters_available=at;if(!af.filters_available){af.filters_div.hide()}af.make_name_popup_menu()}}}},50);for(var ai=0;ai<this.child_tracks.length;ai++){this.child_tracks[ai].draw(W,Z)}},delayed_draw:function(X,ae,ac,ag,Y,aa,af,ah,ab){var Z=this;var ad=function(ap,ai,ak,aj,an,ao,al){returned_tile=Z.draw_tile(ai,ak,aj,an,ao,al);var am=$("<div class='track-tile'>").prepend(returned_tile);tile_element=am;Z.tile_cache.set(ae,tile_element);Z.show_tile(tile_element,an,ac,ao);delete ab[ap]};var W=setTimeout(function(){if(ac<=Z.view.high&&ag>=Z.view.low){var ai=(X?undefined:Z.tile_cache.get(ae));if(ai){Z.show_tile(ai,af,ac,ah);delete ab[W]}else{$.when(Z.data_cache.get_data(view.chrom,ac,ag,Z.mode,aa,Z.data_url_extra_params)).then(function(aj){if(view.reference_track&&ah>view.canvas_manager.char_width_px){$.when(view.reference_track.data_cache.get_data(view.chrom,ac,ag,Z.mode,aa,view.reference_track.data_url_extra_params)).then(function(ak){ad(W,aj,aa,Y,af,ah,ak)})}else{ad(W,aj,aa,Y,af,ah)}})}}},50);ab[W]=true},show_tile:function(W,ab,Z,ac){var X=this;var Y=this.view.high-this.view.low,aa=(Z-this.view.low)*ac;if(this.left_offset){aa-=this.left_offset}W.css({position:"absolute",top:0,left:aa,height:""});ab.append(W);X.max_height=Math.max(X.max_height,W.height());X.content_div.css("height",X.max_height+"px");ab.children().css("height",X.max_height+"px")},set_overview:function(){var W=this.view;if(this.initial_canvas&&this.is_overview){W.overview_close.show();W.overview_viewport.append(this.initial_canvas);W.overview_highlight.show().height(this.initial_canvas.height());W.overview_viewport.height(this.initial_canvas.height()+W.overview_box.height())}$(window).trigger("resize")},tool_region_and_parameters_str:function(Y,W,Z){var X=this,aa=(Y!==undefined&&W!==undefined&&Z!==undefined?Y+":"+W+"-"+Z:"all");return" - region=["+aa+"], parameters=["+X.tool.get_param_values().join(", ")+"]"},add_track:function(W){W.track_id=this.track_id+"_"+this.child_tracks.length;W.container_div.attr("id","track_"+W.track_id);this.child_tracks_container.append(W.container_div);A(W.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(W);this.view.has_changes=true},remove_track:function(W){W.container_div.fadeOut("slow",function(){$(this).remove()})}});var T=function(W,X){this.track_type="LabelTrack";this.hidden=true;k.call(this,null,W,X);this.container_div.addClass("label-track")};extend(T.prototype,k.prototype,{draw:function(){var Y=this.view,Z=Y.high-Y.low,ac=Math.floor(Math.pow(10,Math.floor(Math.log(Z)/Math.log(10)))),W=Math.floor(Y.low/ac)*ac,aa=this.view.container.width(),X=$("<div style='position: relative; height: 1.3em;'></div>");while(W<Y.high){var ab=(W-Y.low)/Z*aa;X.append($("<div class='label'>"+commatize(W)+"</div>").css({position:"absolute",left:ab-1}));W+=ac}this.content_div.children(":first").remove();this.content_div.append(X)}});var w=function(W){this.track_type="ReferenceTrack";this.hidden=true;k.call(this,null,W,W.top_labeltrack);G.call(this);W.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:W.dbkey};this.data_cache=new J(x,this,false);this.tile_cache=new c(q)};extend(w.prototype,G.prototype,{draw_tile:function(ag,ab,X,ad,ah){var aa=this,Y=I*ab;if(ah>this.view.canvas_manager.char_width_px){if(ag===null){aa.content_div.css("height","0px");return}var Z=this.view.canvas_manager.new_canvas();var af=Z.getContext("2d");Z.width=Math.ceil(Y*ah+aa.left_offset);Z.height=aa.height_px;af.font=af.canvas.manager.default_font;af.textAlign="center";for(var ac=0,ae=ag.length;ac<ae;ac++){var W=Math.round(ac*ah);af.fillText(ag[ac],W+aa.left_offset,10)}return Z}this.content_div.css("height","0px")}});var l=function(aa,Y,ab,W,Z){var X=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";k.call(this,aa,Y,Y.viewport_container);G.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=ab;this.dataset_id=W;this.original_dataset_id=W;this.data_cache=new J(x,this);this.tile_cache=new c(q);this.track_config=new R({track:this,params:[{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:Z,onchange:function(){X.vertical_range=X.prefs.max_value-X.prefs.min_value;$("#linetrack_"+X.track_id+"_minval").text(X.prefs.min_value);$("#linetrack_"+X.track_id+"_maxval").text(X.prefs.max_value);X.tile_cache.clear();X.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};extend(l.prototype,G.prototype,{add_resize_handle:function(){var W=this;var Z=false;var Y=false;var X=$("<div class='track-resize'>");$(W.container_div).hover(function(){Z=true;X.show()},function(){Z=false;if(!Y){X.hide()}});X.hide().bind("dragstart",function(aa,ab){Y=true;ab.original_height=$(W.content_div).height()}).bind("drag",function(ab,ac){var aa=Math.min(Math.max(ac.original_height+ac.deltaY,W.min_height_px),W.max_height_px);$(W.content_div).css("height",aa);W.height_px=aa;W.draw(true)}).bind("dragend",function(aa,ab){W.tile_cache.clear();Y=false;if(!Z){X.hide()}W.track_config.values.height=W.height_px}).appendTo(W.container_div)},predraw_init:function(){var W=this,X=W.view.tracks.indexOf(W);W.vertical_range=undefined;return $.getJSON(W.data_url,{stats:true,chrom:W.view.chrom,low:null,high:null,hda_ldda:W.hda_ldda,dataset_id:W.dataset_id},function(Y){W.container_div.addClass("line-track");var aa=Y.data;if(isNaN(parseFloat(W.prefs.min_value))||isNaN(parseFloat(W.prefs.max_value))){W.prefs.min_value=aa.min;W.prefs.max_value=aa.max;$("#track_"+X+"_minval").val(W.prefs.min_value);$("#track_"+X+"_maxval").val(W.prefs.max_value)}W.vertical_range=W.prefs.max_value-W.prefs.min_value;W.total_frequency=aa.total_frequency;W.container_div.find(".yaxislabel").remove();var ab=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+X+"_minval").text(t(W.prefs.min_value));var Z=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+X+"_maxval").text(t(W.prefs.max_value));Z.css({position:"absolute",top:"24px",left:"10px"});Z.prependTo(W.container_div);ab.css({position:"absolute",bottom:"2px",left:"10px"});ab.prependTo(W.container_div)})},draw_tile:function(ah,aa,X,ae,ag){if(this.vertical_range===undefined){return}var ab=X*I*aa,Z=I*aa,W=Math.ceil(Z*ag),ad=this.height_px;var Y=this.view.canvas_manager.new_canvas();Y.width=W,Y.height=ad;var af=Y.getContext("2d");var ac=new F.LinePainter(ah.data,ab,ab+Z,this.prefs,this.mode);ac.draw(af,W,ad);return Y}});var e=function(W,ab,aa,ae,ad,Y,Z,ac){var X=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];this.track_config=new R({track:this,params:[{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:ad,onchange:function(){X.tile_cache.clear();X.draw()}});this.prefs=this.track_config.values;k.call(this,W,ab,ab.viewport_container);G.call(this,Y,Z,ac);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=aa;this.dataset_id=ae;this.original_dataset_id=ae;this.zo_slots={};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_cache=new J(20,this);this.left_offset=200;this.painter=F.LinkedFeaturePainter};extend(e.prototype,G.prototype,{update_auto_mode:function(W){if(this.mode=="Auto"){if(W=="no_detail"){W="feature spans"}else{if(W=="summary_tree"){W="coverage histogram"}}this.mode_div.text("Auto ("+W+")")}},incremental_slots:function(aa,X,Z){var Y=this.view.canvas_manager.dummy_context,W=this.inc_slots[aa];if(!W||(W.mode!==Z)){W=new (o.FeatureSlotter)(aa,Z==="Pack",v,function(ab){return Y.measureText(ab)});W.mode=Z;this.inc_slots[aa]=W}return W.slot_features(X)},draw_tile:function(aj,ar,aw,ae,ag,Z){var ao=this,ay=aw*I*ar,X=(aw+1)*I*ar,al=X-ay,ap=Math.ceil(al*ag),an=this.mode,aC=25,aa=this.left_offset,ak,ab;if(an==="Auto"){if(aj.dataset_type==="summary_tree"){an=aj.dataset_type}else{if(aj.extra_info==="no_detail"){an="no_detail"}else{var aB=aj.data;if(this.view.high-this.view.low>C){an="Squish"}else{an="Pack"}}}this.update_auto_mode(an)}if(an==="summary_tree"){ab=this.summary_draw_height;ae.parent().css("height",Math.max(this.height_px,ab)+"px");this.container_div.find(".yaxislabel").remove();var W=$("<div />").addClass("yaxislabel");W.text(aj.max);W.css({position:"absolute",top:"22px",left:"10px"});W.prependTo(this.container_div);var Y=this.view.canvas_manager.new_canvas();Y.width=ap+aa;Y.height=ab+K;var az=new F.SummaryTreePainter(aj,ay,X,this.prefs);var aq=Y.getContext("2d");aq.translate(aa,K);az.draw(aq,ap,ab);return Y}var ak,ad=1;if(an==="no_detail"||an==="Squish"||an==="Pack"){ad=this.incremental_slots(ag,aj.data,an);ak=this.inc_slots[ag].slots}var af=[];if(aj.data){var ah=this.filters_manager.filters;for(var at=0,av=aj.data.length;at<av;at++){var ac=aj.data[at];var au=false;var ai;for(var ax=0,aA=ah.length;ax<aA;ax++){ai=ah[ax];ai.update_attrs(ac);if(!ai.keep(ac)){au=true;break}}if(!au){af.push(ac)}}}var az=new (this.painter)(af,ay,X,this.prefs,an,Z);var ab=az.get_required_height(ad)+y;var Y=this.view.canvas_manager.new_canvas();Y.width=ap+aa;Y.height=ab;ae.parent().css("height",Math.max(this.height_px,ab)+"px");var aq=Y.getContext("2d");aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aj.message){$(Y).css({"border-top":"1px solid red"});aq.fillStyle="red";aq.textAlign="left";var am=aq.textBaseline;aq.textBaseline="top";aq.fillText(aj.message,aa,0);aq.textBaseline=am;if(!aj.data){return Y}}this.example_feature=(aj.data.length?aj.data[0]:undefined);aq.translate(aa,y);az.draw(aq,ap,ab,ak);return Y}});var L=function(Z,X,ab,W,Y,aa){e.call(this,Z,X,ab,W,Y,aa);this.track_type="VcfTrack";this.painter=F.VariantPainter};extend(L.prototype,G.prototype,e.prototype);var O=function(Z,X,ab,W,Y,aa){e.call(this,Z,X,ab,W,Y,aa);this.track_config=new R({track:this,params:[{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:Y,onchange:function(){this.track.tile_cache.clear();this.track.draw()}});this.prefs=this.track_config.values;this.track_type="ReadTrack";this.painter=F.ReadPainter;this.make_name_popup_menu()};extend(O.prototype,G.prototype,e.prototype);var M=function(aa,Y,ac,W,Z,ab,X){e.call(this,aa,Y,ac,W,Z,ab,{},X);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};extend(M.prototype,G.prototype,e.prototype,{predraw_init:function(){var X=this;var W=function(){if(X.data_cache.size()===0){setTimeout(W,300)}else{X.data_url=default_data_url;X.data_query_wait=E;X.dataset_state_url=converted_datasets_state_url;$.getJSON(X.dataset_state_url,{dataset_id:X.dataset_id,hda_ldda:X.hda_ldda},function(Y){})}};W()}});P.View=U;P.LineTrack=l;P.FeatureTrack=e;P.ReadTrack=O};var slotting_module=function(c,b){var d=2,a=5;b.FeatureSlotter=function(h,g,e,f){this.slots={};this.start_end_dct={};this.w_scale=h;this.include_label=g;this.max_rows=e;this.measureText=f};extend(b.FeatureSlotter.prototype,{slot_features:function(l){var o=this.w_scale,r=this.slots,g=this.start_end_dct,x=[],z=[],m=0,y=this.max_rows;for(var v=0,w=l.length;v<w;v++){var k=l[v],n=k[0];if(r[n]!==undefined){m=Math.max(m,r[n]);z.push(r[n])}else{x.push(v)}}var p=function(F,G){for(var E=0;E<=y;E++){var C=false,H=g[E];if(H!==undefined){for(var B=0,D=H.length;B<D;B++){var A=H[B];if(G>A[0]&&F<A[1]){C=true;break}}}if(!C){return E}}return -1};for(var v=0,w=x.length;v<w;v++){var k=l[x[v]],n=k[0],t=k[1],e=k[2],q=k[3],f=Math.floor(t*o),j=Math.ceil(e*o),u=this.measureText(q).width,h;if(q!==undefined&&this.include_label){u+=(d+a);if(f-u>=0){f-=u;h="left"}else{j+=u;h="right"}}var s=p(f,j);if(s>=0){if(g[s]===undefined){g[s]=[]}g[s].push([f,j]);r[n]=s;m=Math.max(m,s)}else{}}return m+1}})};var painters_module=function(k,B){var r=function(M,E,K,D,J,H){if(H===undefined){H=4}var G=D-E;var F=J-K;var I=Math.floor(Math.sqrt(G*G+F*F)/H);var N=G/I;var L=F/I;var C;for(C=0;C<I;C++,E+=N,K+=L){if(C%2!==0){continue}M.fillRect(E,K,H,1)}};var s=function(E,D,C,H){var G=D-H/2,F=D+H/2,I=C-Math.sqrt(H*3/2);E.beginPath();E.moveTo(G,I);E.lineTo(F,I);E.lineTo(D,C);E.lineTo(G,I);E.strokeStyle=this.fillStyle;E.fill();E.stroke();E.closePath()};var o=function(E,G,C,D,F){this.data=E;this.view_start=G;this.view_end=C;this.prefs=extend({},this.default_prefs,D);this.mode=F};o.prototype.default_prefs={};var w=function(E,G,C,D,F){o.call(this,E,G,C,D,F)};w.prototype.default_prefis={show_counts:false};w.prototype.draw=function(P,C,O){var H=this.view_start,R=this.view_end-this.view_start,Q=C/R;var M=this.data.data,L=this.data.delta,J=this.data.max,E=O;delta_x_px=Math.ceil(L*Q);P.save();for(var F=0,G=M.length;F<G;F++){var K=Math.floor((M[F][0]-H)*Q);var I=M[F][1];if(!I){continue}var N=I/J*O;P.fillStyle="black";P.fillRect(K,E-N,delta_x_px,N);var D=4;if(this.prefs.show_counts&&(P.measureText(I).width+D)<delta_x_px){P.fillStyle="#666";P.textAlign="center";P.fillText(I,K+(delta_x_px/2),10)}}P.restore()};var c=function(E,G,C,D,F){o.call(this,E,G,C,D,F)};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(R,Q,O){var J=false,K=this.prefs.min_value,H=this.prefs.max_value,N=H-K,D=O,E=this.view_start,P=this.view_end-this.view_start,F=Q/P,L=this.mode,V=this.data;R.save();var W=Math.round(O+K/N*O);if(L!=="Intensity"){R.fillStyle="#aaa";R.fillRect(0,W,Q,1)}R.beginPath();R.fillStyle=this.prefs.color;var U,I,G;if(V.length>1){G=Math.ceil((V[1][0]-V[0][0])*F)}else{G=10}for(var S=0,T=V.length;S<T;S++){U=Math.round((V[S][0]-E)*F);I=V[S][1];if(I===null){if(J&&L==="Filled"){R.lineTo(U,D)}J=false;continue}if(I<K){I=K}else{if(I>H){I=H}}if(L==="Histogram"){I=Math.round(I/N*D);R.fillRect(U,W,G,-I)}else{if(L==="Intensity"){I=255-Math.floor((I-K)/N*255);R.fillStyle="rgb("+I+","+I+","+I+")";R.fillRect(U,0,G,D)}else{I=Math.round(D-(I-K)/N*D);if(J){R.lineTo(U,I)}else{J=true;if(L==="Filled"){R.moveTo(U,D);R.lineTo(U,I)}else{R.moveTo(U,I)}}}}}if(L==="Filled"){if(J){R.lineTo(U,W);R.lineTo(0,W)}R.fill()}else{R.stroke()}var C=-1,M=-1;R.fillStyle=this.prefs.overflow_color;for(var S=0,T=V.length;S<T;S++){I=V[S][1];U=Math.round((V[S][0]-E)*F);x_minus_scaled=Math.round((V[S][0]-1-E)*F);if(M>=0&&(I===null||I<H)){R.fillRect(M,0,x_minus_scaled-M+1,2);M=-1}else{if(C>=0&&(I===null||I>K)){R.fillRect(C,O-2,x_minus_scaled-C+1,2);C=-1}}if(I!==null&&I>H&&M<0){M=U}else{if(I!==null&&I<K&&C<0){C=U}}}R.restore()};var q=function(E,G,C,D,F){o.call(this,E,G,C,D,F)};q.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(q.prototype,{get_required_height:function(D){var C=y_scale=this.get_row_height(),E=this.mode;if(E==="no_detail"||E==="Squish"||E==="Pack"){C=D*y_scale}return C+Math.max(Math.round(y_scale/2),5)},draw:function(O,F,N,K){var I=this.data,L=this.view_start,P=this.view_end;O.save();O.fillStyle=this.prefs.block_color;O.textAlign="right";var S=this.view_end-this.view_start,R=F/S,E=this.get_row_height();for(var H=0,J=I.length;H<J;H++){var Q=I[H],G=Q[0],C=Q[1],D=Q[2],M=(K&&K[G]!==undefined?K[G]:null);if((C<P&&D>L)&&(this.mode=="Dense"||M!==null)){this.draw_element(O,this.mode,Q,M,L,P,R,E,F)}}O.restore()}});var d=10,j=3,n=5,A=10,g=1,u=3,f=3,a=9,p=2,h="#ccc";var t=function(E,G,C,D,F){q.call(this,E,G,C,D,F)};extend(t.prototype,q.prototype,{get_row_height:function(){var D=this.mode,C;if(D==="Dense"){C=d}else{if(D==="no_detail"){C=j}else{if(D==="Squish"){C=n}else{C=A}}}return C},draw_element:function(O,H,W,J,Q,ag,ak,al,C){var T=W[0],ai=W[1],aa=W[2]-1,R=W[3],ab=Math.floor(Math.max(0,(ai-Q)*ak)),P=Math.ceil(Math.min(C,Math.max(0,(aa-Q)*ak))),Z=(H==="Dense"?0:(0+J))*al,N,ae,S=null,am=null,F=this.prefs.block_color,ad=this.prefs.label_color;if(H=="Dense"){J=1}if(H==="no_detail"){O.fillStyle=F;O.fillRect(ab,Z+5,P-ab,g)}else{var M=W[4],Y=W[5],ac=W[6],G=W[7];if(Y&&ac){S=Math.floor(Math.max(0,(Y-Q)*ak));am=Math.ceil(Math.min(C,Math.max(0,(ac-Q)*ak)))}var aj,U;if(H==="Squish"||H==="Dense"){aj=1;U=f}else{aj=5;U=a}if(!G){if(W.strand){if(W.strand==="+"){O.fillStyle=O.canvas.manager.get_pattern("right_strand_inv")}else{if(W.strand==="-"){O.fillStyle=O.canvas.manager.get_pattern("left_strand_inv")}}}else{O.fillStyle=F}O.fillRect(ab,Z,P-ab,U)}else{var L,V;if(H==="Squish"||H==="Dense"){O.fillStyle=h;L=Z+Math.floor(f/2)+1;V=1}else{if(M){var L=Z;var V=U;if(M==="+"){O.fillStyle=O.canvas.manager.get_pattern("right_strand")}else{if(M==="-"){O.fillStyle=O.canvas.manager.get_pattern("left_strand")}}}else{O.fillStyle=h;L+=(f/2)+1;V=1}}O.fillRect(ab,L,P-ab,V);for(var ah=0,E=G.length;ah<E;ah++){var I=G[ah],D=Math.floor(Math.max(0,(I[0]-Q)*ak)),X=Math.ceil(Math.min(C,Math.max((I[1]-1-Q)*ak)));if(D>X){continue}O.fillStyle=F;O.fillRect(D,Z+(U-aj)/2+1,X-D,aj);if(S!==undefined&&ac>Y&&!(D>am||X<S)){var af=Math.max(D,S),K=Math.min(X,am);O.fillRect(af,Z+1,K-af,U);if(G.length==1&&H=="Pack"){if(M==="+"){O.fillStyle=O.canvas.manager.get_pattern("right_strand_inv")}else{if(M==="-"){O.fillStyle=O.canvas.manager.get_pattern("left_strand_inv")}}if(af+14<K){af+=2;K-=2}O.fillRect(af,Z+1,K-af,U)}}}}if(H==="Pack"&&ai>Q){O.fillStyle=ad;if(Q===0&&ab-O.measureText(R).width<0){O.textAlign="left";O.fillText(R,P+p,Z+8)}else{O.textAlign="right";O.fillText(R,ab-p,Z+8)}O.fillStyle=F}}}});var b=function(E,G,C,D,F){q.call(this,E,G,C,D,F)};extend(b.prototype,q.prototype,{draw_element:function(V,Q,K,G,Y,E,N,W,T){var K=data[i],M=K[0],U=K[1],F=K[2]-1,P=K[3],I=Math.floor(Math.max(0,(U-Y)*N)),L=Math.ceil(Math.min(T,Math.max(0,(F-Y)*N))),H=(Q==="Dense"?0:(0+G))*W,C,Z,D=null,O=null;if(no_label){V.fillStyle=block_color;V.fillRect(I+left_offset,H+5,L-I,1)}else{var X=K[4],S=K[5],J=K[6];C=9;Z=1;V.fillRect(I+left_offset,H,L-I,C);if(Q!=="Dense"&&P!==undefined&&U>Y){V.fillStyle=label_color;if(Y===0&&I-V.measureText(P).width<0){V.textAlign="left";V.fillText(P,L+2+left_offset,H+8)}else{V.textAlign="right";V.fillText(P,I-2+left_offset,H+8)}V.fillStyle=block_color}var R=X+" / "+S;if(U>Y&&V.measureText(R).width<(L-I)){V.fillStyle="white";V.textAlign="center";V.fillText(R,left_offset+I+(L-I)/2,H+8);V.fillStyle=block_color}}}});var z=1001,m=1002,e=1003,y=1004,l=1005;var x=function(G,D){var I=G[0],H=G[1],F=D[0],E=D[1],C;if(I<F){if(H<F){C=z}else{if(H<=E){C=e}else{C=m}}}else{if(I>E){C=z}else{if(H<=E){C=l}else{C=y}}}return C};var v=function(F,H,C,E,G,D){q.call(this,F,H,C,E,G);this.ref_seq=D};v.prototype.default_prefs=extend({},q.prototype.default_prefs,{show_insertions:false});extend(v.prototype,q.prototype,{get_row_height:function(){var C,D=this.mode;if(D==="Dense"){C=d}else{if(D==="Squish"){C=n}else{C=A;if(this.prefs.show_insertions){C*=2}}}return C},draw_read:function(Z,U,P,ae,E,Y,M,J,I){Z.textAlign="center";var X=this,D=[ae,E],S=0,aa=0,W=0;ref_seq=this.ref_seq,char_width_px=Z.canvas.manager.char_width_px;var aj=[];if((U==="Pack"||this.mode==="Auto")&&J!==undefined&&P>char_width_px){W=Math.round(P/2)}if(!M){M=[[0,J.length]]}for(var Q=0,ac=M.length;Q<ac;Q++){var N=M[Q],F="MIDNSHP=X"[N[0]],R=N[1];if(F==="H"||F==="S"){S-=R}var K=Y+S,ai=Math.floor(Math.max(0,(K-ae)*P)),L=Math.floor(Math.max(0,(K+R-ae)*P));if(ai===L){L+=1}switch(F){case"H":break;case"S":case"M":case"=":var T=x([K,K+R],D);if(T!==z){var V=J.slice(aa,aa+R);if(W>0){Z.fillStyle=this.prefs.block_color;Z.fillRect(ai-W,I+1,L-ai,9);Z.fillStyle=h;for(var ag=0,C=V.length;ag<C;ag++){if(this.prefs.show_differences&&ref_seq){var O=ref_seq[K-ae+ag];if(!O||O.toLowerCase()===V[ag].toLowerCase()){continue}}if(K+ag>=ae&&K+ag<=E){var ah=Math.floor(Math.max(0,(K+ag-ae)*P));Z.fillText(V[ag],ah,I+9)}}}else{Z.fillStyle=this.prefs.block_color;Z.fillRect(ai,I+4,L-ai,f)}}aa+=R;S+=R;break;case"N":Z.fillStyle=h;Z.fillRect(ai-W,I+5,L-ai,1);S+=R;break;case"D":Z.fillStyle="red";Z.fillRect(ai-W,I+4,L-ai,3);S+=R;break;case"P":break;case"I":var T=x([K,K+R],D),ad=ai-W;if(T!==z){var V=J.slice(aa,aa+R);if(this.prefs.show_insertions){var H=ai-(L-ai)/2;if((U==="Pack"||this.mode==="Auto")&&J!==undefined&&P>char_width_px){Z.fillStyle="yellow";Z.fillRect(H-W,I-9,L-ai,9);aj[aj.length]={type:"triangle",data:[ad,I+4,5]};Z.fillStyle=h;switch(T){case (e):V=V.slice(ae-K);break;case (y):V=V.slice(0,K-E);break;case (l):break;case (m):V=V.slice(ae-K,K-E);break}for(var ag=0,C=V.length;ag<C;ag++){var ah=Math.floor(Math.max(0,(K+ag-ae)*P));Z.fillText(V[ag],ah-(L-ai)/2,I)}}else{Z.fillStyle="yellow";Z.fillRect(H,I+(this.mode!=="Dense"?2:5),L-ai,(U!=="Dense"?f:u))}}else{if((U==="Pack"||this.mode==="Auto")&&J!==undefined&&P>char_width_px){aj[aj.length]={type:"text",data:[V.length,ad,I+9]}}else{}}}aa+=R;break;case"X":aa+=R;break}}Z.fillStyle="yellow";var af,G,ak;for(var ab=0;ab<aj.length;ab++){af=aj[ab];G=af.type;ak=af.data;if(G==="text"){Z.save();Z.font="bold "+Z.font;Z.fillText(ak[0],ak[1],ak[2]);Z.restore()}else{if(G=="triangle"){s(Z,ak[0],ak[1],ak[2])}}}},draw_element:function(V,Q,I,F,Y,D,M,W,T){var L=I[0],U=I[1],E=I[2],N=I[3],H=Math.floor(Math.max(0,(U-Y)*M)),J=Math.ceil(Math.min(T,Math.max(0,(E-Y)*M))),G=(Q==="Dense"?0:(0+F))*W,Z=this.prefs.block_color,K=this.prefs.label_color,S=0;if((Q==="Pack"||this.mode==="Auto")&&M>V.canvas.manager.char_width_px){var S=Math.round(M/2)}V.fillStyle=Z;if(I[5] instanceof Array){var R=Math.floor(Math.max(0,(I[4][0]-Y)*M)),P=Math.ceil(Math.min(T,Math.max(0,(I[4][1]-Y)*M))),O=Math.floor(Math.max(0,(I[5][0]-Y)*M)),C=Math.ceil(Math.min(T,Math.max(0,(I[5][1]-Y)*M)));if(I[4][1]>=Y&&I[4][0]<=D&&I[4][2]){this.draw_read(V,Q,M,Y,D,I[4][0],I[4][2],I[4][3],G)}if(I[5][1]>=Y&&I[5][0]<=D&&I[5][2]){this.draw_read(V,Q,M,Y,D,I[5][0],I[5][2],I[5][3],G)}if(O>P){V.fillStyle=h;r(V,P-S,G+5,O-S,G+5)}}else{V.fillStyle=Z;this.draw_read(V,Q,M,Y,D,U,I[4],I[5],G)}if(Q==="Pack"&&U>Y){V.fillStyle=this.prefs.label_color;var X=1;if(X===0&&H-V.measureText(N).width<0){V.textAlign="left";V.fillText(N,J+p-S,G+8)}else{V.textAlign="right";V.fillText(N,H-p-S,G+8)}V.fillStyle=Z}}});B.SummaryTreePainter=w;B.LinePainter=c;B.LinkedFeaturePainter=t;B.ReadPainter=v;B.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("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 extend=function(){var c=arguments[0];for(var b=1;b<arguments.length;b++){var a=arguments[b];for(key in a){c[key]=a[key]}}return c};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,R){var p=f("slotting"),G=f("painters");var X=function(Y,Z){this.document=Y;this.default_font=Z!==undefined?Z:"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")};extend(X.prototype,{load_pattern:function(Y,ac){var Z=this.patterns,aa=this.dummy_context,ab=new Image();ab.src=image_path+ac;ab.onload=function(){Z[Y]=aa.createPattern(ab,"repeat")}},get_pattern:function(Y){return this.patterns[Y]},new_canvas:function(){var Y=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(Y)}Y.manager=this;return Y}});var B=function(Y,Z){Y.bind("drag",{handle:Z,relative:true},function(ad,ae){var ac=$(this).parent();var ab=ac.children();var aa;for(aa=0;aa<ab.length;aa++){if(ae.offsetY<$(ab.get(aa)).position().top){break}}if(aa===ab.length){if(this!==ab.get(aa-1)){ac.append(this)}}else{if(this!==ab.get(aa)){$(this).insertBefore(ab.get(aa))}}})};var h=function(aa,Y){var Z=Y-aa;return(Z<=2?0.01:(Z<=100?1:(Z<=1000?5:10)))};var C=9,z=10,M=C+2,w=100,D=12000,K=200,s=10,F=5000,t=100,n="There was an error in indexing this dataset. ",E="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",A="No data for this chrom/contig.",q="Currently indexing... please wait",v="Tool cannot be rerun: ",a="Loading data...",S="Ready for display",d=10,r=5,y=5;function u(Y){return Math.round(Y*1000)/1000}var c=function(Y){this.num_elements=Y;this.clear()};extend(c.prototype,{get:function(Z){var Y=this.key_ary.indexOf(Z);if(Y!==-1){this.move_key_to_end(Z,Y)}return this.obj_cache[Z]},set:function(Z,aa){if(!this.obj_cache[Z]){if(this.key_ary.length>=this.num_elements){var Y=this.key_ary.shift();delete this.obj_cache[Y]}this.key_ary.push(Z)}this.obj_cache[Z]=aa;return aa},move_key_to_end:function(Z,Y){this.key_ary.splice(Y,1);this.key_ary.push(Z)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var L=function(Z,Y,aa){c.call(this,Z);this.track=Y;this.subset=(aa!==undefined?aa:true)};extend(L.prototype,c.prototype,{load_data:function(ag,ah,ac,af,Z,ae){if(this.track.track_type=="ReferenceTrack"&&Z>1){return}var ab={chrom:ag,low:ah,high:ac,mode:af,resolution:Z,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ab,ae);if(this.track.filters_manager){var ai=[];var Y=this.track.filters_manager.filters;for(var ad=0;ad<Y.length;ad++){ai[ai.length]=Y[ad].name}ab.filter_cols=JSON.stringify(ai)}var aa=this;return $.getJSON(this.track.data_url,ab,function(aj){aa.set_data(ah,ac,af,aj)})},get_data:function(aa,Y,ad,ae,Z,ac){var ab=this.get(this.gen_key(Y,ad,ae));if(ab){return ab}ab=this.load_data(aa,Y,ad,ae,Z,ac);this.set_data(Y,ad,ae,ab);return ab},set_data:function(Z,aa,ab,Y){return this.set(this.gen_key(Z,aa,ab),Y)},gen_key:function(Y,aa,ab){var Z=Y+"_"+aa+"_"+ab;return Z},split_key:function(Y){return Y.split("_")}});var W=function(Y,ab,aa,Z,ac){this.container=Y;this.chrom=null;this.vis_id=aa;this.dbkey=Z;this.title=ab;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(ac);this.canvas_manager=new X(Y.get(0).ownerDocument);this.reset()};extend(W.prototype,{init:function(ab){var aa=this.container,Y=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aa);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aa);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aa);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();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 Z=function(ac){if(ac.type==="focusout"||(ac.keyCode||ac.which)===13||(ac.keyCode||ac.which)===27){if((ac.keyCode||ac.which)!==27){Y.go_to($(this).val())}$(this).hide();$(this).val("");Y.location_span.show();Y.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",Z).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.bind("click",function(){Y.location_span.hide();Y.chrom_select.hide();Y.nav_input.val(Y.chrom+":"+Y.low+"-"+Y.high);Y.nav_input.css("display","inline-block");Y.nav_input.select();Y.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(){Y.zoom_out();Y.redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){Y.zoom_in();Y.redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},ab);this.chrom_select.bind("change",function(){Y.change_chrom(Y.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(ac){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(ac){Y.zoom_in(ac.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ac,ad){this.current_x=ad.offsetX}).bind("drag",function(ac,ae){var af=ae.offsetX-this.current_x;this.current_x=ae.offsetX;var ad=Math.round(af/Y.viewport_container.width()*(Y.max_high-Y.max_low));Y.move_delta(-ad)});this.overview_close.bind("click",function(){for(var ad=0,ac=Y.tracks.length;ad<ac;ad++){Y.tracks[ad].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",Y.overview_box.height());Y.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(ac,ad){if(ac.clientX>Y.viewport_container.width()-16){return false}}).bind("dragstart",function(ac,ad){ad.original_low=Y.low;ad.current_height=ac.clientY;ad.current_x=ad.offsetX}).bind("drag",function(ae,ag){var ac=$(this);var ah=ag.offsetX-ag.current_x;var ad=ac.scrollTop()-(ae.clientY-ag.current_height);ac.scrollTop(ad);ag.current_height=ae.clientY;ag.current_x=ag.offsetX;var af=Math.round(ah/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}).bind("mousewheel",function(ae,ag,ad,ac){if(ad){var af=Math.round(-ad/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}});this.top_labeltrack.bind("dragstart",function(ac,ad){return $("<div />").css({height:Y.content_div.height()+Y.top_labeltrack.height()+Y.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ag,ah){$(ah.proxy).css({left:Math.min(ag.pageX,ah.startX),width:Math.abs(ag.pageX-ah.startX)});var ad=Math.min(ag.pageX,ah.startX)-Y.container.offset().left,ac=Math.max(ag.pageX,ah.startX)-Y.container.offset().left,af=(Y.high-Y.low),ae=Y.viewport_container.width();Y.update_location(Math.round(ad/ae*af)+Y.low,Math.round(ac/ae*af)+Y.low)}).bind("dragend",function(ah,ai){var ad=Math.min(ah.pageX,ai.startX),ac=Math.max(ah.pageX,ai.startX),af=(Y.high-Y.low),ae=Y.viewport_container.width(),ag=Y.low;Y.low=Math.round(ad/ae*af)+ag;Y.high=Math.round(ac/ae*af)+ag;$(ai.proxy).remove();Y.redraw()});this.add_label_track(new V(this,this.top_labeltrack));this.add_label_track(new V(this,this.nav_labeltrack));$(window).bind("resize",function(){Y.resize_window()});$(document).bind("redraw",function(){Y.redraw()});this.reset();$(window).trigger("resize")},update_location:function(Y,Z){this.location_span.text(commatize(Y)+" - "+commatize(Z));this.nav_input.val(this.chrom+":"+commatize(Y)+"-"+commatize(Z))},load_chroms:function(Z,aa){Z.num=t;$.extend(Z,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var Y=this;$.ajax({url:chrom_url,data:Z,dataType:"json",success:function(ac){if(ac.chrom_info.length===0){alert("Invalid chromosome: "+Z.chrom);return}if(ac.reference){Y.add_label_track(new x(Y))}Y.chrom_data=ac.chrom_info;var af='<option value="">Select Chrom/Contig</option>';for(var ae=0,ab=Y.chrom_data.length;ae<ab;ae++){var ad=Y.chrom_data[ae].chrom;af+='<option value="'+ad+'">'+ad+"</option>"}if(ac.prev_chroms){af+='<option value="previous">Previous '+t+"</option>"}if(ac.next_chroms){af+='<option value="next">Next '+t+"</option>"}Y.chrom_select.html(af);if(aa){aa()}Y.chrom_start_index=ac.start_index},error:function(){alert("Could not load chroms for this dbkey:",Y.dbkey)}})},change_chrom:function(ac,Z,ae){if(!ac||ac==="None"){return}var ab=this;if(ac==="previous"){ab.load_chroms({low:this.chrom_start_index-t});return}if(ac==="next"){ab.load_chroms({low:this.chrom_start_index+t});return}var ad=$.grep(ab.chrom_data,function(ag,ah){return ag.chrom===ac})[0];if(ad===undefined){ab.load_chroms({chrom:ac},function(){ab.change_chrom(ac,Z,ae)});return}else{if(ac!==ab.chrom){ab.chrom=ac;if(!ab.chrom){ab.intro_div.show()}else{ab.intro_div.hide()}ab.chrom_select.val(ab.chrom);ab.max_high=ad.len-1;ab.reset();ab.redraw(true);for(var af=0,Y=ab.tracks.length;af<Y;af++){var aa=ab.tracks[af];if(aa.init){aa.init()}}}if(Z!==undefined&&ae!==undefined){ab.low=Math.max(Z,0);ab.high=Math.min(ae,ab.max_high)}ab.reset_overview();ab.redraw()}},go_to:function(ac){var ag=this,Y,ab,Z=ac.split(":"),ae=Z[0],af=Z[1];if(af!==undefined){try{var ad=af.split("-");Y=parseInt(ad[0].replace(/,/g,""),10);ab=parseInt(ad[1].replace(/,/g,""),10)}catch(aa){return false}}ag.change_chrom(ae,Y,ab)},move_fraction:function(aa){var Y=this;var Z=Y.high-Y.low;this.move_delta(aa*Z)},move_delta:function(aa){var Y=this;var Z=Y.high-Y.low;if(Y.low-aa<Y.max_low){Y.low=Y.max_low;Y.high=Y.max_low+Z}else{if(Y.high-aa>Y.max_high){Y.high=Y.max_high;Y.low=Y.max_high-Z}else{Y.high-=aa;Y.low-=aa}}Y.redraw()},add_track:function(Y){Y.view=this;Y.track_id=this.track_id_counter;this.tracks.push(Y);if(Y.init){Y.init()}Y.container_div.attr("id","track_"+Y.track_id);B(Y.container_div,".draghandle");this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(Y){Y.view=this;this.label_tracks.push(Y)},remove_track:function(Y){this.has_changes=true;Y.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(Y)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(af){var ae=this.high-this.low,ad=this.low,Z=this.high;if(ad<this.max_low){ad=this.max_low}if(Z>this.max_high){Z=this.max_high}if(this.high!==0&&ae<this.min_separation){Z=ad+this.min_separation}this.low=Math.floor(ad);this.high=Math.ceil(Z);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/K)/Math.LN10));this.zoom_res=Math.pow(s,Math.max(0,Math.ceil(Math.log(this.resolution,s)/Math.log(s))));var Y=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ac=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ag=13;this.overview_box.css({left:Y,width:Math.max(ag,ac)}).show();if(ac<ag){this.overview_box.css("left",Y-(ag-ac)/2)}if(this.overview_highlight){this.overview_highlight.css({left:Y,width:ac})}this.update_location(this.low,this.high);if(!af){for(var aa=0,ab=this.tracks.length;aa<ab;aa++){if(this.tracks[aa]&&this.tracks[aa].enabled){this.tracks[aa].draw()}}for(aa=0,ab=this.label_tracks.length;aa<ab;aa++){this.label_tracks[aa].draw()}}},zoom_in:function(Z,aa){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ab=this.high-this.low,ac=ab/2+this.low,Y=(ab/this.zoom_factor)/2;if(Z){ac=Z/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ac-Y);this.high=Math.round(ac+Y);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var Z=this.high-this.low,aa=Z/2+this.low,Y=(Z*this.zoom_factor)/2;this.low=Math.round(aa-Y);this.high=Math.round(aa+Y);this.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.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").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()}});var o=function(Z,ac){this.track=Z;this.name=ac.name;this.params=[];var ak=ac.params;for(var aa=0;aa<ak.length;aa++){var af=ak[aa],Y=af.name,aj=af.label,ab=unescape(af.html),ah=af.type;if(ah==="number"){this.params[this.params.length]=new g(Y,aj,ab,af.min,af.max)}else{if(ah=="select"){this.params[this.params.length]=new I(Y,aj,ab)}else{console.log("WARNING: unrecognized tool parameter type:",Y,ah)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(am){am.stopPropagation()}).bind("click",function(am){am.stopPropagation()}).bind("dblclick",function(am){am.stopPropagation()});var ai=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ag=this.params;var ad=this;$.each(this.params,function(an,aq){var ap=$("<div>").addClass("param-row").appendTo(ad.parent_div);var am=$("<div>").addClass("param-label").text(aq.label).appendTo(ap);var ao=$("<div/>").addClass("slider").html(aq.html).appendTo(ap);$("<div style='clear: both;'/>").appendTo(ap)});this.parent_div.find("input").click(function(){$(this).select()});var al=$("<div>").addClass("slider-row").appendTo(this.parent_div);var ae=$("<input type='submit'>").attr("value","Run").appendTo(al);var ad=this;ae.click(function(){ad.run()})};extend(o.prototype,{get_param_values_dict:function(){var Y={};this.parent_div.find(":input").each(function(){var Z=$(this).attr("name"),aa=$(this).val();Y[Z]=JSON.stringify(aa)});return Y},get_param_values:function(){var Z=[];var Y={};this.parent_div.find(":input").each(function(){var aa=$(this).attr("name"),ab=$(this).val();if(aa){Z[Z.length]=ab}});return Z},run:function(){var Z={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};$.extend(Z,this.get_param_values_dict());var ab=this.track,aa=Z.tool_id+ab.tool_region_and_parameters_str(Z.chrom,Z.low,Z.high),ac;if(ab.track_type==="FeatureTrack"){ac=new O(aa,view,ab.hda_ldda,undefined,{},{},ab)}this.track.add_track(ac);ac.content_div.text("Starting job.");var Y=function(){$.getJSON(run_tool_url,Z,function(ad){if(ad==="no converter"){ac.container_div.addClass("error");ac.content_div.text(E)}else{if(ad.error){ac.container_div.addClass("error");ac.content_div.text(v+ad.message)}else{if(ad==="pending"){ac.container_div.addClass("pending");ac.content_div.text("Converting input data so that it can be easily reused.");setTimeout(Y,2000)}else{ac.dataset_id=ad.dataset_id;ac.content_div.text("Running job.");ac.init()}}}})};Y()}});var I=function(Z,Y,aa){this.name=Z;this.label=Y;this.html=aa};var g=function(aa,Z,ac,ab,Y){I.call(this,aa,Z,ac);this.min=ab;this.max=Y};var j=function(Z,Y,aa){this.name=Z;this.index=Y;this.value=aa};var P=function(Z,Y){this.name=Z;this.index=Y;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};extend(P.prototype,{applies_to:function(Y){if(Y.length>this.index){return true}return false},keep:function(Y){if(!this.applies_to(Y)){return true}var Z=parseInt(Y[this.index]);return(isNaN(Z)||(Z>=this.low&&Z<=this.high))},update_attrs:function(Z){var Y=false;if(!this.applies_to(Z)){return Y}if(Z[this.index]<this.min){this.min=Math.floor(Z[this.index]);Y=true}if(Z[this.index]>this.max){this.max=Math.ceil(Z[this.index]);Y=true}return Y},update_ui_elt:function(){var Z=this.slider.slider("option","min"),Y=this.slider.slider("option","max");if(this.min<Z||this.max>Y){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",h(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var U=function(aa,ag){this.track=aa;this.filters=[];for(var ac=0;ac<ag.length;ac++){var Y=ag[ac];var Z=Y.name,af=Y.type,ad=Y.index;if(af==="int"||af==="float"){this.filters[ac]=new P(Z,ad)}else{this.filters[ac]=new j(Z,ad,af)}}var ae=function(ah,ai,aj){ah.click(function(){var ak=ai.text();max=parseFloat(aj.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aj.slider("option","values")){input_size=2*input_size+1;multi_value=true}ai.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",ak).appendTo(ai).focus().select().click(function(al){al.stopPropagation()}).blur(function(){$(this).remove();ai.text(ak)}).keyup(function(ap){if(ap.keyCode===27){$(this).trigger("blur")}else{if(ap.keyCode===13){var an=aj.slider("option","min"),al=aj.slider("option","max"),ao=function(aq){return(isNaN(aq)||aq>al||aq<an)},am=$(this).val();if(!multi_value){am=parseFloat(am);if(ao(am)){alert("Parameter value must be in the range ["+an+"-"+al+"]");return $(this)}}else{am=am.split("-");am=[parseFloat(am[0]),parseFloat(am[1])];if(ao(am[0])||ao(am[1])){alert("Parameter value must be in the range ["+an+"-"+al+"]");return $(this)}}aj.slider((multi_value?"values":"value"),am)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ah){ah.stopPropagation()}).bind("click",function(ah){ah.stopPropagation()}).bind("dblclick",function(ah){ah.stopPropagation()});var ab=this;$.each(this.filters,function(an,ai){var ak=$("<div/>").addClass("slider-row").appendTo(ab.parent_div);var ah=$("<div/>").addClass("slider-label").appendTo(ak);var ap=$("<span/>").addClass("slider-name").text(ai.name+" ").appendTo(ah);var aj=$("<span/>");var al=$("<span/>").addClass("slider-value").appendTo(ah).append("[").append(aj).append("]");var ao=$("<div/>").addClass("slider").appendTo(ak);ai.control_element=$("<div/>").attr("id",ai.name+"-filter-control").appendTo(ao);var am=[0,0];ai.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aq,ar){am=ar.values;aj.text(ar.values[0]+"-"+ar.values[1]);setTimeout(function(){if(ar.values[0]==am[0]&&ar.values[1]==am[1]){var at=ar.values;aj.text(at[0]+"-"+at[1]);ai.low=at[0];ai.high=at[1];ab.track.draw(true,true)}},50)},change:function(aq,ar){ai.control_element.slider("option","slide").call(ai.control_element,aq,ar)}});ai.slider=ai.control_element;ai.slider_label=aj;ae(al,aj,ai.control_element);$("<div style='clear: both;'/>").appendTo(ak)})};var T=function(Y){this.track=Y.track;this.params=Y.params;this.values={};if(Y.saved_values){this.restore_values(Y.saved_values)}this.onchange=Y.onchange};extend(T.prototype,{restore_values:function(Y){var Z=this;$.each(this.params,function(aa,ab){if(Y[ab.key]!==undefined){Z.values[ab.key]=Y[ab.key]}else{Z.values[ab.key]=ab.default_value}})},build_form:function(){var Z=this;var Y=$("<div />");$.each(this.params,function(ad,ab){if(!ab.hidden){var aa="param_"+ad;var ai=$("<div class='form-row' />").appendTo(Y);ai.append($("<label />").attr("for",aa).text(ab.label+":"));if(ab.type==="bool"){ai.append($('<input type="checkbox" />').attr("id",aa).attr("name",aa).attr("checked",Z.values[ab.key]))}else{if(ab.type==="color"){var af=Z.values[ab.key];var ae=$("<input />").attr("id",aa).attr("name",aa).val(af);var ag=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var ac=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ag);var ah=$("<div/>").appendTo(ac).farbtastic({width:100,height:100,callback:ae,color:af});$("<div />").append(ae).append(ag).appendTo(ai).bind("click",function(aj){ag.css({left:$(this).position().left+($(ae).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ag.hide();$(document).unbind("click.color-picker")});aj.stopPropagation()})}else{ai.append($("<input />").attr("id",aa).attr("name",aa).val(Z.values[ab.key]))}}}});return Y},update_from_form:function(Y){var aa=this;var Z=false;$.each(this.params,function(ab,ad){if(!ad.hidden){var ae="param_"+ab;var ac=Y.find("#"+ae).val();if(ad.type==="float"){ac=parseFloat(ac)}else{if(ad.type==="int"){ac=parseInt(ac)}else{if(ad.type==="bool"){ac=Y.find("#"+ae).is(":checked")}}}if(ac!==aa.values[ad.key]){aa.values[ad.key]=ac;Z=true}}});if(Z){this.onchange()}}});var b=function(aa,Z,Y){this.index=aa;this.resolution=Z;this.canvas=$("<div class='track-tile'/>").append(Y)};var m=function(aa,Z,Y,ab){b.call(this,aa,Z,Y);this.max_val=ab};var J=function(aa,Z,Y){b.call(this,aa,Z,Y)};var k=function(Z,Y,ac,aa,ab){this.name=Z;this.view=Y;this.parent_element=ac;this.data_url=(aa?aa:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ab?ab:F);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").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 class='draghandle' />").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)};extend(k.prototype,{init:function(){var Y=this;Y.enabled=false;Y.tile_cache.clear();Y.data_cache.clear();Y.initial_canvas=undefined;Y.content_div.css("height","auto");Y.container_div.removeClass("nodata error pending");if(!Y.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:Y.hda_ldda,dataset_id:Y.dataset_id,chrom:Y.view.chrom},function(Z){if(!Z||Z==="error"||Z.kind==="error"){Y.container_div.addClass("error");Y.content_div.text(n);if(Z.message){var ab=Y.view.tracks.indexOf(Y);var aa=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+Z.message+"</pre>",{Close:hide_modal})});Y.content_div.append(aa)}}else{if(Z==="no converter"){Y.container_div.addClass("error");Y.content_div.text(E)}else{if(Z==="no data"||(Z.data!==undefined&&(Z.data===null||Z.data.length===0))){Y.container_div.addClass("nodata");Y.content_div.text(A)}else{if(Z==="pending"){Y.container_div.addClass("pending");Y.content_div.text(q);setTimeout(function(){Y.init()},Y.data_query_wait)}else{if(Z.status==="data"){if(Z.valid_chroms){Y.valid_chroms=Z.valid_chroms;Y.make_name_popup_menu()}Y.content_div.text(S);if(Y.view.chrom){Y.content_div.text("");Y.content_div.css("height",Y.height_px+"px");Y.enabled=true;$.when(Y.predraw_init()).done(function(){Y.container_div.removeClass("nodata error pending");Y.draw()})}}}}}}})},predraw_init:function(){},update_name:function(Y){this.old_name=this.name;this.name=Y;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var H=function(ag,ae,ah){var Z=this,ai=Z.view;this.filters_manager=(ag!==undefined?new U(this,ag):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(ae!==undefined&&obj_length(ae)>0?new o(this,ae):undefined);this.parent_track=ah;this.child_tracks=[];if(Z.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}Z.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();Z.container_div.append(Z.child_tracks_container);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(Z.display_modes!==undefined){if(Z.mode_div===undefined){Z.mode_div=$("<div class='right-float menubutton popup' />").appendTo(Z.header_div);var ab=(Z.track_config&&Z.track_config.values.mode?Z.track_config.values.mode:Z.display_modes[0]);Z.mode=ab;Z.mode_div.text(ab);var aa=function(aj){Z.mode_div.text(aj);Z.mode=aj;Z.track_config.values.mode=aj;Z.tile_cache.clear();Z.draw()};var Y={};for(var ac=0,af=Z.display_modes.length;ac<af;ac++){var ad=Z.display_modes[ac];Y[ad]=function(aj){return function(){aa(aj)}}(ad)}make_popupmenu(Z.mode_div,Y)}else{Z.mode_div.hide()}}this.make_name_popup_menu()};extend(H.prototype,k.prototype,{make_name_popup_menu:function(){var Z=this;var Y={};Y["Edit configuration"]=function(){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){Z.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ad()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure Track",Z.track_config.build_form(),{Cancel:af,OK:ad})};if(Z.filters_available>0){var ac=(Z.filters_div.is(":visible")?"Hide filters":"Show filters");Y[ac]=function(){Z.filters_visible=(Z.filters_div.is(":visible"));Z.filters_div.toggle();Z.make_name_popup_menu()}}if(Z.tool){var ac=(Z.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");Y[ac]=function(){if(!Z.dynamic_tool_div.is(":visible")){Z.update_name(Z.name+Z.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";Z.revert_name()}Z.dynamic_tool_div.toggle();Z.make_name_popup_menu()}}if(Z.valid_chroms){Y["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+Z.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var aa=view;var ab=function(){$("#no-tracks").show()};if(this.parent_track){aa=this.parent_track;ab=function(){}}Y.Remove=function(){aa.remove_track(Z);if(aa.num_tracks===0){ab()}};make_popupmenu(Z.name_div,Y)},draw:function(Y,aa){var ar=this.view.low,ae=this.view.high,ag=ae-ar,ai=this.view.container.width(),ac=ai/ag,aj=this.view.resolution,ab=$("<div style='position: relative;'></div>"),ak=function(au,av,at){return au+"_"+av+"_"+at};if(!aa){this.content_div.children().remove()}this.content_div.append(ab);this.max_height=0;var am=Math.floor(ar/aj/K);var ad=[];var an=0;while((am*K*aj)<ae){var aq=ak(ai,ac,am);var af=this.tile_cache.get(aq);var ao=am*K*this.view.resolution;var Z=ao+K*this.view.resolution;if(!Y&&af){ad[ad.length]=af;this.show_tile(af,ab,ao,ac)}else{this.delayed_draw(Y,aq,am,aj,ab,ac,ad)}am+=1;an++}var ah=this;var ap=setInterval(function(){if(ad.length===an){clearInterval(ap);if(aa){var aw=ah.content_div.children();var ax=false;for(var av=aw.length-1,aB=0;av>=aB;av--){var au=$(aw[av]);if(ax){au.remove()}else{if(au.children().length!==0){ax=true}}}}if(ah.track_type=="FeatureTrack"&&ah.mode=="Histogram"){var aA=-1;for(var av=0;av<ad.length;av++){var aD=ad[av].max_val;if(aD>aA){aA=aD}}for(var av=0;av<ad.length;av++){if(ad[av].max_val!==aA){var aC=ad[av];aC.canvas.remove();ah.delayed_draw(true,ak(ai,ac,aC.index),aC.index,aC.resolution,ab,ac,[],{max:aA})}}}if(ah.filters_manager){var at=ah.filters_manager.filters;for(var az=0;az<at.length;az++){at[az].update_ui_elt()}var ay=false;if(ah.example_feature){for(var az=0;az<at.length;az++){if(at[az].applies_to(ah.example_feature)){ay=true;break}}}if(ah.filters_available!==ay){ah.filters_available=ay;if(!ah.filters_available){ah.filters_div.hide()}ah.make_name_popup_menu()}}}},50);for(var al=0;al<this.child_tracks.length;al++){this.child_tracks[al].draw(Y,aa)}},delayed_draw:function(Z,ag,aa,ac,ah,ak,ai,ad){var ab=this,ae=aa*K*ac,aj=ae+K*ac;var af=function(at,al,an,am,aq,ar,ao){var ap=ab.draw_tile(al,an,am,ar,ao);ab.tile_cache.set(ag,ap);ab.show_tile(ap,aq,ae,ar);ai[ai.length]=ap};var Y=setTimeout(function(){if(ae<=ab.view.high&&aj>=ab.view.low){var al=(Z?undefined:ab.tile_cache.get(ag));if(al){ab.show_tile(al,ah,ae,ak);ai[ai.length]=al}else{$.when(ab.data_cache.get_data(view.chrom,ae,aj,ab.mode,ac,ab.data_url_extra_params)).then(function(am){extend(am,ad);if(view.reference_track&&ak>view.canvas_manager.char_width_px){$.when(view.reference_track.data_cache.get_data(view.chrom,ae,aj,ab.mode,ac,view.reference_track.data_url_extra_params)).then(function(an){af(Y,am,ac,aa,ah,ak,an)})}else{af(Y,am,ac,aa,ah,ak)}})}}},50)},show_tile:function(ab,ae,ac,af){var Z=this;var aa=this.view.high-this.view.low,ad=(ac-this.view.low)*af;if(this.left_offset){ad-=this.left_offset}var Y=ab.canvas;Y.css({position:"absolute",top:0,left:ad,height:""});ae.append(Y);Z.max_height=Math.max(Z.max_height,Y.height());Z.content_div.css("height",Z.max_height+"px");ae.children().css("height",Z.max_height+"px")},set_overview:function(){var Y=this.view;if(this.initial_canvas&&this.is_overview){Y.overview_close.show();Y.overview_viewport.append(this.initial_canvas);Y.overview_highlight.show().height(this.initial_canvas.height());Y.overview_viewport.height(this.initial_canvas.height()+Y.overview_box.height())}$(window).trigger("resize")},tool_region_and_parameters_str:function(aa,Y,ab){var Z=this,ac=(aa!==undefined&&Y!==undefined&&ab!==undefined?aa+":"+Y+"-"+ab:"all");return" - region=["+ac+"], parameters=["+Z.tool.get_param_values().join(", ")+"]"},add_track:function(Y){Y.track_id=this.track_id+"_"+this.child_tracks.length;Y.container_div.attr("id","track_"+Y.track_id);this.child_tracks_container.append(Y.container_div);B(Y.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(Y);this.view.has_changes=true},remove_track:function(Y){Y.container_div.fadeOut("slow",function(){$(this).remove()})}});var V=function(Y,Z){this.track_type="LabelTrack";this.hidden=true;k.call(this,null,Y,Z);this.container_div.addClass("label-track")};extend(V.prototype,k.prototype,{draw:function(){var aa=this.view,ab=aa.high-aa.low,ae=Math.floor(Math.pow(10,Math.floor(Math.log(ab)/Math.log(10)))),Y=Math.floor(aa.low/ae)*ae,ac=this.view.container.width(),Z=$("<div style='position: relative; height: 1.3em;'></div>");while(Y<aa.high){var ad=(Y-aa.low)/ab*ac;Z.append($("<div class='label'>"+commatize(Y)+"</div>").css({position:"absolute",left:ad-1}));Y+=ae}this.content_div.children(":first").remove();this.content_div.append(Z)}});var x=function(Y){this.track_type="ReferenceTrack";this.hidden=true;k.call(this,null,Y,Y.top_labeltrack);H.call(this);Y.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:Y.dbkey};this.data_cache=new L(y,this,false);this.tile_cache=new c(r)};extend(x.prototype,H.prototype,{draw_tile:function(ag,ad,Z,ai){var ac=this,aa=K*ad;if(ai>this.view.canvas_manager.char_width_px){if(ag===null){ac.content_div.css("height","0px");return}var ab=this.view.canvas_manager.new_canvas();var ah=ab.getContext("2d");ab.width=Math.ceil(aa*ai+ac.left_offset);ab.height=ac.height_px;ah.font=ah.canvas.manager.default_font;ah.textAlign="center";for(var ae=0,af=ag.length;ae<af;ae++){var Y=Math.round(ae*ai);ah.fillText(ag[ae],Y+ac.left_offset,10)}return new b(Z,ad,ab)}this.content_div.css("height","0px")}});var l=function(ac,aa,ad,Y,ab){var Z=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";k.call(this,ac,aa,aa.viewport_container);H.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=ad;this.dataset_id=Y;this.original_dataset_id=Y;this.data_cache=new L(y,this);this.tile_cache=new c(r);this.track_config=new T({track:this,params:[{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:ab,onchange:function(){Z.vertical_range=Z.prefs.max_value-Z.prefs.min_value;$("#linetrack_"+Z.track_id+"_minval").text(Z.prefs.min_value);$("#linetrack_"+Z.track_id+"_maxval").text(Z.prefs.max_value);Z.tile_cache.clear();Z.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};extend(l.prototype,H.prototype,{add_resize_handle:function(){var Y=this;var ab=false;var aa=false;var Z=$("<div class='track-resize'>");$(Y.container_div).hover(function(){ab=true;Z.show()},function(){ab=false;if(!aa){Z.hide()}});Z.hide().bind("dragstart",function(ac,ad){aa=true;ad.original_height=$(Y.content_div).height()}).bind("drag",function(ad,ae){var ac=Math.min(Math.max(ae.original_height+ae.deltaY,Y.min_height_px),Y.max_height_px);$(Y.content_div).css("height",ac);Y.height_px=ac;Y.draw(true)}).bind("dragend",function(ac,ad){Y.tile_cache.clear();aa=false;if(!ab){Z.hide()}Y.track_config.values.height=Y.height_px}).appendTo(Y.container_div)},predraw_init:function(){var Y=this,Z=Y.view.tracks.indexOf(Y);Y.vertical_range=undefined;return $.getJSON(Y.data_url,{stats:true,chrom:Y.view.chrom,low:null,high:null,hda_ldda:Y.hda_ldda,dataset_id:Y.dataset_id},function(aa){Y.container_div.addClass("line-track");var ac=aa.data;if(isNaN(parseFloat(Y.prefs.min_value))||isNaN(parseFloat(Y.prefs.max_value))){Y.prefs.min_value=ac.min;Y.prefs.max_value=ac.max;$("#track_"+Z+"_minval").val(Y.prefs.min_value);$("#track_"+Z+"_maxval").val(Y.prefs.max_value)}Y.vertical_range=Y.prefs.max_value-Y.prefs.min_value;Y.total_frequency=ac.total_frequency;Y.container_div.find(".yaxislabel").remove();var ad=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+Z+"_minval").text(u(Y.prefs.min_value));var ab=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+Z+"_maxval").text(u(Y.prefs.max_value));ab.css({position:"absolute",top:"24px",left:"10px"});ab.prependTo(Y.container_div);ad.css({position:"absolute",bottom:"2px",left:"10px"});ad.prependTo(Y.container_div)})},draw_tile:function(ai,ac,Z,ah){if(this.vertical_range===undefined){return}var ad=Z*K*ac,ab=K*ac,Y=Math.ceil(ab*ah),af=this.height_px;var aa=this.view.canvas_manager.new_canvas();aa.width=Y,aa.height=af;var ag=aa.getContext("2d");var ae=new G.LinePainter(ai.data,ad,ad+ab,this.prefs,this.mode);ae.draw(ag,Y,af);return new b(ab,ac,aa)}});var e=function(Y,ad,ac,ag,af,aa,ab,ae){var Z=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];this.track_config=new T({track:this,params:[{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:af,onchange:function(){Z.tile_cache.clear();Z.draw()}});this.prefs=this.track_config.values;k.call(this,Y,ad,ad.viewport_container);H.call(this,aa,ab,ae);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=ac;this.dataset_id=ag;this.original_dataset_id=ag;this.zo_slots={};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_cache=new L(20,this);this.left_offset=200;this.painter=G.LinkedFeaturePainter};extend(e.prototype,H.prototype,{update_auto_mode:function(Y){if(this.mode=="Auto"){if(Y=="no_detail"){Y="feature spans"}else{if(Y=="summary_tree"){Y="coverage histogram"}}this.mode_div.text("Auto ("+Y+")")}},incremental_slots:function(ac,Z,ab){var aa=this.view.canvas_manager.dummy_context,Y=this.inc_slots[ac];if(!Y||(Y.mode!==ab)){Y=new (p.FeatureSlotter)(ac,ab==="Pack",w,function(ad){return aa.measureText(ad)});Y.mode=ab;this.inc_slots[ac]=Y}return Y.slot_features(Z)},get_summary_tree_data:function(ac,af,aa,an){if(an>aa-af){an=aa-af}var aj=Math.floor((aa-af)/an),am=[],ab=0;var ad=0,ae=0,ai,al=0,ag=[],ak,ah;var Z=function(aq,ap,ar,ao){aq[0]=ap+ar*ao;aq[1]=ap+(ar+1)*ao};while(al<an&&ad!==ac.length){var Y=false;for(;al<an&&!Y;al++){Z(ag,af,al,aj);for(ae=ad;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){Y=true;break}}if(Y){break}}data_start_index=ae;am[am.length]=ak=[ag[0],0];for(;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){ak[1]++}else{break}}if(ak[1]>ab){ab=ak[1]}al++}return{max:ab,delta:aj,data:am}},draw_tile:function(al,au,ay,ah,ab){var aq=this,aA=ay*K*au,Z=(ay+1)*K*au,an=Z-aA,ar=Math.ceil(an*ah),ap=this.mode,aE=25,ac=this.left_offset,am,ad;if(ap==="Auto"){if(al.dataset_type==="summary_tree"){ap=al.dataset_type}else{if(al.extra_info==="no_detail"){ap="no_detail"}else{var aD=al.data;if(this.view.high-this.view.low>D){ap="Squish"}else{ap="Pack"}}}this.update_auto_mode(ap)}if(ap==="summary_tree"||ap==="Histogram"){ad=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var Y=$("<div />").addClass("yaxislabel");Y.text(al.max);Y.css({position:"absolute",top:"22px",left:"10px"});Y.prependTo(this.container_div);var aa=this.view.canvas_manager.new_canvas();aa.width=ar+ac;aa.height=ad+M;if(al.dataset_type!="summary_tree"){var ai=this.get_summary_tree_data(al.data,aA,Z,200);if(al.max){ai.max=al.max}al=ai}var aB=new G.SummaryTreePainter(al,aA,Z,this.prefs);var at=aa.getContext("2d");at.translate(ac,M);aB.draw(at,ar,ad);return new m(ay,au,aa,al.max)}var am,af=1;if(ap==="no_detail"||ap==="Squish"||ap==="Pack"){af=this.incremental_slots(ah,al.data,ap);am=this.inc_slots[ah].slots}var ag=[];if(al.data){var aj=this.filters_manager.filters;for(var av=0,ax=al.data.length;av<ax;av++){var ae=al.data[av];var aw=false;var ak;for(var az=0,aC=aj.length;az<aC;az++){ak=aj[az];ak.update_attrs(ae);if(!ak.keep(ae)){aw=true;break}}if(!aw){ag.push(ae)}}}var aB=new (this.painter)(ag,aA,Z,this.prefs,ap,ab);var ad=aB.get_required_height(af)+z;var aa=this.view.canvas_manager.new_canvas();aa.width=ar+ac;aa.height=ad;var at=aa.getContext("2d");at.fillStyle=this.prefs.block_color;at.font=at.canvas.manager.default_font;at.textAlign="right";this.container_div.find(".yaxislabel").remove();if(al.message){$(aa).css({"border-top":"1px solid red"});at.fillStyle="red";at.textAlign="left";var ao=at.textBaseline;at.textBaseline="top";at.fillText(al.message,ac,0);at.textBaseline=ao;if(!al.data){return new b(ay,au,aa,ad)}}this.example_feature=(al.data.length?al.data[0]:undefined);at.translate(ac,z);aB.draw(at,ar,ad,am);return new J(ay,au,aa)}});var N=function(ab,Z,ad,Y,aa,ac){e.call(this,ab,Z,ad,Y,aa,ac);this.track_type="VcfTrack";this.painter=G.VariantPainter};extend(N.prototype,H.prototype,e.prototype);var Q=function(ab,Z,ad,Y,aa,ac){e.call(this,ab,Z,ad,Y,aa,ac);this.track_config=new T({track:this,params:[{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:aa,onchange:function(){this.track.tile_cache.clear();this.track.draw()}});this.prefs=this.track_config.values;this.track_type="ReadTrack";this.painter=G.ReadPainter;this.make_name_popup_menu()};extend(Q.prototype,H.prototype,e.prototype);var O=function(ac,aa,ae,Y,ab,ad,Z){e.call(this,ac,aa,ae,Y,ab,ad,{},Z);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};extend(O.prototype,H.prototype,e.prototype,{predraw_init:function(){var Z=this;var Y=function(){if(Z.data_cache.size()===0){setTimeout(Y,300)}else{Z.data_url=default_data_url;Z.data_query_wait=F;Z.dataset_state_url=converted_datasets_state_url;$.getJSON(Z.dataset_state_url,{dataset_id:Z.dataset_id,hda_ldda:Z.hda_ldda},function(aa){})}};Y()}});R.View=W;R.LineTrack=l;R.FeatureTrack=e;R.ReadTrack=Q};var slotting_module=function(c,b){var d=2,a=5;b.FeatureSlotter=function(h,g,e,f){this.slots={};this.start_end_dct={};this.w_scale=h;this.include_label=g;this.max_rows=e;this.measureText=f};extend(b.FeatureSlotter.prototype,{slot_features:function(l){var o=this.w_scale,r=this.slots,g=this.start_end_dct,x=[],z=[],m=0,y=this.max_rows;for(var v=0,w=l.length;v<w;v++){var k=l[v],n=k[0];if(r[n]!==undefined){m=Math.max(m,r[n]);z.push(r[n])}else{x.push(v)}}var p=function(F,G){for(var E=0;E<=y;E++){var C=false,H=g[E];if(H!==undefined){for(var B=0,D=H.length;B<D;B++){var A=H[B];if(G>A[0]&&F<A[1]){C=true;break}}}if(!C){return E}}return -1};for(var v=0,w=x.length;v<w;v++){var k=l[x[v]],n=k[0],t=k[1],e=k[2],q=k[3],f=Math.floor(t*o),j=Math.ceil(e*o),u=this.measureText(q).width,h;if(q!==undefined&&this.include_label){u+=(d+a);if(f-u>=0){f-=u;h="left"}else{j+=u;h="right"}}var s=p(f,j);if(s>=0){if(g[s]===undefined){g[s]=[]}g[s].push([f,j]);r[n]=s;m=Math.max(m,s)}else{}}return m+1}})};var painters_module=function(j,v){var o=function(G,y,E,x,D,B){if(B===undefined){B=4}var A=x-y;var z=D-E;var C=Math.floor(Math.sqrt(A*A+z*z)/B);var H=A/C;var F=z/C;var w;for(w=0;w<C;w++,y+=H,E+=F){if(w%2!==0){continue}G.fillRect(y,E,B,1)}};var p=function(z,x,w,C){var B=x-C/2,A=x+C/2,D=w-Math.sqrt(C*3/2);z.beginPath();z.moveTo(B,D);z.lineTo(A,D);z.lineTo(x,w);z.lineTo(B,D);z.strokeStyle=this.fillStyle;z.fill();z.stroke();z.closePath()};var l=function(y,A,w,x,z){this.data=y;this.view_start=A;this.view_end=w;this.prefs=extend({},this.default_prefs,x);this.mode=z};l.prototype.default_prefs={};var t=function(y,A,w,x,z){l.call(this,y,A,w,x,z)};t.prototype.default_prefs={show_counts:false};t.prototype.draw=function(L,w,K){var D=this.view_start,N=this.view_end-this.view_start,M=w/N;var I=this.data.data,H=this.data.delta,F=this.data.max,A=K;delta_x_px=Math.ceil(H*M);L.save();for(var B=0,C=I.length;B<C;B++){var G=Math.floor((I[B][0]-D)*M);var E=I[B][1];if(!E){continue}var J=E/F*K;if(E!==0&&J<1){J=1}L.fillStyle="black";L.fillRect(G,A-J,delta_x_px,J);var z=4;if(this.prefs.show_counts&&(L.measureText(E).width+z)<delta_x_px){L.fillStyle="#666";L.textAlign="center";L.fillText(E,G+(delta_x_px/2),10)}}L.restore()};var c=function(y,A,w,x,z){l.call(this,y,A,w,x,z)};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(M,L,J){var E=false,F=this.prefs.min_value,C=this.prefs.max_value,I=C-F,x=J,z=this.view_start,K=this.view_end-this.view_start,A=L/K,G=this.mode,Q=this.data;M.save();var R=Math.round(J+F/I*J);if(G!=="Intensity"){M.fillStyle="#aaa";M.fillRect(0,R,L,1)}M.beginPath();M.fillStyle=this.prefs.color;var P,D,B;if(Q.length>1){B=Math.ceil((Q[1][0]-Q[0][0])*A)}else{B=10}for(var N=0,O=Q.length;N<O;N++){P=Math.round((Q[N][0]-z)*A);D=Q[N][1];if(D===null){if(E&&G==="Filled"){M.lineTo(P,x)}E=false;continue}if(D<F){D=F}else{if(D>C){D=C}}if(G==="Histogram"){D=Math.round(D/I*x);M.fillRect(P,R,B,-D)}else{if(G==="Intensity"){D=255-Math.floor((D-F)/I*255);M.fillStyle="rgb("+D+","+D+","+D+")";M.fillRect(P,0,B,x)}else{D=Math.round(x-(D-F)/I*x);if(E){M.lineTo(P,D)}else{E=true;if(G==="Filled"){M.moveTo(P,x);M.lineTo(P,D)}else{M.moveTo(P,D)}}}}}if(G==="Filled"){if(E){M.lineTo(P,R);M.lineTo(0,R)}M.fill()}else{M.stroke()}var w=-1,H=-1;M.fillStyle=this.prefs.overflow_color;for(var N=0,O=Q.length;N<O;N++){D=Q[N][1];P=Math.round((Q[N][0]-z)*A);x_minus_scaled=Math.round((Q[N][0]-1-z)*A);if(H>=0&&(D===null||D<C)){M.fillRect(H,0,x_minus_scaled-H+1,2);H=-1}else{if(w>=0&&(D===null||D>F)){M.fillRect(w,J-2,x_minus_scaled-w+1,2);w=-1}}if(D!==null&&D>C&&H<0){H=P}else{if(D!==null&&D<F&&w<0){w=P}}}M.restore()};var n=function(y,A,w,x,z){l.call(this,y,A,w,x,z)};n.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(n.prototype,{get_required_height:function(x){var w=y_scale=this.get_row_height(),y=this.mode;if(y==="no_detail"||y==="Squish"||y==="Pack"){w=x*y_scale}return w+Math.max(Math.round(y_scale/2),5)},draw:function(I,z,H,E){var C=this.data,F=this.view_start,J=this.view_end;I.save();I.fillStyle=this.prefs.block_color;I.textAlign="right";var M=this.view_end-this.view_start,L=z/M,y=this.get_row_height();for(var B=0,D=C.length;B<D;B++){var K=C[B],A=K[0],w=K[1],x=K[2],G=(E&&E[A]!==undefined?E[A]:null);if((w<J&&x>F)&&(this.mode=="Dense"||G!==null)){this.draw_element(I,this.mode,K,G,F,J,L,y,z)}}I.restore()}});var d=10,h=3,k=5,u=10,f=1,r=3,e=3,a=9,m=2,g="#ccc";var q=function(y,A,w,x,z){n.call(this,y,A,w,x,z)};extend(q.prototype,n.prototype,{get_row_height:function(){var x=this.mode,w;if(x==="Dense"){w=d}else{if(x==="no_detail"){w=h}else{if(x==="Squish"){w=k}else{w=u}}}return w},draw_element:function(I,B,Q,D,K,aa,ae,af,w){var N=Q[0],ac=Q[1],U=Q[2],L=Q[3],V=Math.floor(Math.max(0,(ac-K)*ae)),J=Math.ceil(Math.min(w,Math.max(0,(U-K)*ae))),T=(B==="Dense"?0:(0+D))*af,H,Y,M=null,ag=null,z=this.prefs.block_color,X=this.prefs.label_color;if(B=="Dense"){D=1}if(B==="no_detail"){I.fillStyle=z;I.fillRect(V,T+5,J-V,f)}else{var G=Q[4],S=Q[5],W=Q[6],A=Q[7];if(S&&W){M=Math.floor(Math.max(0,(S-K)*ae));ag=Math.ceil(Math.min(w,Math.max(0,(W-K)*ae)))}var ad,O;if(B==="Squish"||B==="Dense"){ad=1;O=e}else{ad=5;O=a}if(!A){if(Q.strand){if(Q.strand==="+"){I.fillStyle=I.canvas.manager.get_pattern("right_strand_inv")}else{if(Q.strand==="-"){I.fillStyle=I.canvas.manager.get_pattern("left_strand_inv")}}}else{I.fillStyle=z}I.fillRect(V,T,J-V,O)}else{var F,P;if(B==="Squish"||B==="Dense"){I.fillStyle=g;F=T+Math.floor(e/2)+1;P=1}else{if(G){var F=T;var P=O;if(G==="+"){I.fillStyle=I.canvas.manager.get_pattern("right_strand")}else{if(G==="-"){I.fillStyle=I.canvas.manager.get_pattern("left_strand")}}}else{I.fillStyle=g;F+=(e/2)+1;P=1}}I.fillRect(V,F,J-V,P);for(var ab=0,y=A.length;ab<y;ab++){var C=A[ab],x=Math.floor(Math.max(0,(C[0]-K)*ae)),R=Math.ceil(Math.min(w,Math.max((C[1]-K)*ae)));if(x>R){continue}I.fillStyle=z;I.fillRect(x,T+(O-ad)/2+1,R-x,ad);if(M!==undefined&&W>S&&!(x>ag||R<M)){var Z=Math.max(x,M),E=Math.min(R,ag);I.fillRect(Z,T+1,E-Z,O);if(A.length==1&&B=="Pack"){if(G==="+"){I.fillStyle=I.canvas.manager.get_pattern("right_strand_inv")}else{if(G==="-"){I.fillStyle=I.canvas.manager.get_pattern("left_strand_inv")}}if(Z+14<E){Z+=2;E-=2}I.fillRect(Z,T+1,E-Z,O)}}}}if(B==="Pack"&&ac>K){I.fillStyle=X;if(K===0&&V-I.measureText(L).width<0){I.textAlign="left";I.fillText(L,J+m,T+8)}else{I.textAlign="right";I.fillText(L,V-m,T+8)}I.fillStyle=z}}}});var b=function(y,A,w,x,z){n.call(this,y,A,w,x,z)};extend(b.prototype,n.prototype,{draw_element:function(P,K,E,A,S,y,H,Q,N){var E=data[i],G=E[0],O=E[1],z=E[2],J=E[3],C=Math.floor(Math.max(0,(O-S)*H)),F=Math.ceil(Math.min(N,Math.max(0,(z-S)*H))),B=(K==="Dense"?0:(0+A))*Q,w,T,x=null,I=null;if(no_label){P.fillStyle=block_color;P.fillRect(C+left_offset,B+5,F-C,1)}else{var R=E[4],M=E[5],D=E[6];w=9;T=1;P.fillRect(C+left_offset,B,F-C,w);if(K!=="Dense"&&J!==undefined&&O>S){P.fillStyle=label_color;if(S===0&&C-P.measureText(J).width<0){P.textAlign="left";P.fillText(J,F+2+left_offset,B+8)}else{P.textAlign="right";P.fillText(J,C-2+left_offset,B+8)}P.fillStyle=block_color}var L=R+" / "+M;if(O>S&&P.measureText(L).width<(F-C)){P.fillStyle="white";P.textAlign="center";P.fillText(L,left_offset+C+(F-C)/2,B+8);P.fillStyle=block_color}}}});var s=function(z,B,w,y,A,x){n.call(this,z,B,w,y,A);this.ref_seq=x};s.prototype.default_prefs=extend({},n.prototype.default_prefs,{show_insertions:false});extend(s.prototype,n.prototype,{get_row_height:function(){var w,x=this.mode;if(x==="Dense"){w=d}else{if(x==="Squish"){w=k}else{w=u;if(this.prefs.show_insertions){w*=2}}}return w},draw_read:function(S,N,J,X,y,R,G,D,C){S.textAlign="center";var Q=this,x=[X,y],M=0,T=0,P=0;ref_seq=this.ref_seq,char_width_px=S.canvas.manager.char_width_px;var ac=[];if((N==="Pack"||this.mode==="Auto")&&D!==undefined&&J>char_width_px){P=Math.round(J/2)}if(!G){G=[[0,D.length]]}for(var K=0,V=G.length;K<V;K++){var H=G[K],z="MIDNSHP=X"[H[0]],L=H[1];if(z==="H"||z==="S"){M-=L}var E=R+M,ab=Math.floor(Math.max(0,(E-X)*J)),F=Math.floor(Math.max(0,(E+L-X)*J));if(ab===F){F+=1}switch(z){case"H":break;case"S":case"M":case"=":if(is_overlap([E,E+L],x)){var O=D.slice(T,T+L);if(P>0){S.fillStyle=this.prefs.block_color;S.fillRect(ab-P,C+1,F-ab,9);S.fillStyle=g;for(var Z=0,w=O.length;Z<w;Z++){if(this.prefs.show_differences&&ref_seq){var I=ref_seq[E-X+Z];if(!I||I.toLowerCase()===O[Z].toLowerCase()){continue}}if(E+Z>=X&&E+Z<=y){var aa=Math.floor(Math.max(0,(E+Z-X)*J));S.fillText(O[Z],aa,C+9)}}}else{S.fillStyle=this.prefs.block_color;S.fillRect(ab,C+4,F-ab,e)}}T+=L;M+=L;break;case"N":S.fillStyle=g;S.fillRect(ab-P,C+5,F-ab,1);M+=L;break;case"D":S.fillStyle="red";S.fillRect(ab-P,C+4,F-ab,3);M+=L;break;case"P":break;case"I":var W=ab-P;if(is_overlap([E,E+L],x)){var O=D.slice(T,T+L);if(this.prefs.show_insertions){var B=ab-(F-ab)/2;if((N==="Pack"||this.mode==="Auto")&&D!==undefined&&J>char_width_px){S.fillStyle="yellow";S.fillRect(B-P,C-9,F-ab,9);ac[ac.length]={type:"triangle",data:[W,C+4,5]};S.fillStyle=g;switch(seq_tile_overlap){case (OVERLAP_START):O=O.slice(X-E);break;case (OVERLAP_END):O=O.slice(0,E-y);break;case (CONTAINED_BY):break;case (CONTAINS):O=O.slice(X-E,E-y);break}for(var Z=0,w=O.length;Z<w;Z++){var aa=Math.floor(Math.max(0,(E+Z-X)*J));S.fillText(O[Z],aa-(F-ab)/2,C)}}else{S.fillStyle="yellow";S.fillRect(B,C+(this.mode!=="Dense"?2:5),F-ab,(N!=="Dense"?e:r))}}else{if((N==="Pack"||this.mode==="Auto")&&D!==undefined&&J>char_width_px){ac[ac.length]={type:"text",data:[O.length,W,C+9]}}else{}}}T+=L;break;case"X":T+=L;break}}S.fillStyle="yellow";var Y,A,ad;for(var U=0;U<ac.length;U++){Y=ac[U];A=Y.type;ad=Y.data;if(A==="text"){S.save();S.font="bold "+S.font;S.fillText(ad[0],ad[1],ad[2]);S.restore()}else{if(A=="triangle"){p(S,ad[0],ad[1],ad[2])}}}},draw_element:function(P,K,C,z,S,x,G,Q,N){var F=C[0],O=C[1],y=C[2],H=C[3],B=Math.floor(Math.max(0,(O-S)*G)),D=Math.ceil(Math.min(N,Math.max(0,(y-S)*G))),A=(K==="Dense"?0:(0+z))*Q,T=this.prefs.block_color,E=this.prefs.label_color,M=0;if((K==="Pack"||this.mode==="Auto")&&G>P.canvas.manager.char_width_px){var M=Math.round(G/2)}P.fillStyle=T;if(C[5] instanceof Array){var L=Math.floor(Math.max(0,(C[4][0]-S)*G)),J=Math.ceil(Math.min(N,Math.max(0,(C[4][1]-S)*G))),I=Math.floor(Math.max(0,(C[5][0]-S)*G)),w=Math.ceil(Math.min(N,Math.max(0,(C[5][1]-S)*G)));if(C[4][1]>=S&&C[4][0]<=x&&C[4][2]){this.draw_read(P,K,G,S,x,C[4][0],C[4][2],C[4][3],A)}if(C[5][1]>=S&&C[5][0]<=x&&C[5][2]){this.draw_read(P,K,G,S,x,C[5][0],C[5][2],C[5][3],A)}if(I>J){P.fillStyle=g;o(P,J-M,A+5,I-M,A+5)}}else{P.fillStyle=T;this.draw_read(P,K,G,S,x,O,C[4],C[5],A)}if(K==="Pack"&&O>S){P.fillStyle=this.prefs.label_color;var R=1;if(R===0&&B-P.measureText(H).width<0){P.textAlign="left";P.fillText(H,D+m-M,A+8)}else{P.textAlign="right";P.fillText(H,B-m-M,A+8)}P.fillStyle=T}}});v.SummaryTreePainter=t;v.LinePainter=c;v.LinkedFeaturePainter=q;v.ReadPainter=s;v.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("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/trackster.js Thu Apr 14 10:37:42 2011 -0400
+++ b/static/scripts/trackster.js Thu Apr 14 14:29:32 2011 -0400
@@ -1311,9 +1311,9 @@
* Tiles drawn by tracks.
*/
var Tile = function(index, resolution, canvas) {
- // Wrap element in div for background
this.index = index;
this.resolution = resolution;
+ // Wrap element in div for background.
this.canvas = $("<div class='track-tile'/>").append(canvas);
};
@@ -1743,7 +1743,9 @@
//
// If mode is Histogram and tiles do not share max, redraw tiles as necessary using new max.
//
- if (track.mode == "Histogram") {
+ // HACK: use track type b/c LineTrack histograms are different; what's needed is different
+ // post-draw actions for different line tracks.
+ if (track.track_type == "FeatureTrack" && track.mode == "Histogram") {
// Get global max.
var global_max = -1;
for (var i = 0; i < drawn_tiles.length; i++) {
@@ -1826,7 +1828,7 @@
var draw_and_show_tile = function(id, result, resolution, tile_index, parent_element, w_scale, seq_data) {
// DEBUG: this is still called too many times when moving slowly,
// console.log( "draw_and_show_tile", resolution, tile_index, w_scale );
- var tile = track.draw_tile(result, resolution, tile_index, parent_element, w_scale, seq_data);
+ var tile = track.draw_tile(result, resolution, tile_index, w_scale, seq_data);
track.tile_cache.set(key, tile);
track.show_tile(tile, parent_element, tile_low, w_scale);
drawn_tiles[drawn_tiles.length] = tile;
@@ -1882,9 +1884,9 @@
}
var tile_element = tile.canvas;
tile_element.css({ position: 'absolute', top: 0, left: left, height: '' });
-
- // Setup and show tile element.
parent_element.append(tile_element);
+
+ // Set track height.
track.max_height = Math.max(track.max_height, tile_element.height());
track.content_div.css("height", track.max_height + "px");
parent_element.children().css("height", track.max_height + "px");
@@ -1984,7 +1986,7 @@
/**
* Draw ReferenceTrack tile.
*/
- draw_tile: function(seq, resolution, tile_index, parent_element, w_scale) {
+ draw_tile: function(seq, resolution, tile_index, w_scale) {
var track = this,
tile_length = DENSITY * resolution;
@@ -2122,7 +2124,7 @@
/**
* Draw LineTrack tile.
*/
- draw_tile: function(result, resolution, tile_index, parent_element, w_scale) {
+ draw_tile: function(result, resolution, tile_index, w_scale) {
if (this.vertical_range === undefined) {
return;
}
@@ -2312,7 +2314,7 @@
/**
* Draw FeatureTrack tile.
*/
- draw_tile: function(result, resolution, tile_index, parent_element, w_scale, ref_seq) {
+ draw_tile: function(result, resolution, tile_index, w_scale, ref_seq) {
var track = this,
tile_low = tile_index * DENSITY * resolution,
tile_high = ( tile_index + 1 ) * DENSITY * resolution,
@@ -2343,7 +2345,7 @@
var data = result.data;
// if ( (data.length && data.length < 4) ||
// (this.view.high - this.view.low > MIN_SQUISH_VIEW_WIDTH) ) {
- if ( this.view.high - this.view.low > MIN_SQUISH_VIEW_WIDTH ) {
+ if ( this.view.high - this.view.low > MIN_SQUISH_VIEW_WIDTH ) {
mode = "Squish";
} else {
mode = "Pack";
@@ -2354,9 +2356,7 @@
// Drawing the summary tree (feature coverage histogram)
if (mode === "summary_tree" || mode === "Histogram") {
- // Set height of parent_element
required_height = this.summary_draw_height;
- parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
// Add label to container div showing maximum count
// TODO: this shouldn't be done at the tile level
this.container_div.find(".yaxislabel").remove();
@@ -2428,7 +2428,6 @@
canvas.width = width + left_offset;
canvas.height = required_height;
- parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
// console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
var ctx = canvas.getContext("2d");
ctx.fillStyle = this.prefs.block_color;
@@ -2452,7 +2451,7 @@
// If there's no data, return.
if (!result.data) {
- return new Tile(tile_index, resolution, canvas);
+ return new Tile(tile_index, resolution, canvas, required_height);
}
}
@@ -2460,8 +2459,8 @@
this.example_feature = (result.data.length ? result.data[0] : undefined);
// Draw features
- ctx.translate( left_offset, ERROR_PADDING );
- painter.draw( ctx, width, required_height, slots );
+ ctx.translate(left_offset, ERROR_PADDING);
+ painter.draw(ctx, width, required_height, slots);
return new FeatureTrackTile(tile_index, resolution, canvas);
}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: refactor so that summary_tree and Histogram modes use the same code.
by Bitbucket 14 Apr '11
by Bitbucket 14 Apr '11
14 Apr '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/9203be6a16b3/
changeset: r5388:9203be6a16b3
user: jgoecks
date: 2011-04-14 16:37:42
summary: Trackster: refactor so that summary_tree and Histogram modes use the same code.
affected #: 1 file (1.3 KB)
--- a/static/scripts/trackster.js Thu Apr 14 10:05:00 2011 -0400
+++ b/static/scripts/trackster.js Thu Apr 14 10:37:42 2011 -0400
@@ -2353,7 +2353,7 @@
}
// Drawing the summary tree (feature coverage histogram)
- if ( mode === "summary_tree" ) {
+ if (mode === "summary_tree" || mode === "Histogram") {
// Set height of parent_element
required_height = this.summary_draw_height;
parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
@@ -2369,44 +2369,22 @@
canvas.width = width + left_offset;
// Extra padding at top of summary tree
canvas.height = required_height + SUMMARY_TREE_TOP_PADDING;
+
+ // Get summary tree data if necessary and set max if there is one.
+ if (result.dataset_type != "summary_tree") {
+ var st_data = this.get_summary_tree_data(result.data, tile_low, tile_high, 200);
+ if (result.max) {
+ st_data.max = result.max;
+ }
+ result = st_data;
+ }
// Paint summary tree into canvas
- var painter = new painters.SummaryTreePainter( result, tile_low, tile_high, this.prefs );
- var ctx = canvas.getContext("2d");
- // Deal with left_offset by translating
- ctx.translate( left_offset, SUMMARY_TREE_TOP_PADDING );
- painter.draw( ctx, width, required_height );
- return new SummaryTreeTile(tile_index, resolution, canvas, result.max);
- }
-
- // Drawing coverage histogram. This is different from summary tree because data can feature
- // details, but user has requested a histogram.
- if (mode === "Histogram") {
- // Set height of parent_element
- required_height = this.summary_draw_height;
- parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
- // Add label to container div showing maximum count
- // TODO: this shouldn't be done at the tile level
- this.container_div.find(".yaxislabel").remove();
- var max_label = $("<div />").addClass('yaxislabel');
- max_label.text( result.max );
- max_label.css({ position: "absolute", top: "22px", left: "10px" });
- max_label.prependTo(this.container_div);
- // Create canvas
- var canvas = this.view.canvas_manager.new_canvas();
- canvas.width = width + left_offset;
- // Extra padding at top of summary tree
- canvas.height = required_height + SUMMARY_TREE_TOP_PADDING;
- // Paint summary tree into canvas.
- var binned_data = this.get_summary_tree_data(result.data, tile_low, tile_high, 200);
- if (result.max) {
- binned_data.max = result.max;
- }
- var painter = new painters.SummaryTreePainter(binned_data, tile_low, tile_high, this.prefs);
+ var painter = new painters.SummaryTreePainter(result, tile_low, tile_high, this.prefs);
var ctx = canvas.getContext("2d");
// Deal with left_offset by translating
ctx.translate(left_offset, SUMMARY_TREE_TOP_PADDING);
painter.draw(ctx, width, required_height);
- return new SummaryTreeTile(tile_index, resolution, canvas, binned_data.max);
+ return new SummaryTreeTile(tile_index, resolution, canvas, result.max);
}
// Start dealing with row-by-row tracks
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Fix bug that prevented workflows with runtime parameters from being exported.
by Bitbucket 14 Apr '11
by Bitbucket 14 Apr '11
14 Apr '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/835656900dd0/
changeset: r5387:835656900dd0
user: jgoecks
date: 2011-04-14 16:05:00
summary: Fix bug that prevented workflows with runtime parameters from being exported.
affected #: 1 file (5 bytes)
--- a/lib/galaxy/web/controllers/workflow.py Thu Apr 14 09:02:20 2011 -0400
+++ b/lib/galaxy/web/controllers/workflow.py Thu Apr 14 10:05:00 2011 -0400
@@ -1587,7 +1587,7 @@
for name, val in module.state.inputs.items():
input_type = type( val )
if input_type == RuntimeValue:
- step['inputs'].append( { "name" : name, "description" : "runtime parameter for tool %s" % module.get_name() } )
+ step_dict['inputs'].append( { "name" : name, "description" : "runtime parameter for tool %s" % module.get_name() } )
elif input_type == dict:
# Input type is described by a dict, e.g. indexed parameters.
for partname, partval in val.items():
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new changesets in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/3504e971d8b8/
changeset: r5384:3504e971d8b8
user: Martijn Vermaat
date: 2011-04-14 12:14:30
summary: Adds filtering to input selection on run workflow page.
affected #: 2 files (2.3 KB)
--- a/static/june_2007_style/blue/base.css Thu Apr 14 01:13:10 2011 +0200
+++ b/static/june_2007_style/blue/base.css Thu Apr 14 12:14:30 2011 +0200
@@ -172,4 +172,4 @@
.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -364px;}
.icon-button.multiinput{background:url(../images/documents-stack.png) no-repeat;cursor:pointer;float:none;display:inline-block;margin-left:10px;}
.icon-button.multiinput.disabled{background:url(../images/documents-stack-faded.png) no-repeat;cursor:auto;}
-.workflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
+.workflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;padding-left:5px;}
--- a/templates/workflow/run.mako Thu Apr 14 01:13:10 2011 +0200
+++ b/templates/workflow/run.mako Thu Apr 14 12:14:30 2011 +0200
@@ -21,6 +21,7 @@
}
}
function toggle_multiinput(select) {
+ var placeholder;
if (select.attr('multiple')) {
$('.multiinput').removeClass('disabled');
if (select.val()) {
@@ -28,12 +29,16 @@
} else {
select.val($('option:last', select).val());
}
- select.removeAttr('multiple');
+ select.removeAttr('multiple').removeAttr('size');
+ placeholder = 'type to filter';
} else {
$('.multiinput').addClass('disabled');
$('.multiinput', select.parent().prev()).removeClass('disabled');
- select.attr('multiple', 'multiple');
+ select.attr('multiple', 'multiple').attr('size', 8);
+ placeholder = 'type to filter, [enter] to select all';
}
+ $('input.multiinput-filter', select.parent()).attr(
+ 'placeholder', placeholder);
}
$( "select[refresh_on_change='true']").change( function() {
$( "#tool_form" ).submit();
@@ -58,6 +63,7 @@
});
$('select[name*="|input"]').removeAttr('multiple').each(function(i, s) {
var select = $(s);
+ var new_width = select.width() + 20;
select.parent().prev().append(
$('<span class="icon-button multiinput"></span>').click(function() {
if ($(this).hasClass('disabled')) return;
@@ -68,6 +74,44 @@
'files. Each selected file will have an ' +
'instance of the workflow.').tipsy({gravity:'s'})
);
+ var filter = $('<input type="text" class="multiinput-filter" ' +
+ 'placeholder="type to filter">');
+ var filter_timeout = false;
+ var original_rows = select.find('option');
+ var previous_filter = '';
+ // Todo: might have to choose keypress, depending on browser
+ filter.keydown(function(e) {
+ var filter_select = function() {
+ var f = $.trim(filter.val());
+ var filtered_rows = original_rows;
+ if (f.length >= 1) {
+ filtered_rows = original_rows.filter(function() {
+ return new RegExp(f, 'ig').test($(this).text());
+ });
+ }
+ select.html('');
+ select.html(filtered_rows);
+ };
+ if (e.which == 13) { // 13 = enter key
+ e.preventDefault();
+ multi = select.attr('multiple');
+ if (typeof multi !== 'undefined' && multi !== false) {
+ if (!select.find('option:not(:selected)').length) {
+ select.find('option').removeAttr('selected');
+ } else {
+ select.find('option').attr('selected', 'selected');
+ }
+ }
+ return;
+ }
+ if (filter.val() != previous_filter) {
+ if (filter_timeout) clearTimeout(filter_timeout);
+ timeout = setTimeout(filter_select, 300);
+ previous_filter = filter.val();
+ }
+ }).width(new_width).css('display', 'block');
+ select.after(filter);
+ select.width(new_width);
});
});
</script>
http://bitbucket.org/galaxy/galaxy-central/changeset/d6fda5e30200/
changeset: r5385:d6fda5e30200
user: Martijn Vermaat
date: 2011-04-14 14:23:28
summary: Give input selection and filtering a minimum width (run tool form).
affected #: 1 file (15 bytes)
--- a/templates/workflow/run.mako Thu Apr 14 12:14:30 2011 +0200
+++ b/templates/workflow/run.mako Thu Apr 14 14:23:28 2011 +0200
@@ -63,7 +63,7 @@
});
$('select[name*="|input"]').removeAttr('multiple').each(function(i, s) {
var select = $(s);
- var new_width = select.width() + 20;
+ var new_width = Math.max(200, select.width()) + 20;
select.parent().prev().append(
$('<span class="icon-button multiinput"></span>').click(function() {
if ($(this).hasClass('disabled')) return;
http://bitbucket.org/galaxy/galaxy-central/changeset/67a19816034b/
changeset: r5386:67a19816034b
user: dannon
date: 2011-04-14 15:02:20
summary: Merge!
affected #: 2 files (2.3 KB)
--- a/static/june_2007_style/blue/base.css Thu Apr 14 08:09:48 2011 -0400
+++ b/static/june_2007_style/blue/base.css Thu Apr 14 09:02:20 2011 -0400
@@ -172,4 +172,4 @@
.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -364px;}
.icon-button.multiinput{background:url(../images/documents-stack.png) no-repeat;cursor:pointer;float:none;display:inline-block;margin-left:10px;}
.icon-button.multiinput.disabled{background:url(../images/documents-stack-faded.png) no-repeat;cursor:auto;}
-.workflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
+.workflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;padding-left:5px;}
--- a/templates/workflow/run.mako Thu Apr 14 08:09:48 2011 -0400
+++ b/templates/workflow/run.mako Thu Apr 14 09:02:20 2011 -0400
@@ -21,6 +21,7 @@
}
}
function toggle_multiinput(select) {
+ var placeholder;
if (select.attr('multiple')) {
$('.multiinput').removeClass('disabled');
if (select.val()) {
@@ -28,12 +29,16 @@
} else {
select.val($('option:last', select).val());
}
- select.removeAttr('multiple');
+ select.removeAttr('multiple').removeAttr('size');
+ placeholder = 'type to filter';
} else {
$('.multiinput').addClass('disabled');
$('.multiinput', select.parent().prev()).removeClass('disabled');
- select.attr('multiple', 'multiple');
+ select.attr('multiple', 'multiple').attr('size', 8);
+ placeholder = 'type to filter, [enter] to select all';
}
+ $('input.multiinput-filter', select.parent()).attr(
+ 'placeholder', placeholder);
}
$( "select[refresh_on_change='true']").change( function() {
$( "#tool_form" ).submit();
@@ -58,6 +63,7 @@
});
$('select[name*="|input"]').removeAttr('multiple').each(function(i, s) {
var select = $(s);
+ var new_width = Math.max(200, select.width()) + 20;
select.parent().prev().append(
$('<span class="icon-button multiinput"></span>').click(function() {
if ($(this).hasClass('disabled')) return;
@@ -68,6 +74,44 @@
'files. Each selected file will have an ' +
'instance of the workflow.').tipsy({gravity:'s'})
);
+ var filter = $('<input type="text" class="multiinput-filter" ' +
+ 'placeholder="type to filter">');
+ var filter_timeout = false;
+ var original_rows = select.find('option');
+ var previous_filter = '';
+ // Todo: might have to choose keypress, depending on browser
+ filter.keydown(function(e) {
+ var filter_select = function() {
+ var f = $.trim(filter.val());
+ var filtered_rows = original_rows;
+ if (f.length >= 1) {
+ filtered_rows = original_rows.filter(function() {
+ return new RegExp(f, 'ig').test($(this).text());
+ });
+ }
+ select.html('');
+ select.html(filtered_rows);
+ };
+ if (e.which == 13) { // 13 = enter key
+ e.preventDefault();
+ multi = select.attr('multiple');
+ if (typeof multi !== 'undefined' && multi !== false) {
+ if (!select.find('option:not(:selected)').length) {
+ select.find('option').removeAttr('selected');
+ } else {
+ select.find('option').attr('selected', 'selected');
+ }
+ }
+ return;
+ }
+ if (filter.val() != previous_filter) {
+ if (filter_timeout) clearTimeout(filter_timeout);
+ timeout = setTimeout(filter_select, 300);
+ previous_filter = filter.val();
+ }
+ }).width(new_width).css('display', 'block');
+ select.after(filter);
+ select.width(new_width);
});
});
</script>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: fubar: Changes to allow all test outputs generated by twill to be saved to a folder pointed to by
by Bitbucket 14 Apr '11
by Bitbucket 14 Apr '11
14 Apr '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b9cff3fbd170/
changeset: r5383:b9cff3fbd170
user: fubar
date: 2011-04-14 14:09:48
summary: Changes to allow all test outputs generated by twill to be saved to a folder pointed to by
an environment variable "GALAXY_TEST_SAVE" if defined before running functional tests
If the environment variable is empty, all tests procede as usual and test outputs are deleted
without saving
affected #: 3 files (770 bytes)
--- a/scripts/functional_tests.py Wed Apr 13 19:14:21 2011 -0400
+++ b/scripts/functional_tests.py Thu Apr 14 08:09:48 2011 -0400
@@ -47,6 +47,8 @@
galaxy_test_host = os.environ.get( 'GALAXY_TEST_HOST', default_galaxy_test_host )
galaxy_test_port = os.environ.get( 'GALAXY_TEST_PORT', None )
+ galaxy_test_save = os.environ.get( 'GALAXY_TEST_SAVE', None)
+
if 'HTTP_ACCEPT_LANGUAGE' not in os.environ:
os.environ['HTTP_ACCEPT_LANGUAGE'] = default_galaxy_locales
galaxy_test_file_dir = os.environ.get( 'GALAXY_TEST_FILE_DIR', default_galaxy_test_file_dir )
@@ -126,10 +128,14 @@
print "Database connection:", database_connection
- # What requires these?
+ # What requires these?
+ # handy for (eg) functional tests to save outputs?
+ if galaxy_test_save:
+ os.environ['GALAXY_TEST_SAVE'] = galaxy_test_save
+ # pass in through script setenv
+ # will leave a copy of ALL test validate files
os.environ['GALAXY_TEST_HOST'] = galaxy_test_host
os.environ['GALAXY_TEST_FILE_DIR'] = galaxy_test_file_dir
-
# ---- Build Application --------------------------------------------------
app = None
--- a/test/base/twilltestcase.py Wed Apr 13 19:14:21 2011 -0400
+++ b/test/base/twilltestcase.py Thu Apr 14 08:09:48 2011 -0400
@@ -32,7 +32,14 @@
self.port = os.environ.get( 'GALAXY_TEST_PORT' )
self.url = "http://%s:%s" % ( self.host, self.port )
self.file_dir = os.environ.get( 'GALAXY_TEST_FILE_DIR' )
+ self.keepOutdir = os.environ.get( 'GALAXY_TEST_SAVE', '' )
+ if self.keepOutdir > '':
+ try:
+ os.makedirs(self.keepOutdir)
+ except:
+ pass
self.home()
+
#self.set_history()
# Functions associated with files
@@ -632,6 +639,10 @@
self.visit_page( "display?hid=" + hid )
data = self.last_page()
file( temp_name, 'wb' ).write(data)
+ if self.keepOutdir > '':
+ ofn = os.path.join(self.keepOutdir,os.path.basename(local_name))
+ shutil.copy(temp_name,ofn)
+ log.debug('## GALAXY_TEST_SAVE=%s. saved %s' % (self.keepOutdir,ofn))
try:
# have to nest try-except in try-finally to handle 2.4
try:
--- a/tools/rgenetics/rgQC.xml Wed Apr 13 19:14:21 2011 -0400
+++ b/tools/rgenetics/rgQC.xml Thu Apr 14 08:09:48 2011 -0400
@@ -28,6 +28,7 @@
</param><param name='title' value='rgQCtest1' /><output name='html_file' file='rgtestouts/rgQC/rgQCtest1.html' ftype='html' lines_diff='300'>
+ <param name="dbkey" value="hg18" /><extra_files type="file" name='tinywga_All_Paged.pdf' value="rgtestouts/rgQC/tinywga_All_Paged.pdf" compare="sim_size" delta = "100000"/><extra_files type="file" name='tinywga.log' value="rgtestouts/rgQC/tinywga.log" compare="diff" lines_diff="15"/><extra_files type="file" name='tinywga.frq' value="rgtestouts/rgQC/tinywga.frq" compare="diff" />
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new changesets in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/74875168e6da/
changeset: r5381:74875168e6da
user: Martijn Vermaat
date: 2011-04-14 01:13:10
summary: Typo.
affected #: 1 file (1 byte)
--- a/static/june_2007_style/blue/base.css Thu Apr 14 01:04:40 2011 +0200
+++ b/static/june_2007_style/blue/base.css Thu Apr 14 01:13:10 2011 +0200
@@ -172,4 +172,4 @@
.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -364px;}
.icon-button.multiinput{background:url(../images/documents-stack.png) no-repeat;cursor:pointer;float:none;display:inline-block;margin-left:10px;}
.icon-button.multiinput.disabled{background:url(../images/documents-stack-faded.png) no-repeat;cursor:auto;}
-.worflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
+.workflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
http://bitbucket.org/galaxy/galaxy-central/changeset/8a0522fff4f7/
changeset: r5382:8a0522fff4f7
user: dannon
date: 2011-04-14 01:14:21
summary: Merge.
affected #: 1 file (1 byte)
--- a/static/june_2007_style/blue/base.css Wed Apr 13 19:07:22 2011 -0400
+++ b/static/june_2007_style/blue/base.css Wed Apr 13 19:14:21 2011 -0400
@@ -172,4 +172,4 @@
.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -364px;}
.icon-button.multiinput{background:url(../images/documents-stack.png) no-repeat;cursor:pointer;float:none;display:inline-block;margin-left:10px;}
.icon-button.multiinput.disabled{background:url(../images/documents-stack-faded.png) no-repeat;cursor:auto;}
-.worflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
+.workflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
5 new changesets in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/56fc50970fc3/
changeset: r5376:56fc50970fc3
user: dannon
date: 2011-04-13 22:35:08
summary: Bugfix for workflow run not reloading history, icon for document stack.
affected #: 2 files (803 bytes)
Binary file static/images/documents-stack.png has changed
--- a/templates/workflow/run_complete.mako Wed Apr 13 16:05:34 2011 -0400
+++ b/templates/workflow/run_complete.mako Wed Apr 13 16:35:08 2011 -0400
@@ -17,4 +17,10 @@
%endfor
%endfor
</div>
-</div>
\ No newline at end of file
+</div>
+
+<script type="text/javascript">
+ if ( parent.frames && parent.frames.galaxy_history ) {
+ parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history' )}";
+ }
+</script>
http://bitbucket.org/galaxy/galaxy-central/changeset/9a72df515de1/
changeset: r5377:9a72df515de1
user: dannon
date: 2011-04-13 22:46:36
summary: Faded document stack icon.
affected #: 1 file (587 bytes)
Binary file static/images/documents-stack-faded.png has changed
http://bitbucket.org/galaxy/galaxy-central/changeset/a946c7e60d1f/
changeset: r5378:a946c7e60d1f
user: dannon
date: 2011-04-14 01:05:45
summary: Merge.
affected #: 1 file (1.8 KB)
--- a/static/scripts/trackster.js Wed Apr 13 16:46:36 2011 -0400
+++ b/static/scripts/trackster.js Wed Apr 13 19:05:45 2011 -0400
@@ -741,7 +741,7 @@
this.high = Math.ceil(high);
// 10^log10(range / DENSITY) Close approximation for browser window, assuming DENSITY = window width
- this.resolution = Math.pow( 10, Math.ceil( Math.log( (this.high - this.low) / 200 ) / Math.LN10 ) );
+ this.resolution = Math.pow( 10, Math.ceil( Math.log( (this.high - this.low) / DENSITY ) / Math.LN10 ) );
this.zoom_res = Math.pow( FEATURE_LEVELS, Math.max(0,Math.ceil( Math.log( this.resolution, FEATURE_LEVELS ) / Math.log(FEATURE_LEVELS) )));
// Overview
@@ -1016,14 +1016,16 @@
return false;
},
/**
- * Returns true iff element is in [low, high]; range is inclusive.
+ * Returns true if (a) element's value is in [low, high] (range is inclusive)
+ * or (b) if value is non-numeric and hence unfilterable.
*/
keep: function(element) {
if ( !this.applies_to( element ) ) {
// No element to filter on.
return true;
}
- return (element[this.index] >= this.low && element[this.index] <= this.high);
+ var val = parseInt(element[this.index]);
+ return (isNaN(val) || (val >= this.low && val <= this.high));
},
/**
* Update filter's min and max values based on element's values.
@@ -1306,11 +1308,22 @@
});
/**
- * Tiles for TiledTracks.
+ * Tiles drawn by tracks.
*/
-var Tile = function(track, canvas) {
- this.track = track;
- this.canvas = canvas;
+var Tile = function(index, resolution, canvas) {
+ // Wrap element in div for background
+ this.index = index;
+ this.resolution = resolution;
+ this.canvas = $("<div class='track-tile'/>").append(canvas);
+};
+
+var SummaryTreeTile = function(index, resolution, canvas, max_val) {
+ Tile.call(this, index, resolution, canvas);
+ this.max_val = max_val;
+};
+
+var FeatureTrackTile = function(index, resolution, canvas) {
+ Tile.call(this, index, resolution, canvas);
};
/**
@@ -1669,30 +1682,33 @@
// w_scale units are pixels per base.
w_scale = width / range,
resolution = this.view.resolution,
- parent_element = $("<div style='position: relative;'></div>");
+ parent_element = $("<div style='position: relative;'></div>"),
+ gen_key = function(width, w_scale, tile_index) {
+ return width + '_' + w_scale + '_' + tile_index;
+ };
if (!clear_after) { this.content_div.children().remove(); }
this.content_div.append( parent_element );
this.max_height = 0;
// Index of first tile that overlaps visible region
var tile_index = Math.floor( low / resolution / DENSITY );
- // A set of setTimeout() ids used when drawing tiles. Each ID indicates
- // a tile has been requested to be drawn or is being drawn.
- var draw_tile_dict = {};
+ // A list of tiles drawn/retrieved.
+ var drawn_tiles = [];
+ var tile_count = 0
while ( ( tile_index * DENSITY * resolution ) < high ) {
// Check in cache
- var key = width + '_' + w_scale + '_' + tile_index;
+ var key = gen_key(width, w_scale, tile_index);
var cached = this.tile_cache.get(key);
var tile_low = tile_index * DENSITY * this.view.resolution;
var tile_high = tile_low + DENSITY * this.view.resolution;
- // console.log(cached, this.tile_cache);
if ( !force && cached ) {
+ drawn_tiles[drawn_tiles.length] = cached;
this.show_tile(cached, parent_element, tile_low, w_scale);
} else {
- this.delayed_draw(force, key, tile_low, tile_high, tile_index,
- resolution, parent_element, w_scale, draw_tile_dict);
+ this.delayed_draw(force, key, tile_index, resolution, parent_element, w_scale, drawn_tiles);
}
tile_index += 1;
+ tile_count++;
}
//
@@ -1700,7 +1716,7 @@
//
var track = this;
var intervalId = setInterval(function() {
- if (obj_length(draw_tile_dict) === 0) {
+ if (drawn_tiles.length === tile_count) {
// All tiles have been drawn.
clearInterval(intervalId);
@@ -1725,6 +1741,29 @@
}
//
+ // If mode is Histogram and tiles do not share max, redraw tiles as necessary using new max.
+ //
+ if (track.mode == "Histogram") {
+ // Get global max.
+ var global_max = -1;
+ for (var i = 0; i < drawn_tiles.length; i++) {
+ var cur_max = drawn_tiles[i].max_val;
+ if (cur_max > global_max) {
+ global_max = cur_max;
+ }
+ }
+
+ for (var i = 0; i < drawn_tiles.length; i++) {
+ if (drawn_tiles[i].max_val !== global_max) {
+ var tile = drawn_tiles[i];
+ tile.canvas.remove();
+ track.delayed_draw(true, gen_key(width, w_scale, tile.index), tile.index,
+ tile.resolution, parent_element, w_scale, [], { max: global_max });
+ }
+ }
+ }
+
+ //
// Update filter attributes, UI.
//
@@ -1755,6 +1794,19 @@
track.make_name_popup_menu();
}
}
+
+ // Store initial canvas in case we need to use it for overview
+ /* This is completely broken, just saves the first tile it sees
+ regardless of if it should be the overview
+ if (!track.initial_canvas && !window.G_vmlCanvasManager) {
+ track.initial_canvas = $(tile_element).clone();
+ var src_ctx = tile_element.get(0).getContext("2d");
+ var tgt_ctx = track.initial_canvas.get(0).getContext("2d");
+ var data = src_ctx.getImageData(0, 0, src_ctx.canvas.width, src_ctx.canvas.height);
+ tgt_ctx.putImageData(data, 0, 0);
+ track.set_overview();
+ }
+ */
}
}, 50);
@@ -1765,44 +1817,28 @@
this.child_tracks[i].draw(force, clear_after);
}
},
- delayed_draw: function(force, key, tile_low, tile_high, tile_index, resolution, parent_element, w_scale, draw_tile_dict) {
- var track = this;
- // Put a 50ms delay on drawing so that if the user scrolls fast, we don't load extra data
+ delayed_draw: function(force, key, tile_index, resolution, parent_element, w_scale, drawn_tiles, more_tile_data) {
+ var track = this,
+ tile_low = tile_index * DENSITY * resolution,
+ tile_high = tile_low + DENSITY * resolution;
+
+ // Helper method.
var draw_and_show_tile = function(id, result, resolution, tile_index, parent_element, w_scale, seq_data) {
// DEBUG: this is still called too many times when moving slowly,
// console.log( "draw_and_show_tile", resolution, tile_index, w_scale );
- returned_tile = track.draw_tile(result, resolution, tile_index, parent_element, w_scale, seq_data)
-
- // Wrap element in div for background
- var wrapper_element = $("<div class='track-tile'>").prepend(returned_tile);
- tile_element = wrapper_element;
-
- track.tile_cache.set(key, tile_element);
- track.show_tile(tile_element, parent_element, tile_low, w_scale);
-
- // TODO: this should go in a post-draw function.
- // Store initial canvas in case we need to use it for overview
- /* This is completely broken, just saves the first tile it sees
- regardless of if it should be the overview
- if (!track.initial_canvas && !window.G_vmlCanvasManager) {
- track.initial_canvas = $(tile_element).clone();
- var src_ctx = tile_element.get(0).getContext("2d");
- var tgt_ctx = track.initial_canvas.get(0).getContext("2d");
- var data = src_ctx.getImageData(0, 0, src_ctx.canvas.width, src_ctx.canvas.height);
- tgt_ctx.putImageData(data, 0, 0);
- track.set_overview();
- }
- */
-
- delete draw_tile_dict[id];
+ var tile = track.draw_tile(result, resolution, tile_index, parent_element, w_scale, seq_data);
+ track.tile_cache.set(key, tile);
+ track.show_tile(tile, parent_element, tile_low, w_scale);
+ drawn_tiles[drawn_tiles.length] = tile;
};
+ // Put a 50ms delay on drawing so that if the user scrolls fast, we don't load extra data
var id = setTimeout(function() {
if (tile_low <= track.view.high && tile_high >= track.view.low) {
// Show/draw tile: check cache for tile; if tile not in cache, draw it.
- var tile_element = (force ? undefined : track.tile_cache.get(key));
- if (tile_element) {
- track.show_tile(tile_element, parent_element, tile_low, w_scale);
- delete draw_tile_dict[id];
+ var tile = (force ? undefined : track.tile_cache.get(key));
+ if (tile) {
+ track.show_tile(tile, parent_element, tile_low, w_scale);
+ drawn_tiles[drawn_tiles.length] = tile;
}
else {
//
@@ -1810,6 +1846,7 @@
//
$.when(track.data_cache.get_data(view.chrom, tile_low, tile_high, track.mode,
resolution, track.data_url_extra_params)).then(function(tile_data) {
+ extend(tile_data, more_tile_data);
// If sequence data needed, get that and draw. Otherwise draw.
if (view.reference_track && w_scale > view.canvas_manager.char_width_px) {
$.when(view.reference_track.data_cache.get_data(view.chrom, tile_low, tile_high,
@@ -1825,12 +1862,11 @@
}
}
}, 50);
- draw_tile_dict[id] = true;
},
/**
* Show track tile and perform associated actions.
*/
- show_tile: function(tile_element, parent_element, tile_low, w_scale) {
+ show_tile: function(tile, parent_element, tile_low, w_scale) {
// Readability.
var track = this;
@@ -1844,6 +1880,7 @@
if (this.left_offset) {
left -= this.left_offset;
}
+ var tile_element = tile.canvas;
tile_element.css({ position: 'absolute', top: 0, left: left, height: '' });
// Setup and show tile element.
@@ -1966,7 +2003,7 @@
var c_start = Math.round(c * w_scale);
ctx.fillText(seq[c], c_start + track.left_offset, 10);
}
- return canvas;
+ return new Tile(tile_index, resolution, canvas);
}
this.content_div.css("height", "0px");
}
@@ -2106,7 +2143,7 @@
this.prefs, this.mode );
painter.draw( ctx, width, height );
- return canvas;
+ return new Tile(tile_length, resolution, canvas);
}
});
@@ -2196,11 +2233,14 @@
* position. Return value is a dict with keys 'data', 'delta' (bin size) and 'max.' Data
* is a two-item list; first item is bin start, second is bin's count.
*/
- get_summary_tree_data: function(data, low, high, bin_size) {
- var num_bins = Math.floor((high - low)/bin_size),
+ get_summary_tree_data: function(data, low, high, num_bins) {
+ if (num_bins > high - low) {
+ num_bins = high - low;
+ }
+ var bin_size = Math.floor((high - low)/num_bins),
bins = [],
max_count = 0;
-
+
/*
// For debugging:
for (var i = 0; i < data.length; i++)
@@ -2335,8 +2375,7 @@
// Deal with left_offset by translating
ctx.translate( left_offset, SUMMARY_TREE_TOP_PADDING );
painter.draw( ctx, width, required_height );
- // Canvas element is returned
- return canvas;
+ return new SummaryTreeTile(tile_index, resolution, canvas, result.max);
}
// Drawing coverage histogram. This is different from summary tree because data can feature
@@ -2359,13 +2398,15 @@
canvas.height = required_height + SUMMARY_TREE_TOP_PADDING;
// Paint summary tree into canvas.
var binned_data = this.get_summary_tree_data(result.data, tile_low, tile_high, 200);
+ if (result.max) {
+ binned_data.max = result.max;
+ }
var painter = new painters.SummaryTreePainter(binned_data, tile_low, tile_high, this.prefs);
var ctx = canvas.getContext("2d");
// Deal with left_offset by translating
ctx.translate(left_offset, SUMMARY_TREE_TOP_PADDING);
painter.draw(ctx, width, required_height);
- // Canvas element is returned
- return canvas;
+ return new SummaryTreeTile(tile_index, resolution, canvas, binned_data.max);
}
// Start dealing with row-by-row tracks
@@ -2433,7 +2474,7 @@
// If there's no data, return.
if (!result.data) {
- return canvas;
+ return new Tile(tile_index, resolution, canvas);
}
}
@@ -2444,7 +2485,7 @@
ctx.translate( left_offset, ERROR_PADDING );
painter.draw( ctx, width, required_height, slots );
- return canvas;
+ return new FeatureTrackTile(tile_index, resolution, canvas);
}
});
@@ -2558,7 +2599,7 @@
this.include_label = include_label;
this.max_rows = max_rows;
this.measureText = measureText;
-}
+};
/**
* Slot a set of features, `this.slots` will be updated with slots by id, and
@@ -2704,7 +2745,7 @@
// ---- Painters ----
var painters_module = function(require, exports){
-
+
/**
* Draw a dashed line on a canvas using filled rectangles. This function is based on:
* http://vetruvet.blogspot.com/2010/10/drawing-dashed-lines-on-html5-canvas.h…
@@ -2776,7 +2817,7 @@
Painter.call( this, data, view_start, view_end, prefs, mode );
}
-SummaryTreePainter.prototype.default_prefis = { show_counts: false };
+SummaryTreePainter.prototype.default_prefs = { show_counts: false };
SummaryTreePainter.prototype.draw = function( ctx, width, height ) {
@@ -2790,16 +2831,15 @@
// max rectangle is required_height.
base_y = height;
delta_x_px = Math.ceil(delta * w_scale);
-
ctx.save();
for (var i = 0, len = points.length; i < len; i++) {
-
var x = Math.floor( (points[i][0] - view_start) * w_scale );
var y = points[i][1];
if (!y) { continue; }
- var y_px = y / max * height;
+ var y_px = y / max * height
+ if (y !== 0 && y_px < 1) { y_px = 1; }
ctx.fillStyle = "black";
ctx.fillRect( x, base_y - y_px, delta_x_px, y_px );
@@ -2991,7 +3031,7 @@
}
});
-// Contstants specific to feature tracks moved here (HACKING, these should
+// Constants specific to feature tracks moved here (HACKING, these should
// basically all be configuration options)
var DENSE_TRACK_HEIGHT = 10,
NO_DETAIL_TRACK_HEIGHT = 3,
@@ -3034,8 +3074,7 @@
var
feature_uid = feature[0],
feature_start = feature[1],
- // -1 b/c intervals are half-open.
- feature_end = feature[2] - 1,
+ feature_end = feature[2],
feature_name = feature[3],
f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
@@ -3134,8 +3173,7 @@
for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
var block = feature_blocks[k],
block_start = Math.floor( Math.max(0, (block[0] - tile_low) * w_scale) ),
- // -1 b/c intervals are half-open.
- block_end = Math.ceil( Math.min(width, Math.max((block[1] - 1 - tile_low) * w_scale)) );
+ block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low) * w_scale)) );
// Skip drawing if block not on tile.
if (block_start > block_end) { continue; }
@@ -3199,8 +3237,7 @@
var feature = data[i],
feature_uid = feature[0],
feature_start = feature[1],
- // -1 b/c intervals are half-open.
- feature_end = feature[2] - 1,
+ feature_end = feature[2],
feature_name = feature[3],
// All features need a start, end, and vertical center.
f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
http://bitbucket.org/galaxy/galaxy-central/changeset/1c5796258fb5/
changeset: r5379:1c5796258fb5
user: Martijn Vermaat
date: 2011-04-14 01:04:40
summary: Run a workflow on a selection of multiple inputs, one invocation for each.
- Makes input selections in the run workflow form support multiple
selection.
- If multiple inputs are selected, a workflow invocation is executed for
each selected input.
- Only of of the workflow inputs can have a multiple selection.
affected #: 6 files (3.8 KB)
--- a/lib/galaxy/tools/parameters/basic.py Wed Apr 13 16:46:36 2011 -0400
+++ b/lib/galaxy/tools/parameters/basic.py Thu Apr 14 01:04:40 2011 +0200
@@ -1421,6 +1421,14 @@
else:
return "No dataset"
+ def validate( self, value, history=None ):
+ for validator in self.validators:
+ if value and self.multiple and isinstance(value, list):
+ for v in value:
+ validator.validate( v, history )
+ else:
+ validator.validate( value, history )
+
def get_dependencies( self ):
"""
Get the *names* of the other params this param depends on.
--- a/lib/galaxy/web/controllers/workflow.py Wed Apr 13 16:46:36 2011 -0400
+++ b/lib/galaxy/web/controllers/workflow.py Thu Apr 14 01:04:40 2011 +0200
@@ -1262,96 +1262,117 @@
if kwargs:
# If kwargs were provided, the states for each step should have
# been POSTed
- for step in workflow.steps:
- step.upgrade_messages = {}
- # Connections by input name
- step.input_connections_by_name = \
- dict( ( conn.input_name, conn ) for conn in step.input_connections )
- # Extract just the arguments for this step by prefix
- p = "%s|" % step.id
- l = len(p)
- step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
- step_errors = None
- if step.type == 'tool' or step.type is None:
- module = module_factory.from_workflow_step( trans, step )
- # Fix any missing parameters
- step.upgrade_messages = module.check_and_update_state()
- if step.upgrade_messages:
- has_upgrade_messages = True
- # Any connected input needs to have value DummyDataset (these
- # are not persisted so we need to do it every time)
- module.add_dummy_datasets( connections=step.input_connections )
- # Get the tool
- tool = module.tool
- # Get the state
- step.state = state = module.state
- # Get old errors
- old_errors = state.inputs.pop( "__errors__", {} )
- # Update the state
- step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
- update_only=True, old_errors=old_errors )
- else:
- module = step.module = module_factory.from_workflow_step( trans, step )
- state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
- step_errors = module.update_runtime_state( trans, state, step_args )
- if step_errors:
- errors[step.id] = state.inputs["__errors__"] = step_errors
- if 'run_workflow' in kwargs and not errors:
- new_history = None
- if 'new_history' in kwargs:
- if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
- nh_name = kwargs['new_history_name']
+ # Get the kwarg keys for data inputs
+ input_keys = filter(lambda a: a.endswith('|input'), kwargs)
+ # Example: prefixed='2|input'
+ # Check if one of them is a list
+ multiple_input_key = None
+ multiple_inputs = [None]
+ for input_key in input_keys:
+ if isinstance(kwargs[input_key], list):
+ multiple_input_key = input_key
+ multiple_inputs = kwargs[input_key]
+ # List to gather values for the template
+ invocations=[]
+ for input_number, single_input in enumerate(multiple_inputs):
+ # Example: single_input='1', single_input='2', etc...
+ # 'Fix' the kwargs, to have only the input for this iteration
+ if multiple_input_key:
+ kwargs[multiple_input_key] = single_input
+ for step in workflow.steps:
+ step.upgrade_messages = {}
+ # Connections by input name
+ step.input_connections_by_name = \
+ dict( ( conn.input_name, conn ) for conn in step.input_connections )
+ # Extract just the arguments for this step by prefix
+ p = "%s|" % step.id
+ l = len(p)
+ step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
+ step_errors = None
+ if step.type == 'tool' or step.type is None:
+ module = module_factory.from_workflow_step( trans, step )
+ # Fix any missing parameters
+ step.upgrade_messages = module.check_and_update_state()
+ if step.upgrade_messages:
+ has_upgrade_messages = True
+ # Any connected input needs to have value DummyDataset (these
+ # are not persisted so we need to do it every time)
+ module.add_dummy_datasets( connections=step.input_connections )
+ # Get the tool
+ tool = module.tool
+ # Get the state
+ step.state = state = module.state
+ # Get old errors
+ old_errors = state.inputs.pop( "__errors__", {} )
+ # Update the state
+ step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
+ update_only=True, old_errors=old_errors )
else:
- nh_name = "History from %s workflow" % workflow.name
- new_history = trans.app.model.History( user=trans.user, name=nh_name )
- trans.sa_session.add( new_history )
- # Run each step, connecting outputs to inputs
- workflow_invocation = model.WorkflowInvocation()
- workflow_invocation.workflow = workflow
- outputs = odict()
- for i, step in enumerate( workflow.steps ):
- # Execute module
- job = None
- if step.type == 'tool' or step.type is None:
- tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
- input_values = step.state.inputs
- # Connect up
- def callback( input, value, prefixed_name, prefixed_label ):
- if isinstance( input, DataToolParameter ):
- if prefixed_name in step.input_connections_by_name:
- conn = step.input_connections_by_name[ prefixed_name ]
- return outputs[ conn.output_step.id ][ conn.output_name ]
- visit_input_values( tool.inputs, step.state.inputs, callback )
- # Execute it
- job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
- outputs[ step.id ] = out_data
- # Create new PJA associations with the created job, to be run on completion.
- # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
- # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
- replacement_dict = {}
- for k, v in kwargs.iteritems():
- if k.startswith('wf_parm|'):
- replacement_dict[k[8:]] = v
- for pja in step.post_job_actions:
- if pja.action_type in ActionBox.immediate_actions:
- ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
- else:
- job.add_post_job_action(pja)
- else:
- job, out_data = step.module.execute( trans, step.state )
- outputs[ step.id ] = out_data
- # Record invocation
- workflow_invocation_step = model.WorkflowInvocationStep()
- workflow_invocation_step.workflow_invocation = workflow_invocation
- workflow_invocation_step.workflow_step = step
- workflow_invocation_step.job = job
- # All jobs ran sucessfully, so we can save now
- trans.sa_session.add( workflow_invocation )
- trans.sa_session.flush()
- return trans.fill_template( "workflow/run_complete.mako",
- workflow=stored,
- outputs=outputs,
- new_history=new_history )
+ # Fix this for multiple inputs
+ module = step.module = module_factory.from_workflow_step( trans, step )
+ state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
+ step_errors = module.update_runtime_state( trans, state, step_args )
+ if step_errors:
+ errors[step.id] = state.inputs["__errors__"] = step_errors
+ if 'run_workflow' in kwargs and not errors:
+ new_history = None
+ if 'new_history' in kwargs:
+ if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
+ nh_name = kwargs['new_history_name']
+ else:
+ nh_name = "History from %s workflow" % workflow.name
+ if multiple_input_key:
+ nh_name = '%s %d' % (nh_name, input_number + 1)
+ new_history = trans.app.model.History( user=trans.user, name=nh_name )
+ trans.sa_session.add( new_history )
+ # Run each step, connecting outputs to inputs
+ workflow_invocation = model.WorkflowInvocation()
+ workflow_invocation.workflow = workflow
+ outputs = odict()
+ for i, step in enumerate( workflow.steps ):
+ # Execute module
+ job = None
+ if step.type == 'tool' or step.type is None:
+ tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ input_values = step.state.inputs
+ # Connect up
+ def callback( input, value, prefixed_name, prefixed_label ):
+ if isinstance( input, DataToolParameter ):
+ if prefixed_name in step.input_connections_by_name:
+ conn = step.input_connections_by_name[ prefixed_name ]
+ return outputs[ conn.output_step.id ][ conn.output_name ]
+ visit_input_values( tool.inputs, step.state.inputs, callback )
+ # Execute it
+ job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
+ outputs[ step.id ] = out_data
+ # Create new PJA associations with the created job, to be run on completion.
+ # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
+ # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
+ replacement_dict = {}
+ for k, v in kwargs.iteritems():
+ if k.startswith('wf_parm|'):
+ replacement_dict[k[8:]] = v
+ for pja in step.post_job_actions:
+ if pja.action_type in ActionBox.immediate_actions:
+ ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
+ else:
+ job.add_post_job_action(pja)
+ else:
+ job, out_data = step.module.execute( trans, step.state )
+ outputs[ step.id ] = out_data
+ # Record invocation
+ workflow_invocation_step = model.WorkflowInvocationStep()
+ workflow_invocation_step.workflow_invocation = workflow_invocation
+ workflow_invocation_step.workflow_step = step
+ workflow_invocation_step.job = job
+ # All jobs ran sucessfully, so we can save now
+ trans.sa_session.add( workflow_invocation )
+ invocations.append({'outputs': outputs,
+ 'new_history': new_history})
+ trans.sa_session.flush()
+ return trans.fill_template( "workflow/run_complete.mako",
+ workflow=stored,
+ invocations=invocations )
else:
# Prepare each step
missing_tools = []
@@ -1816,4 +1837,4 @@
cleanup( prefix, input.cases[current_case].inputs, group_values )
cleanup( "", inputs, values )
return associations
-
\ No newline at end of file
+
--- a/lib/galaxy/workflow/modules.py Wed Apr 13 16:46:36 2011 -0400
+++ b/lib/galaxy/workflow/modules.py Thu Apr 14 01:04:40 2011 +0200
@@ -131,7 +131,7 @@
def get_runtime_inputs( self, filter_set=['data'] ):
label = self.state.get( "name", "Input Dataset" )
- return dict( input=DataToolParameter( None, Element( "param", name="input", label=label, type="data", format=', '.join(filter_set) ) ) )
+ return dict( input=DataToolParameter( None, Element( "param", name="input", label=label, multiple=True, type="data", format=', '.join(filter_set) ) ) )
def get_runtime_state( self ):
state = DefaultToolState()
state.inputs = dict( input=None )
--- a/static/june_2007_style/blue/base.css Wed Apr 13 16:46:36 2011 -0400
+++ b/static/june_2007_style/blue/base.css Thu Apr 14 01:04:40 2011 +0200
@@ -170,3 +170,6 @@
.editable-text{cursor:pointer;}
.editable-text:hover{cursor:text;border:dotted #999999 1px;}
.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -364px;}
+.icon-button.multiinput{background:url(../images/documents-stack.png) no-repeat;cursor:pointer;float:none;display:inline-block;margin-left:10px;}
+.icon-button.multiinput.disabled{background:url(../images/documents-stack-faded.png) no-repeat;cursor:auto;}
+.worflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
--- a/templates/workflow/run.mako Wed Apr 13 16:46:36 2011 -0400
+++ b/templates/workflow/run.mako Thu Apr 14 01:04:40 2011 +0200
@@ -2,7 +2,7 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "jquery.autocomplete" )}
+ ${h.js( "jquery.autocomplete", "jquery.tipsy" )}
<script type="text/javascript">
$( function() {
function show_tool_body(title){
@@ -20,6 +20,21 @@
show_tool_body(title);
}
}
+ function toggle_multiinput(select) {
+ if (select.attr('multiple')) {
+ $('.multiinput').removeClass('disabled');
+ if (select.val()) {
+ select.val(select.val()[0]);
+ } else {
+ select.val($('option:last', select).val());
+ }
+ select.removeAttr('multiple');
+ } else {
+ $('.multiinput').addClass('disabled');
+ $('.multiinput', select.parent().prev()).removeClass('disabled');
+ select.attr('multiple', 'multiple');
+ }
+ }
$( "select[refresh_on_change='true']").change( function() {
$( "#tool_form" ).submit();
});
@@ -41,6 +56,19 @@
$("#new_history_cbx").click(function(){
$("#new_history_input").toggle(this.checked);
});
+ $('select[name*="|input"]').removeAttr('multiple').each(function(i, s) {
+ var select = $(s);
+ select.parent().prev().append(
+ $('<span class="icon-button multiinput"></span>').click(function() {
+ if ($(this).hasClass('disabled')) return;
+ toggle_multiinput(select);
+ select.focus();
+ }).attr('original-title',
+ 'Enable/disable selection of multiple input ' +
+ 'files. Each selected file will have an ' +
+ 'instance of the workflow.').tipsy({gravity:'s'})
+ );
+ });
});
</script></%def>
--- a/templates/workflow/run_complete.mako Wed Apr 13 16:46:36 2011 -0400
+++ b/templates/workflow/run_complete.mako Thu Apr 14 01:04:40 2011 +0200
@@ -2,21 +2,25 @@
<div class="donemessagelarge">
Successfully ran workflow "${workflow.name}". The following datasets have been added to the queue:
- %if new_history:
- These datasets will appear in a new history:
- <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(new_history.id), use_panels=False, show_deleted=False )}">
- '${h.to_unicode(new_history.name)}'.
- </a>
- %endif
- <div style="padding-left: 10px;">
- %for step_outputs in outputs.itervalues():
- %for data in step_outputs.itervalues():
- %if not new_history or data.history == new_history:
- <p><strong>${data.hid}</strong>: ${data.name}</p>
- %endif
- %endfor
- %endfor
- </div>
+ %for invocation in invocations:
+ <div class="workflow-invocation-complete">
+ %if invocation['new_history']:
+ <p>These datasets will appear in a new history:
+ <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(invocation['new_history'].id), use_panels=False, show_deleted=False )}">
+ '${h.to_unicode(invocation['new_history'].name)}'.
+ </a></p>
+ %endif
+ <div style="padding-left: 10px;">
+ %for step_outputs in invocation['outputs'].itervalues():
+ %for data in step_outputs.itervalues():
+ %if not invocation['new_history'] or data.history == invocation['new_history']:
+ <p><strong>${data.hid}</strong>: ${data.name}</p>
+ %endif
+ %endfor
+ %endfor
+ </div>
+ </div>
+ %endfor
</div><script type="text/javascript">
http://bitbucket.org/galaxy/galaxy-central/changeset/383258d637cb/
changeset: r5380:383258d637cb
user: dannon
date: 2011-04-14 01:07:22
summary: Merge.
affected #: 6 files (3.8 KB)
--- a/lib/galaxy/tools/parameters/basic.py Wed Apr 13 19:05:45 2011 -0400
+++ b/lib/galaxy/tools/parameters/basic.py Wed Apr 13 19:07:22 2011 -0400
@@ -1421,6 +1421,14 @@
else:
return "No dataset"
+ def validate( self, value, history=None ):
+ for validator in self.validators:
+ if value and self.multiple and isinstance(value, list):
+ for v in value:
+ validator.validate( v, history )
+ else:
+ validator.validate( value, history )
+
def get_dependencies( self ):
"""
Get the *names* of the other params this param depends on.
--- a/lib/galaxy/web/controllers/workflow.py Wed Apr 13 19:05:45 2011 -0400
+++ b/lib/galaxy/web/controllers/workflow.py Wed Apr 13 19:07:22 2011 -0400
@@ -1262,96 +1262,117 @@
if kwargs:
# If kwargs were provided, the states for each step should have
# been POSTed
- for step in workflow.steps:
- step.upgrade_messages = {}
- # Connections by input name
- step.input_connections_by_name = \
- dict( ( conn.input_name, conn ) for conn in step.input_connections )
- # Extract just the arguments for this step by prefix
- p = "%s|" % step.id
- l = len(p)
- step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
- step_errors = None
- if step.type == 'tool' or step.type is None:
- module = module_factory.from_workflow_step( trans, step )
- # Fix any missing parameters
- step.upgrade_messages = module.check_and_update_state()
- if step.upgrade_messages:
- has_upgrade_messages = True
- # Any connected input needs to have value DummyDataset (these
- # are not persisted so we need to do it every time)
- module.add_dummy_datasets( connections=step.input_connections )
- # Get the tool
- tool = module.tool
- # Get the state
- step.state = state = module.state
- # Get old errors
- old_errors = state.inputs.pop( "__errors__", {} )
- # Update the state
- step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
- update_only=True, old_errors=old_errors )
- else:
- module = step.module = module_factory.from_workflow_step( trans, step )
- state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
- step_errors = module.update_runtime_state( trans, state, step_args )
- if step_errors:
- errors[step.id] = state.inputs["__errors__"] = step_errors
- if 'run_workflow' in kwargs and not errors:
- new_history = None
- if 'new_history' in kwargs:
- if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
- nh_name = kwargs['new_history_name']
+ # Get the kwarg keys for data inputs
+ input_keys = filter(lambda a: a.endswith('|input'), kwargs)
+ # Example: prefixed='2|input'
+ # Check if one of them is a list
+ multiple_input_key = None
+ multiple_inputs = [None]
+ for input_key in input_keys:
+ if isinstance(kwargs[input_key], list):
+ multiple_input_key = input_key
+ multiple_inputs = kwargs[input_key]
+ # List to gather values for the template
+ invocations=[]
+ for input_number, single_input in enumerate(multiple_inputs):
+ # Example: single_input='1', single_input='2', etc...
+ # 'Fix' the kwargs, to have only the input for this iteration
+ if multiple_input_key:
+ kwargs[multiple_input_key] = single_input
+ for step in workflow.steps:
+ step.upgrade_messages = {}
+ # Connections by input name
+ step.input_connections_by_name = \
+ dict( ( conn.input_name, conn ) for conn in step.input_connections )
+ # Extract just the arguments for this step by prefix
+ p = "%s|" % step.id
+ l = len(p)
+ step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
+ step_errors = None
+ if step.type == 'tool' or step.type is None:
+ module = module_factory.from_workflow_step( trans, step )
+ # Fix any missing parameters
+ step.upgrade_messages = module.check_and_update_state()
+ if step.upgrade_messages:
+ has_upgrade_messages = True
+ # Any connected input needs to have value DummyDataset (these
+ # are not persisted so we need to do it every time)
+ module.add_dummy_datasets( connections=step.input_connections )
+ # Get the tool
+ tool = module.tool
+ # Get the state
+ step.state = state = module.state
+ # Get old errors
+ old_errors = state.inputs.pop( "__errors__", {} )
+ # Update the state
+ step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
+ update_only=True, old_errors=old_errors )
else:
- nh_name = "History from %s workflow" % workflow.name
- new_history = trans.app.model.History( user=trans.user, name=nh_name )
- trans.sa_session.add( new_history )
- # Run each step, connecting outputs to inputs
- workflow_invocation = model.WorkflowInvocation()
- workflow_invocation.workflow = workflow
- outputs = odict()
- for i, step in enumerate( workflow.steps ):
- # Execute module
- job = None
- if step.type == 'tool' or step.type is None:
- tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
- input_values = step.state.inputs
- # Connect up
- def callback( input, value, prefixed_name, prefixed_label ):
- if isinstance( input, DataToolParameter ):
- if prefixed_name in step.input_connections_by_name:
- conn = step.input_connections_by_name[ prefixed_name ]
- return outputs[ conn.output_step.id ][ conn.output_name ]
- visit_input_values( tool.inputs, step.state.inputs, callback )
- # Execute it
- job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
- outputs[ step.id ] = out_data
- # Create new PJA associations with the created job, to be run on completion.
- # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
- # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
- replacement_dict = {}
- for k, v in kwargs.iteritems():
- if k.startswith('wf_parm|'):
- replacement_dict[k[8:]] = v
- for pja in step.post_job_actions:
- if pja.action_type in ActionBox.immediate_actions:
- ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
- else:
- job.add_post_job_action(pja)
- else:
- job, out_data = step.module.execute( trans, step.state )
- outputs[ step.id ] = out_data
- # Record invocation
- workflow_invocation_step = model.WorkflowInvocationStep()
- workflow_invocation_step.workflow_invocation = workflow_invocation
- workflow_invocation_step.workflow_step = step
- workflow_invocation_step.job = job
- # All jobs ran sucessfully, so we can save now
- trans.sa_session.add( workflow_invocation )
- trans.sa_session.flush()
- return trans.fill_template( "workflow/run_complete.mako",
- workflow=stored,
- outputs=outputs,
- new_history=new_history )
+ # Fix this for multiple inputs
+ module = step.module = module_factory.from_workflow_step( trans, step )
+ state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
+ step_errors = module.update_runtime_state( trans, state, step_args )
+ if step_errors:
+ errors[step.id] = state.inputs["__errors__"] = step_errors
+ if 'run_workflow' in kwargs and not errors:
+ new_history = None
+ if 'new_history' in kwargs:
+ if 'new_history_name' in kwargs and kwargs['new_history_name'] != '':
+ nh_name = kwargs['new_history_name']
+ else:
+ nh_name = "History from %s workflow" % workflow.name
+ if multiple_input_key:
+ nh_name = '%s %d' % (nh_name, input_number + 1)
+ new_history = trans.app.model.History( user=trans.user, name=nh_name )
+ trans.sa_session.add( new_history )
+ # Run each step, connecting outputs to inputs
+ workflow_invocation = model.WorkflowInvocation()
+ workflow_invocation.workflow = workflow
+ outputs = odict()
+ for i, step in enumerate( workflow.steps ):
+ # Execute module
+ job = None
+ if step.type == 'tool' or step.type is None:
+ tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ input_values = step.state.inputs
+ # Connect up
+ def callback( input, value, prefixed_name, prefixed_label ):
+ if isinstance( input, DataToolParameter ):
+ if prefixed_name in step.input_connections_by_name:
+ conn = step.input_connections_by_name[ prefixed_name ]
+ return outputs[ conn.output_step.id ][ conn.output_name ]
+ visit_input_values( tool.inputs, step.state.inputs, callback )
+ # Execute it
+ job, out_data = tool.execute( trans, step.state.inputs, history=new_history)
+ outputs[ step.id ] = out_data
+ # Create new PJA associations with the created job, to be run on completion.
+ # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
+ # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
+ replacement_dict = {}
+ for k, v in kwargs.iteritems():
+ if k.startswith('wf_parm|'):
+ replacement_dict[k[8:]] = v
+ for pja in step.post_job_actions:
+ if pja.action_type in ActionBox.immediate_actions:
+ ActionBox.execute(trans.app, trans.sa_session, pja, job, replacement_dict)
+ else:
+ job.add_post_job_action(pja)
+ else:
+ job, out_data = step.module.execute( trans, step.state )
+ outputs[ step.id ] = out_data
+ # Record invocation
+ workflow_invocation_step = model.WorkflowInvocationStep()
+ workflow_invocation_step.workflow_invocation = workflow_invocation
+ workflow_invocation_step.workflow_step = step
+ workflow_invocation_step.job = job
+ # All jobs ran sucessfully, so we can save now
+ trans.sa_session.add( workflow_invocation )
+ invocations.append({'outputs': outputs,
+ 'new_history': new_history})
+ trans.sa_session.flush()
+ return trans.fill_template( "workflow/run_complete.mako",
+ workflow=stored,
+ invocations=invocations )
else:
# Prepare each step
missing_tools = []
@@ -1816,4 +1837,4 @@
cleanup( prefix, input.cases[current_case].inputs, group_values )
cleanup( "", inputs, values )
return associations
-
\ No newline at end of file
+
--- a/lib/galaxy/workflow/modules.py Wed Apr 13 19:05:45 2011 -0400
+++ b/lib/galaxy/workflow/modules.py Wed Apr 13 19:07:22 2011 -0400
@@ -131,7 +131,7 @@
def get_runtime_inputs( self, filter_set=['data'] ):
label = self.state.get( "name", "Input Dataset" )
- return dict( input=DataToolParameter( None, Element( "param", name="input", label=label, type="data", format=', '.join(filter_set) ) ) )
+ return dict( input=DataToolParameter( None, Element( "param", name="input", label=label, multiple=True, type="data", format=', '.join(filter_set) ) ) )
def get_runtime_state( self ):
state = DefaultToolState()
state.inputs = dict( input=None )
--- a/static/june_2007_style/blue/base.css Wed Apr 13 19:05:45 2011 -0400
+++ b/static/june_2007_style/blue/base.css Wed Apr 13 19:07:22 2011 -0400
@@ -170,3 +170,6 @@
.editable-text{cursor:pointer;}
.editable-text:hover{cursor:text;border:dotted #999999 1px;}
.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -364px;}
+.icon-button.multiinput{background:url(../images/documents-stack.png) no-repeat;cursor:pointer;float:none;display:inline-block;margin-left:10px;}
+.icon-button.multiinput.disabled{background:url(../images/documents-stack-faded.png) no-repeat;cursor:auto;}
+.worflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;}
--- a/templates/workflow/run.mako Wed Apr 13 19:05:45 2011 -0400
+++ b/templates/workflow/run.mako Wed Apr 13 19:07:22 2011 -0400
@@ -2,7 +2,7 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "jquery.autocomplete" )}
+ ${h.js( "jquery.autocomplete", "jquery.tipsy" )}
<script type="text/javascript">
$( function() {
function show_tool_body(title){
@@ -20,6 +20,21 @@
show_tool_body(title);
}
}
+ function toggle_multiinput(select) {
+ if (select.attr('multiple')) {
+ $('.multiinput').removeClass('disabled');
+ if (select.val()) {
+ select.val(select.val()[0]);
+ } else {
+ select.val($('option:last', select).val());
+ }
+ select.removeAttr('multiple');
+ } else {
+ $('.multiinput').addClass('disabled');
+ $('.multiinput', select.parent().prev()).removeClass('disabled');
+ select.attr('multiple', 'multiple');
+ }
+ }
$( "select[refresh_on_change='true']").change( function() {
$( "#tool_form" ).submit();
});
@@ -41,6 +56,19 @@
$("#new_history_cbx").click(function(){
$("#new_history_input").toggle(this.checked);
});
+ $('select[name*="|input"]').removeAttr('multiple').each(function(i, s) {
+ var select = $(s);
+ select.parent().prev().append(
+ $('<span class="icon-button multiinput"></span>').click(function() {
+ if ($(this).hasClass('disabled')) return;
+ toggle_multiinput(select);
+ select.focus();
+ }).attr('original-title',
+ 'Enable/disable selection of multiple input ' +
+ 'files. Each selected file will have an ' +
+ 'instance of the workflow.').tipsy({gravity:'s'})
+ );
+ });
});
</script></%def>
--- a/templates/workflow/run_complete.mako Wed Apr 13 19:05:45 2011 -0400
+++ b/templates/workflow/run_complete.mako Wed Apr 13 19:07:22 2011 -0400
@@ -2,21 +2,25 @@
<div class="donemessagelarge">
Successfully ran workflow "${workflow.name}". The following datasets have been added to the queue:
- %if new_history:
- These datasets will appear in a new history:
- <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(new_history.id), use_panels=False, show_deleted=False )}">
- '${h.to_unicode(new_history.name)}'.
- </a>
- %endif
- <div style="padding-left: 10px;">
- %for step_outputs in outputs.itervalues():
- %for data in step_outputs.itervalues():
- %if not new_history or data.history == new_history:
- <p><strong>${data.hid}</strong>: ${data.name}</p>
- %endif
- %endfor
- %endfor
- </div>
+ %for invocation in invocations:
+ <div class="workflow-invocation-complete">
+ %if invocation['new_history']:
+ <p>These datasets will appear in a new history:
+ <a target='galaxy_history' href="${h.url_for( controller='history', action='list', operation="Switch", id=trans.security.encode_id(invocation['new_history'].id), use_panels=False, show_deleted=False )}">
+ '${h.to_unicode(invocation['new_history'].name)}'.
+ </a></p>
+ %endif
+ <div style="padding-left: 10px;">
+ %for step_outputs in invocation['outputs'].itervalues():
+ %for data in step_outputs.itervalues():
+ %if not invocation['new_history'] or data.history == invocation['new_history']:
+ <p><strong>${data.hid}</strong>: ${data.name}</p>
+ %endif
+ %endfor
+ %endfor
+ </div>
+ </div>
+ %endfor
</div><script type="text/javascript">
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/acee660871cd/
changeset: r5375:acee660871cd
user: jgoecks
date: 2011-04-14 00:09:07
summary: Add Tile objects to trackster to support better tracking of Tile data properties; use SummaryTreeTile objects to ensure that feature track coverage histograms are drawn with the same max. Some refactoring of TiledTrack.draw() done as well for simplicity. Finally, fixed typos and GFF display bugs.
affected #: 1 file (1.8 KB)
--- a/static/scripts/trackster.js Wed Apr 13 16:05:34 2011 -0400
+++ b/static/scripts/trackster.js Wed Apr 13 18:09:07 2011 -0400
@@ -741,7 +741,7 @@
this.high = Math.ceil(high);
// 10^log10(range / DENSITY) Close approximation for browser window, assuming DENSITY = window width
- this.resolution = Math.pow( 10, Math.ceil( Math.log( (this.high - this.low) / 200 ) / Math.LN10 ) );
+ this.resolution = Math.pow( 10, Math.ceil( Math.log( (this.high - this.low) / DENSITY ) / Math.LN10 ) );
this.zoom_res = Math.pow( FEATURE_LEVELS, Math.max(0,Math.ceil( Math.log( this.resolution, FEATURE_LEVELS ) / Math.log(FEATURE_LEVELS) )));
// Overview
@@ -1016,14 +1016,16 @@
return false;
},
/**
- * Returns true iff element is in [low, high]; range is inclusive.
+ * Returns true if (a) element's value is in [low, high] (range is inclusive)
+ * or (b) if value is non-numeric and hence unfilterable.
*/
keep: function(element) {
if ( !this.applies_to( element ) ) {
// No element to filter on.
return true;
}
- return (element[this.index] >= this.low && element[this.index] <= this.high);
+ var val = parseInt(element[this.index]);
+ return (isNaN(val) || (val >= this.low && val <= this.high));
},
/**
* Update filter's min and max values based on element's values.
@@ -1306,11 +1308,22 @@
});
/**
- * Tiles for TiledTracks.
+ * Tiles drawn by tracks.
*/
-var Tile = function(track, canvas) {
- this.track = track;
- this.canvas = canvas;
+var Tile = function(index, resolution, canvas) {
+ // Wrap element in div for background
+ this.index = index;
+ this.resolution = resolution;
+ this.canvas = $("<div class='track-tile'/>").append(canvas);
+};
+
+var SummaryTreeTile = function(index, resolution, canvas, max_val) {
+ Tile.call(this, index, resolution, canvas);
+ this.max_val = max_val;
+};
+
+var FeatureTrackTile = function(index, resolution, canvas) {
+ Tile.call(this, index, resolution, canvas);
};
/**
@@ -1669,30 +1682,33 @@
// w_scale units are pixels per base.
w_scale = width / range,
resolution = this.view.resolution,
- parent_element = $("<div style='position: relative;'></div>");
+ parent_element = $("<div style='position: relative;'></div>"),
+ gen_key = function(width, w_scale, tile_index) {
+ return width + '_' + w_scale + '_' + tile_index;
+ };
if (!clear_after) { this.content_div.children().remove(); }
this.content_div.append( parent_element );
this.max_height = 0;
// Index of first tile that overlaps visible region
var tile_index = Math.floor( low / resolution / DENSITY );
- // A set of setTimeout() ids used when drawing tiles. Each ID indicates
- // a tile has been requested to be drawn or is being drawn.
- var draw_tile_dict = {};
+ // A list of tiles drawn/retrieved.
+ var drawn_tiles = [];
+ var tile_count = 0
while ( ( tile_index * DENSITY * resolution ) < high ) {
// Check in cache
- var key = width + '_' + w_scale + '_' + tile_index;
+ var key = gen_key(width, w_scale, tile_index);
var cached = this.tile_cache.get(key);
var tile_low = tile_index * DENSITY * this.view.resolution;
var tile_high = tile_low + DENSITY * this.view.resolution;
- // console.log(cached, this.tile_cache);
if ( !force && cached ) {
+ drawn_tiles[drawn_tiles.length] = cached;
this.show_tile(cached, parent_element, tile_low, w_scale);
} else {
- this.delayed_draw(force, key, tile_low, tile_high, tile_index,
- resolution, parent_element, w_scale, draw_tile_dict);
+ this.delayed_draw(force, key, tile_index, resolution, parent_element, w_scale, drawn_tiles);
}
tile_index += 1;
+ tile_count++;
}
//
@@ -1700,7 +1716,7 @@
//
var track = this;
var intervalId = setInterval(function() {
- if (obj_length(draw_tile_dict) === 0) {
+ if (drawn_tiles.length === tile_count) {
// All tiles have been drawn.
clearInterval(intervalId);
@@ -1725,6 +1741,29 @@
}
//
+ // If mode is Histogram and tiles do not share max, redraw tiles as necessary using new max.
+ //
+ if (track.mode == "Histogram") {
+ // Get global max.
+ var global_max = -1;
+ for (var i = 0; i < drawn_tiles.length; i++) {
+ var cur_max = drawn_tiles[i].max_val;
+ if (cur_max > global_max) {
+ global_max = cur_max;
+ }
+ }
+
+ for (var i = 0; i < drawn_tiles.length; i++) {
+ if (drawn_tiles[i].max_val !== global_max) {
+ var tile = drawn_tiles[i];
+ tile.canvas.remove();
+ track.delayed_draw(true, gen_key(width, w_scale, tile.index), tile.index,
+ tile.resolution, parent_element, w_scale, [], { max: global_max });
+ }
+ }
+ }
+
+ //
// Update filter attributes, UI.
//
@@ -1755,6 +1794,19 @@
track.make_name_popup_menu();
}
}
+
+ // Store initial canvas in case we need to use it for overview
+ /* This is completely broken, just saves the first tile it sees
+ regardless of if it should be the overview
+ if (!track.initial_canvas && !window.G_vmlCanvasManager) {
+ track.initial_canvas = $(tile_element).clone();
+ var src_ctx = tile_element.get(0).getContext("2d");
+ var tgt_ctx = track.initial_canvas.get(0).getContext("2d");
+ var data = src_ctx.getImageData(0, 0, src_ctx.canvas.width, src_ctx.canvas.height);
+ tgt_ctx.putImageData(data, 0, 0);
+ track.set_overview();
+ }
+ */
}
}, 50);
@@ -1765,44 +1817,28 @@
this.child_tracks[i].draw(force, clear_after);
}
},
- delayed_draw: function(force, key, tile_low, tile_high, tile_index, resolution, parent_element, w_scale, draw_tile_dict) {
- var track = this;
- // Put a 50ms delay on drawing so that if the user scrolls fast, we don't load extra data
+ delayed_draw: function(force, key, tile_index, resolution, parent_element, w_scale, drawn_tiles, more_tile_data) {
+ var track = this,
+ tile_low = tile_index * DENSITY * resolution,
+ tile_high = tile_low + DENSITY * resolution;
+
+ // Helper method.
var draw_and_show_tile = function(id, result, resolution, tile_index, parent_element, w_scale, seq_data) {
// DEBUG: this is still called too many times when moving slowly,
// console.log( "draw_and_show_tile", resolution, tile_index, w_scale );
- returned_tile = track.draw_tile(result, resolution, tile_index, parent_element, w_scale, seq_data)
-
- // Wrap element in div for background
- var wrapper_element = $("<div class='track-tile'>").prepend(returned_tile);
- tile_element = wrapper_element;
-
- track.tile_cache.set(key, tile_element);
- track.show_tile(tile_element, parent_element, tile_low, w_scale);
-
- // TODO: this should go in a post-draw function.
- // Store initial canvas in case we need to use it for overview
- /* This is completely broken, just saves the first tile it sees
- regardless of if it should be the overview
- if (!track.initial_canvas && !window.G_vmlCanvasManager) {
- track.initial_canvas = $(tile_element).clone();
- var src_ctx = tile_element.get(0).getContext("2d");
- var tgt_ctx = track.initial_canvas.get(0).getContext("2d");
- var data = src_ctx.getImageData(0, 0, src_ctx.canvas.width, src_ctx.canvas.height);
- tgt_ctx.putImageData(data, 0, 0);
- track.set_overview();
- }
- */
-
- delete draw_tile_dict[id];
+ var tile = track.draw_tile(result, resolution, tile_index, parent_element, w_scale, seq_data);
+ track.tile_cache.set(key, tile);
+ track.show_tile(tile, parent_element, tile_low, w_scale);
+ drawn_tiles[drawn_tiles.length] = tile;
};
+ // Put a 50ms delay on drawing so that if the user scrolls fast, we don't load extra data
var id = setTimeout(function() {
if (tile_low <= track.view.high && tile_high >= track.view.low) {
// Show/draw tile: check cache for tile; if tile not in cache, draw it.
- var tile_element = (force ? undefined : track.tile_cache.get(key));
- if (tile_element) {
- track.show_tile(tile_element, parent_element, tile_low, w_scale);
- delete draw_tile_dict[id];
+ var tile = (force ? undefined : track.tile_cache.get(key));
+ if (tile) {
+ track.show_tile(tile, parent_element, tile_low, w_scale);
+ drawn_tiles[drawn_tiles.length] = tile;
}
else {
//
@@ -1810,6 +1846,7 @@
//
$.when(track.data_cache.get_data(view.chrom, tile_low, tile_high, track.mode,
resolution, track.data_url_extra_params)).then(function(tile_data) {
+ extend(tile_data, more_tile_data);
// If sequence data needed, get that and draw. Otherwise draw.
if (view.reference_track && w_scale > view.canvas_manager.char_width_px) {
$.when(view.reference_track.data_cache.get_data(view.chrom, tile_low, tile_high,
@@ -1825,12 +1862,11 @@
}
}
}, 50);
- draw_tile_dict[id] = true;
},
/**
* Show track tile and perform associated actions.
*/
- show_tile: function(tile_element, parent_element, tile_low, w_scale) {
+ show_tile: function(tile, parent_element, tile_low, w_scale) {
// Readability.
var track = this;
@@ -1844,6 +1880,7 @@
if (this.left_offset) {
left -= this.left_offset;
}
+ var tile_element = tile.canvas;
tile_element.css({ position: 'absolute', top: 0, left: left, height: '' });
// Setup and show tile element.
@@ -1966,7 +2003,7 @@
var c_start = Math.round(c * w_scale);
ctx.fillText(seq[c], c_start + track.left_offset, 10);
}
- return canvas;
+ return new Tile(tile_index, resolution, canvas);
}
this.content_div.css("height", "0px");
}
@@ -2106,7 +2143,7 @@
this.prefs, this.mode );
painter.draw( ctx, width, height );
- return canvas;
+ return new Tile(tile_length, resolution, canvas);
}
});
@@ -2196,11 +2233,14 @@
* position. Return value is a dict with keys 'data', 'delta' (bin size) and 'max.' Data
* is a two-item list; first item is bin start, second is bin's count.
*/
- get_summary_tree_data: function(data, low, high, bin_size) {
- var num_bins = Math.floor((high - low)/bin_size),
+ get_summary_tree_data: function(data, low, high, num_bins) {
+ if (num_bins > high - low) {
+ num_bins = high - low;
+ }
+ var bin_size = Math.floor((high - low)/num_bins),
bins = [],
max_count = 0;
-
+
/*
// For debugging:
for (var i = 0; i < data.length; i++)
@@ -2335,8 +2375,7 @@
// Deal with left_offset by translating
ctx.translate( left_offset, SUMMARY_TREE_TOP_PADDING );
painter.draw( ctx, width, required_height );
- // Canvas element is returned
- return canvas;
+ return new SummaryTreeTile(tile_index, resolution, canvas, result.max);
}
// Drawing coverage histogram. This is different from summary tree because data can feature
@@ -2359,13 +2398,15 @@
canvas.height = required_height + SUMMARY_TREE_TOP_PADDING;
// Paint summary tree into canvas.
var binned_data = this.get_summary_tree_data(result.data, tile_low, tile_high, 200);
+ if (result.max) {
+ binned_data.max = result.max;
+ }
var painter = new painters.SummaryTreePainter(binned_data, tile_low, tile_high, this.prefs);
var ctx = canvas.getContext("2d");
// Deal with left_offset by translating
ctx.translate(left_offset, SUMMARY_TREE_TOP_PADDING);
painter.draw(ctx, width, required_height);
- // Canvas element is returned
- return canvas;
+ return new SummaryTreeTile(tile_index, resolution, canvas, binned_data.max);
}
// Start dealing with row-by-row tracks
@@ -2433,7 +2474,7 @@
// If there's no data, return.
if (!result.data) {
- return canvas;
+ return new Tile(tile_index, resolution, canvas);
}
}
@@ -2444,7 +2485,7 @@
ctx.translate( left_offset, ERROR_PADDING );
painter.draw( ctx, width, required_height, slots );
- return canvas;
+ return new FeatureTrackTile(tile_index, resolution, canvas);
}
});
@@ -2558,7 +2599,7 @@
this.include_label = include_label;
this.max_rows = max_rows;
this.measureText = measureText;
-}
+};
/**
* Slot a set of features, `this.slots` will be updated with slots by id, and
@@ -2704,7 +2745,7 @@
// ---- Painters ----
var painters_module = function(require, exports){
-
+
/**
* Draw a dashed line on a canvas using filled rectangles. This function is based on:
* http://vetruvet.blogspot.com/2010/10/drawing-dashed-lines-on-html5-canvas.h…
@@ -2776,7 +2817,7 @@
Painter.call( this, data, view_start, view_end, prefs, mode );
}
-SummaryTreePainter.prototype.default_prefis = { show_counts: false };
+SummaryTreePainter.prototype.default_prefs = { show_counts: false };
SummaryTreePainter.prototype.draw = function( ctx, width, height ) {
@@ -2790,16 +2831,15 @@
// max rectangle is required_height.
base_y = height;
delta_x_px = Math.ceil(delta * w_scale);
-
ctx.save();
for (var i = 0, len = points.length; i < len; i++) {
-
var x = Math.floor( (points[i][0] - view_start) * w_scale );
var y = points[i][1];
if (!y) { continue; }
- var y_px = y / max * height;
+ var y_px = y / max * height
+ if (y !== 0 && y_px < 1) { y_px = 1; }
ctx.fillStyle = "black";
ctx.fillRect( x, base_y - y_px, delta_x_px, y_px );
@@ -2991,7 +3031,7 @@
}
});
-// Contstants specific to feature tracks moved here (HACKING, these should
+// Constants specific to feature tracks moved here (HACKING, these should
// basically all be configuration options)
var DENSE_TRACK_HEIGHT = 10,
NO_DETAIL_TRACK_HEIGHT = 3,
@@ -3034,8 +3074,7 @@
var
feature_uid = feature[0],
feature_start = feature[1],
- // -1 b/c intervals are half-open.
- feature_end = feature[2] - 1,
+ feature_end = feature[2],
feature_name = feature[3],
f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
@@ -3134,8 +3173,7 @@
for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
var block = feature_blocks[k],
block_start = Math.floor( Math.max(0, (block[0] - tile_low) * w_scale) ),
- // -1 b/c intervals are half-open.
- block_end = Math.ceil( Math.min(width, Math.max((block[1] - 1 - tile_low) * w_scale)) );
+ block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low) * w_scale)) );
// Skip drawing if block not on tile.
if (block_start > block_end) { continue; }
@@ -3199,8 +3237,7 @@
var feature = data[i],
feature_uid = feature[0],
feature_start = feature[1],
- // -1 b/c intervals are half-open.
- feature_end = feature[2] - 1,
+ feature_end = feature[2],
feature_name = feature[3],
// All features need a start, end, and vertical center.
f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0