galaxy-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions

galaxy-dist commit af2d04e35680: Radio boxes in tool forms now have clickable labels as well. Update unit tests to reflect changes
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1288137500 14400
# Node ID af2d04e3568078d8d7ad94e229a17983f8282e20
# Parent 6a1ea9b6029416945caba087f2696c64a9a06621
Radio boxes in tool forms now have clickable labels as well. Update unit tests to reflect changes
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -184,16 +184,16 @@ class SelectField(BaseField):
>>> t.add_option( "tuti", 1 )
>>> t.add_option( "fruity", "x" )
>>> print t.get_html()
- <div><input type="radio" name="foo" value="1">tuti</div>
- <div><input type="radio" name="foo" value="x">fruity</div>
+ <div><input type="radio" name="foo" value="1" id="foo|1"><label for="foo|1">tuti</label></div>
+ <div><input type="radio" name="foo" value="x" id="foo|x"><label for="foo|x">fruity</label></div>
>>> t = SelectField( "bar", multiple=True, display="checkboxes" )
>>> t.add_option( "automatic", 3 )
>>> t.add_option( "bazooty", 4, selected=True )
>>> print t.get_html()
<div class="checkUncheckAllPlaceholder" checkbox_name="bar"></div>
- <div><input type="checkbox" name="bar" value="3">automatic</div>
- <div><input type="checkbox" name="bar" value="4" checked>bazooty</div>
+ <div><input type="checkbox" name="bar" value="3" id="bar|3"><label for="bar|3">automatic</label></div>
+ <div><input type="checkbox" name="bar" value="4" id="bar|4" checked='checked'><label for="bar|4">bazooty</label></div>
"""
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, refresh_on_change_values=[], size=None ):
self.name = name
@@ -232,13 +232,14 @@ class SelectField(BaseField):
for text, value, selected in self.options:
style = ""
escaped_value = escape( str( value ), quote=True )
+ uniq_id = "%s%s|%s" % (prefix, self.name, escaped_value)
if len(self.options) > 2 and ctr % 2 == 1:
style = " class=\"odd_row\""
selected_text = ""
if selected:
- selected_text = "checked='checked'"
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s" %s%s><label for="%s">%s</label></div>' % \
- ( style, prefix, self.name, escaped_value, escaped_value, selected_text, self.get_disabled_str( disabled ), escaped_value, text ) )
+ selected_text = " checked='checked'"
+ rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s"%s%s><label for="%s">%s</label></div>' % \
+ ( style, prefix, self.name, escaped_value, uniq_id, selected_text, self.get_disabled_str( disabled ), uniq_id, text ) )
ctr += 1
return "\n".join( rval )
def get_html_radio( self, prefix="", disabled=False ):
@@ -246,18 +247,23 @@ class SelectField(BaseField):
ctr = 0
for text, value, selected in self.options:
style = ""
+ escaped_value = escape( str( value ), quote=True )
+ uniq_id = "%s%s|%s" % (prefix, self.name, escaped_value)
if len(self.options) > 2 and ctr % 2 == 1:
style = " class=\"odd_row\""
- if selected: selected_text = " checked"
- else: selected_text = ""
- rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s"%s%s>%s</div>' % \
+ selected_text = ""
+ if selected:
+ selected_text = " checked='checked'"
+ rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s" id="%s"%s%s><label for="%s">%s</label></div>' % \
( style,
prefix,
self.name,
self.refresh_on_change_text,
- escape( str( value ), quote=True ),
+ escaped_value,
+ uniq_id,
selected_text,
self.get_disabled_str( disabled ),
+ uniq_id,
text ) )
ctr += 1
return "\n".join( rval )
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -474,14 +474,14 @@ class SelectToolParameter( ToolParameter
blah
>>> print p.get_html()
<div class="checkUncheckAllPlaceholder" checkbox_name="blah"></div>
- <div><input type="checkbox" name="blah" value="x">I am X</div>
- <div class="odd_row"><input type="checkbox" name="blah" value="y" checked>I am Y</div>
- <div><input type="checkbox" name="blah" value="z" checked>I am Z</div>
+ <div><input type="checkbox" name="blah" value="x" id="blah|x"><label for="blah|x">I am X</label></div>
+ <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label for="blah|y">I am Y</label></div>
+ <div><input type="checkbox" name="blah" value="z" id="blah|z" checked='checked'><label for="blah|z">I am Z</label></div>
>>> print p.get_html( value=["x","y"])
<div class="checkUncheckAllPlaceholder" checkbox_name="blah"></div>
- <div><input type="checkbox" name="blah" value="x" checked>I am X</div>
- <div class="odd_row"><input type="checkbox" name="blah" value="y" checked>I am Y</div>
- <div><input type="checkbox" name="blah" value="z">I am Z</div>
+ <div><input type="checkbox" name="blah" value="x" id="blah|x" checked='checked'><label for="blah|x">I am X</label></div>
+ <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label for="blah|y">I am Y</label></div>
+ <div><input type="checkbox" name="blah" value="z" id="blah|z"><label for="blah|z">I am Z</label></div>
>>> print p.to_param_dict_string( ["y", "z"] )
y,z
"""
1
0

galaxy-dist commit c22562b86d0f: Make the production buildbot use Main's tool conf
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Nate Coraor <nate(a)bx.psu.edu>
# Date 1288123416 14400
# Node ID c22562b86d0f62d361fd2531d22d42cfd6bf07c1
# Parent 49c7938d582799125a89f0d6ba38be0ddc6f4b4f
Make the production buildbot use Main's tool conf
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -54,6 +54,7 @@ def main():
galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir )
start_server = 'GALAXY_TEST_EXTERNAL' not in os.environ
tool_path = os.environ.get( 'GALAXY_TEST_TOOL_PATH', 'tools' )
+ tool_config_file = os.environ.get( 'GALAXY_TEST_TOOL_CONF', 'tool_conf.xml.sample' )
if start_server:
psu_production = False
galaxy_test_proxy_port = None
@@ -75,6 +76,7 @@ def main():
nginx_upload_store = os.environ.get( 'GALAXY_TEST_NGINX_UPLOAD_STORE', None )
if not nginx_upload_store:
raise Exception( 'Please set GALAXY_TEST_NGINX_UPLOAD_STORE to the path where the nginx upload module places uploaded files' )
+ tool_config_file = 'tool_conf.xml.main'
default_cluster_job_runner = os.environ.get( 'GALAXY_TEST_DEFAULT_CLUSTER_JOB_RUNNER', 'pbs:///' )
file_path = tempfile.mkdtemp( dir=base_file_path )
new_file_path = tempfile.mkdtemp( dir=base_new_file_path )
@@ -142,7 +144,7 @@ def main():
file_path = file_path,
new_file_path = new_file_path,
tool_path = tool_path,
- tool_config_file = "tool_conf.xml.sample",
+ tool_config_file = tool_config_file,
datatype_converters_config_file = "datatype_converters_conf.xml.sample",
tool_parse_help = False,
test_conf = "test.conf",
1
0

galaxy-dist commit e5f90080a2db: Merge with 29157e97e95453c5f9022d9c571527a6de4032e1
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1288149696 14400
# Node ID e5f90080a2db9c16bad2300c5ef0b5c49a558638
# Parent 61c786bd2efb6f9cc4d5fa4d43dfb056ed99b909
# Parent 29157e97e95453c5f9022d9c571527a6de4032e1
Merge with 29157e97e95453c5f9022d9c571527a6de4032e1
1
0

galaxy-dist commit 29157e97e954: Added setup script to configure RabbitMQ
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1288148662 14400
# Node ID 29157e97e95453c5f9022d9c571527a6de4032e1
# Parent af2d04e3568078d8d7ad94e229a17983f8282e20
Added setup script to configure RabbitMQ
--- a/transfer_datasets.ini.sample
+++ b/transfer_datasets.ini.sample
@@ -3,13 +3,8 @@
[data_transfer_user_login_info]
#email = datatx(a)bx.psu.edu
#password = datatx
-
-# The following section contains 4 config variables neede for the data transfer.
-# Please copy the exact values for each of these variables from the universe_wsgi.ini
-# configuration file for this installation
+#api_key = Generate it from the User menu in Galaxy
[universe_wsgi_config]
-#host = 127.0.0.1
-#port =
-#database_connection =
-#library_import_dir =
+# The http server section name in the Galaxy config file (universe_wsgi.ini)
+#http_server_section = server:main
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -420,4 +420,4 @@ upload1 = local:///
#queue = galaxy_queue
#exchange = galaxy_exchange
#routing_key = bar_code_scanner
-
+#rabbitmqctl_path = /path/to/rabbitmqctl
--- /dev/null
+++ b/scripts/galaxy_messaging/server/setup_rabbitmq.py
@@ -0,0 +1,34 @@
+#
+# Configuration script for RabbitMQ in Galaxy
+#
+# Requirements:
+# - set the rabbitmqctl_path variable in the 'galaxy_amqp' section in Galaxy config file
+#
+# Usage:
+# $ python setup_rabbitmq.py <Galaxy config file>
+#
+
+import os, sys, csv, ConfigParser
+
+def main( config_file ):
+ config = ConfigParser.ConfigParser()
+ config.read( config_file )
+ rabbitmqctl_path = config.get( 'galaxy_amqp', 'rabbitmqctl_path' )
+ username = config.get( 'galaxy_amqp', 'userid' )
+ password = config.get( 'galaxy_amqp', 'password' )
+ virtual_host = config.get( 'galaxy_amqp', 'virtual_host' )
+
+ cmd_list = [
+ 'add_user %s %s' % ( username, password ),
+ 'add_vhost %s' % config.get( 'galaxy_amqp', 'virtual_host' ),
+ 'set_permissions -p %s %s "%s.*" ".*" ".*"' % ( virtual_host, username, username )
+ ]
+
+ for cmd in cmd_list:
+ retval = os.system( rabbitmqctl_path + ' ' + cmd )
+ if retval:
+ print "Failed command: %s" % cmd
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main( sys.argv[1] )
1
0

