galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
August 2013
- 1 participants
- 149 discussions
commit/galaxy-central: jgoecks: Tophat2 wrapper enhancements: (a) better error handling; (b) include alignment statistics in output; and (c) document compatible tool versions.
by commits-noreply@bitbucket.org 05 Aug '13
by commits-noreply@bitbucket.org 05 Aug '13
05 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/20e2d056b843/
Changeset: 20e2d056b843
User: jgoecks
Date: 2013-08-05 23:08:28
Summary: Tophat2 wrapper enhancements: (a) better error handling; (b) include alignment statistics in output; and (c) document compatible tool versions.
Affected #: 1 file
diff -r af1daa86ba5b713240fb3f7ccd607f3adb8c05a7 -r 20e2d056b843504ea77c49adc0cb08818bb7bdc6 tools/ngs_rna/tophat2_wrapper.xml
--- a/tools/ngs_rna/tophat2_wrapper.xml
+++ b/tools/ngs_rna/tophat2_wrapper.xml
@@ -1,5 +1,5 @@
-<tool id="tophat2" name="Tophat2" version="0.5">
- <!-- Wrapper compatible with Tophat version 2.0.0 -->
+<tool id="tophat2" name="Tophat2" version="0.6">
+ <!-- Wrapper compatible with Tophat version 2.0.0+ --><description>Gapped-read mapper for RNA-seq data</description><version_command>tophat2 --version</version_command><requirements>
@@ -268,11 +268,12 @@
</inputs><stdio>
- <regex match="Exception" source="both" level="fatal" description="Tool exception"/>
+ <regex match="Exception|Error" source="both" level="fatal" description="Tool execution failed"/><regex match=".*" source="both" level="log" description="tool progress"/></stdio><outputs>
+ <data format="txt" name="align_summary" label="${tool.name} on ${on_string}: align_summary" from_work_dir="tophat_out/align_summary.txt"/><data format="tabular" name="fusions" label="${tool.name} on ${on_string}: fusions" from_work_dir="tophat_out/fusions.out"><filter>(params['settingsType'] == 'full' and params['fusion_search']['do_search'] == 'Yes')</filter></data>
@@ -312,6 +313,7 @@
</actions></macro></macros>
+
<tests><!-- Test base-space single-end reads with pre-built index and preset parameters --><test>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
05 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/af1daa86ba5b/
Changeset: af1daa86ba5b
User: guerler
Date: 2013-08-05 23:04:50
Summary: Pack JS-scripts
Affected #: 5 files
diff -r ba8555d1fed4b95e2882afd33c45be3300c00ded -r af1daa86ba5b713240fb3f7ccd607f3adb8c05a7 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.attributes);a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}if(b.title){a+=" tooltip"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this)},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(PopupMenu.templates.menu({options:this.options,id:this.$button.attr("id")}));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width(),a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this,a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?(a):(this.options.length);this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if((_.has(this.options[a],"html"))&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.templates={menu:Handlebars.templates["template-popupmenu-menu"]};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ No newline at end of file
+var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.attributes);a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}if(b.title){a+=" tooltip"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this)},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(this.template(this.$button.attr("id"),this.options));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this;var a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"},template:function(e,b){var a='<ul id="'+e+'-menu" class="dropdown-menu">';if(b.length>0){for(var c in b){var d=b[c];if(d.divider){a+='<li class="divider"></li>'}else{if(d.header){a+='<li class="head"><a href="javascript:void(0);">'+d.html+"</a></li>"}else{if(d.href){a+='<li><a href="'+d.href+'"';a+='target="'+d.target+'"'}else{a+='<li><a href="javascript:void(0);"'}a+='class="popupmenu-option">';if(d.checked){a+='<span class="fa-icon-ok"></span>'}a+=d.html}}}}else{a+="<li>No Options.</li>"}return a+"</ul>"}});PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ No newline at end of file
diff -r ba8555d1fed4b95e2882afd33c45be3300c00ded -r af1daa86ba5b713240fb3f7ccd607f3adb8c05a7 static/scripts/packed/viz/circster.js
--- a/static/scripts/packed/viz/circster.js
+++ b/static/scripts/packed/viz/circster.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","libs/d3","viz/visualization"],function(f,k,h){var l=Backbone.Model.extend({is_visible:function(p,m){var n=p.getBoundingClientRect(),o=$("svg")[0].getBoundingClientRect();if(n.right<0||n.left>o.right||n.bottom<0||n.top>o.bottom){return false}return true}});var g={drawTicks:function(q,p,u,o,m){var t=q.append("g").selectAll("g").data(p).enter().append("g").selectAll("g").data(u).enter().append("g").attr("class","tick").attr("transform",function(v){return"rotate("+(v.angle*180/Math.PI-90)+")translate("+v.radius+",0)"});var s=[],r=[],n=function(v){return v.angle>Math.PI?"end":null};if(m){s=[0,0,0,-4];r=[4,0,"",".35em"];n=null}else{s=[1,0,4,0];r=[0,4,".35em",""]}t.append("line").attr("x1",s[0]).attr("y1",s[1]).attr("x2",s[2]).attr("y1",s[3]).style("stroke","#000");t.append("text").attr("x",r[0]).attr("y",r[1]).attr("dx",r[2]).attr("dy",r[3]).attr("text-anchor",n).attr("transform",o).text(function(v){return v.label})},formatNum:function(n,m){if(m===undefined){m=2}var p=null;if(n<1){p=n.toPrecision(m)}else{var o=Math.round(n.toPrecision(m));if(n<1000){p=o}else{if(n<1000000){p=Math.round((o/1000).toPrecision(3)).toFixed(0)+"K"}else{if(n<1000000000){p=Math.round((o/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return p}};var c=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(m){this.total_gap=m.total_gap;this.genome=m.genome;this.dataset_arc_height=m.dataset_arc_height;this.track_gap=10;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("tracks").on("add",this.add_track,this);this.model.get("tracks").on("remove",this.remove_track,this);this.get_circular_tracks()},get_circular_tracks:function(){return this.model.get("tracks").filter(function(m){return m.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("tracks").filter(function(m){return m.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var n=this.get_circular_tracks();dataset_arc_height=this.dataset_arc_height,min_dimension=Math.min(this.$el.width(),this.$el.height()),radius_start=min_dimension/2-n.length*(this.dataset_arc_height+this.track_gap)-(this.label_arc_height+this.track_gap),tracks_start_radii=k.range(radius_start,min_dimension/2,this.dataset_arc_height+this.track_gap);var m=this;return f.map(tracks_start_radii,function(o){return[o,o+m.dataset_arc_height]})},render:function(){var v=this,p=this.dataset_arc_height,m=v.$el.width(),u=v.$el.height(),r=this.get_circular_tracks(),o=this.get_chord_tracks(),q=this.get_tracks_bounds(),n=k.select(v.$el[0]).append("svg").attr("width",m).attr("height",u).attr("pointer-events","all").append("svg:g").call(k.behavior.zoom().on("zoom",function(){var w=k.event.scale;n.attr("transform","translate("+k.event.translate+") scale("+w+")");if(v.scale!==w){if(v.zoom_drag_timeout){clearTimeout(v.zoom_drag_timeout)}v.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+m/2+","+u/2+")").append("svg:g").attr("class","tracks");this.circular_views=r.map(function(x,y){var w=new d({el:n.append("g")[0],track:x,radius_bounds:q[y],genome:v.genome,total_gap:v.total_gap});w.render();return w});this.chords_views=o.map(function(x){var w=new i({el:n.append("g")[0],track:x,radius_bounds:q[0],genome:v.genome,total_gap:v.total_gap});w.render();return w});var t=this.circular_views[this.circular_views.length-1].radius_bounds[1],s=[t,t+this.label_arc_height];this.label_track_view=new b({el:n.append("g")[0],track:new c(),radius_bounds:s,genome:v.genome,total_gap:v.total_gap});this.label_track_view.render()},add_track:function(s){if(s.get("track_type")==="DiagonalHeatmapTrack"){var o=this.circular_views[0].radius_bounds,r=new i({el:k.select("g.tracks").append("g")[0],track:s,radius_bounds:o,genome:this.genome,total_gap:this.total_gap});r.render();this.chords_views.push(r)}else{var q=this.get_tracks_bounds();f.each(this.circular_views,function(t,u){t.update_radius_bounds(q[u])});f.each(this.chords_views,function(t){t.update_radius_bounds(q[0])});var p=this.circular_views.length,m=new d({el:k.select("g.tracks").append("g")[0],track:s,radius_bounds:q[p],genome:this.genome,total_gap:this.total_gap});m.render();this.circular_views.push(m);var n=q[q.length-1];n[1]=n[0];this.label_track_view.update_radius_bounds(n)}},remove_track:function(n,p,o){var m=this.circular_views[o.index];this.circular_views.splice(o.index,1);m.$el.remove();var q=this.get_tracks_bounds();f.each(this.circular_views,function(r,s){r.update_radius_bounds(q[s])})}});var j=Backbone.View.extend({tagName:"g",initialize:function(m){this.bg_stroke="ccc";this.loading_bg_fill="000";this.bg_fill="ccc";this.total_gap=m.total_gap;this.track=m.track;this.radius_bounds=m.radius_bounds;this.genome=m.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=k.select(this.$el[0])},get_fill_color:function(){var m=this.track.get("config").get_value("block_color");if(!m){m=this.track.get("config").get_value("color")}return m},render:function(){var q=this.parent_elt;if(!q){console.log("no parent elt")}var p=this.chroms_layout,s=k.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),m=q.selectAll("g").data(p).enter().append("svg:g"),o=m.append("path").attr("d",s).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);o.append("title").text(function(u){return u.data.chrom});var n=this,r=n.track.get("data_manager"),t=(r?r.data_is_ready():true);$.when(t).then(function(){$.when(n._render_data(q)).then(function(){o.style("fill",n.bg_fill);n.render_labels()})})},render_labels:function(){},update_radius_bounds:function(n){this.radius_bounds=n;var m=k.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",m);this._transition_chrom_data();this._transition_labels()},update_scale:function(p){var o=this.scale;this.scale=p;if(p<=o){return}var n=this,m=new l();this.parent_elt.selectAll("path.chrom-data").filter(function(r,q){return m.is_visible(this)}).each(function(w,s){var v=k.select(this),r=v.attr("chrom"),u=n.genome.get_chrom_region(r),t=n.track.get("data_manager"),q;if(!t.can_get_more_detailed_data(u)){return}q=n.track.get("data_manager").get_more_detailed_data(u,"Coverage",0,p);$.when(q).then(function(z){v.remove();n._update_data_bounds();var y=f.find(n.chroms_layout,function(A){return A.data.chrom===r});var x=n.get_fill_color();n._render_chrom_data(n.parent_elt,y,z).style("stroke",x).style("fill",x)})});return n},_transition_chrom_data:function(){var n=this.track,p=this.chroms_layout,m=this.parent_elt.selectAll("g>path.chrom-data"),q=m[0].length;if(q>0){var o=this;$.when(n.get("data_manager").get_genome_wide_data(this.genome)).then(function(s){var r=f.reject(f.map(s,function(t,u){var v=null,w=o._get_path_function(p[u],t);if(w){v=w(t.data)}return v}),function(t){return t===null});m.each(function(u,t){k.select(this).transition().duration(1000).attr("d",r[t])})})}},_transition_labels:function(){},_update_data_bounds:function(){var m=this.data_bounds;this.data_bounds=this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));if(this.data_bounds[0]<m[0]||this.data_bounds[1]>m[1]){this._transition_chrom_data()}},_render_data:function(p){var o=this,n=this.chroms_layout,m=this.track,q=$.Deferred();$.when(m.get("data_manager").get_genome_wide_data(this.genome)).then(function(s){o.data_bounds=o.get_data_bounds(s);layout_and_data=f.zip(n,s),chroms_data_layout=f.map(layout_and_data,function(t){var u=t[0],v=t[1];return o._render_chrom_data(p,u,v)});var r=o.get_fill_color();o.parent_elt.selectAll("path.chrom-data").style("stroke",r).style("fill",r);q.resolve(p)});return q},_render_chrom_data:function(m,n,o){},_get_path_function:function(n,m){},_chroms_layout:function(){var n=this.genome.get_chroms_info(),p=k.layout.pie().value(function(r){return r.len}).sort(null),q=p(n),m=this.total_gap/n.length,o=f.map(q,function(t,s){var r=t.endAngle-m;t.endAngle=(r>t.startAngle?r:t.startAngle);return t});return o}});var b=j.extend({initialize:function(m){j.prototype.initialize.call(this,m);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="fff";this.bg_fill="fff";this.min_arc_len=0.08},_render_data:function(o){var n=this,m=o.selectAll("g");m.selectAll("path").attr("id",function(s){return"label-"+s.data.chrom});m.append("svg:text").filter(function(s){return s.endAngle-s.startAngle>n.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("xlink:href",function(s){return"#label-"+s.data.chrom}).attr("startOffset","25%").attr("font-weight","bold").text(function(s){return s.data.chrom});var p=function(u){var s=(u.endAngle-u.startAngle)/u.value,t=k.range(0,u.value,25000000).map(function(w,x){return{radius:n.innerRadius,angle:w*s+u.startAngle,label:x===0?0:(x%3?null:n.formatNum(w))}});if(t.length<4){t[t.length-1].label=n.formatNum(Math.round((t[t.length-1].angle-u.startAngle)/s))}return t};var r=function(s){return s.angle>Math.PI?"rotate(180)translate(-16)":null};var q=f.filter(this.chroms_layout,function(s){return s.endAngle-s.startAngle>n.min_arc_len});this.drawTicks(this.parent_elt,q,p,r)}});f.extend(b.prototype,g);var e=j.extend({_quantile:function(n,m){n.sort(k.ascending);return k.quantile(n,m)},_render_chrom_data:function(m,p,n){var q=this._get_path_function(p,n);if(!q){return null}var o=m.datum(n.data),r=o.append("path").attr("class","chrom-data").attr("chrom",p.data.chrom).attr("d",q);return r},_get_path_function:function(p,o){if(typeof o==="string"||!o.data||o.data.length===0){return null}var m=k.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var q=k.scale.linear().domain([0,o.data.length]).range([p.startAngle,p.endAngle]);var n=k.svg.line.radial().interpolate("linear").radius(function(r){return m(r[1])}).angle(function(s,r){return q(r)});return k.svg.area.radial().interpolate(n.interpolate()).innerRadius(m(0)).outerRadius(n.radius()).angle(n.angle())},render_labels:function(){var m=this,p=function(){return"rotate(90)"};var o=f.filter(this.chroms_layout,function(q){return q.endAngle-q.startAngle>0.08}),n=f.filter(o,function(r,q){return q%3===0});this.drawTicks(this.parent_elt,n,this._data_bounds_ticks_fn(),p,true)},_transition_labels:function(){if(this.data_bounds.length===0){return}var n=this,p=f.filter(this.chroms_layout,function(q){return q.endAngle-q.startAngle>0.08}),o=f.filter(p,function(r,q){return q%3===0}),m=f.flatten(f.map(o,function(q){return n._data_bounds_ticks_fn()(q)}));this.parent_elt.selectAll("g.tick").data(m).transition().attr("transform",function(q){return"rotate("+(q.angle*180/Math.PI-90)+")translate("+q.radius+",0)"})},_data_bounds_ticks_fn:function(){var m=this;visibleChroms=0;return function(n){return[{radius:m.radius_bounds[0],angle:n.startAngle,label:m.formatNum(m.data_bounds[0])},{radius:m.radius_bounds[1],angle:n.startAngle,label:m.formatNum(m.data_bounds[1])}]}},get_data_bounds:function(m){}});f.extend(e.prototype,g);var d=e.extend({get_data_bounds:function(n){var m=f.flatten(f.map(n,function(o){if(o){return f.map(o.data,function(q){return q[1]})}else{return 0}}));return[f.min(m),this._quantile(m,0.98)]}});var i=j.extend({render:function(){var m=this;$.when(m.track.get("data_manager").data_is_ready()).then(function(){$.when(m.track.get("data_manager").get_genome_wide_data(m.genome)).then(function(p){var o=[],n=m.genome.get_chroms_info();f.each(p,function(t,s){var q=n[s].chrom;var r=f.map(t.data,function(v){var u=m._get_region_angle(q,v[1]),w=m._get_region_angle(v[3],v[4]);return{source:{startAngle:u,endAngle:u+0.01},target:{startAngle:w,endAngle:w+0.01}}});o=o.concat(r)});m.parent_elt.append("g").attr("class","chord").selectAll("path").data(o).enter().append("path").style("fill",m.get_fill_color()).attr("d",k.svg.chord().radius(m.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(m){this.radius_bounds=m;this.parent_elt.selectAll("path").transition().attr("d",k.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(o,m){var n=f.find(this.chroms_layout,function(p){return p.data.chrom===o});return n.endAngle-((n.endAngle-n.startAngle)*(n.data.len-m)/n.data.len)}});return{CircsterView:a}});
\ No newline at end of file
+define(["libs/underscore","libs/d3","viz/visualization"],function(g,l,i){var m=Backbone.Model.extend({is_visible:function(q,n){var o=q.getBoundingClientRect(),p=$("svg")[0].getBoundingClientRect();if(o.right<0||o.left>p.right||o.bottom<0||o.top>p.bottom){return false}return true}});var h={drawTicks:function(r,q,v,p,n){var u=r.append("g").selectAll("g").data(q).enter().append("g").selectAll("g").data(v).enter().append("g").attr("class","tick").attr("transform",function(w){return"rotate("+(w.angle*180/Math.PI-90)+")translate("+w.radius+",0)"});var t=[],s=[],o=function(w){return w.angle>Math.PI?"end":null};if(n){t=[0,0,0,-4];s=[4,0,"",".35em"];o=null}else{t=[1,0,4,0];s=[0,4,".35em",""]}u.append("line").attr("x1",t[0]).attr("y1",t[1]).attr("x2",t[2]).attr("y1",t[3]).style("stroke","#000");u.append("text").attr("x",s[0]).attr("y",s[1]).attr("dx",s[2]).attr("dy",s[3]).attr("text-anchor",o).attr("transform",p).text(function(w){return w.label})},formatNum:function(o,n){if(n===undefined){n=2}var q=null;if(o<1){q=o.toPrecision(n)}else{var p=Math.round(o.toPrecision(n));if(o<1000){q=p}else{if(o<1000000){q=Math.round((p/1000).toPrecision(3)).toFixed(0)+"K"}else{if(o<1000000000){q=Math.round((p/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return q}};var c=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(n){this.total_gap=n.total_gap;this.genome=n.genome;this.dataset_arc_height=n.dataset_arc_height;this.track_gap=10;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("tracks").on("add",this.add_track,this);this.model.get("tracks").on("remove",this.remove_track,this);this.get_circular_tracks()},get_circular_tracks:function(){return this.model.get("tracks").filter(function(n){return n.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("tracks").filter(function(n){return n.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var o=this.get_circular_tracks();dataset_arc_height=this.dataset_arc_height,min_dimension=Math.min(this.$el.width(),this.$el.height()),radius_start=min_dimension/2-o.length*(this.dataset_arc_height+this.track_gap)-(this.label_arc_height+this.track_gap),tracks_start_radii=l.range(radius_start,min_dimension/2,this.dataset_arc_height+this.track_gap);var n=this;return g.map(tracks_start_radii,function(p){return[p,p+n.dataset_arc_height]})},render:function(){var w=this,q=this.dataset_arc_height,n=w.$el.width(),v=w.$el.height(),s=this.get_circular_tracks(),p=this.get_chord_tracks(),r=this.get_tracks_bounds(),o=l.select(w.$el[0]).append("svg").attr("width",n).attr("height",v).attr("pointer-events","all").append("svg:g").call(l.behavior.zoom().on("zoom",function(){var x=l.event.scale;o.attr("transform","translate("+l.event.translate+") scale("+x+")");if(w.scale!==x){if(w.zoom_drag_timeout){clearTimeout(w.zoom_drag_timeout)}w.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+n/2+","+v/2+")").append("svg:g").attr("class","tracks");this.circular_views=s.map(function(y,z){var x=new d({el:o.append("g")[0],track:y,radius_bounds:r[z],genome:w.genome,total_gap:w.total_gap});x.render();return x});this.chords_views=p.map(function(y){var x=new j({el:o.append("g")[0],track:y,radius_bounds:r[0],genome:w.genome,total_gap:w.total_gap});x.render();return x});var u=this.circular_views[this.circular_views.length-1].radius_bounds[1],t=[u,u+this.label_arc_height];this.label_track_view=new b({el:o.append("g")[0],track:new c(),radius_bounds:t,genome:w.genome,total_gap:w.total_gap});this.label_track_view.render()},add_track:function(t){if(t.get("track_type")==="DiagonalHeatmapTrack"){var p=this.circular_views[0].radius_bounds,s=new j({el:l.select("g.tracks").append("g")[0],track:t,radius_bounds:p,genome:this.genome,total_gap:this.total_gap});s.render();this.chords_views.push(s)}else{var r=this.get_tracks_bounds();g.each(this.circular_views,function(u,v){u.update_radius_bounds(r[v])});g.each(this.chords_views,function(u){u.update_radius_bounds(r[0])});var q=this.circular_views.length,n=new d({el:l.select("g.tracks").append("g")[0],track:t,radius_bounds:r[q],genome:this.genome,total_gap:this.total_gap});n.render();this.circular_views.push(n);var o=r[r.length-1];o[1]=o[0];this.label_track_view.update_radius_bounds(o)}},remove_track:function(o,q,p){var n=this.circular_views[p.index];this.circular_views.splice(p.index,1);n.$el.remove();var r=this.get_tracks_bounds();g.each(this.circular_views,function(s,t){s.update_radius_bounds(r[t])})}});var k=Backbone.View.extend({tagName:"g",initialize:function(n){this.bg_stroke="ccc";this.loading_bg_fill="000";this.bg_fill="ccc";this.total_gap=n.total_gap;this.track=n.track;this.radius_bounds=n.radius_bounds;this.genome=n.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=l.select(this.$el[0])},get_fill_color:function(){var n=this.track.get("config").get_value("block_color");if(!n){n=this.track.get("config").get_value("color")}return n},render:function(){var r=this.parent_elt;if(!r){console.log("no parent elt")}var q=this.chroms_layout,t=l.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),n=r.selectAll("g").data(q).enter().append("svg:g"),p=n.append("path").attr("d",t).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);p.append("title").text(function(v){return v.data.chrom});var o=this,s=o.track.get("data_manager"),u=(s?s.data_is_ready():true);$.when(u).then(function(){$.when(o._render_data(r)).then(function(){p.style("fill",o.bg_fill);o.render_labels()})})},render_labels:function(){},update_radius_bounds:function(o){this.radius_bounds=o;var n=l.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",n);this._transition_chrom_data();this._transition_labels()},update_scale:function(q){var p=this.scale;this.scale=q;if(q<=p){return}var o=this,n=new m();this.parent_elt.selectAll("path.chrom-data").filter(function(s,r){return n.is_visible(this)}).each(function(x,t){var w=l.select(this),s=w.attr("chrom"),v=o.genome.get_chrom_region(s),u=o.track.get("data_manager"),r;if(!u.can_get_more_detailed_data(v)){return}r=o.track.get("data_manager").get_more_detailed_data(v,"Coverage",0,q);$.when(r).then(function(A){w.remove();o._update_data_bounds();var z=g.find(o.chroms_layout,function(B){return B.data.chrom===s});var y=o.get_fill_color();o._render_chrom_data(o.parent_elt,z,A).style("stroke",y).style("fill",y)})});return o},_transition_chrom_data:function(){var o=this.track,q=this.chroms_layout,n=this.parent_elt.selectAll("g>path.chrom-data"),r=n[0].length;if(r>0){var p=this;$.when(o.get("data_manager").get_genome_wide_data(this.genome)).then(function(t){var s=g.reject(g.map(t,function(u,v){var w=null,x=p._get_path_function(q[v],u);if(x){w=x(u.data)}return w}),function(u){return u===null});n.each(function(v,u){l.select(this).transition().duration(1000).attr("d",s[u])})})}},_transition_labels:function(){},_update_data_bounds:function(){var n=this.data_bounds;this.data_bounds=this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));if(this.data_bounds[0]<n[0]||this.data_bounds[1]>n[1]){this._transition_chrom_data()}},_render_data:function(q){var p=this,o=this.chroms_layout,n=this.track,r=$.Deferred();$.when(n.get("data_manager").get_genome_wide_data(this.genome)).then(function(t){p.data_bounds=p.get_data_bounds(t);layout_and_data=g.zip(o,t),chroms_data_layout=g.map(layout_and_data,function(u){var v=u[0],w=u[1];return p._render_chrom_data(q,v,w)});var s=p.get_fill_color();p.parent_elt.selectAll("path.chrom-data").style("stroke",s).style("fill",s);r.resolve(q)});return r},_render_chrom_data:function(n,o,p){},_get_path_function:function(o,n){},_chroms_layout:function(){var o=this.genome.get_chroms_info(),q=l.layout.pie().value(function(s){return s.len}).sort(null),r=q(o),n=this.total_gap/o.length,p=g.map(r,function(u,t){var s=u.endAngle-n;u.endAngle=(s>u.startAngle?s:u.startAngle);return u});return p}});var b=k.extend({initialize:function(n){k.prototype.initialize.call(this,n);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="fff";this.bg_fill="fff";this.min_arc_len=0.08},_render_data:function(p){var o=this,n=p.selectAll("g");n.selectAll("path").attr("id",function(t){return"label-"+t.data.chrom});n.append("svg:text").filter(function(t){return t.endAngle-t.startAngle>o.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("xlink:href",function(t){return"#label-"+t.data.chrom}).attr("startOffset","25%").attr("font-weight","bold").text(function(t){return t.data.chrom});var q=function(v){var t=(v.endAngle-v.startAngle)/v.value,u=l.range(0,v.value,25000000).map(function(w,x){return{radius:o.innerRadius,angle:w*t+v.startAngle,label:x===0?0:(x%3?null:o.formatNum(w))}});if(u.length<4){u[u.length-1].label=o.formatNum(Math.round((u[u.length-1].angle-v.startAngle)/t))}return u};var s=function(t){return t.angle>Math.PI?"rotate(180)translate(-16)":null};var r=g.filter(this.chroms_layout,function(t){return t.endAngle-t.startAngle>o.min_arc_len});this.drawTicks(this.parent_elt,r,q,s)}});g.extend(b.prototype,h);var f=k.extend({_quantile:function(o,n){o.sort(l.ascending);return l.quantile(o,n)},_render_chrom_data:function(n,q,o){var r=this._get_path_function(q,o);if(!r){return null}var p=n.datum(o.data),s=p.append("path").attr("class","chrom-data").attr("chrom",q.data.chrom).attr("d",r);return s},_get_path_function:function(q,p){if(typeof p==="string"||!p.data||p.data.length===0){return null}var n=l.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var r=l.scale.linear().domain([0,p.data.length]).range([q.startAngle,q.endAngle]);var o=l.svg.line.radial().interpolate("linear").radius(function(s){return n(s[1])}).angle(function(t,s){return r(s)});return l.svg.area.radial().interpolate(o.interpolate()).innerRadius(n(0)).outerRadius(o.radius()).angle(o.angle())},render_labels:function(){var n=this,q=function(){return"rotate(90)"};var p=g.filter(this.chroms_layout,function(r){return r.endAngle-r.startAngle>0.08}),o=g.filter(p,function(s,r){return r%3===0});this.drawTicks(this.parent_elt,o,this._data_bounds_ticks_fn(),q,true)},_transition_labels:function(){if(this.data_bounds.length===0){return}var o=this,q=g.filter(this.chroms_layout,function(r){return r.endAngle-r.startAngle>0.08}),p=g.filter(q,function(s,r){return r%3===0}),n=g.flatten(g.map(p,function(r){return o._data_bounds_ticks_fn()(r)}));this.parent_elt.selectAll("g.tick").data(n).transition().attr("transform",function(r){return"rotate("+(r.angle*180/Math.PI-90)+")translate("+r.radius+",0)"})},_data_bounds_ticks_fn:function(){var n=this;visibleChroms=0;return function(o){return[{radius:n.radius_bounds[0],angle:o.startAngle,label:n.formatNum(n.data_bounds[0])},{radius:n.radius_bounds[1],angle:o.startAngle,label:n.formatNum(n.data_bounds[1])}]}},get_data_bounds:function(n){}});g.extend(f.prototype,h);var d=f.extend({get_data_bounds:function(o){var n=g.flatten(g.map(o,function(p){if(p){return g.map(p.data,function(q){return q[1]})}else{return 0}}));return[g.min(n),this._quantile(n,0.98)]}});var j=k.extend({render:function(){var n=this;$.when(n.track.get("data_manager").data_is_ready()).then(function(){$.when(n.track.get("data_manager").get_genome_wide_data(n.genome)).then(function(q){var p=[],o=n.genome.get_chroms_info();g.each(q,function(u,t){var r=o[t].chrom;var s=g.map(u.data,function(w){var v=n._get_region_angle(r,w[1]),x=n._get_region_angle(w[3],w[4]);return{source:{startAngle:v,endAngle:v+0.01},target:{startAngle:x,endAngle:x+0.01}}});p=p.concat(s)});n.parent_elt.append("g").attr("class","chord").selectAll("path").data(p).enter().append("path").style("fill",n.get_fill_color()).attr("d",l.svg.chord().radius(n.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(n){this.radius_bounds=n;this.parent_elt.selectAll("path").transition().attr("d",l.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(p,n){var o=g.find(this.chroms_layout,function(q){return q.data.chrom===p});return o.endAngle-((o.endAngle-o.startAngle)*(o.data.len-n)/o.data.len)}});var e=Backbone.View.extend({initialize:function(){var n=new i.Genome(config.app.genome),o=new i.GenomeVisualization(config.app.viz_config),q=new a({el:$("#center .unified-panel-body"),total_gap:2*Math.PI*0.1,genome:n,model:o,dataset_arc_height:25});q.render();$("#center .unified-panel-header-inner").append(config.app.viz_config.title+" "+config.app.viz_config.dbkey);var p=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){i.select_datasets(config.root+"visualization/list_current_history_datasets",config.root+"api/datasets",o.get("dbkey"),function(r){o.add_tracks(r)})}},{icon_class:"disk--arrow",title:"Save",on_click:function(){show_modal("Saving...","progress");var r=config.app.viz_config;$.ajax({url:config.root+"visualization/save",type:"POST",dataType:"json",data:{id:r.vis_id,title:r.title,dbkey:r.dbkey,type:"trackster",vis_json:JSON.stringify(r)}}).success(function(s){hide_modal();r.vis_id=s.vis_id;r.has_changes=false;window.history.pushState({},"",s.url+window.location.hash)}).error(function(){show_modal("Could Not Save","Could not save visualization. Please try again later.",{Close:hide_modal})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=config.root+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});p.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(p.$el);$(".menu-button").tooltip({placement:"bottom"})}});return{GalaxyApp:e}});
\ No newline at end of file
diff -r ba8555d1fed4b95e2882afd33c45be3300c00ded -r af1daa86ba5b713240fb3f7ccd607f3adb8c05a7 static/scripts/packed/viz/trackster.js
--- a/static/scripts/packed/viz/trackster.js
+++ b/static/scripts/packed/viz/trackster.js
@@ -1,1 +1,1 @@
-var ui=null;var view=null;var browser_router=null;require(["utils/galaxy.css","libs/jquery/jstorage","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/jquery-ui-combobox","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating"],function(a){a.load_file("/static/style/jquery.rating.css");a.load_file("/static/style/history.css");a.load_file("/static/style/autocomplete_tagging.css");a.load_file("/static/style/jquery-ui/smoothness/jquery-ui.css");a.load_file("/static/style/library.css");a.load_file("/static/style/trackster.css")});define(["libs/backbone/backbone-relational","viz/visualization","viz/trackster_ui"],function(c,a,b){var d=Backbone.View.extend({initialize:function(){ui=new b.TracksterUI(config.url.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(config.app.id){this.view_existing()}else{this.view_new()}},set_up_router:function(e){browser_router=new a.TrackBrowserRouter(e);Backbone.history.start()},view_existing:function(){var e=config.app.viz_config;view=ui.create_visualization({container:$("#browser-container"),name:e.title,vis_id:e.vis_id,dbkey:e.dbkey},e.viewport,e.tracks,e.bookmarks,true);this.init_editor()},view_new:function(){var e=this;$.ajax({url:config.url.new_browser,data:{},error:function(){alert("Couldn't create new browser.")},success:function(f){show_modal("New Visualization",f,{Cancel:function(){window.location=config.url.viz_list},Create:function(){e.create_browser($("#new-title").val(),$("#new-dbkey").val())}});$("#new-title").focus();$("select[name='dbkey']").combobox({appendTo:$("#overlay"),size:40});$("#overlay").css("overflow","auto")}})},create_browser:function(f,e){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#browser-container"),name:f,dbkey:e},config.app.gene_region);this.init_editor();view.editor=true;hide_modal()},init_editor:function(){$("#title").text(view.name+" ("+view.dbkey+")");if(config.app.add_dataset){$.ajax({url:config.url.datasets+"/"+config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(e){view.add_drawable(b.object_from_template(e,view,view))}})}$("#add-bookmark-button").click(function(){var f=view.chrom+":"+view.low+"-"+view.high,e="Bookmark description";return ui.add_bookmark(f,e,true)});ui.init_keyboard_nav(view);this.set_up_router({view:view})}});return{GalaxyApp:d}});
\ No newline at end of file
+var ui=null;var view=null;var browser_router=null;require(["utils/galaxy.css","libs/jquery/jstorage","libs/jquery/jquery.event.drag","libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel","libs/jquery/jquery-ui","libs/jquery/jquery-ui-combobox","libs/farbtastic","libs/jquery/jquery.form","libs/jquery/jquery.rating","mvc/ui"],function(a){a.load_file("/static/style/jquery.rating.css");a.load_file("/static/style/history.css");a.load_file("/static/style/autocomplete_tagging.css");a.load_file("/static/style/jquery-ui/smoothness/jquery-ui.css");a.load_file("/static/style/library.css");a.load_file("/static/style/trackster.css")});define(["libs/backbone/backbone-relational","viz/visualization","viz/trackster_ui"],function(c,a,b){var d=Backbone.View.extend({initialize:function(){ui=new b.TracksterUI(config.root);ui.createButtonMenu();ui.buttonMenu.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(ui.buttonMenu.$el);$("#right .unified-panel-title").append("Bookmarks");$("#right .unified-panel-icons").append("<a id='add-bookmark-button' class='icon-button menu-button plus-button' href='javascript:void(0);' title='Add bookmark'></a>");$("#right-border").click(function(){view.resize_window()});force_right_panel("hide");if(config.app.id){this.view_existing()}else{this.view_new()}},set_up_router:function(e){browser_router=new a.TrackBrowserRouter(e);Backbone.history.start()},view_existing:function(){var e=config.app.viz_config;view=ui.create_visualization({container:$("#center .unified-panel-body"),name:e.title,vis_id:e.vis_id,dbkey:e.dbkey},e.viewport,e.tracks,e.bookmarks,true);this.init_editor()},view_new:function(){var e=this;$.ajax({url:config.app.new_browser,data:{},error:function(){alert("Couldn't create new browser.")},success:function(f){show_modal("New Visualization",f,{Cancel:function(){window.location=config.root+"visualization/list"},Create:function(){e.create_browser($("#new-title").val(),$("#new-dbkey").val())}});$("#new-title").focus();$("select[name='dbkey']").combobox({appendTo:$("#overlay"),size:40});$("#overlay").css("overflow","auto")}})},create_browser:function(f,e){$(document).trigger("convert_to_values");view=ui.create_visualization({container:$("#center .unified-panel-body"),name:f,dbkey:e},config.app.gene_region);this.init_editor();view.editor=true;hide_modal()},init_editor:function(){$("#center .unified-panel-title").text(view.name+" ("+view.dbkey+")");if(config.app.add_dataset){$.ajax({url:config.root+"api/datasets/"+config.app.add_dataset,data:{hda_ldda:"hda",data_type:"track_config"},dataType:"json",success:function(e){view.add_drawable(b.object_from_template(e,view,view))}})}$("#add-bookmark-button").click(function(){var f=view.chrom+":"+view.low+"-"+view.high,e="Bookmark description";return ui.add_bookmark(f,e,true)});ui.init_keyboard_nav(view);this.set_up_router({view:view})}});return{GalaxyApp:d}});
\ No newline at end of file
diff -r ba8555d1fed4b95e2882afd33c45be3300c00ded -r af1daa86ba5b713240fb3f7ccd607f3adb8c05a7 static/scripts/packed/viz/trackster/tracks.js
--- a/static/scripts/packed/viz/trackster/tracks.js
+++ b/static/scripts/packed/viz/trackster/tracks.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,w,k,t,L,X,i){var p=ab.extend;var m={};var j=function(ac,ad){m[ac.attr("id")]=ad};var l=function(ac,ae,ag,af){ag=".group";var ad={};m[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=m[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=m[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=m[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}m[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);m[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));m[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,z=100,I=12000,S=400,K=5000,v=100,n="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",u="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",x="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",R=10,H=20,A=["Histogram","Line","Filled","Intensity"];function V(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var q=function(ad,ac,af){if(!q.id_counter){q.id_counter=0}this.id=q.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};q.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];p(q.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(ac){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var y=function(ad,ac,ae){q.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};p(y.prototype,q.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=o(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(ac){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad]._draw(ac)}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables},get_tracks:function(af){var ac=this.drawables.slice(0),ad=[],ae;while(ac.length!==0){ae=ac.shift();if(ae instanceof af){ad.push(ae)}else{if(ae.drawables){ac=ac.concat(ae.drawables)}}}return ad}});var Q=function(ad,ac,af){p(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});y.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);j(this.container_div,this);j(this.content_div,this);l(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};p(Q.prototype,q.prototype,y.prototype,{action_icons_def:[q.prototype.action_icons_def[0],q.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw({clear_tile_cache:true})}ac.filters_manager.toggle()}},q.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ad=new f(this.view,this.view,{name:this.name,drawables:this.drawables});var ac=this.container.replace_drawable(this,ad,true);ad.request_draw()},add_drawable:function(ac){y.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){y.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=p(y.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac){ab.each(this.drawables,function(ad){ad.request_draw(ac)})}});var Y=Backbone.View.extend({initialize:function(ac){p(ac,{obj_type:"View"});y.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new w.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ac.prefs,onchange:function(){track.request_redraw({clear_tile_cache:true})}})},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;j(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){w.select_datasets(config.url.select_datasets,config.url.datasets,{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(o(ah,ac,ac))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_tracks(c),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ac){return this.config.values[ac.toLowerCase()+"_color"]||this.config.values.n_color}});p(Y.prototype,y.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=v;var ac=this,ad=$.Deferred();$.ajax({url:config.url.genomes+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+v+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+v+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-v});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+v});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad&&aj){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/,/g,"");ag=ag.replace(/:|\-/g," ");var ad=ag.split(/\s+/),af=ad[0],ae=(ad[1]?parseInt(ad[1],10):null),ac=(ad[2]?parseInt(ad[2],10):null);if(!ac){ae=ae-15;ac=ae+15}this.change_chrom(af,ae,ac)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw({data_fetch:false});if(this.redraw_on_move_fn){clearTimeout(this.redraw_on_move_fn)}this.redraw_on_move_fn=setTimeout(function(){ac.request_redraw()},200);var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){y.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){y.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ad,ae){var ac=this,af=(ae?[ae]:ac.drawables);ab.each(af,function(ag){var ah=ab.find(ac.tracks_to_be_redrawn,function(ai){return ai[0]===ag});if(ah){ah[1]=ad}else{ac.tracks_to_be_redrawn.push([ag,ad])}});if(!this.requested_redraw){requestAnimationFrame(function(){ac._redraw()});this.requested_redraw=true}},_redraw:function(){this.requested_redraw=false;var ac=this.low,ag=this.high;if(ac<this.max_low){ac=this.max_low}if(ag>this.max_high){ag=this.max_high}var ad=this.high-this.low;if(this.high!==0&&ad<this.min_separation){ag=ac+this.min_separation}this.low=Math.floor(ac);this.high=Math.ceil(ag);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var af=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ah=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ae=13;this.overview_box.css({left:af,width:Math.max(ae,ah)}).show();if(ah<ae){this.overview_box.css("left",af-(ae-ah)/2)}if(this.overview_highlight){this.overview_highlight.css({left:af,width:ah})}ab.each(this.tracks_to_be_redrawn,function(ak){var ai=ak[0],aj=ak[1];if(ai){ai._draw(aj)}});this.tracks_to_be_redrawn=[];ab.each(this.label_tracks,function(ai){ai._draw()})},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ae){if(this.overview_drawable){if(this.overview_drawable.dataset.id===ae.dataset.id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();view.overview_drawable=null}});var r=function(ae,aj,af){this.track=ae;this.id=aj.id;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new O(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};p(r.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.dataset.id,action:"rerun",tool_id:ac.id},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new w.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.dataset.id,action:"rerun",tool_id:this.id,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new Q(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new X.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new k.ServerStateDeferred({ajax_settings:{url:config.url.tool,data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(x+ag.message)}else{af(ag)}}})}});var O=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};p(O.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){O.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};p(e.prototype,O.prototype,{update_value:function(){O.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};p(F.prototype,{set_param_default_value:function(ad,ac){var ae=ab.find(this.params,function(af){return af.key===ad});if(ae){ae.default_value=ac}},set_param_value:function(ac,ad){var ae=ab.find(this.params,function(af){return af.key===ac});if(ae){if(typeof ad==="string"||ad instanceof String){if(ad.trim()===""){ad=ae.default_value}else{if(ae.type==="float"){ad=parseFloat(ad)}else{if(ae.type==="int"){ad=parseInt(ad,10)}}}}}if(this.values[ac]!==ad){this.values[ac]=ad;return true}else{return false}},restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(k.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}ad=ae.set_param_value(ah.key,ag)||ad}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var M=function(ac,ag,ae,ad,af){b.call(this,ac,ag,ae,ad,af)};M.prototype.predisplay_actions=function(){};var P=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new w.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw()}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw()}).dblclick(function(ar){ar.stopPropagation()})}};p(P.prototype,b.prototype);P.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?V(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){p(ae,{drag_handle_class:"draghandle"});q.call(this,ad,ac,ae);this.dataset=new X.Dataset(ae.dataset);this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new w.GenomeDataManager({dataset:this.dataset,genome:new w.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ae)||ae.resize){this.add_resize_handle()}}};p(g.prototype,q.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},q.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},q.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new w.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new w.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=config.url.sweepster+"?"+$.param({dataset_id:ac.dataset.id,hda_ldda:ac.dataset.get("hda_ldda"),regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},q.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset.id&&q.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},set_dataset:function(ac){this.dataset=ac;this.data_manager.set("dataset",ac)},on_resize:function(){this.request_draw({clear_tile_cache:true})},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){q.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.tiles_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset.id){return}var ac=$.Deferred(),af={hda_ldda:ad.dataset.get("hda_ldda"),data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(n);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(u);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(U);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when.apply($,ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){var ac=this;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.dataset.get("hda_ldda")},function(ad){ac.container_div.addClass("line-track");var af=ad.data;if(af&&af.min&&af.max){var ae=af.min,ag=af.max;ae=Math.floor(Math.min(0,Math.max(ae,af.mean-2*af.sd)));ag=Math.ceil(Math.max(0,Math.min(ag,af.mean+2*af.sd)));ac.config.set_param_default_value("min_value",ae);ac.config.set_param_default_value("max_value",ag);ac.prefs.min_value=ae;ac.prefs.max_value=ag}})},get_drawables:function(){return this}});var N=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;l(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new r(this,af.tool,af.tool_state):null);this.tile_cache=new w.Cache(R);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(af.mode){this.change_mode(af.mode)}};p(N.prototype,q.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw({clear_tile_cache:true})},hide:true}]),copy:function(ac){var ad=this.to_dict();p(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,dataset:{id:this.dataset.id,hda_ldda:this.dataset.get("hda_ldda")},prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},set_min_max:function(){var ac=this;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.dataset.get("hda_ldda")},function(ad){var af=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=af.min,ag=af.max;ae=Math.floor(Math.min(0,Math.max(ae,af.mean-2*af.sd)));ag=Math.ceil(Math.max(0,Math.min(ag,af.mean+2*af.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ag}})},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;if(ad==="Auto"){this.data_manager.clear()}ac.request_draw({clear_tile_cache:true});this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ac){if(ac&&ac.clear_tile_cache){this.tile_cache.clear()}this.view.request_redraw(ac,this)},before_draw:function(){this.max_height_px=0},_draw:function(ap){if(!this.can_draw()){return}var am=ap&&ap.clear_after,ak=this.view.low,ag=this.view.high,aj=ag-ak,ad=this.view.container.width(),ao=this.view.resolution_px_b,af=this.view.resolution_b_px;if(this.is_overview){ak=this.view.max_low;ag=this.view.max_high;af=(view.max_high-view.max_low)/ad;ao=1/af}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(ak/(af*S)),al,ah,ai=[],an=[];while((ac*S*af)<ag){al=this._get_tile_bounds(ac,af);ah=this.draw_helper(al,af,ao,ap);ai.push(ah);$.when(ah).then(function(aq){an.push(aq)});ac+=1}if(!am){this.tiles_div.children(".remove").removeClass("remove").remove()}var ae=this;$.when.apply($,ai).then(function(){ae.tiles_div.children(".remove").remove();an=ab.filter(an,function(aq){return aq!==null});if(an.length!==0){ae.postdraw_actions(an,ad,ao,am)}})},_add_yaxis_label:function(af,ah){var ad=this,ag=(af==="max"?"top":"bottom"),ai=(af==="max"?"max":"min"),ac=(af==="max"?"max_value":"min_value"),ah=ah||function(){ad.request_draw({clear_tile_cache:true})},ae=this.container_div.find(".yaxislabel."+ag);if(ae.length!==0){ae.text(ad.prefs[ac])}else{ae=$("<div/>").text(ad.prefs[ac]).make_text_editable({num_cols:12,on_finish:function(aj){$(".bs-tooltip").remove();ad.config.set_param_value(ac,aj);ah()},help_text:"Set "+ai+" value"}).addClass("yaxislabel "+ag).css("color",this.prefs.label_color);this.container_div.prepend(ae)}},postdraw_actions:function(af,ag,ai,ac){var ae=ab.filter(af,function(aj){return(aj instanceof M)});if(ae.length>0){this.max_height_px=0;var ad=this;ab.each(af,function(aj){if(!(aj instanceof M)){aj.html_elt.remove();ad.draw_helper(aj.region,aj.resolution,ai,{force:true,mode:"Coverage"})}});ad._add_yaxis_label("max")}else{this.container_div.find(".yaxislabel").remove();var ah=ab.find(af,function(aj){return aj.has_icons});if(ah){ab.each(af,function(aj){if(!aj.has_icons){aj.html_elt.css("padding-top",D)}})}}},get_mode:function(ac){return this.mode},update_auto_mode:function(ac){},_get_drawables:function(){return[this]},draw_helper:function(al,af,ao,ap){if(!ap){ap={}}var ad=ap.force,an=!(ap.data_fetch===false),ai=ap.mode||this.mode,ae=this,ag=this._get_drawables(),am=this._gen_tile_cache_key(ao,al),ah=function(aq){return(aq&&"track" in aq)};var aj=(ad?undefined:ae.tile_cache.get_elt(am));if(aj){if(ah(aj)){ae.show_tile(aj,ao)}return aj}if(!an){return null}var ak=function(){var aq=(ab.find(A,function(at){return at===ai})?"Coverage":ai);var ar=ab.map(ag,function(at){return at.data_manager.get_data(al,aq,af,ae.data_url_extra_params)});if(view.reference_track){ar.push(view.reference_track.data_manager.get_data(al,ai,af,view.reference_track.data_url_extra_params))}return ar};var ac=$.Deferred();ae.tile_cache.set_elt(am,ac);$.when.apply($,ak()).then(function(){var aq=ak(),aw=aq,aC;if(view.reference_track){aC=view.reference_track.data_manager.subset_entry(aq.pop(),al)}var ax=[],au=[];ab.each(ag,function(aH,aE){var aG=aH.mode,aF=aw[aE];if(aG==="Auto"){aG=aH.get_mode(aF);aH.update_auto_mode(aG)}ax.push(aG);au.push(aH.get_canvas_height(aF,aG,ao,ar))});var av=ae.view.canvas_manager.new_canvas(),ay=al.get("start"),aD=al.get("end"),at=0,ar=Math.ceil((aD-ay)*ao)+ae.left_offset,aA=ab.max(au),az;av.width=ar;av.height=(ap.height||aA);var aB=av.getContext("2d");aB.translate(ae.left_offset,0);if(ag.length>1){aB.globalAlpha=0.5;aB.globalCompositeOperation="source-over"}ab.each(ag,function(aF,aE){az=aF.draw_tile(aw[aE],aB,ax[aE],af,al,ao,aC)});if(az!==undefined){ae.tile_cache.set_elt(am,az);ae.show_tile(az,ao)}ac.resolve(az)});return ac},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},_draw_line_track_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.LinePainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new M(this,ah,ag,af,ac.data)},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ah;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{this.tiles_div.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*S*ad),ag=Math.ceil(S*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new w.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="bigwig"}else{if(ac.extra_info==="no_detail"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="bigwig"||ac.message||ac.extra_info==="no_detail"){return false}return true},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new k.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset.id,hda_ldda:ad.dataset.get("hda_ldda")},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var W=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};p(W.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},predraw_init:function(){},_draw:function(ag){var ae=this.view,af=ae.high-ae.low,aj=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/aj)*aj,ah=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ai=(ac-ae.low)/af*ah;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ai-1}));ac+=aj}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){this.display_modes=A;N.call(this,ad,ac,ag);this.drawables=[];if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=o(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}ab.each(this.drawables,function(ah){if(ah instanceof c||ah instanceof T){ah.change_mode("Coverage")}});this.update_icons();this.obj_type="CompositeTrack"};p(f.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(N.prototype.action_icons_def),to_dict:y.prototype.to_dict,add_drawable:y.prototype.add_drawable,unpack_drawables:y.prototype.unpack_drawables,change_mode:function(ac){N.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:q.prototype.can_draw,_get_drawables:function(){return this.drawables},show_group:function(){var af=new Q(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw({clear_tile_cache:true})},before_draw:function(){N.prototype.before_draw.call(this);var ad=ab.min(ab.map(this.drawables,function(ae){return ae.prefs.min_value})),ac=ab.max(ab.map(this.drawables,function(ae){return ae.prefs.max_value}));this.prefs.min_value=ad;this.prefs.max_value=ac;ab.each(this.drawables,function(ae){ae.prefs.min_value=ad;ae.prefs.max_value=ac})},update_all_min_max:function(){var ac=this;ab.each(this.drawables,function(ad){ad.prefs.min_value=ac.prefs.min_value;ad.prefs.max_value=ac.prefs.max_value});this.request_draw({clear_tile_cache:true})},postdraw_actions:function(ai,ac,al,ah){N.prototype.postdraw_actions.call(this,ai,ac,al,ah);var ag=-1;for(var ae=0;ae<ai.length;ae++){var aj=ai[ae].html_elt.find("canvas").height();if(aj>ag){ag=aj}}for(var ae=0;ae<ai.length;ae++){var af=ai[ae];if(af.html_elt.find("canvas").height()!==ag){this.draw_helper(af.region,af.resolution,al,{force:true,height:ag});af.html_elt.remove()}}var ad=this,ak=function(){ad.update_all_min_max()};this._add_yaxis_label("min",ak);this._add_yaxis_label("max",ak)}});var B=function(ac){N.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=config.url.genomes+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new w.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};p(B.prototype,q.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},predraw_init:function(){},can_draw:q.prototype.can_draw,draw_helper:function(ae,ad,af,ac){if(af>this.view.canvas_manager.char_width_px){this.tiles_div.show();return N.prototype.draw_helper.call(this,ae,ad,af,ac)}else{this.tiles_div.hide();return null}},can_subset:function(ac){return true},draw_tile:function(af,al,ag,ad,ai,am){var ae=this.data_manager.subset_entry(af,ai),ak=ae.data;var ac=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";for(var ah=0,aj=ak.length;ah<aj;ah++){al.fillStyle=this.view.get_base_color(ak[ah]);al.fillText(ak[ah],Math.floor(ah*am),10)}return new b(this,ai,ad,ac,ae)}});var h=function(ae,ad,af){var ac=this;this.display_modes=A;this.mode="Histogram";N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:k.get_random_color()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};p(h.prototype,q.prototype,N.prototype,{before_draw:function(){},draw_tile:function(ac,ad,ag,ae,af,ah){return this._draw_line_track_tile(ac,ad,ag,ae,af,ah)},can_subset:function(ac){return(ac.data[1][0]-ac.data[0][0]===1)},postdraw_actions:function(ad,ae,af,ac){this._add_yaxis_label("max");this._add_yaxis_label("min")}});var s=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);this.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};p(s.prototype,q.prototype,N.prototype,{draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,af,ae,ah);var ag=k.get_random_color(),ac=k.get_random_color([ag,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.set_painter_from_config();ad.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};p(c.prototype,q.prototype,N.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},postdraw_actions:function(am,ae,an,al){N.prototype.postdraw_actions.call(this,am,ae,an,al);var ag=this,ah;if(ag.filters_manager){var af=ag.filters_manager.filters;for(var aj=0;aj<af.length;aj++){af[aj].update_ui_elt()}var ai=false,ak,ad;for(ah=0;ah<am.length;ah++){if(am[ah].data.length){ak=am[ah].data[0];for(var aj=0;aj<af.length;aj++){ad=af[aj];if(ad.applies_to(ak)&&ad.min!==ad.max){ai=true;break}}}}if(ag.filters_available!==ai){ag.filters_available=ai;if(!ag.filters_available){ag.filters_manager.hide()}ag.update_icons()}}if(am[0] instanceof P){var ac=true;for(ah=0;ah<am.length;ah++){if(!am[ah].all_slotted){ac=false;break}}if(!ac){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (t.FeatureSlotter)(ag,af,z,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}return mode},get_canvas_height:function(ac,ag,ah,ad){if(ag==="Coverage"||ac.dataset_type==="bigwig"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(am.dataset_type==="bigwig"){return this._draw_line_track_tile(am,aq,ao,ar,af,aj)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae,function(aD){return ap.view.get_base_color(aD)});var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new P(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)}});var Z=function(ad,ac,ae){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ad,ac,ae);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Histogram color",type:"color",default_value:k.get_random_color()},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};p(Z.prototype,q.prototype,N.prototype,{draw_tile:function(ac,af,ai,ag,ah,aj){if(ac.dataset_type==="bigwig"){return this._draw_line_track_tile(ac,af,"Histogram",ag,ah,aj)}else{var ae=this.view,ad=new (this.painter)(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai,function(ak){return ae.get_base_color(ak)});ad.draw(af,af.canvas.width,af.canvas.height,aj);return new b(this,ah,ag,af.canvas,ac.data)}},get_canvas_height:function(ac,ag,ah,ae){if(ac.dataset_type==="bigwig"){return this.summary_draw_height}else{var af=new (this.painter)(null,null,null,this.prefs,ag);var ad=(this.dataset.get_metadata("sample_names")?this.dataset.get_metadata("sample_names").length:0);if(ad===0&&ac.data.length!==0){ad=ac.data[0][7].match(/,/g);if(ad===null){ad=1}else{ad=ad.length+1}}return af.get_required_height(ad)}},predraw_init:function(){var ac=[g.prototype.predraw_init.call(this)];if(!this.dataset.get_metadata("sample_names")){ac.push(this.dataset.fetch())}return ac},postdraw_actions:function(af,ag,ai,ad){N.prototype.postdraw_actions.call(this,af,ag,ai,ad);var ae=ab.filter(af,function(aj){return(aj instanceof M)});if(ae.length===0&&this.prefs.show_labels){var ac;if(this.container_div.find(".yaxislabel.variant").length===0){ac=this.prefs.summary_height/2;this.tiles_div.prepend($("<div/>").text("Summary").addClass("yaxislabel variant top").css({"font-size":ac+"px",top:(this.prefs.summary_height-ac)/2+"px"}));if(this.prefs.show_sample_data){var ah=this.dataset.get("metadata").get("sample_names").join("<br/>");this.tiles_div.prepend($("<div/>").html(ah).addClass("yaxislabel variant top sample").css({top:this.prefs.summary_height+2,}))}}ac=(this.mode==="Squish"?5:10)+"px";$(this.tiles_div).find(".sample").css({"font-size":ac,"line-height":ac});$(this.tiles_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel.variant").remove()}}});var T=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=k.get_random_color(),ac=k.get_random_color([af,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=(ae.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};p(T.prototype,q.prototype,N.prototype,c.prototype);var d={CompositeTrack:f,DrawableGroup:Q,DiagonalHeatmapTrack:s,FeatureTrack:c,LineTrack:h,ReadTrack:T,VariantTrack:Z,VcfTrack:Z};var o=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Y,DrawableGroup:Q,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:s,ReadTrack:T,VariantTrack:Z,CompositeTrack:f,object_from_template:o}});
\ No newline at end of file
+define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,w,k,t,L,X,i){var p=ab.extend;var m={};var j=function(ac,ad){m[ac.attr("id")]=ad};var l=function(ac,ae,ag,af){ag=".group";var ad={};m[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=m[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=m[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=m[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}m[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);m[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));m[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,z=100,I=12000,S=400,K=5000,v=100,n="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",u="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",x="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",R=10,H=20,A=["Histogram","Line","Filled","Intensity"];function V(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var q=function(ad,ac,af){if(!q.id_counter){q.id_counter=0}this.id=q.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};q.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];p(q.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(ac){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var y=function(ad,ac,ae){q.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};p(y.prototype,q.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=o(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(ac){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad]._draw(ac)}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables},get_tracks:function(af){var ac=this.drawables.slice(0),ad=[],ae;while(ac.length!==0){ae=ac.shift();if(ae instanceof af){ad.push(ae)}else{if(ae.drawables){ac=ac.concat(ae.drawables)}}}return ad}});var Q=function(ad,ac,af){p(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});y.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);j(this.container_div,this);j(this.content_div,this);l(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};p(Q.prototype,q.prototype,y.prototype,{action_icons_def:[q.prototype.action_icons_def[0],q.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw({clear_tile_cache:true})}ac.filters_manager.toggle()}},q.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ad=new f(this.view,this.view,{name:this.name,drawables:this.drawables});var ac=this.container.replace_drawable(this,ad,true);ad.request_draw()},add_drawable:function(ac){y.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){y.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=p(y.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac){ab.each(this.drawables,function(ad){ad.request_draw(ac)})}});var Y=Backbone.View.extend({initialize:function(ac){p(ac,{obj_type:"View"});y.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new w.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ac.prefs,onchange:function(){track.request_redraw({clear_tile_cache:true})}})},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;j(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){w.select_datasets(config.root+"/visualization/list_current_history_datasets",config.root+"/api/datasets",{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(o(ah,ac,ac))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_tracks(c),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ac){return this.config.values[ac.toLowerCase()+"_color"]||this.config.values.n_color}});p(Y.prototype,y.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=v;var ac=this,ad=$.Deferred();$.ajax({url:config.root+"api/genomes/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+v+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+v+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-v});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+v});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad&&aj){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/,/g,"");ag=ag.replace(/:|\-/g," ");var ad=ag.split(/\s+/),af=ad[0],ae=(ad[1]?parseInt(ad[1],10):null),ac=(ad[2]?parseInt(ad[2],10):null);if(!ac){ae=ae-15;ac=ae+15}this.change_chrom(af,ae,ac)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw({data_fetch:false});if(this.redraw_on_move_fn){clearTimeout(this.redraw_on_move_fn)}this.redraw_on_move_fn=setTimeout(function(){ac.request_redraw()},200);var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){y.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){y.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ad,ae){var ac=this,af=(ae?[ae]:ac.drawables);ab.each(af,function(ag){var ah=ab.find(ac.tracks_to_be_redrawn,function(ai){return ai[0]===ag});if(ah){ah[1]=ad}else{ac.tracks_to_be_redrawn.push([ag,ad])}});if(!this.requested_redraw){requestAnimationFrame(function(){ac._redraw()});this.requested_redraw=true}},_redraw:function(){this.requested_redraw=false;var ac=this.low,ag=this.high;if(ac<this.max_low){ac=this.max_low}if(ag>this.max_high){ag=this.max_high}var ad=this.high-this.low;if(this.high!==0&&ad<this.min_separation){ag=ac+this.min_separation}this.low=Math.floor(ac);this.high=Math.ceil(ag);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var af=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ah=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ae=13;this.overview_box.css({left:af,width:Math.max(ae,ah)}).show();if(ah<ae){this.overview_box.css("left",af-(ae-ah)/2)}if(this.overview_highlight){this.overview_highlight.css({left:af,width:ah})}ab.each(this.tracks_to_be_redrawn,function(ak){var ai=ak[0],aj=ak[1];if(ai){ai._draw(aj)}});this.tracks_to_be_redrawn=[];ab.each(this.label_tracks,function(ai){ai._draw()})},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ae){if(this.overview_drawable){if(this.overview_drawable.dataset.id===ae.dataset.id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();view.overview_drawable=null}});var r=function(ae,aj,af){this.track=ae;this.id=aj.id;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new O(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};p(r.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.dataset.id,action:"rerun",tool_id:ac.id},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new w.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.dataset.id,action:"rerun",tool_id:this.id,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new Q(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new X.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new k.ServerStateDeferred({ajax_settings:{url:config.root+"/api/tools",data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(x+ag.message)}else{af(ag)}}})}});var O=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};p(O.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){O.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};p(e.prototype,O.prototype,{update_value:function(){O.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};p(F.prototype,{set_param_default_value:function(ad,ac){var ae=ab.find(this.params,function(af){return af.key===ad});if(ae){ae.default_value=ac}},set_param_value:function(ac,ad){var ae=ab.find(this.params,function(af){return af.key===ac});if(ae){if(typeof ad==="string"||ad instanceof String){if(ad.trim()===""){ad=ae.default_value}else{if(ae.type==="float"){ad=parseFloat(ad)}else{if(ae.type==="int"){ad=parseInt(ad,10)}}}}}if(this.values[ac]!==ad){this.values[ac]=ad;return true}else{return false}},restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(k.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}ad=ae.set_param_value(ah.key,ag)||ad}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var M=function(ac,ag,ae,ad,af){b.call(this,ac,ag,ae,ad,af)};M.prototype.predisplay_actions=function(){};var P=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new w.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw()}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw()}).dblclick(function(ar){ar.stopPropagation()})}};p(P.prototype,b.prototype);P.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?V(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){p(ae,{drag_handle_class:"draghandle"});q.call(this,ad,ac,ae);this.dataset=new X.Dataset(ae.dataset);this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new w.GenomeDataManager({dataset:this.dataset,genome:new w.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ae)||ae.resize){this.add_resize_handle()}}};p(g.prototype,q.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},q.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},q.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new w.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new w.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=config.root+"visualization/sweepster?"+$.param({dataset_id:ac.dataset.id,hda_ldda:ac.dataset.get("hda_ldda"),regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},q.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset.id&&q.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},set_dataset:function(ac){this.dataset=ac;this.data_manager.set("dataset",ac)},on_resize:function(){this.request_draw({clear_tile_cache:true})},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){q.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.tiles_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset.id){return}var ac=$.Deferred(),af={hda_ldda:ad.dataset.get("hda_ldda"),data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(n);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(u);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(U);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when.apply($,ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){var ac=this;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.dataset.get("hda_ldda")},function(ad){ac.container_div.addClass("line-track");var af=ad.data;if(af&&af.min&&af.max){var ae=af.min,ag=af.max;ae=Math.floor(Math.min(0,Math.max(ae,af.mean-2*af.sd)));ag=Math.ceil(Math.max(0,Math.min(ag,af.mean+2*af.sd)));ac.config.set_param_default_value("min_value",ae);ac.config.set_param_default_value("max_value",ag);ac.prefs.min_value=ae;ac.prefs.max_value=ag}})},get_drawables:function(){return this}});var N=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;l(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new r(this,af.tool,af.tool_state):null);this.tile_cache=new w.Cache(R);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(af.mode){this.change_mode(af.mode)}};p(N.prototype,q.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw({clear_tile_cache:true})},hide:true}]),copy:function(ac){var ad=this.to_dict();p(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,dataset:{id:this.dataset.id,hda_ldda:this.dataset.get("hda_ldda")},prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},set_min_max:function(){var ac=this;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.dataset.get("hda_ldda")},function(ad){var af=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=af.min,ag=af.max;ae=Math.floor(Math.min(0,Math.max(ae,af.mean-2*af.sd)));ag=Math.ceil(Math.max(0,Math.min(ag,af.mean+2*af.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ag}})},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;if(ad==="Auto"){this.data_manager.clear()}ac.request_draw({clear_tile_cache:true});this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ac){if(ac&&ac.clear_tile_cache){this.tile_cache.clear()}this.view.request_redraw(ac,this)},before_draw:function(){this.max_height_px=0},_draw:function(ap){if(!this.can_draw()){return}var am=ap&&ap.clear_after,ak=this.view.low,ag=this.view.high,aj=ag-ak,ad=this.view.container.width(),ao=this.view.resolution_px_b,af=this.view.resolution_b_px;if(this.is_overview){ak=this.view.max_low;ag=this.view.max_high;af=(view.max_high-view.max_low)/ad;ao=1/af}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(ak/(af*S)),al,ah,ai=[],an=[];while((ac*S*af)<ag){al=this._get_tile_bounds(ac,af);ah=this.draw_helper(al,af,ao,ap);ai.push(ah);$.when(ah).then(function(aq){an.push(aq)});ac+=1}if(!am){this.tiles_div.children(".remove").removeClass("remove").remove()}var ae=this;$.when.apply($,ai).then(function(){ae.tiles_div.children(".remove").remove();an=ab.filter(an,function(aq){return aq!==null});if(an.length!==0){ae.postdraw_actions(an,ad,ao,am)}})},_add_yaxis_label:function(af,ah){var ad=this,ag=(af==="max"?"top":"bottom"),ai=(af==="max"?"max":"min"),ac=(af==="max"?"max_value":"min_value"),ah=ah||function(){ad.request_draw({clear_tile_cache:true})},ae=this.container_div.find(".yaxislabel."+ag);if(ae.length!==0){ae.text(ad.prefs[ac])}else{ae=$("<div/>").text(ad.prefs[ac]).make_text_editable({num_cols:12,on_finish:function(aj){$(".bs-tooltip").remove();ad.config.set_param_value(ac,aj);ah()},help_text:"Set "+ai+" value"}).addClass("yaxislabel "+ag).css("color",this.prefs.label_color);this.container_div.prepend(ae)}},postdraw_actions:function(af,ag,ai,ac){var ae=ab.filter(af,function(aj){return(aj instanceof M)});if(ae.length>0){this.max_height_px=0;var ad=this;ab.each(af,function(aj){if(!(aj instanceof M)){aj.html_elt.remove();ad.draw_helper(aj.region,aj.resolution,ai,{force:true,mode:"Coverage"})}});ad._add_yaxis_label("max")}else{this.container_div.find(".yaxislabel").remove();var ah=ab.find(af,function(aj){return aj.has_icons});if(ah){ab.each(af,function(aj){if(!aj.has_icons){aj.html_elt.css("padding-top",D)}})}}},get_mode:function(ac){return this.mode},update_auto_mode:function(ac){},_get_drawables:function(){return[this]},draw_helper:function(al,af,ao,ap){if(!ap){ap={}}var ad=ap.force,an=!(ap.data_fetch===false),ai=ap.mode||this.mode,ae=this,ag=this._get_drawables(),am=this._gen_tile_cache_key(ao,al),ah=function(aq){return(aq&&"track" in aq)};var aj=(ad?undefined:ae.tile_cache.get_elt(am));if(aj){if(ah(aj)){ae.show_tile(aj,ao)}return aj}if(!an){return null}var ak=function(){var aq=(ab.find(A,function(at){return at===ai})?"Coverage":ai);var ar=ab.map(ag,function(at){return at.data_manager.get_data(al,aq,af,ae.data_url_extra_params)});if(view.reference_track){ar.push(view.reference_track.data_manager.get_data(al,ai,af,view.reference_track.data_url_extra_params))}return ar};var ac=$.Deferred();ae.tile_cache.set_elt(am,ac);$.when.apply($,ak()).then(function(){var aq=ak(),aw=aq,aC;if(view.reference_track){aC=view.reference_track.data_manager.subset_entry(aq.pop(),al)}var ax=[],au=[];ab.each(ag,function(aH,aE){var aG=aH.mode,aF=aw[aE];if(aG==="Auto"){aG=aH.get_mode(aF);aH.update_auto_mode(aG)}ax.push(aG);au.push(aH.get_canvas_height(aF,aG,ao,ar))});var av=ae.view.canvas_manager.new_canvas(),ay=al.get("start"),aD=al.get("end"),at=0,ar=Math.ceil((aD-ay)*ao)+ae.left_offset,aA=ab.max(au),az;av.width=ar;av.height=(ap.height||aA);var aB=av.getContext("2d");aB.translate(ae.left_offset,0);if(ag.length>1){aB.globalAlpha=0.5;aB.globalCompositeOperation="source-over"}ab.each(ag,function(aF,aE){az=aF.draw_tile(aw[aE],aB,ax[aE],af,al,ao,aC)});if(az!==undefined){ae.tile_cache.set_elt(am,az);ae.show_tile(az,ao)}ac.resolve(az)});return ac},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},_draw_line_track_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.LinePainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new M(this,ah,ag,af,ac.data)},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ah;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{this.tiles_div.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*S*ad),ag=Math.ceil(S*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new w.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="bigwig"}else{if(ac.extra_info==="no_detail"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="bigwig"||ac.message||ac.extra_info==="no_detail"){return false}return true},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new k.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset.id,hda_ldda:ad.dataset.get("hda_ldda")},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var W=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};p(W.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},predraw_init:function(){},_draw:function(ag){var ae=this.view,af=ae.high-ae.low,aj=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/aj)*aj,ah=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ai=(ac-ae.low)/af*ah;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ai-1}));ac+=aj}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){this.display_modes=A;N.call(this,ad,ac,ag);this.drawables=[];if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=o(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}ab.each(this.drawables,function(ah){if(ah instanceof c||ah instanceof T){ah.change_mode("Coverage")}});this.update_icons();this.obj_type="CompositeTrack"};p(f.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(N.prototype.action_icons_def),to_dict:y.prototype.to_dict,add_drawable:y.prototype.add_drawable,unpack_drawables:y.prototype.unpack_drawables,change_mode:function(ac){N.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:q.prototype.can_draw,_get_drawables:function(){return this.drawables},show_group:function(){var af=new Q(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw({clear_tile_cache:true})},before_draw:function(){N.prototype.before_draw.call(this);var ad=ab.min(ab.map(this.drawables,function(ae){return ae.prefs.min_value})),ac=ab.max(ab.map(this.drawables,function(ae){return ae.prefs.max_value}));this.prefs.min_value=ad;this.prefs.max_value=ac;ab.each(this.drawables,function(ae){ae.prefs.min_value=ad;ae.prefs.max_value=ac})},update_all_min_max:function(){var ac=this;ab.each(this.drawables,function(ad){ad.prefs.min_value=ac.prefs.min_value;ad.prefs.max_value=ac.prefs.max_value});this.request_draw({clear_tile_cache:true})},postdraw_actions:function(ai,ac,al,ah){N.prototype.postdraw_actions.call(this,ai,ac,al,ah);var ag=-1;for(var ae=0;ae<ai.length;ae++){var aj=ai[ae].html_elt.find("canvas").height();if(aj>ag){ag=aj}}for(var ae=0;ae<ai.length;ae++){var af=ai[ae];if(af.html_elt.find("canvas").height()!==ag){this.draw_helper(af.region,af.resolution,al,{force:true,height:ag});af.html_elt.remove()}}var ad=this,ak=function(){ad.update_all_min_max()};this._add_yaxis_label("min",ak);this._add_yaxis_label("max",ak)}});var B=function(ac){N.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=config.root+"api/genomes//"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new w.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};p(B.prototype,q.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},predraw_init:function(){},can_draw:q.prototype.can_draw,draw_helper:function(ae,ad,af,ac){if(af>this.view.canvas_manager.char_width_px){this.tiles_div.show();return N.prototype.draw_helper.call(this,ae,ad,af,ac)}else{this.tiles_div.hide();return null}},can_subset:function(ac){return true},draw_tile:function(af,al,ag,ad,ai,am){var ae=this.data_manager.subset_entry(af,ai),ak=ae.data;var ac=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";for(var ah=0,aj=ak.length;ah<aj;ah++){al.fillStyle=this.view.get_base_color(ak[ah]);al.fillText(ak[ah],Math.floor(ah*am),10)}return new b(this,ai,ad,ac,ae)}});var h=function(ae,ad,af){var ac=this;this.display_modes=A;this.mode="Histogram";N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:k.get_random_color()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};p(h.prototype,q.prototype,N.prototype,{before_draw:function(){},draw_tile:function(ac,ad,ag,ae,af,ah){return this._draw_line_track_tile(ac,ad,ag,ae,af,ah)},can_subset:function(ac){return(ac.data[1][0]-ac.data[0][0]===1)},postdraw_actions:function(ad,ae,af,ac){this._add_yaxis_label("max");this._add_yaxis_label("min")}});var s=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);this.request_redraw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height};p(s.prototype,q.prototype,N.prototype,{draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,af,ae,ah);var ag=k.get_random_color(),ac=k.get_random_color([ag,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.set_painter_from_config();ad.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};p(c.prototype,q.prototype,N.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},postdraw_actions:function(am,ae,an,al){N.prototype.postdraw_actions.call(this,am,ae,an,al);var ag=this,ah;if(ag.filters_manager){var af=ag.filters_manager.filters;for(var aj=0;aj<af.length;aj++){af[aj].update_ui_elt()}var ai=false,ak,ad;for(ah=0;ah<am.length;ah++){if(am[ah].data.length){ak=am[ah].data[0];for(var aj=0;aj<af.length;aj++){ad=af[aj];if(ad.applies_to(ak)&&ad.min!==ad.max){ai=true;break}}}}if(ag.filters_available!==ai){ag.filters_available=ai;if(!ag.filters_available){ag.filters_manager.hide()}ag.update_icons()}}if(am[0] instanceof P){var ac=true;for(ah=0;ah<am.length;ah++){if(!am[ah].all_slotted){ac=false;break}}if(!ac){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (t.FeatureSlotter)(ag,af,z,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}return mode},get_canvas_height:function(ac,ag,ah,ad){if(ag==="Coverage"||ac.dataset_type==="bigwig"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(am.dataset_type==="bigwig"){return this._draw_line_track_tile(am,aq,ao,ar,af,aj)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae,function(aD){return ap.view.get_base_color(aD)});var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new P(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)}});var Z=function(ad,ac,ae){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ad,ac,ae);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Histogram color",type:"color",default_value:k.get_random_color()},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};p(Z.prototype,q.prototype,N.prototype,{draw_tile:function(ac,af,ai,ag,ah,aj){if(ac.dataset_type==="bigwig"){return this._draw_line_track_tile(ac,af,"Histogram",ag,ah,aj)}else{var ae=this.view,ad=new (this.painter)(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai,function(ak){return ae.get_base_color(ak)});ad.draw(af,af.canvas.width,af.canvas.height,aj);return new b(this,ah,ag,af.canvas,ac.data)}},get_canvas_height:function(ac,ag,ah,ae){if(ac.dataset_type==="bigwig"){return this.summary_draw_height}else{var af=new (this.painter)(null,null,null,this.prefs,ag);var ad=(this.dataset.get_metadata("sample_names")?this.dataset.get_metadata("sample_names").length:0);if(ad===0&&ac.data.length!==0){ad=ac.data[0][7].match(/,/g);if(ad===null){ad=1}else{ad=ad.length+1}}return af.get_required_height(ad)}},predraw_init:function(){var ac=[g.prototype.predraw_init.call(this)];if(!this.dataset.get_metadata("sample_names")){ac.push(this.dataset.fetch())}return ac},postdraw_actions:function(af,ag,ai,ad){N.prototype.postdraw_actions.call(this,af,ag,ai,ad);var ae=ab.filter(af,function(aj){return(aj instanceof M)});if(ae.length===0&&this.prefs.show_labels){var ac;if(this.container_div.find(".yaxislabel.variant").length===0){ac=this.prefs.summary_height/2;this.tiles_div.prepend($("<div/>").text("Summary").addClass("yaxislabel variant top").css({"font-size":ac+"px",top:(this.prefs.summary_height-ac)/2+"px"}));if(this.prefs.show_sample_data){var ah=this.dataset.get("metadata").get("sample_names").join("<br/>");this.tiles_div.prepend($("<div/>").html(ah).addClass("yaxislabel variant top sample").css({top:this.prefs.summary_height+2,}))}}ac=(this.mode==="Squish"?5:10)+"px";$(this.tiles_div).find(".sample").css({"font-size":ac,"line-height":ac});$(this.tiles_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel.variant").remove()}}});var T=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=k.get_random_color(),ac=k.get_random_color([af,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"min_value",label:"Histogram minimum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"max_value",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.request_draw({clear_tile_cache:true})}});this.prefs=this.config.values;this.painter=(ae.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};p(T.prototype,q.prototype,N.prototype,c.prototype);var d={CompositeTrack:f,DrawableGroup:Q,DiagonalHeatmapTrack:s,FeatureTrack:c,LineTrack:h,ReadTrack:T,VariantTrack:Z,VcfTrack:Z};var o=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Y,DrawableGroup:Q,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:s,ReadTrack:T,VariantTrack:Z,CompositeTrack:f,object_from_template:o}});
\ No newline at end of file
diff -r ba8555d1fed4b95e2882afd33c45be3300c00ded -r af1daa86ba5b713240fb3f7ccd607f3adb8c05a7 static/scripts/packed/viz/trackster_ui.js
--- a/static/scripts/packed/viz/trackster_ui.js
+++ b/static/scripts/packed/viz/trackster_ui.js
@@ -1,1 +1,1 @@
-define(["base","libs/underscore","viz/trackster/slotting","viz/trackster/painters","viz/trackster/tracks","viz/visualization"],function(a,f,e,c,d,h){var j=d.object_from_template;var b=function(l,k){if(!k){k={}}var m=new IconButtonCollection(f.map(l,function(n){return new IconButton(f.extend(n,k))}));return new IconButtonMenuView({collection:m})};var g=a.Base.extend({initialize:function(k){this.baseURL=k},createButtonMenu:function(){var k=this,l=b([{icon_class:"plus-button",title:"Add tracks",on_click:function(){h.select_datasets(config.url.select_datasets,config.url.datasets,{"f-dbkey":view.dbkey},function(m){f.each(m,function(n){view.add_drawable(j(n,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new d.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=k.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){show_modal("Saving...","progress");var m=[];$(".bookmark").each(function(){m.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var n=(view.overview_drawable?view.overview_drawable.name:null),o={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:n},bookmarks:m};$.ajax({url:config.url.visualization,type:"POST",dataType:"json",data:{id:view.vis_id,title:view.name,dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(o)}}).success(function(p){hide_modal();view.vis_id=p.vis_id;view.has_changes=false;window.history.pushState({},"",p.url+window.location.hash)}).error(function(){show_modal("Could Not Save","Could not save visualization. Please try again later.",{Close:hide_modal})})}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=l;return l},add_bookmarks:function(){var k=this,l=this.baseURL;show_modal("Select dataset for new bookmarks","progress");$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(m){show_modal("Select dataset for new bookmarks",m,{Cancel:function(){hide_modal()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var n,o=$(this).val();if($(this).attr("name")==="id"){n={hda_id:o}}else{n={ldda_id:o}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:n,dataType:"json"}).then(function(p){for(i=0;i<p.data.length;i++){var q=p.data[i];k.add_bookmark(q[0],q[1])}})});hide_modal()}})}})},add_bookmark:function(o,m,k){var q=$("#bookmarks-container"),s=$("<div/>").addClass("bookmark").appendTo(q);var t=$("<div/>").addClass("position").appendTo(s),p=$("<a href=''/>").text(o).appendTo(t).click(function(){view.go_to(o);return false}),n=$("<div/>").text(m).appendTo(s);if(k){var r=$("<div/>").addClass("delete-icon-container").prependTo(s).click(function(){s.slideUp("fast");s.remove();view.has_changes=true;return false}),l=$("<a href=''/>").addClass("icon-button delete").appendTo(r);n.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return s},create_visualization:function(p,k,o,q,n){var m=this,l=new d.TracksterView(p);l.editor=true;$.when(l.load_chroms_deferred).then(function(B){if(k){var z=k.chrom,r=k.start,w=k.end,t=k.overview;if(z&&(r!==undefined)&&w){l.change_chrom(z,r,w)}else{l.change_chrom(B[0].chrom)}}else{l.change_chrom(B[0].chrom)}if(o){var u,s,v;for(var x=0;x<o.length;x++){l.add_drawable(j(o[x],l,l))}}l.update_intro_div();var A;for(var x=0;x<l.drawables.length;x++){if(l.drawables[x].name===t){l.set_overview(l.drawables[x]);break}}if(q){var y;for(var x=0;x<q.length;x++){y=q[x];m.add_bookmark(y.position,y.annotation,n)}}l.has_changes=false});return l},init_keyboard_nav:function(k){$(document).keydown(function(l){if($(l.srcElement).is(":input")){return}switch(l.which){case 37:k.move_fraction(0.25);break;case 38:var m=Math.round(k.viewport_container.height()/15);k.viewport_container.scrollTop(k.viewport_container.scrollTop()-20);break;case 39:k.move_fraction(-0.25);break;case 40:var m=Math.round(k.viewport_container.height()/15);k.viewport_container.scrollTop(k.viewport_container.scrollTop()+20);break}})}});return{object_from_template:j,TracksterUI:g}});
\ No newline at end of file
+define(["base","libs/underscore","viz/trackster/slotting","viz/trackster/painters","viz/trackster/tracks","viz/visualization"],function(a,f,e,c,d,h){var j=d.object_from_template;var b=function(l,k){if(!k){k={}}var m=new IconButtonCollection(f.map(l,function(n){return new IconButton(f.extend(n,k))}));return new IconButtonMenuView({collection:m})};var g=a.Base.extend({initialize:function(k){this.baseURL=k},createButtonMenu:function(){var k=this,l=b([{icon_class:"plus-button",title:"Add tracks",on_click:function(){h.select_datasets(config.root+"visualization/list_current_history_datasets",config.root+"api/datasets",{"f-dbkey":view.dbkey},function(m){f.each(m,function(n){view.add_drawable(j(n,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new d.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=k.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){show_modal("Saving...","progress");var m=[];$(".bookmark").each(function(){m.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var n=(view.overview_drawable?view.overview_drawable.name:null),o={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:n},bookmarks:m};$.ajax({url:config.root+"visualization/save",type:"POST",dataType:"json",data:{id:view.vis_id,title:view.name,dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(o)}}).success(function(p){hide_modal();view.vis_id=p.vis_id;view.has_changes=false;window.history.pushState({},"",p.url+window.location.hash)}).error(function(){show_modal("Could Not Save","Could not save visualization. Please try again later.",{Close:hide_modal})})}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=l;return l},add_bookmarks:function(){var k=this,l=this.baseURL;show_modal("Select dataset for new bookmarks","progress");$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(m){show_modal("Select dataset for new bookmarks",m,{Cancel:function(){hide_modal()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var n,o=$(this).val();if($(this).attr("name")==="id"){n={hda_id:o}}else{n={ldda_id:o}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:n,dataType:"json"}).then(function(p){for(i=0;i<p.data.length;i++){var q=p.data[i];k.add_bookmark(q[0],q[1])}})});hide_modal()}})}})},add_bookmark:function(o,m,k){var q=$("#right .unified-panel-body"),s=$("<div/>").addClass("bookmark").appendTo(q);var t=$("<div/>").addClass("position").appendTo(s),p=$("<a href=''/>").text(o).appendTo(t).click(function(){view.go_to(o);return false}),n=$("<div/>").text(m).appendTo(s);if(k){var r=$("<div/>").addClass("delete-icon-container").prependTo(s).click(function(){s.slideUp("fast");s.remove();view.has_changes=true;return false}),l=$("<a href=''/>").addClass("icon-button delete").appendTo(r);n.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return s},create_visualization:function(p,k,o,q,n){var m=this,l=new d.TracksterView(p);l.editor=true;$.when(l.load_chroms_deferred).then(function(B){if(k){var z=k.chrom,r=k.start,w=k.end,t=k.overview;if(z&&(r!==undefined)&&w){l.change_chrom(z,r,w)}else{l.change_chrom(B[0].chrom)}}else{l.change_chrom(B[0].chrom)}if(o){var u,s,v;for(var x=0;x<o.length;x++){l.add_drawable(j(o[x],l,l))}}l.update_intro_div();var A;for(var x=0;x<l.drawables.length;x++){if(l.drawables[x].name===t){l.set_overview(l.drawables[x]);break}}if(q){var y;for(var x=0;x<q.length;x++){y=q[x];m.add_bookmark(y.position,y.annotation,n)}}l.has_changes=false});return l},init_keyboard_nav:function(k){$(document).keydown(function(l){if($(l.srcElement).is(":input")){return}switch(l.which){case 37:k.move_fraction(0.25);break;case 38:var m=Math.round(k.viewport_container.height()/15);k.viewport_container.scrollTop(k.viewport_container.scrollTop()-20);break;case 39:k.move_fraction(-0.25);break;case 40:var m=Math.round(k.viewport_container.height()/15);k.viewport_container.scrollTop(k.viewport_container.scrollTop()+20);break}})}});return{object_from_template:j,TracksterUI:g}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Include a file name export_info.xml to repository archives for repositories exported from the tool shed.
by commits-noreply@bitbucket.org 05 Aug '13
by commits-noreply@bitbucket.org 05 Aug '13
05 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/113fce3ecc3a/
Changeset: 113fce3ecc3a
User: greg
Date: 2013-08-05 22:45:16
Summary: Include a file name export_info.xml to repository archives for repositories exported from the tool shed.
Affected #: 1 file
diff -r 927bea0f9ae7077b5ed821968a772add98466db7 -r 113fce3ecc3a665d18b13d8b9f168c261bbf7594 lib/tool_shed/util/export_util.py
--- a/lib/tool_shed/util/export_util.py
+++ b/lib/tool_shed/util/export_util.py
@@ -4,6 +4,8 @@
import tarfile
import tempfile
import threading
+from time import gmtime
+from time import strftime
import tool_shed.util.shed_util_common as suc
from galaxy import eggs
from galaxy import web
@@ -97,9 +99,14 @@
elem = xml_util.create_element( 'repository', attributes=attributes, sub_elements=sub_elements )
exported_repository_registry.exported_repository_elems.append( elem )
shutil.rmtree( work_dir )
+ # Keep information about the export in a file name export_info.xml in the archive.
+ sub_elements = generate_export_elem( tool_shed_url, repository, changeset_revision, export_repository_dependencies, api )
+ export_elem = xml_util.create_element( 'export_info', attributes=None, sub_elements=sub_elements )
+ tmp_export_info = xml_util.create_and_write_tmp_file( export_elem, use_indent=True )
+ repositories_archive.add( tmp_export_info, arcname='export_info.xml' )
# Write the manifest, which must preserve the order in which the repositories should be imported.
- tmp_xml_file = xml_util.create_and_write_tmp_file( exported_repository_registry.exported_repository_elems, use_indent=True )
- repositories_archive.add( tmp_xml_file, arcname='manifest.xml' )
+ tmp_manifest = xml_util.create_and_write_tmp_file( exported_repository_registry.exported_repository_elems, use_indent=True )
+ repositories_archive.add( tmp_manifest, arcname='manifest.xml' )
except Exception, e:
log.exception( str( e ) )
finally:
@@ -161,6 +168,17 @@
repositories_archive_filename = os.path.join( tmp_archive_dir, repositories_archive_filename )
return repositories_archive_filename
+def generate_export_elem( tool_shed_url, repository, changeset_revision, export_repository_dependencies, api ):
+ sub_elements = odict()
+ sub_elements[ 'export_time' ] = strftime( '%a, %d %b %Y %H:%M:%S +0000', gmtime() )
+ sub_elements[ 'tool_shed' ] = str( tool_shed_url.rstrip( '/' ) )
+ sub_elements[ 'repository_name' ] = str( repository.name )
+ sub_elements[ 'repository_owner' ] = str( repository.user.username )
+ sub_elements[ 'changeset_revision' ] = str( changeset_revision )
+ sub_elements[ 'export_repository_dependencies' ] = str( export_repository_dependencies )
+ sub_elements[ 'exported_via_api' ] = str( api )
+ return sub_elements
+
def get_components_from_repo_info_dict( trans, repo_info_dict ):
"""
Return the repository and the associated latest installable changeset_revision (including updates) for the repository defined by the received
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2acb664c5185/
Changeset: 2acb664c5185
Branch: next-stable
User: natefoo
Date: 2013-08-05 22:06:31
Summary: Don't allow exceptions in set_metadata.py to hang the process when the distributed object store's free space monitor is in use. Also, don't run the monitor unless the object store is started inside the Galaxy application.
Affected #: 2 files
diff -r a2fcb4655e0faa0bebb062a54cad05e448ed6c51 -r 2acb664c5185727bfbf37166dbdcef4cb30eb797 lib/galaxy/app.py
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -54,7 +54,7 @@
from tool_shed.galaxy_install.migrate.check import verify_tools
verify_tools( self, db_url, kwargs.get( 'global_conf', {} ).get( '__file__', None ), self.config.database_engine_options )
# Object store manager
- self.object_store = build_object_store_from_config(self.config)
+ self.object_store = build_object_store_from_config(self.config, fsmon=True)
# Setup the database engine and ORM
from galaxy.model import mapping
self.model = mapping.init( self.config.file_path,
diff -r a2fcb4655e0faa0bebb062a54cad05e448ed6c51 -r 2acb664c5185727bfbf37166dbdcef4cb30eb797 lib/galaxy/objectstore/__init__.py
--- a/lib/galaxy/objectstore/__init__.py
+++ b/lib/galaxy/objectstore/__init__.py
@@ -864,7 +864,7 @@
store selected randomly, but with weighting.
"""
- def __init__(self, config):
+ def __init__(self, config, fsmon=False):
super(DistributedObjectStore, self).__init__()
self.distributed_config = config.distributed_object_store_config_file
assert self.distributed_config is not None, "distributed object store ('object_store = distributed') " \
@@ -881,9 +881,10 @@
self.__parse_distributed_config(config)
self.sleeper = None
- if self.global_max_percent_full or filter(lambda x: x != 0.0, self.max_percent_full.values()):
+ if fsmon and ( self.global_max_percent_full or filter( lambda x: x != 0.0, self.max_percent_full.values() ) ):
self.sleeper = Sleeper()
self.filesystem_monitor_thread = threading.Thread(target=self.__filesystem_monitor)
+ self.filesystem_monitor_thread.setDaemon( True )
self.filesystem_monitor_thread.start()
log.info("Filesystem space monitor started")
@@ -1020,7 +1021,7 @@
def __init__(self, backends=[]):
super(HierarchicalObjectStore, self).__init__()
-def build_object_store_from_config(config):
+def build_object_store_from_config(config, fsmon=False):
""" Depending on the configuration setting, invoke the appropriate object store
"""
store = config.object_store
@@ -1029,7 +1030,7 @@
elif store == 's3' or store == 'swift':
return S3ObjectStore(config=config)
elif store == 'distributed':
- return DistributedObjectStore(config=config)
+ return DistributedObjectStore(config=config, fsmon=fsmon)
elif store == 'hierarchical':
return HierarchicalObjectStore()
else:
https://bitbucket.org/galaxy/galaxy-central/commits/6053d0aa63cc/
Changeset: 6053d0aa63cc
Branch: next-stable
User: natefoo
Date: 2013-08-05 22:06:55
Summary: Bug fix for job recovery in the Condor runner.
Affected #: 1 file
diff -r 2acb664c5185727bfbf37166dbdcef4cb30eb797 -r 6053d0aa63cc1e9f295c7a36787d064d754de7ef lib/galaxy/jobs/runners/condor.py
--- a/lib/galaxy/jobs/runners/condor.py
+++ b/lib/galaxy/jobs/runners/condor.py
@@ -246,12 +246,12 @@
if job_id is None:
self.put( job_wrapper )
return
- cjs = CondorJobState()
+ cjs = CondorJobState( job_wrapper=job_wrapper, files_dir=self.app.config.cluster_files_directory )
cjs.job_id = str( job_id )
cjs.command_line = job.get_command_line()
cjs.job_wrapper = job_wrapper
cjs.job_destination = job_wrapper.job_destination
- cjs.user_log = os.path.join( self.app.config.cluster_files_directory, '%s.condor.log' % galaxy_id_tag )
+ cjs.user_log = os.path.join( self.app.config.cluster_files_directory, 'galaxy_%s.condor.log' % galaxy_id_tag )
cjs.register_cleanup_file_attribute( 'user_log' )
self.__old_state_paths( cjs )
if job.state == model.Job.states.RUNNING:
@@ -268,9 +268,9 @@
files in the AsychronousJobState object
"""
if cjs.job_wrapper is not None:
- user_log = "%s/%s.condor.log" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- if not os.path.exists( cjs.job_file ) and os.path.exists( job_file ):
- cjs.output_file = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- cjs.error_file = "%s/%s.e" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- cjs.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
+ user_log = "%s/%s.condor.log" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
+ if not os.path.exists( cjs.user_log ) and os.path.exists( user_log ):
+ cjs.output_file = "%s/%s.o" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
+ cjs.error_file = "%s/%s.e" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
+ cjs.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
cjs.user_log = user_log
https://bitbucket.org/galaxy/galaxy-central/commits/927bea0f9ae7/
Changeset: 927bea0f9ae7
User: natefoo
Date: 2013-08-05 22:08:10
Summary: Merge next-stable.
Affected #: 3 files
diff -r bd469f8d2944f2719fb4fca7078e06e6411c86a3 -r 927bea0f9ae7077b5ed821968a772add98466db7 lib/galaxy/app.py
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -54,7 +54,7 @@
from tool_shed.galaxy_install.migrate.check import verify_tools
verify_tools( self, db_url, kwargs.get( 'global_conf', {} ).get( '__file__', None ), self.config.database_engine_options )
# Object store manager
- self.object_store = build_object_store_from_config(self.config)
+ self.object_store = build_object_store_from_config(self.config, fsmon=True)
# Setup the database engine and ORM
from galaxy.model import mapping
self.model = mapping.init( self.config.file_path,
diff -r bd469f8d2944f2719fb4fca7078e06e6411c86a3 -r 927bea0f9ae7077b5ed821968a772add98466db7 lib/galaxy/jobs/runners/condor.py
--- a/lib/galaxy/jobs/runners/condor.py
+++ b/lib/galaxy/jobs/runners/condor.py
@@ -246,12 +246,12 @@
if job_id is None:
self.put( job_wrapper )
return
- cjs = CondorJobState()
+ cjs = CondorJobState( job_wrapper=job_wrapper, files_dir=self.app.config.cluster_files_directory )
cjs.job_id = str( job_id )
cjs.command_line = job.get_command_line()
cjs.job_wrapper = job_wrapper
cjs.job_destination = job_wrapper.job_destination
- cjs.user_log = os.path.join( self.app.config.cluster_files_directory, '%s.condor.log' % galaxy_id_tag )
+ cjs.user_log = os.path.join( self.app.config.cluster_files_directory, 'galaxy_%s.condor.log' % galaxy_id_tag )
cjs.register_cleanup_file_attribute( 'user_log' )
self.__old_state_paths( cjs )
if job.state == model.Job.states.RUNNING:
@@ -268,9 +268,9 @@
files in the AsychronousJobState object
"""
if cjs.job_wrapper is not None:
- user_log = "%s/%s.condor.log" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- if not os.path.exists( cjs.job_file ) and os.path.exists( job_file ):
- cjs.output_file = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- cjs.error_file = "%s/%s.e" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- cjs.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
+ user_log = "%s/%s.condor.log" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
+ if not os.path.exists( cjs.user_log ) and os.path.exists( user_log ):
+ cjs.output_file = "%s/%s.o" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
+ cjs.error_file = "%s/%s.e" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
+ cjs.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, cjs.job_wrapper.job_id)
cjs.user_log = user_log
diff -r bd469f8d2944f2719fb4fca7078e06e6411c86a3 -r 927bea0f9ae7077b5ed821968a772add98466db7 lib/galaxy/objectstore/__init__.py
--- a/lib/galaxy/objectstore/__init__.py
+++ b/lib/galaxy/objectstore/__init__.py
@@ -864,7 +864,7 @@
store selected randomly, but with weighting.
"""
- def __init__(self, config):
+ def __init__(self, config, fsmon=False):
super(DistributedObjectStore, self).__init__()
self.distributed_config = config.distributed_object_store_config_file
assert self.distributed_config is not None, "distributed object store ('object_store = distributed') " \
@@ -881,9 +881,10 @@
self.__parse_distributed_config(config)
self.sleeper = None
- if self.global_max_percent_full or filter(lambda x: x != 0.0, self.max_percent_full.values()):
+ if fsmon and ( self.global_max_percent_full or filter( lambda x: x != 0.0, self.max_percent_full.values() ) ):
self.sleeper = Sleeper()
self.filesystem_monitor_thread = threading.Thread(target=self.__filesystem_monitor)
+ self.filesystem_monitor_thread.setDaemon( True )
self.filesystem_monitor_thread.start()
log.info("Filesystem space monitor started")
@@ -1020,7 +1021,7 @@
def __init__(self, backends=[]):
super(HierarchicalObjectStore, self).__init__()
-def build_object_store_from_config(config):
+def build_object_store_from_config(config, fsmon=False):
""" Depending on the configuration setting, invoke the appropriate object store
"""
store = config.object_store
@@ -1029,7 +1030,7 @@
elif store == 's3' or store == 'swift':
return S3ObjectStore(config=config)
elif store == 'distributed':
- return DistributedObjectStore(config=config)
+ return DistributedObjectStore(config=config, fsmon=fsmon)
elif store == 'hierarchical':
return HierarchicalObjectStore()
else:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Enhance the generated name of the archive file created when exporting a tool shed repository.
by commits-noreply@bitbucket.org 05 Aug '13
by commits-noreply@bitbucket.org 05 Aug '13
05 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bd469f8d2944/
Changeset: bd469f8d2944
User: greg
Date: 2013-08-05 21:59:49
Summary: Enhance the generated name of the archive file created when exporting a tool shed repository.
Affected #: 3 files
diff -r cf08022b68927bebe340c976e6d5eb7a657de7d6 -r bd469f8d2944f2719fb4fca7078e06e6411c86a3 lib/galaxy/webapps/tool_shed/api/repository_revisions.py
--- a/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
+++ b/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
@@ -54,7 +54,6 @@
try:
# We'll currently support only gzip-compressed tar archives.
file_type = 'gz'
- file_type_str = suc.get_file_type_str( changeset_revision, file_type )
export_repository_dependencies = util.string_as_bool( export_repository_dependencies )
# Get the repository information.
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
diff -r cf08022b68927bebe340c976e6d5eb7a657de7d6 -r bd469f8d2944f2719fb4fca7078e06e6411c86a3 lib/tool_shed/scripts/api/export.py
--- a/lib/tool_shed/scripts/api/export.py
+++ b/lib/tool_shed/scripts/api/export.py
@@ -13,6 +13,7 @@
sys.path.insert( 0, os.path.dirname( __file__ ) )
from common import display
from common import submit
+from tool_shed.util import export_util
CHUNK_SIZE = 2**20 # 1Mb
@@ -54,17 +55,20 @@
if repository_id:
# We'll currently support only gzip-compressed tar archives.
file_type = 'gz'
- file_type_str = get_file_type_str( options.changeset_revision, file_type )
url = '%s%s' % ( base_tool_shed_url, '/api/repository_revisions/%s/export' % str( repository_id ) )
export_dict = submit( url, data, return_formatted=False )
error_messages = export_dict[ 'error_messages' ]
if error_messages:
print "Error attempting to export revision ", options.changeset_revision, " of repository ", options.name, " owned by ", options.owner, ":\n", error_messages
else:
- if string_as_bool( options.export_repository_dependencies ):
- repositories_archive_filename = 'exported-with-dependencies-%s-%s' % ( name, file_type_str )
- else:
- repositories_archive_filename = 'exported-%s-%s' % ( name, file_type_str )
+ repositories_archive_filename = \
+ export_util.generate_repository_archive_filename( base_tool_shed_url,
+ options.name,
+ options.owner,
+ options.changeset_revision,
+ file_type,
+ export_repository_dependencies=string_as_bool( options.export_repository_dependencies ),
+ use_tmp_archive_dir=False )
download_url = export_dict[ 'download_url' ]
download_dir = os.path.abspath( options.download_dir )
file_path = os.path.join( download_dir, repositories_archive_filename )
diff -r cf08022b68927bebe340c976e6d5eb7a657de7d6 -r bd469f8d2944f2719fb4fca7078e06e6411c86a3 lib/tool_shed/util/export_util.py
--- a/lib/tool_shed/util/export_util.py
+++ b/lib/tool_shed/util/export_util.py
@@ -24,6 +24,8 @@
log = logging.getLogger( __name__ )
+CAPSULE_FILENAME = 'capsule'
+CAPSULE_WITH_DEPENDENCIES_FILENAME = 'capsule_with_dependencies'
class ExportedRepositoryRegistry( object ):
@@ -45,11 +47,22 @@
log.exception( error_message )
return return_code, error_message
+def clean_tool_shed_url( base_url ):
+ protocol, base = base_url.split( '://' )
+ base = base.replace( ':', '_colon_' )
+ base = base.rstrip( '/' )
+ return base
+
def export_repository( trans, tool_shed_url, repository_id, repository_name, changeset_revision, file_type, export_repository_dependencies, api=False ):
- file_type_str = suc.get_file_type_str( changeset_revision, file_type )
- tmp_archive_dir = tempfile.mkdtemp( prefix="tmp-toolshed-arcdir" )
+ repository = suc.get_repository_in_tool_shed( trans, repository_id )
+ repositories_archive_filename = generate_repository_archive_filename( tool_shed_url,
+ str( repository.name ),
+ str( repository.user.username ),
+ changeset_revision,
+ file_type,
+ export_repository_dependencies=export_repository_dependencies,
+ use_tmp_archive_dir=True )
if export_repository_dependencies:
- repositories_archive_filename = os.path.join( tmp_archive_dir, 'exported-with-dependencies-%s-%s' % ( repository_name, file_type_str ) )
repo_info_dicts = get_repo_info_dicts( trans, tool_shed_url, repository_id, changeset_revision )
repository_ids = get_repository_ids( trans, repo_info_dicts )
ordered_repository_ids, ordered_repositories, ordered_changeset_revisions = order_components_for_import( trans, repository_ids, repo_info_dicts )
@@ -57,8 +70,6 @@
ordered_repository_ids = []
ordered_repositories = []
ordered_changeset_revisions = []
- repositories_archive_filename = os.path.join( tmp_archive_dir, 'exported-%s-%s' % ( repository_name, file_type_str ) )
- repository = suc.get_repository_in_tool_shed( trans, repository_id )
if repository:
repository_metadata = suc.get_current_repository_metadata_for_changeset_revision( trans, repository, changeset_revision )
if repository_metadata:
@@ -138,6 +149,18 @@
repository_archive.close()
return repository_archive, error_message
+def generate_repository_archive_filename( tool_shed_url, name, owner, changeset_revision, file_type, export_repository_dependencies=False, use_tmp_archive_dir=False ):
+ tool_shed = clean_tool_shed_url( tool_shed_url )
+ file_type_str = suc.get_file_type_str( changeset_revision, file_type )
+ if export_repository_dependencies:
+ repositories_archive_filename = '%s_%s_%s_%s_%s' % ( CAPSULE_WITH_DEPENDENCIES_FILENAME, tool_shed, name, owner, file_type_str )
+ else:
+ repositories_archive_filename = '%s_%s_%s_%s_%s' % ( CAPSULE_FILENAME, tool_shed, name, owner, file_type_str )
+ if use_tmp_archive_dir:
+ tmp_archive_dir = tempfile.mkdtemp( prefix="tmp-toolshed-arcdir" )
+ repositories_archive_filename = os.path.join( tmp_archive_dir, repositories_archive_filename )
+ return repositories_archive_filename
+
def get_components_from_repo_info_dict( trans, repo_info_dict ):
"""
Return the repository and the associated latest installable changeset_revision (including updates) for the repository defined by the received
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Do not display the same repository multiple times on the Monitor installing tool shed repositories page when installing / reinstalling repositories into Galaxy.
by commits-noreply@bitbucket.org 05 Aug '13
by commits-noreply@bitbucket.org 05 Aug '13
05 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cf08022b6892/
Changeset: cf08022b6892
User: greg
Date: 2013-08-05 20:05:38
Summary: Do not display the same repository multiple times on the Monitor installing tool shed repositories page when installing / reinstalling repositories into Galaxy.
Affected #: 3 files
diff -r 901808e8e65eed49de6cb42f2cd1ebac0d5eabb8 -r cf08022b68927bebe340c976e6d5eb7a657de7d6 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -1054,18 +1054,19 @@
no_changes_checked=no_changes_checked,
tool_panel_section=tool_panel_section,
new_tool_panel_section=new_tool_panel_section )
- # The repository's status must be updated from 'Uninstall' to 'New' when initiating reinstall so the repository_installation_updater will function.
- tool_shed_repository = suc.create_or_update_tool_shed_repository( trans.app,
- tool_shed_repository.name,
- tool_shed_repository.description,
- tool_shed_repository.installed_changeset_revision,
- tool_shed_repository.ctx_rev,
- repository_clone_url,
- metadata,
- trans.model.ToolShedRepository.installation_status.NEW,
- tool_shed_repository.installed_changeset_revision,
- tool_shed_repository.owner,
- tool_shed_repository.dist_to_shed )
+ if tool_shed_repository.status == trans.model.ToolShedRepository.installation_status.UNINSTALLED:
+ # The repository's status must be updated from 'Uninstalled' to 'New' when initiating reinstall so the repository_installation_updater will function.
+ tool_shed_repository = suc.create_or_update_tool_shed_repository( trans.app,
+ tool_shed_repository.name,
+ tool_shed_repository.description,
+ tool_shed_repository.installed_changeset_revision,
+ tool_shed_repository.ctx_rev,
+ repository_clone_url,
+ metadata,
+ trans.model.ToolShedRepository.installation_status.NEW,
+ tool_shed_repository.installed_changeset_revision,
+ tool_shed_repository.owner,
+ tool_shed_repository.dist_to_shed )
ctx_rev = suc.get_ctx_rev( trans.app,
tool_shed_url,
tool_shed_repository.name,
@@ -1096,7 +1097,8 @@
repository_metadata=None,
tool_dependencies=tool_dependencies,
repository_dependencies=repository_dependencies )
- repo_info_dicts.append( repo_info_dict )
+ if repo_info_dict not in repo_info_dicts:
+ repo_info_dicts.append( repo_info_dict )
# Make sure all tool_shed_repository records exist.
created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts = \
repository_dependency_util.create_repository_dependency_objects( trans=trans,
@@ -1107,7 +1109,7 @@
install_repository_dependencies=install_repository_dependencies,
no_changes_checked=no_changes_checked,
tool_panel_section=tool_panel_section,
- new_tool_panel_section=new_tool_panel_section )
+ new_tool_panel_section=new_tool_panel_section )
# Default the selected tool panel location for loading tools included in each newly installed required tool shed repository to the location
# selected for the repository selected for reinstallation.
for index, tps_key in enumerate( tool_panel_section_keys ):
diff -r 901808e8e65eed49de6cb42f2cd1ebac0d5eabb8 -r cf08022b68927bebe340c976e6d5eb7a657de7d6 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -231,14 +231,16 @@
current_changeset_revision=changeset_revision,
owner=repository_owner,
dist_to_shed=False )
- # Add the processed tool shed repository to the list of all processed repositories maintained within this method.
- all_created_or_updated_tool_shed_repositories.append( tool_shed_repository )
+ if tool_shed_repository not in all_created_or_updated_tool_shed_repositories:
+ # Add the processed tool shed repository to the list of all processed repositories maintained within this method.
+ all_created_or_updated_tool_shed_repositories.append( tool_shed_repository )
# Only append the tool shed repository to the list of created_or_updated_tool_shed_repositories if it is supposed to be installed.
if install_repository_dependencies or is_in_repo_info_dicts( repo_info_dict, repo_info_dicts ):
- # Keep the one-to-one mapping between items in 3 lists.
- created_or_updated_tool_shed_repositories.append( tool_shed_repository )
- tool_panel_section_keys.append( tool_panel_section_key )
- filtered_repo_info_dicts.append( repo_info_dict )
+ if tool_shed_repository not in created_or_updated_tool_shed_repositories:
+ # Keep the one-to-one mapping between items in 3 lists.
+ created_or_updated_tool_shed_repositories.append( tool_shed_repository )
+ tool_panel_section_keys.append( tool_panel_section_key )
+ filtered_repo_info_dicts.append( repo_info_dict )
# Build repository dependency relationships even if the user chose to not install repository dependencies.
build_repository_dependency_relationships( trans, all_repo_info_dicts, all_created_or_updated_tool_shed_repositories )
return created_or_updated_tool_shed_repositories, tool_panel_section_keys, all_repo_info_dicts, filtered_repo_info_dicts
diff -r 901808e8e65eed49de6cb42f2cd1ebac0d5eabb8 -r cf08022b68927bebe340c976e6d5eb7a657de7d6 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -242,7 +242,7 @@
"""
# The received value for dist_to_shed will be True if the InstallManager is installing a repository that contains tools or datatypes that used
# to be in the Galaxy distribution, but have been moved to the main Galaxy tool shed.
- log.debug( "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % name )
+ log.debug( "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table, status set to '%s'." % ( str( name ), str( status ) ) )
if current_changeset_revision is None:
# The current_changeset_revision is not passed if a repository is being installed for the first time. If a previously installed repository
# was later uninstalled, this value should be received as the value of that change set to which the repository had been updated just prior
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Fix issue where a tool shed functional test was failing. Only allow hours between check to be less than 1 when running functional tests.
by commits-noreply@bitbucket.org 05 Aug '13
by commits-noreply@bitbucket.org 05 Aug '13
05 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/901808e8e65e/
Changeset: 901808e8e65e
User: Dave Bouvier
Date: 2013-08-05 16:17:10
Summary: Fix issue where a tool shed functional test was failing. Only allow hours between check to be less than 1 when running functional tests.
Affected #: 1 file
diff -r 2060df75cb2817fa567853af141c11b53d1ea0da -r 901808e8e65eed49de6cb42f2cd1ebac0d5eabb8 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -76,21 +76,24 @@
self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root )
self.shed_tool_data_table_config = resolve_path( kwargs.get( 'shed_tool_data_table_config', 'shed_tool_data_table_conf.xml' ), self.root )
self.enable_tool_shed_check = string_as_bool( kwargs.get( 'enable_tool_shed_check', False ) )
+ self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
self.hours_between_check = kwargs.get( 'hours_between_check', 12 )
try:
- hbc_test = int( self.hours_between_check )
- self.hours_between_check = hbc_test
- if self.hours_between_check < 1 or self.hours_between_check > 24:
+ if isinstance( self.hours_between_check, int ):
+ if self.hours_between_check < 1 or self.hours_between_check > 24:
+ self.hours_between_check = 12
+ elif isinstance( self.hours_between_check, float ):
+ # If we're running functional tests, the minimum hours between check should be reduced to 0.001, or 3.6 seconds.
+ if self.running_functional_tests:
+ if self.hours_between_check < 0.001 or self.hours_between_check > 24.0:
+ self.hours_between_check = 12.0
+ else:
+ if self.hours_between_check < 1.0 or self.hours_between_check > 24.0:
+ self.hours_between_check = 12.0
+ else:
self.hours_between_check = 12
except:
- try:
- # Float values are supported for functional tests.
- hbc_test = float( self.hours_between_check )
- self.hours_between_check = hbc_test
- if self.hours_between_check < 0.001 or self.hours_between_check > 24.0:
- self.hours_between_check = 12.0
- except:
- self.hours_between_check = 12
+ self.hours_between_check = 12
self.update_integrated_tool_panel = kwargs.get( "update_integrated_tool_panel", True )
self.enable_data_manager_user_view = string_as_bool( kwargs.get( "enable_data_manager_user_view", "False" ) )
self.data_manager_config_file = resolve_path( kwargs.get('data_manager_config_file', 'data_manager_conf.xml' ), self.root )
@@ -276,7 +279,6 @@
self.biostar_url = kwargs.get( 'biostar_url', None )
self.biostar_key_name = kwargs.get( 'biostar_key_name', None )
self.biostar_key = kwargs.get( 'biostar_key', None )
- self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
# Experimental: This will not be enabled by default and will hide
# nonproduction code.
# The api_folders refers to whether the API exposes the /folders section.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Andrew Robinson: Fixed a clobbering of 'util' package in the permissions API.
by commits-noreply@bitbucket.org 05 Aug '13
by commits-noreply@bitbucket.org 05 Aug '13
05 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2060df75cb28/
Changeset: 2060df75cb28
User: Andrew Robinson
Date: 2013-08-05 04:17:52
Summary: Fixed a clobbering of 'util' package in the permissions API.
- used a qualified import to avoid a module name clobbering. This addresses the "AttributeError: 'module' object has no attribute 'Params'" exception when updating permissions via the GalaxyAPI.
Affected #: 1 file
diff -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a -r 2060df75cb2817fa567853af141c11b53d1ea0da lib/galaxy/webapps/galaxy/api/permissions.py
--- a/lib/galaxy/webapps/galaxy/api/permissions.py
+++ b/lib/galaxy/webapps/galaxy/api/permissions.py
@@ -3,7 +3,8 @@
"""
import logging, os, string, shutil, urllib, re, socket
from cgi import escape, FieldStorage
-from galaxy import util, datatypes, jobs, web, util
+import galaxy.util
+from galaxy import util, datatypes, jobs, web
from galaxy.web.base.controller import *
from galaxy.util.sanitize_html import sanitize_html
from galaxy.model.orm import *
@@ -23,7 +24,7 @@
trans.response.status = 403
return "You are not authorized to update library permissions."
- params = util.Params( payload )
+ params = galaxy.util.Params( payload )
try:
decoded_library_id = trans.security.decode_id( library_id )
except TypeError:
@@ -38,7 +39,7 @@
permissions = {}
for k, v in trans.app.model.Library.permitted_actions.items():
role_params = params.get( k + '_in', [] )
- in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in util.listify( role_params ) ]
+ in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in galaxy.util.listify( role_params ) ]
permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
trans.app.security_agent.set_all_library_permissions( trans, library, permissions )
trans.sa_session.refresh( library )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
02 Aug '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8ca6cfea1909/
Changeset: 8ca6cfea1909
User: greg
Date: 2013-08-03 01:30:03
Summary: Add the ability to export a specified repository revision from the tool shed to a gzip compressed archive saved locally. The ability to import this archive to the same or another tool shed is not yet implemented, but coming soon. All of the repository's repository dependencies can optionally be exported into the same archive. The archive includes a manifest.xml file that contains the order in whcih the repositories in the archive must be imported.
This feature is now available for any installable revision of a repository using the new "Export this revision" option in the Repository actions menu in the browser. It is also available via the Tool Shed API using a command like the following:
export.py --url http://testtoolshed.g2.bx.psu.edu --name chemicaltoolbox --owner bgruening --revision 4133dbf7ff4d --export_repository_dependencies True --download_dir /tmp
Affected #: 20 files
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/galaxy/webapps/tool_shed/api/repository_revisions.py
--- a/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
+++ b/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
@@ -6,6 +6,8 @@
from galaxy import util
from galaxy.model.orm import and_, not_, select
from galaxy.web.base.controller import BaseAPIController
+from tool_shed.util import export_util
+import tool_shed.util.shed_util_common as suc
log = logging.getLogger( __name__ )
@@ -20,6 +22,58 @@
class RepositoryRevisionsController( BaseAPIController ):
"""RESTful controller for interactions with tool shed repository revisions."""
+ @web.expose_api_anonymous
+ def export( self, trans, payload, **kwd ):
+ """
+ POST /api/repository_revisions/export
+ Creates and saves a gzip compressed tar archive of a repository and optionally all of it's repository dependencies.
+
+ The following parameters are included in the payload.
+ :param tool_shed_url (required): the base URL of the Tool Shed from which the Repository was installed
+ :param name (required): the name of the Repository
+ :param owner (required): the owner of the Repository
+ :param changset_revision (required): the changset_revision of the RepositoryMetadata object associated with the Repository
+ :param export_repository_dependencies (optional): whether to export repository dependencies - defaults to False
+ :param download_dir (optional): the local directory to which to download the archive - defaults to /tmp
+ """
+ tool_shed_url = payload.get( 'tool_shed_url', '' )
+ if not tool_shed_url:
+ raise HTTPBadRequest( detail="Missing required parameter 'tool_shed_url'." )
+ tool_shed_url = tool_shed_url.rstrip( '/' )
+ name = payload.get( 'name', '' )
+ if not name:
+ raise HTTPBadRequest( detail="Missing required parameter 'name'." )
+ owner = payload.get( 'owner', '' )
+ if not owner:
+ raise HTTPBadRequest( detail="Missing required parameter 'owner'." )
+ changeset_revision = payload.get( 'changeset_revision', '' )
+ if not changeset_revision:
+ raise HTTPBadRequest( detail="Missing required parameter 'changeset_revision'." )
+ export_repository_dependencies = payload.get( 'export_repository_dependencies', False )
+ download_dir = payload.get( 'download_dir', '/tmp' )
+ try:
+ # We'll currently support only gzip-compressed tar archives.
+ file_type = 'gz'
+ file_type_str = suc.get_file_type_str( changeset_revision, file_type )
+ export_repository_dependencies = util.string_as_bool( export_repository_dependencies )
+ # Get the repository information.
+ repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
+ repository_id = trans.security.encode_id( repository.id )
+ response = export_util.export_repository( trans,
+ tool_shed_url,
+ repository_id,
+ str( repository.name ),
+ changeset_revision,
+ file_type,
+ export_repository_dependencies,
+ api=True )
+ return response
+ except Exception, e:
+ message = "Error in the Tool Shed repository_revisions API in export: %s" % str( e )
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return message
+
@web.expose_api
def index( self, trans, **kwd ):
"""
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/galaxy/webapps/tool_shed/buildapp.py
--- a/lib/galaxy/webapps/tool_shed/buildapp.py
+++ b/lib/galaxy/webapps/tool_shed/buildapp.py
@@ -86,6 +86,7 @@
parent_resources=dict( member_name='repository', collection_name='repositories' ) )
webapp.mapper.resource( 'repository_revision',
'repository_revisions',
+ member={ 'export' : 'POST' },
controller='repository_revisions',
name_prefix='repository_revision_',
path_prefix='/api',
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -18,6 +18,7 @@
from galaxy.model.orm import and_
import tool_shed.util.shed_util_common as suc
from tool_shed.util import encoding_util
+from tool_shed.util import export_util
from tool_shed.util import metadata_util
from tool_shed.util import readme_util
from tool_shed.util import repository_dependency_util
@@ -1064,25 +1065,101 @@
@web.expose
def download( self, trans, repository_id, changeset_revision, file_type, **kwd ):
- # Download an archive of the repository files compressed as zip, gz or bz2.
+ """Download an archive of the repository files compressed as zip, gz or bz2."""
+ # FIXME: thgis will currently only download the repository tip, no matter which installable changeset_revision is being viewed.
+ # This should be enhanced to use the export method below, which accounts for the currently viewed changeset_revision.
repository = suc.get_repository_in_tool_shed( trans, repository_id )
# Allow hgweb to handle the download. This requires the tool shed
# server account's .hgrc file to include the following setting:
# [web]
# allow_archive = bz2, gz, zip
- if file_type == 'zip':
- file_type_str = '%s.zip' % changeset_revision
- elif file_type == 'bz2':
- file_type_str = '%s.tar.bz2' % changeset_revision
- elif file_type == 'gz':
- file_type_str = '%s.tar.gz' % changeset_revision
+ file_type_str = suc.get_file_type_str( changeset_revision, file_type )
repository.times_downloaded += 1
trans.sa_session.add( repository )
trans.sa_session.flush()
- download_url = '/repos/%s/%s/archive/%s' % ( repository.user.username, repository.name, file_type_str )
+ download_url = suc.url_join( '/', 'repos', repository.user.username, repository.name, 'archive', file_type_str )
return trans.response.send_redirect( download_url )
@web.expose
+ def export( self, trans, repository_id, changeset_revision, **kwd ):
+ message = kwd.get( 'message', '' )
+ status = kwd.get( 'status', 'done' )
+ export_repository_dependencies = kwd.get( 'export_repository_dependencies', '' )
+ repository = suc.get_repository_in_tool_shed( trans, repository_id )
+ if kwd.get( 'export_repository_button', False ):
+ # We'll currently support only gzip-compressed tar archives.
+ file_type = 'gz'
+ export_repository_dependencies = CheckboxField.is_checked( export_repository_dependencies )
+ tool_shed_url = web.url_for( '/', qualified=True )
+ repositories_archive, error_message = export_util.export_repository( trans,
+ tool_shed_url,
+ repository_id,
+ str( repository.name ),
+ changeset_revision,
+ file_type,
+ export_repository_dependencies )
+ repositories_archive_filename = os.path.basename( repositories_archive.name )
+ if error_message:
+ message = error_message
+ else:
+ trans.response.set_content_type( 'application/x-gzip' )
+ trans.response.headers[ "Content-Disposition" ] = 'attachment; filename="%s"' % ( repositories_archive_filename )
+ opened_archive = open( repositories_archive.name )
+ # Make sure the file is removed from disk after the contents have been downloaded.
+ os.unlink( repositories_archive.name )
+ return opened_archive
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
+ trans.security.encode_id( repository.id ),
+ changeset_revision )
+ metadata = repository_metadata.metadata
+ # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ repository_dependencies = \
+ repository_dependency_util.get_repository_dependencies_for_changeset_revision( trans=trans,
+ repository=repository,
+ repository_metadata=repository_metadata,
+ toolshed_base_url=str( web.url_for( '/', qualified=True ) ).rstrip( '/' ),
+ key_rd_dicts_to_be_processed=None,
+ all_repository_dependencies=None,
+ handled_key_rd_dicts=None )
+ if repository_dependencies:
+ # Only display repository dependencies if they exist.
+ exclude = [ 'datatypes', 'invalid_repository_dependencies', 'invalid_tool_dependencies', 'invalid_tools',
+ 'readme_files', 'tool_dependencies', 'tools', 'tool_test_results', 'workflows', 'data_manager' ]
+ containers_dict = container_util.build_repository_containers_for_tool_shed( trans,
+ repository,
+ changeset_revision,
+ repository_dependencies,
+ repository_metadata,
+ exclude=exclude )
+ export_repository_dependencies_check_box = CheckboxField( 'export_repository_dependencies', checked=True )
+ else:
+ containers_dict = None
+ export_repository_dependencies_check_box = None
+ revision_label = suc.get_revision_label( trans, repository, changeset_revision )
+ return trans.fill_template( "/webapps/tool_shed/repository/export_repository.mako",
+ changeset_revision=changeset_revision,
+ containers_dict=containers_dict,
+ export_repository_dependencies_check_box=export_repository_dependencies_check_box,
+ repository=repository,
+ repository_metadata=repository_metadata,
+ revision_label=revision_label,
+ metadata=metadata,
+ message=message,
+ status=status )
+
+ @web.expose
+ def export_via_api( self, trans, **kwd ):
+ """Return an exported gzip compressed repository archive file opened for reading."""
+ encoded_repositories_archive_name = kwd.get( 'encoded_repositories_archive_name', None )
+ if encoded_repositories_archive_name:
+ repositories_archive_name = encoding_util.tool_shed_decode( encoded_repositories_archive_name )
+ opened_archive = open( repositories_archive_name )
+ # Make sure the file is removed from disk after the contents have been downloaded.
+ os.unlink( repositories_archive_name )
+ return opened_archive
+ return ''
+
+ @web.expose
def find_tools( self, trans, **kwd ):
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/galaxy/webapps/tool_shed/controllers/upload.py
--- a/lib/galaxy/webapps/tool_shed/controllers/upload.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py
@@ -135,7 +135,7 @@
# Move some version of the uploaded file to the load_point within the repository hierarchy.
if uploaded_file_filename in [ suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME ]:
# Inspect the contents of the file to see if changeset_revision values are missing and if so, set them appropriately.
- altered, root_elem = commit_util.handle_repository_dependencies_definition( trans, uploaded_file_name )
+ altered, root_elem = commit_util.handle_repository_dependencies_definition( trans, uploaded_file_name, unpopulate=False )
if altered:
tmp_filename = xml_util.create_and_write_tmp_file( root_elem )
shutil.move( tmp_filename, full_path )
@@ -277,7 +277,7 @@
uploaded_file_name = os.path.abspath( os.path.join( root, uploaded_file ) )
if os.path.split( uploaded_file_name )[ -1 ] == suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME:
# Inspect the contents of the file to see if changeset_revision values are missing and if so, set them appropriately.
- altered, root_elem = commit_util.handle_repository_dependencies_definition( trans, uploaded_file_name )
+ altered, root_elem = commit_util.handle_repository_dependencies_definition( trans, uploaded_file_name, unpopulate=False )
if altered:
tmp_filename = xml_util.create_and_write_tmp_file( root_elem )
shutil.move( tmp_filename, uploaded_file_name )
@@ -338,7 +338,7 @@
uploaded_file_name = os.path.join( full_path, filename )
if os.path.split( uploaded_file_name )[ -1 ] == suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME:
# Inspect the contents of the file to see if changeset_revision values are missing and if so, set them appropriately.
- altered, root_elem = commit_util.handle_repository_dependencies_definition( trans, uploaded_file_name )
+ altered, root_elem = commit_util.handle_repository_dependencies_definition( trans, uploaded_file_name, unpopulate=False )
if altered:
tmp_filename = xml_util.create_and_write_tmp_file( root_elem )
shutil.move( tmp_filename, uploaded_file_name )
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/galaxy/webapps/tool_shed/util/container_util.py
--- a/lib/galaxy/webapps/tool_shed/util/container_util.py
+++ b/lib/galaxy/webapps/tool_shed/util/container_util.py
@@ -710,8 +710,10 @@
lock.release()
return containers_dict
-def build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata ):
+def build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata, exclude=None ):
"""Return a dictionary of containers for the received repository's dependencies and contents for display in the tool shed."""
+ if exclude is None:
+ exclude = []
containers_dict = dict( datatypes=None,
invalid_tools=None,
readme_files=None,
@@ -734,13 +736,13 @@
folder_id = 0
# Datatypes container.
if metadata:
- if 'datatypes' in metadata:
+ if 'datatypes' not in exclude and 'datatypes' in metadata:
datatypes = metadata[ 'datatypes' ]
folder_id, datatypes_root_folder = build_datatypes_folder( trans, folder_id, datatypes )
containers_dict[ 'datatypes' ] = datatypes_root_folder
# Invalid repository dependencies container.
if metadata:
- if 'invalid_repository_dependencies' in metadata:
+ if 'invalid_repository_dependencies' not in exclude and 'invalid_repository_dependencies' in metadata:
invalid_repository_dependencies = metadata[ 'invalid_repository_dependencies' ]
folder_id, invalid_repository_dependencies_root_folder = \
build_invalid_repository_dependencies_root_folder( trans,
@@ -749,7 +751,7 @@
containers_dict[ 'invalid_repository_dependencies' ] = invalid_repository_dependencies_root_folder
# Invalid tool dependencies container.
if metadata:
- if 'invalid_tool_dependencies' in metadata:
+ if 'invalid_tool_dependencies' not in exclude and 'invalid_tool_dependencies' in metadata:
invalid_tool_dependencies = metadata[ 'invalid_tool_dependencies' ]
folder_id, invalid_tool_dependencies_root_folder = \
build_invalid_tool_dependencies_root_folder( trans,
@@ -758,7 +760,7 @@
containers_dict[ 'invalid_tool_dependencies' ] = invalid_tool_dependencies_root_folder
# Invalid tools container.
if metadata:
- if 'invalid_tools' in metadata:
+ if 'invalid_tools' not in exclude and 'invalid_tools' in metadata:
invalid_tool_configs = metadata[ 'invalid_tools' ]
folder_id, invalid_tools_root_folder = build_invalid_tools_folder( trans,
folder_id,
@@ -769,21 +771,22 @@
containers_dict[ 'invalid_tools' ] = invalid_tools_root_folder
# Readme files container.
if metadata:
- if 'readme_files' in metadata:
+ if 'readme_files' not in exclude and 'readme_files' in metadata:
readme_files_dict = readme_util.build_readme_files_dict( metadata )
folder_id, readme_files_root_folder = build_readme_files_folder( trans, folder_id, readme_files_dict )
containers_dict[ 'readme_files' ] = readme_files_root_folder
- # Repository dependencies container.
- folder_id, repository_dependencies_root_folder = build_repository_dependencies_folder( trans=trans,
- folder_id=folder_id,
- repository_dependencies=repository_dependencies,
- label='Repository dependencies',
- installed=False )
- if repository_dependencies_root_folder:
- containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder
+ if 'repository_dependencies' not in exclude:
+ # Repository dependencies container.
+ folder_id, repository_dependencies_root_folder = build_repository_dependencies_folder( trans=trans,
+ folder_id=folder_id,
+ repository_dependencies=repository_dependencies,
+ label='Repository dependencies',
+ installed=False )
+ if repository_dependencies_root_folder:
+ containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder
# Tool dependencies container.
if metadata:
- if 'tool_dependencies' in metadata:
+ if 'tool_dependencies' not in exclude and 'tool_dependencies' in metadata:
tool_dependencies = metadata[ 'tool_dependencies' ]
if trans.webapp.name == 'tool_shed':
if 'orphan_tool_dependencies' in metadata:
@@ -797,7 +800,7 @@
containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder
# Valid tools container.
if metadata:
- if 'tools' in metadata:
+ if 'tools' not in exclude and 'tools' in metadata:
valid_tools = metadata[ 'tools' ]
folder_id, valid_tools_root_folder = build_tools_folder( trans,
folder_id,
@@ -807,7 +810,7 @@
label='Valid tools' )
containers_dict[ 'valid_tools' ] = valid_tools_root_folder
# Tool test results container.
- if tool_test_results and len( tool_test_results ) > 1:
+ if 'tool_test_results' not in exclude and tool_test_results and len( tool_test_results ) > 1:
# Only create and populate this folder if there are actual tool test results to display, since the display of the 'Test environment'
# folder by itself can be misleading. We check for more than a single entry in the tool_test_results dictionary because it may have
# only the "test_environment" entry, but we want at least 1 of "passed_tests", "failed_tests", "installation_errors", "missing_test_components"
@@ -816,7 +819,7 @@
containers_dict[ 'tool_test_results' ] = tool_test_results_root_folder
# Workflows container.
if metadata:
- if 'workflows' in metadata:
+ if 'workflows' not in exclude and 'workflows' in metadata:
workflows = metadata[ 'workflows' ]
folder_id, workflows_root_folder = build_workflows_folder( trans=trans,
folder_id=folder_id,
@@ -827,7 +830,7 @@
containers_dict[ 'workflows' ] = workflows_root_folder
# Valid Data Managers container
if metadata:
- if 'data_manager' in metadata:
+ if 'data_manager' not in exclude and 'data_manager' in metadata:
data_managers = metadata['data_manager'].get( 'data_managers', None )
folder_id, data_managers_root_folder = build_data_managers_folder( trans, folder_id, data_managers, label="Data Managers" )
containers_dict[ 'valid_data_managers' ] = data_managers_root_folder
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -4,7 +4,6 @@
import tempfile
import threading
from galaxy import tools
-from galaxy.util import asbool
from galaxy.util import json
from galaxy import util
from galaxy import web
@@ -118,34 +117,6 @@
installed_repositories.append( installed_repository )
return installed_repositories
-def get_next_prior_install_required_dict_entry( prior_install_required_dict, processed_tsr_ids ):
- """
- The order in which the prior_install_required_dict is processed is critical in order to ensure that the ultimate repository installation order is correctly
- defined. This method determines the next key / value pair from the received prior_install_required_dict that should be processed.
- """
- # Return the first key / value pair that is not yet processed and whose value is an empty list.
- for key, value in prior_install_required_dict.items():
- if key in processed_tsr_ids:
- continue
- if not value:
- return key
- # Return the first key / value pair that is not yet processed and whose ids in value are all included in processed_tsr_ids.
- for key, value in prior_install_required_dict.items():
- if key in processed_tsr_ids:
- continue
- all_contained = True
- for required_repository_id in value:
- if required_repository_id not in processed_tsr_ids:
- all_contained = False
- break
- if all_contained:
- return key
- # Return the first key / value pair that is not yet processed. Hopefully this is all that is necessary at this point.
- for key, value in prior_install_required_dict.items():
- if key in processed_tsr_ids:
- continue
- return key
-
def get_prior_install_required_dict( trans, tsr_ids, repo_info_dicts ):
"""
Return a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained in the received list of tsr_ids
@@ -155,15 +126,15 @@
prior_install_required_dict = {}
for tsr_id in tsr_ids:
prior_install_required_dict[ tsr_id ] = []
- # inspect the repository dependencies for each repository about to be installed and populate the dictionary.
+ # Inspect the repository dependencies for each repository about to be installed and populate the dictionary.
for repo_info_dict in repo_info_dicts:
- repository, repository_dependencies = get_repository_and_repository_dependencies_from_repo_info_dict( trans, repo_info_dict )
+ repository, repository_dependencies = suc.get_repository_and_repository_dependencies_from_repo_info_dict( trans, repo_info_dict )
if repository:
encoded_repository_id = trans.security.encode_id( repository.id )
if encoded_repository_id in tsr_ids:
# We've located the database table record for one of the repositories we're about to install, so find out if it has any repository
# dependencies that require prior installation.
- prior_install_ids = get_repository_ids_requiring_prior_install( trans, tsr_ids, repository_dependencies )
+ prior_install_ids = suc.get_repository_ids_requiring_prior_import_or_install( trans, tsr_ids, repository_dependencies )
prior_install_required_dict[ encoded_repository_id ] = prior_install_ids
return prior_install_required_dict
@@ -287,38 +258,6 @@
return repo_info_dict, tool_panel_section_key
return None, None
-def get_repository_and_repository_dependencies_from_repo_info_dict( trans, repo_info_dict ):
- """Return a tool_shed_repository record defined by the information in the received repo_info_dict."""
- repository_name = repo_info_dict.keys()[ 0 ]
- repo_info_tuple = repo_info_dict[ repository_name ]
- description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = \
- suc.get_repo_info_tuple_contents( repo_info_tuple )
- tool_shed = suc.get_tool_shed_from_clone_url( repository_clone_url )
- repository = suc.get_repository_for_dependency_relationship( trans.app, tool_shed, repository_name, repository_owner, changeset_revision )
- return repository, repository_dependencies
-
-def get_repository_ids_requiring_prior_install( trans, tsr_ids, repository_dependencies ):
- """
- Inspect the received repository_dependencies and determine if the encoded id of each required repository is in the received tsr_ids. If so,
- then determine whether that required repository should be installed prior to it's dependent repository. Return a list of encoded repository
- ids, each of which is contained in the received list of tsr_ids, and whose associated repositories must be installed prior to the dependent
- repository associated with the received repository_dependencies.
- """
- prior_install_ids = []
- if repository_dependencies:
- for key, rd_tups in repository_dependencies.items():
- if key in [ 'description', 'root_key' ]:
- continue
- for rd_tup in rd_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
- if asbool( prior_installation_required ):
- repository = suc.get_repository_for_dependency_relationship( trans.app, tool_shed, name, owner, changeset_revision )
- if repository:
- encoded_repository_id = trans.security.encode_id( repository.id )
- if encoded_repository_id in tsr_ids:
- prior_install_ids.append( encoded_repository_id )
- return prior_install_ids
-
def get_tool_shed_repository_ids( as_string=False, **kwd ):
tsrid = kwd.get( 'tool_shed_repository_id', None )
tsridslist = util.listify( kwd.get( 'tool_shed_repository_ids', None ) )
@@ -722,10 +661,10 @@
ordered_tool_panel_section_keys = []
# Create a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained in the received list of tsr_ids
# and whose associated repository must be installed prior to the repository associated with the tsr_id key.
- prior_install_required_dict = get_prior_install_required_dict( trans, tsr_ids, repo_info_dicts )
+ prior_install_required_dict = suc.get_prior_import_or_install_required_dict( trans, tsr_ids, repo_info_dicts )
processed_tsr_ids = []
while len( processed_tsr_ids ) != len( prior_install_required_dict.keys() ):
- tsr_id = get_next_prior_install_required_dict_entry( prior_install_required_dict, processed_tsr_ids )
+ tsr_id = suc.get_next_prior_import_or_install_required_dict_entry( prior_install_required_dict, processed_tsr_ids )
processed_tsr_ids.append( tsr_id )
# Create the ordered_tsr_ids, the ordered_repo_info_dicts and the ordered_tool_panel_section_keys lists.
if tsr_id not in ordered_tsr_ids:
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/scripts/api/common.py
--- a/lib/tool_shed/scripts/api/common.py
+++ b/lib/tool_shed/scripts/api/common.py
@@ -1,6 +1,6 @@
import os, sys, urllib, urllib2
-new_path = [ os.path.join( os.path.dirname( __file__ ), '..', '..', '..', 'lib' ) ]
+new_path = [ os.path.join( os.path.dirname( __file__ ), '..', '..', '..', '..', 'lib' ) ]
new_path.extend( sys.path[ 1: ] )
sys.path = new_path
@@ -45,10 +45,10 @@
print '--------'
print r
-def display( api_key, url, return_formatted=True ):
+def display( url, api_key=None, return_formatted=True ):
# Sends an API GET request and acts as a generic formatter for the JSON response.
try:
- r = get( api_key, url )
+ r = get( url, api_key=api_key )
except urllib2.HTTPError, e:
print e
print e.read( 1024 ) # Only return the first 1K of errors.
@@ -82,43 +82,44 @@
else:
print 'response is unknown type: %s' % type( r )
-def get( api_key, url ):
+def get( url, api_key=None ):
# Do the actual GET.
- url = make_url( api_key, url )
+ url = make_url( url, api_key=api_key )
try:
return simplejson.loads( urllib2.urlopen( url ).read() )
except simplejson.decoder.JSONDecodeError, e:
print "URL did not return JSON data"
sys.exit(1)
-def make_url( api_key, url, args=None ):
+def make_url( url, api_key=None, args=None ):
# Adds the API Key to the URL if it's not already there.
if args is None:
args = []
argsep = '&'
if '?' not in url:
argsep = '?'
- if '?key=' not in url and '&key=' not in url:
- args.insert( 0, ( 'key', api_key ) )
+ if api_key:
+ if '?key=' not in url and '&key=' not in url:
+ args.insert( 0, ( 'key', api_key ) )
return url + argsep + '&'.join( [ '='.join( t ) for t in args ] )
-def post( api_key, url, data ):
+def post( url, data, api_key=None ):
# Do the actual POST.
- url = make_url( api_key, url )
+ url = make_url( url, api_key=api_key )
req = urllib2.Request( url, headers = { 'Content-Type': 'application/json' }, data = simplejson.dumps( data ) )
return simplejson.loads( urllib2.urlopen( req ).read() )
-def put( api_key, url, data ):
+def put( url, data, api_key=None ):
# Do the actual PUT.
- url = make_url( api_key, url )
+ url = make_url( url, api_key=api_key )
req = urllib2.Request( url, headers = { 'Content-Type': 'application/json' }, data = simplejson.dumps( data ))
req.get_method = lambda: 'PUT'
return simplejson.loads( urllib2.urlopen( req ).read() )
-def submit( api_key, url, data, return_formatted=True ):
+def submit( url, data, api_key=None, return_formatted=True ):
# Sends an API POST request and acts as a generic formatter for the JSON response - 'data' will become the JSON payload read by Galaxy.
try:
- r = post( api_key, url, data )
+ r = post( url, data, api_key=api_key )
except urllib2.HTTPError, e:
if return_formatted:
print e
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/scripts/api/export.py
--- /dev/null
+++ b/lib/tool_shed/scripts/api/export.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+"""
+Export a specified repository revision and optionally all of it's defined repository dependencies from the tool shed into a compressed archive.
+
+Here is a working example of how to use this script to export a repository from the tool shed.
+./export.py --url http://testtoolshed.g2.bx.psu.edu --name chemicaltoolbox --owner bgruening --revision 4133dbf7ff4d --export_repository_dependencies True --download_dir /tmp
+"""
+
+import os
+import sys
+import argparse
+import urllib2
+sys.path.insert( 0, os.path.dirname( __file__ ) )
+from common import display
+from common import submit
+
+CHUNK_SIZE = 2**20 # 1Mb
+
+def get_file_type_str( changeset_revision, file_type ):
+ if file_type == 'zip':
+ file_type_str = '%s.zip' % changeset_revision
+ elif file_type == 'bz2':
+ file_type_str = '%s.tar.bz2' % changeset_revision
+ elif file_type == 'gz':
+ file_type_str = '%s.tar.gz' % changeset_revision
+ else:
+ file_type_str = ''
+ return file_type_str
+
+def string_as_bool( string ):
+ if str( string ).lower() in ( 'true', 'yes', 'on' ):
+ return True
+ else:
+ return False
+
+def main( options ):
+ """Collect all user data and export the repository via the Tool Shed API."""
+ base_tool_shed_url = options.tool_shed_url.rstrip( '/' )
+ repositories_url = '%s/api/repositories' % base_tool_shed_url
+ data = {}
+ data[ 'tool_shed_url' ] = base_tool_shed_url
+ data[ 'name' ] = options.name
+ data[ 'owner' ] = options.owner
+ data[ 'changeset_revision' ] = options.changeset_revision
+ data[ 'export_repository_dependencies' ] = options.export_repository_dependencies
+ repository_id = None
+ repositories = display( repositories_url, api_key=None, return_formatted=False )
+ for repository in repositories:
+ name = str( repository[ 'name' ] )
+ owner = str( repository[ 'owner' ] )
+ if name == options.name and owner == options.owner:
+ repository_id = repository[ 'id' ]
+ break
+ if repository_id:
+ # We'll currently support only gzip-compressed tar archives.
+ file_type = 'gz'
+ file_type_str = get_file_type_str( options.changeset_revision, file_type )
+ url = '%s%s' % ( base_tool_shed_url, '/api/repository_revisions/%s/export' % str( repository_id ) )
+ export_dict = submit( url, data, return_formatted=False )
+ error_messages = export_dict[ 'error_messages' ]
+ if error_messages:
+ print "Error attempting to export revision ", options.changeset_revision, " of repository ", options.name, " owned by ", options.owner, ":\n", error_messages
+ else:
+ if string_as_bool( options.export_repository_dependencies ):
+ repositories_archive_filename = 'exported-with-dependencies-%s-%s' % ( name, file_type_str )
+ else:
+ repositories_archive_filename = 'exported-%s-%s' % ( name, file_type_str )
+ download_url = export_dict[ 'download_url' ]
+ download_dir = os.path.abspath( options.download_dir )
+ file_path = os.path.join( download_dir, repositories_archive_filename )
+ src = None
+ dst = None
+ try:
+ src = urllib2.urlopen( download_url )
+ dst = open( file_path, 'wb' )
+ while True:
+ chunk = src.read( CHUNK_SIZE )
+ if chunk:
+ dst.write( chunk )
+ else:
+ break
+ except:
+ raise
+ finally:
+ if src:
+ src.close()
+ if dst:
+ dst.close()
+ print "Successfully exported revision ", options.changeset_revision, " of repository ", options.name, " owned by ", options.owner
+ print "to location ", file_path
+ else:
+ print "Invalid tool_shed / name / owner ."
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser( description='Installation of tool shed repositories via the Galaxy API.' )
+ parser.add_argument( "-u", "--url", dest="tool_shed_url", required=True, help="Tool Shed URL" )
+ parser.add_argument( "-n", "--name", required=True, help="Repository name." )
+ parser.add_argument( "-o", "--owner", required=True, help="Repository owner." )
+ parser.add_argument( "-r", "--revision", dest="changeset_revision", required=True, help="Repository owner." )
+ parser.add_argument( "-e", "--export_repository_dependencies", dest="export_repository_dependencies", required=False, default='False', help="Export repository dependencies." )
+ parser.add_argument( "-d", "--download_dir", dest="download_dir", required=False, default='/tmp', help="Download directory." )
+ options = parser.parse_args()
+ main( options )
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/util/commit_util.py
--- a/lib/tool_shed/util/commit_util.py
+++ b/lib/tool_shed/util/commit_util.py
@@ -9,6 +9,7 @@
from galaxy import util
from galaxy.datatypes import checkers
from galaxy.util import json
+from galaxy.util.odict import odict
from galaxy.web import url_for
import tool_shed.util.shed_util_common as suc
from tool_shed.util import tool_util
@@ -228,7 +229,12 @@
gzipped_file.close()
shutil.move( uncompressed, uploaded_file_name )
-def handle_repository_dependencies_definition( trans, repository_dependencies_config ):
+def handle_repository_dependencies_definition( trans, repository_dependencies_config, unpopulate=False ):
+ """
+ Populate or unpopulate the toolshed and changeset_revision attributes of a <repository> tag. Populating will occur when a
+ dependency definition file is being uploaded to the repository, while depopulating will occur when the repository is being
+ exported.
+ """
altered = False
# Make sure we're looking at a valid repository_dependencies.xml file.
tree, error_message = xml_util.parse_xml( repository_dependencies_config )
@@ -239,33 +245,45 @@
for index, elem in enumerate( root ):
if elem.tag == 'repository':
# <repository name="molecule_datatypes" owner="test" changeset_revision="1a070566e9c6" />
- populated, elem, error_message = handle_repository_dependency_elem( trans, elem )
+ revised, elem, error_message = handle_repository_dependency_elem( trans, elem, unpopulate=unpopulate )
if error_message:
exception_message = 'The repository_dependencies.xml file contains an invalid <repository> tag. %s' % error_message
raise Exception( exception_message )
- if populated:
+ if revised:
root[ index ] = elem
if not altered:
altered = True
return altered, root
return False, None
-def handle_repository_dependency_elem( trans, elem ):
+def handle_repository_dependency_elem( trans, elem, unpopulate=False ):
# <repository name="molecule_datatypes" owner="test" changeset_revision="1a070566e9c6" />
error_message = ''
name = elem.get( 'name' )
owner = elem.get( 'owner' )
+ # The name and owner attributes are always required, so if either are missing, return the error message.
if not name or not owner:
error_message = handle_missing_repository_attribute( elem )
return False, elem, error_message
- populated = False
+ revised = False
toolshed = elem.get( 'toolshed' )
+ changeset_revision = elem.get( 'changeset_revision' )
+ if unpopulate:
+ # We're exporting the repository, so eliminate all toolshed and changeset_revision attributes from the <repository> tag.
+ if toolshed or changeset_revision:
+ attributes = odict()
+ attributes[ 'name' ] = name
+ attributes[ 'owner' ] = owner
+ attributes[ 'prior_installation_required' ] = elem.get( 'prior_installation_required', 'False' )
+ elem = xml_util.create_element( 'repository', attributes=attributes, sub_elements=None )
+ revised = True
+ return revised, elem, error_message
+ # From here on we're populating the toolshed and changeset_revisions if necessary.
if not toolshed:
# Default the setting to the current tool shed.
toolshed = str( url_for( '/', qualified=True ) ).rstrip( '/' )
elem.attrib[ 'toolshed' ] = toolshed
- populated = True
- changeset_revision = elem.get( 'changeset_revision' )
+ revised = True
if not changeset_revision:
# Populate the changeset_revision attribute with the latest installable metadata revision for the defined repository.
# We use the latest installable revision instead of the latest metadata revision to ensure that the contents of the
@@ -277,12 +295,12 @@
lastest_installable_changeset_revision = suc.get_latest_downloadable_changeset_revision( trans, repository, repo )
if lastest_installable_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
elem.attrib[ 'changeset_revision' ] = lastest_installable_changeset_revision
- populated = True
+ revised = True
else:
error_message = 'Unable to locate repository with name %s and owner %s. ' % ( str( name ), str( owner ) )
- return populated, elem, error_message
+ return revised, elem, error_message
-def handle_tool_dependencies_definition( trans, tool_dependencies_config ):
+def handle_tool_dependencies_definition( trans, tool_dependencies_config, unpopulate=False ):
altered = False
# Make sure we're looking at a valid tool_dependencies.xml file.
tree, error_message = xml_util.parse_xml( tool_dependencies_config )
@@ -297,11 +315,11 @@
for package_index, package_elem in enumerate( root_elem ):
if package_elem.tag == 'repository':
# <repository name="package_eigen_2_0" owner="test" changeset_revision="09eb05087cd0" prior_installation_required="True" />
- populated, repository_elem, error_message = handle_repository_dependency_elem( trans, package_elem )
+ revised, repository_elem, error_message = handle_repository_dependency_elem( trans, package_elem, unpopulate=unpopulate )
if error_message:
exception_message = 'The tool_dependencies.xml file contains an invalid <repository> tag. %s' % error_message
raise Exception( exception_message )
- if populated:
+ if revised:
root_elem[ package_index ] = repository_elem
package_altered = True
if not altered:
@@ -318,11 +336,11 @@
# </repository>
# </action>
for repo_index, repo_elem in enumerate( action_elem ):
- populated, repository_elem, error_message = handle_repository_dependency_elem( trans, repo_elem )
+ revised, repository_elem, error_message = handle_repository_dependency_elem( trans, repo_elem, unpopulate=unpopulate )
if error_message:
exception_message = 'The tool_dependencies.xml file contains an invalid <repository> tag. %s' % error_message
raise Exception( exception_message )
- if populated:
+ if revised:
action_elem[ repo_index ] = repository_elem
package_altered = True
if not altered:
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/util/export_util.py
--- /dev/null
+++ b/lib/tool_shed/util/export_util.py
@@ -0,0 +1,255 @@
+import logging
+import os
+import shutil
+import tarfile
+import tempfile
+import threading
+import tool_shed.util.shed_util_common as suc
+from galaxy import eggs
+from galaxy import web
+from galaxy.util.odict import odict
+from tool_shed.util import commit_util
+from tool_shed.util import common_install_util
+from tool_shed.util import encoding_util
+from tool_shed.util import repository_dependency_util
+from tool_shed.util import xml_util
+
+eggs.require( 'mercurial' )
+
+import mercurial.util
+from mercurial import commands
+from mercurial import hg
+from mercurial import patch
+from mercurial import ui
+
+log = logging.getLogger( __name__ )
+
+
+class ExportedRepositoryRegistry( object ):
+
+ def __init__( self ):
+ self.exported_repository_elems = []
+
+def archive_repository_revision( trans, ui, repository, archive_dir, changeset_revision ):
+ '''Create an un-versioned archive of a repository.'''
+ repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
+ options_dict = suc.get_mercurial_default_options_dict( 'archive' )
+ options_dict[ 'rev' ] = changeset_revision
+ error_message = ''
+ return_code = None
+ try:
+ return_code = commands.archive( ui, repo, archive_dir, **options_dict )
+ except Exception, e:
+ error_message = "Error attempting to archive revision <b>%s</b> of repository %s: %s\nReturn code: %s\n" % \
+ ( str( changeset_revision ), str( repository.name ), str( e ), str( return_code ) )
+ log.exception( error_message )
+ return return_code, error_message
+
+def export_repository( trans, tool_shed_url, repository_id, repository_name, changeset_revision, file_type, export_repository_dependencies, api=False ):
+ file_type_str = suc.get_file_type_str( changeset_revision, file_type )
+ tmp_archive_dir = tempfile.mkdtemp( prefix="tmp-toolshed-arcdir" )
+ if export_repository_dependencies:
+ repositories_archive_filename = os.path.join( tmp_archive_dir, 'exported-with-dependencies-%s-%s' % ( repository_name, file_type_str ) )
+ repo_info_dicts = get_repo_info_dicts( trans, tool_shed_url, repository_id, changeset_revision )
+ repository_ids = get_repository_ids( trans, repo_info_dicts )
+ ordered_repository_ids, ordered_repositories, ordered_changeset_revisions = order_components_for_import( trans, repository_ids, repo_info_dicts )
+ else:
+ ordered_repository_ids = []
+ ordered_repositories = []
+ ordered_changeset_revisions = []
+ repositories_archive_filename = os.path.join( tmp_archive_dir, 'exported-%s-%s' % ( repository_name, file_type_str ) )
+ repository = suc.get_repository_in_tool_shed( trans, repository_id )
+ if repository:
+ repository_metadata = suc.get_current_repository_metadata_for_changeset_revision( trans, repository, changeset_revision )
+ if repository_metadata:
+ ordered_repository_ids = [ repository_id ]
+ ordered_repositories = [ repository ]
+ ordered_changeset_revisions = [ repository_metadata.changeset_revision ]
+ repositories_archive = None
+ error_messages = ''
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ repositories_archive = tarfile.open( repositories_archive_filename, "w:%s" % file_type )
+ exported_repository_registry = ExportedRepositoryRegistry()
+ for index, repository_id in enumerate( ordered_repository_ids ):
+ work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-export-er" )
+ ordered_repository = ordered_repositories[ index ]
+ ordered_changeset_revision = ordered_changeset_revisions[ index ]
+ repository_archive, error_message = generate_repository_archive( trans, work_dir, tool_shed_url, ordered_repository, ordered_changeset_revision, file_type )
+ if error_message:
+ error_messages = '%s %s' % ( error_messages, error_message )
+ else:
+ archive_name = str( os.path.basename( repository_archive.name ) )
+ repositories_archive.add( repository_archive.name, arcname=archive_name )
+ attributes, sub_elements = get_repository_attributes_and_sub_elements( ordered_repository, archive_name )
+ elem = xml_util.create_element( 'repository', attributes=attributes, sub_elements=sub_elements )
+ exported_repository_registry.exported_repository_elems.append( elem )
+ shutil.rmtree( work_dir )
+ # Write the manifest, which must preserve the order in which the repositories should be imported.
+ tmp_xml_file = xml_util.create_and_write_tmp_file( exported_repository_registry.exported_repository_elems, use_indent=True )
+ repositories_archive.add( tmp_xml_file, arcname='manifest.xml' )
+ except Exception, e:
+ log.exception( str( e ) )
+ finally:
+ lock.release()
+ repositories_archive.close()
+ if api:
+ encoded_repositories_archive_name = encoding_util.tool_shed_encode( repositories_archive_filename )
+ download_url = suc.url_join( web.url_for( '/', qualified=True ),
+ 'repository/export_via_api?encoded_repositories_archive_name=%s' % encoded_repositories_archive_name )
+ return dict( download_url=download_url, error_messages=error_messages )
+ return repositories_archive, error_messages
+
+def generate_repository_archive( trans, work_dir, tool_shed_url, repository, changeset_revision, file_type ):
+ file_type_str = suc.get_file_type_str( changeset_revision, file_type )
+ file_name = '%s-%s' % ( repository.name, file_type_str )
+ return_code, error_message = archive_repository_revision( trans, ui, repository, work_dir, changeset_revision )
+ if return_code:
+ return None, error_message
+ repository_archive_name = os.path.join( work_dir, file_name )
+ # Create a compressed tar archive that will contain only valid files and possibly altered dependency definition files.
+ repository_archive = tarfile.open( repository_archive_name, "w:%s" % file_type )
+ for root, dirs, files in os.walk( work_dir ):
+ if root.find( '.hg' ) < 0 and root.find( 'hgrc' ) < 0:
+ for dir in dirs:
+ if dir in commit_util.UNDESIRABLE_DIRS:
+ dirs.remove( dir )
+ for name in files:
+ name = str( name )
+ if str( name ) in commit_util.UNDESIRABLE_FILES:
+ continue
+ full_path = os.path.join( root, name )
+ relative_path = full_path.replace( work_dir, '' ).lstrip( '/' )
+ # See if we have a repository dependencies defined.
+ if name == suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME:
+ # Eliminate the toolshed, and changeset_revision attributes from all <repository> tags.
+ altered, root_elem = commit_util.handle_repository_dependencies_definition( trans, full_path, unpopulate=True )
+ if altered:
+ tmp_filename = xml_util.create_and_write_tmp_file( root_elem, use_indent=True )
+ shutil.move( tmp_filename, full_path )
+ elif name == suc.TOOL_DEPENDENCY_DEFINITION_FILENAME:
+ # Eliminate the toolshed, and changeset_revision attributes from all <repository> tags.
+ altered, root_elem = commit_util.handle_tool_dependencies_definition( trans, full_path, unpopulate=True )
+ if altered:
+ tmp_filename = xml_util.create_and_write_tmp_file( root_elem, use_indent=True )
+ shutil.move( tmp_filename, full_path )
+ repository_archive.add( full_path, arcname=relative_path )
+ repository_archive.close()
+ return repository_archive, error_message
+
+def get_components_from_repo_info_dict( trans, repo_info_dict ):
+ """
+ Return the repository and the associated latest installable changeset_revision (including updates) for the repository defined by the received
+ repo_info_dict.
+ """
+ for repository_name, repo_info_tup in repo_info_dict.items():
+ # There should only be one entry in the received repo_info_dict.
+ description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = \
+ suc.get_repo_info_tuple_contents( repo_info_tup )
+ repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
+ repository_metadata = suc.get_current_repository_metadata_for_changeset_revision( trans, repository, changeset_revision )
+ if repository_metadata:
+ return repository, repository_metadata.changeset_revision
+ return None, None
+
+def get_repo_info_dict_for_import( encoded_repository_id, encoded_repository_ids, repo_info_dicts ):
+ """
+ The received encoded_repository_ids and repo_info_dicts are lists that contain associated elements at each location in the list. This method will return the element
+ from repo_info_dicts associated with the received encoded_repository_id by determining it's location in the received encoded_repository_ids list.
+ """
+ for index, repository_id in enumerate( encoded_repository_ids ):
+ if repository_id == encoded_repository_id:
+ repo_info_dict = repo_info_dicts[ index ]
+ return repo_info_dict
+ return None
+
+def get_repo_info_dicts( trans, tool_shed_url, repository_id, changeset_revision ):
+ repository = suc.get_repository_in_tool_shed( trans, repository_id )
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
+ # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ repository_dependencies = \
+ repository_dependency_util.get_repository_dependencies_for_changeset_revision( trans=trans,
+ repository=repository,
+ repository_metadata=repository_metadata,
+ toolshed_base_url=str( web.url_for( '/', qualified=True ) ).rstrip( '/' ),
+ key_rd_dicts_to_be_processed=None,
+ all_repository_dependencies=None,
+ handled_key_rd_dicts=None )
+ repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
+ ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
+ repo_info_dict = {}
+ # Cast unicode to string.
+ repo_info_dict[ str( repository.name ) ] = ( str( repository.description ),
+ suc.generate_clone_url_for_repository_in_tool_shed( trans, repository ),
+ str( changeset_revision ),
+ str( ctx.rev() ),
+ str( repository.user.username ),
+ repository_dependencies,
+ None )
+ all_required_repo_info_dict = common_install_util.get_required_repo_info_dicts( trans, tool_shed_url, [ repo_info_dict ] )
+ all_repo_info_dicts = all_required_repo_info_dict.get( 'all_repo_info_dicts', [] )
+ return all_repo_info_dicts
+
+def get_repository_attributes_and_sub_elements( repository, archive_name ):
+ """
+ Get the information about a repository to create and populate an XML tag set. The generated attributes will be contained within the <repository>
+ tag, while the sub_elements will be tag sets contained within the <repository> tag set.
+ """
+ attributes = odict()
+ sub_elements = odict()
+ attributes[ 'name' ] = str( repository.name )
+ attributes[ 'type' ] = str( repository.type )
+ # We have to associate the public username since the user_id will be different between tool sheds.
+ attributes[ 'username' ] = str( repository.user.username )
+ sub_elements[ 'description' ] = str( repository.description )
+ sub_elements[ 'long_description' ] = str( repository.long_description )
+ sub_elements[ 'archive' ] = archive_name
+ return attributes, sub_elements
+
+def get_repository_ids( trans, repo_info_dicts ):
+ repository_ids = []
+ for repo_info_dict in repo_info_dicts:
+ for repository_name, repo_info_tup in repo_info_dict.items():
+ description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = \
+ suc.get_repo_info_tuple_contents( repo_info_tup )
+ repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
+ repository_ids.append( trans.security.encode_id( repository.id ) )
+ return repository_ids
+
+def order_components_for_import( trans, repository_ids, repo_info_dicts ):
+ """
+ Some repositories may have repository dependencies that must be imported and have metadata set on them before the dependent repository is imported. This method
+ will inspect the list of repositories about to be exported and make sure to order them appropriately for proper import. For each repository about to be exported,
+ if required repositories are not contained in the list of repositories about to be exported, then they are not considered. Repository dependency definitions that
+ contain circular dependencies should not result in an infinite loop, but obviously ordering the list will not be handled for one or more of the repositories that
+ require prior import.
+ """
+ ordered_repository_ids = []
+ ordered_repositories = []
+ ordered_changeset_revisions = []
+ # Create a dictionary whose keys are the received repository_ids and whose values are a list of repository_ids, each of which is contained in the received list of
+ # repository_ids and whose associated repository must be imported prior to the repository associated with the repository_id key.
+ prior_import_required_dict = suc.get_prior_import_or_install_required_dict( trans, repository_ids, repo_info_dicts )
+ processed_repository_ids = []
+ while len( processed_repository_ids ) != len( prior_import_required_dict.keys() ):
+ repository_id = suc.get_next_prior_import_or_install_required_dict_entry( prior_import_required_dict, processed_repository_ids )
+ processed_repository_ids.append( repository_id )
+ if repository_id not in ordered_repository_ids:
+ prior_import_required_ids = prior_import_required_dict[ repository_id ]
+ for prior_import_required_id in prior_import_required_ids:
+ if prior_import_required_id not in ordered_repository_ids:
+ # Import the associated repository dependency first.
+ prior_repo_info_dict = get_repo_info_dict_for_import( prior_import_required_id, repository_ids, repo_info_dicts )
+ prior_repository, prior_import_changeset_revision = get_components_from_repo_info_dict( trans, prior_repo_info_dict )
+ if prior_repository and prior_import_changeset_revision:
+ ordered_repository_ids.append( prior_import_required_id )
+ ordered_repositories.append( prior_repository )
+ ordered_changeset_revisions.append( prior_import_changeset_revision )
+ repo_info_dict = get_repo_info_dict_for_import( repository_id, repository_ids, repo_info_dicts )
+ repository, changeset_revision = get_components_from_repo_info_dict( trans, repo_info_dict )
+ if repository and changeset_revision:
+ ordered_repository_ids.append( repository_id )
+ ordered_repositories.append( repository )
+ ordered_changeset_revisions.append( changeset_revision )
+ return ordered_repository_ids, ordered_repositories, ordered_changeset_revisions
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -1614,7 +1614,6 @@
ancestor_changeset_revision = None
ancestor_metadata_dict = None
invalid_file_tups = []
- home_dir = os.getcwd()
for changeset in repository.get_changesets_for_setting_metadata( trans.app ):
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-ramorits" )
current_changeset_revision = str( repo.changectx( changeset ) )
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -7,6 +7,7 @@
from time import gmtime
from time import strftime
from galaxy import util
+from galaxy.util import asbool
from galaxy.util import json
from galaxy.util import unicodify
from galaxy.web import url_for
@@ -22,7 +23,10 @@
import pkg_resources
pkg_resources.require( 'mercurial' )
-from mercurial import hg, ui, commands
+from mercurial import cmdutil
+from mercurial import commands
+from mercurial import hg
+from mercurial import ui
eggs.require( 'markupsafe' )
import markupsafe
@@ -530,6 +534,20 @@
return manifest_ctx, ctx_file
return None, None
+def get_current_repository_metadata_for_changeset_revision( trans, repository, changeset_revision ):
+ encoded_repository_id = trans.security.encode_id( repository.id )
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, changeset_revision )
+ if repository_metadata:
+ return repository_metadata
+ # The installable changeset_revision may have been changed because it was "moved ahead" in the repository changelog.
+ repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
+ updated_changeset_revision = get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision=changeset_revision )
+ if updated_changeset_revision:
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, updated_changeset_revision )
+ if repository_metadata:
+ return repository_metadata
+ return None
+
def get_file_context_from_ctx( ctx, filename ):
"""Return the mercurial file context for a specified file."""
# We have to be careful in determining if we found the correct file because multiple files with the same name may be in different directories
@@ -552,6 +570,17 @@
return 'DELETED'
return None
+def get_file_type_str( changeset_revision, file_type ):
+ if file_type == 'zip':
+ file_type_str = '%s.zip' % changeset_revision
+ elif file_type == 'bz2':
+ file_type_str = '%s.tar.bz2' % changeset_revision
+ elif file_type == 'gz':
+ file_type_str = '%s.tar.gz' % changeset_revision
+ else:
+ file_type_str = ''
+ return file_type_str
+
def get_ids_of_tool_shed_repositories_being_installed( trans, as_string=False ):
installing_repository_ids = []
new_status = trans.model.ToolShedRepository.installation_status.NEW
@@ -594,6 +623,18 @@
return changeset_revisions[ -1 ]
return INITIAL_CHANGELOG_HASH
+def get_mercurial_default_options_dict( command, command_table=None, **kwd ):
+ '''Borrowed from repoman - get default parameters for a mercurial command.'''
+ if command_table is None:
+ command_table = commands.table
+ possible = cmdutil.findpossible( command, command_table )
+ if len( possible ) != 1:
+ raise Exception, 'unable to find mercurial command "%s"' % command
+ default_options_dict = dict( ( r[ 1 ].replace( '-', '_' ), r[ 2 ] ) for r in possible[ possible.keys()[ 0 ] ][ 1 ][ 1 ] )
+ for option in kwd:
+ default_options_dict[ option ] = kwd[ option ]
+ return default_options_dict
+
def get_named_tmpfile_from_ctx( ctx, filename, dir ):
"""Return a named temporary file created from a specified file with a given name included in a repository changeset revision."""
filename = strip_path( filename )
@@ -638,6 +679,36 @@
found_after_changeset_revision = True
return None
+def get_next_prior_import_or_install_required_dict_entry( prior_required_dict, processed_tsr_ids ):
+ """
+ This method is used in the Tool Shed when exporting a repository and it's dependencies, and in Galaxy when a repository and it's dependencies
+ are being installed. The order in which the prior_required_dict is processed is critical in order to ensure that the ultimate repository import
+ or installation order is correctly defined. This method determines the next key / value pair from the received prior_required_dict that should
+ be processed.
+ """
+ # Return the first key / value pair that is not yet processed and whose value is an empty list.
+ for key, value in prior_required_dict.items():
+ if key in processed_tsr_ids:
+ continue
+ if not value:
+ return key
+ # Return the first key / value pair that is not yet processed and whose ids in value are all included in processed_tsr_ids.
+ for key, value in prior_required_dict.items():
+ if key in processed_tsr_ids:
+ continue
+ all_contained = True
+ for required_repository_id in value:
+ if required_repository_id not in processed_tsr_ids:
+ all_contained = False
+ break
+ if all_contained:
+ return key
+ # Return the first key / value pair that is not yet processed. Hopefully this is all that is necessary at this point.
+ for key, value in prior_required_dict.items():
+ if key in processed_tsr_ids:
+ continue
+ return key
+
def get_or_create_tool_shed_repository( trans, tool_shed, name, owner, changeset_revision ):
"""
Return a tool shed repository database record defined by the combination of tool shed, repository name, repository owner and changeset_revision
@@ -703,6 +774,28 @@
else:
previous_changeset_revision = changeset_revision
+def get_prior_import_or_install_required_dict( trans, tsr_ids, repo_info_dicts ):
+ """
+ This method is used in the Tool Shed when exporting a repository and it's dependencies, and in Galaxy when a repository and it's dependencies
+ are being installed. Return a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained
+ in the received list of tsr_ids and whose associated repository must be imported or installed prior to the repository associated with the tsr_id key.
+ """
+ # Initialize the dictionary.
+ prior_import_or_install_required_dict = {}
+ for tsr_id in tsr_ids:
+ prior_import_or_install_required_dict[ tsr_id ] = []
+ # Inspect the repository dependencies for each repository about to be installed and populate the dictionary.
+ for repo_info_dict in repo_info_dicts:
+ repository, repository_dependencies = get_repository_and_repository_dependencies_from_repo_info_dict( trans, repo_info_dict )
+ if repository:
+ encoded_repository_id = trans.security.encode_id( repository.id )
+ if encoded_repository_id in tsr_ids:
+ # We've located the database table record for one of the repositories we're about to install, so find out if it has any repository
+ # dependencies that require prior installation.
+ prior_import_or_install_ids = get_repository_ids_requiring_prior_import_or_install( trans, tsr_ids, repository_dependencies )
+ prior_import_or_install_required_dict[ encoded_repository_id ] = prior_import_or_install_ids
+ return prior_import_or_install_required_dict
+
def get_repo_info_tuple_contents( repo_info_tuple ):
"""Take care in handling the repo_info_tuple as it evolves over time as new tool shed features are introduced."""
if len( repo_info_tuple ) == 6:
@@ -712,6 +805,20 @@
description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = repo_info_tuple
return description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies
+def get_repository_and_repository_dependencies_from_repo_info_dict( trans, repo_info_dict ):
+ """Return a tool_shed_repository or repository record defined by the information in the received repo_info_dict."""
+ repository_name = repo_info_dict.keys()[ 0 ]
+ repo_info_tuple = repo_info_dict[ repository_name ]
+ description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = \
+ get_repo_info_tuple_contents( repo_info_tuple )
+ if trans.webapp.name == 'galaxy':
+ tool_shed = get_tool_shed_from_clone_url( repository_clone_url )
+ repository = get_repository_for_dependency_relationship( trans.app, tool_shed, repository_name, repository_owner, changeset_revision )
+ else:
+ # We're in the tool shed.
+ repository = get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
+ return repository, repository_dependencies
+
def get_repository_by_id( trans, id ):
"""Get a repository from the database via id."""
if trans.webapp.name == 'galaxy':
@@ -745,7 +852,7 @@
return None
def get_repository_for_dependency_relationship( app, tool_shed, name, owner, changeset_revision ):
- """Return a tool shed repository database record that is defined by either the current changeset revision or the installed_changeset_revision."""
+ """Return an installed tool_shed_repository database record that is defined by either the current changeset revision or the installed_changeset_revision."""
# This method is used only in Galaxy, not the tool shed.
if tool_shed.endswith( '/' ):
tool_shed = tool_shed.rstrip( '/' )
@@ -821,6 +928,32 @@
# This should never be reached - raise an exception?
return v, None
+def get_repository_ids_requiring_prior_import_or_install( trans, tsr_ids, repository_dependencies ):
+ """
+ This method is used in the Tool Shed when exporting a repository and it's dependencies, and in Galaxy when a repository and it's dependencies
+ are being installed. Inspect the received repository_dependencies and determine if the encoded id of each required repository is in the received
+ tsr_ids. If so, then determine whether that required repository should be imported / installed prior to it's dependent repository. Return a list
+ of encoded repository ids, each of which is contained in the received list of tsr_ids, and whose associated repositories must be impoerted / installed
+ prior to the dependent repository associated with the received repository_dependencies.
+ """
+ prior_tsr_ids = []
+ if repository_dependencies:
+ for key, rd_tups in repository_dependencies.items():
+ if key in [ 'description', 'root_key' ]:
+ continue
+ for rd_tup in rd_tups:
+ tool_shed, name, owner, changeset_revision, prior_installation_required = parse_repository_dependency_tuple( rd_tup )
+ if asbool( prior_installation_required ):
+ if trans.webapp.name == 'galaxy':
+ repository = get_repository_for_dependency_relationship( trans.app, tool_shed, name, owner, changeset_revision )
+ else:
+ repository = get_repository_by_name_and_owner( trans.app, name, owner )
+ if repository:
+ encoded_repository_id = trans.security.encode_id( repository.id )
+ if encoded_repository_id in tsr_ids:
+ prior_tsr_ids.append( encoded_repository_id )
+ return prior_tsr_ids
+
def get_repository_in_tool_shed( trans, id ):
"""Get a repository on the tool shed side from the database via id."""
return trans.sa_session.query( trans.model.Repository ).get( trans.security.decode_id( id ) )
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a lib/tool_shed/util/xml_util.py
--- a/lib/tool_shed/util/xml_util.py
+++ b/lib/tool_shed/util/xml_util.py
@@ -2,6 +2,7 @@
import os
import sys
import tempfile
+from galaxy.util import listify
from xml.etree import ElementTree as XmlET
import xml.etree.ElementTree
@@ -30,8 +31,10 @@
self.data( data )
self.end( XmlET.Comment )
-def create_and_write_tmp_file( elem ):
- tmp_str = xml_to_string( elem )
+def create_and_write_tmp_file( elems, use_indent=False ):
+ tmp_str = ''
+ for elem in listify( elems ):
+ tmp_str += xml_to_string( elem, use_indent=use_indent )
fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-cawrf" )
tmp_filename = fh.name
fh.close()
@@ -41,6 +44,28 @@
fh.close()
return tmp_filename
+def create_element( tag, attributes=None, sub_elements=None ):
+ """
+ Create a new element whose tag is the value of the received tag, and whose attributes are all key / value pairs in the received the attributes
+ and sub_elements.
+ """
+ if tag:
+ elem = XmlET.Element( tag )
+ if attributes:
+ # The received attributes is an odict to preserve ordering.
+ for k, v in attributes.items():
+ elem.set( k, v )
+ if sub_elements:
+ # The received attributes is an odict as well. These handle information that tends to be long text including paragraphs (e.g.,
+ # description and long_description.
+ for k, v in sub_elements.items():
+ # Don't include fields that are blank.
+ if v:
+ sub_elem = XmlET.SubElement( elem, k )
+ sub_elem.text = v
+ return elem
+ return None
+
def indent( elem, level=0 ):
"""
Prints an XML tree with each node indented according to its depth. This method is used to print the shed tool config (e.g., shed_tool_conf.xml
@@ -86,11 +111,11 @@
fobj.close()
return tree, error_message
-def xml_to_string( elem, encoding='utf-8', use_indent=False ):
- if len( elem ):
+def xml_to_string( elem, encoding='utf-8', use_indent=False, level=0 ):
+ if elem is not None:
if use_indent:
# We were called from suc.config_elems_to_xml_file(), so set the level to 1 since level 0 is the <toolbox> tag set.
- indent( elem, level=1 )
+ indent( elem, level=level )
if using_python_27:
xml_str = '%s\n' % xml.etree.ElementTree.tostring( elem, encoding=encoding, method="xml" )
else:
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a scripts/api/repair_tool_shed_repository.py
--- a/scripts/api/repair_tool_shed_repository.py
+++ b/scripts/api/repair_tool_shed_repository.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python
"""
Repair a specified repository revision previously installed into Galaxy.
-</section>
Here is a working example of how to use this script to repair a repository installed into Galaxy.
./repair_tool_shed_repository.py --api <api key> --local <galaxy base url> --url http://testtoolshed.g2.bx.psu.edu --name gregs_filter --owner greg --revision f28d5018f9cb
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a templates/admin/tool_shed_repository/common.mako
--- a/templates/admin/tool_shed_repository/common.mako
+++ b/templates/admin/tool_shed_repository/common.mako
@@ -69,7 +69,7 @@
</script></%def>
-<%def name="render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict )">
+<%def name="render_dependencies_section( repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict, revision_label=None, export=False )"><style type="text/css">
#dependency_table{ table-layout:fixed;
width:100%;
@@ -89,27 +89,44 @@
def __str__( self ):
return str( self.count )
- repository_dependencies_root_folder = containers_dict[ 'repository_dependencies' ]
- tool_dependencies_root_folder = containers_dict[ 'tool_dependencies' ]
- missing_tool_dependencies_root_folder = containers_dict[ 'missing_tool_dependencies' ]
+ repository_dependencies_root_folder = containers_dict.get( 'repository_dependencies', None )
+ tool_dependencies_root_folder = containers_dict.get( 'tool_dependencies', None )
+ missing_tool_dependencies_root_folder = containers_dict.get( 'missing_tool_dependencies', None )
env_settings_heaader_row_displayed = False
package_header_row_displayed = False
+ if revision_label:
+ revision_label_str = ' revision <b>%s</b> of ' % str( revision_label )
+ else:
+ revision_label_str = ' '
%><div class="form-row"><div class="toolParamHelp" style="clear: both;"><p>
- These dependencies can be automatically handled with the installed repository, providing significant benefits, and
- Galaxy includes various features to manage them.
+ %if export:
+ The following additional repositories are required by${revision_label_str}the <b>${repository.name}</b> repository
+ and they can be exported as well.
+ %else:
+ These dependencies can be automatically handled with${revision_label_str}the installed repository, providing significant
+ benefits, and Galaxy includes various features to manage them.
+ %endif
</p></div></div>
%if repository_dependencies_root_folder:
- %if install_repository_dependencies_check_box is not None:
+ %if repository_dependencies_check_box is not None:
<div class="form-row">
- <label>Handle repository dependencies?</label>
- ${install_repository_dependencies_check_box.get_html()}
+ %if export:
+ <label>Export repository dependencies?</label>
+ %else:
+ <label>Handle repository dependencies?</label>
+ %endif
+ ${repository_dependencies_check_box.get_html()}
<div class="toolParamHelp" style="clear: both;">
- Un-check to skip automatic installation of these additional repositories required by this repository.
+ %if export:
+ Un-check to skip exporting the following additional repositories that are required by this repository.
+ %else:
+ Un-check to skip automatic installation of these additional repositories required by this repository.
+ %endif
</div></div><div style="clear: both"></div>
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
--- a/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
+++ b/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
@@ -39,7 +39,7 @@
<th bgcolor="#EBD9B2">Confirm dependency installation</th></table></div>
- ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict )}
+ ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict, revision_label=None, export=False )}
%endif
%if shed_tool_conf_select_field:
<div class="form-row">
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a templates/admin/tool_shed_repository/select_shed_tool_panel_config.mako
--- a/templates/admin/tool_shed_repository/select_shed_tool_panel_config.mako
+++ b/templates/admin/tool_shed_repository/select_shed_tool_panel_config.mako
@@ -78,7 +78,7 @@
<th bgcolor="#EBD9B2">Confirm dependency installation</th></table></div>
- ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict )}
+ ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict, revision_label=None, export=False )}
<div style="clear: both"></div>
%endif
<div class="form-row">
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a templates/admin/tool_shed_repository/select_tool_panel_section.mako
--- a/templates/admin/tool_shed_repository/select_tool_panel_section.mako
+++ b/templates/admin/tool_shed_repository/select_tool_panel_section.mako
@@ -78,7 +78,7 @@
<th bgcolor="#EBD9B2">Confirm dependency installation</th></table></div>
- ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict )}
+ ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict, revision_label=None, export=False )}
<div style="clear: both"></div>
%endif
%if shed_tool_conf_select_field:
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a templates/webapps/tool_shed/common/repository_actions_menu.mako
--- a/templates/webapps/tool_shed/common/repository_actions_menu.mako
+++ b/templates/webapps/tool_shed/common/repository_actions_menu.mako
@@ -174,6 +174,7 @@
<a class="action-button" target="galaxy_main" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=False )}">Mark repository as not deprecated</a>
%endif
%if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='export', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Export this revision</a><a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a><a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a><a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
diff -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 -r 8ca6cfea19091f0d44be3eec3b3d18794133a39a templates/webapps/tool_shed/repository/export_repository.mako
--- /dev/null
+++ b/templates/webapps/tool_shed/repository/export_repository.mako
@@ -0,0 +1,47 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/admin/tool_shed_repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" />
+
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/tool_shed/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="stylesheets()">
+ ${parent.stylesheets()}
+ ${h.css( "library" )}
+</%def>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${container_javascripts()}
+</%def>
+
+${render_tool_shed_repository_actions( repository )}
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div>
+ <div class="toolFormBody">
+ <form name="export_repository" id="export_repository" action="${h.url_for( controller='repository', action='export', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}" method="post" >
+ %if containers_dict is not None and export_repository_dependencies_check_box is not None:
+ ${render_dependencies_section( export_repository_dependencies_check_box, None, containers_dict, revision_label=revision_label, export=True )}
+ <div style="clear: both"></div>
+ %else:
+ No repository dependencies are defined for revision <b>${revision_label}</b> of this repository, so click <b>Export</b> to export the selected revision.
+ %endif
+ <div class="form-row">
+ <input type="submit" name="export_repository_button" value="Export"/>
+ </div>
+ </form>
+ </div>
+</div>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a2fcb4655e0f/
Changeset: a2fcb4655e0f
Branch: next-stable
User: natefoo
Date: 2013-08-02 22:39:05
Summary: Merge changes from stable.
Affected #: 3 files
diff -r 96eba6391a06e7e6230e06208347dfb51a64a1e1 -r a2fcb4655e0faa0bebb062a54cad05e448ed6c51 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -264,6 +264,7 @@
self.datatypes_config = kwargs.get( 'datatypes_config_file', 'datatypes_conf.xml' )
# Cloud configuration options
self.enable_cloud_launch = string_as_bool( kwargs.get( 'enable_cloud_launch', False ) )
+ self.cloudlaunch_default_ami = kwargs.get( 'cloudlaunch_default_ami', 'ami-118bfc78' )
# Galaxy messaging (AMQP) configuration options
self.amqp = {}
try:
diff -r 96eba6391a06e7e6230e06208347dfb51a64a1e1 -r a2fcb4655e0faa0bebb062a54cad05e448ed6c51 lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
--- a/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
+++ b/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
@@ -26,7 +26,6 @@
PKEY_PREFIX = 'gxy_pkey'
DEFAULT_KEYPAIR = 'cloudman_keypair'
-DEFAULT_AMI = 'ami-da58aab3'
class CloudController(BaseUIController):
@@ -96,7 +95,7 @@
return to_json_string(account_info)
@web.expose
- def launch_instance(self, trans, cluster_name, password, key_id, secret, instance_type, share_string, keypair, ami=DEFAULT_AMI, zone=None, bucket_default=None, **kwargs):
+ def launch_instance(self, trans, cluster_name, password, key_id, secret, instance_type, share_string, keypair, ami=None, zone=None, bucket_default=None, **kwargs):
ec2_error = None
try:
# Create security group & key pair used when starting an instance
@@ -120,6 +119,9 @@
if bucket_default:
user_provided_data['bucket_default'] = bucket_default
+ if not ami:
+ ami = trans.app.config.cloudlaunch_default_ami
+
rs = run_instance(ec2_conn=ec2_conn,
image_id = ami,
user_provided_data=user_provided_data,
diff -r 96eba6391a06e7e6230e06208347dfb51a64a1e1 -r a2fcb4655e0faa0bebb062a54cad05e448ed6c51 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -324,9 +324,10 @@
# Note that this requires java > 1.4 for executing yuicompressor.jar
#pack_scripts = False
-# Enable Cloud Launch
+# Cloud Launch
#enable_cloud_launch = False
+#cloudlaunch_default_ami = ami-118bfc78
# -- Advanced proxy features
https://bitbucket.org/galaxy/galaxy-central/commits/436ca79f8211/
Changeset: 436ca79f8211
User: natefoo
Date: 2013-08-02 22:39:52
Summary: Merge stable.
Affected #: 3 files
diff -r 57c593cc70a1de89f32e77833cbf1e329cf52c6b -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -264,6 +264,7 @@
self.datatypes_config = kwargs.get( 'datatypes_config_file', 'datatypes_conf.xml' )
# Cloud configuration options
self.enable_cloud_launch = string_as_bool( kwargs.get( 'enable_cloud_launch', False ) )
+ self.cloudlaunch_default_ami = kwargs.get( 'cloudlaunch_default_ami', 'ami-118bfc78' )
# Galaxy messaging (AMQP) configuration options
self.amqp = {}
try:
diff -r 57c593cc70a1de89f32e77833cbf1e329cf52c6b -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
--- a/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
+++ b/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
@@ -26,7 +26,6 @@
PKEY_PREFIX = 'gxy_pkey'
DEFAULT_KEYPAIR = 'cloudman_keypair'
-DEFAULT_AMI = 'ami-da58aab3'
class CloudController(BaseUIController):
@@ -96,7 +95,7 @@
return to_json_string(account_info)
@web.expose
- def launch_instance(self, trans, cluster_name, password, key_id, secret, instance_type, share_string, keypair, ami=DEFAULT_AMI, zone=None, bucket_default=None, **kwargs):
+ def launch_instance(self, trans, cluster_name, password, key_id, secret, instance_type, share_string, keypair, ami=None, zone=None, bucket_default=None, **kwargs):
ec2_error = None
try:
# Create security group & key pair used when starting an instance
@@ -120,6 +119,9 @@
if bucket_default:
user_provided_data['bucket_default'] = bucket_default
+ if not ami:
+ ami = trans.app.config.cloudlaunch_default_ami
+
rs = run_instance(ec2_conn=ec2_conn,
image_id = ami,
user_provided_data=user_provided_data,
diff -r 57c593cc70a1de89f32e77833cbf1e329cf52c6b -r 436ca79f821132163526fa9bf1f7d6b7fe3f13c7 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -324,9 +324,10 @@
# Note that this requires java > 1.4 for executing yuicompressor.jar
#pack_scripts = False
-# Enable Cloud Launch
+# Cloud Launch
#enable_cloud_launch = False
+#cloudlaunch_default_ami = ami-118bfc78
# -- Advanced proxy features
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0