galaxy-dist commit 0185bb614c77: Fix condition used to check if tiles have been loaded/drawn in trackster.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User jeremy goecks <jeremy.goecks(a)emory.edu>
# Date 1288186007 14400
# Node ID 0185bb614c7721d6edf6822ad973e589620b91f5
# Parent e5f90080a2db9c16bad2300c5ef0b5c49a558638
Fix condition used to check if tiles have been loaded/drawn in trackster.
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -772,7 +772,8 @@ var TiledTrack = function() {
this.max_height = 0;
// Index of first tile that overlaps visible region
var tile_index = Math.floor( low / resolution / DENSITY );
- // A list of setTimeout() ids used when drawing tiles.
+ // A list 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_ids = {};
while ( ( tile_index * DENSITY * resolution ) < high ) {
// Check in cache
@@ -800,8 +801,9 @@ var TiledTrack = function() {
//
var track = this;
var intervalId = setInterval(function() {
- if ( draw_tile_ids.length !== 0 ) {
- // Add drawing has finished; if there is more than one child in the content div,
+ // Only do stuff if all tile drawing is complete:
+ if (obj_length(draw_tile_ids) === 0) {
+ // All drawing has finished; if there is more than one child in the content div,
// remove the first one, which is the oldest.
if ( track.content_div.children().length > 1 ) {
track.content_div.children( ":first" ).remove();
--- a/static/scripts/packed/trackster.js
+++ b/static/scripts/packed/trackster.js
@@ -1,1 +1,1 @@
-var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}CONTEXT=DUMMY_CANVAS.getContext("2d");PX_PER_CHAR=CONTEXT.measureText("A").width;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPa
ttern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b){this.container=a;this.vis_id=c;this.dbkey=b;this.ti
tle=d;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();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);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_container=$("<div/>").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.nav);this.overview_viewport=$("<div/>").addClas
s("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_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.wh
ich)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a/>").click(function(){a.zoom_out();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);this.zi_link=$("<a/>").click(function(){a.zoom_in();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:
this.dbkey}),dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}a.chrom_select.html(h);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.overview_close.bind("click",function(){for(var e=0,d=a.tracks.length;e<d;e++){a.tracks[e].is_overview=false}$(this).siblings().filter("canvas").remove();
$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(g){if(!this.enable_pan||this.in_reordering){return}var d=$(this);var i=g.offsetX-this.current_x;var f=d.scrollTop()-(g.clientY-this.current_height);d.scrollTop(f);this.current_height=g.clientY;this.current_x=g.offsetX;var h=Math.round(i/a.viewport_container.width()*(a.high-a.low));a.move_delta(h)});this.top_labeltrack.bind("dragstart",function(d){this.drag_origin_x=d.clientX;this.drag_origin_pos=d.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag
",function(i){var f=Math.min(i.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(i.clientX,this.drag_origin_x)-a.container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(j){var f=Math.min(j.clientX,this.drag_origin_x),d=Math.max(j.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),i=a.low;a.low=Math.round(f/g*h)+i;a.high=Math.round(d/g*h)+i;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+c
ommatize(b))},change_chrom:function(e,b,g){var d=this;var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){return}if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counte
r;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max
_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);th
is.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.nav_container.height()-45);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 Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b
){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=function(b,a,d,c){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");i
f(!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.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.filtering_div.hide();this.filtering_div.bind("drag",function(i){i.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);var g=$("<th class='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200
px; position: relative'>").appendTo(h);a.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(k,l){var i=l.values;d.text("["+i[0]+"-"+i[1]+"]");a.low=i[0];a.high=i[1];c.draw(true)},change:function(i,k){a.control_element.slider("option","slide").call(a.control_element,i,k)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("
<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var b=this,j=b.view;if(b.hidden){return}if(b.display_modes!==undefined){if(b.mode_div===undefined){b.mode_div=$("<div class='right-float menubutton popup' />").appendTo(b.header_div);var e=
b.display_modes[0];b.mode=e;b.mode_div.text(e);var c=function(i){b.mode_div.text(i);b.mode=i;b.tile_cache.clear();b.draw()};var a={};for(var f,h=b.display_modes.length;f<h;f++){var g=b.display_modes[f];a[g]=function(i){return function(){c(i)}}(g)}make_popupmenu(b.mode_div,a)}else{b.mode_div.hide()}}var d={};d["Set as overview"]=function(){j.overview_viewport.find("canvas").remove();b.is_overview=true;b.set_overview();for(var i in j.tracks){if(j.tracks[i]!==b){j.tracks[i].is_overview=false}}};d["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){b.update_options(b.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.keyCode||m.which)===27){l()}else{if((m.keyCode||m.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",b.gen_options(b.track_id),{Cancel:l,OK:i})};if(b.filters.length>0){d["Show filters"]=function(){var i;if(!b.filterin
g_div.is(":visible")){i="Hide filters";b.filters_visible=true}else{i="Show filters";b.filters_visible=false}$("#"+b.name_div.attr("id")+"-menu").find("li").eq(2).text(i);b.filtering_div.toggle()}}d.Remove=function(){j.remove_track(b);if(j.num_tracks===0){$("#no-tracks").show()}};b.popup_menu=make_popupmenu(b.name_div,d);show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(a){var k=this.view.low,g=this.view.high,h=g-k,f=this.view.resolution;var n=$("<div style='position: relative;'></div>"),o=this.content_div.width()/h;this.content_div.append(n);this.max_height=0;var b=Math.floor(k/f/DENSITY);var j={};while((b*DENSITY*f)<g){var l=this.content_div.width()+"_"+o+"_"+b;var e=this.tile_cache.get(l);if(!a&&e){var i=b*DENSITY*f;var d=(i-k)*o;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,n)}else{this.delayed_draw(this,l,k,g,b,f,n,o,j)}b+=1}var c=this;var m=setInterval(function(
){if(j.length!==0){if(c.content_div.children().length>1){c.content_div.children(":first").remove()}for(var p=0;p<c.filters.length;p++){c.filters[p].update_ui_elt()}clearInterval(m)}},50)},delayed_draw:function(c,h,g,e,b,d,i,j,f){var a=setTimeout(function(){if(g<=c.view.high&&e>=c.view.low){var k=c.draw_tile(d,b,i,j);if(k){if(!c.initial_canvas&&!window.G_vmlCanvasManager){c.initial_canvas=$(k).clone();var n=k.get(0).getContext("2d");var l=c.initial_canvas.get(0).getContext("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,k);c.show_tile(k,i)}}delete f[a]},50);f[a]=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide)
filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.appen
d(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>PX_PER_CHAR){if(this.data_cache
.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_r
ange=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"22px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",top:a.height_px+11+"px",left:"10px"});f.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*D
ENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,w=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(w)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(w);if(!v){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;n.beginPath();n.fillStyle=this.prefs.color;var
u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(d-(h-k)/m*d);n.fillRect(u,h,f,d-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,d)}n.fill()}else{n.stroke()}c.append(b);return b},gen_options:function(m){var a=$("<div />").addClass("form-row");var e="track_"+m+"_color",b=$("<label />").attr("for",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+m+"_minval",l=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===undefined?"":this.prefs.min_value),k=$("<input></input>")
.attr("id",h).val(d),j="track_"+m+"_maxval",g=$("<label></label>").attr("for",j).text("Max value:"),i=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",j).val(i);return a.append(l).append(k).append(g).append(f).append(b).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_color").val();if(a!==this.prefs.min_value||c!==this.prefs.max_value||b!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.color=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container,e);TiledTrack.call(this);this.height_px=0;thi
s.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resol
ution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,g,b,q){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=q;this.s_e_by_tile[a]={}}var m=this.inc_slots[a].w_scale,y=[],h=0,n=this.view.max_low;var A=[];if(this.inc_slots[a].mode!==q){delete this.inc_slots[a];this.inc_slots[a]={mode:q,w_scale:m};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var v=0,w=g.length;v<w;v++){var f=g[v],l=f[0];if(this.inc_slots[a][l]!==undefined){h=Math.max(h,this.inc_slots[a][l]);A.push(this.inc_slots[a][l])}else{y.push(v)}}for(var v=0,w=y.length;v<w;v++){var f=g[y[v]],l=f[0],r=f[1],c=f[2],p=f[3],d=Math.floor((r-n)*m),e=Math.ceil((c-n)*m);if(p!==undefined&&!b){var s=CONTEXT.measureText(p).width;if(d-s<0){e+=s}else{d-=s}}var u=0;while(u<=MAX_FEATURE_DEPTH){var o=true;if(this.s_e_by_tile[a][u]!==undefined){for(var t=0,z=this.s_e_by_tile[a][u].length;t<z;t++){var x=this.s_e_by_tile
[a][u][t];if(e>x[0]&&d<x[1]){o=false;break}}}if(o){if(this.s_e_by_tile[a][u]===undefined){this.s_e_by_tile[a][u]=[]}this.s_e_by_tile[a][u].push([d,e]);this.inc_slots[a][l]=u;h=Math.max(h,u);break}u++}}return h},rect_or_text:function(r,l,t,b,q,f,i,e){r.textAlign="center";var k=0,p=Math.round(l/2);for(var m=0,s=i.length;m<s;m++){var j=i[m],d="MIDNSHP"[j[0]],n=j[1];if(d==="H"||d==="S"){k-=n}var g=q+k,w=Math.floor(Math.max(0,(g-t)*l)),h=Math.floor(Math.max(0,(g+n-t)*l));switch(d){case"S":case"H":case"M":var o=f.slice(k,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&l>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+1,h-w,9);r.fillStyle=CONNECTOR_COLOR;for(var u=0,a=o.length;u<a;u++){if(g+u>=t&&g+u<=b){var v=Math.floor(Math.max(0,(g+u-t)*l));r.fillText(o[u],v+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+4,h-w,3)}break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(w+this.left_offse
t,e+5,h-w,1);break;case"D":r.fillStyle="red";r.fillRect(w+this.left_offset,e+4,h-w,3);break;case"P":case"I":break}k+=n}},draw_tile:function(ag,o,s,av){var N=o*DENSITY*ag,al=(o+1)*DENSITY*ag,M=al-N;var an=(!this.initial_canvas?"initial":N+"_"+al);var I=this.data_cache.get(an);var e;if(I===undefined||(this.mode!=="Auto"&&I.dataset_type==="summary_tree")){this.data_queue[[N,al]]=true;this.get_data(N,al);return}var a=Math.ceil(M*av),ai=this.prefs.label_color,l=this.prefs.block_color,r=this.mode,z=25,ae=(r==="Squish")||(r==="Dense")&&(r!=="Pack")||(r==="Auto"&&(I.extra_info==="no_detail")),W=this.left_offset,au,D,aw;var q=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(q)}q=$(q);if(I.dataset_type==="summary_tree"){D=this.summary_draw_height}else{if(r==="Dense"){D=z;aw=10}else{aw=(ae?this.vertical_nodetail_px:this.vertical_detail_px);var A=(av<0.0001?1/this.view.zoom_res:av);D=this.incremental_slots(A,I.data,ae,r)*aw+z;au=this.inc_slot
s[A]}}q.css({position:"absolute",top:0,left:(N-this.view.low)*av-W});q.get(0).width=a+W;q.get(0).height=D;s.parent().css("height",Math.max(this.height_px,D)+"px");var J=q.get(0).getContext("2d");J.fillStyle=l;J.font=this.default_font;J.textAlign="right";this.container_div.find(".yaxislabel").remove();if(I.dataset_type=="summary_tree"){var Y=I.data,L=I.max,b=Math.ceil(I.delta*av);var p=$("<div />").addClass("yaxislabel").text(L);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var ap=0,H=Y.length;ap<H;ap++){var aa=Math.floor((Y[ap][0]-N)*av);var Z=Y[ap][1];if(!Z){continue}var am=Z/L*this.summary_draw_height;J.fillStyle="black";J.fillRect(aa+W,this.summary_draw_height-am,b,am);if(this.prefs.show_counts&&J.measureText(Z).width<b){J.fillStyle="#bbb";J.textAlign="center";J.fillText(Z,aa+W+(b/2),this.summary_draw_height-5)}}e="Summary";s.append(q);return q}if(I.message){q.css({border:"solid red","border-width":"2px 2px 2px 0px"});J.fillStyle=
"red";J.textAlign="left";J.fillText(I.message,100+W,aw)}var ad=false;if(I.data){ad=true;for(var ar=0;ar<this.filters.length;ar++){if(!this.filters[ar].applies_to(I.data[0])){ad=false}}}if(ad){q.addClass(FILTERABLE_CLASS)}var at=I.data;var ao=0;for(var ap=0,H=at.length;ap<H;ap++){var S=at[ap],R=S[0],aq=S[1],ac=S[2],O=S[3];if(au[R]===undefined){continue}var ab=false;var U;for(var ar=0;ar<this.filters.length;ar++){U=this.filters[ar];U.update_attrs(S);if(!U.keep(S)){ab=true;break}}if(ab){continue}if(aq<=al&&ac>=N){var af=Math.floor(Math.max(0,(aq-N)*av)),K=Math.ceil(Math.min(a,Math.max(0,(ac-N)*av))),X=(r==="Dense"?1:(1+au[R]))*aw;var G,aj,P=null,ax=null;if(I.dataset_type==="bai"){var v=S[4];J.fillStyle=l;if(S[5] instanceof Array){var E=Math.floor(Math.max(0,(S[5][0]-N)*av)),Q=Math.ceil(Math.min(a,Math.max(0,(S[5][1]-N)*av))),C=Math.floor(Math.max(0,(S[6][0]-N)*av)),w=Math.ceil(Math.min(a,Math.max(0,(S[6][1]-N)*av)));if(S[5][1]>=N&&S[5][0]<=al){this.rect_or_text(J,av,N,al,S[5][0
],S[5][2],v,X)}if(S[6][1]>=N&&S[6][0]<=al){this.rect_or_text(J,av,N,al,S[6][0],S[6][2],v,X)}if(C>Q){J.fillStyle=CONNECTOR_COLOR;J.fillRect(Q+W,X+5,C-Q,1)}}else{J.fillStyle=l;this.rect_or_text(J,av,N,al,aq,O,v,X)}if(r!=="Dense"&&!ae&&aq>N){J.fillStyle=this.prefs.label_color;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(R,K+2+W,X+8)}else{J.textAlign="right";J.fillText(R,af-2+W,X+8)}J.fillStyle=l}}else{if(I.dataset_type==="interval_index"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var F=S[4],V=S[5],ah=S[6],h=S[7];if(V&&ah){P=Math.floor(Math.max(0,(V-N)*av));ax=Math.ceil(Math.min(a,Math.max(0,(ah-N)*av)))}if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}if(h){if(F){if(F=="+"){J.fillStyle=RIGHT_STRAND}else{if(F=="-"){J.fillStyle=LEFT_STRAND}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}for(var an=0,g=h.
length;an<g;an++){var u=h[an],d=Math.floor(Math.max(0,(u[0]-N)*av)),T=Math.ceil(Math.min(a,Math.max((u[1]-N)*av)));if(d>T){continue}G=5;aj=3;J.fillRect(d+W,X+aj,T-d,G);if(P!==undefined&&!(d>ax||T<P)){G=9;aj=1;var ak=Math.max(d,P),B=Math.min(T,ax);J.fillRect(ak+W,X+aj,B-ak,G)}}}else{G=9;aj=1;J.fillRect(af+W,X+aj,K-af,G);if(S.strand){if(S.strand=="+"){J.fillStyle=RIGHT_STRAND_INV}else{if(S.strand=="-"){J.fillStyle=LEFT_STRAND_INV}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}}}}else{if(I.dataset_type==="vcf"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var t=S[4],n=S[5],c=S[6];G=9;aj=1;J.fillRect(af+W,X,K-af,G);if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}var m=t+" / "+n;if(aq>N&&J.measureText(m).width<(K-af)){J.fillStyle="white";J.textAlign="center";J.fillText(m,W+af+(K-af)/2,X+8);J.fillStyle=l}}}}}ao++}}return q},gen_o
ptions:function(i){var a=$("<div />").addClass("form-row");var e="track_"+i+"_block_color",k=$("<label />").attr("for",e).text("Block color:"),l=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),j="track_"+i+"_label_color",g=$("<label />").attr("for",j).text("Text color:"),h=$("<input />").attr("id",j).attr("name",j).val(this.prefs.label_color),f="track_"+i+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(k).append(l).append(g).append(h).append(d)},update_options:function(d){var b=$("#track_"+d+"_block_color").val(),c=$("#track_"+d+"_label_color").val(),a=$("#track_"+d+"_show_count").attr("checked");if(b!==this.prefs.block_color||c!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=c;this.prefs.show_counts=
a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
+var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}CONTEXT=DUMMY_CANVAS.getContext("2d");PX_PER_CHAR=CONTEXT.measureText("A").width;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPa
ttern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b){this.container=a;this.vis_id=c;this.dbkey=b;this.ti
tle=d;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();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);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_container=$("<div/>").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.nav);this.overview_viewport=$("<div/>").addClas
s("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_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.wh
ich)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a/>").click(function(){a.zoom_out();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);this.zi_link=$("<a/>").click(function(){a.zoom_in();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:
this.dbkey}),dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}a.chrom_select.html(h);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.overview_close.bind("click",function(){for(var e=0,d=a.tracks.length;e<d;e++){a.tracks[e].is_overview=false}$(this).siblings().filter("canvas").remove();
$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(g){if(!this.enable_pan||this.in_reordering){return}var d=$(this);var i=g.offsetX-this.current_x;var f=d.scrollTop()-(g.clientY-this.current_height);d.scrollTop(f);this.current_height=g.clientY;this.current_x=g.offsetX;var h=Math.round(i/a.viewport_container.width()*(a.high-a.low));a.move_delta(h)});this.top_labeltrack.bind("dragstart",function(d){this.drag_origin_x=d.clientX;this.drag_origin_pos=d.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag
",function(i){var f=Math.min(i.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(i.clientX,this.drag_origin_x)-a.container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(j){var f=Math.min(j.clientX,this.drag_origin_x),d=Math.max(j.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),i=a.low;a.low=Math.round(f/g*h)+i;a.high=Math.round(d/g*h)+i;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+c
ommatize(b))},change_chrom:function(e,b,g){var d=this;var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){return}if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counte
r;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max
_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);th
is.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.nav_container.height()-45);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 Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b
){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=function(b,a,d,c){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");i
f(!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.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.filtering_div.hide();this.filtering_div.bind("drag",function(i){i.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);var g=$("<th class='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200
px; position: relative'>").appendTo(h);a.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(k,l){var i=l.values;d.text("["+i[0]+"-"+i[1]+"]");a.low=i[0];a.high=i[1];c.draw(true)},change:function(i,k){a.control_element.slider("option","slide").call(a.control_element,i,k)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("
<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var b=this,j=b.view;if(b.hidden){return}if(b.display_modes!==undefined){if(b.mode_div===undefined){b.mode_div=$("<div class='right-float menubutton popup' />").appendTo(b.header_div);var e=
b.display_modes[0];b.mode=e;b.mode_div.text(e);var c=function(i){b.mode_div.text(i);b.mode=i;b.tile_cache.clear();b.draw()};var a={};for(var f,h=b.display_modes.length;f<h;f++){var g=b.display_modes[f];a[g]=function(i){return function(){c(i)}}(g)}make_popupmenu(b.mode_div,a)}else{b.mode_div.hide()}}var d={};d["Set as overview"]=function(){j.overview_viewport.find("canvas").remove();b.is_overview=true;b.set_overview();for(var i in j.tracks){if(j.tracks[i]!==b){j.tracks[i].is_overview=false}}};d["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){b.update_options(b.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.keyCode||m.which)===27){l()}else{if((m.keyCode||m.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",b.gen_options(b.track_id),{Cancel:l,OK:i})};if(b.filters.length>0){d["Show filters"]=function(){var i;if(!b.filterin
g_div.is(":visible")){i="Hide filters";b.filters_visible=true}else{i="Show filters";b.filters_visible=false}$("#"+b.name_div.attr("id")+"-menu").find("li").eq(2).text(i);b.filtering_div.toggle()}}d.Remove=function(){j.remove_track(b);if(j.num_tracks===0){$("#no-tracks").show()}};b.popup_menu=make_popupmenu(b.name_div,d);show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(a){var k=this.view.low,g=this.view.high,h=g-k,f=this.view.resolution;var n=$("<div style='position: relative;'></div>"),o=this.content_div.width()/h;this.content_div.append(n);this.max_height=0;var b=Math.floor(k/f/DENSITY);var j={};while((b*DENSITY*f)<g){var l=this.content_div.width()+"_"+o+"_"+b;var e=this.tile_cache.get(l);if(!a&&e){var i=b*DENSITY*f;var d=(i-k)*o;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,n)}else{this.delayed_draw(this,l,k,g,b,f,n,o,j)}b+=1}var c=this;var m=setInterval(function(
){if(obj_length(j)===0){if(c.content_div.children().length>1){c.content_div.children(":first").remove()}for(var p=0;p<c.filters.length;p++){c.filters[p].update_ui_elt()}clearInterval(m)}},50)},delayed_draw:function(c,h,g,e,b,d,i,j,f){var a=setTimeout(function(){if(g<=c.view.high&&e>=c.view.low){var k=c.draw_tile(d,b,i,j);if(k){if(!c.initial_canvas&&!window.G_vmlCanvasManager){c.initial_canvas=$(k).clone();var n=k.get(0).getContext("2d");var l=c.initial_canvas.get(0).getContext("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,k);c.show_tile(k,i)}}delete f[a]},50);f[a]=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|H
ide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.
append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>PX_PER_CHAR){if(this.data_
cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.verti
cal_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"22px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",top:a.height_px+11+"px",left:"10px"});f.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b
+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,w=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(w)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(w);if(!v){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;n.beginPath();n.fillStyle=this.prefs.colo
r;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(d-(h-k)/m*d);n.fillRect(u,h,f,d-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,d)}n.fill()}else{n.stroke()}c.append(b);return b},gen_options:function(m){var a=$("<div />").addClass("form-row");var e="track_"+m+"_color",b=$("<label />").attr("for",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+m+"_minval",l=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===undefined?"":this.prefs.min_value),k=$("<input></inp
ut>").attr("id",h).val(d),j="track_"+m+"_maxval",g=$("<label></label>").attr("for",j).text("Max value:"),i=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",j).val(i);return a.append(l).append(k).append(g).append(f).append(b).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_color").val();if(a!==this.prefs.min_value||c!==this.prefs.max_value||b!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.color=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container,e);TiledTrack.call(this);this.height_px=
0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.
resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,g,b,q){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=q;this.s_e_by_tile[a]={}}var m=this.inc_slots[a].w_scale,y=[],h=0,n=this.view.max_low;var A=[];if(this.inc_slots[a].mode!==q){delete this.inc_slots[a];this.inc_slots[a]={mode:q,w_scale:m};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var v=0,w=g.length;v<w;v++){var f=g[v],l=f[0];if(this.inc_slots[a][l]!==undefined){h=Math.max(h,this.inc_slots[a][l]);A.push(this.inc_slots[a][l])}else{y.push(v)}}for(var v=0,w=y.length;v<w;v++){var f=g[y[v]],l=f[0],r=f[1],c=f[2],p=f[3],d=Math.floor((r-n)*m),e=Math.ceil((c-n)*m);if(p!==undefined&&!b){var s=CONTEXT.measureText(p).width;if(d-s<0){e+=s}else{d-=s}}var u=0;while(u<=MAX_FEATURE_DEPTH){var o=true;if(this.s_e_by_tile[a][u]!==undefined){for(var t=0,z=this.s_e_by_tile[a][u].length;t<z;t++){var x=this.s_e_by
_tile[a][u][t];if(e>x[0]&&d<x[1]){o=false;break}}}if(o){if(this.s_e_by_tile[a][u]===undefined){this.s_e_by_tile[a][u]=[]}this.s_e_by_tile[a][u].push([d,e]);this.inc_slots[a][l]=u;h=Math.max(h,u);break}u++}}return h},rect_or_text:function(r,l,t,b,q,f,i,e){r.textAlign="center";var k=0,p=Math.round(l/2);for(var m=0,s=i.length;m<s;m++){var j=i[m],d="MIDNSHP"[j[0]],n=j[1];if(d==="H"||d==="S"){k-=n}var g=q+k,w=Math.floor(Math.max(0,(g-t)*l)),h=Math.floor(Math.max(0,(g+n-t)*l));switch(d){case"S":case"H":case"M":var o=f.slice(k,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&l>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+1,h-w,9);r.fillStyle=CONNECTOR_COLOR;for(var u=0,a=o.length;u<a;u++){if(g+u>=t&&g+u<=b){var v=Math.floor(Math.max(0,(g+u-t)*l));r.fillText(o[u],v+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+4,h-w,3)}break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(w+this.left_
offset,e+5,h-w,1);break;case"D":r.fillStyle="red";r.fillRect(w+this.left_offset,e+4,h-w,3);break;case"P":case"I":break}k+=n}},draw_tile:function(ag,o,s,av){var N=o*DENSITY*ag,al=(o+1)*DENSITY*ag,M=al-N;var an=(!this.initial_canvas?"initial":N+"_"+al);var I=this.data_cache.get(an);var e;if(I===undefined||(this.mode!=="Auto"&&I.dataset_type==="summary_tree")){this.data_queue[[N,al]]=true;this.get_data(N,al);return}var a=Math.ceil(M*av),ai=this.prefs.label_color,l=this.prefs.block_color,r=this.mode,z=25,ae=(r==="Squish")||(r==="Dense")&&(r!=="Pack")||(r==="Auto"&&(I.extra_info==="no_detail")),W=this.left_offset,au,D,aw;var q=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(q)}q=$(q);if(I.dataset_type==="summary_tree"){D=this.summary_draw_height}else{if(r==="Dense"){D=z;aw=10}else{aw=(ae?this.vertical_nodetail_px:this.vertical_detail_px);var A=(av<0.0001?1/this.view.zoom_res:av);D=this.incremental_slots(A,I.data,ae,r)*aw+z;au=this.inc
_slots[A]}}q.css({position:"absolute",top:0,left:(N-this.view.low)*av-W});q.get(0).width=a+W;q.get(0).height=D;s.parent().css("height",Math.max(this.height_px,D)+"px");var J=q.get(0).getContext("2d");J.fillStyle=l;J.font=this.default_font;J.textAlign="right";this.container_div.find(".yaxislabel").remove();if(I.dataset_type=="summary_tree"){var Y=I.data,L=I.max,b=Math.ceil(I.delta*av);var p=$("<div />").addClass("yaxislabel").text(L);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var ap=0,H=Y.length;ap<H;ap++){var aa=Math.floor((Y[ap][0]-N)*av);var Z=Y[ap][1];if(!Z){continue}var am=Z/L*this.summary_draw_height;J.fillStyle="black";J.fillRect(aa+W,this.summary_draw_height-am,b,am);if(this.prefs.show_counts&&J.measureText(Z).width<b){J.fillStyle="#bbb";J.textAlign="center";J.fillText(Z,aa+W+(b/2),this.summary_draw_height-5)}}e="Summary";s.append(q);return q}if(I.message){q.css({border:"solid red","border-width":"2px 2px 2px 0px"});J.fillS
tyle="red";J.textAlign="left";J.fillText(I.message,100+W,aw)}var ad=false;if(I.data){ad=true;for(var ar=0;ar<this.filters.length;ar++){if(!this.filters[ar].applies_to(I.data[0])){ad=false}}}if(ad){q.addClass(FILTERABLE_CLASS)}var at=I.data;var ao=0;for(var ap=0,H=at.length;ap<H;ap++){var S=at[ap],R=S[0],aq=S[1],ac=S[2],O=S[3];if(au[R]===undefined){continue}var ab=false;var U;for(var ar=0;ar<this.filters.length;ar++){U=this.filters[ar];U.update_attrs(S);if(!U.keep(S)){ab=true;break}}if(ab){continue}if(aq<=al&&ac>=N){var af=Math.floor(Math.max(0,(aq-N)*av)),K=Math.ceil(Math.min(a,Math.max(0,(ac-N)*av))),X=(r==="Dense"?1:(1+au[R]))*aw;var G,aj,P=null,ax=null;if(I.dataset_type==="bai"){var v=S[4];J.fillStyle=l;if(S[5] instanceof Array){var E=Math.floor(Math.max(0,(S[5][0]-N)*av)),Q=Math.ceil(Math.min(a,Math.max(0,(S[5][1]-N)*av))),C=Math.floor(Math.max(0,(S[6][0]-N)*av)),w=Math.ceil(Math.min(a,Math.max(0,(S[6][1]-N)*av)));if(S[5][1]>=N&&S[5][0]<=al){this.rect_or_text(J,av,N,al,S
[5][0],S[5][2],v,X)}if(S[6][1]>=N&&S[6][0]<=al){this.rect_or_text(J,av,N,al,S[6][0],S[6][2],v,X)}if(C>Q){J.fillStyle=CONNECTOR_COLOR;J.fillRect(Q+W,X+5,C-Q,1)}}else{J.fillStyle=l;this.rect_or_text(J,av,N,al,aq,O,v,X)}if(r!=="Dense"&&!ae&&aq>N){J.fillStyle=this.prefs.label_color;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(R,K+2+W,X+8)}else{J.textAlign="right";J.fillText(R,af-2+W,X+8)}J.fillStyle=l}}else{if(I.dataset_type==="interval_index"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var F=S[4],V=S[5],ah=S[6],h=S[7];if(V&&ah){P=Math.floor(Math.max(0,(V-N)*av));ax=Math.ceil(Math.min(a,Math.max(0,(ah-N)*av)))}if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}if(h){if(F){if(F=="+"){J.fillStyle=RIGHT_STRAND}else{if(F=="-"){J.fillStyle=LEFT_STRAND}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}for(var an=0
,g=h.length;an<g;an++){var u=h[an],d=Math.floor(Math.max(0,(u[0]-N)*av)),T=Math.ceil(Math.min(a,Math.max((u[1]-N)*av)));if(d>T){continue}G=5;aj=3;J.fillRect(d+W,X+aj,T-d,G);if(P!==undefined&&!(d>ax||T<P)){G=9;aj=1;var ak=Math.max(d,P),B=Math.min(T,ax);J.fillRect(ak+W,X+aj,B-ak,G)}}}else{G=9;aj=1;J.fillRect(af+W,X+aj,K-af,G);if(S.strand){if(S.strand=="+"){J.fillStyle=RIGHT_STRAND_INV}else{if(S.strand=="-"){J.fillStyle=LEFT_STRAND_INV}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}}}}else{if(I.dataset_type==="vcf"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var t=S[4],n=S[5],c=S[6];G=9;aj=1;J.fillRect(af+W,X,K-af,G);if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}var m=t+" / "+n;if(aq>N&&J.measureText(m).width<(K-af)){J.fillStyle="white";J.textAlign="center";J.fillText(m,W+af+(K-af)/2,X+8);J.fillStyle=l}}}}}ao++}}return q},
gen_options:function(i){var a=$("<div />").addClass("form-row");var e="track_"+i+"_block_color",k=$("<label />").attr("for",e).text("Block color:"),l=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),j="track_"+i+"_label_color",g=$("<label />").attr("for",j).text("Text color:"),h=$("<input />").attr("id",j).attr("name",j).val(this.prefs.label_color),f="track_"+i+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(k).append(l).append(g).append(h).append(d)},update_options:function(d){var b=$("#track_"+d+"_block_color").val(),c=$("#track_"+d+"_label_color").val(),a=$("#track_"+d+"_show_count").attr("checked");if(b!==this.prefs.block_color||c!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=c;this.prefs.show_co
unts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
1
0

galaxy-dist commit 87a6d4a29eee: fixed mutation viz functional tests
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1288111817 14400
# Node ID 87a6d4a29eeea038c669f086d254aaa4140a15bb
# Parent e6e68c67dd9759154876546662f59ee280b78a34
fixed mutation viz functional tests
--- a/test-data/mutation_data1_zoom3x.svg
+++ b/test-data/mutation_data1_zoom3x.svg
@@ -5,21 +5,21 @@
<g id="viewport">
-<text y="4" x="12" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">A</tspan></text>
+<text y="3" x="12" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">A</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="14" fill="blue" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="14" fill="blue" />
-<text y="4" x="22" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">C</tspan></text>
+<text y="3" x="22" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">C</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="24" fill="green" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="24" fill="green" />
-<text y="4" x="32" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">G</tspan></text>
+<text y="3" x="32" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">G</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="34" fill="orange" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="34" fill="orange" />
-<text y="4" x="42" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">T</tspan></text>
+<text y="3" x="42" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">T</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="44" fill="red" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="44" fill="red" /><text y="25" x="23" stroke="none" transform="rotate(-90 23,25)" fill="black"><tspan style="font-family:Verdana;font-size:25%">s1</tspan></text>
--- a/test-data/mutation_data1_interactive.svg
+++ b/test-data/mutation_data1_interactive.svg
@@ -234,21 +234,21 @@ function handleMouseUp(evt) {
<g id="viewport">
-<text y="4" x="12" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">A</tspan></text>
+<text y="3" x="12" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">A</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="14" fill="blue" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="14" fill="blue" />
-<text y="4" x="22" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">C</tspan></text>
+<text y="3" x="22" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">C</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="24" fill="green" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="24" fill="green" />
-<text y="4" x="32" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">G</tspan></text>
+<text y="3" x="32" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">G</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="34" fill="orange" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="34" fill="orange" />
-<text y="4" x="42" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">T</tspan></text>
+<text y="3" x="42" stroke="none" fill="black"><tspan style="font-family:Verdana;font-size:20%">T</tspan></text>
-<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="1" x="44" fill="red" />
+<rect fill-opacity="0.5" height="3" width="4" stroke="none" y="0" x="44" fill="red" /><text y="35" x="23" stroke="none" transform="rotate(-90 23,35)" fill="black"><tspan style="font-family:Verdana;font-size:25%">s1</tspan></text>
1
0

galaxy-dist commit d73fa5f14b01: fixed select all checkbox in grid. the footer now updates when all items are selected
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1288121253 14400
# Node ID d73fa5f14b013333b2e49bfbf775db8dd0197e2b
# Parent 314f8a5d38237c3f1fafccb522ee45aebfa8464f
fixed select all checkbox in grid. the footer now updates when all items are selected
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -611,34 +611,27 @@
});
}
- function check_all_items()
- {
+ function check_all_items() {
var chk_all = document.getElementById('check_all');
var checks = document.getElementsByTagName('input');
//var boxLength = checks.length;
var total = 0;
- if ( chk_all.checked == true )
- {
- for ( i=0; i < checks.length; i++ )
- {
- if ( checks[i].name.indexOf( 'id' ) != -1)
- {
+ if ( chk_all.checked == true ) {
+ for ( i=0; i < checks.length; i++ ) {
+ if ( checks[i].name.indexOf( 'id' ) != -1) {
checks[i].checked = true;
total++;
}
}
}
- else
- {
- for ( i=0; i < checks.length; i++ )
- {
- if ( checks[i].name.indexOf( 'id' ) != -1)
- {
+ else {
+ for ( i=0; i < checks.length; i++ ) {
+ if ( checks[i].name.indexOf( 'id' ) != -1) {
checks[i].checked = false
}
}
}
-
+ init_grid_elements();
}
</script></%def>
1
0

galaxy-dist commit bdcbd7ab6e7f: Fix solid_qual_stats tool when value is 0 or not a valid int. Fixes #405
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1288115163 14400
# Node ID bdcbd7ab6e7fe0a6ed869d8a682660c0cebb7658
# Parent 87a6d4a29eeea038c669f086d254aaa4140a15bb
Fix solid_qual_stats tool when value is 0 or not a valid int. Fixes #405
--- a/tools/solid_tools/solid_qual_stats.py
+++ b/tools/solid_tools/solid_qual_stats.py
@@ -31,6 +31,7 @@ def __main__():
infile_name = infile_score_name
readlen = None
+ invalid_lines = 0
j = 0
for line in file( infile_name ):
line = line.strip()
@@ -39,18 +40,17 @@ def __main__():
elems = line.split()
try:
for item in elems:
- assert int(item)
- if not(readlen):
+ int(item)
+ if not readlen:
readlen = len(elems)
if len(elems) != readlen:
print "Note: Reads in the input dataset are of variable lengths."
j += 1
- except:
+ except ValueError:
invalid_lines += 1
if j > 10:
break
- invalid_lines = 0
position_dict = {}
print >>fout, "column\tcount\tmin\tmax\tsum\tmean\tQ1\tmed\tQ3\tIQR\tlW\trW"
for k,line in enumerate(file( infile_name )):
@@ -132,7 +132,7 @@ def __main__():
if invalid_lines:
print "Skipped %d reads as invalid." %invalid_lines
if invalid_positions:
- print "Skipped stats computation for %d read postions." %invalid_positions
+ print "Skipped stats computation for %d read positions." %invalid_positions
if __name__=="__main__":
__main__()
1
0

galaxy-dist commit 379d0701f198: added select all checkbox to grid framework
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1288119695 14400
# Node ID 379d0701f198964fb964c3834cce7414cbc8f888
# Parent 262c91e3a2ea7d11d65875ec2af42526c92b7123
added select all checkbox to grid framework
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -610,6 +610,36 @@
}
});
}
+
+ function check_all_items()
+ {
+ var chk_all = document.getElementById('check_all');
+ var checks = document.getElementsByTagName('input');
+ //var boxLength = checks.length;
+ var total = 0;
+ if ( chk_all.checked == true )
+ {
+ for ( i=0; i < checks.length; i++ )
+ {
+ if ( checks[i].name.indexOf( 'id' ) != -1)
+ {
+ checks[i].checked = true;
+ total++;
+ }
+ }
+ }
+ else
+ {
+ for ( i=0; i < checks.length; i++ )
+ {
+ if ( checks[i].name.indexOf( 'id' ) != -1)
+ {
+ checks[i].checked = false
+ }
+ }
+ }
+
+ }
</script></%def>
@@ -761,7 +791,11 @@
<thead id="grid-table-header"><tr>
%if show_item_checkboxes:
- <th></th>
+ <th>
+ %if query.count() > 0:
+ <input type="checkbox" id="check_all" name=select_all_checkbox value="true" onclick='check_all_items(1);'><input type="hidden" name=select_all_checkbox value="true">
+ %endif
+ </th>
%endif
%for column in grid.columns:
%if column.visible:
1
0

galaxy-dist commit e6e68c67dd97: Use a job to import a history from an archive. This makes it possible to move a history from one Galaxy instance to another, subject to the limitations below. The job itself unpacks the archive, and the job's cleanup creates a history from the archive. A history imported via an archive is only visible to the user when it has finished being imported.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User jeremy goecks <jeremy.goecks(a)emory.edu>
# Date 1288106620 14400
# Node ID e6e68c67dd9759154876546662f59ee280b78a34
# Parent 677bcc65f74f5a460277f089d0cdebf170f02831
Use a job to import a history from an archive. This makes it possible to move a history from one Galaxy instance to another, subject to the limitations below. The job itself unpacks the archive, and the job's cleanup creates a history from the archive. A history imported via an archive is only visible to the user when it has finished being imported.
Currently, there are limitations to this functionality; these will be fixed going forward. These limitations are:
-history archives can be imported only via URL, not file;
-histories must be shared in order for them to be importable via archive;
-tags are not currently imported;
-reproducibility is limited as parameters for imported jobs are not always recovered and set.
--- a/lib/galaxy/web/controllers/history.py
+++ b/lib/galaxy/web/controllers/history.py
@@ -79,7 +79,7 @@ class HistoryListGrid( grids.Grid ):
def get_current_item( self, trans, **kwargs ):
return trans.get_history()
def apply_query_filter( self, trans, query, **kwargs ):
- return query.filter_by( user=trans.user, purged=False )
+ return query.filter_by( user=trans.user, purged=False, importing=False )
class SharedHistoryListGrid( grids.Grid ):
# Custom column types
@@ -465,212 +465,40 @@ class HistoryController( BaseController,
trans.sa_session.flush()
return new_annotation
- def import_archive( self, trans, archived_history=None, gzip=True ):
- """ Import a history. """
+ @web.expose
+ # TODO: Remove require_login when users are warned that, if they are not
+ # logged in, this will remove their current history.
+ @web.require_login( "use Galaxy histories" )
+ def import_archive( self, trans, **kwargs ):
+ """ Import a history from a file archive. """
- def file_in_dir( file_path, a_dir ):
- """ Returns true if file is in directory. """
- abs_file_path = os.path.abspath( file_path )
- return os.path.split( abs_file_path )[0] == a_dir
+ # Set archive source and type.
+ archive_file = kwargs.get( 'archive_file', None )
+ archive_url = kwargs.get( 'archive_url', None )
+ archive_source = None
+ if archive_file:
+ archive_source = archive_file
+ archive_type = 'file'
+ elif archive_url:
+ archive_source = archive_url
+ archive_type = 'url'
- if archived_history is not None:
- try:
- history_archive_file = tarfile.open( archived_history.file.name )
-
- # Unpack archive in temporary directory.
- temp_output_dir = tempfile.mkdtemp()
- history_archive_file.extractall( path=temp_output_dir )
- history_archive_file.close()
-
- #
- # Create history.
- #
- history_attr_file_name = os.path.join( temp_output_dir, 'history_attrs.txt')
- if not file_in_dir( history_attr_file_name, temp_output_dir ):
- raise Exception( "Invalid location for history attributes file: %s" % history_attr_file_name )
- history_attr_in = open( history_attr_file_name, 'rb' )
- history_attr_str = ''
- buffsize = 1048576
- try:
- while True:
- history_attr_str += history_attr_in.read( buffsize )
- if not history_attr_str or len( history_attr_str ) % buffsize != 0:
- break
- except OverflowError:
- pass
- history_attr_in.close()
- history_attrs = from_json_string( history_attr_str )
-
- # Create history.
- new_history = model.History( name='imported from archive: %s' % history_attrs['name'].encode( 'utf-8' ), user=trans.user )
- trans.sa_session.add( new_history )
-
- new_history.hid_counter = history_attrs['hid_counter']
- new_history.genome_build = history_attrs['genome_build']
- trans.sa_session.flush()
-
- # Builds a tag string for a tag, value pair.
- def get_tag_str( tag, value ):
- if not value:
- return tag
- else:
- return tag + ":" + value
-
- # Add annotation, tags.
- if trans.user:
- self.add_item_annotation( trans.sa_session, trans.get_user(), new_history, history_attrs[ 'annotation' ] )
- for tag, value in history_attrs[ 'tags' ].items():
- trans.app.tag_handler.apply_item_tags( trans, trans.user, new_history, get_tag_str( tag, value ) )
-
- #
- # Create datasets.
- #
- datasets_attrs_file_name = os.path.join( temp_output_dir, 'datasets_attrs.txt')
- if not file_in_dir( datasets_attrs_file_name, temp_output_dir ):
- raise Exception( "Invalid location for dataset attributes file: %s" % datasets_attrs_file_name )
- datasets_attr_in = open( datasets_attrs_file_name, 'rb' )
- datasets_attr_str = ''
- buffsize = 1048576
- try:
- while True:
- datasets_attr_str += datasets_attr_in.read( buffsize )
- if not datasets_attr_str or len( datasets_attr_str ) % buffsize != 0:
- break
- except OverflowError:
- pass
- datasets_attr_in.close()
- datasets_attrs = from_json_string( datasets_attr_str )
-
- # Create datasets.
- for dataset_attrs in datasets_attrs:
- metadata = dataset_attrs['metadata']
-
- # Create dataset and HDA.
- hda = model.HistoryDatasetAssociation( name = dataset_attrs['name'].encode( 'utf-8' ),
- extension = dataset_attrs['extension'],
- info = dataset_attrs['info'].encode( 'utf-8' ),
- blurb = dataset_attrs['blurb'],
- peek = dataset_attrs['peek'],
- designation = dataset_attrs['designation'],
- visible = dataset_attrs['visible'],
- dbkey = metadata['dbkey'],
- metadata = metadata,
- history = new_history,
- create_dataset = True,
- sa_session = trans.sa_session )
- hda.state = hda.states.OK
- trans.sa_session.add( hda )
- trans.sa_session.flush()
- new_history.add_dataset( hda, genome_build = None )
- hda.hid = dataset_attrs['hid'] # Overwrite default hid set when HDA added to history.
- permissions = trans.app.security_agent.history_get_default_permissions( new_history )
- trans.app.security_agent.set_all_dataset_permissions( hda.dataset, permissions )
- trans.sa_session.flush()
-
- # Do security check and copy dataset data.
- temp_dataset_file_name = os.path.join( temp_output_dir, dataset_attrs['file_name'] )
- if not file_in_dir( temp_dataset_file_name, os.path.join( temp_output_dir, "datasets" ) ):
- raise Exception( "Invalid dataset path: %s" % temp_dataset_file_name )
- shutil.move( temp_dataset_file_name, hda.file_name )
-
- # Set tags, annotations.
- if trans.user:
- self.add_item_annotation( trans.sa_session, trans.get_user(), hda, dataset_attrs[ 'annotation' ] )
- for tag, value in dataset_attrs[ 'tags' ].items():
- trans.app.tag_handler.apply_item_tags( trans, trans.user, hda, get_tag_str( tag, value ) )
- trans.sa_session.flush()
-
- #
- # Create jobs.
- #
-
- # Read jobs attributes.
- jobs_attr_file_name = os.path.join( temp_output_dir, 'jobs_attrs.txt')
- if not file_in_dir( jobs_attr_file_name, temp_output_dir ):
- raise Exception( "Invalid location for jobs' attributes file: %s" % jobs_attr_file_name )
- jobs_attr_in = open( jobs_attr_file_name, 'rb' )
- jobs_attr_str = ''
- buffsize = 1048576
- try:
- while True:
- jobs_attr_str += jobs_attr_in.read( buffsize )
- if not jobs_attr_str or len( jobs_attr_str ) % buffsize != 0:
- break
- except OverflowError:
- pass
- jobs_attr_in.close()
-
- # Decode jobs attributes.
- def as_hda( obj_dct ):
- """ Hook to 'decode' an HDA; method uses history and HID to get the HDA represented by
- the encoded object. This only works because HDAs are created above. """
- if obj_dct.get( '__HistoryDatasetAssociation__', False ):
- return trans.sa_session.query( model.HistoryDatasetAssociation ) \
- .filter_by( history=new_history, hid=obj_dct['hid'] ).first()
- return obj_dct
- jobs_attrs = from_json_string( jobs_attr_str, object_hook=as_hda )
-
- # Create each job.
- for job_attrs in jobs_attrs:
- imported_job = model.Job()
- imported_job.user = trans.user
- imported_job.session = trans.get_galaxy_session().id
- imported_job.history = new_history
- imported_job.tool_id = job_attrs[ 'tool_id' ]
- imported_job.tool_version = job_attrs[ 'tool_version' ]
- imported_job.set_state( job_attrs[ 'state' ] )
- imported_job.imported = True
- trans.sa_session.add( imported_job )
- trans.sa_session.flush()
-
- class HistoryDatasetAssociationIDEncoder( simplejson.JSONEncoder ):
- """ Custom JSONEncoder for a HistoryDatasetAssociation that encodes an HDA as its ID. """
- def default( self, obj ):
- """ Encode an HDA, default encoding for everything else. """
- if isinstance( obj, model.HistoryDatasetAssociation ):
- return obj.id
- return simplejson.JSONEncoder.default( self, obj )
+ # If no source to create archive from, show form to upload archive or specify URL.
+ if not archive_source:
+ return trans.show_form(
+ web.FormBuilder( web.url_for(), "Import a History from an Archive", submit_text="Submit" ) \
+ .add_input( "text", "Archived History URL", "archive_url", value="", error=None )
+ # TODO: add support for importing via a file.
+ #.add_input( "file", "Archived History File", "archive_file", value=None, error=None )
+ )
- # Set parameters. May be useful to look at metadata.py for creating parameters.
- # TODO: there may be a better way to set parameters, e.g.:
- # for name, value in tool.params_to_strings( incoming, trans.app ).iteritems():
- # job.add_parameter( name, value )
- # to make this work, we'd need to flesh out the HDA objects. The code below is
- # relatively similar.
- for name, value in job_attrs[ 'params' ].items():
- # Transform parameter values when necessary.
- if isinstance( value, model.HistoryDatasetAssociation ):
- # HDA input: use hid to find input.
- input_hda = trans.sa_session.query( model.HistoryDatasetAssociation ) \
- .filter_by( history=new_history, hid=value.hid ).first()
- value = input_hda.id
- #print "added parameter %s-->%s to job %i" % ( name, value, imported_job.id )
- imported_job.add_parameter( name, to_json_string( value, cls=HistoryDatasetAssociationIDEncoder ) )
-
- # TODO: Connect jobs to input datasets.
-
- # Connect jobs to output datasets.
- for output_hid in job_attrs[ 'output_datasets' ]:
- #print "%s job has output dataset %i" % (imported_job.id, output_hid)
- output_hda = trans.sa_session.query( model.HistoryDatasetAssociation ) \
- .filter_by( history=new_history, hid=output_hid ).first()
- if output_hda:
- imported_job.add_output_dataset( output_hda.name, output_hda )
- trans.sa_session.flush()
-
- # Cleanup.
- if os.path.exists( temp_output_dir ):
- shutil.rmtree( temp_output_dir )
-
- return trans.show_ok_message( message="History '%s' has been imported. " % history_attrs['name'] )
- except Exception, e:
- return trans.show_error_message( 'Error importing history archive. ' + str( e ) )
-
- return trans.show_form(
- web.FormBuilder( web.url_for(), "Import a History from an Archive", submit_text="Submit" )
- .add_input( "file", "Archived History File", "archived_history", value=None, error=None )
- )
-
+ # Run job to do import.
+ history_imp_tool = trans.app.toolbox.tools_by_id[ '__IMPORT_HISTORY__' ]
+ incoming = { '__ARCHIVE_SOURCE__' : archive_source, '__ARCHIVE_TYPE__' : archive_type }
+ history_imp_tool.execute( trans, incoming=incoming )
+ return trans.show_message( "Importing history from '%s'. \
+ This history will be visible when the import is complete" % archive_source )
+
@web.expose
def export_archive( self, trans, id=None, gzip=True, include_hidden=False, include_deleted=False ):
""" Export a history to an archive. """
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -608,6 +608,7 @@ class JobWrapper( object ):
if self.app.config.set_metadata_externally:
self.external_output_metadata.cleanup_external_metadata( self.sa_session )
galaxy.tools.imp_exp.JobExportHistoryArchiveWrapper( self.job_id ).cleanup_after_job( self.sa_session )
+ galaxy.tools.imp_exp.JobImportHistoryArchiveWrapper( self.job_id ).cleanup_after_job( self.sa_session )
except:
log.exception( "Unable to cleanup job %d" % self.job_id )
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -227,7 +227,13 @@ class JobExportHistoryArchive( object ):
self.history_attrs_filename = history_attrs_filename
self.datasets_attrs_filename = datasets_attrs_filename
self.jobs_attrs_filename = jobs_attrs_filename
-
+
+class JobImportHistoryArchive( object ):
+ def __init__( self, job=None, history=None, archive_dir=None ):
+ self.job = job
+ self.history = history
+ self.archive_dir=archive_dir
+
class Group( object ):
def __init__( self, name = None ):
self.name = name
@@ -244,6 +250,7 @@ class History( object, UsesAnnotations )
self.name = name or "Unnamed history"
self.deleted = False
self.purged = False
+ self.importing = False
self.genome_build = None
self.published = False
# Relationships
--- a/lib/galaxy/tools/imp_exp/__init__.py
+++ b/lib/galaxy/tools/imp_exp/__init__.py
@@ -2,7 +2,7 @@ import os, shutil, logging, tempfile, si
from galaxy import model
from galaxy.web.framework.helpers import to_unicode
from galaxy.model.item_attrs import UsesAnnotations
-from galaxy.util.json import to_json_string
+from galaxy.util.json import *
from galaxy.web.base.controller import UsesHistory
log = logging.getLogger(__name__)
@@ -26,21 +26,252 @@ def load_history_imp_exp_tools( toolbox
</outputs></tool>
"""
+
+ # Load export tool.
tmp_name = tempfile.NamedTemporaryFile()
tmp_name.write( tool_xml_text )
tmp_name.flush()
history_exp_tool = toolbox.load_tool( tmp_name.name )
toolbox.tools_by_id[ history_exp_tool.id ] = history_exp_tool
log.debug( "Loaded history export tool: %s", history_exp_tool.id )
+
+ # Load import tool.
+ tool_xml = os.path.join( os.getcwd(), "lib/galaxy/tools/imp_exp/imp_history_from_archive.xml" )
+ history_imp_tool = toolbox.load_tool( tool_xml )
+ toolbox.tools_by_id[ history_imp_tool.id ] = history_imp_tool
+ log.debug( "Loaded history import tool: %s", history_imp_tool.id )
+
+class JobImportHistoryArchiveWrapper( object, UsesHistory, UsesAnnotations ):
+ """
+ Class provides support for performing jobs that import a history from
+ an archive.
+ """
+ def __init__( self, job_id ):
+ self.job_id = job_id
+
+ def cleanup_after_job( self, db_session ):
+ """ Set history, datasets, and jobs' attributes and clean up archive directory. """
+
+ #
+ # Helper methods.
+ #
+
+ def file_in_dir( file_path, a_dir ):
+ """ Returns true if file is in directory. """
+ abs_file_path = os.path.abspath( file_path )
+ return os.path.split( abs_file_path )[0] == a_dir
+
+ def read_file_contents( file_path ):
+ """ Read contents of a file. """
+ fp = open( file_path, 'rb' )
+ buffsize = 1048576
+ file_contents = ''
+ try:
+ while True:
+ file_contents += fp.read( buffsize )
+ if not file_contents or len( file_contents ) % buffsize != 0:
+ break
+ except OverflowError:
+ pass
+ fp.close()
+ return file_contents
+
+ def get_tag_str( tag, value ):
+ """ Builds a tag string for a tag, value pair. """
+ if not value:
+ return tag
+ else:
+ return tag + ":" + value
+
+ #
+ # Import history.
+ #
+
+ jiha = db_session.query( model.JobImportHistoryArchive ).filter_by( job_id=self.job_id ).first()
+ if jiha:
+ try:
+ archive_dir = jiha.archive_dir
+ user = jiha.job.user
+
+ #
+ # Create history.
+ #
+ history_attr_file_name = os.path.join( archive_dir, 'history_attrs.txt')
+ history_attr_str = read_file_contents( history_attr_file_name )
+ history_attrs = from_json_string( history_attr_str )
+
+ # Create history.
+ new_history = model.History( name='imported from archive: %s' % history_attrs['name'].encode( 'utf-8' ), \
+ user=user )
+ new_history.importing = True
+ new_history.hid_counter = history_attrs['hid_counter']
+ new_history.genome_build = history_attrs['genome_build']
+ db_session.add( new_history )
+ jiha.history = new_history
+ db_session.flush()
+
+ # Add annotation, tags.
+ if user:
+ self.add_item_annotation( db_session, user, new_history, history_attrs[ 'annotation' ] )
+ """
+ TODO: figure out to how add tags to item.
+ for tag, value in history_attrs[ 'tags' ].items():
+ trans.app.tag_handler.apply_item_tags( trans, trans.user, new_history, get_tag_str( tag, value ) )
+ """
+
+ #
+ # Create datasets.
+ #
+ datasets_attrs_file_name = os.path.join( archive_dir, 'datasets_attrs.txt')
+ datasets_attr_str = read_file_contents( datasets_attrs_file_name )
+ datasets_attrs = from_json_string( datasets_attr_str )
+
+ # Get counts of how often each dataset file is used; a file can
+ # be linked to multiple dataset objects (HDAs).
+ datasets_usage_counts = {}
+ for dataset_attrs in datasets_attrs:
+ temp_dataset_file_name = \
+ os.path.abspath( os.path.join( archive_dir, dataset_attrs['file_name'] ) )
+ if ( temp_dataset_file_name not in datasets_usage_counts ):
+ datasets_usage_counts[ temp_dataset_file_name ] = 0
+ datasets_usage_counts[ temp_dataset_file_name ] += 1
+
+ # Create datasets.
+ for dataset_attrs in datasets_attrs:
+ metadata = dataset_attrs['metadata']
+
+ # Create dataset and HDA.
+ hda = model.HistoryDatasetAssociation( name = dataset_attrs['name'].encode( 'utf-8' ),
+ extension = dataset_attrs['extension'],
+ info = dataset_attrs['info'].encode( 'utf-8' ),
+ blurb = dataset_attrs['blurb'],
+ peek = dataset_attrs['peek'],
+ designation = dataset_attrs['designation'],
+ visible = dataset_attrs['visible'],
+ dbkey = metadata['dbkey'],
+ metadata = metadata,
+ history = new_history,
+ create_dataset = True,
+ sa_session = db_session )
+ hda.state = hda.states.OK
+ db_session.add( hda )
+ db_session.flush()
+ new_history.add_dataset( hda, genome_build = None )
+ hda.hid = dataset_attrs['hid'] # Overwrite default hid set when HDA added to history.
+ # TODO: Is there a way to recover permissions? Is this needed?
+ #permissions = trans.app.security_agent.history_get_default_permissions( new_history )
+ #trans.app.security_agent.set_all_dataset_permissions( hda.dataset, permissions )
+ db_session.flush()
+
+ # Do security check and move/copy dataset data.
+ temp_dataset_file_name = \
+ os.path.abspath( os.path.join( archive_dir, dataset_attrs['file_name'] ) )
+ if not file_in_dir( temp_dataset_file_name, os.path.join( archive_dir, "datasets" ) ):
+ raise Exception( "Invalid dataset path: %s" % temp_dataset_file_name )
+ if datasets_usage_counts[ temp_dataset_file_name ] == 1:
+ shutil.move( temp_dataset_file_name, hda.file_name )
+ else:
+ datasets_usage_counts[ temp_dataset_file_name ] -= 1
+ shutil.copyfile( temp_dataset_file_name, hda.file_name )
+
+ # Set tags, annotations.
+ if user:
+ self.add_item_annotation( db_session, user, hda, dataset_attrs[ 'annotation' ] )
+ # TODO: Set tags.
+ """
+ for tag, value in dataset_attrs[ 'tags' ].items():
+ trans.app.tag_handler.apply_item_tags( trans, trans.user, hda, get_tag_str( tag, value ) )
+ db_session.flush()
+ """
+
+ #
+ # Create jobs.
+ #
+
+ # Read jobs attributes.
+ jobs_attr_file_name = os.path.join( archive_dir, 'jobs_attrs.txt')
+ jobs_attr_str = read_file_contents( jobs_attr_file_name )
+
+ # Decode jobs attributes.
+ def as_hda( obj_dct ):
+ """ Hook to 'decode' an HDA; method uses history and HID to get the HDA represented by
+ the encoded object. This only works because HDAs are created above. """
+ if obj_dct.get( '__HistoryDatasetAssociation__', False ):
+ return db_session.query( model.HistoryDatasetAssociation ) \
+ .filter_by( history=new_history, hid=obj_dct['hid'] ).first()
+ return obj_dct
+ jobs_attrs = from_json_string( jobs_attr_str, object_hook=as_hda )
+
+ # Create each job.
+ for job_attrs in jobs_attrs:
+ imported_job = model.Job()
+ imported_job.user = user
+ # TODO: set session?
+ # imported_job.session = trans.get_galaxy_session().id
+ imported_job.history = new_history
+ imported_job.tool_id = job_attrs[ 'tool_id' ]
+ imported_job.tool_version = job_attrs[ 'tool_version' ]
+ imported_job.set_state( job_attrs[ 'state' ] )
+ imported_job.imported = True
+ db_session.add( imported_job )
+ db_session.flush()
+
+ class HistoryDatasetAssociationIDEncoder( simplejson.JSONEncoder ):
+ """ Custom JSONEncoder for a HistoryDatasetAssociation that encodes an HDA as its ID. """
+ def default( self, obj ):
+ """ Encode an HDA, default encoding for everything else. """
+ if isinstance( obj, model.HistoryDatasetAssociation ):
+ return obj.id
+ return simplejson.JSONEncoder.default( self, obj )
+
+ # Set parameters. May be useful to look at metadata.py for creating parameters.
+ # TODO: there may be a better way to set parameters, e.g.:
+ # for name, value in tool.params_to_strings( incoming, trans.app ).iteritems():
+ # job.add_parameter( name, value )
+ # to make this work, we'd need to flesh out the HDA objects. The code below is
+ # relatively similar.
+ for name, value in job_attrs[ 'params' ].items():
+ # Transform parameter values when necessary.
+ if isinstance( value, model.HistoryDatasetAssociation ):
+ # HDA input: use hid to find input.
+ input_hda = db_session.query( model.HistoryDatasetAssociation ) \
+ .filter_by( history=new_history, hid=value.hid ).first()
+ value = input_hda.id
+ #print "added parameter %s-->%s to job %i" % ( name, value, imported_job.id )
+ imported_job.add_parameter( name, to_json_string( value, cls=HistoryDatasetAssociationIDEncoder ) )
+
+ # TODO: Connect jobs to input datasets.
+
+ # Connect jobs to output datasets.
+ for output_hid in job_attrs[ 'output_datasets' ]:
+ #print "%s job has output dataset %i" % (imported_job.id, output_hid)
+ output_hda = db_session.query( model.HistoryDatasetAssociation ) \
+ .filter_by( history=new_history, hid=output_hid ).first()
+ if output_hda:
+ imported_job.add_output_dataset( output_hda.name, output_hda )
+
+ # Done importing.
+ new_history.importing = False
+
+ db_session.flush()
+
+ # Cleanup.
+ if os.path.exists( archive_dir ):
+ shutil.rmtree( archive_dir )
+ except Exception, e:
+ jiha.job.stderr += "Error cleaning up history import job: %s" % e
+ db_session.flush()
class JobExportHistoryArchiveWrapper( object, UsesHistory, UsesAnnotations ):
- """ Class provides support for performing jobs that export a history to an archive. """
+ """
+ Class provides support for performing jobs that export a history to an
+ archive.
+ """
def __init__( self, job_id ):
self.job_id = job_id
# TODO: should use db_session rather than trans in this method.
def setup_job( self, trans, jeha, include_hidden=False, include_deleted=False ):
- # jeha = job_export_history_archive for the job.
""" Perform setup for job to export a history into an archive. Method generates
attribute files for export, sets the corresponding attributes in the jeha
object, and returns a command line for running the job. The command line
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1904,6 +1904,9 @@ class SetMetadataTool( Tool ):
class ExportHistoryTool( Tool ):
tool_type = 'export_history'
+
+class ImportHistoryTool( Tool ):
+ tool_type = 'import_history'
# Populate tool_type to ToolClass mappings
tool_types = {}
--- a/lib/galaxy/tools/actions/history_imp_exp.py
+++ b/lib/galaxy/tools/actions/history_imp_exp.py
@@ -1,10 +1,56 @@
+import tempfile
from __init__ import ToolAction
from galaxy.util.odict import odict
-from galaxy.tools.imp_exp import JobExportHistoryArchiveWrapper
+from galaxy.tools.imp_exp import *
import logging
log = logging.getLogger( __name__ )
+class ImportHistoryToolAction( ToolAction ):
+ """Tool action used for importing a history to an archive. """
+
+ def execute( self, tool, trans, incoming = {}, set_output_hid = False, overwrite = True ):
+ #
+ # Create job.
+ #
+ job = trans.app.model.Job()
+ job.session_id = trans.get_galaxy_session().id
+ job.history_id = trans.history.id
+ job.tool_id = tool.id
+ job.user_id = trans.user.id
+ start_job_state = job.state #should be job.states.NEW
+ job.state = job.states.WAITING #we need to set job state to something other than NEW, or else when tracking jobs in db it will be picked up before we have added input / output parameters
+ trans.sa_session.add( job )
+ trans.sa_session.flush() #ensure job.id are available
+
+ #
+ # Setup job and job wrapper.
+ #
+
+ # Add association for keeping track of job, history relationship.
+ archive_dir = tempfile.mkdtemp()
+ jiha = trans.app.model.JobImportHistoryArchive( job=job, archive_dir=archive_dir )
+ trans.sa_session.add( jiha )
+ job_wrapper = JobImportHistoryArchiveWrapper( job )
+
+ #
+ # Add parameters to job_parameter table.
+ #
+
+ # Set additional parameters.
+ incoming[ '__DEST_DIR__' ] = jiha.archive_dir
+ for name, value in tool.params_to_strings( incoming, trans.app ).iteritems():
+ job.add_parameter( name, value )
+
+ job.state = start_job_state #job inputs have been configured, restore initial job state
+ trans.sa_session.flush()
+
+ # Queue the job for execution
+ trans.app.job_queue.put( job.id, tool )
+ trans.log_event( "Added import history job to the job queue, id: %s" % str(job.id), tool_id=job.tool_id )
+
+ return job, odict()
+
class ExportHistoryToolAction( ToolAction ):
"""Tool action used for exporting a history to an archive. """
@@ -30,6 +76,7 @@ class ExportHistoryToolAction( ToolActio
job.session_id = trans.get_galaxy_session().id
job.history_id = trans.history.id
job.tool_id = tool.id
+ job.user_id = trans.user.id
start_job_state = job.state #should be job.states.NEW
job.state = job.states.WAITING #we need to set job state to something other than NEW, or else when tracking jobs in db it will be picked up before we have added input / output parameters
trans.sa_session.add( job )
--- /dev/null
+++ b/lib/galaxy/tools/imp_exp/imp_history_from_archive.xml
@@ -0,0 +1,10 @@
+<tool id="__IMPORT_HISTORY__" name="Import History" version="0.1" tool_type="import_history">
+ <type class="ImportHistoryTool" module="galaxy.tools"/>
+ <action module="galaxy.tools.actions.history_imp_exp" class="ImportHistoryToolAction"/>
+ <command interpreter="python">unpack_tar_gz_archive.py $__ARCHIVE_SOURCE__ $__DEST_DIR__ --$__ARCHIVE_TYPE__</command>
+ <inputs>
+ <param name="__ARCHIVE_SOURCE__" type="text"/>
+ <param name="__ARCHIVE_TYPE__" type="text"/>
+ <param name="__DEST_DIR__" type="text"/>
+ </inputs>
+</tool>
--- a/templates/root/index.mako
+++ b/templates/root/index.mako
@@ -53,10 +53,10 @@
galaxy_main.location = "${h.url_for( controller='history', action='delete_current' )}";
}
},
- ##"Other Actions": null,
- ##"Import from File": function() {
- ## galaxy_main.location = "${h.url_for( controller='history', action='import_archive' )}";
- ##}
+ "Other Actions": null,
+ "Import from File": function() {
+ galaxy_main.location = "${h.url_for( controller='history', action='import_archive' )}";
+ }
});
// Init tool options.
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -77,6 +77,7 @@ History.table = Table( "history", metada
Column( "hid_counter", Integer, default=1 ),
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ),
+ Column( "importing", Boolean, index=True, default=False ),
Column( "genome_build", TrimmedString( 40 ) ),
Column( "importable", Boolean, default=False ),
Column( "slug", TEXT, index=True ),
@@ -384,6 +385,13 @@ JobExportHistoryArchive.table = Table( "
Column( "jobs_attrs_filename", TEXT )
)
+JobImportHistoryArchive.table = Table( "job_import_history_archive", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "job_id", Integer, ForeignKey( "job.id" ), index=True ),
+ Column( "history_id", Integer, ForeignKey( "history.id" ), index=True ),
+ Column( "archive_dir", TEXT )
+ )
+
PostJobAction.table = Table("post_job_action", metadata,
Column("id", Integer, primary_key=True),
Column("workflow_step_id", Integer, ForeignKey( "workflow_step.id" ), index=True, nullable=False),
@@ -1220,6 +1228,9 @@ assign_mapper( context, JobExportHistory
properties=dict( job = relation( Job ),
history = relation( History ),
dataset = relation( Dataset ) ) )
+
+assign_mapper( context, JobImportHistoryArchive, JobImportHistoryArchive.table,
+ properties=dict( job = relation( Job ), history = relation( History ) ) )
assign_mapper( context, PostJobAction, PostJobAction.table,
properties=dict(workflow_step = relation( WorkflowStep, backref='post_job_actions', primaryjoin=(WorkflowStep.table.c.id == PostJobAction.table.c.workflow_step_id))))
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0060_history_archive_import.py
@@ -0,0 +1,72 @@
+"""
+Migration script to create column and table for importing histories from
+file archives.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+# Columns to add.
+
+importing_col = Column( "importing", Boolean, index=True, default=False )
+ldda_parent_col = Column( "ldda_parent_id", Integer, ForeignKey( "library_dataset_dataset_association.id" ), index=True )
+
+# Table to add.
+
+JobImportHistoryArchive_table = Table( "job_import_history_archive", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "job_id", Integer, ForeignKey( "job.id" ), index=True ),
+ Column( "history_id", Integer, ForeignKey( "history.id" ), index=True ),
+ Column( "archive_dir", TEXT )
+ )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ # Add column to history table and initialize.
+ try:
+ History_table = Table( "history", metadata, autoload=True )
+ importing_col.create( History_table )
+ assert importing_col is History_table.c.importing
+
+ # Initialize column to false.
+ if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ default_false = "0"
+ elif migrate_engine.name == 'postgres':
+ default_false = "false"
+ db_session.execute( "UPDATE history SET importing=%s" % default_false )
+ except Exception, e:
+ print str(e)
+ log.debug( "Adding column 'importing' to history table failed: %s" % str( e ) )
+
+ # Create job_import_history_archive table.
+ try:
+ JobImportHistoryArchive_table.create()
+ except Exception, e:
+ log.debug( "Creating job_import_history_archive table failed: %s" % str( e ) )
+
+def downgrade():
+ metadata.reflect()
+
+ # Drop 'importing' column from history table.
+ try:
+ History_table = Table( "history", metadata, autoload=True )
+ importing_col = History_table.c.importing
+ importing_col.drop()
+ except Exception, e:
+ log.debug( "Dropping column 'importing' from history table failed: %s" % ( str( e ) ) )
+
+ # Drop job_import_history_archive table.
+ try:
+ JobImportHistoryArchive_table.drop()
+ except Exception, e:
+ log.debug( "Dropping job_import_history_archive table failed: %s" % str( e ) )
--- /dev/null
+++ b/lib/galaxy/tools/imp_exp/unpack_tar_gz_archive.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+"""
+Unpack a tar or tar.gz archive into a directory.
+
+usage: %prog archive_source dest_dir
+ --[url|file] source type, either a URL or a file.
+"""
+
+import sys, optparse, tarfile, tempfile, urllib2, math
+
+# Set max size of archive/file that will be handled to be 100 GB. This is
+# arbitrary and should be adjusted as needed.
+MAX_SIZE = 100 * math.pow( 2, 30 )
+
+def url_to_file( url, dest_file ):
+ """
+ Transfer a file from a remote URL to a temporary file.
+ """
+ try:
+ url_reader = urllib2.urlopen( url )
+ CHUNK = 10 * 1024 # 10k
+ total = 0
+ fp = open( dest_file, 'wb')
+ while True:
+ chunk = url_reader.read( CHUNK )
+ if not chunk:
+ break
+ fp.write( chunk )
+ total += CHUNK
+ if total > MAX_SIZE:
+ break
+ fp.close()
+ return dest_file
+ except Exception, e:
+ print "Exception getting file from URL: %s" % e, sys.stderr
+ return None
+
+def unpack_archive( archive_file, dest_dir ):
+ """
+ Unpack a tar and/or gzipped archive into a destination directory.
+ """
+ archive_fp = tarfile.open( archive_file, mode='r:gz' )
+ archive_fp.extractall( path=dest_dir )
+ archive_fp.close()
+
+if __name__ == "__main__":
+ # Parse command line.
+ parser = optparse.OptionParser()
+ parser.add_option( '-U', '--url', dest='is_url', action="store_true", help='Source is a URL.' )
+ parser.add_option( '-F', '--file', dest='is_file', action="store_true", help='Source is a URL.' )
+ (options, args) = parser.parse_args()
+ is_url = bool( options.is_url )
+ is_file = bool( options.is_file )
+ archive_source, dest_dir = args
+
+ try:
+ # Get archive from URL.
+ if is_url:
+ archive_file = url_to_file( archive_source, tempfile.NamedTemporaryFile( dir=dest_dir ).name )
+ elif is_file:
+ archive_file = archive_source
+
+ # Unpack archive.
+ unpack_archive( archive_file, dest_dir )
+ except Exception, e:
+ print "Error unpacking tar/gz archive: %s" % e, sys.stderr
1
0